Trabajar con formas mediante la API de JavaScript de Excel

Excel define las formas como cualquier objeto que se encuentra en la capa de dibujo de Excel. Eso significa que cualquier cosa fuera de una celda es una forma. En este artículo se describe cómo usar formas geométricas, líneas e imágenes junto con las API Shape y ShapeCollection . Los gráficos se tratan en su propio artículo, Trabajar con gráficos mediante la API de JavaScript de Excel.

En la imagen siguiente se muestran formas que forman un termómetro. Imagen de un termómetro hecho como una forma de Excel.

Crear formas

Las formas se crean y almacenan en la colección de formas de una hoja de cálculo (Worksheet.shapes). ShapeCollection tiene varios .add* métodos para este propósito. Todas las formas tienen nombres e identificadores generados para ellas cuando se agregan a la colección. Estas son las name propiedades y id , respectivamente. name el complemento puede establecerlo para facilitar la recuperación con el ShapeCollection.getItem(name) método .

Los siguientes tipos de formas se agregan mediante el método asociado.

Forma Add (método) Firma
Forma geométrica addGeometricShape addGeometricShape(geometricShapeType: Excel.GeometricShapeType): Excel.Shape
Imagen (JPEG o PNG) addImage addImage(base64ImageString: string): Excel.Shape
Línea Addline addLine(startLeft: number, startTop: number, endLeft: number, endTop: number, connectorType?: Excel.ConnectorType): Excel.Shape
Svg addSvg addSvg(xml: string): Excel.Shape
Cuadro de texto addTextBox addTextBox(text?: string): Excel.Shape

Formas geométricas

Se crea una forma geométrica con ShapeCollection.addGeometricShape. Ese método toma una enumeración GeometricShapeType como argumento.

En el ejemplo de código siguiente se crea un rectángulo de 150 x 150 píxeles denominado "Cuadrado" que se coloca a 100 píxeles de los lados superior e izquierdo de la hoja de cálculo.

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

Imágenes

Las imágenes JPEG, PNG y SVG se pueden insertar en una hoja de cálculo como formas. El ShapeCollection.addImage método toma una cadena codificada en base64 como argumento. Se trata de una imagen JPEG o PNG en forma de cadena. ShapeCollection.addSvg también toma una cadena, aunque este argumento es XML que define el gráfico.

En el ejemplo de código siguiente se muestra un archivo de imagen cargado por un Objeto FileReader como una cadena. La cadena tiene los metadatos "base64" quitados antes de crear la forma.

// 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]);

Lines

Se crea una línea con ShapeCollection.addLine. Ese método necesita los márgenes izquierdo y superior de los puntos inicial y final de la línea. También toma una enumeración ConnectorType para especificar cómo se contorsiona la línea entre los puntos de conexión. En el ejemplo de código siguiente se crea una línea recta en la hoja de cálculo.

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

Las líneas se pueden conectar a otros objetos Shape. Los connectBeginShape métodos y connectEndShape asocian el principio y el final de una línea a las formas de los puntos de conexión especificados. Las ubicaciones de estos puntos varían según la Shape.connectionSiteCount forma, pero se pueden usar para asegurarse de que el complemento no se conecta a un punto que está fuera de límites. Una línea se desconecta de las formas adjuntas mediante los disconnectBeginShape métodos y disconnectEndShape .

En el ejemplo de código siguiente se conecta la línea "MyLine" a dos formas denominadas "LeftShape" y "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 y cambiar el tamaño de las formas

Las formas se colocan encima de la hoja de cálculo. Su ubicación se define mediante la left propiedad y top . Estos actúan como márgenes de los bordes respectivos de la hoja de cálculo, siendo [0, 0] la esquina superior izquierda. Se pueden establecer directamente o ajustar desde su posición actual con los incrementLeft métodos y incrementTop . La cantidad de rotación de una forma desde la posición predeterminada también se establece de esta manera, siendo la rotation propiedad la cantidad absoluta y el incrementRotation método que ajusta la rotación existente.

La profundidad de una forma con respecto a otras formas se define mediante la zorderPosition propiedad . Esto se establece mediante el setZOrder método , que toma shapeZOrder. setZOrder ajusta el orden de la forma actual en relación con las otras formas.

El complemento tiene un par de opciones para cambiar el alto y el ancho de las formas. Al establecer la height propiedad o width se cambia la dimensión especificada sin cambiar la otra dimensión. scaleHeight y scaleWidth ajustar las dimensiones respectivas de la forma en relación con el tamaño actual o original (en función del valor de ShapeScaleType proporcionado). Un parámetro ShapeScaleFrom opcional especifica desde dónde se escala la forma (esquina superior izquierda, esquina central o esquina inferior derecha). Si la lockAspectRatio propiedad es true, los métodos de escala mantienen la relación de aspecto actual de la forma ajustando también la otra dimensión.

Nota:

Los cambios directos en las height propiedades y width solo afectan a esa propiedad, independientemente del valor de la lockAspectRatio propiedad.

En el ejemplo de código siguiente se muestra una forma que se escala a 1,25 veces su tamaño original y gira 30 grados.

// 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 en formas

Las formas geométricas pueden contener texto. Las formas tienen una textFrame propiedad de tipo TextFrame. El TextFrame objeto administra las opciones de visualización de texto (como márgenes y desbordamiento de texto). TextFrame.textRange es un objeto TextRange con la configuración de contenido de texto y fuente.

En el ejemplo de código siguiente se crea una forma geométrica denominada "Wave" con el texto "Shape Text". También ajusta la forma y los colores del texto, así como establece la alineación horizontal del texto en el 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();
});

El addTextBox método de ShapeCollection crea un GeometricShape de tipo Rectangle con un fondo blanco y texto negro. Esto es lo mismo que lo que crea el botón Cuadro de texto de Excel en la pestaña Insertar . addTextBox toma un argumento de cadena para establecer el texto de TextRange.

En el ejemplo de código siguiente se muestra la creación de un cuadro de texto con el texto "Hello!".

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

Las formas se pueden agrupar. Esto permite a un usuario tratarlos como una sola entidad para el posicionamiento, el ajuste de tamaño y otras tareas relacionadas. ShapeGroup es un tipo de Shape, por lo que el complemento trata el grupo como una sola forma.

En el ejemplo de código siguiente se muestran tres formas agrupadas. En el ejemplo de código siguiente se muestra que el grupo de formas se mueve a la derecha 50 píxeles.

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

Se hace referencia a formas individuales dentro del grupo a través de la ShapeGroup.shapes propiedad , que es de tipo GroupShapeCollection. Ya no se puede acceder a ellos a través de la colección de formas de la hoja de cálculo después de agruparse. Por ejemplo, si la hoja de cálculo tenía tres formas y todas estaban agrupadas, el método de la hoja de shapes.getCount cálculo devolvería un recuento de 1.

Exportación de formas como imágenes

Cualquier Shape objeto se puede convertir en una imagen. Shape.getAsImage devuelve una cadena codificada en base64. El formato de la imagen se especifica como una enumeración PictureFormat pasada a 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.
});

Eliminar formas

Las formas se quitan de la hoja de cálculo con el Shape método del delete objeto. No se necesitan otros metadatos.

En el ejemplo de código siguiente se eliminan todas las formas de 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();
});

Vea también