一般而言,Excel.run
的目的是针对最终自动清理的OM进行连续操作。即,Excel.run
创建一个上下文,运行您的操作,然后清理分配的所有主机对象。
这就是说,正如Gab Royer所提到的,您可以通过将传出对象。而且,每个Excel对象都有一个通过“.context”属性指向其“上下文”的反指针。因此,例如,你可以这样做:
Excel.run(function (ctx) {
var worksheet = ctx.workbook.worksheets.getActiveWorksheet();
return ctx.sync(worksheet);
}).then(function(worksheet) {
worksheet.name = "Test"
return worksheet.context.sync();
}).catch(function(e) {
console.log(e)
});
正如你所看到的,在上面的代码中,你创造了Excel.run
里面的工作表对象,但外面使用它。
如果你有类似Range对象的东西,它会变得有点棘手。范围,不像工作表,而不是拥有持久性ID(它们怎么可能?基本上所有可能的单元组合都有无数个排列)。相反,在Excel.run
期间,我们自动创建持久指针,指向由Excel调整并保持跟踪的支持Range对象。当Excel.run
内的批次完成时,我们告诉主机销毁这些引用。所以如果你有这样的代码:
Excel.run(function (ctx) {
var range = ctx.workbook.getSelectedRange();
return ctx.sync(range);
}).then(function(range) {
range.format.fill.color = "red";
return ctx.sync();
}).catch(function(e) {
console.log(e)
})
它会遇到“InvalidObjectPath”错误。
但是,您可以通过手动将对象添加到ctx.trackedObjects
集合来退出跟踪对象清理。然而,在这样做的时候,你最后要自己去清理 - 而且你需要格外小心,记住不仅要清除成功,还要清除失败。否则,你基本上会创建一个内存泄漏,这将会使Excel主机应用程序变慢。
var range;
Excel.run(function (ctx) {
range = ctx.workbook.getSelectedRange();
ctx.trackedObjects.add(range);
return ctx.sync(range);
}).then(function(range) {
range.format.fill.color = "red";
return range.context.sync();
}).then(function() {
// Attempt to clean up any orphaned references
range.context.trackedObjects.remove(range);
range.context.sync(); // don't need to await it, since it's just the final cleanup call
}).catch(function(e) {
console.log(e);
})
长话短说:它肯定是可行的,并且可以Excel.run
后使用对象。您只需要为需要“跟踪”的任何对象负责内存管理。在上面的例子中,没有理由都要经过这方面的努力,因为你也可以同样有内相同的代码Excel.run(记住,你可以链的承诺内的Excel.run内批也不需要在外面做这件事)。但是如果你有一个场景,例如你有一个需要频繁运行的计时器作业(例如,更新股票代码),或者你想创建一个带有特定对象的onclick处理器的按钮,等等上面的技巧可以让你在Excel.run里创建对象,然后在它之外使用它们。
PS:至于需要嵌套模式:这是事实,如果你需要链中Excel.run ctx.sync()
电话,您将结束与嵌套了一层 - 而只是一个单一额外层。在内部,你仍然可以在没有回调金字塔的情况下链接你的承诺。例如:
Excel.run(function (ctx) {
var range = ctx.workbook.worksheets.getActiveWorksheet().getRange("A1:C3");
range.load("values");
return ctx.sync()
.then(function() {
// Some set of actions against the OM, now that the "values"
// property has been loaded and can be read from the "range" object.
})
.then(ctx.sync)
.then(function() {
// Another set of actions against the OM, presumably after doing
// another load-requiring operation (otherwise could have
// been part of the same .then as above)
})
.then(ctx.sync)
.then(function() {
// One final set of actions
});
}).catch(function(error) {
console.log("Error: " + error);
});
这应该直接复制到文档中。卓越的见解。谢谢! – user3653075
所以你提到了这个:“你想创建一个带有特定对象的onclick处理程序的按钮等等,上面的技术可以让你在Excel.run中创建对象,然后在它之外使用它们。” 我做的这事,但我发现,如果我叫'。选择()'我对象的身体,我的对象是*不*滚动或突出,但我没有收到任何异常。 我有一个带有表格的Word文档。我添加对特定单元格的引用,将其添加为跟踪对象,并附加一个事件处理程序。但点击没有任何反应。 这有效吗? –
对于有这个问题的人,我误解了上下文同步的本质。在我的初始上下文之外,我不得不打开一个新的'Word.run'来获得一个新的上下文,然后在执行我的'select()'后,在我实际的'trackedObject'上调用'context.sync()'。我认为'setTimeOut'示例很好地说明了这一点,我错过了它。 –