问题
I wrote the following function to replace a huge amount of CCs with specified values:
/** replaceManyCCs()
*
* Replaces the content of many content controls, based on the replacementObject.
*
* @arg replacementObject A dictionary. The keys are the titles of the CCs which should be replaced. The values are the replacement values.
*/
function replaceManyCCs (replacementObject) {
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
var replaceCounter = 0;
for(var key in replacementObject) {
var index = documentCCtitleList.indexOf(key);
if(index == -1) { // title is missing
throw 'Could not find CC with title "'+key+'"';
}
else { // replace
CCc.items[index].insertText(' '+replacementObject[key], 'Replace');
replaceCounter++;
}
}
$('#status').html('...replacing...');
return context.sync().then(function () {
var time2 = Date.now();
var tdiff = time2-time1;
$('#status').html('Replaced '+replaceCounter+' CCs in '+(tdiff/1000)+' seconds');
});
});
}).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));
}
});
}
Replacing 816 CCs requires 50-60 seconds with this code. Are there any better/faster ways of accomplishing this?
回答1:
good follow up question. I would need to know more details about how big the replacementObject array is I am assuming at least the same size as the # of content controls in the document, that definitely has direct impact on the overall perf of your method. As you can see from my previous answer, updating 700 CCs with a fixed value takes no more than 5 seconds, so I think the satellite operations you are doing to find the new values are affecting negatively the performance.
Specifically, I see a couple of things you are doing that impact negatively the perf, and you could potentially fix.
- You are traversing at least 2 times the content control collection. One for getting the titles (and push them into a temp array), and another one to replace the content (if the replacement object matched the CCs in the doc). I would really try to do this in a single pass.
- On top of the above, In the inner loop where you are finding the titles, you are practically traversing the replacementObject for each CC (this means at least you are traversing this array 700 times) and to make things worse you are using the array.indexOf method to find the index by key (just FYI in the browser we use for Add-ins, latest IE, this is the most expensive way of traversing an array, in fact is 90% slower than if you do a for loop trying to find the indesx given the key, this simple change theoretically will be 90% faster in latest IE, if you want to keep this logic). Check out this page demonstrating this (use latest IE browser for test).
I think you should tag (or title) each content control with the index that directly maps it to the relacementObject array position (title=index in the replacement object and just directly use the index of the replacementObject array to change the values in a single pass. If there is a way of doing that you will get the fastest outcome!
来源:https://stackoverflow.com/questions/45321706/what-is-the-fastest-way-of-replacing-the-text-of-many-content-controls-via-offic