Anwendungsspezifisches API-Modell
In diesem Artikel wird beschrieben, wie Sie das API-Modell zum Erstellen von Add-Ins in Excel, OneNote, PowerPoint, Visio und Word verwenden. Es werden Kernkonzepte vorgestellt, die für die Verwendung der auf versprechenbasierten APIs von grundlegender Bedeutung sind.
Hinweis
Dieses Modell wird von Outlook- oder Project-Clients nicht unterstützt. Verwenden Sie das allgemeine API-Modell , um mit diesen Anwendungen zu arbeiten. Vollständige Hinweise zur Plattformverfügbarkeit finden Sie unter Office-Clientanwendung und Plattformverfügbarkeit für Office-Add-Ins.
Tipp
Die Beispiele auf dieser Seite verwenden die Excel-JavaScript-APIs, aber die Konzepte gelten auch für OneNote, PowerPoint, Visio und Word JavaScript-APIs. Vollständige Codebeispiele, die zeigen, wie Sie diese und andere Konzepte in verschiedenen Office-Anwendungen verwenden können, finden Sie unter Office-Add-In-Codebeispiele.
Asynchrone Art der versprechenbasierten APIs
Office-Add-Ins sind Websites, die in einem Webview-Steuerelement in Office-Anwendungen wie Excel angezeigt werden. Dieses Steuerelement ist in die Office-Anwendung auf desktopbasierten Plattformen wie Office unter Windows eingebettet und wird in einem HTML-iframe in Office im Web ausgeführt. Aufgrund von Leistungsaspekten können die Office.js-APIs nicht auf allen Plattformen synchron mit den Office-Anwendungen interagieren. Daher gibt der sync()
API-Anfruf in Office.js ein Versprechen zurück, das aufgelöst wird, wenn die Office-Anwendung die angeforderten Lese- oder Schreibaktionen abschließt. Sie können auch mehrere Aktionen in die Warteschlange stellen, z. B. Eigenschaften festlegen oder Methoden aufrufen, und diese als Batch von Befehlen mit einem einzigen Aufruf an sync()
ausführen, anstatt für jede Aktion eine separate Anforderung zu senden. In den folgenden Abschnitten wird beschrieben, wie dies mithilfe von run()
und sync()
APIs erreicht wird.
*.run-Funktion
Excel.run
, OneNote.run
, PowerPoint.run
und Word.run
führen eine Funktion aus, die die Aktionen angibt, die für Excel, Word und OneNote ausgeführt werden sollen.
*.run
erstellt automatisch einen Anforderungskontext, mit dem Sie mit Office-Objekten interagieren können. Nach Abschluss von *.run
wird ein Versprechen aufgelöst und alle Objekte, die zur Laufzeit zugewiesen wurden, werden automatisch freigegeben.
Das folgende Beispiel zeigt die Verwendung von Excel.run
. Das gleiche Muster wird auch für OneNote, PowerPoint, Visio und Word verwendet.
Excel.run(function (context) {
// Add your Excel JS API calls here that will be batched and sent to the workbook.
console.log('Your code goes here.');
}).catch(function (error) {
// Catch and log any errors that occur within `Excel.run`.
console.log('error: ' + error);
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
Anforderungskontext
Die Office-Anwendung und Ihr Add-In werden in verschiedenen Prozessen ausgeführt. Da Add-Ins unterschiedliche Laufzeitumgebungen verwenden, benötigen sie ein RequestContext
-Objekt, um Ihr Add-In mit Objekten in Office wie Arbeitsblättern, Bereichen, Absätzen und Tabellen zu verbinden. Dieses RequestContext
Objekt wird beim Aufruf als Argument angegeben *.run
.
Proxyobjekte
Die Office-JavaScript-Objekte, die Sie deklarieren und mit den versprechenbasierten APIs verwenden, sind Proxy-Objekte. Alle Methoden, die Sie aufrufen, oder Eigenschaften, die Sie auf Proxyobjekte festlegen oder laden, werden einfach zu einer Warteschlange mit ausstehenden Befehlen hinzugefügt. Wenn Sie die sync()
-Methode aufrufen, beispielsweise im Anforderungskontext context.sync()
, werden die Befehle in der Warteschlange an die Office-Anwendung gesendet und ausgeführt. Diese APIs sind grundsätzlich batchzentriert. Sie können beliebig viele Änderungen im Anforderungskontext in die Warteschlange stellen und dann die sync()
-Methode aufrufen, um den Batch von Befehlen in der Warteschlange auszuführen.
Das folgende Codeausschnitt deklariert beispielsweise das lokale JavaScript Excel.Range-Objekt, selectedRange
um auf einen ausgewählten Bereich in der Excel-Arbeitsmappe zu verweisen, und legt dann einige Eigenschaften für dieses Objekt fest. Das selectedRange
-Objekt ist ein Proxy-Objekt, sodass die festgelegten Eigenschaften und die Methode, die für dieses Objekt aufgerufen wird, erst bei Ihren Add-In-Aufrufen context.sync()
im Excel-Dokument angezeigt werden.
const selectedRange = context.workbook.getSelectedRange();
selectedRange.format.fill.color = "#4472C4";
selectedRange.format.font.color = "white";
selectedRange.format.autofitColumns();
Leistungstipp: Minimieren Sie die Anzahl der erstellten Proxy-Objekte
Vermeiden Sie das wiederholte Erstellen desselben Proxyobjekts. Wenn Sie stattdessen dasselbe Proxyobjekt für mehrere Vorgänge benötigen, erstellen Sie es einmal, weisen Sie es einer Variablen zu, und verwenden Sie diese Variable in Ihrem Code.
// BAD: Repeated calls to .getRange() to create the same proxy object.
worksheet.getRange("A1").format.fill.color = "red";
worksheet.getRange("A1").numberFormat = "0.00%";
worksheet.getRange("A1").values = [[1]];
// GOOD: Create the range proxy object once and assign to a variable.
const range = worksheet.getRange("A1");
range.format.fill.color = "red";
range.numberFormat = "0.00%";
range.values = [[1]];
// ALSO GOOD: Use a "set" method to immediately set all the properties
// without even needing to create a variable!
worksheet.getRange("A1").set({
numberFormat: [["0.00%"]],
values: [[1]],
format: {
fill: {
color: "red"
}
}
});
sync()
Durch Aufrufen der sync()
-Methode im Anforderungskontext wird der Status zwischen Proxy-Objekten und Objekten im Office-Dokument synchronisiert. Die sync()
Methode führt alle Befehle aus, die im Anforderungskontext in die Warteschlange gestellt werden, und ruft Werte für alle Eigenschaften ab, die in die Proxy-Objekte geladen werden sollen. Die sync()
Methode wird asynchron ausgeführt und gibt ein Versprechen zurück, das nach Abschluss der sync()
-Methode aufgelöst wird.
Das folgende Beispiel zeigt eine Batch-Funktion, die ein lokales JavaScript-Proxyobjekt definiert (selectedRange
), eine Eigenschaft dieses Objekts lädt und anschließend das Muster des JavaScript-Versprechens verwendet, um context.sync()
dazu aufzurufen, den Zustand zwischen den Proxyobjekten und den Objekten im Excel-Dokument zu synchronisieren.
await Excel.run(async (context) => {
const selectedRange = context.workbook.getSelectedRange();
selectedRange.load('address');
await context.sync();
console.log('The selected range is: ' + selectedRange.address);
});
Im vorherigen Beispiel wird selectedRange
festgelegt und seine address
-Eigenschaft beim Aufruf von context.sync()
geladen.
Da sync()
ein asynchroner Vorgang ist, sollten Sie das Promise
-Objekt immer zurückgeben, um sicherzustellen, dass der sync()
-Vorgang abgeschlossen ist, bevor das Skript weiter ausgeführt wird. Wenn Sie TypeScript oder ES6 + JavaScript verwenden, können Sie den context.sync()
-Aufruf await
, anstatt das Versprechen zurückzugeben.
Leistungstipp: Minimieren Sie die Anzahl der Synchronisierungsaufrufe
In der Excel-JavaScript-API ist sync()
der einzige asynchrone Vorgang, der unter bestimmten Umständen langsam sein kann, insbesondere für Excel im Web. Um die Leistung zu optimieren, minimieren Sie die Anzahl der Aufrufe auf sync()
, indem Sie vor dem Aufrufen so viele Änderungen wie möglich in die Warteschlange stellen. Weitere Informationen zum Optimieren der Leistung mit sync()
finden Sie unter Vermeiden der Verwendung der context.sync-Methode in Schleifen.
load()
Bevor Sie die Eigenschaften eines Proxy-Objekts lesen können, müssen Sie die Eigenschaften explizit laden, um das Proxy-Objekt mit Daten aus dem Office-Dokument zu füllen, und dann context.sync()
aufrufen. Wenn Sie beispielsweise ein Proxy-Objekt erstellen, um auf einen ausgewählten Bereich zu verweisen, und dann die address
-Eigenschaft des ausgewählten Bereichs lesen möchten, müssen Sie die address
-Eigenschaft laden, bevor Sie diese lesen können. Um das Laden von Eigenschaften eines Proxy-Objekts anzufordern, rufen Sie die load()
-Methode für das Objekt auf und geben Sie die zu ladenden Eigenschaften an. Das folgende Beispiel zeigt die Range.address
-Eigenschaft, das für myRange
geladen wird.
await Excel.run(async (context) => {
const sheetName = 'Sheet1';
const rangeAddress = 'A1:B2';
const myRange = context.workbook.worksheets.getItem(sheetName).getRange(rangeAddress);
myRange.load('address');
await context.sync();
console.log (myRange.address); // ok
//console.log (myRange.values); // not ok as it was not loaded
console.log('done');
});
Hinweis
Wenn Sie nur Methoden aufrufen oder Eigenschaften für ein Proxyobjekt festlegen, müssen Sie die load()
-Methode nicht aufrufen. Die load()
-Methode ist nur erforderlich, wenn Sie Eigenschaften für ein Proxy-Objekt lesen möchten.
Genau wie Anforderungen zum Festlegen von Eigenschaften oder Aufrufen von Methoden für Proxyobjekte werden Anforderungen zum Laden von Eigenschaften für Proxyobjekte der Warteschlange der ausstehenden Befehle im Anforderungskontext hinzugefügt, die beim nächsten Aufruf der sync()
-Methode ausgeführt wird. Sie können so viele load()
Aufrufe wie erforderlich im Anforderungskontext in die Warteschlange stellen.
Skalare und Navigationseigenschaften
Es gibt zwei Kategorien von Eigenschaften: skalare Eigenschaften und Navigationseigenschaften. Skalare Eigenschaften sind zuweisbare Typen wie Zeichenfolgen, ganze Zahlen und JSON-Strukturen. Navigationseigenschaften sind schreibgeschützte Objekte und Sammlungen von Objekten, denen Felder zugewiesen wurden, anstatt die Eigenschaft direkt zuzuweisen. Beispielsweise sind name
und position
Mitglieder im Excel.Worksheet-Objekt skalare Eigenschaften, während protection
und tables
Navigationseigenschaften sind.
Ihr Add-In kann Navigationseigenschaften als Pfad zum Laden bestimmter Skalareigenschaften verwenden. Der folgende Code stellt einen load
-Befehl für den Namen der von einem Excel.Range
-Objekt verwendeten Schriftart in die Warteschlange, ohne andere Informationen zu laden.
someRange.load("format/font/name")
Sie können die Skalareigenschaften einer Navigationseigenschaft auch festlegen, indem Sie den Pfad durchlaufen. Beispielsweise können Sie die Schriftgröße für Excel.Range
mithilfe von someRange.format.font.size = 10;
festlegen. Sie müssen die Eigenschaft nicht laden, bevor Sie diese festlegen.
Bitte beachten Sie, dass einige der Eigenschaften unter einem Objekt möglicherweise denselben Namen wie ein anderes Objekt haben. Zum Beispiel ist format
eine Eigenschaft unter dem Excel.Range
-Objekt, aber format
selbst ist auch ein Objekt. Wenn Sie also einen Aufruf wie range.load("format")
tätigen, entspricht dies range.format.load()
(einer unerwünschten leeren load()
-Anweisung). Um dies zu vermeiden, sollte Ihr Code nur die "Blattknoten" in einen Objektbaum laden.
Laden aus einer Sammlung
Wenn Sie mit einer Auflistung arbeiten, verwenden Sie load
für die Auflistung, um Eigenschaften für jedes Objekt in der Auflistung zu laden. Verwenden Sie load
genau wie für ein einzelnes Objekt in dieser Auflistung.
Der folgende Beispielcode zeigt die Eigenschaft, die name
für jedes Diagramm im Arbeitsblatt "Sample" geladen und protokolliert wird.
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getItem("Sample");
const chartCollection = sheet.charts;
// Load the name property on every chart in the chart collection.
chartCollection.load("name");
await context.sync();
chartCollection.items.forEach((chart) => {
console.log(chart.name);
});
});
Normalerweise schließen Sie die items
-Eigenschaft der Auflistung nicht in die load
Argumente ein. Alle Elemente werden geladen, wenn Sie Elementeigenschaften laden. Wenn Sie jedoch eine Schleife über die Elemente in der Auflistung ausführen, aber keine bestimmte Eigenschaft der Elemente laden müssen, müssen Sie die items
-Eigenschaft verwendenload
.
Der folgende Beispielcode zeigt die Eigenschaft, die name
für jedes Diagramm im Arbeitsblatt "Sample" festgelegt wird.
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getItem("Sample");
const chartCollection = sheet.charts;
// Load the items property from the chart collection to set properties on individual charts.
chartCollection.load("items");
await context.sync();
chartCollection.items.forEach((chart, index) => {
chart.name = `Sample chart ${index}`;
});
});
Aufrufen von load
ohne Parameter (nicht empfohlen)
Wenn Sie die load()
-Methode für ein Objekt (oder eine Sammlung) aufrufen, ohne Parameter anzugeben, werden alle skalaren Eigenschaften des Objekts oder der Objekte der Sammlung geladen. Das Laden nicht benötigter Daten verlangsamt Ihr Add-In. Sie sollten immer explizit angeben, welche Eigenschaften geladen werden sollen.
Wichtig
Die Menge der Daten, die von einer parameterlosen load
-Anweisung zurückgegeben werden, kann die Größenbeschränkungen des Diensts überschreiten. Um die Risiken für ältere Add-Ins zu verringern, werden einige Eigenschaften nicht von load
zurückgegeben, ohne dass diese explizit angefordert werden. Die folgenden Eigenschaften sind von solchen Ladevorgängen ausgeschlossen.
Excel.Range.numberFormatCategories
ClientResult
Methoden in den auf Versprechen basierenden APIs, die primitive Typen zurückgeben, weisen ein ähnliches Muster wie das load
/sync
-Paradigma auf.
Excel.TableCollection.getCount
ruft zum Beispiel die Anzahl von Tabellen in der Auflistung ab.
getCount
gibt ein ClientResult<number>
zurück, was bedeutet, dass die value
-Eigenschaft in der zurückgegebenen ClientResult
eine Zahl ist. Ihr Skript kann erst auf diesen Wert zugreifen, wenn context.sync()
aufgerufen wird.
Der folgende Code ruft die Gesamtzahl der Tabellen in einer Excel-Arbeitsmappe ab und protokolliert diese Nummer in der Konsole.
const tableCount = context.workbook.tables.getCount();
// This sync call implicitly loads tableCount.value.
// Any other ClientResult values are loaded too.
await context.sync();
// Trying to log the value before calling sync would throw an error.
console.log (tableCount.value);
set()
Das Festlegen von Eigenschaften für ein Objekt mit geschachtelten Navigationseigenschaften kann umständlich sein. Alternativ zum Festlegen einzelner Eigenschaften mithilfe von Navigationspfaden wie oben beschrieben können Sie die object.set()
-Methode verwenden, die für Objekte in den auf Versprechen basierenden JavaScript-APIs verfügbar ist. Mit dieser Methode können Sie mehrere Eigenschaften eines Objekts gleichzeitig festlegen, indem Sie entweder ein anderes Objekt des gleichen Office-Typs oder ein JavaScript-Objekt mit Eigenschaften übergeben, die wie die Eigenschaften des Objekts strukturiert sind, für das die Methode aufgerufen wird.
Im folgenden Codebeispiel werden mehrere Formateigenschaften eines Bereichs festgelegt, indem die set()
-Methode aufgerufen und ein JavaScript-Objekt mit Eigenschaftennamen und -typen übergeben wird, die die Struktur der Eigenschaften im Range
Objekt Spiegel. In dem Beispiel wird davon ausgegangen, dass im Bereich B2:E2 Daten vorhanden sind.
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getItem("Sample");
const range = sheet.getRange("B2:E2");
range.set({
format: {
fill: {
color: '#4472C4'
},
font: {
name: 'Verdana',
color: 'white'
}
}
});
range.format.autofitColumns();
await context.sync();
});
Einige Eigenschaften können nicht direkt festgelegt werden
Einige Eigenschaften können nicht festgelegt werden, obwohl sie beschreibbar sind. Diese Eigenschaften sind Teil einer übergeordneten Eigenschaft, die als einzelnes Objekt festgelegt werden muss. Dies liegt daran, dass diese übergeordnete Eigenschaft von den Untereigenschaften abhängt, die bestimmte logische Beziehungen haben. Diese übergeordneten Eigenschaften müssen mithilfe der Objekt-Literalnotation festgelegt werden, um das gesamte Objekt festzulegen, anstatt die einzelnen Untereigenschaften des Objekts. Ein Beispiel hierfür finden Sie in PageLayout. Die zoom
-Eigenschaft muss mit einem einzelnen PageLayoutZoomOptions-Objekt festgelegt werden, wie hier gezeigt.
// PageLayout.zoom.scale must be set by assigning PageLayout.zoom to a PageLayoutZoomOptions object.
sheet.pageLayout.zoom = { scale: 200 };
Im vorherigen Beispiel könnten Sie nicht direkt einen Wert zuweisen zoom
: sheet.pageLayout.zoom.scale = 200;
. Diese Anweisung löst einen Fehler aus, da zoom
nicht geladen wird. Selbst wenn zoom
geladen werden sollte, wird der Skalensatz nicht effektiv. Alle Kontextvorgänge werden auf zoom
ausgeführt, wobei das Proxy-Objekt im Add-In aktualisiert und lokal festgelegte Werte überschrieben werden.
Dieses Verhalten unterscheidet sich von Navigationseigenschaften wie Range.format. Eigenschaften von können mithilfe der format
Objektnavigation festgelegt werden, wie hier gezeigt.
// This will set the font size on the range during the next `content.sync()`.
range.format.font.size = 10;
Sie können eine Eigenschaft identifizieren, deren Untereigenschaften nicht direkt festgelegt werden können, indem Sie den schreibgeschützten Modifikator überprüfen. Für alle schreibgeschützten Eigenschaften können ihre nicht schreibgeschützten Untereigenschaften direkt festgelegt werden. Beschreibbare Eigenschaften wie PageLayout.zoom
müssen mit einem Objekt auf dieser Ebene festgelegt werden. Zusammenfassend:
- Schreibgeschützte Eigenschaft: Untereigenschaften können über die Navigation festgelegt werden.
- Beschreibbare Eigenschaft: Untereigenschaften können nicht über die Navigation festgelegt werden (müssen im Rahmen der anfänglichen übergeordneten Objektzuweisung festgelegt werden).
*OrNullObject-Methoden und -Eigenschaften
Einige Zugriffsmethoden und -eigenschaften lösen eine Ausnahme aus, wenn das gewünschte Objekt nicht vorhanden ist. Wenn Sie beispielsweise versuchen, ein Excel-Arbeitsblatt abzurufen, indem Sie einen Arbeitsblattnamen angeben, der nicht in der Arbeitsmappe enthalten ist, löst die getItem()
-Methode eine ItemNotFound
-Ausnahme aus. Die anwendungsspezifischen Bibliotheken bieten Ihrem Code die Möglichkeit, die Existenz von Dokumententitäten zu testen, ohne dass ein Code für die Ausnahmebehandlung erforderlich ist. Dies wird durch die Verwendung der *OrNullObject
-Variationen von Methoden und Eigenschaften erreicht. Diese Variationen geben ein Objekt zurück, dessen isNullObject
-Eigenschaft auf true
festgelegt ist, wenn das angegebene Element nicht vorhanden ist, anstatt eine Ausnahme auszulösen.
Beispielsweise können Sie die getItemOrNullObject()
-Methode für eine Sammlung wie Arbeitsblätter aufrufen, um ein Element aus der Sammlung abzurufen. Die getItemOrNullObject()
-Methode gibt das angegebene Element zurück, falls vorhanden. Andernfalls wird ein Objekt zurückgegeben, dessen isNullObject
-Eigenschaft auf true
festgelegt ist. Ihr Code kann diese Eigenschaft dann auswerten, um festzustellen, ob das Objekt vorhanden ist.
Hinweis
Die *OrNullObject
-Variationen geben niemals den JavaScript-Wert null
zurück. Sie geben normale Office-Proxyobjekte zurück. Wenn die Entität, die das Objekt darstellt, nicht vorhanden ist, wird die isNullObject
-Eigenschaft des Objekts auf true
festgelegt. Testen Sie das zurückgegebene Objekt nicht auf Ungültigkeit oder Falschheit. Es ist niemals null
, false
oder undefined
.
Das folgende Codebeispiel versucht, mithilfe der getItemOrNullObject()
-Methode ein Excel-Arbeitsblatt mit dem Namen "Daten" abzurufen. Wenn ein Arbeitsblatt mit diesem Namen nicht vorhanden ist, wird ein neues Blatt erstellt. Beachten Sie, dass der Code die isNullObject
-Eigenschaft nicht lädt. Office lädt diese Eigenschaft automatisch, wenn context.sync
aufgerufen wird, sodass Sie diese nicht explizit mit etwas wie dataSheet.load('isNullObject')
laden müssen.
await Excel.run(async (context) => {
let dataSheet = context.workbook.worksheets.getItemOrNullObject("Data");
await context.sync();
if (dataSheet.isNullObject) {
dataSheet = context.workbook.worksheets.add("Data");
}
// Set `dataSheet` to be the second worksheet in the workbook.
dataSheet.position = 1;
});
Anwendungs- und Rückgängig-Stapel
Wenn eine anwendungsspezifische API verarbeitet wird, wird der Rückgängig-Stapel der Anwendung gelöscht. Dies bedeutet, dass Sie Änderungen, die vor einer Aktion durch ein Add-In vorgenommen wurden, nicht rückgängig machen können (es sei denn, dieses Add-In verwendet nur allgemeine APIs oder interagiert nicht mit der Datei). Das gleiche gilt für Änderungen, die vom Add-In vorgenommen werden.
Mehr dazu
Office Add-ins