如何在不同的Word.run上下文中使用范围? [英] How can a range be used across different Word.run contexts?

查看:92
本文介绍了如何在不同的Word.run上下文中使用范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have created a taskpane addin for word that runs a search and displays information about the results as a list to the user. When the user clicks on an item in the list I want to select the range in word to show the user the location of the item. The addin will then allow the user to perform additional tasks on the range, for example change the font colour.

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

I am able to run the search and get ranges for display using the function below:

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;
  });
}; 

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

However I am having difficulty selecting the range on user click. I have tried using the ranges context:

function selectRange(range){
  range.select();
  return range.context.sync();
}

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

Or using the range in a new Word.run context:

function selectRange(range){
  return Word.run(function(context) {
    context.load(range);
    return context.sync().then(function(){
      range.select();
      return context.sync();
    });
  });
}

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

I have come across a potential method that involves creating a content control for each search result and then reloading all the content controls in the selectRangefunction in the new context and finding the matching control, but that seems very inefficient when I have the range already.

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

What is the best method for reusing a range across different Word.run contexts?

推荐答案

您不能在Word.run调用之间使用对象. Word.run每次调用时都会创建一个新的上下文,而原始对象绑定到其自己的上下文中,从而导致不匹配.

You cannot use an object across Word.run invocations. Word.run creates a new context every time that it's invoked, whereas the original object is tied to its own context, creating a mismatch.

话虽如此,您绝对可以在Word.run内部可以将所需的对象添加到context.trackedObjects.add(obj),即使在Word.run完成执行后,它们仍将保留为工作对象. 工作对象"是指它们的路径不会失效(想想类似于垃圾回收的东西,但对于远程对象).

That being said, you absolutely can, from within a Word.run, add the objects you desire to context.trackedObjects.add(obj), and they will remain as working objects even after Word.run finishes executing. By "working objects" I mean that their path will not get invalidated (think something similar to garbage collection, but for remote objects).

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

Once you have such object (and it looks above like you do), you should be able to call

range.select();
range.context.sync().catch(...);

如果它不适合您,能否举例说明您遇到的错误?

If it's not working for you, can you provide an example of the error you're getting?

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

For completeness sake, I should note that once you add objects to the trackedObjects collection, you're effectively taking memory management of those objects into your own hands. This means that if you don't properly release the memory, you will be slowing down Word by bogging down its memory / range-adjustment chain. So once you're done using the tracked object(s), you should call obj.context.trackedObjects.remove(obj), followed by obj.context.sync(). Don't forget the last part - if you don't do a sync, your request to remove the tracked objects will not be dispatched, and you'll continue to use up the memory.

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

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

Tom, thanks for providing the error message. It looks like this might be a bug in the Word implementation of the APIs -- I'll follow up on that, and someone might reach out to you if there's more questions.

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

From a conceptual standpoint, you are absolutely on the right path -- and the following does work in Excel, for example:

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);        
});

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

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

It turns out there is indeed a bug in the product. However, the good news is that it's easy to fix with a JavaScript-only fix, and in fact we'll do so in the next couple of weeks, updating the CDN.

使用此修复程序,可以运行以下代码:

With the fix, the following code works:

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));
    }
}

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

Want even better news? Until the CDN is updated, you can use the code below to "patch" the JavaScript library and make the code above run. You should run this code some time after Office.js has already loaded (i.e., within your Office.initialize function), and before you do a 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;

希望这会有所帮助!

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

~ Michael Zlatkovsky, developer on Office Extensibility team, MSFT

这篇关于如何在不同的Word.run上下文中使用范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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