7

I've written a script that does various things, one part of this script, is installing a trigger:

function setTrigger() { 
var ss = SpreadsheetApp.getActive();
var triggers = ScriptApp.getProjectTriggers();
Logger.log('Amount of triggers ' +triggers.length);


var j = 0;
for (var i = 0 ; i < triggers.length;i++){

if(triggers[i].getHandlerFunction() == 'getNotes' ){j++;}

}

Logger.log('Amount of matching triggers ' +j);

if(j == 0 ){ScriptApp.newTrigger("getNotes").forSpreadsheet(ss).onFormSubmit().create();} 
}

Here is the problem I'm having.

The above code is called in the onOpen() trigger. When I open the sheet, and check logs, my trigger isn't installed and I get the following message.

Execution failed: You do not have permission to call getProjectTriggers

When I run the onOpen() manually. The trigger is installed.

I currently own the spreadsheet, but ideally, i'd like to share it with people and the trigger installs and works.

Any ideas how to fix this error with getting project triggers called in onOpen?

Kos
  • 4,890
  • 9
  • 38
  • 42
Munkey
  • 958
  • 11
  • 28
  • When you say "The above code is called in the onOpen() trigger", do you mean a function called "onOpen" or a function that you installed a trigger for and that runs on open ? please have a look at this doc : https://developers.google.com/apps-script/understanding_triggers?hl=fr-FR#Simple – Serge insas Jan 19 '14 at 17:24
  • @Sergeinsas Thanks for the reply and the link. I've used some of the info in this link to build my script. I mean I've made a function called onOpen() at the top of my script as per that link instructions. It builds a menu, then checks for the trigger, if it's not found it should install it. Here is the onOpen() code, I guess I should have included it in the first place. http://jsfiddle.net/8gU9m/ – Munkey Jan 19 '14 at 18:37

1 Answers1

9

Following your comment :

Change the name of your function to anything else and create an installable trigger that runs this function on SS open, as mentioned in the doc, simple triggers can't do anything that requires authorization but installable ones do.

enter image description here

enter image description here


Edit : complete example with your code

After saving this in a spreadsheet and setting manually a trigger on open with the specialonOpen function (and accepting the authorization request), I refreshed the browser and get it working with your menu and the new trigger as well (see illustration below -in french because I used another gmail account with old spreadsheet version, my english one has new version and onFormSubmit doesn't work in new versions)

function specialonOpen() {
  var ss = SpreadsheetApp.getActive();

  var items = [
    {name: 'Refresh TOL Notes', functionName: 'getNotes'},
    null, // Results in a line separator.
    {name: 'Coming Soon!', functionName: 'menuItem2'}
  ];
  ss.addMenu('TOL Toolkit', items);  
  var sheet = ss.getSheetByName('New Notes');
  if (sheet == null) {var ss = SpreadsheetApp.getActive();
                      ss.insertSheet('New Notes',0 );

                      var sheet = ss.getSheetByName('New Notes');
                      sheet.deleteColumns(3, 18);
                      sheet.deleteRows(12, 88 );
                      sheet.getRange('a1').setValue('Agent Name');
                      sheet.getRange('b1').setValue('Tol Notes');
                      getNotes();

                      sheet.setColumnWidth(1, 120);
                      sheet.setColumnWidth(2, 400);
                      setTrigger()              }


  getNotes();        
  setTrigger()
}


function setTrigger() {
  var ss = SpreadsheetApp.getActive();
  var triggers = ScriptApp.getProjectTriggers();
  Logger.log('Amount of triggers ' + triggers.length);
  var j = 0;
  for (var i = 0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == 'getNotes') {
      j++;
    } 
  }
    Logger.log('Amount of matching triggers ' + j);
  if (j == 0) {
    ScriptApp.newTrigger("getNotes").forSpreadsheet(ss).onFormSubmit().create();
  }
}


function getNotes() {
  var s = SpreadsheetApp.getActive();
  var sheet1 = s.getSheetByName('New Notes');
  if (sheet1 == null) {
    var s = SpreadsheetApp.getActive();
    s.insertSheet('New Notes', 0);
    var sheet1 = s.getSheetByName('New Notes');
    sheet1.deleteColumns(3, 18);
    sheet1.deleteRows(12, 88);
    sheet1.getRange('a1').setValue('Agent Name');
    sheet1.getRange('b1').setValue('Tol Notes');    
    sheet1.setColumnWidth(1, 120);
    sheet1.setColumnWidth(2, 400);   
  }
}

