2017-07-25 5 views
0

Ich versuche, eine Funktion zu schreiben, die eine Liste von Rich Text Content Controls und eine einzelne Zeichenfolge als Argument enthält und den Inhalt aller übereinstimmenden Inhaltssteuerelemente durch diese Zeichenfolge ersetzt.Wie ersetzen Sie den Text in einer großen Anzahl von Inhaltskontrollen über Word-js?

Während dies mit einer kleineren Menge von Inhaltssteuerelementen funktioniert, schlägt es bei Dokumenten mit einer großen Menge von ihnen fehl. Ich muss mit Dokumenten mit über 700 Content Controls mit einzelnen Titeln arbeiten. In diesem Fall ersetzt der Code nur die ersten 66X CCs und bricht dann mit einer GeneralException ab. Ich nehme an, dies ist nur wegen der riesigen Menge an Inhaltskontrollen. Ich habe ähnliche Probleme, wenn ich versuche, Bindungen für alle diese CCs zu registrieren (GeneralException). Aber das ist ein anderes Thema.

Ich habe versucht, dieses Problem zu umgehen, indem Sie die Anzahl der Änderungen pro .sync() und das Durchlaufen der CCs begrenzen und so viele Schleifen wie nötig durchführen. Dies ist jedoch aufgrund der asynchronen Natur von Office-js nicht so einfach. Ich bin mit Javascript-Async-Versprechen-Programmierung bisher nicht sehr vertraut. Aber das ist, was ich habe:

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; 
    }); 
} 

Allerdings ... es funktioniert nicht. Es ersetzt die ersten 100 CCs und stoppt dann. Ohne einen Fehler, ohne Ausnahme oder irgendetwas. Die return loop(replaceCounter, CClist); wird einfach nicht ausgeführt und ich weiß nicht warum. Wenn ich versuche, diese Zeile im Debugger zu betreten, wirft es mich irgendwo in den Office-js-Code.

Irgendwelche Vorschläge?

Edit:

ich meinen Code aktualisiert auf der Grundlage der Vorschläge von Juan Balmori und es funktioniert wie ein Charme:

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)); 
     } 
    }); 
} 

Es dauert noch immer 13.995 ms abgeschlossen ist, aber zumindest funktioniert es :-)

Irgendwelche Ideen, was die GeneralException provozierte?

gab ich eine neue Frage in Bezug auf die Geschwindigkeit Frage: What is the fastest way of replacing the text of many content controls via office-js?

Antwort

1

gute Frage .. ich einige perf Test vor langer Zeit tat, und ich konnte mehr als 10k Inhalt Steuerelemente in einem Dokument ändern. mit 700 solltest du ok sein. Nicht sicher, warum Sie eine Liste ausfüllen, die nicht benötigt wird, Sie navigieren tatsächlich 2 Mal die Sammlung, die nicht gut für Perf ist. Sie können den Stringvergleich durchführen, während Sie die Sammlung durchlaufen!

Hier ist ein Beispiel, ich habe gerade einen schnellen Test mit einem 700 Inhaltskontrolldokument mit einem hypothetischen Tag von "test" gemacht.

Ich konnte 1. Vergleichen Sie ihren Text mit allem, was Sie es vergleichen möchten (es ist eine Zeichenfolge) 2. Ändern Sie den Wert, wenn die Bedingung erfüllt ist.

Es dauerte 5134 Millisekunden, um den Vorgang abzuschließen, und hier ist der Code. was ich denke, es ist durchaus akzeptabel.

Hoffe, das hilft!

function perfContentControls() { 
 
     var time1 = Date.now(); // lets see in how much time we complete the operation :) 
 
     var CCs =0 
 
     Word.run(function (context) { 
 
      var myCCs = context.document.body.contentControls.getByTag("test"); 
 
      context.load(myCCs); 
 
      return context.sync() 
 
      .then(function() { 
 
       CCs = myCCs.items.length 
 
       for (var i = 0; i < CCs; i++) { 
 
        if (myCCs.items[i].text == "new text 3") // you can check the cc content and if needed replace it.... 
 
         myCCs.items[i].insertText("new text 4", "replace"); 
 
       
 
       } 
 

 
       return context.sync() 
 
       .then(function() { 
 
        var time2 = Date.now(); 
 
        var diff = time2 - time1; 
 
        console.log("# of CCs:" + CCs + " time to change:" + diff + "ms"); 
 
       }) 
 
      }) 
 
      .catch(function (er) { 
 
       console.log(er.message); 
 

 
      }) 
 

 
     }) 
 

 
    }

+0

Ich habe nach Titel einzelner Inhalte Kontrollen zuzugreifen, weil der nächste Schritt sein, sollten die einzelnen Inhalte für alle diese zur Verfügung zu stellen, den Titel basiert. Ich werde versuchen, meine Funktion basierend auf Ihren Vorschlägen neu zu erstellen, die Änderungszeit zu berechnen und meinen Beitrag zu aktualisieren. –

Verwandte Themen