Search code examples
google-apps-scriptgoogle-docs-api

Google Apps Scripts - Optimal way to replace text


I have tons of strings that I need to replace in a Google document. My performance to run my script is taking a huge hit and takes forever to run now. I am looking at how to optimize.

body.replaceText("oldvalue1",newValue1)
body.replaceText("oldvalue2",newValue2)
body.replaceText("oldvalue3",newValue3)
..
..
..

Is there a more optimal way to replace text in a Google Doc using google scripts?


Solution

  • As @Kos refers in the comments, the best approximation is using Google Docs API batchUpdates as Advanced Service inside Google Apps Script.

    I leave you an example on how Docs API works as an Advanced Service. For the example I suppose you have an array of objects that contains the oldValue and newValue:

    function batchUpdating(DocID = DocID) {
      const replaceRules = [
        {
          toReplace: "oldValue1",
          newValue: "newValue1"
        },
    ...
      ]
      const requestBuild = replaceRules.map(rule => {
        var replaceAllTextRequest = Docs.newReplaceAllTextRequest()
        replaceAllTextRequest.replaceText = rule.newValue
        replaceAllTextRequest.containsText = Docs.newSubstringMatchCriteria()
        replaceAllTextRequest.containsText.text = rule.toReplace
        replaceAllTextRequest.containsText.matchCase = false
        Logger.log(replaceAllTextRequest)
        var request = Docs.newRequest()
        request.replaceAllText = replaceAllTextRequest
        return request
      })
      var batchUpdateRequest = Docs.newBatchUpdateDocumentRequest()
      batchUpdateRequest.requests = requestBuild
      var result = Docs.Documents.batchUpdate(batchUpdateRequest, DocID)
      Logger.log(result)
    }
    

    Google Apps Script helps us handle the authorization flow, and gives us hints on how to construct our request. For example, Docs.newReplaceAllTextRequest(), helps us build the request for that service, giving us hints that it contains replaceText and containText. In any case, we could also supply the object directly to the request:

    const requestBuild = replaceRules.map(rule => {
        return {
          replaceAllText:
          {
            replaceText: rule.newValue,
            containsText: { text: rule.oldValue, matchCase: false }
          }
        }
    })
    
    To take in account

    Each request is validated before being applied. If any request is not valid, then the entire request will fail and nothing will be applied.

    If your script project uses a default GCP project created on or after April 8, 2019, the API is enabled automatically after you enable the advanced service and save the script project. If you have not done so already, you may also be asked to agree to the Google Cloud Platform and Google APIs Terms of Service as well.

    Documentation: