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
}
}
Related
I'll try to be as specific as possible. This questions relates to Google Apps Script, bounded to two sheets.
I have a function that runs on edit through an installable (not simple) trigger. (Installable because it needs to call e.g. GmailApp). Call it Sheet A.
On another sheet, which we'll call Sheet B, is a script which causes an edit to be made in a cell on Sheet A.
When an edit is made manually on Sheet A, the installable on-edit script runs fine.
When the edit is made via the script on Sheet B, the installable on-edit script does not run. In other words, there doesn't seem to be any event associated with edits made by a script.
I am wondering if there is any way to trigger the on-edit script on Sheet A to run when changes are being made through another, external, bounded script.
I've looked through GAS documentation and searched as best I can here, but I cannot find an answer. I've tried to use a simple trigger, but it also does not seem to "pick up" the edit event when performed by another script.
Any help would be greatly appreciated.
Triggers only run on "human" changes. You need to rethink your flow.
If you have a function funA() changing something programmatically in a cell and you need to trigger another function funB(), just call funB() directly from funA() without counting on a trigger.
onEdit is triggered only if user updates a cell, not when the cell is updated programmatically.
You should expose onEdit from sheet A (or extract the method that actually does send the emails) and publish it as API executable
Then you can call that method from sheet B, after the edit is made programmatically.
I use an OnEdit function to move data to another sheet whenever a changed in a particular column. But The change should happen with a formula. But, it is not working.
example : When I change A1 to "ok" manually the OnEdit function work, but when the A1 cell change through an If condition to "ok" it's not moving and there is no movement.
Can you help me work the Onedit function without a human interfere?
Issue:
As you can see in the official documentation:
onEdit(e) runs when a user changes a value in a spreadsheet.
That is to day, this trigger does not track changes that are made programmatically:
Script executions and API requests do not cause triggers to run. For example, calling Range.setValue() to edit a cell does not cause the spreadsheet's onEdit trigger to run.
Workaround:
A possible workaround to this limitation is to have a time-driven trigger instead. You could, for example, have a trigger that will fire every minute, disregarding whether the spreadsheet was edited or not.
Then, inside the triggered function you could think of a way to check if the spreadsheet was edited during the last minute (for example, have the previous values stored in another sheet, or in a script property, and compare them to the current ones), and execute your desired actions if that's the case.
Reference:
Simple Triggers: Restrictions
ClockTriggerBuilder.everyMinutes(n)
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:(
I wrote a small script bound to a Google spreadsheet that reads an email-address from a cell in the last row and sends an email to it.
The values are collected by a WebApp (not by Google form).
I tried all kind of triggers. The time driven triggers work, but the spreadsheet triggers don't work. I tried all of them. If I change manually some cell in the spreadsheet the onEdit trigger is working, but it doesn't fire up when the sheet was changed by another script.
Google's dev says : The onEdit() trigger runs automatically when a user changes the value of any cell in a spreadsheet. but it doesn't precise the change could be from script or not.
You'll find here a comment from HDCerberus :
I'm not at my PC to write a full response, but at a glance it could be the OnEdit trigger, which ONLY works when the sheet is edited manually, and NOT by a script. Are you expecting it to run when the sheet is edited manually or by a script?
Not every change triggers onEdit(). Please take a look on answer from topic Detect user inserting row or column in a google spreadsheet and reacting in a script - you will find registered bugs and one of them says that values written by scripts do not trigger onEdit().
I'm playing with triggers.
In a spreadsheet, I have a function that inserts a date in a new row. Runs as a clock trigger every minute. Works fine if the spreadsheet is open or closed (loving that part).
In a standalone script, I setup a trigger for onEdit in the above spreadsheet. All it does is email me the e.value.
It works if I'm in the spreadsheet and just type in some characters in a cell.
What I'd "expect" is each time the date is inserted by the first trigger, it would trip the onEdit. Alas, it does not. Even if I run the insert date function outside of the trigger, my email onEdit trigger does not fire.
Any thoughts?
I ask, as my goal was to have scripts updating a sheet that kicked off an onEdit event.
Jim
UPDATE #1:
Maybe this code example helps?
I simplified this to one script inside a spreadsheet container. Each function works fine on their own and the second works if I do any interactive changes to the spreadsheet.
This is just exploration, so please ignore quota's or the utter nonsense of what I'm testing here :-)
insertClockTrigger: runs every minute, works fine
installableOnEdit: never triggers as an installable onEdit when insertClockTrigger fires
I'm curious why what looks to be an edit done by the insertClockTrigger is not firing an onEdit trigger. Do triggers not trigger triggers (could not help myself!)?
function insertClockTrigger() {
var sheet = SpreadsheetApp.openById('spreadsheet-ID').getSheets()[0];
var nDate = new Date();
sheet.getRange(sheet.getLastRow()+1,1,1,1).setValue(nDate).flush;
}
function installableOnEdit(e) {
GmailApp.sendEmail("some#email.com", "Test trig2", "FISH: "+e.value);
}
Call the onEdit function from the clock trigger function.
Also, you might hit a quota issue with running such a trigger every min.
Think I found an answer.
Henrique Abreu posted:
http://productforums.google.com/d/msg/apps-script/HmBg0p7dOZ8/xMb6wfcfvVQJ
Yes, "on edit" events are not called when the changes are made from
the code, they're are called only for manual changes. This behaviour
is intended by design, as to avoid unnecessary recursion problems.
Also, it just too easy to just call your desired on-edit function
directly from your code. i.e. when you script that inserts a new
ticket does so, it can just plainly call your "fundEmail" function,
there's no need for another trigger.
onEdit should be renamed to onUserEdit. It doesn't receive system changes, only direct user edits.
I haven't tested this, but onChange may do what you want.