Interesting use case:
1. Script 1 with ScriptApp trigger management associated as an image link in a Google Site
2. Created a new instance of the script under a new account and update the image link
3. Deleted the container script 1 within the Google Site
4. A user visited the Google Site to invoke the script, but the page was cached pointing to the previous script 1.
5. The on-error trap emails are being emailed to me every time the "deleted" script runs.
How do I delete or stop these triggers?
If you know the user that installed the trigger you could ask them to do to the "All my triggers" menu item in the script editor, find the trigger and delete it.
In the on-error email, there is a link to manage triggers. Make sure that the triggers are really gone. I had this issue with a set of shared spreadsheets, where I thought I had removed all the triggers, but my partner still had some enabled.
In the Script Editor, You can also check for a project's triggers programmatically, then work with that trigger and it's source:
// Get triggers
var triggers = ScriptApp.getProjectTriggers();
// Loop through each trigger
triggers.forEach(function(trigger) {
// Get the id
var id = trigger.getTriggerSourceId();
// You can then use that id to get the related form or a sheet. E.g. :
var ss = SpreadSheetApp.openById(id);
// You can also work with the trigger (i.e. delete it)
ScriptApp.deleteTrigger(trigger);
});
See https://developers.google.com/apps-script/reference/script/script-app for more
Related
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
}
}
I have wrote a Apps Script for my Google Sheet.
I activate some triggers to schedule some functions.
I add a bad trigger and I want to delete IT, I clicked on ALL Triggers page :
https://script.google.com/home/triggers
and inadvertently I have cliked on the name of project on the list of triggers.
Then I have clicked on the trash sure to delete the trigger but It delete my Project !!!
Possible that the trash page is empty and I have lost all my project with a click ?
https://script.google.com/home/trash
When deleting a project you get an alert adverting you of it.
As mentioned on it, if you have deleted the file, is gone forever.
Is there a way to get (and change/remove) all Triggers from all documents in Google Script, as if I opened Script Editor -> Edit -> All your triggers ?
Update:
I added a few test triggers and tried to loop all the spreadsheet files as it is said by Pierre-Marie Richard:
function getAllSpreadsheetTriggers()
{
var files = DriveApp.getFilesByType('application/vnd.google-apps.spreadsheet'),
spreadsheets = [],
triggers = [];
while(files.hasNext())
spreadsheets.push( SpreadsheetApp.openById(files.next().getId()) );
for (var i = 0; i < spreadsheets.length; i++)
{
triggers = ScriptApp.getUserTriggers( spreadsheets[i] );
Logger.log(triggers);
}
}
But .getUserTriggers() always return an empty array. I read this issue, the last answer is "We decided not to take action on this issue. Triggers always belong to a particular script and are not accessible to other scripts. The documentation has been clarified to make this clear."
It turns out that can't it be done?
You can get the trigger from your docs/forms/spreadsheets with the getUserTriggers(document), getUserTriggers(forms) and getUserTriggers(spreadsheet) methods, but it will return only the trigger for the specify file. So you'll need to loop on all the files if you want to modify the triggers from all your Drive's file.
Also, you can't modify trigger by code, but you can delete a trigger (deleteTrigger(Trigger) method) and create a new one (see TriggerBuilder class).
Edit:
As FLighter point it, you can't get the triggers from another script that the one you're running. I should have read the documentation with more attention:
Gets all installable triggers owned by this user in the given
document, for this script or add-on only. This method cannot be used
to see the triggers attached to other scripts.
So, to anwser the original question, no, you can't. You can made some code for each script you've got, but it will require to be trigger manually.
Just so you are aware, in addition to Pierre-Marie Richard's response, you can only delete the triggers you created on a document, you won't be able to delete the triggers created by other users. Any user with edit access can create a trigger on a document but that trigger can only be manipulated by that user.
I installed a form submit trigger for my project using ScriptApp around the beginning of May. The trigger has worked just fine however I now wish to uninstall the trigger and am running into problems. When I try to view all my current project triggers (Resources > Current project triggers), it returns that there are no associated triggers. Also when I try to run (Resources > All your triggers) it returns that there are no triggers shown.
I'd like to believe that this is the case, that the trigger in question has been somehow deleted but I don't believe that it is. To make sure the trigger didn't run, I de-authorized the script to run from my google account settings.
My suspicions that the trigger was not deleted were confirmed when I received a "Summary of failures for Google Apps Script: Form Processing Script" which told me my script had failed 3 times because, "Authorization is required to perform that action."
These failure e-mails also contain a statement, "To configure the triggers for this script, or change your setting for receiving future failure notifications, click here." When I click on the link, there are no triggers shown...
Here's a look at the code i used to install the trigger:
function formSubmitTriggerInstall() {
var formID = '1rOikLDUAqMWCB0ktjWzFE0oB6LmOHvXuzPAqyq0XLwE';
ScriptApp.newTrigger('processForm')
.forForm(formID)
.onFormSubmit()
.create();
}
I have also tried to locate the trigger using ScriptApp but to no avail.
Does anyone have any suggestions on how I can eliminate this trigger or get the associated trigger ID?
One other note, since I installed the trigger, the google developer's website and documentation went through a major face lift and some of the page content appears to be updated as well. Not sure that would affect my triggers though.
It was confirmed that this was a big and it was fixed by the apps script team.
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);
}