Plantillas PDF

imagen¡Habrahabr, queridos colegas!



El problema de imprimir datos en un documento PDF no es nuevo, no soy el primero ni el último que se encuentra con él, por eso decidí compartir mi experiencia de solución y al mismo tiempo presentar a su atención una pequeña web aplicación sobre este tema.



1. El formato PDF es bueno porque no se puede editar. En cualquier caso, es poco probable que un usuario común participe en la edición de un documento PDF. Esto significa que el formato PDF es adecuado para el intercambio de documentos legalmente significativos.



2. El formato PDF es malo porque no se puede editar). crear plantillas, completar un conjunto de datos de un formulario de documento PDF en modo automático es difícil, y el modo manual requiere la instalación de aplicaciones de pago pesadas.



Como programador, me preocupa principalmente el segundo punto. ¿Cómo imprimo el conjunto de datos requerido en un documento PDF en una aplicación de software?



Otra búsqueda en Google sobre este tema no arrojó ningún resultado.

Solo logré googlear que todo está mal al escribir ( ¿Por qué es tan difícil extraer texto de PDF ? , PDF desde el punto de vista de un programador ) y hay una opción para hacer una plantilla del archivo docx primero, esto no es difícil hacer ( Rellenar documentos en Microsoft Word ... ), y luego convertir en la consola el archivo docx de libreoffice (librewrite) a PDF. Todo esto se puede hacer automáticamente desde la aplicación.



Pero primero, tal decisión significa que el proyecto dependerá en gran medida de libreoffice.



Y en segundo lugar, al convertir docx a PDF en libreoffice, el documento se ve un poco diferente de cómo se ve en Word y / o PDF generado en Word a partir de un archivo docx.



Finalmente, pasemos a la esencia de la solución en consideración. Por supuesto, "hacer plantillas" en este caso es una palabra fuerte, pero la solución propuesta es bastante adecuada y útil.



En python (y php) hay varias bibliotecas (no difíciles de buscar en Google) que le permiten imprimir cadenas e imágenes en archivos PDF, usamos pdfrw + reportlab.Canvas. Es decir, en principio, no hay problema para teclear los datos, el problema con estas bibliotecas es que para cada campo necesitas establecer sus coordenadas exactas en el documento, lo que significa que



1.Necesitamos algún tipo de funcionalidad unificada que almacene las coordenadas de los campos no dentro del código fuente, sino en un archivo separado. Aclararé de inmediato que por experiencia recomiendo almacenar estas coordenadas en archivos y bajo control de versiones, es decir, confirmar coordenadas junto con los formularios y métodos PDF correspondientes que generan un conjunto particular de documentos. Y no ponga estas coordenadas en la base de datos, porque esto dificultará la reversión a versiones anteriores (coordenadas) de los documentos, si surge la necesidad. Todo parece estar claro aquí.



2. Estas coordenadas deben calcularse de alguna manera, y esta es una tarea triste si lo hace manualmente.



La idea principal aquí es crear elementos div móviles en el navegador, usar el mouse para ajustar su posición al lugar deseado en el documento y guardar las coordenadas de los elementos obtenidos en el navegador en un archivo en el backend. De hecho, estos dos puntos están implementados en la aplicación.



Modo de aplicación



Parece una pequeña aplicación web con un front-end y un back-end, es decir, emitirlo como un paquete de Python, tal vez, no funcione.



1. Descargue las fuentes del gita



2. Instale las dependencias



3. Lea README.md (instale y configure nginx para archivos estáticos)



4. En la carpeta de documentos, cree una subcarpeta con el nombre del documento que necesita ser generado y dentro esta subcarpeta crea dos archivos y (si es necesario) un directorio con imágenes:



- form.pdf # formulario del documento en el que necesita

imprimir datos - fields.json # parámetros de los campos que deben imprimirse

- images # es opcional, un conjunto de imágenes que deben teclearse te

recomiendo que también guardes el archivo docx original (si lo hay), que no está involucrado en la generación del documento, pero será útil si lo necesitas hacer cambios y regenerar el formulario del documento PDF

