Generar PDFs con Python: facturas y reportes con fpdf2
Cómo crear archivos PDF desde Python con fpdf2: texto, tablas, imágenes y saltos de página. Para automatizar facturas, reportes o certificados sin hacerlos a mano.
Generar un PDF a mano cada vez que necesitas una factura, un reporte o un certificado es trabajo repetido que Python puede hacer por ti. Con la librería fpdf2 creas PDFs desde cero con unas pocas líneas, y una vez armada la plantilla, generas cientos con los datos que quieras.
pip install fpdf2
Ojo con el nombre: se instala como fpdf2 (con el 2), pero en el código se importa como fpdf. La versión vieja fpdf (sin el 2) está abandonada; fpdf2 es la que se mantiene y la que debes usar.
Tu primer PDF
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=12)
pdf.cell(0, 10, "Hola, este PDF lo generó Python")
pdf.output("ejemplo.pdf")
Las piezas: add_page() crea una página, set_font() elige la fuente y el tamaño, cell() escribe una celda de texto, y output() guarda el archivo. El orden importa: primero la página, luego la fuente, luego el contenido.
Sobre el cell(0, 10, texto): el primer número es el ancho (0 significa “hasta el margen derecho”), el segundo es el alto de la línea, y luego el texto. Es el método básico para colocar una línea.
Saltos de línea y párrafos
cell escribe en una sola línea. Para texto que ocupa varias líneas o párrafos, usa multi_cell, que parte el texto solo:
pdf.multi_cell(0, 8, "Este es un párrafo largo que se ajustará "
"automáticamente al ancho de la página, "
"saltando de línea cuando haga falta.")
Y para bajar una línea manualmente entre elementos, ln():
pdf.cell(0, 10, "Primera línea")
pdf.ln() # baja una línea
pdf.cell(0, 10, "Segunda línea")
Un ejemplo real: estructura de factura
Combinando lo anterior, una cabecera de factura simple:
from fpdf import FPDF
from datetime import date
pdf = FPDF()
pdf.add_page()
# Título
pdf.set_font("Helvetica", "B", 18) # "B" = negrita
pdf.cell(0, 12, "FACTURA")
pdf.ln(20)
# Datos
pdf.set_font("Helvetica", size=11)
pdf.cell(0, 8, f"Fecha: {date.today().strftime('%d/%m/%Y')}")
pdf.ln()
pdf.cell(0, 8, "Cliente: Empresa Ejemplo C.A.")
pdf.ln()
pdf.cell(0, 8, "Concepto: Servicio de desarrollo")
pdf.output("factura.pdf")
El "B" en set_font activa la negrita; "I" sería cursiva. Fíjate cómo se combina con el módulo datetime para poner la fecha actual automáticamente — justo el tipo de cosa que hace útil generar PDFs por código en lugar de a mano.
Añadir una imagen (un logo)
pdf.image("logo.png", x=10, y=10, w=30) # x, y = posición; w = ancho
Útil para poner el logo de tu marca en cada documento. La posición es en milímetros desde la esquina superior izquierda.
Saltos de página
Para reportes largos, fuerzas una página nueva cuando la necesites:
pdf.add_page() # empieza una página nueva
fpdf2 también salta de página solo cuando el contenido no cabe, así que para listas largas no tienes que controlarlo todo a mano.
Generar muchos de golpe
Aquí está el verdadero poder. Mete lo anterior en un bucle y generas un PDF por cada registro:
clientes = [
{"nombre": "Empresa A", "monto": 500},
{"nombre": "Empresa B", "monto": 750},
]
for c in clientes:
pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=12)
pdf.cell(0, 10, f"Factura para {c['nombre']}")
pdf.ln()
pdf.cell(0, 10, f"Monto: {c['monto']} USD")
pdf.output(f"factura_{c['nombre'].replace(' ', '_')}.pdf")
Cien facturas en lo que tarda en correr el bucle. Eso es automatización de verdad: lo que te tomaría una tarde, resuelto en segundos.
Resumen
- Instala
fpdf2, importa comofpdf. add_page()→set_font()→ contenido →output(), en ese orden.cellpara una línea,multi_cellpara párrafos,ln()para bajar."B"negrita,"I"cursiva enset_font.- Combínalo con un bucle para generar documentos en masa.
Con esto automatizas facturas, reportes, certificados o cualquier documento repetitivo. Y combinándolo con el envío de correos con Python, podrías generar una factura y enviarla por correo, todo en un solo script.
¿Necesitas tablas con bordes, varias fuentes, o generar el PDF a partir de datos de un Excel? Escríbeme desde contacto y lo vemos.