'Getting a range's surrounding text in Office-js

I have code that finds text in Word and stores the resulting ranges in an array. I am able to navigate the matching result using the array of ranges. I also want to be able to display the surrounding text of a range. This is very similar to how Find works in Word.

enter image description here

For example, I want to show the surrounding text (maybe twenty characters preceding and following) of the range of the second instance of Reading in the following text:

"To change the way a picture fits in your document, click it and a button for layout options appears next to it. When you work on a table, click where you want to add a row or a column, and then click the plus sign. Reading is easier, too, in the new Reading view. You can collapse parts of the document and focus on the text you want. If you need to stop reading before you reach the end, Word remembers where you left off - even on another device."

Here would be the output.

"Reading is easier, too, in the new Reading view. You can collapse parts of the"

I'm using Visual Studio 2017 and Office-js 1.1.

    function first() {
        ranges[0].select();
        ranges[0].font.highlightColor = "aqua";
        ranges[0].context.sync();
        showSurroundText(ranges[0]);
    }

    function previous() {
        if (index > 0) {
            ranges[--index].select();
            ranges[index].font.highlightColor = "aqua";
            ranges[index+1].font.highlightColor = "yellow";
            ranges[index].context.sync();
            showSurroundText(ranges[index]);
        }
    }

    function next() {
        console.log("Next");
        if (index < ranges.length - 1) {
            ranges[++index].select();
            ranges[index].font.highlightColor = "aqua";
            ranges[index-1].font.highlightColor = "yellow";
            ranges[index].context.sync();
            showSurroundText(ranges[index]);
        }
    }

    function showSurroundText(range:Word.Range){
        surroundTextRange = /*need help computing this range */
        surroundTextRange.load("text");
        $("#output").htmml(surroundTextRange.text);
    }


Solution 1:[1]

Unfortunately, there's no method in the Office JS API to expand (or contract) a range or selection by a certain number of characters. (Reference)

In comparison to the COM API, expanding a range is a complex undertaking. The available methods:

  • expandToOrNullObject(range)
  • getNextTextRangeOrNullObject(endingMarks, trimSpacing)
  • getRange(rangeLocationString)
  • getTextRanges

Using getNextTextRangeOrNullObject it's possible to get, for example, the next sentence following a range (the search result) by specifying a . as the endingMarks. This can be "collapsed" to its starting point using getRange, so that the search range can be extended to the start of the next sentence.

Going backwards is even more complex. One possibility is to get all the paragraphs up to the one containing the search term, then get the last sentence of the that paragraph and extend to that point.

The following code snippet demonstrates and provides a place to start "tweaking" for what you need:

let results = context.document.body.search("Reading");
results.load("length");
await context.sync();

//Work with the first found search term
let rngFound = results.items[0];

//Expand to end of sentence
let rngNextSent = rngFound.getNextTextRangeOrNullObject(["."]);
let rngExpAfter = rngNextSent.getRange("Start");
let rngFoundExp = rngFound.expandToOrNullObject(rngExpAfter);

await context.sync();

//Get paragraphs to this point
let rngDocStart = rngFound.parentBody.getRange("Start");
let rngToStart = rngFoundExp.expandToOrNullObject(rngDocStart);
let paras = rngToStart.paragraphs;
paras.load("items");
await context.sync();

//Get the paragraph previous
let nrParas = rngToStart.paragraphs.items.length-2;
let rngPrev = rngToStart.paragraphs.items[nrParas];

//Get the last sentence in that paragraph
let rngParaSent = rngPrev.getTextRanges(["."]);
rngParaSent.load("items"); await context.sync();
let rngPrevSent = rngParaSent.items[rngParaSent.items.length - 1];

//Extend the extended range to the last sentence in the previous paragraph
let rngComplete = rngFoundExp.expandToOrNullObject(rngPrevSent);
rngComplete.select();
await context.sync();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Michael T