OnEdit code stopped working without any changes - google-apps-script

I wrote the code below about a month ago. All it does it highlight the row when the checkbox is checked and clears it when unchecked. It was working fine, now it's not and I did not change anything.
In the executions section I can see it failing with:
Exception: The parameters (String,number,number,number) don't match the method signature for SpreadsheetApp.Spreadsheet.getRange.
at onEdit(Code:43:55)
and
Exception: The parameters (String,number,number,number) don't match the method signature for SpreadsheetApp.Spreadsheet.getRange.
at onEdit(Code:44:56)
Clearly it thinks that the variable "editRow" is a string but I have no idea why it does now and didn't before. 43:55 and 44:56 are the if statements for TRUE and FALSE, this code is clipped from all the rest (other things not relivant).
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();var sheet = ss.getSheetByName("Form Responses 1")
var editRange = sheet.getActiveRange();var editRow = e.range.rowStart;var editColumn = e.range.columnStart;var editValue = e.value;
var sheet = SpreadsheetApp.getActiveSpreadsheet();var formResponses = sheet.getSheetByName ("Form Responses 1");
if(ss.getActiveSheet().getName() == "Form Responses 1"){}
else{return};
if (editValue == "TRUE" && editColumn == 20) {sheet.getRange(editRow,1,1,21).setBackground("yellow")};
if (editValue == "FALSE" && editColumn == 20) {sheet.getRange(editRow,1,1,21).setBackground(null)};
}

The error messages says that e.range.rowStart and e.range.columnStart are returning a string rather than a number. That string might occurr, among other possibilities, if they are undefined i.e. because onEdit is triggered by something that provides a range property but that hasn't rowStart and columnStart properties.
Add console.log(JSON.stringify(e)); after function onEdit(e){ so you could see in the logs the values properties of e.

I started commenting out lines that did other things in the onEdit function. I narrowed it down to these lines that set variables for an email that is sent. It does not edit any of the already established variables, just makes new ones.
I do not understand why commenting these lines out allows it to work but it does. I was able to move them to below the lines that were erroring out and it's working again.
var recipient = formResponses.getRange("E"+editRow).getValue();
var subject = "Chromebook " + formResponses.getRange("B"+editRow).getValue() + " was marked as returned";
if (formResponses.getRange("H"+editRow).getValue() === ''){
var body = "Chromebook " + formResponses.getRange("B"+editRow).getValue() + " was marked as returned. Action taken: Returned from //ITSavvy"
}
else{var body = "Chromebook " + formResponses.getRange("B"+editRow).getValue() + " was marked at returned. Action taken: " + formResponses.getRange("H"+editRow).getValue()};

Related

You do not have permission to call Ui.showModalDialog Error, but Scope is Present, and Dialog box Shows Anyway [duplicate]

This question already has answers here:
Google Sheets OnEdit() - You do not have permission to call a service
(2 answers)
Google Spreadsheets "You do not have permission to call fetch" [duplicate]
(1 answer)
Closed 2 years ago.
When I'm on my Google Sheet, I have a checkbox that triggers a Modal Dialog box when selected via an onEdit function. I've added in the trigger on the project and when the checkbox is selected, the dialog shows just fine and I do not see an error.
However, in the Executions log, it lists the execution twice, and one of them fails and the other processes just fine. I checked in the project Overview, and the listed scope is present, so I'm not sure what the issue is. Here is the onEdit function and the function that has the Modal Dialog box.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var ui = SpreadsheetApp.getUi();
var sheet = ss.getName();
var cell = e.range;
var row = cell.getRow();
var col = cell.getColumn();
var val = cell.getValue();
if (sheet == "Emails" && col == 5 && row == 2) {
addEmailValidations(ss,ui);
} else if (sheet == "Emails" && col == 10 && row != 1 && val == true) {
previewEmail(ss,ui,row); //Row 24 in error message below
} else {
}
}
function previewEmail(ss,ui,row) {
console.log('previewemail start');
var sendCheck = ss.getRange(row,8).getValue();
var emailTemp = ss.getRange(row,9).getValue();
if (emailTemp == "") {
console.log('Stopped process: template not selected.');
ui.alert("Error","Please select an Email Template.",ui.ButtonSet.OK);
} else {
if (sendCheck == false) {
console.log('send was false');
ss.getRange(row,8).setValue(true);
SpreadsheetApp.flush();
} else {
}
var subject = ss.getRange(row,14).getValue();
var body = ss.getRange(row,15).getValue();
var rec = ss.getRange(row,16).getValue();
var htmlOut = HtmlService
.createHtmlOutput('<font face="Arial"><b>To:</b> ' + rec + '<br /><b>Subject:</b> ' + subject + '<br /><hr><br />' + body + '</font>')
.setWidth(800)
.setHeight(450);
ui.showModalDialog(htmlOut,'Email Preview'); //Row 113 in error message below
ss.getRange(row,10).setValue(false);
}
}
From the user perspective, the dialog box shows just fine, but here is the execution log:
Exception: You do not have permission to call Ui.showModalDialog.
Required permissions:
https://www.googleapis.com/auth/script.container.ui
at previewEmail(Code:113:8)
at onEdit(Code:24:5)
But when I go into the Overview, the correct scope is listed:
Is there something weird that I've done with my onEdit trigger that's causing this to happen? And yes, I've gone into the Triggers section and added in a trigger to run this function on edit.
Any help would be greatly appreciated - thanks!

