Search code examples
javascriptms-wordoffice-jsword-addinsword-web-addins

Read color and width of table border in MS Word add-in Javascript APIs


I am trying to use the Word add-in Javascript APIs to print the color and width of the top border of all the tables in a document.

I am using the following code:

    Word.run(function (context) {
        var range = context.document.getSelection();
        var tables = context.document.body.tables;
        context.load(range);
        context.load(tables);
        return context.sync().then(function () {
            for (var i = 0; i < tables.items.length; i++) {
                var topBorder = tables.items[i].getBorder("Top");
                context.load(topBorder, ['color', 'width']);
                var color = "1", width = "1";
                context.sync().then(function () {
                    color = topBorder.color.toString();
                    width = topBorder.width.toString();
                });
                range.insertText(color, "End");
                range.insertText(width, "End");
            }
            return context.sync();
        });
    });

But when I run this, it prints 11 instead of printing the correct values.

I have tried searching for some sample codes online but have been able to find codes to set value only. What am I missing?

Thanks!


Solution

  • A few problems in your code:

    1. Minor: You don't need to load the range object because you are writing to it, not reading it.
    2. You've got a context.sync inside a loop. This is rarely a good idea. It can hurt performance and makes it hard to reason about your code. The usual fix for this is to loop twice, with a single context.sync between the loops. The first loop populates an array (that will be looped through in the second loop) and loads every Office object property that will be read in the second loop. See code below.
    3. You've got a context.sync().then() and inside it another context.sync().then(). If you put a console.log("outer then") as the very last line of the outer then and console.log("inner then") as the first line of the inner then, you'll see that your outer then is completing before the inner then. That's why you are getting "11". The lines that write to the document run before these variables have been changed from their initial values.
    4. I discovered from running your code in the Script Lab tool that the line color = topBorder.color.toString(); is throwing an error saying that the color property is not loaded. This is probably another side effect of your branching Promise chain.

    The following code works, is simpler, and is more performant because it syncs only 3 times no matter how many tables are in the document.

    Word.run(function (context) {
        var range = context.document.getSelection();
        var tables = context.document.body.tables.load("items");
        var topBorders = [];
        return context.sync()
          .then(function () {
            for (var i = 0; i < tables.items.length; i++) {
              topBorders.push(tables.items[i].getBorder("Top").load(['color', 'width']));
            }
          })
          .then(context.sync)
          .then(function () {
            for (var i = 0; i < topBorders.length; i++) {
              range.insertText(topBorders[i].color.toString(), "End");
              range.insertText(topBorders[i].width.toString(), "End");
            }
          })
          .then(context.sync)
    });