Compartilhar via


Modelo de API específico da aplicação

Este artigo descreve como utilizar o modelo de API para criar suplementos no Excel, OneNote, PowerPoint, Visio e Word. Ele introduz os conceitos fundamentais do uso de APIs baseadas em promessas.

Observação

Os clientes do Outlook e do Project não suportam este modelo. Utilize o modelo de API Comum para trabalhar com essas aplicações. Para notas completas sobre disponibilidade de plataforma, confira Disponibilidade de plataforma e de Aplicativo cliente do Office para Suplementos do Office.

Dica

Os exemplos neste artigo utilizam as APIs JavaScript do Excel, mas os conceitos também se aplicam às APIs do OneNote, PowerPoint, Visio e Word JavaScript. Para obter exemplos de código completos que mostram como pode utilizar estes e outros conceitos em várias aplicações do Office, consulte Exemplos de código do Suplemento do Office.

Caráter assíncrono das APIs baseadas em promessas

Os Suplementos do Office são sites que aparecem dentro de um controlo de webview nas aplicações do Office, como o Excel. Este controlo está incorporado na aplicação do Office em plataformas baseadas no ambiente de trabalho, como o Office no Windows, e é executado dentro de um iframe HTML no Office na Web. Devido a considerações de desempenho, as APIs Office.js não podem interagir de forma síncrona com as aplicações do Office em todas as plataformas. Desse modo, a chamada à API sync() no Office.js retorna uma Promessa que é resolvida quando o aplicativo do Excel conclui as ações solicitadas de leitura ou de gravação. Além disso, você pode enfileirar várias ações, como configurar propriedades ou invocar métodos, e executá-las como um lote de comandos com uma única chamada a sync(), em vez de enviar uma solicitação separada para cada ação. As seções a seguir descrevem como fazer isso usando as APIs run() e sync().

Função *.run

Excel.run, OneNote.run, PowerPoint.rune Word.run execute uma função que especifica as ações a executar no Excel, Word e No OneNote. *.run cria automaticamente um contexto de solicitação que pode ser usado para interagir com objetos do Excel. Quando *.run concluída, resolve uma promessa e liberta automaticamente todos os objetos que foram alocados no runtime.

O exemplo a seguir mostra como usar Excel.run. O mesmo padrão também é utilizado com o OneNote, PowerPoint, Visio e Word.

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

Contexto de solicitação

A aplicação do Office e o seu suplemento são executados em processos diferentes. Uma vez que utilizam diferentes ambientes de runtime, o seu suplemento precisa de um RequestContext objeto para ligar a objetos do Office, como folhas de cálculo, intervalos, parágrafos e tabelas. Este objeto é fornecido RequestContext como um argumento ao chamar *.run.

Objetos proxy

Os objetos JavaScript do Office, que você declara e usa com as APIs baseadas em promessa, são objetos proxy. Todos os métodos invocados, ou as propriedades definidas ou carregadas em objetos proxy são simplesmente adicionados a uma fila de comandos pendentes. Ao chamar o método sync() no contexto de solicitação (por exemplo, context.sync()), os comandos enfileirados são expedidos para o aplicativo do Office e executados. Essas APIs são fundamentalmente centradas em lotes. Enfileire quantas alterações desejar no contexto de solicitação e, em seguida, chame o método sync() para executar o lote de comandos enfileirados.

Por exemplo, o trecho de código a seguir declara o objeto JavaScript Excel.Range local, selectedRange, para fazer referência a um intervalo selecionado na pasta de trabalho do Excel e, em seguida, define algumas propriedades nesse objeto. O objeto selectedRange é um objeto proxy, de modo que as propriedades definidas e o método invocado nesse objeto não serão refletidos no documento do Excel até que seu suplemento chame context.sync().

const selectedRange = context.workbook.getSelectedRange();
selectedRange.format.fill.color = "#4472C4";
selectedRange.format.font.color = "white";
selectedRange.format.autofitColumns();

