替换文字后文档不同步 [英] Document not in sync after replace text

查看:82
本文介绍了替换文字后文档不同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试替换Word Online文档中的某些文本,但无法使其正常工作.

I'm trying to replace some text within a Word Online document but cannot get it to work.

'{{test}},[[test]],{test}'的结果为'13,2,3',而不是'1,2,3'.

'{{test}} , [[test]] , {test}' results in '13 , 2 , 3' and not '1 , 2 , 3'.

第一个文本似乎被处理了两次.

The first text seems to be processed twice.

任何帮助,不胜感激!

Office.initialize = function(reason) {

    function ready() {

        var myTags = [
            { "value": "1", "text": "{{test}}" },
            { "value": "2", "text": "[[test]]" },
            { "value": "3", "text": "{test}" }
        ];

        async function FillTag(tag) {

            await Word.run(async function(context) {

                    var options = Word.SearchOptions.newObject(context);
                    options.matchWildCards = false;

                    var searchResults = context.document.body.search(tag.text, options);
                    context.load(searchResults, 'text');

                    await context.sync();

                    searchResults.items.forEach(function(item) {
                        item.insertText(tag.value, Word.InsertLocation.replace);
                    });
                    await context.sync();
                })
                .catch(function(error) {
                    console.log('Error: ' + JSON.stringify(error));
                    if (error instanceof OfficeExtension.Error) {
                        console.log('Debug info: ' + JSON.stringify(error.debugInfo));
                    }
                });
        }

        async function ProcessArray(myTags) {
            myTags.forEach(async function(tag) {
                await FillTag(tag);
            });
        }

        ProcessArray(myTags);
    }

    if (document.readyState !== 'loading') {
        ready();
    }
    else {
        document.addEventListener('DOMContentLoaded', ready);
    }
};

推荐答案

这不是调试建议,而是答案,但可以稍后进行编辑.请从AppSource安装脚本实验室工具进入Word.您将在其中找到的示例片段之一称为搜索.片段中的功能之一是basicSearch.我将搜索文本在线"替换为"{{test}}",并用以下几行替换了以黄色突出显示找到的文本的行:

This is more a debugging suggestion than an answer, but it can be edited later. Please install the Script Lab tool from AppSource into Word. One of the sample snippets that you'll find in it is called Search. One of the functions in the snippet is basicSearch. I replaced the search text "Online" with "{{test}}" and I replaced the line that highlights found text in yellow with the following line:

results.items[i].insertText("1", Word.InsertLocation.replace);

这很好用,因此在足够简单的情况下,它可以准确地找到并替换"{{test}}".

This worked fine, so in simple enough scenarios, it can find and replace "{{test}}" accurately.

请您自己尝试一下,然后逐渐更改方法以使其更接近您的方法,然后看看它在什么时候开始崩溃?

Could you please try this yourself and then gradually change the method to more closely resemble yours and see at what point it begins to break?

修改1/15/18:

@Kim Brandl 的答案可能是最适合您的.但是,它在循环中确实有一个context.sync.由于每次同步都是到Office主机的往返,因此当输入数量很大和/或外接程序正在Office Online中运行时,这可能是性能问题(这意味着Office主机跨Internet访问同一主机)机器).

@Kim Brandl's answer is probably the best for you, assuming that you really have just 3 search strings. It does, however, have a context.sync inside a loop. Since each sync is a roundtrip to the Office host, that can be a peformance problem when the number of inputs is large and/or the add-in is running in Office Online (which means the Office host is across the internet instread of the same machine).

对于任何阅读此书且具有大量输入字符串的人,此解决方案可确保在整个Word.run中不超过3个同步.它还直接攻击您要解决的问题的根源,即某些找到的范围与其他范围的相对位置(特别是某些范围在其他范围内).