enter image description here

enter image description here


EDIT 2 : a solution with a Browser message to suggest install from a menu.

function onOpen() {
  var ss = SpreadsheetApp.getActive();

  var items = [
    {name: 'Install this script', functionName: 'setTriggers'},
  ];
    ss.addMenu('Custom Menu', items);  
    Browser.msgBox('please run INSTALL from the custom menu');
    }
Serge insas
  • 45,904
  • 7
  • 105
  • 131
  • @Sergeinas Thanks for the reply. So if I'm understanding correctly. Should I rename the onOpen() to something else entirely. Then manually install the triggers via the trigger menu in script editor. So there is no way to install the trigger via script? As it will require authorization (sorry if I'm being dumb here. But this is all new to me) – Munkey Jan 19 '14 at 20:03
  • No, the script can create triggers, What I was talking about is only the opOpen that will launch your onOpen function (actually it should have another name as I explained). Tell me if it is not clear. – Serge insas Jan 19 '14 at 20:21
  • Hey, I'm really sorry, but it's not 100% clear :$ If you wanted to give up, I don't blame you. I've altered my code and split the functions up. http://jsfiddle.net/33xRG/ As I've changed onOpen() to onMyOpen(), this will not load menu unless I set it up manually. setTrigger() does work when manually run, but not at opening of sheet. What I was hoping to do, perhaps it's not possible, on load of sheet: Menu is created. getNotes() run and then check if trigger is there on form submit. While I'm owner of the sheets, about 5 people use them & I was hoping to save them all time with this. – Munkey Jan 19 '14 at 20:39
  • I guess I haven't been clear enough... sorry about that. Ill edit my answer with an example, I guess that will help you more than extra long comments... give me a few minutes. – Serge insas Jan 19 '14 at 20:51
  • @Sergeinas I really appreciate it, I owe you a beer! I dont understand why it setTrigger won't work on onOpen. Yet fine when I manually run it. And the script already has authority to run, as I'd done that :s. PS you probably have been clear enough, I'm just the right amount of dumb I guess. But I am trying and making progress :) – Munkey Jan 19 '14 at 20:53
  • As for the beer I guess it might be uneasy... how far are you from Belgium ? ("the" beer country btw ;-) – Serge insas Jan 19 '14 at 21:07
  • I was in Belgium last year, in Stavelot, for the F1. Was drinking Jupiter all day long :) I'm in London UK, and currently a rising star in the google sheets forum. Javascript is new to me, steep learning curve, only started as Google sheets is limited in functions without it. Just going to read through your handy work. Merci/danke thank you! – Munkey Jan 19 '14 at 21:10
  • You're welcome, de rien... if you're happy with the answer please consider accepting it. (never been in Stavelot but I've been in London quite a few times... go figure why !? wonderful city:) – Serge insas Jan 19 '14 at 21:20
  • @Sergeinas all works as you describe, thank you. But we are still having to add a trigger manually, I'm guessing there is no getting away from that? As that is what my setTrigger() was for. At least your trigger is persistent, previously if it was deleted it wouldn't reappear unless you ran onOpen manually. :) thanks again for your time and help. – Munkey Jan 19 '14 at 21:28
  • You could avoid that by creating a popup (Browser.MsgBox) that suggests the user to run a function in a menu that creates the triggers. In this case the simple onOpen does nothing else than showing a suggestion, the user runs the trigger function and grant access to the script from the menu. see second edit – Serge insas Jan 19 '14 at 21:51
  • Ideally, I want to keep users (except supervisors) away from the spreadsheet. They all have edit rights, but the form they fill out is embedded in a google site. The 'New Notes' Sheet in is the same page too. It's easier, given the conditions, to do a one time setup for all users. I was just trying to automate it a bit, and reinstall triggers if they get deleted somehow. Thanks for all the input :) it's appreciated. – Munkey Jan 19 '14 at 21:58
  • @Sergeinas - a really helpful answer and it works! Ideally it would be great if we could shorten some of the steps like clicking on the menu etc so that only the permissions pop-up appeared...I'll just have to create some idiot-proof instructions to walk the users through the process ! – user2677034 Feb 15 '17 at 23:08