Install trigger for google app script in custom addon - google-apps-script

I am still very new to addons and I am having trouble to install triggers and have the related functions to run.
Below is the function to add 1 "on open" trigger and 1 "on edit" trigger to the sheet.
function addTriggers() {
var sheet = SpreadsheetApp.getActiveSheet();
var triggers = ScriptApp.getUserTriggers(sheet);
if(triggers.length!=2)//
{
ScriptApp.newTrigger('sheetOpen')
.forSpreadsheet(sheet)
.onEdit()
.create();
ScriptApp.newTrigger('sheetEdited')
.forSpreadsheet(sheet)
.onOpen()
.create();
}
Then I tried to install this function through onInstall();
function onInstall(e){
addSpreadsheetEditTrigger();
sheetOpen();
}
function sheetOpen()
{
//do something after the sheet is open;
}
function sheetEdited()
{
//do something when the sheet is edited by user;
}
When I tested this addon, the triggers were not installed and thus none happened. Also please note that I need to use installable triggers because I need to access external files.
Could someone let me know where I did wrong?

1. How to build a trigger manually
If you want to build a trigger for a spreadsheet, you need to specify as parameter in forSpreadsheet() the spreadsheet, not the sheet!
So:
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
...
ScriptApp.newTrigger('sheetOpen')
.forSpreadsheet(spreadsheet)
.onOpen()
.create();
...
It seems that you got the assignment of the functions 'sheetOpen' and 'sheetEdited' the wrong way around
You should doublecheck either you really need to build the trigger manually. Instead you can call the already existing onOpen(e) trigger (unless you need an installable one).
Sample:
function onInstall(e){
sheetOpen();
}
function onOpen(e){
sheetOpen();
}
function sheetOpen()
{
//do something after the sheet is open;
}
UPDATE
Now, the limitations of Addons won't allow you to install triggers directly. Instead, you can create a custom menu giving the user the option to install the triggers when choosing the respective option.
Sample:
function onInstall(e) {
onOpen(e);
}
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('MyAddOn Menu')
.addItem('Please click here to get started', 'addTriggers')
.addToUi();
}
function addTriggers() {
...
}

Related

Function based trigger using Sheet instead of Spreadsheet failing

I have two form feeding into the same sheet and I need different triggers for each sheet.
Tried to trigger using function based triggers but that is not working.
This function works:
function testTrigger() {
var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("myFunction")
.forSpreadsheet(sheet)
.onChange()
.create();
}
This one fails:
function testTriggerTwo() {
var sheet = SpreadsheetApp.openById("...").getSheetByName("Responses");
ScriptApp.newTrigger("myFunction")
.forSpreadsheet(sheet)
.onChange()
.create();
}
with
"Exception: The parameters (SpreadsheetApp.Sheet) don't match the method signature for ScriptApp.TriggerBuilder.forSpreadsheet."
Any ideas?
function testTrigger() {
var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("myFunction")
.forSpreadsheet(sheet)//this sheet is a class Spreadsheet
.create();
}
This one fails:
function testTriggerTwo() {
var sheet = SpreadsheetApp.openById("...").getSheetByName("Responses");
ScriptApp.newTrigger("myFunction")
.forSpreadsheet(sheet)//this sheet is a class Sheet
.onChange()
.create();
}
One of the problems in dealing with Google Apps Script and Google in general is that the people that sell products decided to begin to use the term Sheet as being synonymous with Spreadsheet but in the Apps Documentation Sheet refers to Excel like worksheet and I guess Spreadsheet refers to the excel like workbook. One is the file and the other is a tab. In the second version of the function you are using a Class Sheet when you should be using a Class Spreadsheet.
I would recommend using something like this for trigger creation to avoid the possibility of creating more that one trigger for any given function which can produce issues that are hard to debug.
function testTrigger() {
const ss = SpreadsheetApp.getActive();
if (ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "myFunction").length == 0) {
ScriptApp.newTrigger("myFunction")
.forSpreadsheet(ss)
.onChange()
.create();
}
}
By checking that none of the project project triggers have a handler with the same function name you can insure that you don't have two triggers for the same function.
You can control it by getting the the sheet name (where the response is landing)
function onFormSubmit(e) {
var sheet = e.range.getSheet().getName();
//do whatever you want by comparing the sheet name
}
You can have only one onFormSubmit Trigger.
But, you can do different things by an if statement

OnFormSubmit() not firing

