Reportia

Actualizado 4 junio 2026 · 15 min de lectura

Automatizar reportes PDF y Excel desde base de datos

Cada mes, alguien en tu empresa abre Excel, copia datos del sistema, ajusta formatos, genera un PDF, y lo envía por email. Ese proceso manual toma 2-4 horas y es propenso a errores.

En este tutorial te muestro cómo automatizarlo completamente: tu script consulta la base de datos, genera el reporte (PDF o Excel), y lo envía por email. Todo en menos de 50 líneas de Python.

Arquitectura de la solución

El flujo es simple:

  1. Cron/scheduler dispara tu script cada mes (o semana, o día)
  2. Script Python consulta tu BD (PostgreSQL, MySQL, SQLite)
  3. JSON estructurado con los datos del reporte
  4. API Reportia convierte JSON → PDF/Excel profesional
  5. Email automático envía el reporte al destinatario

Sin Chromium. Sin LaTeX. Sin Excel COM. Solo HTTP + JSON.

1 Consultar la base de datos

import psycopg2
from datetime import datetime, timedelta

# Conectar a PostgreSQL
conn = psycopg2.connect(
    host="localhost", dbname="mi_app",
    user="readonly", password="secret"
)
cur = conn.cursor()

# Datos del mes anterior
mes_anterior = datetime.now().replace(day=1) - timedelta(days=1)
inicio = mes_anterior.replace(day=1)
fin = mes_anterior

cur.execute("""
    SELECT producto, COUNT(*) as ventas, SUM(monto) as ingreso
    FROM ordenes
    WHERE fecha BETWEEN %s AND %s
    AND status = 'completada'
    GROUP BY producto
    ORDER BY ingreso DESC
""", (inicio, fin))

productos = [
    {"producto": r[0], "ventas": r[1], "ingreso": float(r[2])}
    for r in cur.fetchall()
]

cur.execute("""
    SELECT COUNT(DISTINCT cliente_id), SUM(monto), AVG(monto)
    FROM ordenes
    WHERE fecha BETWEEN %s AND %s AND status = 'completada'
""", (inicio, fin))

total = cur.fetchone()
resumen = {
    "clientes_activos": total[0],
    "ingreso_total": float(total[1]),
    "ticket_promedio": round(float(total[2]), 2)
}

conn.close()

2 Generar el reporte con la API

import requests

response = requests.post(
    "https://reportia.4l3.org/v1/render",
    headers={"Authorization": "Bearer TU_API_KEY"},
    json={
        "template": "reporte-mensual",
        "format": "pdf",  # o "xlsx" para Excel
        "data": {
            "titulo": f"Reporte de ventas - {mes_anterior.strftime('%B %Y')}",
            "periodo": f"{inicio.strftime('%d/%m/%Y')} - {fin.strftime('%d/%m/%Y')}",
            "resumen": resumen,
            "tabla": productos,
            "generado": datetime.now().isoformat(),
            "moneda": "MXN"
        }
    }
)

# Guardar el archivo
nombre = f"reporte_{mes_anterior.strftime('%Y-%m')}.pdf"
with open(nombre, "wb") as f:
    f.write(response.content)

print(f"Reporte generado: {nombre} ({len(response.content)//1024} KB)")

3 Enviar por email

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders

msg = MIMEMultipart()
msg["From"] = "[email protected]"
msg["To"] = "[email protected]"
msg["Subject"] = f"Reporte de ventas - {mes_anterior.strftime('%B %Y')}"

body = f"""Hola,

Adjunto el reporte de ventas de {mes_anterior.strftime('%B %Y')}.

Resumen:
- Clientes activos: {resumen['clientes_activos']}
- Ingreso total: ${resumen['ingreso_total']:,.2f} MXN
- Ticket promedio: ${resumen['ticket_promedio']:,.2f} MXN

Este reporte se genera automáticamente.
"""
msg.attach(MIMEText(body, "plain"))

# Adjuntar PDF
with open(nombre, "rb") as f:
    adjunto = MIMEBase("application", "pdf")
    adjunto.set_payload(f.read())
    encoders.encode_base64(adjunto)
    adjunto.add_header("Content-Disposition", f"attachment; filename={nombre}")
    msg.attach(adjunto)

with smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls()
    server.login("[email protected]", "app_password")
    server.send_message(msg)

print("Email enviado")

4 Programar con cron

Agrega una línea al crontab para que se ejecute el primer día de cada mes:

# Ejecutar a las 8am del primer día de cada mes
0 8 1 * * cd /opt/reportes && python3 generar_reporte.py >> /var/log/reportes.log 2>&1

También funciona con:

Caso real: reportes semanales para agencia de marketing

Una agencia digital en CDMX genera reportes semanales de campañas para 15 clientes. Antes:

Después de automatizar con Reportia:

PDF vs Excel: ¿cuál generar?

Genera ambos con el mismo JSON. Solo cambia el campo format:

# Generar ambos formatos del mismo reporte
for fmt in ["pdf", "xlsx"]:
    r = requests.post(api_url, json={**payload, "format": fmt}, headers=headers)
    ext = "pdf" if fmt == "pdf" else "xlsx"
    with open(f"reporte.{ext}", "wb") as f:
        f.write(r.content)

Automatiza tus reportes hoy

50 documentos gratis al mes. Sin tarjeta. API REST para Python, JavaScript, PHP y más.

Empezar gratis →

Preguntas frecuentes

¿Cómo automatizar la generación de reportes PDF mensuales?

Crea un script Python que consulte tu base de datos, estructure los datos en JSON, y los envíe a la API de Reportia. Programa el script con cron para que se ejecute automáticamente cada mes.

¿Puedo generar reportes Excel automáticos desde PostgreSQL?

Sí. Consulta tus datos con psycopg2 o SQLAlchemy, estructura el resultado en JSON, y envíalo a Reportia con format: xlsx. Recibes un .xlsx profesional con formato.

¿Qué es mejor para reportes automáticos, PDF o Excel?

Depende del receptor. PDF para presentación y distribución (clientes, gerencia). Excel para análisis y manipulación de datos (contabilidad, operaciones). Reportia genera ambos desde el mismo JSON.

¿Funciona con MySQL, MongoDB, SQLite?

Sí. Reportia recibe JSON estándar. No importa de dónde vengan los datos: PostgreSQL, MySQL, MongoDB, SQLite, archivos CSV, APIs externas. Tú generas el JSON, Reportia genera el documento.