onEdit() function does not triggered when change was made by automatic script - google-apps-script

my onEdit() function calling to other function when there is a change in the sheet.
if the user makes the change all works fine.
but if the change was made by google-form (the form fill some cells with the answers it gets) onEdit() does not trigger.
do I miss something?

Yes, you forgot to read the documentation for the simple triggers:
onOpen(e) runs when a user opens a spreadsheet, document, or form that he or she has permission to edit.
onEdit(e) runs when a user changes a value in a spreadsheet.
onInstall(e) runs when a user installs an add-on.
doGet(e) runs when a user visits a web app or a program sends an HTTP GET request to a web app.
doPost(e) runs when a program sends an HTTP POST request to a web app.
and installed triggers:
Even though installable triggers offer more flexibility than simple triggers, they are still subject to several restrictions:
They do not run if a file is opened in read-only (view or comment) mode.
Script executions and API requests do not cause triggers to run. For example, calling FormResponse.submit() to submit a new form response does not cause the form's submit trigger to run.
Installable triggers always run under the account of the person who created them. For example, if you create an installable open trigger, it will run when your colleague opens the document (if your colleague has edit access), but it will run as your account. This means that if you create a trigger to send an email when a document is opened, the email will always be sent from your account, not necessarily the account that opened the document. However, you could create an installable trigger for each account, which would result in one email sent from each account.
A given account cannot see triggers installed from a second account, even though the first account can still activate those triggers.
Consider what would happen if your onEdit(e) was activated by programmatic changes, such as if your onEdit function alters the spreadsheet values...
In your situation, where you want form submission to activate your on edit function, You will need to install a form submission trigger (there is no simple trigger for form submissions).
An example function to receive your form submission trigger:
function giveMeAnInstalledFormSubmitTrigger(formSubmitEventObject) {
if(!formSubmitEventObject) throw new Error("You called this from the Script Editor");
var newEventObject = /* do something with the formSubmitEventObject */;
// Call the on edit function explicitly
onEdit(newEventObject);
}
You can read more about the event objects that triggered functions receive in the Apps Script documentation: https://developers.google.com/apps-script/guides/triggers/events

onEdit() will not be triggered by another script editing a sheet or by a form submission.
You can use onFormSubmit(e) instead depending on what your function does it would be a good idea to use the e parameter of the trigger.
https://developers.google.com/apps-script/guides/triggers/events#form-submit

