https://fotosycaptura.cl

Bitácora personal del capitán @fotosycaptura ✨

Org Mode, tablas y exportación: cuando una hoja de cálculo se encuentra con Python


Texto alternativo

Una de las cosas que más me gustan de Org Mode es que, a simple vista, parece un formato de texto plano bastante sencillo. Sin embargo, a medida que se profundiza, se descubre que es una auténtica navaja suiza para organizar información, realizar cálculos, generar informes e incluso automatizar tareas.

Veamos lo que he ido descubriendo mientras experimento...

El problema

Recientemente me encontré con una necesidad: tenía que trabajar con varias tablas de datos en un documento que estaba realizando en Org Mode, estuve realizando unos cálculos sencillos y con ello realizar una imagen, pero también, tenía que pensar en que es muy probable que tenga que presentar los números para compartirla con usuarios que viven en el mundo de Excel.

Lo que parecía una tarea con diversas herramientas de ofimática, donde habría mucho copiar y pegar de un lado a otro, terminó siendo una interesante exploración de las capacidades de Org Mode.

Para ejemplificar, Supongamos algo sencillo, imaginen que se tiene una tabla de costos:

| Año  | Costo    |
|------|----------|
| 2026 | 17250000 |
| 2027 | 25875000 |
| 2028 | 38812500 |

Para Org Mode esos números son perfectos. Son fáciles de utilizar en fórmulas y cálculos.

Para los seres humanos con tú que estás leyendo esto, no tanto.

No es lo mismo leer:

38812500

que leer:

38.812.500

Para el ser humano, es mas fácil con los separadores de miles.

La primera idea: usar TBLFM

Org Mode incorpora un sistema de fórmulas mediante la directiva #+TBLFM:.

Por ejemplo:

#+TBLFM: $2=$1*1.5

Y gracias a esta directiva, es que se pueden realizar cálculos de manera similar a una hoja de cálculo.

Sin embargo, las opciones de formato numérico disponibles no agregan automáticamente separadores de miles como el común de los mortales podría esperar.

Es decir, se puede calcular fácilmente:

25875000

pero no necesariamente mostrar:

25.875.000

así sin más...

Emacs Lisp

La solución natural en Emacs consistiría en escribir una función en Emacs Lisp que reciba un número y devuelva una cadena formateada.

Algo como:

(defun miles (n)
  ...)

Y luego utilizarla desde las fórmulas de la tabla.

Funciona bastante bien.

Sin embargo, yo quería juntar todas las tablas desperdigadas en el documento y unirlas en una sola, principalmente porque estoy realizando un documento de matriz de riesgos, que está segmentado por diversos temas, pero estoy seguro que en algún punto tendré que juntar todas y cada una de esas tablas para que alguien visualice esa matriz en una hoja de cálculo más amigable...

Y ahí fue donde apareció una idea interesante.

Dejar que Python haga el trabajo pesado

En Emacs, en Org Mode existe algo denominado Babel que permite ejecutar código de diversos lenguajes, entre ellos Python, y con ello se puede aprovechar para generar tablas listas para presentar o más bien, exportar...

Por ejemplo, has cuenta que se tienen estas dos tablas:

#+NAME: servidores_locales
| Nombre | SO      | RAM |
|--------|---------|-----|
| srv01  | Linux   | 4   |
| srv02  | Windows | 16  |

#+NAME: servidores_nube
| Nombre | SO      | RAM |
|--------|---------|-----|
| vm01   | Linux   | 8   |
| vm02   | Windows | 32  |

Se puede combinar o fusionar mediante Python:

#+BEGIN_SRC python :var t1=servidores_locales t2=servidores_nube :results table
resultado = [
    ["Nombre", "SO", "RAM"]
]

resultado.extend(t1)
resultado.extend(t2)

return resultado
#+END_SRC

El resultado será una única tabla consolidada:

| Nombre | SO      | RAM |
|--------|---------|-----|
| srv01  | Linux   | 4   |
| srv02  | Windows | 16  |
| vm01   | Linux   | 8   |
| vm02   | Windows | 32  |

Y aquí es donde Python realmente brilla.

Formateando números de forma amigable

Una simple función puede mejorar considerablemente la legibilidad de los datos:

def miles(n):
    return f"{int(n):,}".replace(",", ".")

Por ejemplo:

miles(38812500)

produce:

38.812.500

Mucho más agradable para la vista.

Exportar a Excel sin sufrimiento

Una vez que los datos están en Python, generar un archivo Excel es sorprendentemente sencillo.

Puedes generar un archivo xlsx con la biblioteca openpyxl:

from openpyxl import Workbook

wb = Workbook()
ws = wb.active

for fila in resultado:
    ws.append(fila)

wb.save("informe.xlsx")

En pocos segundos se tiene un archivo listo para abrir en Excel o LibreOffice Calc.

Pero si estás en Emacs también puedes usar la función org-table-export.

Una lección interesante sobre los encabezados

Durante las pruebas observé un detalle... Esperaba que Python recibiera una tabla Org completa, incluyendo la fila de los encabezados.

Sin embargo, en las pruebas que se realizaron, Org Mode solo pudo entregar únicamente los datos.

Por eso, anteriormente preferí definir explícitamente la fila de los encabezados de esta manera:

resultado = [
    ["Nombre", "SO", "RAM"]
]

y con ello, tema resuelto.

Recomendaciones

Después de experimentar con distintas alternativas, estas son mis conclusiones:

  • Es mejor utilizar fórmulas de Org para cálculos simples: Si se necesita realizar operaciones básicas o referenciar entre tablas, #+TBLFM: es una excelente opción.
  • Es mejor utilizar Python (o el lenguaje con el que tengas mejor soltura) para otras tareas...

Cuando aparecen necesidades como:

  • Formatear números.
  • Generar archivos CSV.
  • Crear documentos Excel.
  • Consolidar múltiples tablas.

Python suele ser más flexible y fácil de mantener.

  • Separa cálculos y presentación

Una estrategia que se podría utilizar podría ser por ejemplo:

  • Mantener una tabla interna con datos "puros".
  • Realizar los cálculos necesarios.
  • Generar una tabla de presentación mediante Python.

Así se obtiene lo mejor de ambos mundos.

Conclusión

Lo que comenzó como una simple necesidad de agregar separadores de miles y después unir varias tablas en una sola, terminó convirtiéndose en una pequeña exploración de las capacidades de Org Mode, Babel y Python.

La principal lección fue descubrir que no siempre es necesario hacerlo todo dentro de las fórmulas de Org. En muchos casos resulta más cómodo utilizar Org para almacenar y organizar la información, mientras Python se encarga de procesarla, formatearla y exportarla.

Y lo mejor de todo es que al trabajar en texto plano, es fácil de versionar, respaldar y mantener.

No está nada mal para algo que aparenta ser "solo un editor de texto".