Skip to content

HenryXCC/pdfuse

Repository files navigation

PDFuse

Aplicación de escritorio para rellenar formularios PDF en lote a partir de datos de Excel o CSV. Soporta dos tipos de PDF: formularios interactivos (AcroForm) y PDFs planos mediante posicionamiento visual de coordenadas.

Python Licencia Tests


Características

  • Detección automática del tipo de PDF — distingue entre AcroForm (campos interactivos) y PDFs planos, y adapta el flujo de trabajo en consecuencia.
  • Relleno de AcroForm — soporta campos de texto, casillas de verificación, botones de radio, listas desplegables y campos de firma (imagen).
  • Editor visual para PDFs planos — haz clic sobre la previsualización del PDF para colocar campos de texto con precisión. Incluye reposicionamiento con arrastrar, previsualización en vivo con datos reales y plantillas de columnas.
  • Plantillas de columnas — combina varias columnas en un solo campo usando expresiones {NombreColumna}. Ejemplo: {Nombre} {Apellido} o {Cargo} — {Empresa}.
  • Procesamiento en lote — genera un PDF por cada fila de datos con barra de progreso en tiempo real y registro de errores por fila.
  • Mapeo automático de campos — sugiere coincidencias entre campos del PDF y columnas del archivo, ignorando diferencias de tildes, mayúsculas y separadores.
  • Excel y CSV — compatible con .xlsx, .xlsm, .xls y .csv.
  • PDFs protegidos con contraseña — si el PDF está cifrado, la aplicación solicita la contraseña automáticamente al cargarlo, con reintentos y mensajes claros.
  • Firma como imagen — los campos /Sig se rellenan superponiendo una imagen (firma escaneada) escalada para encajar dentro del área del campo.
  • Aplanado de campos — convierte los campos interactivos en contenido estático al guardar, impidiendo edición posterior. Preserva texto, casillas, botones de radio, listas desplegables y firmas.
  • Exportar ZIP — empaqueta todos los PDFs generados en un solo archivo en un clic.
  • Perfiles JSON — guarda y recarga la configuración completa (rutas, mapeos, opciones de salida) para reutilizarla con la misma plantilla.
  • Modo CLI — ejecución en lote sin interfaz gráfica desde la línea de comandos.

Nota sobre la apariencia de los resultados: La calidad visual de los PDFs generados depende íntegramente de la plantilla que uses. Si tu plantilla tiene un diseño profesional — tipografías, colores corporativos, logos, secciones estructuradas — los PDFs de salida lucirán igual de bien. PDFuse solo rellena los campos; no modifica el diseño de la plantilla.


Vista previa

Modo AcroForm — relleno en lote desde Excel
Modo AcroForm: mapeo de campos y generación en lote

Modo coordenadas — posicionamiento visual en PDF plano
Modo coordenadas: posicionamiento visual sobre PDF plano

---

Estructura del proyecto

pdfuse/
│
├── main.py           # Punto de entrada — verifica dependencias y lanza la app
├── core.py           # Lógica de negocio: detección, relleno, lectura de datos, utilidades
├── cli.py            # Interfaz de línea de comandos (modo batch sin GUI)
│
├── gui.py            # PDFuseApp — ventana principal y estado central de la aplicación
├── constants.py      # Colores, fuentes y etiquetas de los pasos del asistente
├── steps.py          # StepsMixin — constructores de UI para los 4 pasos
├── batch.py          # BatchMixin — generación en lote, log de progreso, exportación ZIP
├── profiles.py       # ProfileMixin — guardado y carga de perfiles JSON
├── dialogs.py        # CoordinateEditorDialog — editor visual para PDFs planos
│
├── assets/           # Icono de la aplicación y GIFs de demostración
│
└── tests/
    ├── __init__.py
    └── └── test_core.py  # 72 tests unitarios (pytest)

Responsabilidades por módulo

Módulo Responsabilidad
core.py Toda la lógica que toca archivos (sin UI). Completamente testeable en aislamiento.
gui.py Estado global de la aplicación y disposición del asistente.
steps.py Construcción de cada paso: selección de archivos, mapeo de campos, configuración de salida.
batch.py Hilo de generación, actualizaciones thread-safe, abrir carpeta, exportar ZIP.
profiles.py Serialización/deserialización JSON de la configuración completa.
dialogs.py Editor modal autocontenido para el modo de coordenadas.
cli.py Parseo de argumentos y ejecución batch en modo headless.
constants.py Fuente única de verdad para colores y tipografía.

Requisitos

  • Python 3.10 o superior
  • Dependencias listadas en requirements.txt

Instalación

# 1. Clonar el repositorio
git clone https://github.com/HenryXCC/pdfuse.git
cd pdfuse

# 2. Crear un entorno virtual (recomendado)
python -m venv .venv
source .venv/bin/activate        # macOS / Linux
.venv\Scripts\activate           # Windows

# 3. Instalar dependencias
pip install -r requirements.txt

Ejecutable