For anyone reading this who has a large number of input strings, here's a solution that guarantees no more than 3 syncs are needed in the entire Word.run. It also directly attacks the source of the problem that you are trying to solve, which is the relative locations of some found ranges to others (specifically, some are inside others).

该策略,我也在

The strategy, which I also used in Word-Add-in-Angular2-StyleChecker, is to first load all the ranges and then use the Range.compareLocationWith method and the LocationRelation enum to find the relative location information you need. Finally, use each range's relative location to other ranges to determine whether/how to process it.

这是功能.按照Kim的示例,我将整个代码片段放在此要点中,您可以将其导入到

Here's the function. Following Kim's example I put the whole snippet in this gist, which you can import to Script Lab tool from AppSource . (See instructions in Kim Brandl's answer.)

async function FindAndReplace() {

    let myTags = [
        { "value": "1", "text": "{{test}}" },
        { "value": "2", "text": "[[test]]" },
        { "value": "3", "text": "{test}" },
        { "value": "4", "text": "bob" },
        { "value": "5", "text": "bobb" },
        { "value": "6", "text": "ssally" },
        { "value": "7", "text": "sally" }
    ];

    let allSearchResults = [];

    await Word.run(async (context) => {    
        for (let tag of myTags) {    
            let options = Word.SearchOptions.newObject(context);
            options.matchWildCards = false;
            let searchResults = context.document.body.search(tag.text, options);
            searchResults.load('text');

            // Store each set of found ranges and the text that should replace 
            // them together, so we don't have to reconstruct the correlation 
            // after the context.sync.
            let correlatedSearchResult = {
                searchHits: searchResults, 
                replacementString: tag.value
            }           
            allSearchResults.push(correlatedSearchResult);       
        }

        await context.sync();

        // Now that we've loaded the found ranges we correlate each to
        // its replacement string, and then find each range's location relation
        // to every other. For example, 'bob' would be Inside 'xbobx'. 
        let correlatedFoundRanges = [];
        allSearchResults.forEach(function (correlatedSearchResult) {
            correlatedSearchResult.searchHits.items.forEach(function (foundRange) {
                let correlatedFoundRange = {
                    range: foundRange,
                    replacementText: correlatedSearchResult.replacementString,
                    locationRelations: []
                }
                correlatedFoundRanges.push(correlatedFoundRange);                
            });
        });

        // Two-dimensional loop over the found ranges to find each one's 
        // location relation with every other range.
        for (let i = 0; i < correlatedFoundRanges.length; i++) {
            for (let j = 0; j < correlatedFoundRanges.length; j++) {
                if (i !== j) // Don't need the range's location relation with itself.
                {
                    let locationRelation = correlatedFoundRanges[i].range.compareLocationWith(correlatedFoundRanges[j].range);
                    correlatedFoundRanges[i].locationRelations.push(locationRelation);
                }
            }
        }

        // It is not necesary to *explicitly* call load() for the 
        // LocationRelation objects, but a sync is required to load them.
        await context.sync();    

        let nonReplaceableRanges = [];
        correlatedFoundRanges.forEach(function (correlatedFoundRange) {
            correlatedFoundRange.locationRelations.forEach(function (locationRelation) {
                switch (locationRelation.value) {
                    case "Inside":
                    case "InsideStart":
                    case "InsideEnd":

                        // If the range is contained inside another range,
                        // blacklist it.
                        nonReplaceableRanges.push(correlatedFoundRange);
                        break;
                    default:
                        // Leave it off the blacklist, so it will get its 
                        // replacement string.
                        break;
                }
            });
        });

        // Do the replacement, but skip the blacklisted ranges.
        correlatedFoundRanges.forEach(function (correlatedFoundRange) {
            if (nonReplaceableRanges.indexOf(correlatedFoundRange) === -1) {
                correlatedFoundRange.range.insertText(correlatedFoundRange.replacementText, Word.InsertLocation.replace);
            }
        })

        await context.sync();
    });
}

这篇关于替换文字后文档不同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