- form.docx # no es necesario, cualquier nombre



El archivo fields.json tiene la siguiente estructura, por ejemplo:



{
    "0": [
        [32.25, 710.25, "fio", "DejaVuSans", 12, 420],
        [425.25, 681.75, "gender", "DejaVuSans", 12, 18],
        [206.25, 681.75, "birth_date", "DejaVuSans", 12, 173],
        [462.75, 681.53, "foto.jpg", "DejaVuSans", 12, 92],
        [146.25, 665.25, "birth_place", "DejaVuSans", 12, 418],
        [228.0, 634.5, "registration", "DejaVuSans", 12, 340]
    ],
    "1": [
        [132.0, 720.76, "1_work", "DejaVuSans", 10, 260],
        [132.0, 697.51, "2_work", "DejaVuSans", 10, 260],
        [132.0, 673.51, "3_work", "DejaVuSans", 10, 141]
    ]
}

      
      





Agregar / eliminar líneas a este archivo agrega / elimina campos que están impresos en el formulario



5. Abra la página para configurar campos (http://127.0.0.1/tpdf/positioning?pdf_name=ZayavlenieNaZagranpasport&page_num=1)



6. Ajuste la posición de los campos con el mouse en el navegador y guardar esta posición



7. El mouse no siempre puede establecer con precisión la posición deseada de los campos, para ajustar la posición de los campos, puede abrir el archivo fieldd.json y corregir el coordenadas manualmente. Los datos en el archivo están ordenados por la coordenada Y y cada campo se almacena en su propia línea en el archivo. Esos. el archivo con las coordenadas de los campos tiene un formato ordenado, lo que le permite realizar los ajustes necesarios de forma manual y sencilla.



ocho.Creamos otro método para imprimir este tipo de documento (si necesita preparar de alguna manera los datos iniciales y / o tomarlos no desde el frente, sino desde el backend).



9. Si todo está en orden, compruebe el dataset fields.json y los archivos resultantes (no en mi git, sino en su git local, aunque si el documento puede ser útil para otra persona, puede recopilar un banco de documentos público , esa es una idea).



El archivo resultante con coordenadas se puede usar en otro proyecto, en otro lenguaje de programación, por ejemplo php, porque las coordenadas en el archivo están escritas en unidades de medida (puntos) que se usan en archivos PDF.



Si tiene un proyecto de Python, entonces el código fuente de esta aplicación puede simplemente incrustarse en el proyecto y, mediante el uso de la clase Tpdf principal, generar PDF en cualquier lugar conveniente del código.



A menudo es necesario generar no solo un documento a partir de varias páginas, sino reunir varios documentos en un archivo PDF, cada uno de los cuales debe imprimirse en el orden correcto y algunos de ellos más de una vez. La clase principal de esta aplicación tiene un método especial para estas necesidades que genera un conjunto de documentos, ver el método de procesamiento / tpdf / example /.



Los datos deben pasarse a la clase principal al crear una instancia. La clase principal se puede ampliar con propiedades (@property), que se calcularán en función de los datos de entrada y se insertarán en el PDF por nombre de propiedad = nombre de campo. Entonces, en el ejemplo, se muestra el campo fio y los datos se transmiten last_name, first_name, middle_name.



Puede implementar esta pequeña aplicación como un servicio independiente, y todas las demás aplicaciones en el entorno accederán a ella para obtener el documento necesario a través de la red. , pero luego habrá costos de transmisión a través de la red, los archivos PDF no son demasiado "livianos", la generación de documentos en sí es rápida.



En lugar de cientos de palabras, a veces es mejor ver una instrucción en video (no grabé un sonido).





Experiencia de implementación (rake).



  1. PyPDF2, 28 3 , - . , , , , , , , - . , — . , pdfrw , , . .. 28 0.3 . : , , , .
  2. ajax, , .
  3. PDF. , , 3/4, PDF. , , .


(TODO)



  1. .



    , / / / () fields.json
  2. , , .
  3. , PDF-.
  4. Un método genérico que toma un conjunto de datos como entrada y devuelve una colección de documentos.



All Articles