Crear y editar archivos Excel con Python permite automatizar informes, facturas, inventarios, calendarios y procesos administrativos. Pandas resulta cómodo para trabajar con tablas completas, mientras que openpyxl permite controlar celdas, fórmulas, estilos, hojas, anchos y gráficos dentro de archivos .xlsx. La elección depende de si tu prioridad es transformar datos o diseñar una hoja de cálculo.
Para complementar esta guía, consulta el tutorial de importación de Excel con Pandas, la guía de Pandas para principiantes, el artículo sobre pathlib, el manejo de excepciones y la introducción a automatización con Python.
Las referencias externas principales son el tutorial oficial de openpyxl y la documentación oficial de DataFrame.to_excel.
Instalar las bibliotecas
python -m pip install pandas openpyxl
Utiliza un entorno virtual y comprueba que las bibliotecas pertenecen al mismo intérprete:
python -m pip show pandas openpyxl
Crear un libro con openpyxl
from openpyxl import Workbook
libro = Workbook()
hoja = libro.active
hoja.title = "Ventas"
hoja["A1"] = "Producto"
hoja["B1"] = "Cantidad"
hoja["C1"] = "Precio"
libro.save("reporte.xlsx")
Un libro nuevo incluye una hoja activa. Cambiar su título facilita encontrarla posteriormente. Guarda con extensión .xlsx.
Añadir filas completas
filas = [
["Teclado", 3, 49.90],
["Ratón", 5, 19.50],
["Monitor", 2, 189.00],
]
for fila in filas:
hoja.append(fila)
libro.save("reporte.xlsx")
append() añade valores en la siguiente fila libre. Mantén el mismo orden de columnas y valida los tipos antes de escribir.
Crear fórmulas
hoja["D1"] = "Total"
for numero_fila in range(2, hoja.max_row + 1):
hoja[f"D{numero_fila}"] = (
f"=B{numero_fila}*C{numero_fila}"
)
hoja[f"D{hoja.max_row + 1}"] = f"=SUM(D2:D{hoja.max_row})"
openpyxl escribe la fórmula, pero no calcula su resultado. Excel u otra aplicación compatible la calculará al abrir el archivo. No confíes en valores de caché antiguos para procesos críticos.
Aplicar estilos al encabezado
from openpyxl.styles import Font, PatternFill, Alignment
relleno = PatternFill("solid", fgColor="D9EAF7")
for celda in hoja[1]:
celda.font = Font(bold=True)
celda.fill = relleno
celda.alignment = Alignment(horizontal="center")
Evita crear miles de estilos distintos en un bucle. Reutiliza objetos de estilo cuando sea posible.
Formatos numéricos
for numero_fila in range(2, hoja.max_row + 1):
hoja[f"C{numero_fila}"].number_format = '#,##0.00'
hoja[f"D{numero_fila}"].number_format = '#,##0.00'
El formato modifica la presentación, no el valor almacenado. Guarda cantidades y precios como números, no como strings con símbolos.
Ajustar anchos de columnas
from openpyxl.utils import get_column_letter
for columna in range(1, hoja.max_column + 1):
letra = get_column_letter(columna)
longitud = max(
len(str(hoja.cell(fila, columna).value or ""))
for fila in range(1, hoja.max_row + 1)
)
hoja.column_dimensions[letra].width = min(longitud + 2, 40)
El límite evita columnas enormes cuando una celda contiene texto largo.
Congelar encabezados y activar filtros
hoja.freeze_panes = "A2"
hoja.auto_filter.ref = hoja.dimensions
Congelar la primera fila facilita navegar por informes grandes. El filtro permite ordenar y seleccionar valores desde Excel.
Crear varias hojas
resumen = libro.create_sheet("Resumen")
resumen["A1"] = "Indicador"
resumen["B1"] = "Valor"
resumen.append(["Productos", len(filas)])
Comprueba si el nombre ya existe antes de crear una hoja:
if "Resumen" in libro.sheetnames:
resumen = libro["Resumen"]
else:
resumen = libro.create_sheet("Resumen")
Abrir y editar un archivo existente
from openpyxl import load_workbook
libro = load_workbook("reporte.xlsx")
hoja = libro["Ventas"]
hoja["F1"] = "Revisado"
hoja["F2"] = "Sí"
libro.save("reporte_actualizado.xlsx")
Guarda primero con otro nombre durante el desarrollo. Así evitas perder el original si el proceso falla.
Leer fórmulas o valores calculados
libro_formulas = load_workbook("reporte.xlsx", data_only=False)
libro_valores = load_workbook("reporte.xlsx", data_only=True)
Con data_only=True se leen valores almacenados por la última aplicación que calculó el libro. Si nunca se recalculó, pueden estar vacíos o desactualizados.
Crear Excel desde un DataFrame
import pandas as pd
df = pd.DataFrame(filas, columns=["Producto", "Cantidad", "Precio"])
df["Total"] = df["Cantidad"] * df["Precio"]
df.to_excel(
"ventas_pandas.xlsx",
index=False,
sheet_name="Ventas",
)
Pandas es ideal para filtros, agrupaciones, uniones y transformaciones antes de exportar.
Escribir varias hojas con Pandas
resumen_df = pd.DataFrame({
"Indicador": ["Productos", "Unidades", "Importe"],
"Valor": [
len(df),
df["Cantidad"].sum(),
df["Total"].sum(),
],
})
with pd.ExcelWriter(
"informe_completo.xlsx",
engine="openpyxl",
) as escritor:
df.to_excel(escritor, sheet_name="Ventas", index=False)
resumen_df.to_excel(escritor, sheet_name="Resumen", index=False)
El contexto garantiza que el escritor se cierre correctamente.
Combinar Pandas y openpyxl
Primero crea las tablas con Pandas y luego aplica estilos:
from openpyxl import load_workbook
libro = load_workbook("informe_completo.xlsx")
hoja = libro["Ventas"]
hoja.freeze_panes = "A2"
for celda in hoja[1]:
celda.font = Font(bold=True)
libro.save("informe_completo.xlsx")
Añadir validación de datos
from openpyxl.worksheet.datavalidation import DataValidation
validacion = DataValidation(
type="list",
formula1='"Pendiente,Revisado,Aprobado"',
allow_blank=True,
)
hoja.add_data_validation(validacion)
validacion.add("E2:E100")
Las listas desplegables reducen errores de escritura en hojas completadas manualmente.
Proteger una hoja
hoja.protection.sheet = True
hoja.protection.password = "ejemplo"
La protección de una hoja evita cambios accidentales, pero no debe considerarse cifrado fuerte. No almacenes información sensible confiando únicamente en esta contraseña.
Añadir un gráfico básico
from openpyxl.chart import BarChart, Reference
grafico = BarChart()
grafico.title = "Ventas por producto"
datos = Reference(
hoja,
min_col=4,
min_row=1,
max_row=hoja.max_row,
)
categorias = Reference(
hoja,
min_col=1,
min_row=2,
max_row=hoja.max_row,
)
grafico.add_data(datos, titles_from_data=True)
grafico.set_categories(categorias)
hoja.add_chart(grafico, "F3")
Evitar sobrescrituras
from pathlib import Path
def ruta_disponible(ruta):
ruta = Path(ruta)
if not ruta.exists():
return ruta
contador = 1
while True:
candidata = ruta.with_name(
f"{ruta.stem}_{contador}{ruta.suffix}"
)
if not candidata.exists():
return candidata
contador += 1
Manejar archivos bloqueados
try:
libro.save("reporte.xlsx")
except PermissionError:
print("Cierra el archivo en Excel o revisa los permisos")
except OSError as error:
print(f"No se pudo guardar el archivo: {error}")
En Windows, Excel puede bloquear el archivo abierto. Ofrece un nombre alternativo o solicita al usuario que lo cierre.
Validar antes de guardar
Comprueba que existan columnas obligatorias, que las cantidades sean positivas y que las fechas sean válidas. Un archivo visualmente correcto puede contener resultados equivocados si la fuente estaba incompleta.
Crear una función reutilizable
def crear_reporte(ventas, destino):
df = pd.DataFrame(ventas)
requeridas = {"producto", "cantidad", "precio"}
faltantes = requeridas - set(df.columns)
if faltantes:
raise ValueError(f"Faltan columnas: {sorted(faltantes)}")
df["total"] = df["cantidad"] * df["precio"]
df.to_excel(destino, index=False, sheet_name="Ventas")
Errores frecuentes
Los problemas habituales son sobrescribir el original, guardar números como texto, confiar en que openpyxl calcula fórmulas, crear estilos únicos para cada celda, utilizar nombres de hojas inválidos y editar un archivo abierto. También es frecuente usar openpyxl para transformaciones tabulares que Pandas resolvería de forma más clara.
Conclusión
Pandas y openpyxl se complementan. Utiliza Pandas para limpiar, filtrar y resumir datos, y openpyxl para controlar la presentación del libro. Valida la información, conserva el original, utiliza rutas seguras y prueba el archivo generado en la aplicación de destino. Con una estructura reutilizable puedes convertir informes manuales en procesos rápidos, consistentes y fáciles de auditar.