Why is this changed value read as the original after Utilities.sleep?

I have Google Sheets running in OnEdit(). When a cell in a specific row is changed to "completed" an email will be sent to the job owner. For now it pops up a browser message.
But I want to avoid sending an email in the case where the selection is accidental and gets changed again a few seconds later.
The surprising issue is that after running Utilities.sleep(10000) and re-reading the cell's value to make sure it's the same, even if it has been changed, it will read the value again as "completed". Is this something to do with the sleep function?
if (changedColumn == stageColumnIndex) {
var newValue = sheet.getRange(changedRow, changedColumn).getValue(); // read changed cell value before the sleep call
if (newValue.toLowerCase() == "completed") {
// check again in a few seconds in case it was an accidental selection which was quickly changed
Logger.log('Sleeping');
Utilities.sleep(10000);
var checkedValue = sheet.getRange(changedRow, changedColumn).getValue(); // read same cell value after sleep call but it is the same as newValue even when the cell was changed while sleeping
Logger.log('newValue: ' + newValue);
Logger.log('checkedValue: ' + checkedValue);
var announceChange = (checkedValue == newValue);
if (announceChange) {
var streetIndex = 2;
var street = sheet.getRange(changedRow, streetIndex).getValue();
Browser.msgBox("Job completed at " + street + ".");
}
}
}

Google Script not Finishing Successfully

I recently adapted a short piece of script to automatically send an e-mail to me when a specific response appears (the word FAIL) in a 'Google docs' spreadsheet, that collects responses from volunteers using a 'Google Form' to record their weekly checks on life-saving equipment.
The email on FAIL is working well, having tested it with a few FAIL responses. However, as the form 'owner' I am receiving notifications from Google, for each normal PASS response submitted, telling me that the script failed to finish successfully.
8/4/15 10:57 AM
SendGoogleForm
ReferenceError: "found" is not defined. (line 35, file "Code")
formSubmit
It finishes successfully if a FAIL response is submitted, so I suspect that, due to my inexperience with scripts, I have not defined what should happen when found is 'not true'.
It's probably glaringly obvious to a more experienced script writer but none of the things I have tried with 'Else' seem to work.
Any suggestions would be greatly appreciated.
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers)
ScriptApp.deleteTrigger(triggers[i]);
ScriptApp.newTrigger("SendGoogleForm")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit().create();
}
function SendGoogleForm(e) {
if (MailApp.getRemainingDailyQuota() < 1) return;
// Recipients email address
var email = "12345#abcde.co.uk";
// Subject for Google Form email notification
var subject = "Weekly Checks - FAIL Submitted";
var s = SpreadsheetApp.getActiveSheet();
var columns = s.getRange(1, 1, 1, s.getLastColumn()).getValues()[0];
var message = "A check form has been submitted containing a ** FAIL ** response: ";
// Look for a 'FAIL' response
var key = columns[keys];
for ( var keys in columns ) {
if ( e.namedValues[columns[keys]] == 'FAIL') {
found = true;
}
}
// Only include form fields that are not blank
if (found)
for (var keys in columns) {
var key = columns[keys];
if (e.namedValues[key] && (e.namedValues[key] !== "")) {
message += key + ' : ' + e.namedValues[key] + "\n\n";
}
}
MailApp.sendEmail(email, subject, message);
}
Your found variable is null whenever a non-"FAIL" occurs in your script and I think your if(found) is creating the error message.
You could Initialise your variable:
var found = false;
before you start testing it. That way, your if(found) will be false and it will skip down to your send email code.
Perhaps u can use
if ( e.namedValues["Pass or Fail"] == "Fail" ) { ... }
where "Pass or Fail" is the form question title. And also use e.range.getRow() to capture the sheet row that the responses were written.

Approval Process: 'e.parameter.approval' inside an "if" cycle

