来自 word-win32-16 的一般异常错误。00.js:19:150094)\n 在 yi
General Exception Error from word-win32-16.00.js:19:150094)\n at yi
我有 100 个左右的 Word Open XML(.xml,不是 .docx,另存为 "Word XML Document")存储在 SharePoint 上的文档(组件)。
我使用AJAX通过选择加载这些,如xml,1对多到一个数组中,我也在其中管理选择顺序.
一旦用户选择了 "components" 他们就可以将它们插入到 Word 中,插入是通过数组遍历完成的(可能有更好的方法来做到这一点 - 但现在它确实有效) ,
wordBuild 进行加载
function writeDocSync(){
// run through nameXMLArray to find the right sequence
var x = 0;
var countXMLAdds = 0;
//debugger;
toggleWriteButton("disable");
$('.progress-button').progressInitialize("Building Word");
toggleProgressBar(true);
// only run if we have data present
if(nameXMLArray.length > 0){
// increment through sequentially until we have all values
while (countXMLAdds <= checkedList.length){
// repeatedly traverse the array to get the next in sequence
while (x < nameXMLArray.length){
if (Number(nameXMLArray[x].position) === countXMLAdds && nameXMLArray[x].useStatus === true){
progHold = countXMLAdds;
wordBuild(nameXMLArray[x].xml, nameXMLArray[x].filename, countXMLAdds);
}
x++;
}
x=0;
countXMLAdds ++;
}
document.getElementById("showCheck").className = "results";
writeSelections("<b>You just built your proposal using<br/>the following components:</b><br/>");
toggleWriteButton("enable");
}
}
xxxxxxxxx
function wordBuild(xmlBody, nameDoc, progress){
var aryLN = checkedList.length;
var progPCT = (progress/aryLN)*100;
progressMeter.progressSet(progPCT);
Word.run(function (context) {
var currentDoc = context.document;
var body = currentDoc.body;
body.insertOoxml(xmlBody, Word.InsertLocation.end);
body.insertBreak(Word.BreakType.page, Word.InsertLocation.end);
return context.sync().then(function () {
showNotification("Written " + nameDoc);
});
})
.catch(function (error) {
showNotification('Error: ' + nameDoc + ' :' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
showNotification('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
所有文档将单独加载,所有文档将分批加载,例如 10 - 30 或更多。
当我加载整个集时出现问题(我有一个 "check all" 选项)。
有时在我得到异常之前会构建 50 个,有时是 60 个,很少超过 60 个,但偶尔我会遇到一个没有发生异常的间隙,然后它会在以后继续。
异常(对每个文件重复)是:
Debug info: {}
Error: componentABC.xml :{"name":"OfficeExtension.Error","code":"GeneralException","message":"An internal error has occurred.","traceMessages":[],"debugInfo":{},"stack":"GeneralException: An internal error has occurred.\n at Anonymous function (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:150094)\n at yi (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:163912)\n at st (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:163999)\n at d (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:163819)\n at c (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:162405)"}
对于可能导致此问题的任何帮助,我们将不胜感激。
哦,我还应该说,引发异常的文件不会插入到Word中。但在较小的批次中 - 它们可以正常工作。
Word.run()
是一个异步调用,您可以进行的并发 Word.run()
调用的数量是有限制的。由于您在 while
循环中执行 Word.run()
,因此所有循环都会同时启动,并且 运行 同时启动。
有几种方法可以解决这个问题。
将所有内容放在一个 Word.run()
调用中。这会将所有内容放在一个巨大的批次中,避免多次往返调用 Word。
if (nameXMLArray.length > 0 {
Word.run(function(context) {
//...
while(...) {
wordBuild(context, nameXMLArray[x].xml, nameXMLArray[x].filename, countXMLAdds);
//...
}
return context.sync();
});
}
function wordBuild(context, xmlBoxy, nameDoc, progress) {
//everything as it currently is, except without the Word.run and the context.sync
}
将 wordBuild 实现为承诺,并使用 AngularJS 的 $q 服务来链接承诺,大致如下所示:
function wordBuild(...) {
var deferred = $q.defer();
Word.run( function(context) {
// current code
return context.sync().then(function() {
deferred.resolve();
});
});
return deferred.promise;
}
//Somewhere else
for (var x…)
{
promises.add(wordBuild);
}
$q.all(promises);
https://docs.angularjs.org/api/ng/service/$q
Angularjs $q.all
链接 wordBuild
调用自己,如下所示:
var x = 0;
var context;
function (wordBuild() {
if (x >= nameXMLArray.length)
return;
else {
context.document.body.insertOoxml(ooxml, Word.InsertLocation.end);
x++;
return context.sync().then(wordBuild);
}
});
Word.run(function (ctx) {
context = ctx;
return wordBuild();
}
这种方法很难维护,但它可以工作。
顺便说一句,原始代码中的进度表仅在调用 Word 开始时更新,而不是实际 returns。您可能希望将进度表更新代码移动到回调中。
我最终使用了 jQuery 延迟,我已经在使用 jQuery 树视图和复选框等,所以这是有道理的。
这是 Geoffrey 的建议和我自己的建议的结合!我不能说它是好的代码,只有这样才行得通。 (如果是好的代码,我会花更多的时间去理解!)
我 运行 批 49 xml 文档插入,在 51 处异步调用 "Word.run" 在测试中失败,并且在一个 Word.run 中插入 80 个左右的文档导致 Word 冻结,因此尽管未证明 1 Word.run 内有 49 个插入似乎是 10 个的良好入门! 49 件中的 50 个插入允许 2450 个插入,这超出了我认为需要的任何内容,并且可能会破坏 Word!
为了让 deferreds 和 sent 变量在作为异步 deferreds 启动后保持它们的值,我必须创建一个变量来传输新的 deferreds 和值,所以我可以使用 "bind" 命令。
作为 Word async returns context.sync() 我检查批次的计数,当批次完成时,我然后调用下一批次 - 在 context.sync()
一种递归调用,仍然是 Geoffrey 的建议和批处理的组合。这具有 50 个批次的 49 个文档部分的理论限制。到目前为止,这在所有测试中都有效。
进度表存在于它自己的定时调用中,但由于 JavaScript 代码优先于 UI 它确实会跳转。例如 120 个文档,它会相当快地跳到一半以下,然后过一会儿跳到几乎完成,然后完成(有效地快速连续百分比增加 3 跳,建议的各种技巧效果为零(forceRepaint() 是最新的实验!)。
function startUILock(){
// batch up in groups of 49 documents (51 and more were shown to fail, 49 gives manouvre room)
toggleProgressBar(true);
$('.progress-button').progressInitialize("Building Word");
progressMeter.progressSet(1);
$.blockUI({message: "Building word..."});
setTimeout(forceRepaint, 3000);
}
function forceRepaint(){
var el = document.getElementById('progDiv');
el.style.cssText += ';-webkit-transform:rotateZ(0deg)';
el.offsetHeight;
el.style.cssText += ';-webkit-transform:none';
}
function UIUnlock(insertedCount){
debugger;
var pct = (insertedCount/checkedList.length)*100
//showNotification('Progress percent is: ' + pct);
if (insertedCount !== checkedList.length ){
progressMeter.progressSet(pct);
forceRepaint();
} else {
$.unblockUI();
progressMeter.progressSet(100);
}
}
function writeDocDeffered(){
insertedCounter = 0;
var lastBatch = 0;
var x = 49;
var z = checkedList.length + 1;
if(x > z){
x=z;
}
deferreds = buildDeferredBatch(x, lastBatch);
$.when(deferreds).done(function () {
return;
})
.fail(function () {
//showNotification('One of our promises failed');
});
}
function buildDeferredBatch(batch, lastBatch) {
// this ensures the variables remain as issued - allows use of "bind"
var deferredsa = [];
var docSender = {
defr : $.Deferred(),
POSITION: batch,
LASTPOSITION: lastBatch,
runMe : function(){
this.defr.resolve(writeDocBatchedDeferred(this.POSITION, this.LASTPOSITION, this.defr));
}
}
// small timeout might not be required
deferredsa.push(setTimeout(docSender.runMe.bind(docSender), 10));
return deferredsa;
}
function writeDocBatchedDeferred(batch, lastBatch, defr){
// write the batches using deferred and promises
var x;
var countXMLAdds = lastBatch;
x = 0;
var fileName;
debugger;
// only run if we have data present
if(nameXMLArray.length > 0){
var aryLN = checkedList.length;
// increment through sequentially until we have all values
Word.run(function (context) {
var currentDoc = context.document;
var body = currentDoc.body;
while (countXMLAdds <= batch){
// repeatedly traverse the array to get the next in sequence
while (x < nameXMLArray.length){
if (Number(nameXMLArray[x].position) === countXMLAdds && nameXMLArray[x].useStatus === true){
fileName = nameXMLArray[x].filename;
body.insertOoxml(nameXMLArray[x].xml, Word.InsertLocation.end);
body.insertBreak(Word.BreakType.page, Word.InsertLocation.end);
insertedCounter = countXMLAdds;
var latest = insertedCounter;
var timerIt = {
LATEST: latest,
runMe : function(){
UIUnlock(this.LATEST);
}
}
setTimeout(timerIt.runMe.bind(timerIt),1000);
}
x++;
}
x=0;
countXMLAdds ++;
}
return context.sync().then(function () {
if(countXMLAdds = batch){
var lastBatch = batch + 1;
// set for next batch
var nextBatch = batch + 50;
var totalBatch = checkedList.length + 1;
// do not exceed the total batch
if(nextBatch > totalBatch){
nextBatch=totalBatch;
}
// any left to process keep going
if (nextBatch <= totalBatch && lastBatch < nextBatch){
deferreds = deferreds.concat(buildDeferredBatch(nextBatch, lastBatch));
}
// this batch done
defr.done();
}
});
})
.catch(function (error) {
showNotification('Error: ' + nameXMLArray[x].filename + " " + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
showNotification('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
document.getElementById("showCheck").className = "results";
writeSelections("<b>You just built your document using<br/>the following components:</b><br/>");
}
return defr.promise;
}
我有 100 个左右的 Word Open XML(.xml,不是 .docx,另存为 "Word XML Document")存储在 SharePoint 上的文档(组件)。
我使用AJAX通过选择加载这些,如xml,1对多到一个数组中,我也在其中管理选择顺序.
一旦用户选择了 "components" 他们就可以将它们插入到 Word 中,插入是通过数组遍历完成的(可能有更好的方法来做到这一点 - 但现在它确实有效) ,
wordBuild 进行加载
function writeDocSync(){
// run through nameXMLArray to find the right sequence
var x = 0;
var countXMLAdds = 0;
//debugger;
toggleWriteButton("disable");
$('.progress-button').progressInitialize("Building Word");
toggleProgressBar(true);
// only run if we have data present
if(nameXMLArray.length > 0){
// increment through sequentially until we have all values
while (countXMLAdds <= checkedList.length){
// repeatedly traverse the array to get the next in sequence
while (x < nameXMLArray.length){
if (Number(nameXMLArray[x].position) === countXMLAdds && nameXMLArray[x].useStatus === true){
progHold = countXMLAdds;
wordBuild(nameXMLArray[x].xml, nameXMLArray[x].filename, countXMLAdds);
}
x++;
}
x=0;
countXMLAdds ++;
}
document.getElementById("showCheck").className = "results";
writeSelections("<b>You just built your proposal using<br/>the following components:</b><br/>");
toggleWriteButton("enable");
}
}
xxxxxxxxx
function wordBuild(xmlBody, nameDoc, progress){
var aryLN = checkedList.length;
var progPCT = (progress/aryLN)*100;
progressMeter.progressSet(progPCT);
Word.run(function (context) {
var currentDoc = context.document;
var body = currentDoc.body;
body.insertOoxml(xmlBody, Word.InsertLocation.end);
body.insertBreak(Word.BreakType.page, Word.InsertLocation.end);
return context.sync().then(function () {
showNotification("Written " + nameDoc);
});
})
.catch(function (error) {
showNotification('Error: ' + nameDoc + ' :' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
showNotification('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
所有文档将单独加载,所有文档将分批加载,例如 10 - 30 或更多。
当我加载整个集时出现问题(我有一个 "check all" 选项)。 有时在我得到异常之前会构建 50 个,有时是 60 个,很少超过 60 个,但偶尔我会遇到一个没有发生异常的间隙,然后它会在以后继续。
异常(对每个文件重复)是:
Debug info: {}
Error: componentABC.xml :{"name":"OfficeExtension.Error","code":"GeneralException","message":"An internal error has occurred.","traceMessages":[],"debugInfo":{},"stack":"GeneralException: An internal error has occurred.\n at Anonymous function (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:150094)\n at yi (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:163912)\n at st (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:163999)\n at d (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:163819)\n at c (https://customerportal.sharepoint.com/sites/components/Shared%20Documents/componentAssembler/Scripts/Office/1/word-win32-16.00.js:19:162405)"}
对于可能导致此问题的任何帮助,我们将不胜感激。
哦,我还应该说,引发异常的文件不会插入到Word中。但在较小的批次中 - 它们可以正常工作。
Word.run()
是一个异步调用,您可以进行的并发 Word.run()
调用的数量是有限制的。由于您在 while
循环中执行 Word.run()
,因此所有循环都会同时启动,并且 运行 同时启动。
有几种方法可以解决这个问题。
将所有内容放在一个
Word.run()
调用中。这会将所有内容放在一个巨大的批次中,避免多次往返调用 Word。if (nameXMLArray.length > 0 { Word.run(function(context) { //... while(...) { wordBuild(context, nameXMLArray[x].xml, nameXMLArray[x].filename, countXMLAdds); //... } return context.sync(); }); } function wordBuild(context, xmlBoxy, nameDoc, progress) { //everything as it currently is, except without the Word.run and the context.sync }
将 wordBuild 实现为承诺,并使用 AngularJS 的 $q 服务来链接承诺,大致如下所示:
function wordBuild(...) { var deferred = $q.defer(); Word.run( function(context) { // current code return context.sync().then(function() { deferred.resolve(); }); }); return deferred.promise; } //Somewhere else for (var x…) { promises.add(wordBuild); } $q.all(promises);
https://docs.angularjs.org/api/ng/service/$q
Angularjs $q.all
链接
wordBuild
调用自己,如下所示:var x = 0; var context; function (wordBuild() { if (x >= nameXMLArray.length) return; else { context.document.body.insertOoxml(ooxml, Word.InsertLocation.end); x++; return context.sync().then(wordBuild); } }); Word.run(function (ctx) { context = ctx; return wordBuild(); }
这种方法很难维护,但它可以工作。
顺便说一句,原始代码中的进度表仅在调用 Word 开始时更新,而不是实际 returns。您可能希望将进度表更新代码移动到回调中。
我最终使用了 jQuery 延迟,我已经在使用 jQuery 树视图和复选框等,所以这是有道理的。
这是 Geoffrey 的建议和我自己的建议的结合!我不能说它是好的代码,只有这样才行得通。 (如果是好的代码,我会花更多的时间去理解!)
我 运行 批 49 xml 文档插入,在 51 处异步调用 "Word.run" 在测试中失败,并且在一个 Word.run 中插入 80 个左右的文档导致 Word 冻结,因此尽管未证明 1 Word.run 内有 49 个插入似乎是 10 个的良好入门! 49 件中的 50 个插入允许 2450 个插入,这超出了我认为需要的任何内容,并且可能会破坏 Word!
为了让 deferreds 和 sent 变量在作为异步 deferreds 启动后保持它们的值,我必须创建一个变量来传输新的 deferreds 和值,所以我可以使用 "bind" 命令。 作为 Word async returns context.sync() 我检查批次的计数,当批次完成时,我然后调用下一批次 - 在 context.sync()
一种递归调用,仍然是 Geoffrey 的建议和批处理的组合。这具有 50 个批次的 49 个文档部分的理论限制。到目前为止,这在所有测试中都有效。
进度表存在于它自己的定时调用中,但由于 JavaScript 代码优先于 UI 它确实会跳转。例如 120 个文档,它会相当快地跳到一半以下,然后过一会儿跳到几乎完成,然后完成(有效地快速连续百分比增加 3 跳,建议的各种技巧效果为零(forceRepaint() 是最新的实验!)。
function startUILock(){
// batch up in groups of 49 documents (51 and more were shown to fail, 49 gives manouvre room)
toggleProgressBar(true);
$('.progress-button').progressInitialize("Building Word");
progressMeter.progressSet(1);
$.blockUI({message: "Building word..."});
setTimeout(forceRepaint, 3000);
}
function forceRepaint(){
var el = document.getElementById('progDiv');
el.style.cssText += ';-webkit-transform:rotateZ(0deg)';
el.offsetHeight;
el.style.cssText += ';-webkit-transform:none';
}
function UIUnlock(insertedCount){
debugger;
var pct = (insertedCount/checkedList.length)*100
//showNotification('Progress percent is: ' + pct);
if (insertedCount !== checkedList.length ){
progressMeter.progressSet(pct);
forceRepaint();
} else {
$.unblockUI();
progressMeter.progressSet(100);
}
}
function writeDocDeffered(){
insertedCounter = 0;
var lastBatch = 0;
var x = 49;
var z = checkedList.length + 1;
if(x > z){
x=z;
}
deferreds = buildDeferredBatch(x, lastBatch);
$.when(deferreds).done(function () {
return;
})
.fail(function () {
//showNotification('One of our promises failed');
});
}
function buildDeferredBatch(batch, lastBatch) {
// this ensures the variables remain as issued - allows use of "bind"
var deferredsa = [];
var docSender = {
defr : $.Deferred(),
POSITION: batch,
LASTPOSITION: lastBatch,
runMe : function(){
this.defr.resolve(writeDocBatchedDeferred(this.POSITION, this.LASTPOSITION, this.defr));
}
}
// small timeout might not be required
deferredsa.push(setTimeout(docSender.runMe.bind(docSender), 10));
return deferredsa;
}
function writeDocBatchedDeferred(batch, lastBatch, defr){
// write the batches using deferred and promises
var x;
var countXMLAdds = lastBatch;
x = 0;
var fileName;
debugger;
// only run if we have data present
if(nameXMLArray.length > 0){
var aryLN = checkedList.length;
// increment through sequentially until we have all values
Word.run(function (context) {
var currentDoc = context.document;
var body = currentDoc.body;
while (countXMLAdds <= batch){
// repeatedly traverse the array to get the next in sequence
while (x < nameXMLArray.length){
if (Number(nameXMLArray[x].position) === countXMLAdds && nameXMLArray[x].useStatus === true){
fileName = nameXMLArray[x].filename;
body.insertOoxml(nameXMLArray[x].xml, Word.InsertLocation.end);
body.insertBreak(Word.BreakType.page, Word.InsertLocation.end);
insertedCounter = countXMLAdds;
var latest = insertedCounter;
var timerIt = {
LATEST: latest,
runMe : function(){
UIUnlock(this.LATEST);
}
}
setTimeout(timerIt.runMe.bind(timerIt),1000);
}
x++;
}
x=0;
countXMLAdds ++;
}
return context.sync().then(function () {
if(countXMLAdds = batch){
var lastBatch = batch + 1;
// set for next batch
var nextBatch = batch + 50;
var totalBatch = checkedList.length + 1;
// do not exceed the total batch
if(nextBatch > totalBatch){
nextBatch=totalBatch;
}
// any left to process keep going
if (nextBatch <= totalBatch && lastBatch < nextBatch){
deferreds = deferreds.concat(buildDeferredBatch(nextBatch, lastBatch));
}
// this batch done
defr.done();
}
});
})
.catch(function (error) {
showNotification('Error: ' + nameXMLArray[x].filename + " " + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
showNotification('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
document.getElementById("showCheck").className = "results";
writeSelections("<b>You just built your document using<br/>the following components:</b><br/>");
}
return defr.promise;
}