javascript - Word 联机加载项 : Using objects across multiple contexts

标签 javascript ms-office office365 office-js

我正在尝试制作一个插件,将一个段落分成几个句子然后说出来,并在阅读时突出显示这些句子。在大多数情况下,我可以正常工作,但当我想突出显示当前正在阅读的句子时就会出现问题。

我有一个根据用户光标所在的位置将段落分成句子的功能:

function selectionTest() {
    Word.run(function (context) {
        originalRange = context.document.getSelection();
        var paragraphs = originalRange.paragraphs;

        context.load(paragraphs, 'text');
        context.load(originalRange, 'text');

        return context.sync().then(function () {
            //Range should only be present in a single paragraph, rather than spanning multiple
            if (paragraphs.items.length === 1) {
                var paragraph = paragraphs.items[0];

                var ranges = paragraph.getTextRanges(['.'], true);

                context.load(ranges, 'text');
                return context.sync(ranges);
            }
        }).then(function (sentences) {
            ...

我想根据“originalRange”对象突出显示文本,以便突出显示正确的句子,如下所示:

function highlightSentence(id, colour) {
    Word.run(function (context) {
        var paragraphs = originalRange.paragraphs;

        context.load(paragraphs, 'text');
        context.load(originalRange, 'text');
        ...

但这会产生错误,因为“originalRange”正在多个上下文中使用。有没有办法让我在多个上下文或其他解决方案中使用“originalRange”?

更新:

我试图在函数中再次获取段落的句子,对原始范围使用“context.trackedObjects.add”。这在尝试从中获取“段落”属性时导致了同样的错误。

我意识到我可能需要的只是段落的句子,而不是使用原始范围再次获取句子。相反,我实现了一个不同的解决方案:

function highlightSentence(id, colour) {
    Word.run(function (context) {
        context.trackedObjects.add(gSentences);

        return context.sync().then(function () {
            gSentences.items[id].font.highlightColor = colour;
        }).then(context.sync);

    }).then(function(){   
        gSentences.context.trackedObjects.remove(gSentences);
        gSentences.context.sync();
    }).catch(function(error) {
        console.log(error.message);
    });
}

但是,我现在收到以下错误: “对象路径‘_reference()’不适合你正在尝试做的事情。如果你在多个\”context.sync\” 调用中使用该对象并且在\的顺序执行之外“.run”批处理,请使用“context.trackedObjects.add()”和“context.trackedObjects.remove()”方法来管理对象的生命周期。

更新:

我设法解决了上面的问题。但是,现在,在高亮功能期间,由于“gSentences”变量尚未在上下文中加载,因此其“字体”等属性不可用,因此我无法更改高亮颜色。如果我尝试在上下文中加载它,则会出现“无法跨上下文使用对象”的原始错误。我不确定此时该做什么。

更新:

这就是我用来检索段落中相同位置或光标之后的句子的方法。这些句子被推到一个数组中被说出来。我发现我不得不花很多时间处理回调才能做到这一点。

function selectionTest() {
    Word.run(function (context) {
        var range = context.document.getSelection();
        var paragraphs = range.paragraphs;

        context.load(paragraphs, 'text');

        return context.sync().then(function () {
            if (paragraphs.items.length === 1) {
                var paragraph = paragraphs.items[0];

                gSentences = paragraph.getTextRanges(['.'], true);

                context.load(gSentences);
                return context.sync();
            }
        }).then(function () {
            if (gSentences.items) {
                var sentencesResult = '';
                var callbacklist = [];

                currentSentence = 0;
                sentencesToSpeak = [];

                function isSentenceinRange(idx, fn) {
                    var rangeLoc = gSentences.items[idx].compareLocationWith(range);

                    return context.sync().then(function () {
                        if (rangeLoc.value === Word.LocationRelation.contains || rangeLoc.value === Word.InsertLocation.after) {
                            return fn(gSentences.items[idx].text);
                        }

                        return fn('');
                    });
                }

                for (var i = 0; i < gSentences.items.length; i++) {
                    callbacklist.push(
                        (function (i) {
                            return function () {
                                isSentenceinRange(i, function (result) {
                                    if (result) {
                                        sentencesToSpeak.push({ id: i, text: result });

                                        if (i === gSentences.items.length - 1) {
                                            sentencesFinialised();
                                        }
                                    }
                                });
                            }
                        })(i)
                    );
                }

                for (var callback in callbacklist) {
                    callbacklist[callback].call(this);
                }

            }
        });
    }).catch(function (error) {
        console.log(error.message);
    });
}

我想在说话时突出显示句子,这是下一个函数要做的(调用音频元素的 onend 事件监听器)

 function highlightSentenceTest(id, colour) {
    Word.run(function (context) {
        context.trackedObjects.add(gSentences);
        //Causes error, but need to load to get access?
        context.load(gSentences);

        return context.sync().then(function () {
            gSentences.items[id].font.highlightColor = colour;

        }).then(context.sync)
    }).catch(function(error) {
        console.log(error.message);
    });
}

最佳答案

很好的问题!这听起来很像我在这里回答的问题:How can a range be used across different Word.run contexts?

如果这没有帮助,请发表评论说明您的场景有何不同,我会尽力提供帮助。

~ Michael Zlatkovsky,Office Extensibility 团队开发人员,MSFT

P.S.:请使用 office-js 标记您的问题,以确保我们(产品组和社区)看到它们。


根据更新的问题/代码进行更新:

说实话,你的回调在做什么有点不清楚......但让我给你一些一般性的指导,看看是否有帮助:

  • 对于 Word.run(function(ctx) { ... }) 期间创建的任何对象, 该对象将在 Word.run 后立即失效执行完毕。我的意思不是 JS 垃圾收集意义上的,而是“将不再绑定(bind)到文档”意义上的。因此,即使您在 Word.run 中创建回调函数试图捕捉范围,这本身是行不通的。

  • 当你确实想在执行之间保留一个对象(或者更确切地说,让它在 Excel.run 之后存在),你必须将它添加到 ctx.trackedObjects 中。 .您需要在 .run 内执行此操作,否则就来不及了。

  • 此后要使用该对象,您不能再使用Word.run ,而是直接使用上下文。

    savedObject.doSomething();//或 savedObject.load("someProperty"); savedObject.context.sync() .then(...)//可选 .catch(...);

  • 顺便说一句:我们正在积极努力使这种模式更容易,敬请期待...

  • 目前,您需要使用 How can a range be used across different Word.run contexts? 中描述的 TrackedObjects 解决方法(额外代码) ,不过我们应该很快就会用修复程序更新 Office.js。

这能帮助您畅通无阻吗?

~迈克尔

关于javascript - Word 联机加载项 : Using objects across multiple contexts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37609667/

相关文章:

javascript - 是否可以选择一个输入字段并仅使用 Parsleyjs 触发该字段的验证

javascript - 如何在 AngularJS 中抛出自定义异常?

ms-access - office 2003 和 2007 之间的 VBA 版本有区别吗?

c# - 在 Excel 中插入页脚的问题 - OpenXML

azure - 在没有基本身份验证的情况下使用 Powershell 连接 Exchange Online

exchange-server - 捕获所有规则 - 如何捕获所有已发送到不存在的电子邮件地址的电子邮件

azure - 如果您有 Office 365,可以取消对 Azure Active Directory 的访问吗?

php - 对php请求的post jquery请求使用一个删除函数

javascript - 无法访问vuex商店中的axios

asp.net - Documents.Add 在 ASP.NET (VB.NET) 上失败