Search code examples
ms-wordoffice-jsword-contentcontrol

How to get a specific content control using contentControls.getItem?


I'm trying to pick up a content control from a document using its position. ccs.getFirstOrNullObject(); works, but I don't want the first content control. ccs.getItem(0); (or any integer value) returns the error:

ItemNotFound: We couldn’t find the item you requested. Check the OfficeExtension.Error.debugInfo for more information.

How can I specify a particular content control by its position in the document?

Code from script lab:

async function
    getAdjacentRange() {
    await Word.run(async (context) => {
        var ccs = context.document.contentControls;
        ccs.load("items");
        await context.sync();
        console.log("Nr cc: " + ccs.items.length);
        //works:
        //let cc = ccs.getFirstOrNullObject();
        //doesn't work:
        let cc = ccs.getItem(0);

        let ccRange = cc.getRange("Start");
        let ccParas = ccRange.paragraphs; cc.load("text,range,paragraphs");
        let ccPara = ccParas.getFirst();
        ccParas.load("items")
        let paraRange = ccPara.getRange("Start");
        let rng = paraRange.expandTo(ccRange);
        let em = [" "];
        console.log(em.length.toString());
        let words = rng.getTextRanges(em, true);
        words.load("items");
        await context.sync();
        let nrWords = words.items.length;
        let lastWord = words.items[nrWords - 1];
        let wordBeforeCC = words.getFirst();
        wordBeforeCC.load("text");
        await context.sync();
        console.log(cc.text + "/" + wordBeforeCC.text + "nr Words: " + nrWords + "last word: " + lastWord.text);
})
    }

Solution

  • Lets not confuse getItem() vs. getItemAt() methods. getItem() works with IDs, while getItemAt() with position.

    Given that CCs can be in header/footer and other subdocument, inferring order can be challenging and hence there is no getItemAt() method in the cc collection.

    That been said, the items array has the content controls in reading order, so items[0] gives you the first content control, items[n - 1] the last one (assuming N ccs in the document).

    And yes, you need to load them all.

    Here is an example on how to access the 3rd content control in the doc:

    await Word.run(async (context) => {
        let ccs = context.document.contentControls;
        ccs.load();
        await context.sync();
        //assuming there are more then 2 
        if(ccs.items.length >= 2)
            console.log(ccs.items[2].text);
    });

    Finally, I recommend you to use the other methods to get access to CCs.

    I.e. contentControls.getById, contentControls.getByName() and getByTag().