← Java

Java · 11 / 18

Read CSV and fill PDF forms

Read structured CSV fields and set an AcroForm value using PDFBox.

  • Medium
  • Intermediate
  • 45 min

Prerequisites: Maven, modules and ports/adapters

A PDF is not automatically a form. AcroForm contains named fields that can be set. A CSV file supplies rows with columns. A mapping connects a PDF field name with a CSV column. Our example creates a safe form and fills recipient from name. You therefore need no private document for learning.

01Prepare the parser and PDFBox

Save the two sample files in a new Maven learning project. Versions match the checked PDF codebase. Commons CSV parses fields correctly. String.split(",") would fail for quoted fields and embedded delimiters.

pom.xml · xmlOpen file
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId><artifactId>learning</artifactId><version>1.0</version>
  <properties><maven.compiler.release>21</maven.compiler.release><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
  <dependencies><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>3.0.8</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-csv</artifactId><version>1.14.1</version></dependency></dependencies>
  <build><plugins>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.14.1</version></plugin>
    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.3</version></plugin>
  </plugins></build>
</project>

Run / check

mvn package dependency:copy-dependencies
java -cp "target/classes:target/dependency/*" tutorial.Main

02Create a form field

PDAcroForm contains field definitions. PDTextField has a partial name. Its widget describes the visible position on a page. The standard font and default appearance make the field value visible. These are different responsibilities inside the PDF model.

src/main/java/tutorial/Main.java · javaOpen file
package tutorial;
import java.io.StringReader;
import java.io.File;
import org.apache.commons.csv.CSVFormat;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDTextField;
import org.apache.pdfbox.cos.COSName;
public class Main {
  public static void main(String[] args) throws Exception {
    var format = CSVFormat.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).get();
    try (var csv = format.parse(new StringReader("name\nAda\n"));
         var document = new PDDocument()) {
      var page = new PDPage(); document.addPage(page);
      var form = new PDAcroForm(document);
      document.getDocumentCatalog().setAcroForm(form);
      var resources = new PDResources();
      resources.put(COSName.getPDFName("Helv"), new PDType1Font(Standard14Fonts.FontName.HELVETICA));
      form.setDefaultResources(resources); form.setDefaultAppearance("/Helv 12 Tf 0 g");
      var field = new PDTextField(form); field.setPartialName("recipient");
      var widget = field.getWidgets().getFirst();
      widget.setRectangle(new PDRectangle(40, 700, 250, 30)); widget.setPage(page);
      page.getAnnotations().add(widget); form.getFields().add(field);
      field.setValue(csv.iterator().next().get("name"));
      document.save(new File("result.pdf"));
      System.out.println("result.pdf: recipient = Ada");
    }
  }
}

03Map columns to fields

get("name") reads the named CSV column. setValue writes the confirmed value into the PDF field. The real engine first checks that both column and field exist and the value matches the field type. Checkboxes need different rules from text fields.

04Verify semantics rather than bytes

Open result.pdf and check Ada. In the testing tutorial we read the field value back using PDFBox. Two PDFs can differ in bytes while containing the same domain content. Verification should check the expected meaning.

Expected result

One page with a visible recipient form field containing Ada.

Your exercise

Change the CSV value to "Ada, Lovelace" using correct CSV quoting.

Show the solution and explanation

The data row is "Ada, Lovelace" including CSV quotes. Escape those quotes inside the Java string. Commons CSV still produces one field value. The PDF text contains the comma.

Project context and sources

The example is simplified for learning. The linked source version shows its use in the project and the checks applied there.