Aspectos estructurales en WXTABLE y XLSX

Figura
Figura. Características estructurales WXTABLE

Entre las características estructurales de WXTABLE encontramos la combinación de celdas, ocultar filas o columnas, bloquear celdas, ajustar o extender el texto de una celda más allá de sus bordes y fijar cabecera o pie. La opción de extender contenido tiene algunas limitaciones como luego veremos. La de bloquear celdas no está disponible en GoogleSheet y EXCEL web. Fijar cabecera en WXTABLE es asimilable a inmovilizar filas en XLSX. Fijar pie no tiene traducción.

En este tema estudiaremos cada una de estas características usando el ejemplo que se observa en la Figura, a excepción del fijado de cabecera, que usaremos otro ejemplo. Con el enlace structural.txt puede acceder a los datos en formato WXTABLE. Y con structural.xlsx a la conversión a XLSX.

Ya hemos dicho que WXTABLE no es otra cosa que una aplicación basada en el elemento <table> de HTML. Los atributos que se permiten en sus elementos, aparte del atributo style son los siguientes:

const configAtributos = [
    //Caracter estructural
    "rowspan",
    "colspan",
    "data-extend",
    "data-locked",
    "data-head",
    "data-foot",
    //Otros atributos
    "data-id"
    "data-formula",
    "data-format",
    "data-original",
    "data-control",
    "data-error",
    "title"
];

Ya vimos en temas anteriores el atributo data-id que sirve para identificar una celda. En data-formula se guarda la fórmula de una celda, pues el resultado de la misma se almacena en la propia celda. Los atributos data-format y data-original sirven para dar formato a las celdas. Estos y data-control que guarda la información de los controles, los veremos en temas posteriores. Los atributos data-error y title sirven para presentar las celdas con error, aspecto que no será traducido a XLSX.

Y los primeros son los que vamos a ver en este tema: rowspan y colspan para combinar celdas, data-extend para ajustar texto y data-locked para bloquear celdas. La característica para ocultar filas y columnas se realiza usando el estilo CSS visibility dentro de un atributo style. Con data-head y data-foot se fijan cabecera y pie. El fijado de cabecera es similar al efecto de inmovilizar filas en XLSX.

Celdas combinadas en XLSX

Figura
Figura. Características estructurales en GoogleSheet

En la Figura vemos una captura del ejemplo en GoogleSheet, donde se combina el rango de celdas A1:B2. En WXTABLE el rango se denomina [R1C1]:[R2C2] y se usan los atributos colspan="2" y rowspan="2" pues el formato WXTABLE es una tabla HTML.

El archivo XML del XLSX que contiene los datos de la hoja es xl/worksheets/sheet1.xml. Observamos que las celdas combinadas se incluyen en el elemento <mergeCells>. Omitimos el contenido no relevante con puntos suspensivos.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
    <dimension ref="A1:C7"/>
    <sheetViews>
        <sheetView workbookViewId="0" ...></sheetView>
    </sheetViews>
    <sheetFormatPr customHeight="1" .../>
    <cols count="3">
        ...
    </cols>
    <sheetData>
        ...
    </sheetData>
    <mergeCells count="1">
        <mergeCell ref="A1:B2"/>
    </mergeCells>
</worksheet>

Filas y columnas ocultas en XLSX

Figura
Figura. Mostrar fila oculta en WXTABLE

En WXTABLE podemos ocultar filas o columnas. Se les adjudica el estilo CSS visibility con valor collapse dentro del elemento style. Tal como muestra la Figura donde la fila 4 está oculta, situándonos en una fila 3 o 5 adyacentes podemos volver a mostrar la fila oculta. Colapsar una fila o columna no significa que desaparezca. Sus celdas siguen manteniendo sus contenidos y podemos referirnos a ellas desde las celdas visibles, de igual forma que sucede en XLSX.

En XLSX las columnas se declaran en un elemento <col>. En el elemento <sheetData> se declaran las filas en los elementos <row>. Si la fila o columna no está oculta no es necesario que lleve la propiedad hidden="0", aunque he decidido incoporarla siempre. Si está oculta tendrá un valor 1, como sucede en el ejemplo con la cuarta fila:

