Function based trigger using Sheet instead of Spreadsheet failing - google-apps-script

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

Related

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.

Google app script - Getting last sheet row updated

I have a script associated with a google sheet that it's call after a Google form is submitted.
Actually I can get all rows or the last but in case one form answer is updated I need to find this row updated to make my treatment.
Is there a way to do that?
This is my two case:
// Getting last row data
function getSpreadSheetLastRowData() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var row = sheet.getLastRow();
return sheet.getRange('A'+row+':BG'+row).getValues();
}
// Getting all rows data
function getSpreadSheetAllData() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var row = sheet.getLastRow();
return sheet.getRange('A2:BG'+row).getValues();
}
You will need to write an event handler for the onFormSubmit event object and attach it to your spreadsheet.
From the Spreadsheet linked to your Form go to Tools > Script Editor.
Here write a function to install the trigger:
function installTriggerToSpreadsheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger('sumbissionHandler')
.forSpreadsheet(ss)
.onFormSubmit()
.create();
}
Now your trigger will handle the form submission calling the submissionHandler function inside the Spreadsheet context.
This means you can read the affected row by using a function like this:
function submissionHandler(e) {
var affectedRow = e.range.getRow();
// ... Apply your treatment.
}
References:
Triggers
Event Objects
If you have a script that is triggered by a form submission then take the event object lets call it e. Then e.range is the range that was edited in the linked sheet. So e.range.getRow() is the row and e.range.getSheet().getName() is the name of the linked sheet.
form submit object for spreadsheet

How to trigger a google spreadsheet function onEdit?

function oneWeek() {
var sheetURL = SpreadsheetApp.getActive().getUrl()
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
var sheet = spreadsheet.getActiveSheet();
// do stuff with sheet
}
How do I get this function to trigger onEdit?
I've tried this for the sheet,
function onEdit(event) {
var sheet = event.source.getSheetByName('x');
// do stuff with sheet
}
EDIT: I forgot to mention that my script did https request so that's the reason onEdit didn't work. The solution is here: https://productforums.google.com/forum/#!topic/docs/0nxLYWXVo6Y
Because this script does other things, like a HTTP request, it cannot be assigned to the default onEdit() functions, you need to create it as a custom function and assign it in the Edit menu. Edit->Current Project Triggers and create a new one for onEdit. Just point it at your function and you’re done.
function onEdit(e){
if(e.range.getSheet().getName()!='x'){return;}
//do stuff on sheet x here
}

Set trigger in script in Google Sheets programmatically

I am trying to get a Google Apps Script to trigger on edit of a particular cell. Right now I have achieved this using a run-time trigger option built in Google Sheets. However, I lose the run-time trigger when I make a copy.
Hence, I have managed to find a programmable trigger from various sources and patched something together, but it is not working. I have no programming knowledge, so I am unable to understand where I am going wrong.
My objective is to run the script when user edits the Named Range "monthfilter".
With script trigger creation
function HideColumns() {
//open the current spreadsheet and get the value of the named range and trigger project
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger("monthfilter").forSpreadsheet(ss).onedit()
var name = ss.getRangeByName("monthfilter");
var namevalue = name.getValue();
My previous function:
function HideColumns() {
//open the current spreadsheet and get the value of the named range
var ss = SpreadsheetApp.getActive();
var name = ss.getRangeByName("monthfilter");
var namevalue = name.getValue();
//show or hide February
if (namevalue == "February") {
var sheet = ss.getSheetByName("MIS");
sheet.hideColumns(30);
/** other stuff */
Not sure what is the 'runtime trigger' you mean, there are three kinds of trigger:
Simple trigger
Installable trigger
Time driven trigger
onEdit(e) is just a Simple trigger.
Let's take a look to the following situation:
yourMainSpreadsheet - (You are the owner)
|
binding script functions: - 1. function makeCopy( ) {...}
2. function monthFilter(e) {...}
3. function onEdit(e) { monthFilter(e); }
|
| After copying, new spreadsheet remains all functions and simple trigger.
V
newSpreadsheet- (You are the owner, maybe share with other editors.)
|
binding script functions: - 1. function makeCopy() {...}
2. function monthFilter(e) {...}
3. function onEdit(e) { monthFilter(e); }
No matter what kind of trigger you use or just manually run makeCopy() in yourMainSpreadsheet, onEdit(e) would be copied to new spreadsheet too, and it works when you or other editors make edits, you don't need to do anything:
function makeCopy(){
var mainSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var newSpreadsheet = mainSpreadsheet.copy('newSheet');
}
function monthFilter(e) {
var thisSheet = e.source.getActiveSheet();
var name = thisSheet.getRangeByName("rangeMonthfilter");
var nameValue = name.getValue();
//...
}
function onEdit(e) {
monthFilter(e);
}
What you have done is set a installable trigger to new spreadsheet.
Highlight of documentation about difference between them.
Installable triggers, however, offer more flexibility than simple
triggers: they can call services that require authorization ...
For example:
function monthFilter(e) {
var thisSheet = e.source.getActiveSheet();
var name = thisSheet.getRangeByName("rangeMonthfilter");
var nameValue = name.getValue();
// If you have operation like:
var onlyYouHavePermission = SpreadsheetApp.openById('xxxxxxxxx');
/* This is not allowed if you just use Simpler trigger onEdit(e) to
drive monthFilter(). */
}
For this, now is the time to use installable trigger:
function makeCopy(){
var mainSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var newSpreadsheet = mainSpreadsheet.copy('newSheet');
ScriptApp.newTrigger('monthFilter')
.forSpreadsheet(newSpreadsheet)
.onEdit()
.create();
/* The host of this trigger is you, it's like you
deploy a trigger to the newSpreadsheet, and make other editors
available to do something on "onlyYouHavePermission" through it.*/
}
Update
If all you want to do is just in HideColumns() you provide, you just need to add a new function which is a simpler trigger in script editor:
function onEdit(e) {
var ss = SpreadsheetApp.getActive();
var name = ss.getRangeByName("monthfilter");
var namevalue = name.getValue();
if (namevalue == "February") {
/* If you copy the spreadsheet, of course including the sheets
inside it, and you share the permission of the new spreadsheet to
other editors, because they own the permission, authorization
is not required here.
*/
var sheet = ss.getSheetByName("MIS");
sheet.hideColumns(30);
}
}

onEdit Installable Trigger not firing

I'm trying to create a script in Google Sheets that will send me an automated email every time that a value within a given column ("Column H") drops below a certain threshold. I've currently got the following script written, which includes an installable onEdit trigger. However, the script is not running when the spreadsheet is edited:
function StationeryEdited(e){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getRange(2, 8, 200, 1).getValues();
var newValue = e.value;
if (newValue < "10"){
MailApp.sendEmail("test#test.co", "TEST", "TEST");
}
function createSpreadsheetEditTrigger(){
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger(StationeryEdited)
.forSpreadsheet(ss)
.onEdit()
.create();
}
}
Have you tried putting function name in quotation marks like this?
ScriptApp.newTrigger('StationeryEdited')
Also, you can simply go to Edit -> Current project triggers and configure the trigger for your function manually select the following options for the 'StationeryEdited' function
Try this and set the installable trigger through the script editor:
function onEdit(e) {
var editColumn=e.range.getSheet().getActiveCell().getColumn()
if(editColumn==8 && e.value>10){
MailApp.sendEmail("test#test.co", "TEST", "TEST");
}}