What i have done is that i created an extra sheet with a cell that is the same where the primarecell is(the cell that changes). Leave it for now. I open the scriptapp and write down the code(the code that should happen if the cell changes). Then i wrte down "if" and take the two value i both cells and make an trigger that goes on every minute. With that said, if The cells are the same the "if" is looping on "true". But if something change on the primary cell, it will be "false" and you use "else". Under"else" you should have what ever function you want when soemthing change in that cell. + You must have a funtion where you insert the new value form the primarycell to the "check cell" if u want this too function as loop. Otherwise the "if" code will loop "false" every minute becuse the both cells are not the same.
My english and explaining is not that good:(

Related

onSpecialEdit() for Google App Script on a sheet with many users executes for all, each time

This can't be right. What am I missing?
I have a Google Sheet with scripts. The scripts are using certain ui functions that require authentication and special permissions coming from an onEdit() event. Therefore, I had to create onSpecialEdit() and the custom trigger to run that function with event source of the spreadsheet and event type onEdit(). This all works fine. Script does what it should.
From what I've seen, each person who needs to have this ability and access the special edit will need their own trigger. That is created for them automatically. Triggers all work for each person.
Now, what I see is that when I do an action that triggers onEdit(), it appears to run the onSpecialEdit() 20 times...once for each person who has that trigger....I'm assuming.
This can't be right. What am I missing? Is there another way to create triggers where they are only executed by the person triggering? Is this approach wrong?
Issue:
You want to have an onEdit trigger that has access to services that require authorization.
These services should have access private of the user who has caused the trigger to run by editing the spreadsheet.
Since the services require authorization, it cannot be a simple but an installed trigger (Restrictions).
Since installed triggers act on behalf of the user who installed them, they can only access data of the user who installed them.
Therefore, each user whose data should be accessed needs to install the trigger, so multiple triggers should be installed.
A trigger runs whenever any user edits the spreadsheet, it doesn't have to be the user who installed the trigger. Because of this, all of the installed onEdit triggers will run whenever any user edits the spreadsheet.
Solution:
Use Session.getActiveUser() and Session.getEffectiveUser() to check whether the user editing the spreadsheet (getActiveUser) is the same as the one who installed the spreadsheet (getEffectiveUser). If it's not, stop the function execution. This way, only one of the multiple onEdit triggers will make the corresponding actions.
Code sample:
function onEditTrigger(e) {
const active = Session.getActiveUser().getEmail();
const effective = Session.getEffectiveUser().getEmail();
if (active === effective) {
// TRIGGER ACTIONS
}
}

Can I somehow force onOpen trigger?

I've been struggling for two days now to allow the users from my organization to edit the protected pieces of a spreadsheet using only the script I made.
I've been through hell and how I made it work in the end is, I made a fake hidden sheet where the data is stored, and then onOpen, I copy-paste that data to the sheet that the user sees (that they cannot edit). I want to make the UX a bit better if possible, and I was hoping there is a way to force the onOpen trigger from the script. I know I probably didn't do this right, but I cannot spend more time researching, so I need to brute-force it now. (I've tried onChange triggers, I've tried setting permissions in my web app, using doPost, and my brain hurts, this is the first time I'm doing scripting).
TL;DR
Is there a way to refresh the whole tab from the script editor? I need to trigger the onOpen event without the user having to reload the page.
To "force" the onOpen simple trigger you have the following options
call onOpen
function respondToChange(e){
onOpen();
}
If your onOpen function requires the event object you will have to emulate it.
function respondToChange(e){
const event = {};
// add the required properties to event
onOpen(event);
}
change the spreadsheet locale by using setSpreadsheetLocale
Related
How to change Google Apps Script locale?
When a function is run by clicking a button or choosing a custom menu item, or through a simple trigger such as onOpen(e) or onEdit(e), it runs under the account of the user at the keyboard.
To trigger a function to run under another account that has rights to the protected ranges, you need an installable trigger.

Trigger onEdit Trigger through programmatic edit

I've built a spreadsheet that tracks form responses using the onSubmit trigger. This works well. I then want to display part of the spreadsheet on another spreadsheet, and have built a script that does this.
In order to ensure the second spreadsheet is dynamically updated and synchronised with the first, I have tried to use the onEdit installable trigger; however, it does not work when it is programmatically edited, only if I manually edit spreadsheet 1. Any solutions?
Triggers do not fire on the spreadsheet changes made by scripts. I think the idea is that the script making changes can also follow through on any consequences of those changes. In your case, I see three solutions:
If you just want to "display part of the spreadsheet on another spreadsheet", then importrange command suffices, you don't need a script to do that.
The function triggered by form submission can modify the target spreadsheet itself. To do this, you need an installable trigger running on form submission, since simple triggers cannot access other spreadsheets.
If you really want to trigger a function in a script attached to another spreadsheet, you can run a time-based trigger that will check the last-updated time of the spreadsheet.
Example of #3: a function that can be set to run every 5 minutes, to detect changes of any kind.
function checkForUpdates() {
var updated = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId()).getLastUpdated();
if (new Date() - updated < 300000) {
// updated in the last 5 minutes, do something
}
}

Google Spreadsheet trigger programmatically added is not

I want to process values submitted from a Google Form when they get saved in the associated spreadsheet. I have an app script associated with the form (as it adds an addon menu there and is suppose to be used from FormApp), and this one install the trigger on destination spreadsheet as following.
ScriptApp.newTrigger('onFormSubmit').
forSpreadsheet(destId).onFormSubmit().create();
function onFormSubmit(e) { Logger.log("--> submit"); }
I also have added an email notification (Immediate) on the trigger.
The trigger appears in project triggers. Calling the onFormSubmit function from editor, or on other event, is working and debug statement is written in the log.
When the form is POSTed, I don't either see anything in the log, nor receive any mail notification.
What's wrong there?

How to get onFormSubmit to trigger automatically?

The "fix" (test_onformsubmit) code you gave, I have to manually run it every time there is new data in the spreadsheet. I was wanting it to automatically send the pdf to email when Form is submitted. Is there a way? Because the manual way runs the code exactly like its supposed to, but I want this as an automatic event so I don't have to do anything.
See parent thread of original problem/question
Read Understanding Triggers. This function is an Installable Trigger, so you need to set it up to run when a form is submitted. It's easy - I would have thought a Forms tutorial would have walked through it.
In the Script Editor:
Choose Edit > Current project's triggers. You see a panel with the message No triggers set up. Click here to add one now.
Click the link.
Under Run, select the function you want executed by the trigger. (That's onFormSubmit(), in this case.)
Under Events, select From Spreadsheet.
From the next drop-down list, select On form submit.
Click Save.
From this point on, the function will be triggered whenever a form is submitted to the spreadsheet.
If you plan to share your script, each recipient will need to repeat these steps.
As an aside, you should change the email setting in your script, so it will work for ANYONE.
var email_address = Session.getActiveUser().getEmail();