I hope you’re not feeling too intimidated and have been able to create and load the “Hello World” sample

This post takes a closer look at the JavaScript part of the sample. The discussion is in two parts: First, how JavaScript is linked into the HTML page; then, the JavaScript code with the main focus on the Office JS API.

For your reference, here’s the final version of the HTML page. Note that this is HTML5 and that the declaration <!DOCTYPE html> is required at the top of the page.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
        <link rel="stylesheet" type="text/css" href="program.css" />
        <script src="https://appsforoffice.microsoft.com/lib/1/office.js">
        <script src="Program.js">
    </head>
    <body>
        <button onclick="writeData()"> Write Data 
<button onclick="ReadData()"> Read Selected Data
Results: <div id="results">
</body> </html>

Also important is the second line of meta data: . This will ensure that the Add-in’s browser control uses the newest version of Internet Explorer available on the machine. For more information see this article on MSDN.

The lines starting with script load the JavaScript libraries used in the Add-in. You might be surprised to see two libraries listed. Program.js is expected – this is the file name you were instructed to give the sample. (There’s no path information because the html and js files are stored in the same folder.) The other entry – office.js – contains the Office APIs: this is the equivalent in VBA of setting a reference to a type library, such as msword.olb, in order to work with its object model using early binding.

Your code might use additional libraries, such as Angular.js or Node.js. In this case, you’d reference them, as well. When referencing libraries you have the choice of providing an outside link, as in the case of office.js in the sample or providing a copy of the library in your project’s folder. If you link to the outside library you can be sure of always accessing the most up-to-date version – assuming the link continues to work.

Further down, in the <body> section are the three “target” lines for the JavaScript. The onclick event of the buttons call the writeDate and ReadData functions in Program.js. The result of the function printData is written to the <div> with the id “results”.

In the sample JavaScript code everything prefixed with Office. comes from the Office API. This sample uses the API released for Office 2013 and much of the functionality functions across all Office applications. This is so that developers don’t need to learn a different approach for each individual application and the original APIs focus primarily on tasks common to all applications, such as reading and writing to the current selection.

When working with JavaScript in Office it’s important to keep in mind that things run asynchronously. In VBA, we pretty much expect the opposite: things happen one after the other and everything (including the user) must wait until each action has completed. Given the on-line nature of Web Add-ins and unpredictable connection speeds, asynchronous behavior allows the user to continue working while the add-in is “doing its thing”. You can read more on the topic on MSDN.

