Automatic triger not executing, manually executing works perfectly - google-apps-script

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.

Related

put current date to a cell if it is filled with zapier

I found this script:
function onEdit () {
var s = SpreadsheetApp.getActiveSheet ();
if (s.getName () == "sheet_name") {
var r = s.getActiveCell ();
if (r.getColumn () == 1) {
var nextCell = r.offset (0, 1);
if (nextCell.getValue () === '')
nextCell.setValue (new Date());
}
}
}
It works if I fill one cell by myself and puts current date to another cell in the right.
BUT if I use Zapier to export my data from Todoist to Google Sheets this script doesn't work. It only works if I change something manually.
Is there any way to make a script which will fill a cell I need with a today date when Zapier export data and fills cells automatically?
Suggestion:
As what Tanaike mentioned, you need to rename your function to something else aside from onEdit() since onEdit is a reserved function name for App Script and use onChange trigger.
But based on how Zapier works, the reason why the current code you have provided is not working is because exports from Zapier is not detected as an active cell, so we would need to revamp the entire code.
Try this instead:
function onZapierUpdate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet2'); //my test sheet is Sheet2
var range = sheet.getRange(2,1,sheet.getLastRow()-1, 2);
var data = range.getValues();
data.forEach(x => x[0] != "" ? x[1] = new Date() : x);
range.setValues(data);
}
After saving the script, set this on an onChange trigger like so:
Now whenever Zapier exports the data, it changes the content of the spreadsheet which means onChange trigger will take effect.
Reference:
https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onChange()

Copying (and deleting) rows in Google Sheets based on dropdown (Data sourced from Google Survey)

I'm a newbie when it comes to any sort of coding, but I'm trying to figure out a way to fix my spreadsheet. I am working on a Google Sheet for a trucking company where data comes in via a Google Form (e.g. date, driver, amount, pickup, destinaiton, etc) and is a linked to a spreadsheet with responses recorded to a sheet called "Loadboard". Responses start on Row 5.
On "Loadboard", I created a dropdown column called "Paid" in Column R (18) as a place to mark when these orders are completed. The idea is that once "Yes" is selected it will be moved from the "Loadboard" sheet to the "Paid" sheet. I also created a "No" option as part of the dropdown in case we need to move from "Paid" back to "Loadboard" in case this dropdown is selected accidentally.
While I have an onedit function that works great, I'm having trouble figuring out how to convert this to work with data submitted via form (in particular how to write the new onformsubmit function and how to setup the form submission trigger)
Here's the function I'm using:
function onEdit(e) {
let r = e.range;
if (r.columnStart != 18 || r.rowStart == 1 || e.value == null) return;
const sh = SpreadsheetApp.getActive();
const valArray = ["No", "Yes"];
const destArray = ["Loadboard", "Paid"];
let dest = sh.getSheetByName(destArray[valArray.indexOf(e.value)]);
let src = sh.getActiveSheet();
if (dest.getName() == src.getName()) return;
src.getRange(r.rowStart, 1, 1, 18).moveTo(dest.getRange(dest.getLastRow() + 1, 1, 1, 18));
src.deleteRow(r.rowStart);
}
After searching for hours on the internet, this was the closest I got -
function formSubmission() {
var s = SpreadsheetApp.getActiveSheet();
var data = range.getValues();
var numCol = range.getLastColumn();
var row = s.getActiveRow;
var targetinfo = s.getRange(row, (18).getValue);
if (targetinfo() == "Yes") {
var targetSheet = ss.getSheetByName("Paid");
var targetrow = targetSheet.getLastrow() + 1);
var Targetcol = numCol();
targetSheet.getRange(targetrow, 1, 1, Targetcol).setValues(data);
}
}
I'm also using the following trigger setup:
Function to Run: OnEdit
Event Source: From Spreadsheet
Event Type: On Change
Unfortunately, neither seem to be working. I also just tried replacing the original onedit with "formsubmission" which did not work.
I would have to do the same thing, I would let a sheet with all the results untouched. I would make a namedRange with it and two sheets Paid and Loadboard with a request like =QUERY(myNamedRange, "select * where R='Yes'") so get a clean sheet with every "Paid" row.
About your code, a hint : I can't find any var row s.getActiveRow function and i it existed it would be s.getActiveRow() (parenthesis).

Getting google spreadsheets to send me an email

