1

I have been following the 'Chapter 8: Filling out interactive forms' iText example (code and pdfs at http://itextpdf.com/examples/iia.php?id=154) and have noticed a number of appearance-related issues which also manifest themselves in the example pdfs.

The example features a list of radio buttons (classic dot within a circle) and a list of checkboxes (crossed box with a red background). So far so good. However the pdf generated after programmatically filling in these fields is visually inconsistent. The radio buttons have all reverted to squares and the selected ('Spanish') has a wingdings (?) cross within it rather than a dot. The fields are all still editable. When I select a different radio button, the previously selected radio button reverts to an empty circle. The newly selected field has changed from an empty square to a dotted circle. This can also be observed with the checkboxes.

Is there any way to fill the fields whilst preserving their original appearances?

Thanks!

EDIT - Here's a simplification of the code I use :

public void buildPdf() throws Exception {

    Document document = new Document(PageSize.A4);

    File file = new File("/test.pdf");
    final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));

    document.open();

    PdfPCell cell = new PdfPCell();

    PdfRadioGroupTable group = new PdfRadioGroupTable("ndna", Arrays.asList("Not Available", "Not Applicable"), writer, Locale.ENGLISH, DEFAULT);

    cell.addElement(group);

    PdfPTable table = new PdfPTable(1);

    table.addCell(cell);

    cell = new PdfPCell();      

    cell.setCellEvent(new ActionEvent(writer, "http://localhost:8080/entrypointpdf"));

    table.addCell(cell);

    document.add(table);

    group.addAnnotations();

    document.close();
}

Here's the ActionEvent

class ActionEvent implements PdfPCellEvent {

        private PdfWriter writer;
        private String submissionUrl;

        public ActionEvent(PdfWriter writer, String submissionUrl) {
            this.writer = writer;
            this.submissionUrl = submissionUrl;
        }

        @Override
        public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {

            PushbuttonField submit = new PushbuttonField(writer, position, "submit") {

                @Override
                public PdfFormField getField() throws IOException, DocumentException {

                    PdfFormField field = super.getField();

                    field.setAction(PdfAction.createSubmitForm(submissionUrl, null, 0));

                    return field;
                }
            };
            submit.setText("CLICK ME");
            submit.setTextColor(BaseColor.BLUE);
            submit.setFont(DEFAULT.getCalculatedBaseFont(false));
            submit.setVisibility(PushbuttonField.VISIBLE);

            try {
                writer.addAnnotation(submit.getField());
            } catch (Exception ignore) {
            }
        }
    }

Here's the PdfRadioGroupTable

public class PdfRadioGroupTable extends PdfPTable {

    private PdfWriter writer;
    public PdfFormField radioGroup;

    public PdfRadioGroupTable(String name, List<String> choices, PdfWriter writer, Locale locale, Font font) {
        super(2);

        this.writer = writer;

        setWidthPercentage(100);
        try {
            setTotalWidth(new float[] { 14, 400 });
        } catch (DocumentException ignore) {
        }

        radioGroup = PdfFormField.createRadioButton(writer, true);
        radioGroup.setFieldName(name);

        PdfPCell cell;

        for (String choice : choices) {
            cell = new PdfPCell();

            cell.setBorder(0);
            cell.setPaddingBottom(5);

            cell.setUseAscender(true);
            cell.setUseDescender(true);
            cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);

            cell.setCellEvent(new RadioCellEvent(radioGroup, choice));

            addCell(cell);

            cell = new PdfPCell();

            cell.setBorder(0);

            cell.setPaddingBottom(5);
            cell.setPaddingLeft(6);

            cell.setUseAscender(true);
            cell.setUseDescender(true);
            cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);

            cell.addElement(new Phrase(choice), font));

            addCell(cell);
        }
    }

    class RadioCellEvent implements PdfPCellEvent {

        protected PdfFormField radioGroup;
        protected String value;

        public RadioCellEvent(PdfFormField radioGroup, String value) {
            this.radioGroup = radioGroup;
            this.value = value;
        }

        @Override
        public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {

            RadioCheckField radio = new RadioCheckField(writer, position, null, value);

            radio.setChecked(false);

            radio.setBorderColor(GrayColor.GRAYBLACK);
            radio.setBackgroundColor(GrayColor.GRAYWHITE);
            radio.setCheckType(RadioCheckField.TYPE_CIRCLE);

            try {
                PdfFormField field = radio.getRadioField();

                writer.addAnnotation(field);
                radioGroup.addKid(field);

            } catch (Exception exception) {
                throw new ExceptionConverter(exception);
            }
        }
    }
}   

And here's what happens on the server side when one clicks the button in the pdf (in acrobat) :

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=\"your.pdf\"");

        try {
            FdfReader fdf = new FdfReader(request.getInputStream());

            File pdfFile = new File("/test.pdf");

            InputStream is = new FileInputStream(pdfFile);

            PdfReader reader = new PdfReader(is);

            File resultFile = new File(System.currentTimeMillis() + "_" + pdfFile.getName());
            FileOutputStream out = new FileOutputStream(resultFile);

            PdfStamper stamper = new PdfStamper(reader, out);

            AcroFields fields = stamper.getAcroFields();
            fields.setFields(fdf);

            // EXTRACT VALUES HERE                                  

            stamper.setFormFlattening(true);

            stamper.close();
            reader.close();

            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            bos.write(FilesUtilities.read(resultFile));

            OutputStream os = response.getOutputStream();
            bos.writeTo(os);
            os.flush();

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

So basically I generate a pdf with one radiogroup and a button. The button results in the pdf fields being imported and the idea is to send a 'receipt' back to the user in the form of the previously generated pdf containing the same fields with the user selection/values and import status fields (ok, missing, bad data, etc.) (which I have omitted in the above code as that part works fine). My problem is that the radio fields in the returned pdf don't look remotely like the editable ones in the original pdf (they don't even look like radio buttons anymore).

Before

Returned

I tried using

fields.setFieldProperty("ndna", "setfflags", PdfFormField.FF_READ_ONLY, null);

and disabling form flattening by this results in the same alternate appearance in the returned pdf.

Your help would be most appreciated as I've been struggling with this for a while now...

Anthony

ChambreNoire
  • 387
  • 7
  • 19
  • 1
    Are you *flattening* the form? If so, the appearance should be preserved. If not, there's a bug somewhere and we'd need an example that reproduces the problem (including the PDF file you're trying to fill out). If you aren't flattening the form, you should check your PDF viewer. You are describing a feature of a viewer that can occur when you choose the option "highlight fields". Selecting or unselecting this feature can fix the problem. In this case the problem isn't caused by the PDF, but by the viewer. – Bruno Lowagie Oct 02 '15 at 19:19
  • I have edited my original question to include a stripped-down version of my code with an extra explanation. I'm using Acrobat reader by the way. – ChambreNoire Oct 05 '15 at 23:12

1 Answers1

0

This seems to be a bug on some versions of iText. I had the same problem with iTextSharp version 5.5.5 and it was solved after I upgraded to version 5.5.9. I used "nuget" to do this. Here's a link: https://www.nuget.org/packages/iTextSharp/5.5.9