2016-05-17 12 views
2

Ich habe ein Aufgabenbereich-Add-In für Word erstellt, das eine Suche ausführt und Informationen zu den Ergebnissen als Liste für den Benutzer anzeigt. Wenn der Benutzer auf ein Element in der Liste klickt, möchte ich den Bereich in Wort auswählen, um dem Benutzer den Standort des Elements anzuzeigen. Das Add-in ermöglicht es dem Benutzer dann, zusätzliche Aufgaben für den Bereich auszuführen, z. B. die Schriftfarbe zu ändern.Wie kann ein Bereich in verschiedenen Word.run-Kontexten verwendet werden?

Ich bin in der Lage, die Suche und erhalten Bereiche für die Anzeige mit der Funktion unten ausgeführt wird:

function runSearch(textToFind) { 
    var items = []; 
    return Word.run(function(context) { 
    var options = Word.SearchOptions.newObject(context); 
    options.matchWildCards = false; 

    var rangesFind = context.document.body.search(textToFind, options); 
    context.load(rangesFind, 'text, font, style'); 
    return context.sync().then(function() { 
     for (var i = 0; i < rangesFind.items.length; i++) { 
     items.push(rangesFind.items[i]); 
     context.trackedObjects.add(rangesFind.items[i]); 
     } 
     return context.sync(); 
    }); 
    }) 
    .then(function() { 
    return items; 
    }); 
}; 

Jedoch habe ich Schwierigkeiten, den Bereich auf Benutzer klicken Sie die Auswahl habe. Ich habe versucht, die Bereiche Zusammenhang mit:

function selectRange(range){ 
    range.select(); 
    return range.context.sync(); 
} 

oder den Bereich in einem neuen Word.run Zusammenhang mit:

function selectRange(range){ 
    return Word.run(function(context) { 
    context.load(range); 
    return context.sync().then(function(){ 
     range.select(); 
     return context.sync(); 
    }); 
    }); 
} 

ich auf ein mögliche Verfahren gekommen, dass eine Inhaltskontrolle für jede umfasst das Erstellen Suche Ergebnis und dann neu laden alle Inhaltskontrollen in der selectRange Funktion im neuen Kontext und finde das passende Steuerelement, aber das scheint sehr ineffizient, wenn ich den Bereich bereits habe.

Was ist die beste Methode für die Wiederverwendung eines Bereichs über verschiedene Word.run-Kontexte?

Antwort

4

Sie können kein Objekt über Word.run Aufrufe hinweg verwenden. Word.run erstellt bei jedem Aufruf einen neuen Kontext, während das ursprüngliche Objekt an seinen eigenen Kontext gebunden ist, wodurch eine Nichtübereinstimmung entsteht.

aber sagen, dass Sie absolut kann, aus einem Word.run, fügen Sie die Objekte, die Sie context.trackedObjects.add(obj) wünschen, und sie bleiben als Objekte auch nach Word.run Arbeits beendet haben sollte. Mit "Arbeitsobjekten" meine ich, dass ihr Pfad nicht ungültig gemacht wird (denke etwas Ähnliches wie Garbage Collection, aber für entfernte Objekte).

Sobald Sie ein solches Objekt haben (und es sieht oben wie Sie tun), sollten Sie in der Lage sein

range.select(); 
range.context.sync().catch(...); 

anrufen Wenn es nicht für Sie arbeiten, können Sie ein Beispiel für den Fehler liefern du bist bekommen?

Der Vollständigkeit halber sollte ich beachten, dass Sie die Speicherverwaltung dieser Objekte in die eigenen Hände nehmen, sobald Sie der trackedObjects-Sammlung Objekte hinzugefügt haben. Dies bedeutet, dass Sie verlangsamen werden, wenn Sie den Speicher nicht ordnungsgemäß freigeben, indem Sie die Speicher-/Bereichseinstellungskette herunterfahren. Wenn Sie die verfolgten Objekte also nicht mehr verwenden, rufen Sie obj.context.trackedObjects.remove(obj), gefolgt von obj.context.sync(), auf. Vergessen Sie nicht den letzten Teil - wenn Sie keine Synchronisierung durchführen, wird Ihre Anforderung zum Entfernen der verfolgten Objekte nicht gesendet, und Sie verbrauchen weiterhin den Speicher.

======= ======= Update 1

Tom, danke für die Fehlermeldung bereitstellt. Es sieht so aus, als wäre dies ein Fehler in der Word-Implementierung der APIs - ich werde das weiterverfolgen, und jemand könnte sich bei weiteren Fragen an Sie wenden.

Aus konzeptioneller Sicht sind Sie absolut auf dem richtigen Weg - und die folgenden funktioniert in Excel, zum Beispiel:

var range; 
Excel.run(function (ctx) { 
    var sheet = ctx.workbook.worksheets.getActiveWorksheet(); 

    range = sheet.getRange("A5"); 
    range.values = [[5]]; 
    ctx.trackedObjects.add(range); 

    return ctx.sync(); 
}) 
.then(function(){ 
    setTimeout(function() { 
     range.select(); 
     range.context.trackedObjects.remove(range); 
     range.context.sync(); 
    }, 2000); 
}) 
.catch(function (error) { 
    showMessage("Error: " + error);   
}); 

======= Update 2 ==== ===

Es stellt sich heraus, dass es tatsächlich einen Fehler im Produkt gibt. Die gute Nachricht ist jedoch, dass es mit einem JavaScript-Fix nur leicht zu beheben ist, und wir werden dies in den nächsten Wochen tun, indem wir das CDN aktualisieren.

