Reportia

Actualizado 6 junio 2026 · 12 min de lectura

Cómo convertir PDF a Excel con Python (API + tutorial paso a paso)

Tienes un PDF con tablas — estados de cuenta bancarios, reportes financieros, listas de precios de proveedores — y necesitas esos datos en Excel para analizarlos. Copiar a mano no es opción cuando son 50 páginas. En este tutorial te muestro cómo extraer tablas de PDFs y convertirlas a Excel (.xlsx) usando Python y una API REST.

Sin instalar dependencias pesadas. Sin configurar Java ni parsers de PDF. Un POST con tu archivo y recibes los datos estructurados.

Por qué extraer datos de PDF es difícil

Un PDF no es una hoja de cálculo. Internamente, un PDF es una serie de instrucciones de dibujo: “coloca este texto en las coordenadas (x, y)”. No hay concepto de “tabla”, “fila” o “columna”. Por eso extraer datos tabulares de un PDF es un problema de reconstrucción visual.

Las soluciones típicas tienen problemas:

Lo que necesitas: sube el PDF, recibe los datos tabulares en JSON, genera el Excel. Sin dependencias locales.

Casos de uso reales

Antes de entrar al código, estos son los escenarios donde esta solución ahorra horas cada semana:

Paso 1: Sube el PDF a la API

El primer paso es enviar tu archivo PDF al endpoint de extracción. La API analiza el documento, detecta las tablas y devuelve los datos estructurados en JSON.

import requests

api_url = "https://reportia.4l3.org/v1/extract"
headers = {
    "Authorization": "Bearer TU_API_KEY"
}

# Subir el PDF
with open("estado-cuenta-junio.pdf", "rb") as f:
    response = requests.post(
        api_url,
        headers=headers,
        files={"file": ("estado-cuenta.pdf", f, "application/pdf")},
        data={"output": "json"}
    )

if response.status_code == 200:
    datos = response.json()
    print(f"Tablas detectadas: {len(datos['tables'])}")
    print(f"Total de filas: {sum(len(t['rows']) for t in datos['tables'])}")
else:
    print(f"Error: {response.status_code} - {response.text}")

La respuesta es un JSON con un array tables. Cada tabla tiene sus encabezados (headers) y filas (rows):

{
  "tables": [
    {
      "page": 1,
      "headers": ["Fecha", "Concepto", "Cargo", "Abono", "Saldo"],
      "rows": [
        ["01/06/2026", "Depósito nómina", "", "25000.00", "25000.00"],
        ["03/06/2026", "Pago luz CFE", "850.00", "", "24150.00"],
        ["05/06/2026", "Transferencia SPEI", "5000.00", "", "19150.00"]
      ]
    }
  ],
  "metadata": {
    "pages": 3,
    "tables_found": 1,
    "total_rows": 47
  }
}

Paso 2: Convierte los datos a Excel

Con los datos ya estructurados en JSON, el siguiente paso es generar el archivo Excel. Envía los datos al endpoint /v1/render con formato xlsx:

import requests

# Paso 1: Extraer datos del PDF
extract_url = "https://reportia.4l3.org/v1/extract"
headers = {"Authorization": "Bearer TU_API_KEY"}

with open("estado-cuenta-junio.pdf", "rb") as f:
    extract_resp = requests.post(
        extract_url,
        headers=headers,
        files={"file": ("estado-cuenta.pdf", f, "application/pdf")},
        data={"output": "json"}
    )

datos = extract_resp.json()

# Paso 2: Generar Excel con los datos extraídos
render_url = "https://reportia.4l3.org/v1/render"
payload = {
    "template": "tabla-datos",
    "format": "xlsx",
    "data": {
        "titulo": "Estado de cuenta - Junio 2026",
        "hojas": [
            {
                "nombre": f"Tabla página {tabla['page']}",
                "headers": tabla["headers"],
                "rows": tabla["rows"]
            }
            for tabla in datos["tables"]
        ]
    }
}