Minimizar o número de objetos proxy criados

Evite criar repetidamente o mesmo objeto proxy. Em vez disso, se você precisar do mesmo objeto proxy para mais de uma operação, crie-o uma vez e o atribua a uma variável, em seguida, use essa variável no seu código.

// 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()

Chamar o método sync() no contexto de solicitação sincroniza o estado entre objetos proxy e objetos no documento do Office. O método sync() executa todos os comandos que são enfileirados no contexto de solicitação e recupera valores para qualquer propriedade que deva ser carregada nos objetos proxy. O método sync() é executado de modo assíncrono e retorna uma Promessa, que é resolvida quando o método sync() é concluído.

O exemplo a seguir mostra uma função de lote que define um objeto proxy JavaScript local (selectedRange), carrega uma propriedade desse objeto e, em seguida, usa o padrão de promessas do JavaScript para chamar context.sync(), a fim de sincronizar o estado entre objetos proxy e objetos no documento do Excel.

await Excel.run(async (context) => {
    const selectedRange = context.workbook.getSelectedRange();
    selectedRange.load('address');
    await context.sync();
    console.log('The selected range is: ' + selectedRange.address);
});

No exemplo anterior, selectedRange é definido e sua propriedade address é carregada quando context.sync() é chamado.

Uma sync() vez que se trata de uma operação assíncrona, devolva sempre o Promise objeto para garantir que a sync() operação é concluída antes de o script continuar a ser executado. Se você estiver usando TypeScript ou ES6+ JavaScript, poderá await a chamada context.sync() em vez de retornar a promessa.

Dica de desempenho: minimizar o número de chamadas síncronas

Na API do JavaScript do Excel, sync() é a única operação assíncrona e pode ser lenta em algumas circunstâncias, especialmente no Excel Online na Web. Para otimizar o desempenho, minimize o número de chamadas para sync(), enfileirando o maior número possível de alterações antes de chamá-lo. Para obter mais informações sobre como otimizar o desempenho com sync()o , consulte Evitar utilizar o método context.sync em ciclos.

load()

Antes de poder ler as propriedades de um objeto proxy, será necessário carregar explicitamente as propriedades para preencher o objeto proxy com dados do documento do Office e, em seguida, chamar context.sync(). Por exemplo, se você criar um objeto proxy para referenciar um intervalo selecionado e, em seguida, quiser ler a propriedade address do intervalo selecionado, carregue a propriedade address antes de poder lê-la. Para solicitar que as propriedades de um objeto proxy sejam carregadas, chame o método load() no objeto e especifique as propriedades a serem carregadas. O exemplo a seguir mostra a propriedade Range.address sendo carregada para myRange.

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

Observação

Se estiver a chamar apenas métodos ou a definir propriedades num objeto proxy, não precisa de chamar o load() método . O método load() só é necessário quando você deseja ler propriedades em um objeto proxy.

Tal como os pedidos para definir propriedades ou invocar métodos em objetos proxy, os pedidos para carregar propriedades em objetos proxy são adicionados à fila de comandos pendentes no contexto do pedido, que é executado da próxima vez que chamar o sync() método. Pode colocar em fila o número load() de chamadas no contexto do pedido conforme necessário.

Propriedades escalares e de navegação

Há duas categorias de propriedades: escalar e de navegação. As propriedades escalares são tipos atribuíveis, como cadeias de caracteres, inteiros e estruturas JSON. As propriedades de navegação são objetos somente leitura e coleções de objetos que têm seus campos atribuídos, em vez de atribuir diretamente a propriedade. Por exemplo, os membros name e position no objeto Excel.Worksheet são propriedades escalares, enquanto protection e tables são propriedades de navegação.

O suplemento pode usar propriedades de navegação como um caminho para carregar propriedades escalares específicas. O código a seguir enfileira um comando load para o nome da fonte usada por um objeto Excel.Range, sem carregar nenhuma outra informação.

someRange.load("format/font/name")

