如何在不同的Word.run上下文中使用范围?

Tom*_*ell 3 ms-word apps-for-office office-js

我为单词创建了一个任务窗格插件,该插件运行搜索并以列表形式向用户显示有关结果的信息。当用户单击列表中的某个项目时,我想选择字词范围以向用户显示该项目的位置。然后,该插件将允许用户在范围上执行其他任务,例如更改字体颜色。

我可以使用以下功能运行搜索并获取显示范围:

function runSearch(textToFind) {
  var items = [];
  return Word.run(function(context) {
    var options = Word.SearchOptions.newObject(context);
    options.matchWildCards = false;

    var rangesFind = context.document.body.search(textToFind, options);
    context.load(rangesFind, 'text, font, style');
    return context.sync().then(function() {
      for (var i = 0; i < rangesFind.items.length; i++) {
        items.push(rangesFind.items[i]);
        context.trackedObjects.add(rangesFind.items[i]);
      }
      return context.sync();
    });
  })
  .then(function() {
    return items;
  });
}; 
Run Code Online (Sandbox Code Playgroud)

但是,我在选择用户点击范围时遇到困难。我试过使用range上下文:

function selectRange(range){
  range.select();
  return range.context.sync();
}
Run Code Online (Sandbox Code Playgroud)

或在新的Word.run上下文中使用范围:

function selectRange(range){
  return Word.run(function(context) {
    context.load(range);
    return context.sync().then(function(){
      range.select();
      return context.sync();
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

我遇到了一种潜在的方法,该方法涉及为每个搜索结果创建一个内容控件,然后selectRange在新的上下文中重新加载该函数中的所有内容控件,并找到匹配的控件,但是当我已经有了范围时,这似乎效率很低。

在不同的Word.run上下文中重用范围的最佳方法是什么?

Mic*_*oft 5

您不能跨Word.run调用使用对象。Word.run每次调用时都会创建一个新的上下文,而原始对象绑定到其自己的上下文,从而造成不匹配。

话虽这么说,您绝对可以在中Word.run添加所需的对象context.trackedObjects.add(obj),即使在Word.run完成执行后,它们仍将作为工作对象保留。所谓“工作对象”,是指它们的路径不会无效(想想类似于垃圾回收的东西,但对于远程对象)。

一旦有了这样的对象(看起来像上面一样),您应该可以调用

range.select();
range.context.sync().catch(...);
Run Code Online (Sandbox Code Playgroud)

如果对您不起作用,能否举例说明您遇到的错误?

为了完整起见,我应该注意,一旦将对象添加到trackedObjects集合中,就可以有效地将这些对象的内存管理交到您自己手中。这意味着,如果您没有适当地释放内存,则会通过拖慢Word的内存/范围调整链来减慢Word的速度。因此,一旦完成使用跟踪对象的操作,就应该调用obj.context.trackedObjects.remove(obj),然后调用obj.context.sync()。不要忘了最后一部分-如果您不进行同步,那么删除跟踪对象的请求将不会被调度,并且您将继续用尽内存。

=======更新1 =======

汤姆,感谢您提供错误消息。看来这可能是API的Word实现中的错误-我将对此进行跟踪,如果还有其他问题,可能有人会与您联系。

从概念上讲,您绝对处于正确的道路上,例如,以下确实适用于Excel:

var range;
Excel.run(function (ctx) {
    var sheet = ctx.workbook.worksheets.getActiveWorksheet();

    range = sheet.getRange("A5");
    range.values = [[5]];
    ctx.trackedObjects.add(range);

    return ctx.sync();
})
.then(function(){
    setTimeout(function() {
        range.select();
        range.context.trackedObjects.remove(range);
        range.context.sync();
    }, 2000);
})
.catch(function (error) {
    showMessage("Error: " + error);        
});
Run Code Online (Sandbox Code Playgroud)

=======更新2 =======

事实证明产品中确实存在错误。但是,好消息是,使用仅JavaScript的修复很容易修复,实际上,我们将在接下来的几周内进行此操作,以更新CDN。

使用此修复程序,以下代码可以工作:

var paragraph;
Word.run(function (ctx) {
    var p = ctx.document.body.paragraphs.first;
    paragraph = p.next;
    ctx.trackedObjects.add(paragraph);
    return ctx.sync();
})
.then(function(){
    setTimeout(function() {
        paragraph.select();
        paragraph.context.trackedObjects.remove(paragraph);
        paragraph.context.sync()
            .then(function() {
                console.log("Done");
            })
            .catch(handleError);
    }, 2000);
})
.catch(handleError);

function handleError (error) {
    console.log('Error: ' + JSON.stringify(error));
    if (error instanceof OfficeExtension.Error) {
        console.log('Debug info: ' + JSON.stringify(error.debugInfo));
    }
}
Run Code Online (Sandbox Code Playgroud)

想要更好的消息吗?在更新CDN之前,您可以使用下面的代码“修补” JavaScript库并使上面的代码运行。您应该在Office.js已加载之后(即,在Office.initialize函数内)并且执行之前的某个时间运行此代码Word.run

var TrackedObjects = (function () {
    function TrackedObjects(context) {
        this._autoCleanupList = {};
        this.m_context = context;
    }
    TrackedObjects.prototype.add = function (param) {
        var _this = this;
        if (Array.isArray(param)) {
            param.forEach(function (item) { return _this._addCommon(item, true); });
        }
        else {
            this._addCommon(param, true);
        }
    };
    TrackedObjects.prototype._autoAdd = function (object) {
        this._addCommon(object, false);
        this._autoCleanupList[object._objectPath.objectPathInfo.Id] = object;
    };
    TrackedObjects.prototype._addCommon = function (object, isExplicitlyAdded) {
        if (object[OfficeExtension.Constants.isTracked]) {
            if (isExplicitlyAdded && this.m_context._autoCleanup) {
                delete this._autoCleanupList[object._objectPath.objectPathInfo.Id];
            }
            return;
        }
        var referenceId = object[OfficeExtension.Constants.referenceId];
        if (OfficeExtension.Utility.isNullOrEmptyString(referenceId) && object._KeepReference) {
            object._KeepReference();
            OfficeExtension.ActionFactory.createInstantiateAction(this.m_context, object);
            if (isExplicitlyAdded && this.m_context._autoCleanup) {
                delete this._autoCleanupList[object._objectPath.objectPathInfo.Id];
            }
            object[OfficeExtension.Constants.isTracked] = true;
        }
    };
    TrackedObjects.prototype.remove = function (param) {
        var _this = this;
        if (Array.isArray(param)) {
            param.forEach(function (item) { return _this._removeCommon(item); });
        }
        else {
            this._removeCommon(param);
        }
    };
    TrackedObjects.prototype._removeCommon = function (object) {
        var referenceId = object[OfficeExtension.Constants.referenceId];
        if (!OfficeExtension.Utility.isNullOrEmptyString(referenceId)) {
            var rootObject = this.m_context._rootObject;
            if (rootObject._RemoveReference) {
                rootObject._RemoveReference(referenceId);
            }
            delete object[OfficeExtension.Constants.isTracked];
        }
    };
    TrackedObjects.prototype._retrieveAndClearAutoCleanupList = function () {
        var list = this._autoCleanupList;
        this._autoCleanupList = {};
        return list;
    };
    return TrackedObjects;
}());
OfficeExtension.TrackedObjects = TrackedObjects;
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

〜MSFT Office可扩展性团队的开发人员Michael Zlatkovsky