How to Create a Google Doc Add-On: A Hello World Tutorial

Frank Vahid
Prof. of Computer Science and Engineering, Univ. of California, Riverside
zyBooks co-founder
vahid@cs.ucr.edu http://www.cs.ucr.edu/~vahid

Google Docs Add-Ons

Google docs (gdocs) are becoming ubiquitous. Add-ons extend gdoc functionality, such as automatically inserting special text, doing translations, or adding bibliographies. Numerous existing add-ons are available from within a gdoc. In a gdoc, clicking "Add-ons -- Get add-ons" takes you to a store where you can browse and select add-ons. Most add-ons are free.

alt_text

Programmers can create their own add-ons. Such add-ons can be especially useful within a organization, to automated specific things that organization does with their gdocs. I found the existing getting-started tutorials hard to follow, so wrote this tutorial. The tutorial goes through a series of successfully more-powerful "Hello World" programs for gdoc add-ons. I hope you find it useful.

A first "Hello world" add-on: HTML in a sidebar

1. Create a gdoc named "My Hello World Document" (any name will do).

2. Select "Tools -- script editor".

alt_text

That will open a new browser tab having an editor where you can write your add-on's code.

alt_text

3. Replace any code in Code.gs by copy-pasting the following code. We'll explain later.

    function onOpen(e) {
      DocumentApp.getUi().createAddonMenu()
          .addItem('Start', 'showSidebar')
          .addToUi();
      showSidebar()
    }

    function onInstall(e) {
      onOpen(e);
    }

    function showSidebar() {
      var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
          .setTitle('Hello World gdoc add-on')
          .setSandboxMode(HtmlService.SandboxMode.IFRAME);
      DocumentApp.getUi().showSidebar(ui);
    }

4. Select "File -- New -- Html file". Name the file "Sidebar". Replace any code in Sidebar.html by the following, and then Select "File -- Save all".

    <!DOCTYPE html>
    <html>
    <body>

    <p> Hello world (in html)</p> 

    </body>
    </html>

5. Name the add-on by replacing "Untitled project" by "Hello world".

6. Go back to the "Hello world add-on example" gdoc and reload the page. Click "Add-ons -- Hello world -- Start". Answer any popups by authorizing the script to run. You should then see a sidebar appear on the right with the "Hello world (in html)" text.

alt_text

Explanation: What you did above was create two items.

Extending the Hello Word add-on's html with Javascript functions

Merely displaying html in a sidebar has limited usefulness. That html can be made more useful by adding some actions using Javascript. Here, we extend the example to include buttons that generate text.

1. In the "Hello world add-on example" gdoc, re-open your script by selecting "Tools -- Script editor". In the newly-opened tab, click on "Sidebar.html". Update the html to include an HTML button as shown below. "alert" is a built-in javascript function.

    <!DOCTYPE html>
    <html>
    <body>

        <p> Hello world (in html)</p> 

        <p> <button type="button" onclick="alert('Hello world! (as javascript alert)')">Go1</button> </p> 

    </body>
    </html>

2. Select "File -- Save all". Go back to your doc, reload the page, and select "Add-ons -- Hello word -- Start". Notice that the sidebar now has a button named "Go1". Press the button and notice the popup that appears.

alt_text

Instead of a popup, you could create a textarea in the html, and create a custom javascript function to update the text in that box. We'll now assume you know how to open your add-on script, edit the html, save, reload your gdoc, and run your add-on.

1. Update your add-on's html to the following.

    <!DOCTYPE html>
    <html>

    <head>
    <script>
        function HelloWorldJavascript() {
            document.getElementById("text-display").innerHTML = "Hello World! (in javascript textarea)";
        }
    </script>
    </head>

    <body>

        <p> Hello world (in html)</p> 

        <p> <button type="button" onclick="alert('Hello world! (as javascript alert)')">Go1</button> </p> 

        <p> <button type="button" onclick="HelloWorldJavascript()">Go2</button> <br /> <br />
        <textarea id="text-display" rows="4" cols="40">(Text output will appear here)</textarea> </p> 

    </body>
    </html>

2. Run the add-on, and press the sidebar's Go2 button. Notice that the sidebar's textarea updates with a hello world message.

alt_text alt_text

Server-side scripts: Interacting with the gdoc's contents

Many add-ons don't just behave as an html page in a sidebar, but interact with the gdoc's contents. To do that, the html needs to call javascript functions that run on google's server, known as Google Apps Script. We create such functions in the Code.gs file, and call those from the html using google.script.run as below.

1. Update your html and Code.gs files as follows. Don't forget to click "File -- Save all" when done.

