我正在嘗試編寫一個函數,它將Rich Text Content Controls和一個字符串列表作爲參數,並用此字符串替換所有匹配的內容控件的內容。如何通過word-js替換大量內容控件中的文本?
雖然這適用於較少量的內容控件,但它會在包含大量內容的文檔時失敗。我必須處理包含700多個內容控件和單獨標題的文檔。在這種情況下,代碼只是取代了第一批66X CC,然後以GeneralException異常終止。我認爲這只是由於大量的內容控制。我遇到類似的問題,當我嘗試註冊所有這些CC的綁定(GeneralException)時。但這是一個不同的話題。
我試圖解決這個問題,通過限制每個.sync()更改的數量和循環通過CC,根據需要執行儘可能多的循環。但是,由於office-js的異步特性,這並不容易。到目前爲止,我對javascript-async-promise-programming不是很熟悉。但這是我所想出的:
function replaceCCtextWithSingleString (CCtitleList, string) {
var maxPerBatch = 100;
/*
* A first .then() block is executed to get proxy objects for all selected CCs
*
* Then we would replace all the text-contents in one single .then() block. BUT:
* Word throws a GeneralException if you try to replace the text in more then 6XX CCs in one .then() block.
* In consequence we only process maxPerBatch CCs per .then() block
*/
Word.run(function (context) {
var CCcList = [];
// load CCs
for(var i = 0; i < CCtitleList.length; i++) {
CCcList.push(context.document.contentControls.getByTitle(CCtitleList[i]).load('id'));
}
return context.sync().then(function() { // synchronous
var CClist = [];
// aggregate list of CCs
for(var i = 0; i < CCcList.length; i++) {
if(CCcList[i].items.length == 0) {
throw 'Could not find CC with title "'+CCtitleList[j]+'"';
}
else {
CClist = CClist.concat(CCcList[i].items);
}
}
$('#status').html('Found '+CClist.length+' CCs matching the criteria. Started replacing...');
console.log('Found '+CClist.length+' CCs matching the criteria. Started replacing...');
// start replacing
return context.sync().then((function loop (replaceCounter, CClist) {
// asynchronous recoursive loop
for(var i = 0; replaceCounter < CClist.length && i < maxPerBatch; i++) { // loop in loop (i does only appear in condition)
// do this maxPerBatch times and then .sync() as long as there are still unreplaced CCs
CClist[replaceCounter].insertText(string, 'Replace');
replaceCounter++;
}
if(replaceCounter < CClist.length) return context.sync() // continue loop
.then(function() {
$('#status').html('...replaced the content of '+replaceCounter+' CCs...');
return loop(replaceCounter, numCCs);
});
else return context.sync() // end loop
.then(function() {
$('#status').html('Replaced the content of all CCs');
});
})(0, CClist));
});
}).catch(function (error) {
$('#status').html('<pre>Error: ' + JSON.stringify(error, null, 4) + '</pre>');
console.log('Error: ' + JSON.stringify(error, null, 4));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo, null, 4));
}
throw error;
});
}
但是...它不工作。它取代了前100個CC,然後停止。沒有失敗,沒有例外或任何東西。 return loop(replaceCounter, CClist);
只是沒有執行,我不知道爲什麼。如果我試圖在調試器中進入這一行,它會引發我在office-js代碼中的某處。
有什麼建議嗎?
編輯:
我更新了我的代碼基於胡安Balmori的建議,它可以作爲一個魅力:
function replaceCCtextWithSingleString_v1_1 (CCtitleList, string) {
Word.run(function (context) {
var time1 = Date.now();
// load the title of all content controls
var CCc = context.document.contentControls.load('title');
return context.sync().then(function() { // synchronous
// extract CC titles
var documentCCtitleList = [];
for(var i = 0; i < CCc.items.length; i++) { documentCCtitleList.push(CCc.items[i].title); }
// check for missing titles and replace
for(var i = 0; i < CCtitleList.length; i++) {
var index = documentCCtitleList.indexOf(CCtitleList[i]);
if(index == -1) { // title is missing
throw 'Could not find CC with title "'+CCtitleList[i]+'"';
}
else { // replace
CCc.items[index].insertText(string, 'Replace');
}
}
$('#status').html('...replacing...');
return context.sync().then(function() {
var time2 = Date.now();
var tdiff = time2-time1;
$('#status').html('Successfully replaced all selected CCs in '+tdiff+' ms');
});
});
}).catch(function (error) {
$('#status').html('<pre>Error: ' + JSON.stringify(error, null, 4) + '</pre>');
console.log('Error: ' + JSON.stringify(error, null, 4));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo, null, 4));
}
});
}
它仍然需要13995毫秒即可完成,但至少它的工作原理:-)
任何想法,什麼引起了GeneralException,但?
我張貼關於速度問題的新問題:What is the fastest way of replacing the text of many content controls via office-js?
我有標題來訪問個人內容的控制,因爲下一個步驟應該是,爲所有這些提供個性化的內容,基於標題。我會嘗試根據您的建議重新創建我的功能,計算更改時間並更新我的帖子。 –