I'm trying to build an Approval flow with Google Apps Script. I would also like to add an "if" cycle that creates a Calendar event if e.parameter.approval is true.
So, everything works but the system doesn't recognize the "if" cycle. I've tried this:
function doGet(e){
var answer = (e.parameter.approval == 'true') ? 'Approved!' : 'Not this time';
MailApp.sendEmail(e.parameter.reply, "Request",
"The answer is: "+ answer);
// here I tried both with (e.parameter.approval === 'true') and (check === answer) and also with "=" "==" and "==="...
var check = 'Approved!';
if(e.parameter.approval === 'true'){
var calendar = CalendarApp.getCalendarById('xxxxxxx')
//create event
var newEventTitle = 'Event Test';
var newEvent = calendar.createAllDayEventSeries(newEventTitle,
Date,
CalendarApp.newRecurrence().addDailyRule().times(10),
{description:'test'});
//get ID
var newEventId = newEvent.getId();
}
var app = UiApp.createApplication();
app.add(app.createHTML('<p><br><h2>An email was sent to '+ e.parameter.reply + ' saying: '+ answer + '</h2>'))
return app
}
Do you have any idea why the system skips the "if" cycle and goes directly to "var app"?
e.parameter.approval might not be returning anything. I could be "undefined". It could be "null". You need to know for sure what e.parameter.approval is doing. There is also the possibility that the if condition is actually working, but then there is an error that kills the code and stops it. You'll need to debug every line. Try using the "debug" tool.
Apps Script Debugging Tool
You are using:
if(e.parameter.approval === 'true'){
The word 'true' is in quotes, which means it's a string value, not a true/false value.
Try:
if(e.parameter.approval === true){

Setting Script Property using it in "if" in Google

I have a script that is supposed to mail a chart URL when a metric falls out of X range and Only if someone has entered a new metric. It's mailing everytime I run the script so I know the setProperty is not working and the "if" statement isn't working because it's only supposed to mail if X is TRUE.
The sheet... https://docs.google.com/spreadsheet/ccc?key=0Ai_2YLvaQba0dHN1dWFpY0ZSbGpudWF4cTJYNlFwNHc&usp=sharing
My code...
function myAverages() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var value = ss.getSheetByName("EmailServices").getRange("P2").getValue().toString();
var outside = ss.getSheetByName("EmailServices").getRange("S2").getValue().toString;
var mailed = ss.getSheetByName("EmailServices").getRange("T2").getValue().toString();
var stemiAverage = ss.getSheetByName("EmailServices").getRange("R2").getValue().toString();
var stemiChart = ss.getSheetByName("EmailServices").getRange("U2").getValue().toString();
var last = ScriptProperties.getProperty('last');
//if "value" is not equal to ScriptProperty "last" AND "outside" is TRUE, then mail
if(value =! last, outside = "TRUE")
{
MailApp.sendEmail("dave#mydomain.com", "Metric Warning",
"Yearly STEMI Average has fallen below 65%, it is now: " + stemiAverage + "%" +
"\n\nTo see the current trending chart " + stemiChart + "\n\n The sheet that calculated this is here " + ss.getUrl());
ScriptProperties.setProperty('last','value');
}
}
Thanks for any help you can lend. I'm teaching myself this stuff and feel very much like a newby. I've tried a hundred or more combinations to the script before posting here.
As a complement to Phil's answer and following your comment, there is another error in your script :
ScriptProperties.setProperty("last","value");
should be
ScriptProperties.setProperty({'last':value},true);
The true parameter is optional, see documentation on ScriptProperties, it gives you the possibility to delete all other keys.
So you're complete function with corrections would be :
function myAverages(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var value = ss.getSheetByName("EmailServices").getRange("P2").getValue().toString();
Logger.log('value = '+value)
var outside = ss.getSheetByName("EmailServices").getRange("S2").getValue().toString();
Logger.log('outside='+outside)
var mailed = ss.getSheetByName("EmailServices").getRange("T2").getValue().toString();
Logger.log('mailed = '+mailed)
var stemiAverage = ss.getSheetByName("EmailServices").getRange("R2").getValue().toString();
var stemiChart = ss.getSheetByName("EmailServices").getRange("U2").getValue().toString();
var last = ScriptProperties.getProperty('last');
Logger.log('last='+last)
if(value != last && outside == "true"){
MailApp.sendEmail("me#mydomain.com", "Metric Warning",
"Yearly STEMI Average has fallen below 65%, it is now: " + stemiAverage + "%" +
"\n\nTo see the current trending chart " + stemiChart + "\n\n The sheet that calculated this is here " + ss.getUrl());
ScriptProperties.setProperty({'last':value});
Logger.log('mail sent')
}
}
You need to use the AND operator: &&.
And also, checking for equality requires 2 equals signs: ==.
So be sure you try this:
if (value!=last && outside=="TRUE") {