Sidebar.html:

    <!DOCTYPE html>
    <html>

    <head>
    <script>
        function HelloWorldJavascript() {
            document.getElementById("text-display").innerHTML = "Hello World! (in javascript textarea)";
        }
    </script>
    </head>

    <body>

        <p> Hello world (in html)</p> 

        <p> <button type="button" onclick="alert('Hello world! (as javascript alert)')">Go1</button> </p> 

        <p> <button type="button" onclick="HelloWorldJavascript()">Go2</button> <br /> <br />
        <textarea id="text-display" rows="4" cols="40">(Text output will appear here)</textarea> </p> 

        <p> <button type="button" onclick="google.script.run.HelloWorldServerscriptAlert()">Go3</button> </p> 

        <p> <button type="button" onclick="google.script.run.HelloWorldServerscriptInsert()">Go4</button> </p> 

    </body>
    </html>

Code.gs:

    function onOpen(e) {
      DocumentApp.getUi().createAddonMenu()
          .addItem('Start', 'showSidebar')
          .addToUi();
      showSidebar()
    }

    function onInstall(e) {
      onOpen(e);
    }

    function showSidebar() {
      var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
          .setTitle('Hello World gdoc add-on')
          .setSandboxMode(HtmlService.SandboxMode.IFRAME);
      DocumentApp.getUi().showSidebar(ui);
    }

    function HelloWorldServerscriptAlert() {
      var ui = DocumentApp.getUi();
      ui.alert("Hello world! (server-side script alert)");
    }

    function HelloWorldServerscriptInsert() {
      var cursor = DocumentApp.getActiveDocument().getCursor();
      cursor.insertText("Hello World! (inserted into document)");
    }

2. Run your add-on, and click button Go3. That button calls the server-side javascript function HelloWorldServerscriptAlert(), which calls an alert function that yields a popup. Notice this popup looks a little different than the popup generated earlier by the html's javascript.

alt_text

Our HelloWorldServerscriptAlert() function's statements are:

    var ui = DocumentApp.getUi();
    ui.alert("Hello world! (server-side script alert)");

The first statement get the user interface associated with the gdoc. The second statement calls the alert function associated with that ui. The ui only supports a few functions, described here: https://developers.google.com/apps-script/reference/base/ui.

3. Now for the best part: Click button Go4. That button calls the server-side javascript function HelloWorldServerscriptInsert(), which actually inserts text into the gdoc!

alt_text

Our HelloWorldServerscriptInsert() function's statements are:

    var cursor = DocumentApp.getActiveDocument().getCursor();
    cursor.insertText("Hello World! (inserted into document)");

The first statement gets the gdoc's cursor. The second statement inserts text at the cursor.

You can now imagine creating an add-on that inserts commonly-typed text blocks automatically, with each block having its own button and own server-side function (or maybe just one server side function that gets passed the text as an argument).

Going a bit beyond hello world

You probably want to get text from the gdoc, in addition to writing text to the gdoc as above. Below is an example that gets all the text from a gdoc, and replaces the word "Voldemort" by "He who must not be named".

Sidebar.html:

    <!DOCTYPE html>
    <html>
    <body>

        <p> <button type="button" onclick="google.script.run.HandleBannedWords()">Handle banned words</button> </p> 

    </body>
    </html>

Code.gs:

    function onOpen(e) {
      DocumentApp.getUi().createAddonMenu()
          .addItem('Start', 'showSidebar')
          .addToUi();
      showSidebar()
    }

    function onInstall(e) {
      onOpen(e);
    }

    function showSidebar() {
      var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
          .setTitle('Hello World gdoc add-on')
          .setSandboxMode(HtmlService.SandboxMode.IFRAME);
      DocumentApp.getUi().showSidebar(ui);
    }

    function HandleBannedWords() {
      var body = DocumentApp.getActiveDocument().getBody();
      var bodyText = body.editAsText();

      bodyText.replaceText("Voldemort", "He who must not be named");

      DocumentApp.getUi().alert("Banned word handling complete.");
    }

alt_text alt_text alt_text

Our function HandleBannedWords() had the following statements:

      var body = DocumentApp.getActiveDocument().getBody();
      var bodyText = body.editAsText();

      bodyText.replaceText("Voldemort", "He who must not be named");

      DocumentApp.getUi().alert("Banned word handling complete.");

The first statement gets the body of the current gdoc. The body class has many functions for accessing and modifying the gdoc. The second statement calls one such function that gets the entire body as text (thus ignoring figures and other items). The third statement calls a function to replace a word in that text. The last statement just generates an alert.

More functions exist for working with a gdoc's body text: https://developers.google.com/apps-script/reference/document/text

Summary

Our gdoc add-on consisted of:

Google provides numerous server-side functions for working with a gdoc's body. You might start here: https://developers.google.com/apps-script/reference/document/body

Note that you can work with other gdocs other than just the active gdoc (assuming you have access).You can even create new gdocs. See: https://developers.google.com/apps-script/reference/document/document-app

Tips:

Have fun!