Estoy tratando de crear un documento de varias páginas a partir de plantillas en mi sistema de archivos, pero en cambio obtengo un comportamiento extraño del mismo título de página en todas las páginas del documento. ¿Alguna idea de lo que estoy haciendo mal aquí?
Algo que no entiendo del todo es la forma en que agregamos páginas. ¿Por qué necesitamos hacer referencia a newDoc en el siguiente ejemplo, cuando await newDoc.copyPages(page, [0]) ? En lugar de simplemente newDoc.addPage(page) ? ¿Será que el campo de formulario denominado Title se sobrescribe porque ambas páginas tienen el mismo nombre de campo durante la copia de flujos de datos?
Nota: Me han informado de que StackOverflow no tiene una etiqueta para pdf-lib.js.org , que no debe confundirse con otras bibliotecas de pdf.
const payload = { rows: [{ id: 1, title: 'Foo', },{ id: 2, title: 'Bar' }, formData: { hello: 'World', lorum: 'Ipsum' } ] } const makePdf = async (payload) => { const newDoc = await PDFDocument.create() newDoc.getForm().acroForm.dict.set(PDFName.of('NeedAppearances'), PDFBool.True) for (const row of payload.rows) { await addPage(row, payload.formData, newDoc) } return newDoc } const addPage = async (dataRow, formData, newDoc) => { const rowId = dataRow.id let templateName switch(true) { case (rowId === 1): templateName = 'foo' break case (rowId === 2): templateName = 'bar' break } const templatePath = path.join(__dirname, `../templates/pdfs_/${templateName}.pdf`) const template = await fs.readFileSync(templatePath) const page = await PDFDocument.load(template) const form = page.getForm() form.acroForm.dict.set(PDFName.of('NeedAppearances'), PDFBool.True) switch(templateName) { case 'foo': foo(form, formData) break case 'bar': bar(form, formData) } // dataRow.title logs correct strings ie: 'Foo' & 'Bar' form.getField('Title').setText(dataRow.title) const [firstPage] = await newDoc.copyPages(page, [0]) return await newDoc.addPage(firstPage) } const bar = (form, formData) => { form.getField('Lorum').setText(formData.lorum) } const foo = (form, payload) => { form.getField('Hello').setText(formData.hello) } return makePdf(payload) // Produces 2 page pdf with the same title // [[ title: Foo, Hello: World ], [title: Foo, Lorum: Ipsum ]]No tengo su archivo de plantilla, así que no estoy exactamente seguro de lo que está tratando de lograr.
De hecho, se requiere copyPage .
Debe guardar el PDFDocument antes de volver a cambiarlo.
Traté de reescribir su código, ignoré la línea PDFName y PDFBool , pero estoy seguro de que puede entender la idea.
const {PDFDocument} = require('./engine/node_modules/pdf-lib'); const fs = require('fs'); const payload = { rows: [ { id: 1, title: 'Foo', }, { id: 2, title: 'Bar', }, ], formData: { hello: 'World', lorum: 'Ipsum', } } class PdfSample { async loadTemplate(templatePath) { const templateFile = fs.readFileSync(templatePath); const templateDoc = this.templateDoc = await PDFDocument.load(templateFile); this.templateForm = templateDoc.getForm(); } async initDoc() { this.resultDoc = await PDFDocument.create(); } fillTextField(fieldName, value) { const field = this.templateForm.getField(fieldName); field.setText(value); } get formFieldsNames() { return this.templateForm.getFields().map(field => field.getName()); } async addDocPage() { const newPageBytes = await this.templateDoc.save(); const newPage = await PDFDocument.load(newPageBytes); const [pageToAdd] = await this.resultDoc.copyPages(newPage, [0]); return this.resultDoc.addPage(pageToAdd); } async saveResult(outputPath) { const pdfBytes = await this.resultDoc.save(); fs.writeFileSync(outputPath, pdfBytes); } } const pdfSample = new PdfSample(); (async () => { await pdfSample.initDoc(); await pdfSample.loadTemplate('./pdfs_/OoPdfFormExample.pdf'); console.log(pdfSample.formFieldsNames); for (const row of payload.rows) { pdfSample.fillTextField('Given Name Text Box', row.title); pdfSample.fillTextField('Family Name Text Box', payload.formData.hello); pdfSample.fillTextField('House nr Text Box', payload.formData.lorum); await pdfSample.addDocPage(pdfSample.templateDoc); } await pdfSample.saveResult('./pdfs_/result.pdf'); })();El formulario de muestra es de este sitio
Está intentando crear un documento con dos campos de formulario denominados Title , uno en cada página. Esto no funciona, ambos son el mismo campo y muestran el mismo valor.
En lugar de "copiar" los campos existentes de una plantilla, debe usar algo como
var newField = form.createTextField('Title' + dataRow.id); newField.addToPage(firstPage, {x: ..., y: ...}); newField.setText(...);