I need a little guidance!
I have created a simple script for a Google Spreadsheet that is designed to email a user when a specific criteria is met and mark that row as "Emailed"; it runs on the onEdit trigger and works great.
However, if more than one trigger enabled user has the sheet open at the same time it will send the same email from each account.
I tried using:
function onChange(e) {
if (ROW HASN'T BEEN EMAILED ALREADY) {
if (3 CELLS IN A ROW HAVE CONTENT) {
if (Session.getActiveUser().getEmail() == e.user.getUserLoginId()) {
SEND THE EMAIL
MARK ROW AS EMAILED
}
}
}
}
So that only the user that made the change sends the email, however, all users still send the email. I have compared the values Session.getActiveUser().getEmail() and e.user.getUserLoginId() produce manually and in theory it should work ... though clearly I am doing something wrong!
Thanks.
This is a bit of a confusing topic but I believing this is functioning correctly.
Here are some details.
In the onChange(e) function, e.user will always be the person that "owns" the document. Look towards the bottom of this page on events in the document. In essence, you cannot figure out which user's change caused the trigger to fire.
When there are two users each with a trigger on the onEdit event, then both of the triggers will run each time (essentially the function runs twice) even if only one of the user has the spreadsheet open. However, per #1 you can't within the trigger function run figure out which user's change caused the onEdit event
You'll have to rethink your workflow a bit, perhaps as a timed trigger that checks every hour for people to be emailed. Another option is to only have one trigger that runs as the document owner and you can perform the checking logic there. Hope this makes sense.
Related
I have a working script on Spreadsheet that pops up prompts and alerts on editing certain ranges, but when multiple users are on the sheet at the same time this pops up to every single one regardless of whom made the change.
Is there a way every message appears only to the user who edited or even triggered it?
And if not, a way to find out how many users have the sheet open so to disable this when more than one?
The trigger is on an admin (owner) account and the sheet is protected, so only certain cells are editable by normal users, and the script completes this cells. Just to mention having triggers on user accounts wouldn't work as the don't have permission to edit everything or it d' defeat the purpose.
Something like this should do the trick
function onEdit(e){
var userMakingTheEdit = e.user;
var UserLoggedON = Session.getActiveUser().getEmail()
if (userMakingTheEdit == UserLoggedON)
{
// Show alert
}
}
Sorry, my mistake.
There was a bug on loop which made that behavior that i had trouble finding, now it's fixed and it works as it should.
Using onEdit(e) works correctly only running the code with prompts and alerts on that single users.
Thank you either way on responding, the last one was actually really helpful on something else, i appreciate it.
This is a trigger and script coded directly into the form rather than on the spreadsheet that gets the form, I'm not sure if that is why this isn't working or not.
The trigger is set:
Owned by: Me
Last Run: null
Deployment: Head
Event: From Form-On form submit
Function: sendEmailFromSheet
Things I've tried: having the person who originally owned the form create a trigger yesterday, me create one today.
Filling out the form DOES result in the answers on the result spreadsheet, but it doesn't fire this onSubmitForm trigger, and I have no idea why. Again, it isn't that the function is failing but that it isn't firing at all.
Given that the function label is 'sendEmailFromSheet' then I suspect that its waiting for the sheet to receive data. But because the function is in the form it will never run because your trigger references the form and not the sheet.
If you can show us the code behind it then we might could tell you better. But without knowing that part then I think that is the mostly reason.
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 have a shared google spreadsheet with rows representing accounts and the state of those accounts.
Accounts can go from being outlined, to signed, to ordered.
I want it so that when an account is Edited from Outlined -> to Signed, I send an email to the person responsible for the "Ordering" portion.
Because I can't send emails inside the onEdit(e) trigger, I have made a custom function, customOnEdit which will listen to the same events and send the email. This works fine.
function customOnEdit(e) {
process(e);
}
What happens next will shock you:
The trigger will simply stop working
The trigger will go from being regular black, to being greyed out. Any edits will not send any emails:
Trigger greyed out
It can be weeks later. It can be just the next day. But because of this I have to check it daily and reset it otherwise things will stop flowing.
How can I deal with this issue?
I recently created a script associated with a spreadsheet. It is a wood supply chain simulation game score viewer. Basically, it fetch (with Urlfetch) the game database to keep track of scores for every team playing in tables and graphs. The spreadsheet is then shared to every team member, which can see the progression of the game.
So I used an installable onMinute time trigger to refresh the spreadsheet with updated score from the database. Everythings was working, but recently, I started to receive app-script-notifications of failure with error :
Service invoked too many times for one day: urlfetch.
I then realised that the installable triggers are executed when the documment is not open, which is totally logic. Also, since developpement mode, I had quite a lot of the spreadsheat copy (je comprend pas sa), which explains the reach of my quota. Altough, I only need to refresh the scores for my application when the document is open.
Here are my questions :
Is the installable onMinute time trigger the right way to do that?
Is there a way to make the trigger run only when the document is open?
This is my first question here so feel free to post useful comments to allow me to improve.
Thank you.
Unless you can write code on the game side to push the changes to the spreadsheet, which would use less resource on both sides, a time-driven triggers seems like the only "automatic" way to go.
I say automatic, because you could change it to "on-demand". I mean, you could add a menu to your spreadsheet or an image (where you can assign to run a script on click), that will update the scores.
This could also be semi-dynamic, for example, when the user clicks the button, you start to update the scores automatically (setting up the time-driven trigger programatically) for the next 30 minutes or so.
Asking your question n.2: no, it is not possible. Well, only half-way. Because you can detect when the spreadsheet is opened (by setting a on-open trigger), but you can't know when it is closed.
What about using the onOpen event to programmatically create the following:
a new trigger that updates the spreadsheet every minute
a new hourly trigger that checks
if {a user property is set}
then deletes all the triggers
else set the user property
a onEdit trigger that unsets the previously mentioned user property
So that if a user hasn't edited the spreadsheet for an hour all the triggers stop
It's a bit convoluted but without an onClose event, convoluted is the best you can hope for.
Here is a piece of code I imagine that could maybe do what you want or at least get close...
I tried it on a testsheet (shared with authorization requested) and it works as expected, i.e the timer triggered function executes only if someone is editing the spreadsheet, otherwise it returns.
Let's say it's a proposal, you'll tell me if it meets your requirements ;-)
function onTimer() { // this function has a timer trigger set to 1 minute
var ss = SpreadsheetApp.openById('0AnqSFd3iikE3dG90MzRwX0FQUnoxTWZjcmtLSlVuT3c')
var sh = ss.getSheets()[0]
var logsheet = ss.getSheets()[1]
var formerUser = ScriptProperties.getProperty('lastUser')
if(formerUser=='nobody'){return}
ss.toast('The sheet is being edited by '+Session.getActiveUser());
ScriptProperties.setProperties({'lastUser': 'nobody'}, true);
logsheet.getRange(logsheet.getLastRow()+1, 1).setValue('onTimer function was running on '+
Utilities.formatDate(new Date(),'GMT+2','HH:mm'))
}
function onUserPresent(){ // this one has an onEdit installable trigger
ScriptProperties.setProperties({'lastUser': 'someone'}, true);
}