VBA->JS: Loading properties

The most recent post in this series introduced the concept of loading properties from the Word object before being able to work with them. The line of code in question is range.load("text"); from the Basic API snippet for Script Lab. This article goes into that concept in more depth.

The load() method is not unique to Range; it’s available for most objects. The preferred way to use it is to list the properties to be used, and only these properties. As with calling context.async() as rarely as possible, this is for performance reasons.

Let’s take a closer look at working with load using the font property as an example. (A list of the available properties for font can be found in the Office JS API documentation, but as of this writing that list is incomplete – Intellisense in Script Lab contains more entries. I’ve gathered all the properties into a list, for the sake of convenience.)

Consider the following sample code, which started out as the same Basic API (Typescript) sample from Script Lab. It sets the font color of the current selection to green and underlines it with a heavy, dashed line. Then the Range’s font properties Name, Size and Underline are loaded, along with the Text: range.load("font/name, font/size, font/underline, text");. Notice how the properties are passed to load as a comma-separated string. In order to specify a sub-property of a property a slash is used (font/name for example).

After the queued commands have been sent to Word (await context.sync();), this sample code shows the formatting information in the console.

$("#run").click(() => tryCatch(run));

async function run() {
    // Change font color and underline of current selection
    await Word.run(async (context) => {
        const range = context.document.getSelection();
        range.font.color = "green";
        range.font.underline =  Word.UnderlineType.dashLineHeavy;

        range.load("font/name, font/size, font/underline, text");

        await context.sync();

        console.log(`The selected text was  "${range.text}" 
           formatted with the font "${range.font.name}", 
           size "${range.font.size}" and
           underlined with "${range.font.underline}".`);

/** Default helper for invoking an action and handling errors. */
async function tryCatch(callback) {
    try {
        await callback();
    catch (error) {

If you were to change range.load("font/name, font/size, font/underline, text"); to range.load("font, text"); the code would still work. In this case all the font properties would be retrieved, even the ones not referred to in the code. Although this is possible, it is not desirable as every propery retrieved consumes additional resources/bandwidth.

What happens if you forget to include a property, such as font/underline? That depends…

In this particular example, if font/underline is removed from the load method the code still works. This is due to having set the underline in an earlier line of code – the information is “known”.

If that line assigning the underline type is removed, as well, then you get the error message:

PropertyNotLoaded: The property ‘underline’ 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.

This form of the load method is not the only one, but it is the recommended way to load properties. Also possible is to pass the list of what to load as a loadOption. This enables limiting the number of sub-properties retrieved if the entire list is requested and there are lots of properties.

So, retrieving the properties of an object is not difficult, but does require a bit of planning and thought in order to be efficient.

The next article in this series will focus on the very useful console.log() command.

Leave a Reply