Também é possível definir propriedades escalares de uma propriedade de navegação percorrendo o caminho. Por exemplo, é possível definir o tamanho da fonte de um Excel.Range usando someRange.format.font.size = 10;. Não é necessário carregar a propriedade antes de configurá-la.

Algumas das propriedades de um objeto podem ter o mesmo nome que outro objeto. Por exemplo, format é uma propriedade no objeto Excel.Range, mas format também é um objeto. Por isso, se fizer uma chamada como range.load("format"), esta chamada é equivalente a range.format.load() (uma declaração vazia load() indesejável). Para evitar este problema, o código deve carregar apenas os "nós de folha" numa árvore de objetos.

Carregar a partir de uma coleção

Ao trabalhar com uma coleção, utilize load na coleção para carregar propriedades para cada objeto na coleção. Utilize load exatamente como faria para um objeto individual nessa coleção.

O código de exemplo seguinte mostra a propriedade que está a name ser carregada e registada para cada gráfico na folha de cálculo "Exemplo".

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

Normalmente, não inclui a items propriedade da coleção nos load argumentos. Todos os itens são carregados se carregar quaisquer propriedades do item. No entanto, se estiver a repetir o ciclo sobre os itens na coleção, mas não precisar de carregar nenhuma propriedade específica dos itens, terá de aceder à loaditems propriedade .

O código de exemplo seguinte mostra a propriedade que está a name ser definida para cada gráfico na folha de cálculo "Exemplo".

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

Se chamar o load() método num objeto ou coleção sem especificar parâmetros, carregue todas as propriedades escalares do objeto ou dos objetos da coleção. O carregamento de dados desnecessários atrasa o suplemento. Especifique sempre explicitamente as propriedades a carregar.

Importante

A quantidade de dados retornados por uma declaração load sem parâmetros pode exceder os limites de tamanho do serviço. Para reduzir os riscos para suplementos mais antigos, o serviço não devolve algumas propriedades sem load pedir explicitamente. As seguintes propriedades são excluídas dessas operações de carga.

  • Excel.Range.numberFormatCategories

ClientResult

Os métodos nas APIs baseadas em promessas que devolvem tipos primitivos seguem um padrão semelhante ao load/sync paradigma. Por exemplo, Excel.TableCollection.getCount obtém o número de tabelas na coleção. getCount devolve um ClientResult<number>, o que significa que a value propriedade no devolvido ClientResult é um número. Seu script não pode acessar esse valor até que context.sync() seja chamado.

O script a seguir obtém o número total de tabelas na pasta de trabalho do Excel e registra esse número no console.

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()

A definição de propriedades em um objeto com propriedades de navegação aninhadas pode ser uma tarefa complicada. Como alternativa à definição de propriedades individuais através de caminhos de navegação, conforme descrito anteriormente, pode utilizar o object.set() método que está disponível em objetos nas APIs JavaScript baseadas em promessas. Ao utilizar este método, pode definir várias propriedades de um objeto ao mesmo tempo ao transmitir outro objeto do mesmo tipo de Office.js ou um objeto JavaScript com propriedades estruturadas como as propriedades do objeto no qual o método é chamado.

O exemplo de código seguinte define várias propriedades de formato de um intervalo ao chamar o set() método e transmitir um objeto JavaScript com nomes de propriedade e tipos que espelho a estrutura das propriedades no Range objeto. Este exemplo pressupõe que existem dados no intervalo B2:E2.

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

Algumas propriedades não podem ser definidas diretamente.

Algumas propriedades não podem ser definidas, apesar de serem graváveis. Essas propriedades fazem parte de uma propriedade pai que deve ser definida como um único objeto. Isso porque essa propriedade pai depende das subpropriedades com relações lógicas específicas. Essas propriedades pai devem ser definidas usando notação literal de objeto para definir o objeto inteiro, em vez de definir subpropriedades individuais do objeto. Um exemplo disso é encontrado na página PageLayout. A zoom propriedade tem de ser definida com um único objeto PageLayoutZoomOptions , conforme mostrado aqui.

