Tutorial: Crear un complemento de panel de tareas de Excel

En este tutorial, deberá crear un complemento de panel de tareas de Excel que:

  • Cree una tabla
  • Filtre y ordene una tabla
  • Cree un gráfico
  • Inmovilice un encabezado de tabla
  • Proteja una hoja de cálculo
  • Abra un cuadro de diálogo

Sugerencia

Si ya ha terminado el inicio rápido de Crear un complemento para el panel de tareas de Excel con el generador de Yeoman y desea usar ese proyecto como punto de partida para este tutorial, vaya directamente a la sección Crear una tabla para iniciar este tutorial.

Requisitos previos

  • Node.js (la última versión de LTS)

  • La versión más reciente de Yeoman y Generador de Yeoman para complementos de Office. Para instalar estas herramientas globalmente, ejecute el siguiente comando desde el símbolo del sistema.

    npm install -g yo generator-office
    

    Nota

    Incluso si ha instalado previamente el generador de Yeoman, se recomienda actualizar el paquete a la versión más reciente de npm.

Crear el proyecto de complemento

Ejecute el siguiente comando para crear un proyecto de complemento con el generador Yeoman.

yo office

Nota

Cuando ejecute el comando yo office, es posible que reciba mensajes sobre las directivas de recopilación de datos de Yeoman y las herramientas de la CLI de complementos de Office. Use la información adecuada que se proporciona para responder a los mensajes.

Cuando se le pida, proporcione la siguiente información para crear el proyecto de complemento.

  • Elija un tipo de proyecto: Office Add-in Task Pane project
  • Elija un tipo de script: JavaScript
  • ¿Qué nombre desea asignar al complemento? My Office Add-in
  • ¿Qué aplicación cliente de Office desea admitir? Excel

Captura de pantalla de la interfaz de línea de comandos del generador de complementos de Office Yeoman.

Después de completar el asistente, el generador creará el proyecto e instalará componentes auxiliares de Node.

Sugerencia

Se pueden pasar por alto las instrucciones de los pasos siguientes que el generador de Yeoman ofrece después de que se haya creado el proyecto de complemento. Las instrucciones paso a paso de este artículo le dan toda la información que necesitará para completar este tutorial.

Crear una tabla

En este paso del tutorial, mediante programación comprobará que el complemento es compatible con la versión actual del usuario de Excel, agregará una tabla a una hoja de cálculo, rellenará la tabla con datos y le dará formato.