Keeping this in mind, look at the first line of code: Office.initialize. This runs when the Web Add-in has finished loading – everything else in the add-in must wait for this. Within the function is $(document).ready(function (). This uses JQuery (you can recognize it by the $) to address the browser (not the Office!) document and determine when it is loaded in the browser window. As the comment says, any logic you want to run at this point comes within this function.

// The initialize function is required for all apps.
Office.initialize = function (reason) {
    // Checks for the DOM to load using the jQuery ready function.
    $(document).ready(function () {
    // After the DOM is loaded, app-specific code can run.
    // Add any initialization logic to this function.
    });
}
var MyArray = [['Berlin'],['Munich'],['Duisburg']];

function writeData() {
    Office.context.document.setSelectedDataAsync(MyArray, { coercionType: 'matrix' });
}

function ReadData() {
    Office.context.document.getSelectedDataAsync("matrix", function (result) {
        if (result.status === "succeeded"){
            printData(result.value);
        }

        else{
            printData(result.error.name + ":" + err.message);
        }
    });
}

      function printData(data) {
    {
        var printOut = "";

        for (var x = 0 ; x < data.length; x++) {
            for (var y = 0; y < data[x].length; y++) {
                printOut += data[x][y] + ",";
            }
        }
       document.getElementById("results").innerText = printOut;
    }
}

From the discussion in the post about variable scope you should recognize that the variable MyArray as well as the three functions are at the global level – they’re visible to the html page and two of the functions are called by the buttons.

Both ReadData and writeData begin with Office.context.document. This returns the currently active file in the Office application interface, whether Word document, Excel workbook, PowerPoint slide or Project page. More information can be found at
https://msdn.microsoft.com/EN-US/library/office/fp161122.aspx,
https://msdn.microsoft.com/EN-US/library/office/fp161104.aspx,
https://msdn.microsoft.com/EN-US/library/office/fp161177.aspx,
https://msdn.microsoft.com/EN-US/library/office/fp142295.aspx.

Logically, writeData inserts content to the Office document using the method setSelectedDataAsync. (Note the suffix “Async” in the method name.) In Office 2013, this can only be done to the current selection unless bindings have been created. So in Word VBA think of this as: Selection.Range.

In this sample, two of three possible parameters are used: data and options. The variable MyArray is passed as the data. This brings up the question how the content of an array should be written. This is determined by the option CoercionType matrix, which is supported only by Word and Excel and results respectively in a table / range of cells.

ReadData is a bit complexer. It uses the method getSelectedDataAsync to read the current selection. Again, “matrix” is specified as the data format to be retrieved. In contrast to writeData, this method executes an anonymous callback function once the read action has completed to evaluate what has happened.

This function receives the parameter result which carries information returned by the method. You can see that an if evaluation checks whether the property result.status returns the string “succeeded”. If it does, the information read from the document (result.value) is sent to the function printData. Otherwise, error information (result.error) is sent to printData.

There are a number of things to note about this function:

  • You do not have to use the term “result” as the function parameter – it can be anything you like. So when reading sample code, be aware that it could be anything, but the purpose and behavior are the same and don’t let yourself become confused.
  • Some code examples won’t check result.status for string value. Instead, they’ll check the object Office.AsyncResultStatus. For example: result.status === Office.AsyncResultStatus.Succeeded. Again, don’t let yourself get confused: these can be used interchangeably. Office.AsyncResultStatus.Succeeded and Office.AsyncResultStatus.Failed return the strings “succeeded” and “failed”, respectively.
  • The parameter (result) returns additional information: value gives you access to the data read from the document; error contains the error information, just as you’d get it from VBA with name, error number (code object) and message.

I found working with nested callbacks one of the most confusing things about the JavaScript Add-ins – it takes a lot of getting used to!

The function printData doesn’t use any Office.js functionality – it’s strictly standard JavaScript. It loops through the array, creating a string of the data, then writes it to the div on the html page in the task pane.

A subsequent post will look at alternative methods (Coercion types) for writing information to Word documents.

3 Responses to “Web Add-ins: Analyzing the “Hello World” JavaScript”
  1. I think that once again Microsoft did not think about power users, only developers. There are two points, in my opinion, that wi’ll determine mass adoption by users of Office Addins.
    1 – Integrated JavaScript IDE on each Office application, like VBE.
    2 – Macro recorder
    Obligating one to download and install Visual Studio is just too much. When I wasn’t into IT, I couldn’t install nothing on my working machine because of admin permissions.
    As you said, we can use notepad to write an Office Add-in, but hell, we’re not hardcore Linux nerds.

    • WordMeister says:

      Thank you for your thoughts, Felipe :-)
      Those would certainly be a bonus, and who knows, perhaps someday they may become reality if the new technology is adopted with more enthusiasm than VSTO was!
      Of course, such an IDE would also need a way to do some kind of distribution/publishing in order for it to make sense – or what do you think?

      • Sorry for the delay, I got lost. In fact, I don’t know how, but I intended to post these toughts on the first JS API post series, not on this page, sorry.

        I agree, distribution/publishing is a tricky part.

        First of all, the application should be able to deploy – at least – its manifest and binaries locally.

        I think it would not bad at all if Microsoft created a “Microsoft Office Add-in Publisher” application. This application would be easy to use: select the deployed manifest you want to publish, then choose where you want to deploy: network, sharepoint or Office store.

        This is just an idea that should be armored with security concerns.

  2.  
Leave a Reply