Si no quieres instalar Python, puedes descargar el ejecutable precompilado desde la sección Releases del repositorio. Descomprime el archivo, coloca la carpeta PDFuse/ donde prefieras y ejecuta PDFuse.exe directamente — no requiere instalación ni dependencias adicionales. Si prefieres compilarlo tú mismo desde el código fuente, instala PyInstaller y ejecuta desde la raíz del proyecto en PowerShell:

pyinstaller --name "PDFuse" --onedir --windowed --icon "assets\icon.ico" --add-data "assets;assets" --distpath "dist" main.py

El ejecutable quedará en dist/PDFuse/PDFuse.exe junto a su carpeta _internal con las dependencias. Ambas deben mantenerse juntas para que funcione correctamente.


Uso

python main.py

El asistente te guía por 4 pasos:

Paso 1 — Cargar archivos Selecciona la plantilla PDF y el archivo Excel o CSV. La app detecta automáticamente si el PDF tiene campos AcroForm o es plano, y muestra una previsualización de las primeras filas del archivo de datos. Si el PDF está protegido con contraseña, se solicitará automáticamente.

Paso 2 — Mapear campos

  • AcroForm: asigna cada campo del PDF a una columna del archivo. El botón "Auto-asignar" sugiere mapeos por similitud de nombres. Los campos de firma muestran una indicación de que la columna debe contener rutas a imágenes.
  • PDF plano: abre el editor visual para colocar marcadores de texto haciendo clic sobre la previsualización.

Paso 3 — Configurar salida Establece la carpeta de destino y el patrón de nombres de archivo (prefijo, columna ID, sufijo). La previsualización del nombre se actualiza en tiempo real. También se configuran las opciones Sobrescribir archivos y Aplanar campos al guardar.

Paso 4 — Generar Revisa el resumen de configuración y pulsa Generar. El registro muestra el resultado fila por fila. Al terminar se habilitan los botones Abrir carpeta y Exportar ZIP.

Perfiles

Usa los botones del panel lateral para guardar o cargar un perfil JSON con la configuración actual completa. Útil cuando se trabaja repetidamente con la misma plantilla PDF.


Modo de coordenadas

El editor de coordenadas permite posicionar campos de texto sobre PDFs planos (sin campos interactivos) haciendo clic directamente sobre la previsualización.

Consejos para una colocación precisa:

  • Haz clic exactamente donde quieres que aparezca la esquina superior izquierda del texto. El marcador y el texto de previsualización están alineados en ese mismo punto, así que lo que ves en el editor es lo que sale en el PDF generado.
  • Usa la sintaxis de plantilla {NombreColumna} para combinar varias columnas en un solo campo. Por ejemplo, si tu archivo tiene columnas separadas Nombre y Apellido pero el PDF tiene una sola línea de nombre completo, escribe {Nombre} {Apellido} como plantilla.
  • El botón 📋 Columnas del editor abre un panel de referencia con todos los nombres de columna disponibles. Hacer clic en uno lo copia al portapapeles como {NombreColumna}, listo para pegar en el campo de plantilla.
  • La colocación requiere precisión — los pequeños desajustes se notan más en formularios con estructura fija. Desplázate hasta el área deseada y coloca los marcadores con cuidado. La previsualización en vivo muestra el texto real de la primera fila del archivo de datos.
  • El campo tamaño de fuente del panel derecho afecta tanto la previsualización como el resultado generado. Ajústalo para que coincida con el texto circundante de la plantilla PDF.

Campos de firma

Los campos /Sig del AcroForm se rellenan superponiendo una imagen (por ejemplo, una firma escaneada) sobre el área del campo. Para usarlos:

  1. En el paso 2, el campo de firma aparece marcado con el icono ✍ en morado.
  2. Asígnale una columna de tu Excel o CSV que contenga rutas absolutas o relativas a archivos de imagen (.png, .jpg, .jpeg).
  3. La imagen se escala automáticamente para encajar dentro del rectángulo del campo, manteniendo la proporción.

Si la ruta de imagen de una fila no existe o no es válida, la firma de esa fila se omite silenciosamente sin interrumpir el lote.


Modo CLI

python cli.py --pdf plantilla.pdf --data datos.xlsx --out ./salida

Opciones disponibles:

Opción Descripción
--pdf Ruta a la plantilla PDF (requerido)
--data Ruta al archivo Excel o CSV (requerido)
--out Carpeta de salida (requerido)
--password Contraseña del PDF si está cifrado
--sheet Nombre de la hoja a leer (solo Excel; por defecto la primera)
--prefix Prefijo de nombre de archivo — ej. facturafactura_0001.pdf
--suffix Sufijo de nombre de archivo — ej. 20250001_2025.pdf
--id-col Columna del archivo a usar como identificador en lugar del índice de fila
--flatten Aplana los campos después de rellenar
--overwrite Sobreescribe archivos existentes en la carpeta de salida
--zip Empaqueta todos los PDFs generados en un ZIP en la ruta indicada

