Generación de informes PDF en Rust con la biblioteca printpdf
En el mundo de la programación moderna, Rust se utiliza cada vez más para crear aplicaciones de servidor de alto rendimiento y herramientas de línea de comandos. Una de las tareas más demandadas es la generación de informes PDF, ya sean paneles analíticos, facturas o documentación. La biblioteca printpdf proporciona una forma ligera y confiable de crear documentos PDF en Rust puro sin dependencias de sistemas externos (por ejemplo, LaTeX o wkhtmltopdf).
¿Qué es printpdf?
printpdf es una biblioteca pure-Rust para generar documentos PDF desde cero. Soporta:
- Texto con varias fuentes (incluyendo TrueType/OpenType incrustadas).
- Gráficos vectoriales (líneas, rectángulos, elipses).
- Imágenes (PNG, JPEG) con transparencia.
- Tablas y formato complejo mediante posicionamiento manual.
- Páginas de cualquier tamaño (A4, Carta, personalizadas).
La biblioteca no utiliza procesos externos, lo que la hace ideal para integrarse en servicios web, utilidades CLI o aplicaciones de escritorio en Rust.
Instalación
Añada a Cargo.toml:
[dependencies]printpdf = "0.7"También necesitará el crate rusttype para trabajar con fuentes (se incluye automáticamente como dependencia).
Ejemplo básico: creación de un informe simple
Escribamos un programa que cree un PDF con un título, texto y una línea. Guardaremos el resultado en el archivo report.pdf.
use printpdf::*;use std::fs::File;use std::io::BufWriter;
fn main() { // Creamos un documento en formato A4 let (doc, page1, layer1) = PdfDocument::new( "Mi informe", Mm(210.0), Mm(297.0), "Layer 1", );
// Obtenemos la fuente (Helvetica incorporada) let font = doc.add_builtin_font(BuiltinFont::Helvetica).unwrap();
// Empezamos a dibujar en la primera capa let current_layer = doc.get_page(page1).get_layer(layer1);
// Texto: título current_layer.use_text( "Informe de ventas", 24.0, Mm(20.0), Mm(270.0), &font, );
// Texto: normal current_layer.use_text( "Fecha del informe: 2025-03-15", 12.0, Mm(20.0), Mm(250.0), &font, );
// Dibujamos una línea separadora current_layer.set_outline_color(Color::Rgb(Rgb::new(0.5, 0.5, 0.5))); current_layer.set_stroke_width(1.0); current_layer.add_line( Point::new(Mm(20.0), Mm(240.0)), Point::new(Mm(190.0), Mm(240.0)), );
// Guardamos en un archivo let file = File::create("report.pdf").unwrap(); let writer = BufWriter::new(file); doc.save(&mut std::io::BufWriter::new(writer)).unwrap();
println!("Informe PDF creado: report.pdf");}Este código crea un PDF de una página con un título, una fecha y una línea gris. Todas las coordenadas se especifican en milímetros (también se pueden usar puntos).
Añadir una tabla con datos
Para los informes a menudo se necesitan tablas. En printpdf no hay estructuras de tabla predefinidas, pero se pueden implementar fácilmente manualmente:
use printpdf::*;use std::fs::File;use std::io::BufWriter;
fn draw_table( layer: &PdfLayerReference, font: &IndirectFontRef, data: Vec<[&str; 3]>, start_x: Mm, start_y: Mm,) { let col_widths = [Mm(40.0), Mm(60.0), Mm(50.0)]; let row_height = Mm(10.0); let header_bg = Color::Rgb(Rgb::new(0.9, 0.9, 0.9));
for (row_idx, row_data) in data.iter().enumerate() { let y = start_y - row_height * (row_idx as f32);
// Fondo para el encabezado if row_idx == 0 { layer.set_fill_color(header_bg); layer.add_rectangle( start_x, y - row_height, También en la biblioteca
Autorización y autenticación en Go (Golang): guía completa
Métricas de Prometheus en Node.js: biblioteca prom-client para monitoreo
TipKit para Swift: guía completa con ejemplos prácticos
Trabajo con imágenes en PHP: resize, crop (redimensionamiento y recorte)