Puedes automatizar un reporte de Excel con Python escribiendo un solo script que lea tus exportaciones, calcule el resumen, genere un archivo .xlsx con formato y corra de forma programada. La librería pandas se encarga de los datos, openpyxl del formato de Excel, y el programador de tareas de tu sistema lo ejecuta cada semana sin que tengas que abrir un solo archivo.
¿Por qué automatizar reportes de Excel con Python?
Muchos reportes semanales siguen la misma rutina: descargar varios CSV, pegarlos en un libro, actualizar una tabla dinámica, arreglar el formato y enviar el resultado por correo. Es repetitivo, y cada copiar y pegar manual es una oportunidad para equivocarse. Un script de Python hace exactamente los mismos pasos cada vez, deja la lógica por escrito y termina en segundos.
Python no es la única opción de automatización. Antes de escribir código, conviene ver dónde encaja:
| Herramienta | Fortalezas | Limitaciones |
|---|---|---|
| Power Query (dentro de Excel) | Sin código, se actualiza con un clic, excelente para limpiar y combinar archivos | Alguien tiene que abrir Excel y darle a Actualizar; el formato y el envío son manuales |
| Macros VBA | Viven dentro del libro y controlan cualquier función de Excel | Solo corren en Excel de escritorio y son más difíciles de mantener y compartir |
| Power Automate / flujos en la nube | Buenos para mover archivos y enviar correos entre apps de Microsoft | La lógica de datos compleja se vuelve incómoda; las funciones dependen de tu licencia |
| Python (pandas + openpyxl) | Maneja archivos grandes, lógica compleja y muchas fuentes; se programa por completo | Hay que instalar Python y aprender lo básico |
Si tu reporte solo necesita limpiar y combinar datos, empieza con Power Query en Excel. Cuando necesites que todo el proceso corra solo, Python es el siguiente paso natural.
Paso 1: Prepara el proyecto y carga tus datos
Crea la carpeta del proyecto
- Instala Python 3 y ejecuta
pip install pandas openpyxlen una terminal. - Crea una carpeta, por ejemplo
weekly_report, con dos subcarpetas:datapara las exportaciones originales youtputpara los reportes terminados. - Guarda tus exportaciones con un patrón de nombre consistente, como
sales_2026-10-19.csv. Ese patrón predecible es lo que permite que el script encuentre los archivos solo. - Crea un archivo vacío llamado
weekly_report.py. Todo el código de abajo va en ese único archivo.
En este ejemplo, cada CSV tiene las columnas date, account, product, units y revenue. Cambia los nombres para que coincidan con tus exportaciones. Si prefieres probar cada paso de forma interactiva, constrúyelo primero en un notebook como explicamos en nuestra guía de Jupyter Notebooks y luego copia el código que funciona al script.
Carga y combina todas las exportaciones
Este bloque busca todos los archivos que siguen el patrón, los apila en una sola tabla, elimina filas duplicadas exactas (útil cuando dos exportaciones se traslapan) y agrega una columna week con el lunes en que empieza cada semana.
from pathlib import Path
import pandas as pd
DATA = Path("data")
OUT = Path("output")
OUT.mkdir(exist_ok=True)
files = sorted(DATA.glob("sales_*.csv"))
sales = pd.concat(
(pd.read_csv(f, parse_dates=["date"]) for f in files),
ignore_index=True,
).drop_duplicates()
sales["week"] = sales["date"].dt.to_period("W").dt.start_time
parse_dates en las columnas de fecha. Si las fechas se cargan como texto, agrupar por semana o por mes va a fallar o, peor aún, se ordenará mal sin mostrar ningún error.Paso 2: Construye el resumen
La mayoría de los reportes de ventas responde una pregunta sencilla: ¿cómo le fue a cada cuenta esta semana comparada con la anterior? El código crea una tabla dinámica con una fila por cuenta y una columna por semana, y luego calcula el cambio porcentual.
this_week = sales["week"].max()
prev_week = this_week - pd.Timedelta(weeks=1)
summary = (
sales[sales["week"].isin([prev_week, this_week])]
.pivot_table(index="account", columns="week", values="revenue",
aggfunc="sum", fill_value=0)
.reindex(columns=[prev_week, this_week], fill_value=0)
)
summary.columns = ["prev_week", "this_week"]
summary["change_pct"] = (
summary["this_week"] / summary["prev_week"] - 1
).where(summary["prev_week"] > 0)
summary = summary.sort_values("this_week", ascending=False).reset_index()
Dos detalles lo hacen robusto. La línea reindex garantiza que existan las dos columnas de semana aunque una cuenta no haya vendido la semana pasada, y .where(...) deja el cambio vacío en lugar de dividir entre cero. Esas pequeñas protecciones son la diferencia entre un script en el que confías y uno que tienes que vigilar. Para aprender más sobre cómo transformar datos así, mira nuestro tutorial de pandas para usuarios de Excel.
Paso 3: Genera el archivo de Excel con formato
Ahora escribe el resumen y los datos detallados en dos hojas. El nombre del archivo incluye la semana, así nunca se sobrescriben los reportes anteriores.
report = OUT / f"weekly_sales_{this_week:%Y-%m-%d}.xlsx"
with pd.ExcelWriter(report, engine="openpyxl") as writer:
summary.to_excel(writer, sheet_name="Summary", index=False)
sales.to_excel(writer, sheet_name="Detail", index=False)
Una exportación sin formato se ve a medio terminar, así que el último paso aplica formato con openpyxl: encabezado de color, formatos de moneda y porcentaje, la primera fila inmovilizada y la primera columna más ancha.
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill
wb = load_workbook(report)
ws = wb["Summary"]
for cell in ws[1]:
cell.font = Font(bold=True, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="1F4E78")
for row in ws.iter_rows(min_row=2, min_col=2, max_col=3):
for cell in row:
cell.number_format = '"$"#,##0'
for cell in ws["D"][1:]:
cell.number_format = "0.0%"
ws.freeze_panes = "A2"
ws.column_dimensions["A"].width = 28
wb.save(report)
print(f"Report saved: {report}")
Ejecuta el script con python weekly_report.py. Abre el archivo en la carpeta output y compara los totales de un par de cuentas con tu reporte manual. Comparar contra un número en el que ya confías es la prueba más importante de todas.
Paso 4: Prográmalo para que corra solo
Windows: Programador de tareas
- Abre el Programador de tareas (Task Scheduler) y elige Crear tarea básica.
- Elige un desencadenador, por ejemplo semanal, los lunes a las 7:00 a. m.
- Como acción, elige Iniciar un programa. En Programa o script pon la ruta completa de
python.exe; en Agregar argumentos,weekly_report.py; y en Iniciar en, la carpeta de tu proyecto. - Guárdala, haz clic derecho sobre la tarea y elige Ejecutar para probarla de inmediato.
macOS y Linux: cron
Ejecuta crontab -e y agrega una línea como esta (ajusta las rutas):
# Todos los lunes a las 7:00 a. m.
0 7 * * 1 cd /home/me/weekly_report && /usr/bin/python3 weekly_report.py
Uses el programador que uses, la computadora tiene que estar encendida a esa hora. Si eso es un problema, más adelante puedes correr el mismo script en un servidor o en una máquina en la nube.
¿Quieres que el reporte también llegue por correo? Los módulos incluidos en Python, smtplib y email, pueden adjuntar el archivo y enviarlo; y en entornos Microsoft muchos equipos prefieren que Power Automate tome el archivo nuevo desde una carpeta compartida. Sigue las reglas de TI de tu empresa para enviar correos desde scripts y nunca guardes contraseñas en texto plano dentro del código.
Problemas comunes y cómo evitarlos
- Cambian los nombres de las columnas. Si un sistema cambia Revenue por Net Revenue, el script se detiene. Agrega al inicio una verificación con la lista de columnas obligatorias que muestre un mensaje claro cuando falte alguna.
- Archivos abiertos. En Windows, escribir en un libro que está abierto en Excel da un error de permisos. Como cada reporte tiene un nombre nuevo con fecha, casi no pasa, pero cierra los archivos viejos antes de probar.
- Carpeta de trabajo equivocada. Los programadores de tareas suelen arrancar en otro directorio. Configurar Iniciar en (o el
cden cron) resuelve la mayoría de los errores de "archivo no encontrado". - Fallas silenciosas. Escribe en cada ejecución una línea de registro con la fecha y la cantidad de filas, para darte cuenta si alguna semana no se generó.
Próximos pasos
Elige el reporte que más veces rehaces, anota en papel sus pasos manuales y tradúcelos a las cuatro etapas de arriba: cargar, resumir, escribir y programar. Empieza solo con la hoja de resumen, confirma durante dos o tres semanas que los números coinciden con tu versión manual y luego agrega el formato y la programación. Si todavía estás diseñando el reporte en sí, nuestra guía para crear un reporte semanal de ventas en Excel explica qué métricas y qué diseño incluir.
Mira: lecciones en video

Preguntas frecuentes
¿Necesito tener Excel instalado para crear archivos de Excel con Python?
No. pandas y openpyxl escriben archivos .xlsx directamente, así que el script puede correr en una computadora o servidor sin Excel. Solo necesitas Excel para abrir y revisar el resultado.
¿Python puede actualizar tablas dinámicas en un libro existente?
openpyxl no recalcula ni actualiza tablas dinámicas. Lo habitual es crear el resumen en pandas y escribirlo como una tabla normal, o usar una librería solo para Windows que controla Excel de escritorio.
¿Python es mejor que VBA para automatizar reportes?
No siempre. VBA es práctico para automatizaciones que se quedan dentro de un libro, mientras que Python es más fuerte con datos grandes, varias fuentes y tareas programadas sin supervisión.
¿Cómo me aseguro de que el reporte automatizado esté correcto?
Córrelo en paralelo con tu reporte manual durante algunos ciclos y compara los totales clave. Agrega verificaciones de columnas faltantes y de cantidad de filas para que un problema detenga el script en vez de generar un archivo equivocado.
Marca esta lección como completada para seguir tu progreso.