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:
- Tabula/Camelot: requieren Java instalado. Fallan con PDFs escaneados.
- PyPDF2/pdfplumber: extraen texto crudo, pero reconstruir tablas es manual y frágil.
- OCR + heurísticas: lento, impreciso, requiere configuración compleja de Tesseract.
- Copiar y pegar: funciona para 1 tabla. Imposible para 200 archivos mensuales.
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:
- Contadores procesando estados de cuenta: un despacho contable recibe 30-50 estados de cuenta bancarios al mes en PDF. Necesitan los movimientos en Excel para conciliar.
- Analistas de datos: reportes de gobierno, censos, datos públicos que solo se publican en PDF. Convertirlos a Excel para graficar y analizar.
- Automatización de reportes mensuales: proveedores que envían listas de precios, inventarios o catálogos en PDF. Extraer y consolidar en un solo Excel.
- Auditorías: revisar cientos de facturas PDF y extraer los totales, fechas e impuestos a una hoja de cálculo.
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ón | Ninguna (API) | Java + pip | N/A |
| PDFs escaneados | Sí (OCR) | No | Sí |
| Batch 100 archivos | ~5 min | ~30 min | ~8 horas |
| Salida directa a Excel | Sí | CSV (manual a xlsx) | Sí |
| Mantenimiento | Cero | Updates, bugs | Infinito |
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.
- tabla-datos — tabla simple con encabezados y autofit de columnas
- reporte-financiero — con totales, subtotales y formato contable
- conciliacion-bancaria — dos columnas comparativas con diferencias resaltadas
- inventario — con códigos, cantidades y alertas de stock bajo
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