I have a spreadsheet on Google spreadsheets that has "D2" through all of "D" (because it will expand as used and when I add more) with a drop down box for priority status. The drop down has "Low, Medium, High". I want to get a script to send me an email when that priority gets edited to "High"
This is the script I did last night at 2AM half asleep.
{
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("TC52 Bugs or Issues and Improvements.");
var valueToCheck = sheet.getRange(D).getValue();
var rangeEdit = e.range.getA1Notation();
if(rangeEdit == "D")
{
if(valueToCheck > High)
{
MailApp.sendEmail("austin.hendrix#decathlon.com", "High Priority please check now.", "Check spreadsheet" + valueToCheck+ ".");
}
}
}````
This article has a tutorial.
On that note, something along the lines of (Heavily edited by MetaMan)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(1,4,sh.getLastRow()) or getRange('D1:D'+sh.getLastRow()));
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = "youremail#email.com"; // First column
var message = "High priority set with data in A column "+sheet.getRange(("A"+i+1)).getValues()[0]; // Second column
var subject = 'High priority set in D'+i;
if(row[0]=="High"){
MailApp.sendEmail(emailAddress, subject, message);
}
}
}
The function will send you an email when column D is edited to "High".
You will need to fill in 'Your Spreadsheet name' the recipient email address and what ever subject you wish. Also you can edit the body as well. The current body just tells you which row issue the email. Alternately, if you wish to provide more information I'll do it for you.
function onMyEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == 'Your Sheet Name' && e.range.columnStart == 4 && e.range.rowStart >1 && e.value == 'High') {
GmailApp.sendEmail('recipient','subject',`row ${e.range.rowStart} has been set to high`)
}
}
Since sending an email requires permission you will have to create an installable trigger for this function.
You can do it manually or use a function like the one below which will prevent you from creating more that one trigger.
function createTrigger() {
const ts = ScriptApp.getProjectTriggers().map(t=>t.getHandlerFunction());
if(!~ts.indexOf('onMyEdit')) {
ScriptApp.newTrigger('onMyEdit').forSpreadsheet(SpreadsheetApp.getActive().getId()).onEdit().create();
}
}
ScriptApp
Please Note: that you cannot run onEdit triggered functions from the Script Editor or even from a menu. They require the onEdit trigger which populates the single parameter e with the event object. You can run them from another function as long as it provides the event object.

setbackground not working in google sheets [duplicate]

I have created the following simple function:
function test(r,c) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.getRange(r,c).setBackground("red");
return 1;
}
In the spreadsheet, I write "=test(row(),column())
This results in ERROR with the following message:
Error: You do not have permission to call setBackground (line 3).
It is NO problem if I create another function call in the script as follows:
function test_the_test(){
test(5,4);
}
Why can't I call the test function from the spreadsheet cell?
Thank you in advance
As it is clearly explained in the documentation, Custom functions return values, but they cannot set values outside the cells they are in. In most circumstances, a custom function in cell A1 cannot modify cell A5. That is of course also true for other methods such as setBackground etc.
It's not possible to call anything which sets content from cell, but it is possible to call it from buttons.
Actually is quite easy. Definitely it's not true that you can't change others cell content.
The trick is to not call the function from cell but mount it into drawing/image.
Click insert -> drawing
Draw a image and save it (you should see
your image in spreadsheet)
Click it by right mouse button - in top right corner, there is a little
triangle opening options
Click Assign script and type name of your
script without parenthesis (like "test" not "test()" ) and confirm
Click the button. A pop-up window asking for privileges to access spreadsheet appears.
Confirm it, if problem with refresh occurs just refresh it manually (F5)
Now you can click the button and you can edit any cell you like
This code work fine when mounted to button.
function test() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.getRange(3,5).setBackground("red");
}
The current version of Google Sheets (Jan 2022) uses the Apps Script editor and allows you to put scripts in a container file that automatically attaches to your Google Sheet.
You can open the Apps Script editor from the Google Sheets menu under Extensions -> App Script
In the default Code.gs editor file you can simply extend a default event hook such as onEdit() and put in logic to filter your actions to a specific set of circumstances. Here is a simple example of using this hook:
function onEdit(e) {
if( ! e ){
return;
}
var currentSheet = e.source.getActiveSheet();
var currentRange = e.range;
// only want action to occur when a single cell changes
if( currentRange.getNumRows() === 1 && currentRange.getNumColumns() === 1 ){
var currentColumn = currentRange.getLastColumn();
var currentRow = currentRange.getLastRow();
// only want action to occur for a column on a certain sheet
var myTargetSheet = "Sheet 1";
var myTargetColumn = 1;
if( currentSheet.getName() == myTargetSheet && currentColumn == myTargetColumn ){
// set background color for the selected row based on a lookup
var cellValue = currentRange.getCell(1,1).getValue();
var assignedColor = myCustomSearch( cellValue );
currentSheet.getRange( "A" + currentRow + ":E" + currentRow ).setBackgroundColor( assignedColor );
}
}
}
function myCustomSearch( searchTerm ){
var assignedColor = "#ffffff";
var lookupSheet = SpreadsheetApp.getActive().getSheetByName("Sheet 2");
var lookupRange = lookupSheet.getRange("H1:H20"); // where the search terms live
var numColumns = lookupRange.getNumColumns();
var numRows = lookupRange.getNumRows();
var lookupList = lookupRange.getValues();
for( var myColumn=0; myColumn < numColumns; myColumn++ ){
for( var myRow=0; myRow < numRows; myRow++ ){
if( lookupList[myRow][myColumn] == searchTerm ){
assignedColor = lookupSheet.getRange("H"+(myRow+1)).getBackgroundColor();
break;
}
}
}
return assignedColor;
}

