Trabalhar com formas usando a API JavaScript do Excel

O Excel define formas como qualquer objeto que esteja na camada de desenho do Excel. Isso significa que qualquer coisa fora de uma célula é uma forma. Este artigo descreve como usar formas geométricas, linhas e imagens em conjunto com as APIs Shape e ShapeCollection . Os gráficos são abordados em seu próprio artigo, Trabalhe com gráficos usando a API JavaScript do Excel.

A imagem a seguir mostra formas que formam um termômetro. Imagem de um termômetro feito como uma forma do Excel.

Criar formas

As formas são criadas por meio e armazenadas na coleção de formas de uma planilha (Worksheet.shapes). ShapeCollection tem vários .add* métodos para essa finalidade. Todas as formas têm nomes e IDs gerados para elas quando são adicionadas à coleção. Estas são as name propriedades e id , respectivamente. name pode ser definido pelo seu suplemento para fácil recuperação com o ShapeCollection.getItem(name) método.

Os tipos de formas a seguir são adicionados usando o método associado.

Shape Add Method Assinatura
Forma geométrica addGeometricShape addGeometricShape(geometricShapeType: Excel.GeometricShapeType): Excel.Shape
Imagem (JPEG ou PNG) Addimage addImage(base64ImageString: string): Excel.Shape
Line Addline addLine(startLeft: number, startTop: number, endLeft: number, endTop: number, connectorType?: Excel.ConnectorType): Excel.Shape
Svg addSvg addSvg(xml: string): Excel.Shape
Caixa de Texto Addtextbox addTextBox(text?: string): Excel.Shape

Formas geométricas

Uma forma geométrica é criada com ShapeCollection.addGeometricShape. Esse método usa um enumeração GeometricShapeType como argumento.

O exemplo de código a seguir cria um retângulo de 150x150 pixels chamado "Square" posicionado a 100 pixels dos lados superior e esquerdo da planilha.

// This sample creates a rectangle positioned 100 pixels from the top and left sides
// of the worksheet and is 150x150 pixels.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;

    let rectangle = shapes.addGeometricShape(Excel.GeometricShapeType.rectangle);
    rectangle.left = 100;
    rectangle.top = 100;
    rectangle.height = 150;
    rectangle.width = 150;
    rectangle.name = "Square";

    await context.sync();
});

Imagens

Imagens JPEG, PNG e SVG podem ser inseridas em uma planilha como formas. O ShapeCollection.addImage método usa uma cadeia de caracteres codificada com base64 como argumento. Esta é uma imagem JPEG ou PNG em forma de cadeia de caracteres. ShapeCollection.addSvg também usa uma cadeia de caracteres, embora esse argumento seja XML que define o gráfico.

O exemplo de código a seguir mostra um arquivo de imagem sendo carregado por um FileReader como uma cadeia de caracteres. A cadeia de caracteres tem os metadados "base64", removidos antes da forma ser criada.

// This sample creates an image as a Shape object in the worksheet.
let myFile = document.getElementById("selectedFile");
let reader = new FileReader();

reader.onload = (event) => {
    Excel.run(function (context) {
        let startIndex = reader.result.toString().indexOf("base64,");
        let myBase64 = reader.result.toString().substr(startIndex + 7);
        let sheet = context.workbook.worksheets.getItem("MyWorksheet");
        let image = sheet.shapes.addImage(myBase64);
        image.name = "Image";
        return context.sync();
    }).catch(errorHandlerFunction);
};

// Read in the image file as a data URL.
reader.readAsDataURL(myFile.files[0]);

Linhas

Uma linha é criada com ShapeCollection.addLine. Esse método precisa das margens esquerda e superior dos pontos de início e de extremidade da linha. Ele também usa um enumeração ConnectorType para especificar como a linha se contorta entre pontos de extremidade. O exemplo de código a seguir cria uma linha reta na planilha.

