2015-03-31 10 views
6

Ich habe ein pdf-Formular gemacht und ich versuche, pdfBox zu benutzen, um das Formular auszufüllen und das Dokument zu drucken. Ich habe es funktioniert hervorragend für 1-Seite Druckaufträge, aber ich musste versuchen, für mehrere Seiten zu ändern. Im Grunde ist es ein Formular mit grundlegenden Informationen oben und einer Liste von Inhalten. Nun, wenn der Inhalt größer ist als das, wofür das Formular Platz hat, muss ich es zu einem mehrseitigen Dokument machen. Ich habe am Ende ein Dokument mit einer schönen Seite Eins und dann sind alle verbleibenden Seiten die leere Vorlage. Was mache ich falsch?Java pdfBox: Füllen Sie pdf-Formular aus, hängen Sie es an pddocument an und wiederholen Sie

PDDocument finalDoc = new PDDocument(); 
File template = new File("path/to/template.pdf"); 

//Declare basic info to be put on every page 
String name = "John Smith"; 
String phoneNum = "555-555-5555"; 
//Get list of contents for each page 
List<List<Map<String, String>>> pageContents = methodThatReturnsMyInfo(); 

for (List<Map<String, String>> content : pageContents) { 
    PDDocument doc = new PDDocument().load(template); 
    PDDocumentCatlog docCatalog = doc.getDocumentCatalog(); 
    PDAcroForm acroForm = docCatalog.getAcroForm(); 

    acroForm.getField("name").setValue(name); 
    acroForm.getField("phoneNum").setValue(phoneNum); 

    for (int i=0; i<content.size(); i++) { 
     acroForm.getField("qty"+i).setValue(content.get(i).get("qty")); 
     acroForm.getField("desc"+i).setValue(content.get(i).get("desc")); 
    } 

    List<PDPage> pages = docCatalog.getAllPages(); 
    finalDoc.addPage(pages.get(0)); 
} 

//Then prints/saves finalDoc 

Antwort

9

Es gibt zwei große Probleme in Sie Code:

  • Das AcroForm Element eines PDF ist ein Dokumentebene Objekt. Sie kopieren nur die ausgefüllte Vorlagenseite in finalDoc. Daher werden die Formularfelder finalDoc nur als Anmerkungen ihrer jeweiligen Seite hinzugefügt, aber sie werden nicht zur AcroForm von finalDoc hinzugefügt.

    Dies ist in Adobe Reader nicht ersichtlich, aber Formularausfüllungsdienste identifizieren häufig verfügbare Felder vom AcroForm-Eintrag auf Dokumentebene und durchsuchen die Seiten nicht nach zusätzlichen Formularfeldern.

  • Der tatsächliche show stopper: Sie fügen Felder mit identischen Namen zum PDF hinzu. PDF-Formulare sind jedoch unternehmensweite Entitäten. I.e. Es kann nur eine einzige Feldeinheit mit einem bestimmten Namen in einer PDF geben. (Diese Feldeinheit kann mehrere Visualisierungen als Widgets haben. Dazu müssen Sie jedoch ein einzelnes Feldobjekt mit mehreren Kid-Widgets erstellen. Außerdem wird erwartet, dass diese Widgets den gleichen Wert anzeigen, der nicht Ihren Vorstellungen entspricht ...)

    Daher müssen Sie die Felder eindeutig umbenennen, bevor Sie sie zum finalDoc hinzufügen.

hier ein simplified example, die mit nur einem Feld "SampleField" auf einer Vorlage arbeitet:

byte[] template = generateSimpleTemplate(); 
Files.write(new File(RESULT_FOLDER, "template.pdf").toPath(), template); 

try ( PDDocument finalDoc = new PDDocument();) 
{ 
    List<PDField> fields = new ArrayList<PDField>(); 
    int i = 0; 

    for (String value : new String[]{"eins", "zwei"}) 
    { 
     PDDocument doc = new PDDocument().load(new ByteArrayInputStream(template)); 
     PDDocumentCatalog docCatalog = doc.getDocumentCatalog(); 
     PDAcroForm acroForm = docCatalog.getAcroForm(); 
     PDField field = acroForm.getField("SampleField"); 
     field.setValue(value); 
     field.setPartialName("SampleField" + i++); 
     List<PDPage> pages = docCatalog.getAllPages(); 
     finalDoc.addPage(pages.get(0)); 
     fields.add(field); 
    } 

    PDAcroForm finalForm = new PDAcroForm(finalDoc); 
    finalDoc.getDocumentCatalog().setAcroForm(finalForm); 
    finalForm.setFields(fields); 

    finalDoc.save(new File(RESULT_FOLDER, "form-two-templates.pdf")); 
} 

Wie Sie sehen alle Felder umbenannt werden, bevor sie zu finalForm hinzugefügt:

field.setPartialName("SampleField" + i++); 

und sie werden in der Liste fields gesammelt, die schließlich zu der finalForm AcroForm hinzugefügt wird:

fields.add(field); 
} 
... 
finalForm.setFields(fields);