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.runund Word.run führen eine Funktion aus, die die Aktionen angibt, die für Excel, Word und OneNote ausgeführt werden sollen. *.runerstellt 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}`;
    });
});

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