Programe el complemento

  1. Abra el proyecto en el editor de código.

  2. Abra el archivo ./src/taskpane/taskpane.html. El archivo contiene el formato HTML para el panel de tareas.

  3. Busque el elemento <main> y elimine todas las líneas que aparecen detrás de la etiqueta de apertura <main> y antes de la etiqueta de cierre </main>.

  4. Agregue el marcado siguiente inmediatamente después de la etiqueta <main> de apertura.

    <button class="ms-Button" id="create-table">Create Table</button><br/><br/>
    
  5. Abra el archivo ./src/taskpane/taskpane.js. Este archivo contiene el código de la API de JavaScript de Office que facilita la interacción entre el panel de tareas y la aplicación cliente de Office.

  6. Para quitar todas las referencias al botón run y a la función run(), haga lo siguiente:

    • Busque y elimine la línea document.getElementById("run").onclick = run;.

    • Encuentre y elimine la función run() completa.

  7. En la llamada al método Office.onReady, busque la línea if (info.host === Office.HostType.Excel) { y agregue el siguiente código inmediatamente después de esa línea. Nota:

    • La primera parte del código determina si la versión de Excel del usuario es compatible con una versión de Excel.js que incluya todas las API que usarán esta serie de tutoriales. En un complemento de producción, utilice el cuerpo del bloque condicional para ocultar o deshabilitar la interfaz de usuario que llama a las API no compatibles. Esto permitirá al usuario seguir usando las partes del complemento que sean compatibles con su versión de Excel.

    • En la segunda parte de este código se agrega un controlador de eventos para el botón create-table.

    // Determine if the user's version of Office supports all the Office.js APIs that are used in the tutorial.
    if (!Office.context.requirements.isSetSupported('ExcelApi', '1.7')) {
        console.log('Sorry. The tutorial add-in uses Excel.js APIs that are not available in your version of Office.');
    }
    
    // Assign event handlers and other initialization logic.
    document.getElementById("create-table").onclick = createTable;
    
  8. Agregue la siguiente función al final del archivo. Nota:

    • La lógica del negocio Excel.js se agregará a la función que se pasa a Excel.run. Esta lógica no se ejecuta inmediatamente. En su lugar, se agrega a una cola de comandos pendientes.

    • El método context.sync envía todos los comandos en cola a Excel para su ejecución.

    • El Excel.run va seguido de un bloque catch. Este es el procedimiento recomendado que debe seguir siempre.

    function createTable() {
        Excel.run(function (context) {
    
            // TODO1: Queue table creation logic here.
    
            // TODO2: Queue commands to populate the table with data.
    
            // TODO3: Queue commands to format the table.
    
            return context.sync();
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
    }
    
  9. En la función createTable(), reemplace TODO1 con el siguiente código. Nota:

    • El código crea una tabla utilizando el método add de la colección de tabla de una hoja de cálculo, que siempre existe incluso si está vacío. Esta es la forma estándar de creación de los objetos Excel.js. No hay API de constructor de clase, y nunca usa un operador new para crear un objeto de Excel. En su lugar, agregue un objeto de la colección primaria.

    • El primer parámetro del método add es el rango de solamente la fila superior de la tabla, no toda la fila que la tabla utilizará finalmente. Esto es porque cuando el complemento rellene las filas de datos (en el paso siguiente), se agregarán nuevas filas a la tabla en lugar de escribir valores en las celdas de las filas existentes. Se trata de un patrón muy común, porque el número de filas que tendrá la tabla con frecuencia se desconoce cuando se crea la tabla.

    • Los nombres de tabla deben ser únicos en todo el libro, no solo en la hoja de cálculo.

    var currentWorksheet = context.workbook.worksheets.getActiveWorksheet();
    var expensesTable = currentWorksheet.tables.add("A1:D1", true /*hasHeaders*/);
    expensesTable.name = "ExpensesTable";
    
  10. En la función createTable(), reemplace TODO2 con el siguiente código. Nota:

    • Se establecen los valores de celda de un rango con una matriz de matrices.

    • Se crean nuevas filas en una tabla mediante una llamada al método add de la colección de filas de la tabla. Puede agregar varias filas en una sola llamada de add añadiendo varias matrices de valores de celda de la matriz principal que se pasa como segundo parámetro.

    expensesTable.getHeaderRowRange().values =
        [["Date", "Merchant", "Category", "Amount"]];
    
    expensesTable.rows.add(null /*add at the end*/, [
        ["1/1/2017", "The Phone Company", "Communications", "120"],
        ["1/2/2017", "Northwind Electric Cars", "Transportation", "142.33"],
        ["1/5/2017", "Best For You Organics Company", "Groceries", "27.9"],
        ["1/10/2017", "Coho Vineyard", "Restaurant", "33"],
        ["1/11/2017", "Bellows College", "Education", "350.1"],
        ["1/15/2017", "Trey Research", "Other", "135"],
        ["1/15/2017", "Best For You Organics Company", "Groceries", "97.88"]
    ]);
    
  11. En la función createTable(), reemplace TODO3 con el siguiente código. Nota:

    • El código obtiene una referencia a la columna Cantidad pasando el índice basado en cero al método getItemAt del conjunto de columnas de la tabla.

      Nota

      Los objetos de colección Excel.js, como TableCollection, WorksheetCollection y TableColumnCollection, tienen un propiedad items que es una matriz de los tipos de objetos secundarios, como Table, Worksheet o TableColumn, pero un objeto *Collection no es una matriz en sí.

    • Entonces, el rango da formato al rango de la columna Cantidad como euros al segundo decimal.

    • Por último, garantiza que el ancho de las columnas y el alto de las filas son lo suficientemente grandes como para albergar el elemento de datos más largo (o más alto). Tenga en cuenta que el código debe obtener objetos Range para dar formato. Los objetos TableColumn y TableRow no cuentan con propiedades de formato.

    expensesTable.columns.getItemAt(3).getRange().numberFormat = [['\u20AC#,##0.00']];
    expensesTable.getRange().format.autofitColumns();
    expensesTable.getRange().format.autofitRows();
    
  12. Compruebe que guardó todos los cambios que realizó en el proyecto.

Probar el complemento

  1. Complete los pasos siguientes para iniciar el servidor web local y transferir localmente el complemento.

    Nota

    Los complementos de Office deben usar HTTPS y no HTTP, incluso cuando está desarrollando. Si le pedirá que instale un certificado después de ejecutar uno de los siguientes comandos, acepte la solicitud para instalar el certificado que proporciona el generador Yeoman.

    Sugerencia

    Si está probando el complemento en Mac, ejecute el siguiente comando en el directorio raíz de su proyecto antes de continuar. Al ejecutar este comando, se iniciará el servidor web local.

    npm run dev-server
    
    • Para probar el complemento en Excel, ejecute el siguiente comando en el directorio raíz del proyecto. Se iniciará el servidor web local (si todavía no está en ejecución) y se abrirá Excel con el complemento cargado.

      npm start
      
    • Para probar el complemento en Excel en la web, ejecute el siguiente comando en el directorio raíz del proyecto. Al ejecutar este comando, se iniciará el servidor web local (si todavía no está en ejecución).

      npm run start:web
      

      Para usar el complemento, abra un nuevo documento en Excel en la Web y, después, transfiera localmente el complemento siguiendo las instrucciones en Transferir localmente complementos de Office en Office en la Web.

  2. En Excel, seleccione la pestaña Inicio y, después, haga clic en el botón Mostrar panel de tareas de la cinta de opciones para abrir el panel de tareas del complemento.

    Captura de pantalla del menú Inicio de Excel con el botón Mostrar panel de tareas resaltado.

  3. En el panel de tareas, use el botón Crear tabla.

    Captura de pantalla de Excel en la que se muestra un panel de tareas de complementos con el botón Crear tabla y una tabla en la hoja de cálculo con los datos Fecha, Vendedor, Categoría y Cantidad.

<a name="filter-and-sort-a-table">Filtrar y ordenar una tabla

En este paso del tutorial, podrá filtrar y ordenar la tabla que creó anteriormente.

Filtrar la tabla

  1. Abra el archivo ./src/taskpane/taskpane.html.

  2. Busque el elemento <button> para el botón create-table y agregue el siguiente marcado después de esa línea.

    <button class=&quot;ms-Button&quot; id=&quot;filter-table&quot;>Filter Table</button><br/><br/>
    
  3. Abra el archivo ./src/taskpane/taskpane.js.

  4. En la llamada al método Office.onReady, busque la línea que asigna un controlador de clic al botón create-table y agregue el siguiente código después de esa línea.

    document.getElementById(&quot;filter-table").onclick = filterTable;
    
  5. Agregue la siguiente función al final del archivo.

    function filterTable() {
        Excel.run(function (context) {
    
            // TODO1: Queue commands to filter out all expense categories except
            //        Groceries and Education.
    
            return context.sync();
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
    }
    
  6. En la función filterTable() reemplace TODO1 con el siguiente código. Nota:

    • Primero, el código obtiene una referencia a la columna que necesita filtrarse pasando el nombre de columna al método getItem, en lugar de pasar el índice al método getItemAt como hace el método createTable. Dado que los usuarios pueden mover las columnas de tabla, la columna de un índice determinado podría cambiar cuando se crea la tabla. Por lo tanto, es más seguro utilizar el nombre de columna para obtener una referencia a la columna. Usamos getItemAt de forma segura en el tutorial anterior, ya que se usó en el mismo método que crea la tabla, así que hay ninguna posibilidad de que un usuario haya movido la columna.

    • El método applyValuesFilter es uno de varios métodos de filtrado en el objeto Filter.

    var currentWorksheet = context.workbook.worksheets.getActiveWorksheet();
    var expensesTable = currentWorksheet.tables.getItem('ExpensesTable');
    var categoryFilter = expensesTable.columns.getItem('Category').filter;
    categoryFilter.applyValuesFilter(['Education', 'Groceries']);
    

Ordenar la tabla

  1. Abra el archivo ./src/taskpane/taskpane.html.

  2. Busque el elemento <button> para el botón filter-table y agregue el siguiente marcado después de esa línea.

    <button class="ms-Button" id="sort-table">Sort Table</button><br/><br/>
    
  3. Abra el archivo ./src/taskpane/taskpane.js.

  4. En la llamada al método Office.onReady, busque la línea que asigna un controlador de clic al botón filter-table y agregue el siguiente código después de esa línea.

    document.getElementById("sort-table").onclick = sortTable;
    
  5. Agregue la siguiente función al final del archivo.

    function sortTable() {
        Excel.run(function (context) {
    
            // TODO1: Queue commands to sort the table by Merchant name.
    
            return context.sync();
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
    }
    
  6. En la función sortTable() reemplace TODO1 con el siguiente código. Nota:

    • El código crea una matriz de objetos SortField que tiene un solo miembro, ya que el complemento solo ordena en la columna Vendedor.

    • La propiedad key de un objeto SortField es el índice de la columna basado en cero que se usa para ordenar. Las filas de la tabla se ordenan en función de los valores de la columna a la que se hace referencia.

    • El miembro sort de un Table es un objeto TableSort, no es un método. Los SortField se pasan al método TableSort del objetoapply.

    var currentWorksheet = context.workbook.worksheets.getActiveWorksheet();
    var expensesTable = currentWorksheet.tables.getItem('ExpensesTable');
    var sortFields = [
        {
            key: 1,            // Merchant column
            ascending: false,
        }
    ];
    
    expensesTable.sort.apply(sortFields);
    
  7. Compruebe que guardó todos los cambios que realizó en el proyecto.

Probar el complemento

  1. Si el servidor web local ya se está ejecutando y el complemento ya está cargado en Excel, continúe con el paso 2. De lo contrario, inicie el servidor web local y transfiera localmente el complemento:

    • Para probar el complemento en Excel, ejecute el siguiente comando en el directorio raíz del proyecto. Se iniciará el servidor web local (si todavía no está en ejecución) y se abrirá Excel con el complemento cargado.

      npm start
      
    • Para probar el complemento en Excel en la web, ejecute el siguiente comando en el directorio raíz del proyecto. Al ejecutar este comando, se iniciará el servidor web local (si todavía no está en ejecución).

      npm run start:web
      

      Para usar el complemento, abra un nuevo documento en Excel en la Web y, después, transfiera localmente el complemento siguiendo las instrucciones en Transferir localmente complementos de Office en Office en la Web.

  2. Si el panel de tareas del complemento no está abierto en Excel, seleccione la pestaña Inicio y, después, haga clic en el botón Mostrar panel de tareas de la cinta de opciones para abrirlo.

  3. Si la tabla que agregó anteriormente en este tutorial no aparece en la hoja de cálculo abierta, elija el botón Crear tabla en el panel de tareas.

  4. Elija los botones Filtrar tabla y Ordenar tabla, en cualquier orden.

    Captura de pantalla de Excel con los botones Filtrar Tabla y Ordenar Tabla en el panel de tareas de complementos.

<a name="create-a-chart">Crear un gráfico

En este paso del tutorial, creará un gráfico con los datos de la tabla que creó anteriormente y, a continuación, dará formato al gráfico.

Crear un gráfico con los datos de tabla

  1. Abra el archivo ./src/taskpane/taskpane.html.

  2. Busque el elemento <button> para el botón sort-table y agregue el siguiente marcado después de esa línea.

    <button class=&quot;ms-Button&quot; id=&quot;create-chart&quot;>Create Chart</button><br/><br/>
    
  3. Abra el archivo ./src/taskpane/taskpane.js.

  4. En la llamada al método Office.onReady, busque la línea que asigna un controlador de clic al botón sort-table y agregue el siguiente código después de esa línea.

    document.getElementById(&quot;create-chart").onclick = createChart;
    
  5. Agregue la siguiente función al final del archivo.

    function createChart() {
        Excel.run(function (context) {
    
            // TODO1: Queue commands to get the range of data to be charted.
    
            // TODO2: Queue command to create the chart and define its type.
    
            // TODO3: Queue commands to position and format the chart.
    
            return context.sync();
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
    }
    
  6. En la función createChart(), reemplace TODO1 con el siguiente código. Tenga en cuenta que para excluir la fila de encabezado, el código utiliza el método Table.getDataBodyRange para obtener el rango de datos que desea representar en el gráfico en lugar del método getRange.

    var currentWorksheet = context.workbook.worksheets.getActiveWorksheet();
    var expensesTable = currentWorksheet.tables.getItem('ExpensesTable');
    var dataRange = expensesTable.getDataBodyRange();
    
  7. En la función createChart(), reemplace TODO2 con el siguiente código. Tenga en cuenta los parámetros siguientes.

    • El primer parámetro para el método add especifica el tipo de gráfico. Hay varios tipos.

    • El segundo parámetro especifica el rango de datos que se incluirá en el gráfico.

    • El tercer parámetro determina si una serie de puntos de datos de la tabla se deben representar como una fila o como una columna. La opción auto le indica a Excel que debe decidir cuál es el mejor método.

    var chart = currentWorksheet.charts.add('ColumnClustered', dataRange, 'Auto');
    
  8. En la función createChart(), reemplace TODO3 con el siguiente código. La mayoría de este código es fácil de entender. Nota:

    • Los parámetros del método setPosition especifican las celdas superior izquierda e inferior derecha del área de hoja de cálculo que debe contener el gráfico. Excel puede ajustar los elementos como el ancho de línea para que el gráfico tenga una buena apariencia en el espacio que se le ha asignado.

    • Una "serie" es un conjunto de puntos de datos de una columna de la tabla. Como hay una única columna sin cadenas en la tabla, Excel deduce que la columna es la única de puntos de datos en el gráfico. Interpreta a las otras columnas como etiquetas de gráfico. Así que habrá una sola serie en el gráfico y tendrá índice 0. Es la que se etiqueta con "Value in €" (valor en €)".

    chart.setPosition("A15", "F30");
    chart.title.text = "Expenses";
    chart.legend.position = "Right";
    chart.legend.format.fill.setSolidColor("white");
    chart.dataLabels.format.font.size = 15;
    chart.dataLabels.format.font.color = "black";
    chart.series.getItemAt(0).name = 'Value in \u20AC';
    
  9. Compruebe que guardó todos los cambios que realizó en el proyecto.

Probar el complemento

  1. Si el servidor web local ya se está ejecutando y el complemento ya está cargado en Excel, continúe con el paso 2. De lo contrario, inicie el servidor web local y transfiera localmente el complemento:

    • Para probar el complemento en Excel, ejecute el siguiente comando en el directorio raíz del proyecto. Se iniciará el servidor web local (si todavía no está en ejecución) y se abrirá Excel con el complemento cargado.

      npm start
      
    • Para probar el complemento en Excel en la web, ejecute el siguiente comando en el directorio raíz del proyecto. Al ejecutar este comando, se iniciará el servidor web local (si todavía no está en ejecución).

      npm run start:web
      

      Para usar el complemento, abra un nuevo documento en Excel en la Web y, después, transfiera localmente el complemento siguiendo las instrucciones en Transferir localmente complementos de Office en Office en la Web.

  2. Si el panel de tareas del complemento no está abierto en Excel, seleccione la pestaña Inicio y, después, haga clic en el botón Mostrar panel de tareas de la cinta de opciones para abrirlo.

  3. Si la tabla que agregó anteriormente en este tutorial no aparece en la hoja de cálculo abierta, elija el botón Crear tabla y, después, el botón Filtrar tabla y el botón Ordenar tabla, en cualquier orden.

  4. Seleccione el botón Crear gráfico. Se crea un gráfico y se incluyen únicamente los datos de las filas que se han filtrado. Las etiquetas de los puntos de datos en la parte inferior están en el orden del gráfico, es decir, los nombres de los comerciantes en orden alfabético inverso.

    Captura de pantalla de Excel con el botón Crear gráfico visible en el panel de tareas de complementos y un gráfico en la hoja de cálculo en el que se muestran los datos de gastos de alimentación y educación.

<a name="freeze-a-table-header">Inmovilizar un encabezado de tabla

Cuando una tabla es lo suficientemente larga para que un usuario deba desplazarse para ver algunas filas, la fila de encabezado puede desplazarse fuera de la vista. En este paso del tutorial, aprenderá a inmovilizar la fila de encabezado de la tabla que creó anteriormente, para que permanezca visible incluso cuando el usuario se desplaza hacia abajo en la hoja de cálculo.

Inmovilizar la fila de encabezado de la tabla

  1. Abra el archivo ./src/taskpane/taskpane.html.

  2. Busque el elemento <button> para el botón create-chart y agregue el siguiente marcado después de esa línea.

    <button class=&quot;ms-Button&quot; id=&quot;freeze-header&quot;>Freeze Header</button><br/><br/>
    
  3. Abra el archivo ./src/taskpane/taskpane.js.

  4. En la llamada al método Office.onReady, busque la línea que asigna un controlador de clic al botón create-chart y agregue el siguiente código después de esa línea.

    document.getElementById(&quot;freeze-header").onclick = freezeHeader;
    
  5. Agregue la siguiente función al final del archivo.

    function freezeHeader() {
        Excel.run(function (context) {
    
            // TODO1: Queue commands to keep the header visible when the user scrolls.
    
            return context.sync();
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
    }
    
  6. En la función freezeHeader() reemplace TODO1 con el siguiente código. Nota:

    • La colección Worksheet.freezePanes es un conjunto de paneles de la hoja de cálculo que se queda anclado o inmovilizado en su lugar mientras el usuario se desplaza por la hoja de cálculo.

    • El método freezeRows acepta como parámetro el número de filas, desde la parte superior, que se van a fijar en su lugar. Pasamos 1 para fijar la primera fila en su lugar.

    var currentWorksheet = context.workbook.worksheets.getActiveWorksheet();
    currentWorksheet.freezePanes.freezeRows(1);
    
  7. Compruebe que guardó todos los cambios que realizó en el proyecto.

Probar el complemento

  1. Si el servidor web local ya se está ejecutando y el complemento ya está cargado en Excel, continúe con el paso 2. De lo contrario, inicie el servidor web local y transfiera localmente el complemento:

    • Para probar el complemento en Excel, ejecute el siguiente comando en el directorio raíz del proyecto. Se iniciará el servidor web local (si todavía no está en ejecución) y se abrirá Excel con el complemento cargado.

      npm start
      
    • Para probar el complemento en Excel en la web, ejecute el siguiente comando en el directorio raíz del proyecto. Al ejecutar este comando, se iniciará el servidor web local (si todavía no está en ejecución).

      npm run start:web
      

      Para usar el complemento, abra un nuevo documento en Excel en la Web y, después, transfiera localmente el complemento siguiendo las instrucciones en Transferir localmente complementos de Office en Office en la Web.

  2. Si el panel de tareas del complemento no está abierto en Excel, seleccione la pestaña Inicio y, después, haga clic en el botón Mostrar panel de tareas de la cinta de opciones para abrirlo.

  3. Si la tabla que agregó anteriormente en este tutorial se encuentra en la hoja de cálculo, elimínela.

  4. En el panel de tareas, elija el botón Crear tabla.

  5. En el panel de tareas, elija el botón Inmovilizar encabezado.

  6. Desplace la hoja de cálculo lo suficiente para ver que el encabezado de tabla permanece visible en la parte superior, aunque las filas más altas se desplacen fuera de la vista.

    Captura de pantalla en la que se muestra una hoja de cálculo de Excel con un encabezado de tabla inmovilizado.

Proteger una hoja de cálculo

En este paso del tutorial, agregará un botón a la cinta de opciones que activa o desactiva la protección de la hoja de cálculo.

Configure el manifiesto para agregar un segundo botón a la cinta de opciones

  1. Abra el archivo de manifiesto ./manifest.xml.

  2. Busque el elemento <Control>. Este elemento define el botón Mostrar panel de tareas de la cinta de opciones Inicio que ha usado para iniciar el complemento. Vamos a agregar un segundo botón al mismo grupo de la cinta de opciones Inicio. Agregue el siguiente marcado entre las etiqueta de cierre de </Control> y </Group>.

    <Control xsi:type="Button" id="<!--TODO1: Unique (in manifest) name for button -->">
        <Label resid="<!--TODO2: Button label -->" />
        <Supertip>
            <Title resid="<!-- TODO3: Button tool tip title -->" />
            <Description resid="<!-- TODO4: Button tool tip description -->" />
        </Supertip>
        <Icon>
            <bt:Image size="16" resid="Icon.16x16"/>
            <bt:Image size="32" resid="Icon.32x32"/>
            <bt:Image size="80" resid="Icon.80x80"/>
        </Icon>
        <Action xsi:type="<!-- TODO5: Specify the type of action-->">
            <!-- TODO6: Identify the function.-->
        </Action>
    </Control>
    
  3. Dentro del XML que acaba de agregar al archivo de manifiesto, reemplace TODO1 con una cadena que proporciona al botón un identificador único dentro de este archivo de manifiesto. Como nuestro botón va a activar o desactivar la protección de la hoja de cálculo, use "ToggleProtection". Cuando haya terminado, la etiqueta de apertura del elemento Control debería tener este aspecto:

    <Control xsi:type="Button" id="ToggleProtection">
    
  4. Los siguientes tres TODOs establecen ID. de recursos, o resids. Un recurso es una cadena (con una longitud máxima de 32 caracteres), y usted creará estas tres cadenas en un paso posterior. Por ahora, debe proporcionar los identificadores a los recursos. En la etiqueta del botón debe poner "Activar o desactivar protección", pero el identificador de esta cadena debe ser "ProtectionButtonLabel", por lo que el elemento Label debe tener un aspecto como el siguiente:

    <Label resid="ProtectionButtonLabel" />
    
  5. El elemento SuperTip define la información sobre herramientas del botón. El título de la información sobre herramientas debe ser el mismo que la etiqueta del botón, por tanto, usamos el mismo identificador de recursos: "ProtectionButtonLabel". La descripción de la información sobre herramientas será "Haga clic para activar y desactivar la protección de la hoja de cálculo". Pero el resid debe ser "ProtectionButtonToolTip". Cuando haya terminado, el elemento SuperTip debería tener este aspecto:

    <Supertip>
        <Title resid="ProtectionButtonLabel" />
        <Description resid="ProtectionButtonToolTip" />
    </Supertip>
    

    Nota

    En un complemento de producción, no querrá usar el mismo icono para dos botones diferentes; pero para simplificar este tutorial, lo haremos. Así que la marcación Icon en nuestro nuevo Control solo es una copia del elemento Icon del existente Control.

  6. El elemento Action incluido en el elemento original Control tiene el tipo establecido en ShowTaskpane, pero nuestro nuevo botón no va a abrir un panel de tareas, va a ejecutar una función personalizada que cree en un paso posterior. Así que reemplace TODO5 con ExecuteFunction, que es el tipo de acción para los botones que desencadenan funciones personalizadas. La etiqueta de apertura del elemento Action debe tener este aspecto:

    <Action xsi:type="ExecuteFunction">
    
  7. El elemento original Action tiene elementos secundarios que especifican un identificador de panel de tareas y una dirección URL de la página que se debe abrir en el panel de tareas. Pero un elemento Action del tipo ExecuteFunction tiene un único elemento secundario que asigna un nombre a la función que ejecuta el control. Deberá crear esa función, que se llamará toggleProtection, en un paso posterior. Por lo tanto, reemplace TODO6 por el marcado siguiente.

    <FunctionName>toggleProtection</FunctionName>
    

    La marcación completa Control tendrá la siguiente apariencia:

    <Control xsi:type="Button" id="ToggleProtection">
        <Label resid="ProtectionButtonLabel" />
        <Supertip>
            <Title resid="ProtectionButtonLabel" />
            <Description resid="ProtectionButtonToolTip" />
        </Supertip>
        <Icon>
            <bt:Image size="16" resid="Icon.16x16"/>
            <bt:Image size="32" resid="Icon.32x32"/>
            <bt:Image size="80" resid="Icon.80x80"/>
        </Icon>
        <Action xsi:type="ExecuteFunction">
           <FunctionName>toggleProtection</FunctionName>
        </Action>
    </Control>
    
  8. Desplácese hacia abajo hasta la sección Resources del manifiesto.

  9. Agregue la siguiente marcación como elemento secundario del elemento bt:ShortStrings.

    <bt:String id="ProtectionButtonLabel" DefaultValue="Toggle Worksheet Protection" />
    
  10. Agregue el siguiente marcado como elemento secundario del elemento bt:LongStrings.

    <bt:String id="ProtectionButtonToolTip" DefaultValue="Click to protect or unprotect the current worksheet." />
    
  11. Guarde el archivo.

Cree la función que proteja la hoja

  1. Abra el archivo .\commands\commands.js.

  2. Agregue la siguiente función justo después de la función action. Tenga en cuenta que especificamos un parámetro args para la función y la última línea de la función llama a args.completed. Este es un requisito para todos los comandos de complemento de tipo ExecuteFunction. Indica a la aplicación cliente de Office que la función ha terminado y que la interfaz de usuario tiene de nuevo capacidad de respuesta.

    function toggleProtection(args) {
        Excel.run(function (context) {
    
            // TODO1: Queue commands to reverse the protection status of the current worksheet.
    
            return context.sync();
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
        args.completed();
    }
    
  3. Agregue la línea siguiente al final del archivo:

    g.toggleProtection = toggleProtection;
    
  4. En la función toggleProtection, reemplace TODO1 con el siguiente código. Este código utiliza la propiedad de protección del objeto de hoja de cálculo en un patrón de alternancia estándar. Se explicará el TODO2 en la sección siguiente.

    var sheet = context.workbook.worksheets.getActiveWorksheet();
    
    // TODO2: Queue command to load the sheet's "protection.protected" property from
    //        the document and re-synchronize the document and task pane.
    
    if (sheet.protection.protected) {
        sheet.protection.unprotect();
    } else {
        sheet.protection.protect();
    }
    

Agregue código para recuperar las propiedades del documento en los objetos del script del panel de tareas

En cada una de las funciones que creó en este tutorial, puso en cola comandos para escribir en el documento de Office. Cada función finalizó con una llamada al método context.sync() que envía los comandos puestos en cola al documento que se ejecutará. Sin embargo, el código que agregó en el último paso llama al sheet.protection.protected property. Se trata de una diferencia significativa con respecto a las funciones anteriores que escribió, porque el objeto sheet solo es un proxy que existe en el script del panel tareas. El objeto de proxy no sabe el estado de protección real del documento, así que su propiedad protection.protected no puede tener un valor real. Para evitar un error de excepción, en primer lugar debe recuperar el estado de protección del documento y usarlo para establecer el valor de sheet.protection.protected. Este proceso de obtención consta de tres pasos.

  1. Ponga a la cola un comando para cargar (es decir, obtener) las propiedades que el código necesita leer.

  2. Llame al método sync del objeto de contexto para enviar el comando en cola al documento para la ejecución y devolución de la información solicitada.

  3. Como el método sync es asincrónico, asegúrese de que ha finalizado antes de que el código llame a las propiedades que se obtuvieron.

Estos pasos deben completarse cuando el código necesite leer información del documento de Office.

  1. En la función toggleProtection, reemplace TODO2 con el siguiente código. Nota:

    • Cada objeto de Excel tiene un método load. Especifique las propiedades del objeto que desea leer en el parámetro como una cadena de nombres delimitada por comas. En este caso, la propiedad que quiere leer es una subpropiedad de la propiedad protection. Hace referencia a la subpropiedad casi exactamente como lo haría en cualquier otro lugar de su código, con la excepción de que usa un carácter de barra diagonal ("/") en lugar de un carácter ".".

    • Para asegurarse de que la lógica del botón de alternancia, que lee sheet.protection.protected, no se ejecuta hasta después de que se ha completado sync y de que se ha asignado a sheet.protection.protected el valor correcto que se obtiene del documento, se moverá (en el paso siguiente) a una función then que no se ejecutará hasta que se ha completado sync.

    sheet.load('protection/protected');
    return context.sync()
        .then(
            function() {
                // TODO3: Move the queued toggle logic here.
            }
        )
        // TODO4: Move the final call of `context.sync` here and ensure that it
        //        does not run until the toggle logic has been queued.
    
  2. No puede tener dos instrucciones return en la misma ruta de código no ramificada, por tanto, elimine la return context.sync(); de la última línea al final de la Excel.run. Podrá agregar un nuevo context.sync final en un paso posterior.

  3. Corte la estructura if ... else en la función toggleProtection y péguela en el lugar de TODO3.

  4. Reemplace TODO4 por el código siguiente. Nota:

    • Pasar el método sync a una función then garantiza que no se ejecuta hasta que se ha puesto en cola sheet.protection.unprotect() o sheet.protection.protect().

    • El método then invoca cualquier función que se pasa a él y no desea invocar a sync dos veces, así que omita "()" del final de context.sync.

    .then(context.sync);
    

    Cuando haya terminado, la función completa debería parecerse a la siguiente:

    function toggleProtection(args) {
        Excel.run(function (context) {
          var sheet = context.workbook.worksheets.getActiveWorksheet();
          sheet.load('protection/protected');
    
          return context.sync()
              .then(
                  function() {
                    if (sheet.protection.protected) {
                        sheet.protection.unprotect();
                    } else {
                        sheet.protection.protect();
                    }
                  }
              )
              .then(context.sync);
        })
        .catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });
        args.completed();
    }
    
  5. Compruebe que guardó todos los cambios que realizó en el proyecto.

Probar el complemento

  1. Cierre todas las aplicaciones de Office, Excel incluido.

  2. Elimine la memoria caché de Office eliminando el contenido (todos los archivos y subcarpetas) de la carpeta de caché. Es necesario hacer esto para borrar completamente la versión anterior del complemento de la aplicación cliente.

    • Para Windows: %LOCALAPPDATA%\Microsoft\Office\16.0\Wef\.

    • Para Mac: ~/Library/Containers/com.Microsoft.OsfWebHost/Data/.

      Nota

      Si esta carpeta no existe, compruebe si hay alguna de las siguientes carpetas y, si las encuentra, elimine el contenido de la carpeta.

      • ~/Library/Containers/com.microsoft.{host}/Data/Library/Caches/ donde {host} es la aplicación de Office (por ejemplo, Excel)
      • ~/Library/Containers/com.microsoft.{host}/Data/Library/Application Support/Microsoft/Office/16.0/Wef/ donde {host} es la aplicación de Office (por ejemplo, Excel)
      • ~/Library/Containers/com.microsoft.Office365ServiceV2/Data/Caches/com.microsoft.Office365ServiceV2/
      • ~/Library/Containers/com.microsoft.Office365ServiceV2/Data/Library/Caches/com.microsoft.Office365ServiceV2/
  3. Si el servidor web local ya está en ejecución, deténgalo cerrando la ventana de comandos de nodo.

  4. Debido a que el archivo de manifiesto se ha actualizado, debe volver a instalar localmente el complemento con el archivo de manifiesto actualizado. Inicie el servidor web local y transfiera localmente el complemento:

    • Para probar el complemento en Excel, ejecute el siguiente comando en el directorio raíz del proyecto. Se iniciará el servidor web local (si todavía no está en ejecución) y se abrirá Excel con el complemento cargado.

      npm start
      
    • Para probar el complemento en Excel en la web, ejecute el siguiente comando en el directorio raíz del proyecto. Al ejecutar este comando, se iniciará el servidor web local (si todavía no está en ejecución).

      npm run start:web
      

      Para usar el complemento, abra un nuevo documento en Excel en la Web y, después, transfiera localmente el complemento siguiendo las instrucciones en Transferir localmente complementos de Office en Office en la Web.

  5. En la pestaña Inicio de Excel, elija el botón Activar o desactivar la protección de la hoja de cálculo. Tenga en cuenta que la mayoría de los controles de la cinta de opciones están deshabilitados (y atenuados visualmente) como se muestra en la siguiente captura de pantalla.

    Captura de pantalla de la cinta de opciones de Excel con el botón de alternancia de Protección de hoja de cálculo resaltado y habilitado. La mayoría de los demás botones aparecen en gris y deshabilitados.

  6. Elija una celda como lo haría si quisiera cambiar su contenido. Excel mostrará un mensaje de error que indica que la hoja de cálculo está protegida.

  7. Seleccione el botón Activar o desactivar la protección de la hoja de cálculo otra vez para habilitar de nuevo los controles y volver a cambiar los valores de celda.

Abrir un cuadro de diálogo

En este paso final del tutorial, abrirá un cuadro de diálogo en el complemento, pasará un mensaje del proceso de diálogo al proceso de panel de tareas y cerrará el cuadro de diálogo. Los cuadros de diálogo del complemento son no modales: un usuario puede continuar interactuando con el documento en la aplicación de Office y con la página host en el panel de tareas.

Crear la página del cuadro de diálogo

  1. En la carpeta ./src ubicada en la raíz del proyecto, cree una nueva carpeta denominada cuadros de diálogo.

  2. En la carpeta ./src/dialogs, cree un nuevo archivo llamado popup.html.

  3. Agregue la siguiente revisión a popup.html. Nota:

    • La página tiene un campo <input> donde el usuario debe escribir su nombre y un botón que enviará el nombre al panel de tareas donde se mostrará.

    • El marcado carga un script denominado popup.js que se creará en un paso posterior.

    • También carga la biblioteca Office.js porque se usará en popup.js.

    <!DOCTYPE html>
    <html>
        <head lang="en">
            <title>Dialog for My Office Add-in</title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
    
            <!-- For more information on Fluent UI, visit https://developer.microsoft.com/fluentui. -->
            <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"/>
    
            <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
            <script type="text/javascript" src="popup.js"></script>
    
        </head>
        <body style="display:flex;flex-direction:column;align-items:center;justify-content:center">
            <p class="ms-font-xl">ENTER YOUR NAME</p>
            <input id="name-box" type="text"/><br/><br/>
            <button id="ok-button" class="ms-Button">OK</button>
        </body>
    </html>
    
  4. En la carpeta ./src/dialogs, cree un nuevo archivo llamado popup.js.

  5. Agregue el siguiente código a popup.js. Tenga en cuenta lo siguiente sobre este código.

    • Todas las páginas que llamen a las API de la biblioteca Office.js deben asegurarse antes de que la biblioteca se ha inicializado completamente. La mejor forma de hacerlo es llamar al método Office.onReady(). Si el complemento tiene sus propias tareas de inicialización, el código debe ir en un método then() enlazado a la llamada de Office.onReady(). La llamada de Office.onReady() debe ejecutarse antes de que se llame a Office.js; por lo tanto, la tarea está en un archivo de script que la página se encarga de cargar, como en este caso.
    (function () {
    "use strict";
    
        Office.onReady()
            .then(function() {
    
                // TODO1: Assign handler to the OK button.
    
            });
    
        // TODO2: Create the OK button handler
    
    }());
    
  6. Reemplace TODO1 por el siguiente código. Creará la función sendStringToParentPage en el paso siguiente.

    document.getElementById("ok-button").onclick = sendStringToParentPage;
    
  7. Reemplace TODO2 por el código siguiente. El método messageParent pasa sus parámetros a la página primaria, en este caso, la página del panel de tareas. El parámetro debe ser una cadena. Esto incluye todo lo que se pueda serializar como una cadena, como XML o JSON, o cualquier tipo que se pueda convertir a una cadena.

    function sendStringToParentPage() {
        var userName = document.getElementById("name-box").value;
        Office.context.ui.messageParent(userName);
    }
    

Nota

El archivo popup.html y el archivo popup.js que se carga se ejecutan en un proceso totalmente independiente del runtime del navegador desde el panel de tareas del complemento. Si popup.js se transpiló en el mismo archivo bundle.js del archivo app.js, a continuación, el complemento tendría que cargar dos copias del archivo bundle.js, lo que anula la finalidad de unión. Por ello, este complemento no transpila en absoluto el archivo popup.js.

Actualizar los valores de configuración de webpack

Abra el archivo webpack.config.js en el directorio raíz del proyecto y siga los pasos siguientes.

  1. Busque el objeto entry en el objeto config y agregue una nueva entrada para popup.

    popup: "./src/dialogs/popup.js"
    

    Una vez hecho esto, el nuevo objeto entry tendrá este aspecto.

    entry: {
      polyfill: "@babel/polyfill",
      taskpane: "./src/taskpane/taskpane.js",
      commands: "./src/commands/commands.js",
      popup: "./src/dialogs/popup.js"
    },
    
  2. Busque la matriz plugins dentro del objeto config y agregue el siguiente objeto al final de esa matriz.

    new HtmlWebpackPlugin({
      filename: "popup.html",
      template: "./src/dialogs/popup.html",
      chunks: ["polyfill", "popup"]
    })
    

    Una vez hecho esto, la nueva matriz plugins tendrá este aspecto.

    plugins: [
      new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
        filename: "taskpane.html",
        template: "./src/taskpane/taskpane.html",
        chunks: ['polyfill', 'taskpane']
      }),
      new CopyWebpackPlugin([
      {
        to: "taskpane.css",
        from: "./src/taskpane/taskpane.css"
      }
      ]),
      new HtmlWebpackPlugin({
        filename: "commands.html",
        template: "./src/commands/commands.html",
        chunks: ["polyfill", "commands"]
      }),
      new HtmlWebpackPlugin({
        filename: "popup.html",
        template: "./src/dialogs/popup.html",
        chunks: ["polyfill", "popup"]
      })
    ],
    
  3. Si el servidor web local está en ejecución, deténgalo cerrando la ventana de comandos de nodo.

  4. Ejecute el siguiente comando para volver a compilar el proyecto.

    npm run build
    

Abra el cuadro de diálogo desde el panel de tareas

  1. Abra el archivo ./src/taskpane/taskpane.html.

  2. Busque el elemento <button> para el botón freeze-header y agregue el siguiente marcado después de esa línea.

    <button class="ms-Button" id="open-dialog">Open Dialog</button><br/><br/>
    
  3. El cuadro de diálogo pedirá al usuario que escriba un nombre y lo pase al panel de tareas. El panel de tareas se mostrará en una etiqueta. Inmediatamente después del button que acaba de agregar, agregue el marcado siguiente.

    <label id="user-name"></label><br/><br/>
    
  4. Abra el archivo ./src/taskpane/taskpane.js.

  5. En la llamada al método Office.onReady, busque la línea que asigna un controlador de clic al botón freeze-header y agregue el siguiente código después de esa línea. Creará el método openDialog en un paso posterior.

    document.getElementById("open-dialog").onclick = openDialog;
    
  6. Agregue la siguiente declaración al final del archivo. Esta variable se usa para almacenar un objeto en el contexto de ejecución de la Página principal que actúa como intermediario al contexto de ejecución de la página del cuadro de diálogo.

    var dialog = null;
    
  7. Agregue la siguiente función al final del archivo (después de la declaración de dialog). Lo más importante que hay que tener en cuenta sobre el código es lo que no hay: no hay ninguna llamada de Excel.run. Esto se debe a que la API para abrir un cuadro de diálogo se comparte entre todas las aplicaciones de Office, por lo que es parte de las API comunes de JavaScript para Office, no de la API específica de Excel.

    function openDialog() {
        // TODO1: Call the Office Common API that opens a dialog
    }
    
  8. Reemplace TODO1 por el código siguiente. Nota:

    • El método displayDialogAsync abre un cuadro de diálogo en el centro de la pantalla.

    • El primer parámetro es la dirección URL de la página que se va a abrir.

    • El segundo parámetro pasa opciones. height y width son porcentajes del tamaño de la ventana de la aplicación de Office.

    Office.context.ui.displayDialogAsync(
        'https://localhost:3000/popup.html',
        {height: 45, width: 55},
    
        // TODO2: Add callback parameter.
    );
    

Procesar el mensaje del cuadro de diálogo y cerrar el cuadro de diálogo

  1. En la función openDialog del archivo ./src/taskpane/taskpane.js, sustituya TODO2 con el siguiente código: Nota:

    • La devolución de llamada se ejecuta inmediatamente después de que el cuadro de diálogo se abra correctamente y antes de que el usuario haya realizado alguna acción en el cuadro de diálogo.

    • El result.value es el objeto que actúa como un tipo de intermediario entre los contextos de ejecución de las páginas primarias y de cuadro de diálogo.

    • The processMessage function will be created in a later step. This handler will process any values that are sent from the dialog page with calls of the messageParent function.

    function (result) {
        dialog = result.value;
        dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
    }
    
  2. Agregue la siguiente función después de la función openDialog.

    function processMessage(arg) {
        document.getElementById("user-name").innerHTML = arg.message;
        dialog.close();
    }
    
  3. Compruebe que guardó todos los cambios que realizó en el proyecto.

Probar el complemento

  1. Si el servidor web local ya se está ejecutando y el complemento ya está cargado en Excel, continúe con el paso 2. De lo contrario, inicie el servidor web local y transfiera localmente el complemento:

    • Para probar el complemento en Excel, ejecute el siguiente comando en el directorio raíz del proyecto. Se iniciará el servidor web local (si todavía no está en ejecución) y se abrirá Excel con el complemento cargado.

      npm start
      
    • Para probar el complemento en Excel en la web, ejecute el siguiente comando en el directorio raíz del proyecto. Al ejecutar este comando, se iniciará el servidor web local (si todavía no está en ejecución).

      npm run start:web
      

      Para usar el complemento, abra un nuevo documento en Excel en la Web y, después, transfiera localmente el complemento siguiendo las instrucciones en Transferir localmente complementos de Office en Office en la Web.

  2. Si el panel de tareas del complemento no está abierto en Excel, seleccione la pestaña Inicio y, después, haga clic en el botón Mostrar panel de tareas de la cinta de opciones para abrirlo.

  3. Elija el botón Abrir cuadro de diálogo en el panel de tareas.

  4. Mientras el cuadro de diálogo está abierto, arrástrelo y ajuste el tamaño. Tenga en cuenta que puede interactuar con la hoja de cálculo y presionar otros botones del panel de tareas, pero no puede iniciar un segundo cuadro de diálogo desde la misma página del panel de tareas.

  5. En el cuadro de diálogo, escriba un nombre y elija Aceptar. El nombre aparece en el panel de tareas y el cuadro de diálogo se cierra.

  6. Optionally, comment out the line dialog.close(); in the processMessage function. Then repeat the steps of this section. The dialog stays open and you can change the name. You can close it manually by pressing the X button in the upper right corner.

    Captura de pantalla de Excel con el botón Abrir cuadro de diálogo visible en el panel de tareas de complementos y un cuadro de diálogo que se muestra sobre la hoja de cálculo.

Pasos siguientes

En este tutorial, ha creado un complemento de Excel que interactúa con tablas, gráficos, hojas de cálculo y cuadros de diálogo en un libro de Excel. Para obtener más información sobre la creación de complementos de Excel, continúe con el siguiente artículo.

Consulte también