El modo CLI solo soporta PDFs AcroForm. Para PDFs planos, usa la GUI para definir las posiciones visualmente.


Tests

pip install pytest
pytest tests/ -v

Los tests cubren core.py de forma aislada (sin UI ni pantalla). Se ejecutan en menos de 2 segundos:

tests/test_core.py::TestSanitizeFilename            (10 tests)
tests/test_core.py::TestEnsureUniquePath             (5 tests)
tests/test_core.py::TestSuggestMapping               (8 tests)
tests/test_core.py::TestValidateMapping              (6 tests)
tests/test_core.py::TestPdfEncodeText                (5 tests)
tests/test_core.py::TestReadExcelData                (5 tests)
tests/test_core.py::TestDetectPdfType                (2 tests)
tests/test_core.py::TestReadExcelDataNanLiteral      (2 tests)  ← regresión bug #5
tests/test_core.py::TestMakeCheckboxAp               (3 tests)  ← regresión bug #2
tests/test_core.py::TestFlattenPdf                   (3 tests)
tests/test_core.py::TestCsvSupport                   (3 tests)
tests/test_core.py::TestExportZip                    (2 tests)
tests/test_core.py::TestCliModule                    (3 tests)
tests/test_core.py::TestFlatPdfCoordinateFix         (2 tests)
tests/test_core.py::TestTemplateResolution           (7 tests)
tests/test_core.py::TestPasswordProtectedPdf         (4 tests)
tests/test_core.py::TestSignatureField               (2 tests)

72 pasados en ~0.85s

Notas técnicas

Codificación Latin-1 en campos AcroForm pypdf convierte automáticamente las cadenas con caracteres no ASCII a UTF-16BE (2 bytes por carácter). Cuando un campo usa una fuente estándar como Helvetica (WinAnsiEncoding / Latin-1), el lector PDF renderiza cada byte por separado, produciendo texto ilegible. La corrección en _pdf_encode_text codifica explícitamente como ByteStringObject en Latin-1, cubriendo español, francés, portugués, alemán y similares. Los caracteres fuera de Latin-1 usan TextStringObject con UTF-16BE, que requiere una fuente embebida en el PDF.

AP stream de casillas de verificación El stream vectorial en _make_checkbox_ap dibuja la marca usando únicamente operadores gráficos PDF estándar (m, l, S), sin depender de fuentes como ZapfDingbats. Funciona con cualquier PDF independientemente de cómo estuvieran configurados originalmente sus campos.

Soporte de botones de radio get_acroform_fields distingue los botones de radio de las casillas de verificación inspeccionando los flags /Ff (bit 15 = Radio, bit 16 = Pushbutton). El valor de exportación de cada widget se lee directamente desde su stream AP /N, ya que get_fields() de pypdf fusiona todos los widgets de un grupo en una sola entrada y pierde los valores individuales.

Firma como imagen Para campos /Sig, fill_acroform acumula las superposiciones de imagen por página y las renderiza con ReportLab después del bucle de anotaciones. La imagen se escala preservando la proporción para encajar dentro del rectángulo del campo. Si el archivo de imagen no existe, el campo se omite silenciosamente.

Aplanado de PDFs flatten_pdf intenta primero pymupdf.bake() (disponible desde pymupdf ≥ 1.24), que renderiza todas las apariencias de los campos en el contenido estático de la página. Si pymupdf no está disponible, el fallback superpone los valores usando ReportLab y elimina la entrada /AcroForm y todas las anotaciones Widget. El fallback maneja campos de texto, casillas, botones de radio y listas desplegables — incluyendo el dibujo del recuadro con el valor seleccionado y un indicador visual de flecha para que la maquetación se preserve tras el aplanado.

Thread safety en la generación en lote La generación corre en un hilo separado para no bloquear la UI. Todas las actualizaciones de progreso y escrituras en el log usan self.after(0, callback) para volver al hilo principal antes de modificar cualquier widget.

Arquitectura de mixins PDFuseApp hereda de StepsMixin, BatchMixin, ProfileMixin y ctk.CTk. Cada mixin agrupa métodos alrededor de una responsabilidad única y accede al estado de la aplicación a través de self, que en tiempo de ejecución apunta a la instancia de PDFuseApp. Todo el estado se declara en PDFuseApp.__init__, haciendo explícito qué pertenece a la app y qué es lógica de cada módulo.


Limitaciones conocidas

  • Los campos de firma solo admiten imágenes estáticas (firma escaneada). Las firmas criptográficas digitales (PKI / certificados) no están soportadas.
  • El modo de coordenadas no soporta estilos de texto avanzados (negrita, cursiva): solo están disponibles las 12 fuentes PDF estándar.
  • El modo CLI solo soporta PDFs AcroForm; los datos de posicionamiento para PDFs planos no pueden expresarse como argumentos de línea de comandos.

Licencia

MIT — ver archivo LICENSE.

About

Batch PDF form filler from Excel/CSV. Supports AcroForm and flat PDFs with visual coordinate editor.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages