Ejercicio: Trabajar con hojas de cálculo y comandos de complemento
En este ejercicio, 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 trabajo. También aprenderá a activar y desactivar la protección de hojas de cálculo.
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 esta sección, inmovilizará la fila de encabezado de la tabla que creó anteriormente, para que permanezca visible incluso cuando el usuario se desplace hacia abajo en la hoja de cálculo.
Inmovilizar la fila de encabezado de la tabla
Abra el archivo ./src/taskpane/taskpane.html.
Busque el
<button>
elemento para el botón crear gráfico y agregue el siguiente marcado después de esa línea:<button class="ms-Button" id="freeze-header">Freeze Header</button><br/><br/>
Abra el archivo ./src/taskpane/taskpane.js.
Dentro del método
Office.onReady()
, busque la siguiente línea:document.getElementById("create-chart").onclick = createChart;
Agregue el código siguiente inmediatamente después de esa línea:
document.getElementById("freeze-header").onclick = freezeHeader;
Agregue la función siguiente al final del archivo:
async function freezeHeader() { await Excel.run(async (context) => { // TODO1: Queue commands to keep the header visible when the user scrolls. await context.sync(); }) .catch(function (error) { console.log("Error: " + error); if (error instanceof OfficeExtension.Error) { console.log("Debug info: " + JSON.stringify(error.debugInfo)); } }); }
En la función
freezeHeader()
, reemplaceTODO1
con el código siguiente:const currentWorksheet = context.workbook.worksheets.getActiveWorksheet(); currentWorksheet.freezePanes.freezeRows(1);
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()
toma como parámetro el número de filas desde la parte superior que se van a anclar en su lugar. Pasamos1
para anclar la primera fila en su posición.
- La colección
Compruebe que los cambios se guardan en el proyecto.
Probar el complemento
Si el servidor web local ya está en ejecución 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.
Si el panel de tareas del complemento aún no está abierto, en la pestaña Inicio, seleccione Mostrar panel de tareas.
Si la tabla que agregó anteriormente en este tutorial se encuentra en la hoja de cálculo, elimínela.
En el panel de tareas, seleccione Crear tabla.
En el panel de tareas, seleccione Inmovilizar encabezado.
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.
Proteger una hoja de cálculo
En esta sección, agregará otro botón a la cinta que, cuando se elija, ejecutará una función que definirá para activar y desactivar la protección de la hoja de trabajo.
Configure el manifiesto para agregar un segundo botón a la cinta de opciones
Abra el archivo de manifiesto ./manifest.xml.
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.Entre la etiqueta Control final (
</Control>
) y la etiqueta Grupo final (</Group>
), agregue la marcación siguiente.<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>
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, useToggleProtection
. Cuando haya terminado, la etiqueta de apertura del elementoControl
debería tener este aspecto:<Control xsi:type="Button" id="ToggleProtection">
Los tres
TODO
siguientes establecenresid
propiedades, que son abreviaturas del identificador de recurso. Un recurso es una cadena y creará estas tres cadenas en un paso posterior. Por ahora, debe proporcionar los identificadores a los recursos. El botónlabel
debe leerToggle Protection
, pero el Identificador de esta cadena debe serProtectionButtonLabel
, por lo que el elementoLabel
debe tener este aspecto:<Label resid="ProtectionButtonLabel" />
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 lo que usamos el mismo identificador de recurso:ProtectionButtonLabel
. La descripción de la información sobre herramientas seClick to turn protection of the worksheet on and off
. Pero el Identificador debe serProtectionButtonToolTip
. Cuando haya terminado, el elementoSuperTip
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 nuevoControl
solo es una copia del elementoIcon
del existenteControl
.El elemento
Action
incluido en el elemento originalControl
, que ya estaba presente en el manifiesto, tiene el tipo establecido enShowTaskpane
, 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 reemplaceTODO5
con que es el tipo de acción para los botones que desencadenan funciones personalizadas. La etiqueta de apertura del elementoAction
debe tener este aspecto:<Action xsi:type="ExecuteFunction">
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 debería abrirse en el panel de tareas. Pero un elementoAction
del tipoExecuteFunction
tiene un elemento secundario que indica el nombre de la función que el control ejecuta. Creará esa función en un paso posterior y se llamarátoggleProtection
. Por lo tanto, reemplaceTODO6
por la marcación 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>
Desplácese hacia abajo hasta la sección
Resources
del manifiesto.Agregue la siguiente marcación como elemento secundario del elemento
bt:ShortStrings
.<bt:String id="ProtectionButtonLabel" DefaultValue="Toggle Worksheet Protection" />
Agregue el siguiente marcado como elemento secundario del elemento
bt:LongStrings
.<bt:String id="ProtectionButtonToolTip" DefaultValue="Click to protect or unprotect the current worksheet." />
Guarde el archivo.
Cree la función que proteja la hoja
Abra el archivo .\commands\commands.js.
Agregue la siguiente función justo después de la función
action()
. Tenga en cuenta que especificamos un parámetroargs
para la función y la última línea de la función llama aargs.completed
. Este es un requisito para todos los comandos de complemento de tipoExecuteFunction
. Indica la aplicación de host de Office que ha terminado la función y la interfaz de usuario puede ser receptiva de nuevo.async function toggleProtection(args) { await Excel.run(async (context) => { // TODO1: Queue commands to reverse the protection status of the current worksheet. await context.sync(); }) .catch(function (error) { console.log("Error: " + error); if (error instanceof OfficeExtension.Error) { console.log("Debug info: " + JSON.stringify(error.debugInfo)); } }); args.completed(); }
Agregue la línea siguiente al final del archivo:
Office.actions.associate("toggleProtection", toggleProtection);
En la función
toggleProtection()
, reemplaceTODO1
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á elTODO2
en la sección siguiente.const 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á. Pero el código que agregó en el último paso llama a la propiedad sheet.protection.protected
, que se trata de una diferencia significante con respecto a las funciones anteriores que escribió, porque el objeto sheet
solo es un proxy que existe en el script del panel tareas. No sabe cuál es el estado de protección real del documento, así que su propiedad protection.protected
no puede tener un valor real. Es necesario obtener primero el estado de protección del documento y usarlo con el valor de sheet.protection.protected
. Solo en ese momento se puede llamar a sheet.protection.protected
sin que se produzca una excepción. Este proceso de obtención consta de tres pasos:
- Ponga a la cola un comando para cargar (es decir, obtener) las propiedades que el código necesita leer.
- 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. - 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.
En la función
toggleProtection()
, reemplaceTODO2
con el siguiente código:sheet.load('protection/protected'); await context.sync();
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 propiedadprotection
. 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 de alternancia, que lee
sheet.protection.protected
, no se ejecuta hasta quesync
se complete ysheet.protection.protected
se haya asignado el valor correcto que se captura del documento, debe ir después delawait
operador .
Cuando haya terminado, la función completa debería parecerse a la siguiente:
async function toggleProtection(args) { await Excel.run(async (context) => { const sheet = context.workbook.worksheets.getActiveWorksheet(); sheet.load('protection/protected'); await context.sync(); if (sheet.protection.protected) { sheet.protection.unprotect(); } else { sheet.protection.protect(); } await context.sync(); }) .catch(function (error) { console.log("Error: " + error); if (error instanceof OfficeExtension.Error) { console.log("Debug info: " + JSON.stringify(error.debugInfo)); } }); args.completed(); }
- Cada objeto de Excel tiene un método
Compruebe que guardó todos los cambios que realizó en el proyecto.
Probar el complemento
Cierre todas las aplicaciones de Office, Excel incluido.
Elimine la memoria caché de Office al eliminar el contenido de la carpeta de caché. Esto es necesario para borrar completamente la versión anterior del complemento del host.
Para Windows:
%LOCALAPPDATA%\Microsoft\Office\16.0\Wef\
.Para macOS:
~/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 el host de Office (por ejemplo,Excel
)~/Library/Containers/com.microsoft.{host}/Data/Library/Application Support/Microsoft/Office/16.0/Wef/
donde{host}
es el host de Office (por ejemplo,Excel
)com.microsoft.Office365ServiceV2/Data/Caches/com.microsoft.Office365ServiceV2/
Si el servidor web local ya se está ejecutando, para detenerlo, escriba el siguiente comando en el símbolo del sistema.
npm stop
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.
En la pestaña Inicio de Excel, elija el botón Activar o desactivar la protección de la hoja de cálculo. La mayoría de los controles de la cinta están desactivados (y visualmente atenuados) como se ve en la siguiente captura de pantalla.
Seleccione una celda como lo haría si quisiera cambiar su contenido. Excel muestra un mensaje de error que indica que la hoja de cálculo está protegida.
Seleccione el botón Alternar la protección de la hoja de cálculo otra vez para habilitar de nuevo los controles y volver a cambiar los valores de la celda.
Resumen
En este ejercicio, ha aprendido a inmovilizar la fila de encabezado de la tabla que creó anteriormente, para que permanezca visible incluso cuando el usuario se desplace hacia abajo en la hoja de cálculo. También ha aprendido a activar y desactivar la protección de la hoja de cálculo.