一般而言,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'示例很好地說明了這一點,我錯過了它。 –