// This sample creates a straight line from [200,50] to [300,150] on the worksheet.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let line = shapes.addLine(200, 50, 300, 150, Excel.ConnectorType.straight);
    line.name = "StraightLine";
    await context.sync();
});

As linhas podem ser conectadas a outros objetos Shape. Os connectBeginShape métodos e connectEndShape anexam o início e o término de uma linha a formas nos pontos de conexão especificados. Os locais desses pontos variam de acordo com a forma, mas podem Shape.connectionSiteCount ser usados para garantir que o suplemento não se conecte a um ponto fora dos limites. Uma linha é desconectada de todas as formas anexadas usando os disconnectBeginShape métodos e disconnectEndShape .

O exemplo de código a seguir conecta a linha "MyLine" a duas formas chamadas "LeftShape" e "RightShape".

// This sample connects a line between two shapes at connection points '0' and '3'.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let line = shapes.getItem("MyLine").line;
    line.connectBeginShape(shapes.getItem("LeftShape"), 0);
    line.connectEndShape(shapes.getItem("RightShape"), 3);
    await context.sync();
});

Mover e redimensionar formas

As formas ficam na parte superior da planilha. Seu posicionamento é definido pela left propriedade e top . Elas atuam como margens das respectivas bordas da planilha, com [0, 0] sendo o canto superior esquerdo. Elas podem ser definidas diretamente ou ajustadas de sua posição atual com os incrementLeft métodos e incrementTop . O quanto uma forma é girada da posição padrão também é estabelecida dessa maneira, com a rotation propriedade sendo a quantidade absoluta e o incrementRotation método ajustando a rotação existente.

A profundidade de uma forma em relação a outras formas é definida pela zorderPosition propriedade. Isso é definido usando o setZOrder método, que usa um ShapeZOrder. setZOrder ajusta a ordenação da forma atual em relação às outras formas.

Seu suplemento tem algumas opções para alterar a altura e a largura das formas. A configuração da height propriedade ou width altera a dimensão especificada sem alterar a outra dimensão. O scaleHeight e scaleWidth ajustar as respectivas dimensões da forma em relação ao tamanho atual ou original (com base no valor do ShapeScaleType fornecido). Um parâmetro opcional ShapeScaleFrom especifica de onde a forma é dimensionada (canto superior esquerdo, canto médio ou canto inferior direito). Se a lockAspectRatio propriedade for true, os métodos de escala manterão a proporção atual da forma ajustando também a outra dimensão.

Observação

Alterações diretas nas height propriedades e width afetam apenas essa propriedade, independentemente do lockAspectRatio valor da propriedade.

O exemplo de código a seguir mostra uma forma sendo dimensionada para 1,25 vezes seu tamanho original e girada 30 graus.

// In this sample, the shape "Octagon" is rotated 30 degrees clockwise
// and scaled 25% larger, with the upper-left corner remaining in place.
await Excel.run(async (context) => {
    let sheet = context.workbook.worksheets.getItem("MyWorksheet");

    let shape = sheet.shapes.getItem("Octagon");
    shape.incrementRotation(30);
    shape.lockAspectRatio = true;
    shape.scaleWidth(
        1.25,
        Excel.ShapeScaleType.currentSize,
        Excel.ShapeScaleFrom.scaleFromTopLeft);

    await context.sync();
});

Texto em formas

Formas geométricas podem conter texto. As formas têm uma textFrame propriedade do tipo TextFrame. O TextFrame objeto gerencia as opções de exibição de texto (como margens e estouro de texto). TextFrame.textRange é um objeto TextRange com o conteúdo de texto e as configurações de fonte.

O exemplo de código a seguir cria uma forma geométrica chamada "Wave" com o texto "Texto de Forma". Ele também ajusta a forma e as cores de texto, bem como define o alinhamento horizontal do texto para o centro.

