0

I want to create a pdf via java which contains two listboxes. Selecting an item of listbox 1 should modify items of listbox 2. I learned that this requires javascript. How can I code this in java. I am using pdfbox so far.

I googled a lot but could not find a complete example. Please see below my code which creates a listbox and a text field and a signature field.

    import org.apache.pdfbox.cos.COSName;
    import org.apache.pdfbox.pdmodel.*;
    import org.apache.pdfbox.pdmodel.common.PDRectangle;
    import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
    import org.apache.pdfbox.pdmodel.font.PDFont;
    import org.apache.pdfbox.pdmodel.font.PDType1Font;
    import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
    import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
    import org.apache.pdfbox.pdmodel.interactive.action.PDAnnotationAdditionalActions;
    import org.apache.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions;
    import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
    import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
    import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
    import org.apache.pdfbox.pdmodel.interactive.form.*;

    import java.awt.*;
    import java.io.File;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.List;


    public class PDFCreate {
public static void main(String[] args) {
    System.out.println("Creating pdf docoument including signature field");

    try {
    // Create a new document with an empty page.
        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);

        // Adobe Acrobat uses Helvetica as a default font and
        // stores that under the name '/Helv' in the resources dictionary
        PDFont font = PDType1Font.HELVETICA;
        PDResources resources = new PDResources();
        resources.put(COSName.getPDFName("Helv"), font);


        PDDocumentCatalog pdCatalog = document.getDocumentCatalog();

        PDAcroForm pdAcroForm = new PDAcroForm(document);
        pdCatalog.setAcroForm(pdAcroForm);

        pdAcroForm.setDefaultResources(resources);

        String defaultAppearanceString = "/Helv 0 Tf 0 g";
        pdAcroForm.setDefaultAppearance(defaultAppearanceString);


        PDTextField textBox = new PDTextField(pdAcroForm);
        textBox.setPartialName("newTextField");

        defaultAppearanceString = "/Helv 12 Tf 0 g";
        textBox.setDefaultAppearance(defaultAppearanceString);
        pdAcroForm.getFields().add(textBox);

        PDAnnotationWidget widget = textBox.getWidgets().get(0);
        PDRectangle rect = new PDRectangle(50, 750, 200, 50);
        widget.setRectangle(rect);
        widget.setPage(page);

        // make sure the annotation is visible on screen and paper
        widget.setPrinted(true);

        // Add the annotation to the page
        page.getAnnotations().add(widget);
        textBox.setValue("value in newly created text field");

        PDListBox pdListBox = new PDListBox(pdAcroForm);
        pdListBox.setPartialName("newListBox");
        List<String> displayList = Arrays.asList("option 1", "option 2", "option 3");
        List<String> exportList = Arrays.asList("option 1 key", "option 2 key", "option 3");
        pdListBox.setOptions(exportList, displayList );
        defaultAppearanceString = "/Helv 12 Tf 0 g";
        pdListBox.setDefaultAppearance(defaultAppearanceString);





        pdAcroForm.getFields().add(pdListBox);

        PDAnnotationWidget widget2 = pdListBox.getWidgets().get(0);
        PDRectangle rect2 = new PDRectangle(50, 680, 200, 50);
        widget2.setRectangle(rect2);
        widget2.setPage(page);

        // make sure the annotation is visible on screen and paper
        widget2.setPrinted(true);

        PDFormFieldAdditionalActions pdFormFieldAdditionalActions = new PDFormFieldAdditionalActions();
        PDActionJavaScript jsChangedAction = new PDActionJavaScript();
        jsChangedAction.setAction("app.alert(\"On 'change' action\")");

        pdFormFieldAdditionalActions.setC((PDAction) jsChangedAction);

        pdListBox.setActions(pdFormFieldAdditionalActions);


        // Add the annotation to the page
        page.getAnnotations().add(widget2);

        pdListBox.setValue("option 2 key");


        PDRectangle rect3 = new PDRectangle(50, 150, 200, 50);

        PDAppearanceDictionary appearanceDictionary = new PDAppearanceDictionary();
        PDAppearanceStream appearanceStream = new PDAppearanceStream(document);
        appearanceStream.setBBox(rect3.createRetranslatedRectangle());
        appearanceStream.setResources(resources);
        appearanceDictionary.setNormalAppearance(appearanceStream);
        PDPageContentStream contentStream = new PDPageContentStream(document, appearanceStream);
        contentStream.setStrokingColor(Color.BLACK);
        contentStream.setNonStrokingColor(Color.LIGHT_GRAY);
        contentStream.setLineWidth(2);
        contentStream.addRect(0, 0, rect3.getWidth(), rect3.getHeight());
        contentStream.fill();
        contentStream.moveTo(1 * rect3.getHeight() / 4, 1 * rect3.getHeight() / 4);
        contentStream.lineTo(2 * rect3.getHeight() / 4, 3 * rect3.getHeight() / 4);
        contentStream.moveTo(1 * rect3.getHeight() / 4, 3 * rect3.getHeight() / 4);
        contentStream.lineTo(2 * rect3.getHeight() / 4, 1 * rect3.getHeight() / 4);
        contentStream.moveTo(3 * rect3.getHeight() / 4, 1 * rect3.getHeight() / 4);
        contentStream.lineTo(rect3.getWidth() - rect3.getHeight() / 4, 1 * rect3.getHeight() / 4);
        contentStream.stroke();
        contentStream.setNonStrokingColor(Color.DARK_GRAY);
        contentStream.beginText();
        contentStream.setFont(font, rect3.getHeight() / 5);
        contentStream.newLineAtOffset(3 * rect3.getHeight() / 4, -font.getBoundingBox().getLowerLeftY() * rect3.getHeight() / 5000);
        contentStream.showText("Customer");
        contentStream.endText();
        contentStream.close();

        PDSignatureField signatureField = new PDSignatureField(pdAcroForm);
        signatureField.setPartialName("SignatureField");

        PDAnnotationWidget widget3 = signatureField.getWidgets().get(0);
        widget3.setAppearance(appearanceDictionary);
        widget3.setRectangle(rect3);
        widget3.setPage(page);

        page.getAnnotations().add(widget3);
        pdAcroForm.getFields().add(signatureField);


        PDFormFieldAdditionalActions pdFormAdditionalActions = new PDFormFieldAdditionalActions();
        String javaScript = "app.alert( {cMsg: 'this is an example', nIcon: 3,"
                + " nType: 0,cTitle: 'PDFBox Javascript example' } );";
        PDActionJavaScript PDAjavascript = new PDActionJavaScript(javaScript);


        pdFormAdditionalActions.setC(PDAjavascript);
        /*        PDActionJavaScript(PDAjavascript); */
        pdListBox.setActions(pdFormAdditionalActions);


                pdListBox.getActions().getCOSObject().addAll(pdFormAdditionalActions.getCOSObject());


        //document.getDocumentCatalog().setOpenAction(PDAjavascript);

        document.save("create from empty.pdf");

        for (PDField pdField : pdAcroForm.getFields()) {
            System.out.println(pdField.getFullyQualifiedName() + " " + pdField.getFieldType() + " " + pdField.getValueAsString());
        }
        document.close();

    } catch (IOException e) {
        e.printStackTrace();
    }

    }
    }

