My previous post on getting started with Script Lab and the Office JS APIs for Word looked at some similarities between the COM and Word JS API object models, based on the Script Lab Basic API call sample. This time, I’ll highlight the core part of the sample code that differs from working with COM/VBA.

The core part of the code snippet consists of the five lines below. The first two were discussed in the previous post. The last three are the subject of this discussion.

   const range = context.document.getSelection();
   range.font.color = "red";

   range.load("text");
   await context.sync();
   console.log(`The selected text was "${range.text}".`);

Unlike working with VBA and the COM object model, the commands are not executed line-by-line as they appear in the code. The commands are queued up for execution and wait for a “sync” (synchronize) command.

VBA/COM is designed to run locally, directly on the machine. Indeed, VBA runs inside the Office application process (is part of it). Often, it blocks you from doing any work on the document or in the application while the code is running. This kind of behavior is problematical when working in an on-line environment (such as a browser) because delay times can be quite long when information is passed via the Internet. Programming for the Internet, therefore, tries as much as possible to not block the user. The former is “synchronous” behavior, the latter requires “ansynchronous” execution. Adapting to an ansynchronous way of thinking and coding is probably the biggest challenge for the VBA/COM developer.

Since the first incarnation of the Office JS APIs, the way ansync is handled has become a bit more “intuitive” – less complex to code. But it still requires adjustments in thinking and coding logic.

As an example, consider how to query Word for the text of the current selection: in the VBA/COM world we can use sText = Selection.Text (or sText = Selection.Range.Text). The string of characters in the selection is immediately available.

Now look at the sample code, above. The variable range is declared and the selection assigned to it. Also a color is assigned to the Range. But in contrast to the equivalent VBA these have not yet taken effect. If you were to query range.text the code would fail with an error:

PropertyNotLoaded: The property ‘text’ is not available. Before reading the property’s value, call the load method on the containing object and call “context.sync()” on the associated request context.

In other words, you can assign values to properties without access to the actual object. But these won’t take effect immediately and it’s not possible to read properties at this point.

The line range.load("text"); is the instruction to get the range’s text property when the next synchronization takes place. But the text is not available when this line of code is consumed – this command, as well, is put in the queue.

In order to execute the queued commands, the fourth line of code is required: await context.sync();. This opens a conduit to the Word application, executes the property assignments and retrieves requested information. Only after this can range.text (the laste line, above) be queried successfully.

At await context.sync(); the code execution pauses until all the queued commands have taken place and any requested information has been returned. This is very important. With VBA/COM, most commands take place one after the other, each waiting for the previous to finish. When working with the Office JS APIs this won’t be the case – you can’t be sure in what order things are executed within a synchronization call.

So why not synchronize after each line of code? This is resource intensive – you get a performance hit each time it executes. This is especially noticeable with the on-line versions of an Office application. It’s important, therefore, to think through the steps your code needs to take and bundle as many commands as possible in the queue.

In the next installment I’ll take a closer look at the load method for retrieving properties.

Leave a Reply