render_resp = requests.post(
    render_url,
    json=payload,
    headers={**headers, "Content-Type": "application/json"}
)

if render_resp.status_code == 200:
    with open("estado-cuenta.xlsx", "wb") as out:
        out.write(render_resp.content)
    print("Excel generado: estado-cuenta.xlsx")
else:
    print(f"Error: {render_resp.status_code}")

El resultado es un archivo .xlsx con una hoja por cada tabla detectada, encabezados formateados y datos listos para filtrar y graficar en Excel.

Prueba gratis: 50 documentos/mes sin tarjeta

Extrae datos de PDFs y genera Excel desde tu aplicación en minutos.

Ver planes →

Procesar múltiples PDFs en lote

El verdadero poder está en la automatización. Si tu despacho contable recibe 40 estados de cuenta al mes, no vas a procesarlos uno por uno:

import requests
import os
import json

api_extract = "https://reportia.4l3.org/v1/extract"
api_render = "https://reportia.4l3.org/v1/render"
headers = {"Authorization": "Bearer TU_API_KEY"}

carpeta_pdfs = "./estados-cuenta/"
carpeta_salida = "./excels/"
os.makedirs(carpeta_salida, exist_ok=True)

archivos = [f for f in os.listdir(carpeta_pdfs) if f.endswith(".pdf")]
print(f"Procesando {len(archivos)} archivos...")

resumen = []
for archivo in archivos:
    ruta = os.path.join(carpeta_pdfs, archivo)

    # Extraer tablas
    with open(ruta, "rb") as f:
        resp = requests.post(
            api_extract,
            headers=headers,
            files={"file": (archivo, f, "application/pdf")},
            data={"output": "json"}
        )

    if resp.status_code != 200:
        print(f"ERROR: {archivo} - {resp.status_code}")
        continue

    datos = resp.json()
    total_filas = sum(len(t["rows"]) for t in datos["tables"])

    # Generar Excel
    payload = {
        "template": "tabla-datos",
        "format": "xlsx",
        "data": {
            "titulo": archivo.replace(".pdf", ""),
            "hojas": [
                {
                    "nombre": f"Tabla {i+1}",
                    "headers": t["headers"],
                    "rows": t["rows"]
                }
                for i, t in enumerate(datos["tables"])
            ]
        }
    }

    render_resp = requests.post(
        api_render,
        json=payload,
        headers={**headers, "Content-Type": "application/json"}
    )

    nombre_xlsx = archivo.replace(".pdf", ".xlsx")
    with open(os.path.join(carpeta_salida, nombre_xlsx), "wb") as out:
        out.write(render_resp.content)

    resumen.append({"archivo": archivo, "tablas": len(datos["tables"]),
                     "filas": total_filas})
    print(f"OK: {archivo} -> {nombre_xlsx} ({total_filas} filas)")

print(f"\nResumen: {len(resumen)} archivos procesados")
for r in resumen:
    print(f"  {r['archivo']}: {r['tablas']} tablas, {r['filas']} filas")

40 PDFs convertidos a Excel en menos de 5 minutos. Sin abrir Adobe, sin copiar y pegar, sin errores humanos.

Integración con bases de datos

Una vez que tienes los datos en JSON, puedes insertarlos directamente en tu base de datos en lugar de (o además de) generar Excel:

import requests
import sqlite3

headers = {"Authorization": "Bearer TU_API_KEY"}

# Extraer datos del PDF
with open("reporte-ventas.pdf", "rb") as f:
    resp = requests.post(
        "https://reportia.4l3.org/v1/extract",
        headers=headers,
        files={"file": ("reporte.pdf", f, "application/pdf")},
        data={"output": "json"}
    )

datos = resp.json()

# Insertar en SQLite (o PostgreSQL, MySQL, etc.)
conn = sqlite3.connect("ventas.db")
cursor = conn.cursor()