Bei dem Update, der folgende Code funktioniert:

var paragraph; 
Word.run(function (ctx) { 
    var p = ctx.document.body.paragraphs.first; 
    paragraph = p.next; 
    ctx.trackedObjects.add(paragraph); 
    return ctx.sync(); 
}) 
.then(function(){ 
    setTimeout(function() { 
     paragraph.select(); 
     paragraph.context.trackedObjects.remove(paragraph); 
     paragraph.context.sync() 
      .then(function() { 
       console.log("Done"); 
      }) 
      .catch(handleError); 
    }, 2000); 
}) 
.catch(handleError); 

function handleError (error) { 
    console.log('Error: ' + JSON.stringify(error)); 
    if (error instanceof OfficeExtension.Error) { 
     console.log('Debug info: ' + JSON.stringify(error.debugInfo)); 
    } 
} 

Wollen Sie noch bessere Nachricht? Bis das CDN aktualisiert wurde, können Sie den folgenden Code verwenden, um die JavaScript-Bibliothek zu "patchen" und den obigen Code auszuführen. Sie sollten diesen Code einige Zeit ausführen, nachdem Office.js bereits geladen wurde (d. H. Innerhalb Ihrer Office.initialize-Funktion) und bevor Sie eine Word.run ausführen.

var TrackedObjects = (function() { 
    function TrackedObjects(context) { 
     this._autoCleanupList = {}; 
     this.m_context = context; 
    } 
    TrackedObjects.prototype.add = function (param) { 
     var _this = this; 
     if (Array.isArray(param)) { 
      param.forEach(function (item) { return _this._addCommon(item, true); }); 
     } 
     else { 
      this._addCommon(param, true); 
     } 
    }; 
    TrackedObjects.prototype._autoAdd = function (object) { 
     this._addCommon(object, false); 
     this._autoCleanupList[object._objectPath.objectPathInfo.Id] = object; 
    }; 
    TrackedObjects.prototype._addCommon = function (object, isExplicitlyAdded) { 
     if (object[OfficeExtension.Constants.isTracked]) { 
      if (isExplicitlyAdded && this.m_context._autoCleanup) { 
       delete this._autoCleanupList[object._objectPath.objectPathInfo.Id]; 
      } 
      return; 
     } 
     var referenceId = object[OfficeExtension.Constants.referenceId]; 
     if (OfficeExtension.Utility.isNullOrEmptyString(referenceId) && object._KeepReference) { 
      object._KeepReference(); 
      OfficeExtension.ActionFactory.createInstantiateAction(this.m_context, object); 
      if (isExplicitlyAdded && this.m_context._autoCleanup) { 
       delete this._autoCleanupList[object._objectPath.objectPathInfo.Id]; 
      } 
      object[OfficeExtension.Constants.isTracked] = true; 
     } 
    }; 
    TrackedObjects.prototype.remove = function (param) { 
     var _this = this; 
     if (Array.isArray(param)) { 
      param.forEach(function (item) { return _this._removeCommon(item); }); 
     } 
     else { 
      this._removeCommon(param); 
     } 
    }; 
    TrackedObjects.prototype._removeCommon = function (object) { 
     var referenceId = object[OfficeExtension.Constants.referenceId]; 
     if (!OfficeExtension.Utility.isNullOrEmptyString(referenceId)) { 
      var rootObject = this.m_context._rootObject; 
      if (rootObject._RemoveReference) { 
       rootObject._RemoveReference(referenceId); 
      } 
      delete object[OfficeExtension.Constants.isTracked]; 
     } 
    }; 
    TrackedObjects.prototype._retrieveAndClearAutoCleanupList = function() { 
     var list = this._autoCleanupList; 
     this._autoCleanupList = {}; 
     return list; 
    }; 
    return TrackedObjects; 
}()); 
OfficeExtension.TrackedObjects = TrackedObjects; 

Hoffe, das hilft!

~ Michael Zlatkovsky, Entwickler auf Office-Extensibility Team, MSFT

+0

Als ich rufen 'range.context.sync()' in der oben bekomme ich folgende Fehlermeldung: 'GeneralException: GeneralException { [Funktionen]:, __proto__: {}, Code:„GeneralException “ debuginfo: { [Funktionen]:, __proto__: {}, errorLocation: "Document._GetObjectByReferenceId" }, Nachricht: "GeneralException", Name: "OfficeExtension.Error", traceMessages: [] } ' –

+0

Se e meine zwei Updates oben. –

0

Neben den TrackedObjects fixieren die runSearch Methode, um die Reichweite des search benötigt Aktualisierung eher zu bekommen, als direkt die Suche länger verwenden.

function runSearch(textToFind) { 
    var items = []; 
    return Word.run(function(context) { 
    var options = Word.SearchOptions.newObject(context); 
    options.matchWildCards = false; 

    var rangesFind = context.document.body.search(textToFind, options); 
    context.load(rangesFind); 
    return context.sync().then(function() { 
     for (var i = 0; i < rangesFind.items.length; i++) { 
     var range = rangesFind.items[i].getRange(); 
     context.load(range, 'text'); 
     items.push(range); 
     context.trackedObjects.add(items[items.length-1]); 
     } 
     return context.sync(); 
    }); 
    }) 
    .then(function() { 
    return items; 
    }); 
}; 
Verwandte Themen