<cols count="3">
    <col min="1" max="1" hidden="0" customWidth="1" width="10.6640625"/>
    <col min="2" max="2" hidden="0" customWidth="1" width="10.6640625"/>
    <col min="3" max="3" hidden="0" customWidth="1" width="10.6640625"/>
</cols>
<sheetData>
    ...
    <row r="3" hidden="0">
        <c r="A3" t="s" s="0">
            <v>1</v>
        </c>
    </row>
    <row r="4" hidden="1">
        <c r="A4"/>
        <c r="B4"/>
        <c r="C4"/>
    </row>
    <row r="5" hidden="0">
        <c r="A5" t="s" s="0">
            <v>2</v>
        </c>
    </row>
    ...
</sheetData>

Celdas con texto extendido (ajuste de texto) en XLSX

Figura
Figura. Ajuste de texto en WXTABLE

La opción para extender texto (ajuste de texto) en WXTABLE permite cinco opciones como se observa en la Figura. Tenemos un texto con un salto de línea en medio que hemos replicado en varias celdas, cada una con un color diferente. Disponen de un atributo data-extend con los valores none, width, height, both y clip respectivamente.

La primera celda con texto de color negro tiene data-extend="none". Realmente no porta ese atributo tomando ese valor por defecto. El elemento tabla de HTML trata el texto reemplazando uno o más espacios, incluso saltos de línea, por un único espacio e incrementando el alto de la fila para albergar el texto. Este es el comportamiento por defecto cuando el estilo CSS width-space tiene el valor por defecto normal, estilo que inicialmente tienen las celdas en WXTABLE.

La celda con texto rojo tiene data-extend="width" con lo que el texto se extiende a lo ancho. La de texto azul tiene data-extend="height" extendiéndose a lo alto, pero manteniendo el ancho. La de color verde tiene data-extend="both" extendiéndose en ambas direcciones. Aunque en las celdas adyacentes no hay contenido, si lo hubiera quedaría por debajo del texto. Observe que esa celda está seleccionada apareciendo el área de la celda extendiéndose a la derecha y abajo sobre otras celdas. Por último la de color violeta tiene data-extend="clip" recortándose el texto al tamaño de la celda.

Este comportamiento es posible en HTML, como se observa en esta tabla HTML que insertamos a continuación, donde su estructura es esencialmente la misma que uso en WXTABLE. Se consigue dando posición relativa a la tabla y posición absoluta a las celdas que se extienden. No voy a explicar más sobre esto pues se sale del objetivo de estos temas, pero puede ver con detalle el HTML y el CSS en el desplegable bajo la tabla.

123
11234567890 abcedfghij
21234567890 abcedfghij
3
41234567890 abcedfghij
5
61234567890 abcedfghij

Veamos ahora la traducción desde WXTABLE a XLSX del ejemplo de la Figura.

Figura
Figura. Ajuste de texto en GoogleSheet y EXCEL

Este ejemplo, cuyos datos en formato WXTABLE puede consultar en el enlace text-adjust.txt y en XLSX en text-adjust.xlsx, no puede traducirse correctamente en GoogleSheet y en EXCEL, como se observa en la captura de la Figura.

XLSX sólo parece soportar dos tipos de ajuste en la propiedad wrapText. Con valor 0 no se realiza ajuste y el texto sobresale de la celda pero solo a lo ancho. Con valor 1 se ajusta el texto incrementándose el alto de la celda para albergarlo. GoogleSheet respesta el salto de línea cuando no se realiza ajuste, mientras que EXCEL lo elimina.

La propidad wrapText se encuentra en el archivo XML de estilo xl/styles.xml. En un tema posterior hablaremos más a fondo de los estilos. Por ahora solo contamos que hay un elemento <cellXfs> que contiene los estilos de las celdas de todo el libro.

<cellXfs count="6">
    <xf borderId="0" fillId="0" ...>
        <alignment ... wrapText="1"/>
    </xf>
    <xf borderId="0" fillId="0" ...>
        <alignment ... wrapText="1"/>
    </xf>
    <xf borderId="0" fillId="0" ....>
        <alignment ... wrapText="0"/>
    </xf>
    <xf borderId="0" fillId="0" ...>
        <alignment ... wrapText="0"/>
    </xf>
    <xf borderId="0" fillId="0" ...>
        <alignment ... wrapText="0"/>
    </xf>
    <xf borderId="0" fillId="0" ....>
        <alignment ... wrapText="1"/>
    </xf>