// This sample creates a light-blue wave shape and adds the purple text "Shape text" to the center.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let wave = shapes.addGeometricShape(Excel.GeometricShapeType.wave);
    wave.left = 100;
    wave.top = 400;
    wave.height = 50;
    wave.width = 150;

    wave.name = "Wave";
    wave.fill.setSolidColor("lightblue");

    wave.textFrame.textRange.text = "Shape text";
    wave.textFrame.textRange.font.color = "purple";
    wave.textFrame.horizontalAlignment = Excel.ShapeTextHorizontalAlignment.center;

    await context.sync();
});

O addTextBox método de ShapeCollection cria um GeometricShape tipo Rectangle com um fundo branco e um texto em preto. Isso é o mesmo que é criado pelo botão Caixa de Texto do Excel na guia Inserir . addTextBox usa um argumento de cadeia de caracteres para definir o texto do TextRange.

O exemplo de código a seguir mostra a criação de uma caixa de texto com o texto "Olá!".

// This sample creates a text box with the text "Hello!" and sizes it appropriately.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let textbox = shapes.addTextBox("Hello!");
    textbox.left = 100;
    textbox.top = 100;
    textbox.height = 20;
    textbox.width = 45;
    textbox.name = "Textbox";
    await context.sync();
});

Grupos de formas

Formas podem ser agrupadas. Isso permite que um usuário os trate como uma única entidade para posicionamento, dimensionamento e outras tarefas relacionadas. Um ShapeGroup é um tipo de Shape, portanto, seu suplemento trata o grupo como uma única forma.

O exemplo de código a seguir mostra três formas sendo agrupadas. O exemplo de código subsequente mostra esse grupo de formas sendo movido para os 50 pixels à direita.

// This sample takes three previously-created shapes ("Square", "Pentagon", and "Octagon")
// and groups them into a single ShapeGroup.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let square = shapes.getItem("Square");
    let pentagon = shapes.getItem("Pentagon");
    let octagon = shapes.getItem("Octagon");

    let shapeGroup = shapes.addGroup([square, pentagon, octagon]);
    shapeGroup.name = "Group";
    console.log("Shapes grouped");

    await context.sync();
});

// This sample moves the previously created shape group to the right by 50 pixels.
await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let shapeGroup = shapes.getItem("Group");
    shapeGroup.incrementLeft(50);
    await context.sync();
});

Importante

As formas individuais dentro do grupo são referenciadas por meio da ShapeGroup.shapes propriedade, que é do tipo GroupShapeCollection. Eles não estão mais acessíveis por meio da coleção de formas da planilha após serem agrupados. Como exemplo, se sua planilha tivesse três formas e todas elas fossem agrupadas, o método da shapes.getCount planilha retornaria uma contagem de 1.

Exportar formas como imagens

Qualquer Shape objeto pode ser convertido em uma imagem. Shape.getAsImage retorna a cadeia de caracteres codificada com base64. O formato da imagem é especificado como um enumeração PictureFormat passado para getAsImage.

await Excel.run(async (context) => {
    let shapes = context.workbook.worksheets.getItem("MyWorksheet").shapes;
    let shape = shapes.getItem("Image");
    let stringResult = shape.getAsImage(Excel.PictureFormat.png);

    await context.sync();

    console.log(stringResult.value);
    // Instead of logging, your add-in may use the base64-encoded string to save the image as a file or insert it in HTML.
});

Excluir formas

As formas são removidas da planilha com o Shape método do delete objeto. Nenhum outro metadado é necessário.

O exemplo de código a seguir exclui todas as formas do MyWorksheet.

// This deletes all the shapes from "MyWorksheet".
await Excel.run(async (context) => {
    let sheet = context.workbook.worksheets.getItem("MyWorksheet");
    let shapes = sheet.shapes;

    // We'll load all the shapes in the collection without loading their properties.
    shapes.load("items/$none");
    await context.sync();

    shapes.items.forEach(function (shape) {
        shape.delete();
    });
    
    await context.sync();
});

Confira também