Anyone who can help me with this?
Why my codes wont work in formulated cell?
I want to run my codes in formulated cell like vlookup
Is there a way to solve this problem?
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheets()[0]; // 0 == first sheet.
var ee = ss.getActiveRange().getA1Notation();
if (ee == "A1") { // Check if edited cell is the one we're watching.
if (e.value == "DONE"){ // If the value == "DONE", do stuff.
var toggle = sh.getRange("A1:M1");
for(var i=0;i<50;i++) {
if( i%2 == 0 )
toggle.setBackground("GOLD");
else
toggle.setBackground("WHITE");
SpreadsheetApp.flush();
Utilities.sleep(500);
}
}
}
}
On edit and on change triggers only are fired by changes directly made by the user, not when the result of a formula changes or a change is made by code.
Use conditional formatting instead.
Related
I'm attempting to create a spreadsheet to organise products ordered at my workplace.
When an order is received a team member would add the details to the sheet; when it is collected they'd fill out date and ID then tick the order complete. See Attached
What I want to happen next is that the row containing the complete details from that order is appended to a second page in the sheet and the original row is deleted.
I can't make sense of how to get this to run automatically when the box is checked; so far I have been compiling a script to run from a button press:
function runFiling() {
function moveRows() {
var ss = SpreadsheetApp.getActive();
var osh = ss.getSheetByName('Current');
var dsh = ss.getSheetByName('Collected');
var srg = osh.getDataRange('H2:H');//You might want to specify a more unique range. This just gets all of the data on the sheet
var svA = srg.getValues();
var d=0;//deleted row counter
for(var i=1;i<svA.length;i++) {
if(svA[i][7] =='TRUE') {
dsh.appendRow(svA[i]);//append entire row to Sheet2
osh.deleteRow(i-d+1);//accounts for the difference between length of array and number of remaining row.
d++;
}
}
}
}
However even this fails to Append or Delete anything although no errors are found/returned.
If anyone can suggest a way to fix the above or, preferably, how to make the script work when the box is ticked your help will be most appreciated.
Try it this way using an onEdit(e) function
function onEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'Current' && e.range.columnStart == 7 && e.range.rowStart > 1 && e.value == "TRUE") {
const dsh = ss.getSheetByName('Collected');
const vs = sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).getValues()
dsh.getRange(dsh.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);
sh.deleteRow(e.range.rowStart);
}
}
This will accomplish the task line by line as the check boxes are checked off by the user.
I tried to create a function that would timestamp a cell. The way I want it to work is: when I turn a cell TRUE (with a checkbox) it fills a cell with text, then the cell right next to it will timestamp when that happens. The problem is that every time I open the sheet, my timestamp function updates to the current date.
It's my first time scripting in this language or in Sheets. I did my best to Google this first but I didn't find anything that quite fit what I was imagining. Anyone willing to help explain what I did wrong and how to fix it?
function timestamp(input){
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var cellRange = sheet.getActiveCell();
var lastCell = cellRange.offset(0, -1);
if( lastCell.getValue() === '' ){
return('')
} else{
return(new Date());
}
}
Also, if anyone has the time, I stripped these from another script I found on here but don't understand what they are needed for, can someone explain their purpose?:
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
I couldn't get the function to run without it.
To put a timestamp when you check you can use onEdit function, for instance
function onEdit(event){
var r = event.source.getActiveRange();
if ((r.getColumn() == 1) && (r.getValue() == true)){
r.offset(0,2).setValue(new Date());
}
}
My script works perfectly when I execute it manually through the editor but fails to fire with the edit or change trigger.
I saw a bunch of people having the same problem but none of these solutions help me solving this issue.
Has anybody a solution for this ?
function createNewSheets() {
// 1. Retrieve the current sheet names.
var dataSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetNames = dataSheet.getSheets().map(s => s.getSheetName());
// 2. Retrieve the values from "mastersheet" sheet.
var masterSheet = dataSheet.getSheetByName('Liste de nageurs');
var values = masterSheet.getRange('A2:B' + masterSheet.getLastRow()).getValues();
// 3. Using the retrieved sheet names and values, the new sheets are inserted and the values are put.
values.forEach(r => {
if (!sheetNames.includes(r[0])) {
var newSheet = dataSheet.insertSheet(r[0])
sheetNames.push(r[0]);
newSheet.appendRow(r);
}
});
}
I ran it this way, using a checkbox in A1:
function onEdit(e) {
//e.source.toast('entry');//just a toast to let me know it's work
const sh = e.range.getSheet();// getting sheet name
//next line limits execution to Sheet1 A1 being changed to 'TRUE'
if (sh.getName() == 'Sheet1' && e.range.columnStart == 1 && e.range.rowStart == 1 && e.value == 'TRUE') {
e.range.setValue('FALSE');//reset the checkbox back to 'FALSE'
//the rest is your code
var ss = SpreadsheetApp.getActive();
var names = ss.getSheets().map(s => s.getSheetName());
var masterSheet = ss.getSheetByName('Sheet2');//changed sheet name
var vs = masterSheet.getRange('A2:B' + masterSheet.getLastRow()).getValues();
vs.forEach(r => {
if (!names.includes(r[0])) {
var newSheet = ss.insertSheet(r[0])
names.push(r[0]);
newSheet.appendRow(r);
}
});
}
}
You can simplify your code if you learn how to use the event object better but I left most of your code intact. The problem that most users dislike about using the event object is that you can't debug the code by running it from the script editor because you have to supply the event object as a parameter. I normally debug them but running them from the trigger. You can use JSON.stringify(e) to look at the event object.
Using the event object normally results in faster code and simple triggers must finish in 30 seconds or less.
First of all, I ask you to excuse me if I make some language-mistake (I'm Italian!).
I'm trying to write a script for a Google Sheet that can help me to track the number of changes of a column. I would like a counter that grows everytime a value of a cell changes. Ex:
-Column A: the cell A3 changes from "2020" to "2021"
-Column B: the cell B3 changes from 0 to 1 (o from 2 to 3, a simple +1 on the value).
I wrote this code but I cannot understand where is the error.
function onEdit(e) {
incrementCounter_(e);
}
function incrementCounter_(e) {
var stw = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Foglio2");
var c1 = stw.getRange(2, 1);
var c2 = stw.getRange(2, 2);
if (!e || !e.range) {
return;
}
var sheet = e.range.getSheet();
for (var i=2; i<=6; i++){
if (sheet.getName() === stw && e.range.getA1Notation() === stw.getrange().getvalue(i,1)) {
var cell = stw.getrange().getvalue(i,2);
cell.setValue((Number(cell.getValue()) || 0) + 1);
}
}
}
Thanks for the help!
There is no need to use two functions for this.
Code
// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0
function onEdit(e) {
var sheet = e.range.getSheet();
var sheetName = sheet.getName();
if (sheetName == "Foglio2" && e.range.getColumn() == 1) {
var row = e.range.getRow();
var val = sheet.getRange(row, 2).getValue();
sheet.getRange(row, 2).setValue(val + 1);
}
}
Explanation
What you want can be achieved by using the onEdit(e) trigger. The above function makes use of the e event object and checks where exactly the edit is being made. As it can be seen, the for loop is not needed in this situation as in order to get the column and row needed the getColumn() and getRow() methods have been used.
In this situation, the script checks if the sheet in which the edit has been made is Foglio2 and if an edit has been made on the A column. If the condition checks, it increments the corresponding value from the B column.
Note
Please note that getValue(value1, value2) is not a valid method and if you want to get the value for that specific range, you must pass the two parameters to the getRange() method.
Reference
Apps Script Event Objects;
Apps Script Sheet Class;
Apps Script Range Class - getValue().
Do you mean this?
function onEdit(e) {
if (e.range.getA1Notation() === 'A3') {
var range = SpreadsheetApp.getActiveSheet().getRange('B3');
var value = range.getValue();
value++;
range.setValue(value);
}
}
I am trying to detect background color change of two cells. A while back I created the following Google Sheet function and added it as an installable trigger From spreadsheet On change since cell color changes are not detected by on Edit. I thought it worked but I just checked it now, and it is not detecting which cell's background color was changed, Any ideas?
function onChangeInstallable(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var activeSheetName = activeSheet.getSheetName();
if (activeSheetName == "Settings") {
if(e.changeType == "OTHER"){
// makes it this far ok but following line returns
// #REF! instead of A1 notation of changed cell.
var editedRange = SpreadsheetApp.getActiveRange().getA1Notation();
if (editedRange == 'B43' || editedRange == 'B44'){
setBackgroundColors();
}
}
}
}
Also tried the following, but it returns a "Cell reference out of range" error.
var editedRange = activeSheet.getActiveCell().getA1Notation();
edit: looks like this case is still broken, star issue 3269 to vote for a fix
try var editedRange = activeSheet.getActiveRange().getA1Notation();
the active spreadsheet is already being passed into the function with the e object too, fyi.
var ss = e.source;