</cellXfs>

Se indexan desde cero. La posición cero se reserva para celdas donde no se declara estilo o están vacías. En el archivo xl/worksheets/sheet1.xml encontramos la hoja de datos, con las filas y celdas declaradas en el elemento <sheetData>. A fin de abreviar sólo presentamos la primera fila que contiene la celda con texto negro y la segunda fila con la celda con texto rojo.

<sheetData>
    <row r="1" hidden="0">
        <c r="A1" t="s" s="1">
            <v>0</v>
        </c>
        <c r="B1" s="1"/>
        <c r="C1" s="1"/>
    </row>
    <row r="2" hidden="0">
        <c r="A2" t="s" s="2">
            <v>0</v>
        </c>
        <c r="B2" s="1"/>
        <c r="C2" s="1"/>
    </row>
    ...
<sheetData>

La primera celda con texto negro tiene el estilo s="1". Este es el segundo elemento en la colección de elementos <xf>, observándose que tiene wrapText="1", al igual que la última celda con texto magenta. Las celdas con texto rojo, azul y verde tienen wrapText="0" que hace que se extienda el texto.

Figura
Figura. Overflow, wrap y clip text en GoogleSheet

GoogleSheet dispone de una aplicación de hoja de cálculo que permite ajustar texto con las opciones overflow, wrap y clip. En la Figura se observa como se extiende o desborda el texto, se envuelve y se recorta a la celda con cada una de las opciones respectivamente. Esto es en parte parecido a lo que hace WXTABLE.

Sin embargo hay que entender que cuando se crea una hoja nueva en la aplicación de GoogleSheet y se descarga en formato XLSX algunas características no serán exportadas o se adaptarán a los requisitos del estándar XLSX. Esta es una de ellas y esas opciones se reducen a wrapText tal como vimos antes.

En la siguiente tabla se resume el comportamiento para ajustar texto en WXTABLE, GoogleSheet y EXCEL web.

WXTABLEdata-extendGoogleSheetGoogleSheet to XLSXEXCEL (XLSX)
No extendernone (sin atributo)wrapwrapText = 1wrapText = 1
Extender anchowidthoverflowwrapText = 0wrapText = 0
Extender altoheightoverflowwrapText = 0wrapText = 0
Extender ambosbothoverflowwrapText = 0wrapText = 0
RecortarclipclipwrapText = 0wrapText = 1

Bloquear celdas en WXTABLE y XLSX

Figura
Figura. Celda bloqueada en WXTABLE

En WXTABLE podemos bloquear una celda dotándola del atributo data-locked. Una celda bloqueada no permite ningún tipo de modificación, como se observa en la Figura, donde todas las opciones del menú aparecen desactivadas menos la opción para desbloquear la celda. Ese bloqueo es sin contraseña, puesto que su objetivo es simplemente impedir cambios indebidos.

En OOX se define la protección de celdas en el apartado 18.3.1.85 sheetProtection (Sheet Protection Options), página 1701. En el archivo XML de datos de la hoja xl/worksheets/sheet1.xml insertaríamos el elemento <sheetProtection sheet="1" algorithmName="SHA-1" hashValue="a9993e364706816aba3e25717850c26c9cd0d89d" insertRows="1"/>. Con la propiedad sheet="1" activaríamos la protección de las hojas. Le pasaríamos el valor hasValue de una contraseña ("abc" en este caso) usando algún algoritmo entre los permitidos, como SHA-1. Parece que también podría ser posible no incluir contraseña. Luego agregaríamos tantas activaciones como deseáramos, por ejemplo, con insertRows="1" activamos la protección que impide insertar filas en las hojas.

Las protecciones que se pueden aplicar son autoFilter, deleteColumns, deleteRows, formatCells, formatColumns, formatRows, insertColumns, insertHyperlinks, insertRows, selectLockedCells, selectUnlockedCell y sort.

Y en el apartado 18.8.33 protection (Protection Properties), página 1802, se define que una vez declarada la protección de hojas se puede aplicar a una celda con la propiedad locked="1". Por ejemplo, en <c r="A5" t="s" s="0" locked="1">.

Figura
Figura. Protección hoja en GoogleSheet

