Pseudo OnEdit Trigger for Google Document using Google Apps Script

Gists

This is a sample script for achieving the pseudo OnEdit trigger for Google Document using Google Apps Script.

In the current stage, there is not OnEdit trigger for Google Document. Ref But I sometimes have the case that I want to use OnEdit trigger. So, as the current workaround, I created this sample script. I think that this workaround can be also used for Google Slides, Google Form and also Google Spreadsheet. In the case of Spreadsheet, what the existing OnEdit trigger and the time-driven trigger cannot do can be achieved.

The flow of this workaround is as follows.

  1. Open a sidebar.
    • This workaround uses Javascript. So the sidebar is used.
  2. Run Javascript every 1 second, and check the change of document body.
    • This cycle can be adjusted for your situation.
  3. When the document body is changed, the script of Google Apps Script is run.

By this flow, the pseudo OnEdit trigger can be achieved.

Usage.

1. Sample script.

Google Apps Script side: Code.gs

Please copy and paste the following script to the script editor of Document as a script.

// Please run this function.
function openSidebar() {
  DocumentApp.getUi().showSidebar(
    HtmlService.createHtmlOutputFromFile("index").setTitle("Sample")
  );
}

function main() {
  //
  // do something
  //
  // Here, as a sample script, the background color of text of "sample" is changed.
  // This is a simple sample script for explaining this workaround. So please change this for your actual situation.
  //

  const search = "sample";
  const color = "#5DF957";
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();
  let s = body.findText(search);
  if (!s) return "Search value was not found.";
  let n = 0;
  while (s) {
    const res = s.getElement().asText();
    const offset = [s.getStartOffset(), s.getEndOffsetInclusive()];
    if (res.getBackgroundColor(offset[0]) != color) {
      res.setBackgroundColor(...offset, color);
      n++;
    }
    s = body.findText(search, s);
  }
  return n == 0 ? "New value was not found." : "Done.";
}

HTML and Javascript side: index.html

Please copy and paste the following script to the script editor of the Document as HTML.

<input type="button" onclick="start()" id="b1" value="start" />
<input type="button" onclick="stop()" id="b2" value="stop" disabled />
<script>
  let run;
  const runGoogleScript = (_) =>
    new Promise((resolve, reject) =>
      google.script.run
        .withFailureHandler(reject)
        .withSuccessHandler(resolve)
        .main()
    );
  const main = (_) =>
    new Promise((resolve, reject) =>
      setTimeout(
        async () => await runGoogleScript().then(resolve).catch(reject),
        1000
      )
    );

  const start = async () => {
    const b1 = document.getElementById("b1");
    const b2 = document.getElementById("b2");
    b1.disabled = true;
    b2.disabled = false;
    run = true;
    console.log("Start.");
    while (run) console.log(await main());
    console.log("End.");
    b1.disabled = false;
    b2.disabled = true;
  };

  const stop = (_) => (run = false);
</script>

2. Testing.

When you run openSidebar, a sidebar is opened on Google Document. And, when you click “start” button, the script is run.

In this sample script, the background color of text of “sample” is changed. This is a simple sample script for explaining this workaround. So please change this for your actual situation.

References

 Share!