I am trying to solve the following case: I have a template that is copied by users and linked to a Google Form. Also, I have a script that does some configuration to the Form Responses tab for its further usage. It works perfectly in the template, however, the installable onFormSubmit() trigger is not copied together with the template. To solve this I added onOpen() trigger that installs the onFormSubmit() which was confirmed to work.
The issue I am facing is that while onFormSubmit() is successfully installed in the template copy, it still does not fire automatically. I assume that this is related to some permissions issue. Is there any way to rewrite the script to avoid additional authorization?
function onOpen(e) {
addFormSubmissionListener();
//// other init...
}
function addFormSubmissionListener() {
var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("onFormSubmit")
.forSpreadsheet(sheet)
.onFormSubmit()
.create();
}
function onFormSubmit(e) {
var range = e.range
var sheet = range.getSheet();
var spreadsheet = SpreadsheetApp.getActive();
if(spreadsheet.getSheetByName('Responses') == null) {
sheet.setName('Responses');
sheet.insertColumnsAfter (7,10)
spreadsheet.getRange('Tech!A:J').copyTo(spreadsheet.getRange('Responses!H:O'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
sheet.hideColumns(16, 2)
var curr_sheet = spreadsheet.getSheetByName('Jira import')
updateFormulasTwoRows(curr_sheet);
}
}
Answer:
If you create a new project you will always have to authorise it, there isn't really a way of getting around this.

Installable trigger is just keep getting disabled

I have been trying to install an installable trigger for a googlesheet workspace addon when a button is clicked. The trigger is meant to get fired whenever a cell is modified.
Unfortunately when a cell is modified, the trigger keeps getting disabled. The "disabled reason" (in Apps Script > Triggers > Last run column in the list) says: This trigger has been disabled for an unknown reason. I have tried calling from onHomepage() also.
Here is the code:
function createWidgetDemoCard() {
return CardService
.newCardBuilder()
.setHeader(...)
.addSection(
CardService.newCardSection()
.setHeader('Simple widgets') // optional
.addWidget(CardService.newTextParagraph().setText('Some text'))
.addWidget(CardService.newImage().setImageUrl('.../trees-autumn-colors-lake-picutre-600w-1827312116.jpg'))
.addWidget(CardService.newButtonSet().addButton(CardService.newTextButton()
.setText('Create trigger')
.setTextButtonStyle(CardService.TextButtonStyle.FILLED)
.setOnClickAction(CardService.newAction().setFunctionName('createSpreadsheetOpenTrigger'))
.setDisabled(false))))
.build();
}
function createSpreadsheetOpenTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('TestMe')
.forSpreadsheet(ss)
.onEdit() //onChange() not working`enter code here`
.create();
}
function TestMe(e) {
var range = e.range;
range.setNote('Last modified: ' + new Date());
}
The authscopes are:
"oauthScopes": [
"https://www.googleapis.com/auth/spreadsheets.currentonly",
"https://www.googleapis.com/auth/spreadsheets"
]
The code from the TestMe() function works perfectly in a container-bound script. But because I am developing a Workspace addon, I want in a standalone script.
I can't really find a comprehensive documentation about developing an workspace addon.
Thanks!

Google Sheet onEdit(e) having permission problem

ERROR : You do not have permission to call ScriptApp.newTrigger. Required permissions: https://www.googleapis.com/auth/script.scriptapp.
Having permission problem to create time based trigger
function onEdit(e){
var sheetName = e.range.getSheet().getName()
if(sheetName == "Config")
{
if(e.range.getRow()==2 && e.range.getColumn()==1){
createSpreadsheetOpenTrigger()
}
}
}
function createSpreadsheetOpenTrigger() {
Logger.log("hello")
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('myFunction')
.forSpreadsheet(ss)
.onOpen()
.create();
}
For Simple Triggers, just running the script within the App Script Web IDE is enough and should prompt you with an authentication popup: Simple Auth Steps.
However, to programmatically create new Triggers you need to make sure the onEdit Trigger is Installable! This gives you increased permissions to do what you need.
We need to open up the dev console to set up an installable trigger.
We need to create a new trigger tied to our function. For installable triggers, it is best not to use the default simple trigger onEdit() function name.
Done! We should be able to run our functions based on triggers with increased permission scopes.

Using onChange trigger on google sheets script

I am running a script in google sheets script editor, to trigger the script I use onChange in the Current project's triggers, using specific function -> From Spreadsheet -> On change.
Important to mention that I use the sheet with 3 more members that have edit permission who change time to time the data, I built the script and activate the trigger.
When I change anything in the sheet I get alerted (the trigger were on) but when other member changes the data the trigger doesn't work.
What have I missed here?
Thanks.
Everyone needs a trigger
You can add the trigger management into the program so that they have the triggers in their projects too. The isTrigger() function insures that you only create one trigger for each instance. You find the documentation here.
function myTriggerSetup()
{
if(!isTrigger('functionName'))
{
ScriptApp.newTrigger('functionName').forSpreadsheet('Spreadsheet').onChange().create();
}
}
function isTrigger(funcName)
{
var r=false;
if(funcName)
{
var allTriggers=ScriptApp.getProjectTriggers();
var allHandlers=[];
for(var i=0;i<allTriggers.length;i++)
{
allHandlers.push(allTriggers[i].getHandlerFunction());
}
if(allHandlers.indexOf(funcName)>-1)
{
r=true;
}
}
return r;
}