Español · English
Convierte las fórmulas de tu hoja de cálculo en un script de Python (pandas) comentado en español, y comprueba celda por celda que da exactamente los mismos resultados.
Tienes un archivo de Excel con fórmulas que repites cada semana o cada mes: sumas por tienda, búsquedas de precios, alertas de inventario. Esta herramienta lo lee y escribe un script de Python que hace los mismos cálculos. Después lo prueba: ejecuta el script con los datos de tu archivo y compara cada resultado con el que muestra tu hoja. Solo te dice "coincide" si coinciden todas las celdas.
Nunca cambia tu archivo: solo lo lee.
- Para quien hace el mismo reporte en Excel una y otra vez y quiere automatizarlo.
- Para quien está aprendiendo pandas (la librería de Python para tablas de datos) y quiere ver cómo se escribe en Python lo que ya sabe hacer con fórmulas.
- Para equipos que quieren pasar un proceso de hojas de cálculo a Python sin perder la confianza en los números.
Important
No cambia tu archivo. Solo lo lee; las pruebas verifican que queda idéntico. Tus datos no salen de tu computadora. Todo se calcula en tu equipo. Solo dice "coincide" con pruebas. Si una celda no se pudo reproducir, te dice cuál y por qué.
-
Ten a mano tu archivo (
.xlsx). Ábrelo y guárdalo una vez en Excel o LibreOffice para que los resultados de las fórmulas queden guardados. -
Pídele a tu asistente de IA que lo convierta. Si usas Claude Code u otro agente de IA (un asistente que puede trabajar con archivos en tu computadora), copia y pega este mensaje:
Instala el skill hoja-a-python desde https://github.com/alejandrocimentada/hoja-a-python y luego pasa a Python mi archivo reporte_mensual.xlsxCambia
reporte_mensual.xlsxpor el nombre de tu archivo.¿No tienes un agente de IA? Así empiezas (5 minutos)
- Qué es un agente de IA: un asistente, como Claude Code, que puede trabajar con archivos en tu computadora: leerlos, ejecutar programas y explicarte los resultados.
- Abre la terminal (la ventana donde se escriben comandos):
- Windows: presiona la tecla Windows, escribe "PowerShell" y ábrelo.
- Mac: presiona Cmd + Espacio, escribe "Terminal" y ábrela.
- Instala Claude Code siguiendo la guía oficial de inicio rápido (pasos 1 y 2). Necesitarás una cuenta de Claude; la guía explica qué planes incluyen Claude Code.
- Ve a la carpeta de tu archivo en la terminal. Ejemplo:
- Windows:
cd "$HOME\Documents\Reportes" - Mac:
cd ~/Documents/Reportes
- Windows:
- Escribe
claudey presiona Enter para abrir el agente. La primera vez te pedirá iniciar sesión con tu cuenta de Claude. Luego pega el mensaje del paso 2.
-
Confirma qué resultados te importan. El agente te muestra un mapa de tu archivo: dónde están los datos, qué fórmulas hay y en qué orden, y qué resultados finales propone reproducir. Tú confirmas (por ejemplo: "solo la hoja Resumen").
-
Recibe el script y la prueba. En la carpeta de tu archivo aparecen tres archivos nuevos:
Archivo Qué es reporte_mensual_pandas.pyEl script de Python. Cada paso tiene encima la fórmula de Excel que reemplaza. reporte_mensual_resultado.xlsxLos resultados que calcula el script, en las mismas hojas y celdas que tu original. reporte_mensual_prueba.xlsxLa prueba: cuántas celdas se compararon, cuántas coinciden y, si alguna no, cuál y por qué. El agente también te explica en español qué hace cada paso del script.
-
El mes que viene, con un archivo nuevo de la misma estructura:
python reporte_mensual_pandas.py reporte_octubre.xlsx resultado_octubre.xlsx
Así quedan algunos pasos de los ejemplos de ventas e inventario. El comentario dice qué fórmula de Excel reemplaza y en qué celdas, y el código es pandas normal, el que verías en un curso:
# --- Paso 3. Ventas · columna «Importe» ---
# (multiplicación)
# Reemplaza =E2*F2 en Ventas!G2:G121
ventas["Importe"] = ventas["Cantidad"] * ventas["Precio"]
# --- Paso 6. Resumen · columna «Electrónica» ---
# (suma con varias condiciones)
# Reemplaza =SUMIFS(Ventas!$G:$G,Ventas!$B:$B,$A2,Ventas!$C:$C,B$1) en Resumen!B2:B6
# Excel no distingue mayúsculas: los textos se comparan en minúsculas (.str.lower()).
# Suma por «Tienda» con groupby (una sola vez para todas las filas)
electronica_por_tienda = (
ventas[ventas["Categoría"].str.lower() == "electrónica"]
.groupby(ventas["Tienda"].str.lower())["Importe"]
.sum()
)
resumen["Electrónica"] = resumen["Tienda"].str.lower().map(electronica_por_tienda).fillna(0)
# --- Paso 5. Inventario · columna «Estado» ---
# (varias condiciones en orden)
# Reemplaza =IFS(D2=0,"Sin ventas",C2/D2>Parametros!$B$1,"Sobrestock",C2/D2<Parametros!$B$2,"Riesgo de quiebre",TRUE,"OK") en Inventario!F2:F41
inventario["Estado"] = np.select(
[
inventario["Venta diaria promedio"] == 0,
inventario["Stock (unidades)"] / inventario["Venta diaria promedio"] > umbral_sobrestock_dias,
inventario["Stock (unidades)"] / inventario["Venta diaria promedio"] < umbral_riesgo_quiebre_dias,
],
["Sin ventas", "Sobrestock", "Riesgo de quiebre"],
default="OK",
)En vez de arrastrar una fórmula hacia abajo, una sola línea calcula toda la columna. Cada fórmula
se traduce a la forma habitual de pandas: np.where y np.select para SI y SI.CONJUNTO, groupby
para SUMAR.SI.CONJUNTO y compañía, .map() sobre una tabla indexada para BUSCARV, BUSCARX e
INDICE + COINCIDIR, .str para textos, .dt y pd.offsets para fechas, .rank(), .idxmax()…
Los nombres salen de las etiquetas de tu hoja: la celda «Sobrestock si la cobertura supera (días)»
se vuelve umbral_sobrestock_dias.
Solo cuando pandas no tiene una forma directa que dé exactamente el mismo resultado que Excel, el
script define una función pequeña al final, explicada en español. La más común es redondear: el
.round() de pandas redondea "al par" (2.5 → 2) y Excel no (2.5 → 3). Otras aparecen solo en casos
especiales, como una búsqueda aproximada (BUSCARV con VERDADERO) o un comodín ?. El script funciona
solo: necesita pandas, numpy y openpyxl, y nada de esta herramienta.
La prueba ejecuta el script con los datos de tu archivo y compara cada celda con fórmula de los resultados que elegiste contra el valor que guardó tu hoja de cálculo:
- Números: coinciden si la diferencia es de 0.005 o menos (medio centavo).
- Textos: tienen que ser exactamente iguales, con mayúsculas y espacios.
- Errores de Excel (
#N/A,#DIV/0!): coinciden si el script deja la celda vacía. Se cuentan aparte en el reporte.
El reporte tiene tres pestañas: Resumen (celdas comparadas, coincidencias, diferencias y el porcentaje), Diferencias (hoja, celda, valor en Excel, valor del script y causa probable) y Excluidas (celdas que no se pudieron comparar, con el motivo).
Si algo no coincide, el agente te explica cada diferencia, corrige el script y repite la prueba (hasta 3 intentos). Si aun así no coincide, te lo dice tal cual.
| Ejemplo | Qué calcula | Celdas comparadas | Resultado |
|---|---|---|---|
| Ventas por tienda | 120 ventas → importe, mes y cierre de mes; SUMAR.SI.CONJUNTO por tienda y categoría, total, ranking, % del total, INDICE + COINCIDIR | 396 | ✅ 396 de 396 (100 %) |
| Cobertura de inventario | Stock y venta diaria de 8 productos en 5 tiendas → días de cobertura, alerta de sobrestock (>30 días) y de quiebre (<3 días), unidades a pedir y resumen por tienda | 154 | ✅ 154 de 154 (100 %); 1 celda con HOY() excluida |
| Lista de precios | Pedido con códigos mal escritos → ESPACIOS/MAYUSC, BUSCARV, BUSCARX, INDICE + COINCIDIR, SI.ERROR, descuentos por categoría | 68 | ✅ 68 de 68 (100 %) |
Los scripts generados y los reportes de prueba están en examples/resultados/.
| Tipo | Funciones (nombre en inglés / en español) |
|---|---|
| Sumas y conteos | SUM/SUMA, SUMIF(S)/SUMAR.SI(.CONJUNTO), COUNT/CONTAR, COUNTA/CONTARA, COUNTIF(S)/CONTAR.SI(.CONJUNTO), AVERAGE/PROMEDIO, AVERAGEIF(S)/PROMEDIO.SI(.CONJUNTO), MIN, MAX |
| Condiciones | IF/SI, IFS/SI.CONJUNTO, IFERROR/SI.ERROR, IFNA/SI.ND, AND/Y, OR/O, NOT/NO |
| Redondeo | ROUND/REDONDEAR, ROUNDUP/REDONDEAR.MAS, ROUNDDOWN/REDONDEAR.MENOS, ABS, INT/ENTERO |
| Búsquedas | VLOOKUP/BUSCARV, XLOOKUP/BUSCARX, INDEX/INDICE + MATCH/COINCIDIR, RANK.EQ/JERARQUIA.EQV |
| Texto | LEFT/IZQUIERDA, RIGHT/DERECHA, MID/EXTRAE, LEN/LARGO, CONCAT/CONCATENAR y &, TRIM/ESPACIOS, UPPER/MAYUSC, LOWER/MINUSC |
| Fechas | DATE/FECHA, YEAR/AÑO, MONTH/MES, DAY/DIA, EOMONTH/FIN.MES, TODAY/HOY (se calcula pero no entra en la prueba) |
| Otros | Operaciones (+ − × ÷ ^ %), comparaciones, referencias a otras hojas y tablas resumen hechas con fórmulas |
La herramienta detecta estas cosas, te explica qué significan y nunca las finge:
| Lo que encuentra | Qué pasa |
|---|---|
| Macros (VBA) | No se ejecutan ni se traducen. El agente te pregunta qué hace la macro. |
| Power Query | No se traduce. El script lee la tabla tal como quedó cargada en la hoja. |
| Tablas dinámicas | No se traducen tal cual. Te propone rehacer el resumen con groupby de pandas (esa parte no entra en la prueba automática). |
| Vínculos a otros archivos | No se siguen. Esas celdas quedan sin traducir y se excluyen de la prueba. |
| HOY, AHORA, ALEATORIO | Se calculan, pero no se pueden comparar: cambian cada vez que abres el archivo. |
| DESREF (OFFSET), INDIRECTO | No se traducen en esta versión. Se marcan NO TRADUCIDA y se excluyen. |
Referencias de tabla (Tabla1[Precio]), fórmulas matriciales de varias celdas |
No se traducen en esta versión. |
Cuando algo se excluye, la prueba no dice "coincide": dice INCOMPLETA y lista esas celdas. La única excepción son HOY/AHORA/ALEATORIO, que se excluyen siempre porque no tienen un valor fijo.
- Script: un archivo de texto con instrucciones que la computadora ejecuta. Aquí, un archivo
.pyde Python. - pandas: una librería de Python para trabajar con tablas de datos, como una hoja de cálculo pero con código.
- DataFrame: una tabla en pandas. Cada columna se usa como
tabla["Nombre de la columna"]. - Valor guardado: el resultado que tu hoja de cálculo guardó la última vez que calculó una fórmula. La prueba compara contra ese valor.
- Tolerancia: la diferencia máxima que se acepta entre dos números (0.005) para no fallar por decimales invisibles.
¿Mis datos se envían a algún lugar? No. Todo se calcula en tu computadora.
¿Necesito saber programar? No, si usas un agente de IA. Pero el script está comentado en español para que puedas leerlo y aprender.
¿Puedo usar el script con el archivo del mes que viene? Sí, si tiene la misma estructura (mismas hojas y columnas). Puede tener más o menos filas.
¿Por qué la prueba dice "INCOMPLETA"? Porque alguna celda usa algo que esta versión no traduce (ver la tabla de arriba). El reporte dice cuál.
¿Funciona con Google Sheets?
Descarga la hoja como .xlsx (Archivo → Descargar → Microsoft Excel) y úsala igual.
hoja-a-python es una skill para agentes de IA (Claude Code, Codex y otros agentes compatibles
con SKILL.md) que también funciona como comando independiente.
Requisitos: Python 3.10 o superior y pip.
Claude Code (macOS / Linux)
git clone https://github.com/alejandrocimentada/hoja-a-python.git
mkdir -p ~/.claude/skills/hoja-a-python
cp -R hoja-a-python/. ~/.claude/skills/hoja-a-python/
pip install -r ~/.claude/skills/hoja-a-python/requirements.txtClaude Code (Windows PowerShell)
git clone https://github.com/alejandrocimentada/hoja-a-python.git
New-Item -ItemType Directory -Force "$HOME\.claude\skills\hoja-a-python" | Out-Null
Copy-Item -Recurse -Force "hoja-a-python\*" "$HOME\.claude\skills\hoja-a-python\"
pip install -r "$HOME\.claude\skills\hoja-a-python\requirements.txt"Codex
git clone https://github.com/alejandrocimentada/hoja-a-python.git
mkdir -p ~/.codex/skills/hoja-a-python
cp -R hoja-a-python/. ~/.codex/skills/hoja-a-python/
pip install -r ~/.codex/skills/hoja-a-python/requirements.txtpython scripts/hoja_a_python.py mapa libro.xlsx # entradas, cálculos, salidas y avisos
python scripts/hoja_a_python.py generar libro.xlsx --salidas "Resumen,Datos!A1:F50"
python scripts/hoja_a_python.py probar libro.xlsx libro_pandas.py # escribe libro_prueba.xlsxmapa --json da el mismo mapa en JSON. generar acepta --script y --resultado para elegir
rutas; por defecto escribe junto al libro, y nunca dentro de la carpeta de la skill. probar
acepta --reporte y --tolerancia. Códigos de salida de probar: 0 coincide, 1 no coincide,
2 error (el script falló o el libro no tiene valores guardados), 3 incompleta.
- Lee el libro dos veces con openpyxl (en modo lectura): una para las fórmulas y otra para los
valores guardados. Detecta macros, Power Query, tablas dinámicas y vínculos externos mirando
dentro del
.xlsx(que es un zip). - Analiza cada fórmula (tokenizador de openpyxl + un analizador propio) y encuentra los bloques: tablas con encabezado, columnas que repiten la misma fórmula hacia abajo y celdas sueltas.
- Ordena los cálculos según de qué depende cada uno y propone como salidas los bloques que ninguna otra fórmula usa.
- Traduce: una columna con la misma fórmula en todas las filas se vuelve una línea de pandas
sobre columnas enteras. Si cada fila apunta a otra fila (un saldo acumulado, por ejemplo), se
traduce celda por celda. Para cada fórmula intenta primero la forma nativa de pandas/numpy, y la
usa solo si se comporta como Excel con esos datos. Para eso mira el tipo de cada columna según los
valores guardados: con textos mezclados usa
pd.to_numeric, y con claves de texto compara en minúsculas. Si no hay forma nativa segura, copia dentro del script una función auxiliar que imita a Excel. - Prueba: ejecuta el script en un proceso aparte, sobre los datos del libro, y compara cada celda con fórmula de las salidas contra el valor guardado. Calcula el hash del libro antes y después.
- 135 pruebas automáticas (
pytest): el analizador de fórmulas, la semántica de cada función (redondeo como Excel, comodines*y?, mayúsculas, celdas vacías, búsquedas aproximadas…), el mapa, la generación, la prueba, un script equivocado a propósito que debe dar diferencias, la detección de lo no soportado y la verificación con hash de que los archivos de entrada no cambian. También verifican que cada script generado solo importa pandas, numpy, openpyxl y la biblioteca estándar, que se ejecuta en otra carpeta sin la skill, que los ejemplos usan las formas nativas (np.select,groupby,.map…) y que lo que no tiene forma nativa sigue coincidiendo con la función auxiliar. - Los valores guardados de los ejemplos los calculó Microsoft Excel (versión 16.0, automatizado
con COM desde
examples/construir_ejemplos.py), no esta herramienta. La idea original era usar LibreOffice en modo headless; no estaba instalado en la máquina donde se construyeron, así que el script usa el primer motor disponible (LibreOffice → Excel → una referencia en Python) y anota cuál usó enexamples/motor_de_calculo.json. - Doble verificación de los ejemplos: además,
construir_ejemplos.pycalcula los mismos 618 valores con Python puro (sin pandas y sin el código de la skill), y coinciden todos con los de Excel (python examples/construir_ejemplos.py --verificar). - Los archivos con tabla dinámica, Power Query y vínculo externo de las pruebas los creó Excel
de verdad (
tests/fixtures/construir_fixtures.py). El caso de macros usa unvbaProject.binsimulado, porque Excel bloquea crear macros por automatización. - Una prueba a mano con un libro nuevo (comisiones de vendedores, que no está en el repositorio ni se usó para escribir el código), calculado por Excel: el script coincidió en todas las celdas comparadas. Esa prueba encontró dos mensajes confusos que se corrigieron. Se repitió con la versión que genera pandas nativo: 96 de 96 con las salidas propuestas, igual que la versión anterior.
- Probado solo con los ejemplos, ese libro y libros de prueba, todavía no con archivos reales de empresas.
- Las causas probables del reporte son pistas automáticas (heurísticas), no un diagnóstico seguro.
- Celdas vacías en cálculos: Excel trata una celda vacía como 0 en una operación; pandas la deja vacía (NaN). Si tus datos tienen huecos, la prueba lo mostrará como diferencia.
- Errores de Excel y celdas vacías se representan igual en el script (NaN). Por eso SI.ERROR también reemplaza celdas vacías, y un error de Excel coincide con una celda vacía en la prueba.
- Comparaciones de texto con
=en una fórmula (por ejemplo=SI(A2="Norte";…)): Excel no distingue mayúsculas y el script sí. Las búsquedas y SUMAR.SI/CONTAR.SI sí lo imitan, comparando en minúsculas. - Búsquedas que encuentran una celda vacía: Excel devuelve 0;
.map()daría vacío. Por eso, si la columna que se devuelve tiene huecos en tu libro, el script usa la función auxiliarbuscarv. Si los huecos aparecen recién en el archivo del mes siguiente, esas filas quedan vacías en vez de 0. - Sumar días a una fecha (
=A2+30) puede fallar en el script; las funciones de fecha soportadas sí funcionan. - Rangos de columna completa (
A:A) que mezclan una tabla con otras celdas debajo no se traducen. - Encabezados: se asume una fila de encabezados de texto; tablas sin encabezado se traducen celda por celda.
- Tamaño: lo nativo (
groupby,.map,np.select) es rápido. Las funciones auxiliares, que solo aparecen en casos especiales, recorren filas en Python y con cientos de miles de filas pueden tardar. - Solo
.xlsxy.xlsm. Los.xlsantiguos y.csvhay que guardarlos como.xlsx.
pip install -r requirements.txt pytest
python -m pytest # 135 pruebas
python examples/construir_ejemplos.py # reconstruye los ejemplos (LibreOffice → Excel → Python)
python examples/construir_ejemplos.py --verificar # compara los valores guardados con la referencia en PythonPara regenerar examples/resultados/ (las rutas dentro de la skill necesitan
--dentro-de-la-skill, que solo existe para esto):
python scripts/hoja_a_python.py generar examples/ventas_por_tienda.xlsx --script examples/resultados/ventas_por_tienda_pandas.py --dentro-de-la-skill
python scripts/hoja_a_python.py probar examples/ventas_por_tienda.xlsx examples/resultados/ventas_por_tienda_pandas.py --dentro-de-la-skill(con --salidas "Inventario,Resumen" para el ejemplo de inventario). El banner se genera desde
docs/banner.html.
Proyecto independiente, sin relación con Microsoft ni con The Document Foundation. Microsoft Excel es una marca registrada de Microsoft Corporation, LibreOffice es una marca registrada de The Document Foundation y Python es una marca registrada de la Python Software Foundation. "Excel" se usa aquí solo para describir los archivos con los que funciona.
MIT © 2026 Alejandro Cimentada.
