I am building a script and want to include some failsafes to prevent the script from getting errors. One of the errors I am attempting to prevent is the script timing out every time the sheet is closed. Even if I reopen the sheet that runs the script before it finishes it’s task it still times out.
The main function uiCheck is set on a ‘onEdit’ trigger, so once a specific cell checkbox is set to true it will input a random digit into column a up to row 150. When I run my script, I let it begin inputting values (so I let it get to the point where it calls randomDigitIntoCell function), then I close the tab, I come back to the sheet before it reaches cell 150, and it continues to go through until cell 150. From here I would expect to catch an error but instead no errors are caught and I have to wait 30 minutes until it times out.
Can someone help me figure out how to get the script to continue after calling the randomDigitIntoCell instead of timing out?
function uiCheck(e) {
let sheetName = e.source.getActiveSheet().getName();
let ss = SpreadsheetApp.getActiveSpreadsheet();
let editResults = e.source.getActiveSheet().getRange(1,2).getValue();
let ui = SpreadsheetApp.getUi();
if(sheetName == "test_sheet" && editResults == true) {
SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(1,2).setBackground('red');
SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(1,2).setValue(false);
console.log('begin updates');
try{
ui.alert('Updates will start once "OK" is clicked. Click "OK" to begin!');
randomDigitIntoCell(ss,sheetName);
SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(1,2).setValue(false);
SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(1,2).setBackground('white');
ui.alert('updates are done!');
return;
}
catch(e){
console.log('error: '+ e);
SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(1,2).setValue(false);
SpreadsheetApp.getActive().getSheetByName(sheetName).getRange(1,2).setBackground('white');
return;
}
}
console.log('non essential update made.')
}
function randomDigitIntoCell(ss,sheetName){
let sheet = ss.getSheetByName(sheetName);
let count =1;
console.log('start inputting values into cells')
do{
let randomDigit = Math.floor((Math.random()*10)+1);
sheet.getRange('A'+count).setValue(randomDigit);
count++;
SpreadsheetApp.flush();
}
while (count <= 150);
console.log('done inputting values into cells');
return;
}
Main problem
It looks that the problem is caused by using and alert (SpreadsheetApp.getUi().alert(/** something */)
) and not closing it before closing the spreadsheet.
Note: I think this problem was introduced recently as since a few weeks ago, the way alerts and dialogs behave has changed.
Workaround
Instead of using ui.alert(/** some mesage */);
use e.source.toast(/** some mesage */)
. Another option is to use the HTML Service to show a dialog instead.
From the question
From here I would expect to catch an error but instead no errors are caught and I have to wait 30 minutes until it times out.
In the meantime, if you fix this, instead of waiting until the time runs out, you can go to the Executions Log page of the Apps Script project and terminate the execution.
DRY = Don’t repeat yourself.
The script includes many SpreadsheetApp.getActive()
/ SpreadsheetApp.getActive().getSheetByName(sheetName)
. On one side, the active spreadsheet is already included in the on-edit event object.
Replace
let sheetName = e.source.getActiveSheet().getName();
by
let sheet = e.source.getActiveSheet();
let sheetName = sheet.getName();
then replace all SpreadsheetApp.getActive().getSheetByName(sheetName)
by sheet
.
Also, replace
randomDigitIntoCell(ss,sheetName);
by
randomDigitIntoCell(sheet);
and
function randomDigitIntoCell(ss,sheetName){
let sheet = ss.getSheetByName(sheetName);
by
function randomDigitIntoCell(sheet){
While this will not solve the problem, it will make your script more efficient.
Related
- Capture onClose event for Spreadsheet App Modal Dialog in Google Apps Script
- SpreadsheetApp.getUi().showModalDialog has changed since 26072024