Cell coloring in google-spreadsheet fails if it is called from a cell, but works ok when called from the script.

I have created the following simple function:
function test(r,c) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.getRange(r,c).setBackground("red");
return 1;
}
In the spreadsheet, I write "=test(row(),column())
This results in ERROR with the following message:
Error: You do not have permission to call setBackground (line 3).
It is NO problem if I create another function call in the script as follows:
function test_the_test(){
test(5,4);
}
Why can't I call the test function from the spreadsheet cell?
Thank you in advance
As it is clearly explained in the documentation, Custom functions return values, but they cannot set values outside the cells they are in. In most circumstances, a custom function in cell A1 cannot modify cell A5. That is of course also true for other methods such as setBackground etc.
It's not possible to call anything which sets content from cell, but it is possible to call it from buttons.
Actually is quite easy. Definitely it's not true that you can't change others cell content.
The trick is to not call the function from cell but mount it into drawing/image.
Click insert -> drawing
Draw a image and save it (you should see
your image in spreadsheet)
Click it by right mouse button - in top right corner, there is a little
triangle opening options
Click Assign script and type name of your
script without parenthesis (like "test" not "test()" ) and confirm
Click the button. A pop-up window asking for privileges to access spreadsheet appears.
Confirm it, if problem with refresh occurs just refresh it manually (F5)
Now you can click the button and you can edit any cell you like
This code work fine when mounted to button.
function test() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.getRange(3,5).setBackground("red");
}
The current version of Google Sheets (Jan 2022) uses the Apps Script editor and allows you to put scripts in a container file that automatically attaches to your Google Sheet.
You can open the Apps Script editor from the Google Sheets menu under Extensions -> App Script
In the default Code.gs editor file you can simply extend a default event hook such as onEdit() and put in logic to filter your actions to a specific set of circumstances. Here is a simple example of using this hook:
function onEdit(e) {
if( ! e ){
return;
}
var currentSheet = e.source.getActiveSheet();
var currentRange = e.range;
// only want action to occur when a single cell changes
if( currentRange.getNumRows() === 1 && currentRange.getNumColumns() === 1 ){
var currentColumn = currentRange.getLastColumn();
var currentRow = currentRange.getLastRow();
// only want action to occur for a column on a certain sheet
var myTargetSheet = "Sheet 1";
var myTargetColumn = 1;
if( currentSheet.getName() == myTargetSheet && currentColumn == myTargetColumn ){
// set background color for the selected row based on a lookup
var cellValue = currentRange.getCell(1,1).getValue();
var assignedColor = myCustomSearch( cellValue );
currentSheet.getRange( "A" + currentRow + ":E" + currentRow ).setBackgroundColor( assignedColor );
}
}
}
function myCustomSearch( searchTerm ){
var assignedColor = "#ffffff";
var lookupSheet = SpreadsheetApp.getActive().getSheetByName("Sheet 2");
var lookupRange = lookupSheet.getRange("H1:H20"); // where the search terms live
var numColumns = lookupRange.getNumColumns();
var numRows = lookupRange.getNumRows();
var lookupList = lookupRange.getValues();
for( var myColumn=0; myColumn < numColumns; myColumn++ ){
for( var myRow=0; myRow < numRows; myRow++ ){
if( lookupList[myRow][myColumn] == searchTerm ){
assignedColor = lookupSheet.getRange("H"+(myRow+1)).getBackgroundColor();
break;
}
}
}
return assignedColor;
}