// PageLayout.zoom.scale must be set by assigning PageLayout.zoom to a PageLayoutZoomOptions object.
sheet.pageLayout.zoom = { scale: 200 };

No exemplo anterior, não pode atribuir zoom diretamente um valor: sheet.pageLayout.zoom.scale = 200;. Essa instrução gera um erro porque zoom não está carregada. Mesmo que zoom fosse carregado, o conjunto de dimensionamento não entraria em vigor. Todas as operações de contexto ocorrem em zoom, atualizando o objeto proxy no suplemento e sobrescrevendo os valores definidos localmente.

Esse comportamento difere das propriedades navegacionais como Range.format. As propriedades de format podem ser definidas com a navegação de objetos, conforme mostrado aqui.

// This will set the font size on the range during the next `content.sync()`.
range.format.font.size = 10;

Você pode identificar uma propriedade que não pode ter suas subpropriedades definidas diretamente, verificando seu modificador somente leitura. Todas as propriedades somente leitura podem ter suas subpropriedades não somente leitura definidas diretamente. Propriedades graváveis, como PageLayout.zoom, devem ser definidas com um objeto nesse nível. Em resumo:

  • Propriedade somente leitura: as subpropriedades podem ser definidas por meio da navegação.
  • Propriedade gravável: As subpropriedades não podem ser definidas por meio da navegação (devem ser definidas como parte da atribuição do objeto pai inicial).

*OrNullObject methods and properties (Métodos e propriedades do OrNullObject)

Alguns métodos e propriedades do acessador lançam uma exceção quando o objeto desejado não existe. Por exemplo, ao tentar obter uma planilha do Excel especificando um nome de planilha que não esteja na pasta de trabalho, o método getItem() lança uma exceção ItemNotFound. As bibliotecas específicas por aplicativo fornecem uma maneira do código testar a existência de entidades de documentos sem exigir código de tratamento de exceções. Esta abordagem utiliza as *OrNullObject variações de métodos e propriedades. Estas variações devolvem um objeto cuja isNullObject propriedade está definida como true se o item especificado não existir, em vez de gerar uma exceção.

Por exemplo, você pode chamar o método getItemOrNullObject() em uma coleção, como Planilhas, para recuperar um item da coleção. O método getItemOrNullObject() retornará o item especificado se ele existir; caso contrário, ele retornará um objeto cuja propriedade isNullObject estiver definida como true. O código pode então avaliar essa propriedade para determinar se o objeto existe.

Observação

As *OrNullObject variações nunca devolvem o valor nullJavaScript . Elas retornam objetos proxy comuns do Office. Se a entidade que o objeto representa não existir, a isNullObject propriedade do objeto será definida como true. Não teste o objeto devolvido por nulidade ou falsificação. Nunca é null, falseou undefined.

O exemplo de código a seguir tenta recuperar uma planilha do Excel chamada "Dados", usando o método getItemOrNullObject(). Se não existir uma folha de cálculo com esse nome, o código cria uma nova folha. Tenha em atenção que o código não carrega a isNullObject propriedade. O Office carrega automaticamente esta propriedade quando context.sync é chamada, pelo que não precisa de a carregar explicitamente com algo como dataSheet.load('isNullObject').

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

Anular suporte

A anulação é parcialmente suportada pelas APIs de JavaScript do Office específicas da aplicação. Isto significa que os utilizadores podem ser capazes de reverter alterações efetuadas pelos suplementos através do comando anular. Se uma determinada API não suportar a anulação, a pilha de anulação da aplicação será limpa. Isto significa que não poderá anular os efeitos dessa API ou qualquer outra coisa antes de chamar essa API.

O suporte da API para anular continua a expandir-se, mas está atualmente incompleto. Recomendamos que não crie o seu suplemento de forma a depender da anulação do suporte.

Confira também