the changed action in my code never shows any effect. More importantly, I need help to add an action that will change a second listbox‘ entries based on the selected item of the first listbox. Thanks in advance!

7
  • Hi pal! Add additional information using the edit button of the question, and not the comment section. Thank you for your understanding. Commented May 27, 2019 at 19:36
  • You didn't add the widget of the field to the page annotation list. And there is no rectangle. Commented May 28, 2019 at 9:22
  • thank you for your comments. I have now pasted my full code. I still need help please to add an action that will change a second listbox‘ entries based on the selected item of the first listbox. Thanks in advance! Commented May 28, 2019 at 19:47
  • The javadoc and the specification mentions that you must have a /CO entry in the acroform. However PDAcroForm doesn't offer this feature. What helps somewhat is this: COSArray coArray = new COSArray(); coArray.add(pdListBox); pdAcroForm.getCOSObject().setItem(COSName.CO, coArray);. Now a message pops up if I change the listbox and then click on the text field. I don't know if that is what you wanted. Commented May 29, 2019 at 9:23
  • Another alternative would be to use PDAnnotationAdditionalActions with the widget and setU(), see here: stackoverflow.com/questions/56192573 Commented May 29, 2019 at 9:24

1 Answer 1

0

// The following solved the issue:

// Define the listbox contents.

String javaScript = " + "this.getField('signatureField').display=display.hidden;" + "var formReady = false;" + "var anacredit = { '-': [['-', '-']], " + " 'Luxembourg': [[ '-', '-'], ['LU01 Entreprise individuelle', 'LU01'],[ 'LU06 Société anonyme', 'LU06'] ,['LU14 Société civile','LU14']] , " + " 'Germany': [[ '-', '-'], ['DE201 Aktiengesellschaft', 'DE201'], ['DE602 EV', 'DE602'], ['DE205 Investmentaktiengesellschaft', 'DE205']], " + " 'Greece': [[ '-', '-'], ['GR906 Εταιρία Περιορισμένης Ευθύνης/Etería', 'GR906'], ['GR912 Κοινοπραξία', 'GR912'], ['GR999 Λοιπά', 'GR999']] };";

// javascript for listbox 1

String jsListBox0 = "var f = this.getField('domicilation');" + "var r = this.getField('legalForm');" + " console.println('dom ' + f.value + 'lF' + r.value);" + "if (event.willCommit)" + "{ console.println('dom EC ' + event.change + ' EV ' + event.value + ' ECE ' + event.changeEx); " + " r.setItems( anacredit[event.value] );" + "this.getField('signatureField').display=display.hidden;" + "r.value= '-';" + " }";

// related java code for listbox 1

jsKeystrokeAction.setAction(jsListBox0); fieldActions.setK(jsKeystrokeAction); domicilation.setActions(fieldActions);

// javascript for listbox 2

String jsListBox2 = "var lb = this.getField('legalForm'); var d = this.getField('domicilation');" + "var sf = this.getField('signatureField');" + "if (!event.willCommit) " + "{ console.println('lF ' + lb.value + ' EC ' + event.change + ' EV ' + event.value + ' ECE ' + event.changeEx);" + " if ((event.changeEx =='-') || (event.changeEx == null)) sf.display = display.hidden;" + " else sf.display = display.visible}";

// related java code for listbox 2

jsKeyStrokeAction.setAction(jsListBox2); fieldActions2.setK(jsKeyStrokeAction); legalForm.setActions(fieldActions2);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.