0

I must be having a misunderstanding as to how this method works. I am trying to create an add-on that copies a large number of templates then fill placeholders in the templates. There are about 6 fields it must replace for each template but this may increase depending on the office's needs. It works on a small number of templates but if I try to apply the data to 20 or so copied templates, I get timed out with the error.

"Exception: Service invoked too many times in a short time: urlfetch. Try Utilities.sleep(1000) between calls."

My goal is to scale this up to be able to handle 200-300 templates. I was under the impression that using fetchAll on an array of requests would count as a single request. Is this wrong? I can certainly add a timer but if it triggers with multiple requests, I worry I will time out on Google's script runtime quota.

function copyTemplates(copiedTemplateIds, destinationFolderId) {
  let copyRequests = []
  copiedTemplateIds.forEach(id => {
    let title = getTitle(enteredInfo.name, DriveApp.getFileById(id).getName())
    copyRequests.push({
      "url": `https://www.googleapis.com/drive/v3/files/${id}/copy`,
      "method": "POST",
      "headers": {
        "Authorization": "Bearer " + token
      },
      "payload": `{"parents":"${destinationFolderId}","name":"${title}"}`,
      "contentType": "application/json",
    })
  })

  let responses = UrlFetchApp.fetchAll(copyRequests);
  responses.forEach(response => {
    copiedTemplateIds.push(JSON.parse(response.getContentText()).id)
  });

  return copiedTemplateIds;
}

function replaceText(copiedTemplateIds) {
  let fillRequests = []
  copiedTemplateIds.forEach(id => {
    for (let [field, data] of Object.entries(enteredInfo)) {
      let fill = "<<" + field + ">>"
      fillRequests.push({
        "url": `https://docs.googleapis.com/v1/documents/${id}:batchUpdate`,
        "method": "POST",
        "headers": {
          "Authorization": "Bearer " + token
        },
        "payload": `{"requests":[{"replaceAllText":{"replaceText":"${data}","containsText":{"text":"${fill}","matchCase":false}}}]}`,
        "contentType": "application/json",
      })
    }
  })
  let responses = UrlFetchApp.fetchAll(fillRequests);

  console.log(responses.toString())
}

Here is the code for building and sending the requests. I thought this would result in 2 total requests. It seems as though, if I'm timing out, each request in the fetchAll counts as an individual request? If that's the case, what's the advantage of fetchAll vs fetch? I feel like I'm missing something here and would appreciate any insight.

jip101
  • 13
  • 3
  • I don't see where you are getting the Oauth token – Cooper Feb 24 '23 at 17:19
  • What do you plan to do with all the files that you are creating? – Cooper Feb 24 '23 at 17:23
  • @Cooper The auth token is created from "let token = ScriptApp.getOAuthToken()." It's created in global scope to be used. I forgot to include it, sorry. – jip101 Feb 24 '23 at 17:31
  • @Cooper The copies of templates have placeholders that are filled with input the user specifies. For now, it's from a card with multiple text fields. In the future, it will be from a spreadsheet, to create a sort of "mail merge" functionality which may have up to a few hundred rows of people. – jip101 Feb 24 '23 at 17:48
  • Did you try putting the 1 second delay in the two forEach loops? You need to insure the loops don't occur less than about 240 ms. Putting the ScriptApp.getOauthToken() function in the loop might actually help. – Cooper Feb 24 '23 at 20:20
  • How do users provide the input data? – Cooper Feb 24 '23 at 20:27
  • @Cooper Through text inputs built in cardbuilder. The information gets populated correctly. It just takes too long and times out. I'm trying to modify the code to utilize batchupdate but it doesn't seem like such functionality exists for Drive like it does for Docs. – jip101 Feb 24 '23 at 20:41
  • Hey @jip101, you can review this answer by Tanaike. He is doing a batchUpdate using Google Drive. [Here](https://stackoverflow.com/a/48310991/17390145) – Giselle Valladares Feb 27 '23 at 17:04

0 Answers0