for tabla in datos["tables"]:
    for fila in tabla["rows"]:
        cursor.execute(
            "INSERT INTO movimientos (fecha, concepto, monto) VALUES (?, ?, ?)",
            (fila[0], fila[1], fila[2])
        )

conn.commit()
print(f"Insertadas {sum(len(t['rows']) for t in datos['tables'])} filas")

Automatizar con cron

Para procesar PDFs automáticamente cada día (por ejemplo, estados de cuenta que llegan por email):

# Ejecutar cada día a las 8:00 AM
# crontab -e
0 8 * * * cd /app && python procesar_pdfs.py >> /var/log/pdf-a-excel.log 2>&1

Combina esto con un script que descargue adjuntos de email (con imaplib) y tendrás un pipeline completamente automático: email con PDF llega → se extrae → se convierte a Excel → se guarda o se envía.

Manejo de errores y PDFs problemáticos

No todos los PDFs son iguales. Algunos son imágenes escaneadas, otros tienen tablas mal formateadas. La API maneja estos casos:

import requests

headers = {"Authorization": "Bearer TU_API_KEY"}

with open("documento.pdf", "rb") as f:
    resp = requests.post(
        "https://reportia.4l3.org/v1/extract",
        headers=headers,
        files={"file": ("documento.pdf", f, "application/pdf")},
        data={"output": "json", "ocr": "auto"}  # OCR automático si es imagen
    )

datos = resp.json()

if datos.get("warnings"):
    for w in datos["warnings"]:
        print(f"Advertencia: {w}")

if not datos["tables"]:
    print("No se detectaron tablas en este PDF")
elif datos["metadata"].get("ocr_used"):
    print("Se usó OCR - verificar precisión de los datos")
else:
    print(f"Extracción limpia: {len(datos['tables'])} tablas")

El parámetro ocr: "auto" activa el reconocimiento óptico solo cuando el PDF es una imagen escaneada. Para PDFs con texto nativo, la extracción es directa y más precisa.

Comparativa: API vs. bibliotecas locales

Criterio Reportia API Tabula / Camelot Manual
InstalaciónNinguna (API)Java + pipN/A
PDFs escaneadosSí (OCR)No
Batch 100 archivos~5 min~30 min~8 horas
Salida directa a ExcelCSV (manual a xlsx)
MantenimientoCeroUpdates, bugsInfinito

Plantillas para Excel

Además de convertir datos crudos, puedes usar plantillas prediseñadas de Reportia para generar Excels con formato profesional: colores corporativos, logos, gráficos y fórmulas precalculadas.

De PDF a Excel en 3 líneas de código

50 documentos gratis al mes. Sin tarjeta. Sin instalar nada.

Empezar gratis →

Preguntas frecuentes

¿Funciona con PDFs escaneados (imágenes)?

Sí. Usa el parámetro ocr: "auto" y la API detecta automáticamente si el PDF necesita OCR. La precisión depende de la calidad del escaneo.

¿Qué pasa si el PDF tiene tablas en varias páginas?

La API detecta y concatena tablas que continúan entre páginas. Recibirás una sola tabla coherente con todas las filas, o tablas separadas si son independientes.

¿Puedo elegir qué páginas procesar?

Sí. Usa el parámetro pages: "1-5" o pages: "2,4,7" para procesar solo las páginas que necesitas.

¿Cuánto cuesta?

Gratis hasta 50 documentos/mes. Plan Pro desde $9 USD/mes (1,000 docs). Ver precios completos.

¿Qué formatos de salida soporta?

Excel (.xlsx), CSV, JSON y PDF. Puedes extraer datos de un PDF y regenerar un nuevo PDF con formato distinto usando las plantillas de Reportia.

Otros tutoriales: Generar facturas PDF con Python · Automatizar reportes PDF y Excel · Reportes Excel desde base de datos · Ver todos los tutoriales