Y eso es lo que he podido deducir del documento OOX desde un punto de vista teórico, pues no lo he podido poner en práctica dado que nada de eso funciona en EXCEL web ni en GoogleSheet que no soportan la protección. GoogleSheet no lo soporta cuando la hoja se importó como XLSX (edición Microsoft Office), como se observa en la Figura al buscar ayuda sobre protección de hoja.

Figura
Figura. Protección hoja en EXCEL web

Como se observa la Figura, si buscamos ayuda sobre protección de hoja en EXCEL web, nos encontramos que nos ofrece que abramos el archivo en una aplicación EXCEL de escritorio para poder aplicar la protección.

Fijar cabecera en WXTABLE o inmovilizar paneles en XLSX

Figura
Figura. Fijar cabecera y pie en WXTABLE

En WXTABLE podemos fijar una cabecera y un pie como se observa en la Figura. En este ejemplo se fijan las dos primeras filas como cabecera y la última fila como pie, filas a las que he puesto un color verde de fondo. El ejemplo es una lista con 163 filas de tal forma que en pantalla se muestran sólo los datos de 10 filas en cada página. El grupo de filas de cabecera o pie se separa con una barra gris horizontal, permaneciendo siempre visibles esas filas. Con los botones y podemos navegar por páginas.

La configuración en WXTABLE permite definir el número de filas por página. Por defecto se establece en 10 filas tal como se observa en la Figura.

En XLSX un efecto parecido es el de inmovilizar paneles. No es exactamente lo mismo, pero si que sirve para uno de sus objetivos que es mantener una o más filas superiores inmóviles y poder desplazar el panel inferior manteniendo visible esas primeras filas. En XLSX también pueden fijarse una o más de las primeras columnas, pero algo similar no es soportado en WXTABLE.

Puede descargar el objeto WXTABLE del ejemplo en el enlace head.txt y la exportación a XLSX en head.xlsx.

Figura
Figura. Inmovilizar panel horizontal en GoogleSheet

En la Figura se observa el resultado en GoogleSheet inmovilizando las dos primeras filas. Se observa una barra gris entre la segunda y tercera fila. Esta barra horizontal y también la vertical se arrastran desde los bordes gruesos del primer selector superior izquierda de la hoja.

Figura
Figura. Inmovilizar panel horizontal en GoogleSheet

Observe en la Figura que en EXCEL web para inmovilizar las dos primeras filas hemos de ubicarnos en la celda A3 y usar el menú de Inmovilizar Paneles.

En la entrada de atributos del origen de datos de WXTABLE del ejemplo encontramos los atributos data-head y data-foot:

"attributes":{
    "1,0":{"data-head":""},
    "2,0":{"data-head":"end"},
    "163,0":{"data-foot":"start"},
    "1,1":{"rowspan":"1","colspan":"3"},
    "163,1":{"rowspan":"1","colspan":"3","data-formula":"=date()"}
}

Esos atributos se incluyen en los elementos <tr> de la tabla WXTABLE. Observe que hay dos filas fijadas en la cabecera, de tal forma que la que porte el valor "end" será la última del grupo de cabecera. De forma similar la primera que porte el valor "start" será la primera del grupo del pie, aunque en este caso sólo hay un fila fijada en el pie. Podemos exportar a XLSX la cabecera pero no el pie, pues no hay algo semejante en XLSX.

La exportación a XLSX se incluye en el archivo xl/worksheets/sheet1.xml de la hoja correspondiente, en un elemento <sheetView> que contiene información de la vista de la hoja:

<worksheet ...">
    <dimension ref="A1:C163"/>
    <sheetViews>
        <sheetView workbookViewId="0" zoomScaleSheetLayoutView="100" zoomScaleNormal="100" tabSelected="1">
            <pane state="frozen" activePane="bottomLeft" topLeftCell="A3" ySplit="2"/>
            <selection sqref="A3" activeCell="A3" pane="bottomLeft"/>
        </sheetView>
    </sheetViews>
    <sheetFormatPr .../>
    ...
</worksheet>

La vista da información del escalado o zoom inicial y la hoja seleccionada. En WXTABLE no hay configuración de este tipo, por lo que siempre se exportará la información con el 100% de zoom y la primera hoja seleccionada.

El elemento <pane> traduce el fijado de cabecera con la referencia en la celda A3, inmovilizando las dos primeras filas. También es posible definir que celda aparecerá seleccionada, en este caso la misma A3.