Tablas con filas «multicolumna» en Org Mode (un apaño)
El sistema de tablas en texto plano que proporciona Org Mode es extremadamente potente,
además de que resulta una delicia tener en un periquete una tabla armada con un par de
pulsaciones de teclado. No obstante, también adolece de ciertas limitaciones menores,
especialmente en lo que atañe a la disposición de la tabla en la exportación a otros
formatos. Son, ya digo, pequeños inconvenientes que no deslucen en absoluto el conjunto, y
que probablemente algunos de ellos sean resueltos en futuras versiones del modo del
unicornio. Entre todos estos pecata minuta una funcionalidad que echo mucho en falta,
por ejemplo, es la de poder construir tablas con filas multicolumna, es decir, filas que
abarquen todas o una parte de las columnas de una tabla. Una forma de salir del paso de
este escollo es usar dentro de Org el otro constructor de tablas que se incluye en GNU
Emacs, el paquete table.el
, que sí permite expansión de filas y de celdas, entre otras
bondades, pero que es algo latoso de usar o de domar, y menos intuitivo y ágil que el
sistema tabular de Org. Y lo peor es que nos veremos bastante limitados para controlar el
formato de estas tablas, ya que el soporte que presta Org a table.el
es muy escueto. Si
puedo, prefiero no usar esta opción. Pero por suerte podemos ensayar otros apaños, gracias
a un poco de Elisp y las facilidades que Org nos presta para fabricarnos nuestros propios
filtros de exportación.
Contamos, en efecto, con un buen ramillete de hooks cuyas funciones se evalúan en el
pre-proceso, y que se enfocan en distintos aspectos de la exportación o de las partes del
documento. El que aquí nos interesa es el que está focalizado en las tablas:
org-export-filter-table-functions
. A este hook le anclaremos una función típica de
sustitución condicional (el principal argumento será la o las tablas de nuestro documento)
que se encargue de reemplazar por expresiones regulares (sí, las gratas expresiones
regulares: no queda otra) una marcas textuales que nos sacaremos enseguida del sombrero, a
fin de generar el formato de salida que nos apetece. Partamos, por ejemplo, de que lo que
queremos es exportar nuestras tablas con filas expandidas a LATEX. Si en nuestra
tabla de (pongamos por caso) cinco columnas deseamos que la primera fila ocupe todas las
columnas, nuestra meta entonces es llegar a la macro de LATEX:
\multicolumn{5}{|c|}{nuestro texto de la fila} \\
Refrescando un poco la memoria latexiana, la macro multicolumn
indica que queremos una fila que se extienda por cinco
columnas (primer argumento), que su contenido esté centrado y entre sendas líneas (segundo argumento) y que el contenido
de esa fila expandida no sea otro que el que encerramos en el tercer argumento. Para llegar a esto, la notación de
marcas que nos sacamos del gorro para nuestro apaño sería el siguiente:
z-nuestro texto de la fila-z,5,c
No hace falta ser un lince para traducirlo: el texto de la fila encerrado entre z-...-z
,
una coma, el número de columnas a expandir, otra coma y por último la marca de centrado
que precisa el código de LATEX. Pero el apaño aún no está completo del todo: ¿cómo
metemos una celda espandida dentro de la tabla de Org si, sencillamente, no podemos hacer
tal cosa? Solución un pelín sucia, pero es lo que hay: dejamos el resto de celdas de la
fila vacías. Lo interesante (al menos a efectos visuales) es que nuestra celda llena quede
en el centro, aunque no es necesario . Así pues, nuestra tabla quedaría como ésta:
|-------+-------+----------------------------------+-------+-------| | | | z-nuestro texto de la fila-z,5,c | | | |-------+-------+----------------------------------+-------+-------| | celda | celda | celda | celda | celda | | celda | celda | celda | celda | celda | | celda | celda | celda | celda | celda | |-------+-------+----------------------------------+-------+-------|
Ya sólo nos queda escribir nuestra función, que podemos incluir directamente en nuestro
documento de Org como bloque de código y anclarla al hook que queremos mediante la marca
#+BIND:
:
#+begin_src emacs-lisp :exports results :results none (defun tabla-latex (texto backend info) "modificaciones entorno `tabular" (when (org-export-derived-backend-p backend 'latex) (replace-regexp-in-string "[&\s]*z-\\(.+\\)-z,\\([[:digit:]]+\\),\\(.\\)[&\s]*" "\\\\multicolumn{\\2}{|\\3|}{\\1}" texto))) #+end_src
Si exportamos el documento (y aceptados los permisos que nos solicite Emacs para evaluar la función), el código LATEX resultante será, por fin:
\begin{tabular}{lllll} \hline \multicolumn{5}{|c|}{nuestro texto de la fila}\\ \hline celda & celda & celda & celda & celda\\ celda & celda & celda & celda & celda\\ celda & celda & celda & celda & celda\\ \hline \end{tabular}
¿Y si queremos que la tabla se exporte a HTML
con las mismas marcas que nos habíamos sacado del sombrero, y con parejo
resultado? Pues entonces la función que tendríamos que anclar al hook, teniendo en cuenta el código HTML
que
queremos lograr, podría parecerse a esta otra:
#+begin_src emacs-lisp :exports results :results none (defun tabla-html (texto backend info) "modificaciones tablas html" (when (org-export-derived-backend-p backend 'html) (replace-regexp-in-string "<th\sscope=\"col\"\sclass=\"org-left\">z-\\(.+\\)-z,\\(.\\),.</th>" "<th colspan=\"\\2\"\sscope=\"col\"\sclass=\"org-center\">\\1</th>" (replace-regexp-in-string "<.+> <.+>" "" texto)))) #+end_src
Al exportar a HTML
, obtendríamos nuestra tabla con la primera fila multicolumna:
Es evidente que no es la más elegante de las soluciones, pero, al menos como queríamos, nos hace el apaño, en espera de que nuestro querido Org Mode pueda contar algún día con una funcionalidad tan grata como es la de las filas expandidas en una tabla.
Actualización de 17/11/20: para multicolumnas parciales
Podemos ensayar esta otra posibilidad en el código, al menos en la salida a LATEX, que permite multicolumnas parciales y además simplifica considerablemente el regexp. Basta con rellenar, como en el caso anterior, una sola celda (con las marcas que hemos comentado), y poner en las celdas vacías de esa misma fila los signos «!!».
#+begin_src emacs-lisp :exports results :results none (defun tabla-latex (texto backend info) "modificaciones entorno `tabular" (when (org-export-derived-backend-p backend 'latex) (replace-regexp-in-string "z-\\(.+\\)-z,\\([[:digit:]]+\\),\\(.\\)" "\\\\multicolumn{\\2}{\\3}{\\1}" (replace-regexp-in-string "!!\s+&" "" (replace-regexp-in-string "&\s+!!" "" #+end_src
Y nuestra tabla, con una fila multicolumna de tres celdas, quedaría así:
|---------------------------------------+-------+-------+-------+-------| | z-texto que ocupa tres columnas-z,3,c | !! | !! | !! | !! | |---------------------------------------+-------+-------+-------+-------| | celda | celda | celda | celda | celda | | celda | celda | celda | celda | celda | | celda | celda | celda | celda | celda | |---------------------------------------+-------+-------+-------+-------|
Produciendo este código en LATEX:
\begin{center} \begin{tabular}{lllll} \hline \multicolumn{3}{c}{texto que ocupa tres columnas} \\ \hline celda & celda & celda & celda & celda\\ celda & celda & celda & celda & celda\\ celda & celda & celda & celda & celda\\ \hline \end{tabular} \end{center}
∞
Publicado: 14/04/20
Última actualización: 21/01/22
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.