2

I am using the Google Sheets API to create a spreadsheet. I want to add an onEdit function to this sheet that calls out and does an ajax request.

  1. Using either the app script api or the spreadsheet API I want to create the onEdit function, something like:
// Following comment ensures UrlFetchApp authorization will be prompted:
// UrlFetchApp.fetch()

function onEdit(e) {
  var range = e.range
  var currentSheet = range.getSheet()
  var sheetId = currentSheet.getParent().getId(); 
  var url = 'https://example.com/synchronise?sheetId=' + sheetId;
  var response = JSON.parse(UrlFetchApp.fetch(url).getContentText());
}

and I want to attach that to the sheet I am creating with the API. My app uses Google OAuth so I am hoping I can also deal with the permissions required to make external calls as part of the OAuth authentication process (but happy if when the user opens the sheet it asks them then which I suspect might be the case?)

So my question is what is the appraoch to

a) create a script and attach it to a sheet b) programmatically (or via API) get the user to accept permissions for the script to call out?

What I want to replicate is going to a sheet, clicking tools->script editor and pasting in the function but do that with an API

amlwwalker
  • 3,161
  • 4
  • 26
  • 47
  • There is a 30 second maximum execution time for onEdit trigger functions. So don't plan on this handling many users at one time. And I'm thinking you might want to consider the use of LockService. – Cooper Jan 08 '21 at 17:47

1 Answers1

1

You can use Apps Script API to add container-bound script.

What to do:

  1. Create a container-bound script using projecs.create method.

To set a container-bound script, you need to assign the spreadsheet file id to the parentId parameter

Sample Request Body:

{
  "title": "new",
  "parentId": "spreadsheet file id"
}
  1. Get the newly created container-bound script id in the project response body of projecs.create method.

Sample Response Body:

{
  "scriptId": "newly created script id",
  "title": "new",
  "parentId": "spreadsheet file id",
  "createTime": "2020-12-25T23:33:48.026Z",
  "updateTime": "2020-12-25T23:33:48.026Z"
}
  1. Update the content of the newly created bound script using projects.updateContent method and include your function.

Sample Request Body:

{
  files: [{
      name: 'hello',
      type: 'SERVER_JS',
      source: 'function helloWorld() {\n  console.log("Hello, world!");\n}'
    }, {
      name: 'appsscript',
      type: 'JSON',
      source: "{\"timeZone\":\"America/New_York\",\"" +
      "exceptionLogging\":\"CLOUD\"}"
    }]
}
Ron M
  • 5,791
  • 1
  • 4
  • 16
  • Thats very cool. Thank you. I'm going to give this a go shortly! Only question is - how do permissions work here? Using the App Script API is a simple OAuth permission, but if the script itself needs permission from the spreadsheet owner does that have to be manually accepted in the Sheet or does oAuth permissions cover that? – amlwwalker Jan 11 '21 at 10:40
  • Are you using a service account in creating your spreadsheet? when I tried this one, I used the same account in creating the standalone script, generating spreadsheet using api and copying the script to the newly created spreadsheet – Ron M Jan 11 '21 at 14:43
  • I also tried this just recently, I shared the script owned by user 1 to user 2 using **Share with people and groups** option, and I was able to get the content of the script using user 2 account. So as long as the user account to be used in generating spreadsheets has access to the main script to be copied, there should be no problem. – Ron M Jan 11 '21 at 14:59
  • 1
    Interesting. I'll try to make sure I can access the script from a second user before going for implementation. Incidentally, looking here at the docs https://developers.google.com/apps-script/api/quickstart/js in the example after the line `gapi.client.script.projects.updateContent ` it looks like they are updating the files array with script content - you mention this isn't possible. Have I read it wrong, has the API changed, or something else? It would obviously be easiest if the script could be created on the fly... – amlwwalker Jan 11 '21 at 15:49
  • oh thank you for this!, I missed this spot. Good catch, yes you may use the source parameter to input your function – Ron M Jan 11 '21 at 15:51
  • that is awesome - so in interms of your anwe, it would now be something like: 1. create a project on the user's account 2. update the project content with the script content AND the spreadsheet ID (in one go?) that should attach the script? And do you know if they then have to manually accept the permissions that the script will require - in my example I believe UrlFetchApp.fetch requires permissions but not sure if that would be covered by oAuth anyway? – amlwwalker Jan 11 '21 at 15:54
  • create a project on the user's account 2. update the project content with the script content AND the spreadsheet ID (in one go?) that should attach the script? [**Yes, correct**] I believe UrlFetchApp.fetch requires permissions but not sure if that would be covered by oAuth anyway? [**Since you are planning to add an onEdit() you need to add it as an installable trigger, you can add installable trigger programmatically as well just search it here in SO**] – Ron M Jan 11 '21 at 15:55
  • Seems that it would require https://www.googleapis.com/auth/script.external_request" - I actually struggled to get this to be accepted manually, so not sure how that works when using the API – amlwwalker Jan 11 '21 at 15:55
  • I did not get your last question sorry – Ron M Jan 11 '21 at 16:11
  • 1
    I'll come back to it once I begin implementing this the permissions on triggers calling externally may be something I discover the answer to when the time comes. Thanks for your help – amlwwalker Jan 11 '21 at 16:26
  • no problem, thank you for raising the updateContent as well. I learned something new – Ron M Jan 11 '21 at 16:28