body.search Issue in word desktop

2019-08-26 08:28发布

问题:

context.document.body.search() is throwing an InvalidArgument exception in Word 2016 for desktops when the text to search for is larger than 255 characters. The same seems to be working with Word Online.

var searchResults = context.document.body.search("TextMoreThan255Chars");
context.load(searchResults);
return context.sync().then(function() {

});

回答1:

What you're experiencing is a limitation in Word (for the desktop). Some more information is available on Greg Maxey's site, for example. The VBA suggestion can adapted for an Office JS approach.

The key point is to break the search term down into pieces less than the 255 character limit. Search for the first part of the term, if it's found, search the next part. If it's found, check that it's immediately following the first found range. Repeat until all parts have been searched.

The sample code that follows works for me in my test - but I'm not a JS person, so it may not be optimally structured. It should at least provide the basics of how to go about performing the task. The most important concept is working with the range objects: a duplicate of any found range needs to be expanded to the end of the document body range. That provides the basis range for searching the next chunk of the term.

If a next part is found, determine whether it's immediately adjacent to the original found range (compareLocationWith). If it is, continue looping until the entire search term has been processed.

At the end, the found term(s) are highlighted.

async function basicSearch() {
    await Word.run(async (context) => {
        let maxNrChars = 254;
        let searchterm = "";
        let shortSearch = true; //search string < 255 chars
        let fullSearchterm = "Video provides a powerful way to help you prove your point. When you click Online Video, you can paste in the embed code for the video you want to add. You can also type a keyword to search online for the video that best fits your document. Aösdlkvaösd faoweifu aösdlkcj aösdofi "
        let searchTermNrChars = fullSearchterm.length;
        let nrSearchCycles = Number((searchTermNrChars / maxNrChars).toFixed(0));
        let nrRemainingChars = searchTermNrChars - (nrSearchCycles * maxNrChars);
        //console.log("Number of characters in search term: " + searchTermNrChars
        //    + "\nnumber of search cycles required: " + nrSearchCycles
        //    + "\nremaining number of characters: " + nrRemainingChars);

//numerous ranges are required to extend original found range
        let bodyRange = context.document.body.getRange();
        bodyRange.load('End');
        let completeRange = null;
        let resultRange = null;
        let extendedRange = null;
        let followupRange = null;

        let cycleCounter = 0;
        let resultText = "";
        if (searchTermNrChars > maxNrChars) {
            searchterm = fullSearchterm.substring(0, maxNrChars);
            cycleCounter++;
            shortSearch = false;
        }
        else { searchterm = fullSearchterm; }

        let results = context.document.body.search(searchterm);
        results.load({ select: 'font/highlightColor, text' });

        await context.sync();

        // short search term, highlight...
        if (shortSearch) {
            for (let i = 0; i < results.items.length; i++) {
                results.items[i].font.highlightColor = "yellow";
            }
        }
        else {
            //console.log("Long search");
            for (let i = 0; i < results.items.length; i++) {
                resultRange = results.items[i];
                resultRange.load('End');
                extendedRange = resultRange.getRange('End').expandTo(bodyRange.getRange('End'));

                await context.sync();

                //search for the remainder of the long search term
                for (let cycle = 1; cycle < nrSearchCycles; cycle++) {
                    searchterm = fullSearchterm.substring((cycle * maxNrChars), maxNrChars);
                    //console.log(searchterm + " in cycle " + cycle);
                    let CycleResults = extendedRange.search(searchterm);
                    CycleResults.load({ select: 'text, Start, End' });
                    await context.sync();
                    followupRange = CycleResults.items[0];

                    //directly adjacent?
                    let isAfter = followupRange.compareLocationWith(resultRange);
                    if (isAfter.value == Word.LocationRelation.adjacentAfter) {
                        resultRange.expandTo(followupRange);
                        extendedRange = resultRange.getRange('End').expandTo(bodyRange.getRange('End'));
                    }
                    await context.sync();
                }

                if (nrRemainingChars > 0) {
                    console.log("In remaining chars");
                    searchterm = fullSearchterm.substring(searchTermNrChars - nrRemainingChars);
                    console.log(searchterm);
                    let xresults = extendedRange.search(searchterm);
                    xresults.load('end, text');
                    await context.sync();

                    let xresult = xresults.items[0];

                    let isAfter = xresult.compareLocationWith(resultRange);

                    await context.sync();
                    console.log(isAfter.value);
                    if (isAfter.value == Word.LocationRelation.adjacentAfter) {
                        completeRange = resultRange.expandTo(xresult);
                        completeRange.load('text');
                        //completeRange.select();
                        await context.sync();
                        resultText = completeRange.text.substring(0, fullSearchterm.length);
                        console.log("Result" + cycleCounter + ": " + resultText);
                    }  
                }
                else {
                    //No remeaining chars
                    resultRange.load('text');
                    //resultRange.select();
                    await context.sync();
                    resultText = resultRange.text.substring(0, fullSearchterm.length);
                    completeRange = resultRange; 
                }

                //long search successful?
                if (resultText == fullSearchterm) {
                    completeRange.font.highlightColor = "yellow";
                }
                else {
                    console.log("Else! " + resultText + "  /  " + fullSearchterm);
                }
                completeRange = null;
            }
        }  
    });