java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java自动填充PDF表单

Java自动读取和填写PDF中的交互式表单字段

作者:用户372157426135

本文详细讲解如何使用Java读取和填写PDF中的交互式表单,包括文本框、复选框、单选按钮、列表框和下拉框等控件,通过引入Spire.PDF for Java库,您可以轻松实现批量表单填充、业务数据回填等场景,并了解如何根据字段名称稳定填写内容

PDF 表单常用于信息登记、申请表、调查问卷、合同确认和业务审批等场景。与普通 PDF 不同,表单型 PDF 中包含可交互的文本框、复选框、单选按钮、下拉列表等控件,可以通过程序自动填写。

在需要批量生成申请表、自动回填客户资料或从业务系统导出 PDF 表单时,手动逐个填写显然效率较低。通过 Java 读取 PDF 表单域并写入数据,可以将这类操作集成到后台服务、桌面程序或批处理流程中。

本文将介绍如何:

本文方法适用于包含可交互表单域的 PDF 文件。如果 PDF 只是扫描图片、普通文本页面,或者表单已经被扁平化,则无法直接通过表单字段 API 进行填写。

一、安装所需的 Java 库

Java 标准库本身不提供 PDF 表单读取和填写功能,因此需要引入第三方 PDF 处理库。

本文示例使用 Spire.PDF for Java 读取 PDF 表单域,并填写不同类型的表单控件。

方式一:手动添加 JAR 包

可以从以下页面下载安装包:​​下载 Spire.PDF for Java​

解压后,将 ​​Spire.Pdf.jar​​ 添加到 Java 项目的构建路径中。

在 IntelliJ IDEA 中,可以依次打开:

File > Project Structure > Modules > Dependencies

然后添加对应的 JAR 文件。

在 Eclipse 中,可以右键项目并依次选择:

Build Path > Configure Build Path > Libraries

然后添加 JAR 文件。

方式二:通过 Maven 添加依赖

如果项目使用 Maven,可以在 ​​pom.xml​​ 中添加以下仓库和依赖配置:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf</artifactId>
        <version>12.6.4</version>
    </dependency>
</dependencies>

二、常见 PDF 表单字段类型

PDF 表单中可能包含多种控件。程序需要先判断字段的具体类型,再调用对应的方法写入内容。

表单类型对应类常用设置方法
文本框​PdfTextBoxFieldWidget​​setText()​
单选按钮组​PdfRadioButtonListFieldWidget​​setSelectedIndex()​
列表框​PdfListBoxWidgetFieldWidget​​setSelectedIndex()​
复选框​PdfCheckBoxWidgetFieldWidget​​setChecked()​
下拉框​PdfComboBoxWidgetFieldWidget​​setSelectedIndex()​

其中,列表框、下拉框和单选按钮通常通过选项索引进行设置。

需要注意,选项索引从 ​​0​​ 开始:

三、填写 PDF 中的所有表单字段

下面的示例会读取 PDF 中的所有表单字段,并根据字段类型填写内容。

实现步骤

  1. 创建 ​​PdfDocument​​ 对象。
  2. 使用 ​​loadFromFile()​​ 加载包含表单的 PDF。
  3. 通过 ​​getForm()​​ 获取 PDF 表单。
  4. 获取表单字段集合。
  5. 遍历字段集合并判断字段类型。
  6. 为不同类型的控件设置对应值。
  7. 保存填写后的 PDF。
  8. 关闭文档并释放资源。

完整代码

import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.fields.PdfField;
import com.spire.pdf.widget.PdfCheckBoxWidgetFieldWidget;
import com.spire.pdf.widget.PdfComboBoxWidgetFieldWidget;
import com.spire.pdf.widget.PdfFormFieldWidgetCollection;
import com.spire.pdf.widget.PdfFormWidget;
import com.spire.pdf.widget.PdfListBoxWidgetFieldWidget;
import com.spire.pdf.widget.PdfRadioButtonListFieldWidget;
import com.spire.pdf.widget.PdfTextBoxFieldWidget;

public class FillFormFields {

    public static void main(String[] args) {

        String inputPath = "Forms.pdf";
        String outputPath = "FillFormFields.pdf";

        // 创建 PdfDocument 对象
        PdfDocument document = new PdfDocument();

        try {
            // 加载包含表单域的 PDF 文件
            document.loadFromFile(inputPath);

            // 获取 PDF 表单
            PdfFormWidget form =
                (PdfFormWidget) document.getForm();

            // 获取表单字段集合
            PdfFormFieldWidgetCollection fields =
                form.getFieldsWidget();

            // 遍历并填写所有表单字段
            for (int i = 0; i < fields.getCount(); i++) {

                PdfField field = fields.get(i);

                // 填写文本框
                if (field instanceof PdfTextBoxFieldWidget) {
                    PdfTextBoxFieldWidget textBox =
                        (PdfTextBoxFieldWidget) field;

                    textBox.setText("Kaila Smith");
                }

                // 选择单选按钮组中的第二项
                else if (
                    field instanceof PdfRadioButtonListFieldWidget
                ) {
                    PdfRadioButtonListFieldWidget radioButton =
                        (PdfRadioButtonListFieldWidget) field;

                    radioButton.setSelectedIndex(1);
                }

                // 选择列表框中的第一项
                else if (
                    field instanceof PdfListBoxWidgetFieldWidget
                ) {
                    PdfListBoxWidgetFieldWidget listBox =
                        (PdfListBoxWidgetFieldWidget) field;

                    listBox.setSelectedIndex(0);
                }

                // 根据字段名称勾选复选框
                else if (
                    field instanceof PdfCheckBoxWidgetFieldWidget
                ) {
                    PdfCheckBoxWidgetFieldWidget checkBox =
                        (PdfCheckBoxWidgetFieldWidget) field;

                    switch (checkBox.getName()) {
                        case "checkbox1":
                        case "checkbox2":
                            checkBox.setChecked(true);
                            break;

                        default:
                            break;
                    }
                }

                // 选择下拉框中的第二项
                else if (
                    field instanceof PdfComboBoxWidgetFieldWidget
                ) {
                    PdfComboBoxWidgetFieldWidget comboBox =
                        (PdfComboBoxWidgetFieldWidget) field;

                    comboBox.setSelectedIndex(1);
                }
            }

            // 保存填写后的 PDF
            document.saveToFile(
                outputPath,
                FileFormat.PDF
            );

            System.out.println(
                "PDF 表单填写完成,输出文件:"
                + outputPath
            );
        } finally {
            // 关闭文档并释放资源
            document.close();
        }
    }
}

四、代码说明

1. 加载 PDF 表单

PdfDocument document = new PdfDocument();
document.loadFromFile("Forms.pdf");

​PdfDocument​​ 用于表示和处理 PDF 文档。​​loadFromFile()​​ 方法从指定路径加载文件。

2. 获取 PDF 表单对象

PdfFormWidget form =
    (PdfFormWidget) document.getForm();

​getForm()​​ 用于获取 PDF 中的表单对象。

由于需要访问表单控件集合,因此将返回结果转换为 ​​PdfFormWidget​​。

3. 获取所有表单字段

PdfFormFieldWidgetCollection fields =
    form.getFieldsWidget();

​getFieldsWidget()​​ 返回 PDF 中所有可交互表单字段的集合。

可以通过以下方法获取字段数量:

int fieldCount = fields.getCount();

并根据索引获取指定字段:

PdfField field = fields.get(i);

4. 判断字段类型

每个字段都继承或关联于 ​​PdfField​​,但实际类型可能不同,因此需要使用 ​​instanceof​​ 判断。

例如:

if (field instanceof PdfTextBoxFieldWidget) {
    PdfTextBoxFieldWidget textBox =
        (PdfTextBoxFieldWidget) field;

    textBox.setText("Kaila Smith");
}

对于不同类型的字段,应转换为对应的 Widget 类,再调用专用设置方法。

5. 保存填写后的文件

document.saveToFile(
    "FillFormFields.pdf",
    FileFormat.PDF
);

填写完成后,将文档保存为新的 PDF 文件,避免直接覆盖源文件。

五、根据字段名称填写不同内容

前面的代码会为所有文本框填写相同的值:

textBox.setText("Kaila Smith");

但在实际业务中,不同文本框通常对应姓名、地址、电话、邮箱等不同信息。此时应根据字段名称写入不同内容。

示例代码

if (field instanceof PdfTextBoxFieldWidget) {

    PdfTextBoxFieldWidget textBox =
        (PdfTextBoxFieldWidget) field;

    String fieldName = textBox.getName();

    switch (fieldName) {
        case "name":
            textBox.setText("Kaila Smith");
            break;

        case "email":
            textBox.setText("kaila@example.com");
            break;

        case "phone":
            textBox.setText("13800000000");
            break;

        case "address":
            textBox.setText(
                "No. 100, Example Road"
            );
            break;

        default:
            break;
    }
}

这种方式比按照字段索引填写更可靠。

原因是表单设计发生变化后,字段顺序可能改变,但只要字段名称不变,程序仍然可以正确识别目标字段。

六、查看 PDF 中所有表单字段的名称和类型

在编写填写逻辑之前,通常需要先了解 PDF 中有哪些字段,以及每个字段的名称和类型。

可以使用以下代码打印表单字段信息:

PdfFormWidget form =
    (PdfFormWidget) document.getForm();

PdfFormFieldWidgetCollection fields =
    form.getFieldsWidget();

for (int i = 0; i < fields.getCount(); i++) {

    PdfField field = fields.get(i);

    System.out.println(
        "字段索引:" + i
    );

    System.out.println(
        "字段名称:" + field.getName()
    );

    System.out.println(
        "字段类型:"
        + field.getClass().getSimpleName()
    );

    System.out.println("--------------------");
}

输出结果可能类似:

字段索引:0
字段名称:name
字段类型:PdfTextBoxFieldWidget
--------------------
字段索引:1
字段名称:gender
字段类型:PdfRadioButtonListFieldWidget
--------------------
字段索引:2
字段名称:checkbox1
字段类型:PdfCheckBoxWidgetFieldWidget
--------------------

根据这些信息,可以更准确地编写字段填写规则。

七、分别填写不同类型的 PDF 表单字段

填写文本框

PdfTextBoxFieldWidget textBox =
    (PdfTextBoxFieldWidget) field;

textBox.setText("Kaila Smith");

文本框通常用于填写:

选择单选按钮

PdfRadioButtonListFieldWidget radioButton =
    (PdfRadioButtonListFieldWidget) field;

radioButton.setSelectedIndex(1);

单选按钮组只能选择其中一个选项。

如果索引为 ​​1​​,表示选择第二个选项。

设置复选框状态

PdfCheckBoxWidgetFieldWidget checkBox =
    (PdfCheckBoxWidgetFieldWidget) field;

checkBox.setChecked(true);

取消勾选时,将参数设置为 ​​false​​:

checkBox.setChecked(false);

选择列表框项目

PdfListBoxWidgetFieldWidget listBox =
    (PdfListBoxWidgetFieldWidget) field;

listBox.setSelectedIndex(0);

索引 ​​0​​ 表示选择列表中的第一项。

选择下拉框项目

PdfComboBoxWidgetFieldWidget comboBox =
    (PdfComboBoxWidgetFieldWidget) field;

comboBox.setSelectedIndex(1);

索引 ​​1​​ 表示选择下拉列表中的第二项。

八、实际使用建议

1. 先确认 PDF 是否包含表单域

并非所有看起来像“表格”或“申请表”的 PDF 都包含可交互表单。

以下文件通常不能直接通过表单字段 API 填写:

可以先检查表单字段数量:

PdfFormWidget form =
    (PdfFormWidget) document.getForm();

PdfFormFieldWidgetCollection fields =
    form.getFieldsWidget();

if (fields.getCount() == 0) {
    System.out.println(
        "当前 PDF 中未检测到可填写的表单域。"
    );
}

2. 不要假设字段索引固定

以下写法依赖字段顺序:

PdfField field = fields.get(0);

如果表单经过修改,字段顺序可能发生变化。

对于业务系统,建议优先通过字段名称匹配:

if ("email".equals(field.getName())) {
    // 填写邮箱
}

3. 检查选项索引范围

单选按钮、列表框和下拉框均通过索引选择项目。如果索引超出实际选项数量,可能导致异常或无法正确选择。

使用前应确认:

4. 将结果保存为新文件

建议不要覆盖原始模板:

document.saveToFile(
    "Forms_Filled.pdf",
    FileFormat.PDF
);

这样可以保留未填写的原始表单,便于重复使用。

5. 及时释放资源

无论填写是否成功,都应关闭 ​​PdfDocument​​:

PdfDocument document =
    new PdfDocument();

try {
    document.loadFromFile("Forms.pdf");

    // 填写和保存操作
} finally {
    document.close();
}

对于批量处理任务,这一点尤其重要。

九、常见问题

为什么程序没有找到任何表单字段?

可能原因包括:

可以先打印 ​​fields.getCount()​​,确认表单字段数量。

为什么所有文本框都被填写成相同内容?

因为示例代码对每个 ​​PdfTextBoxFieldWidget​​ 都执行了相同的:

textBox.setText("Kaila Smith");

实际项目中应根据字段名称分别设置内容。

如何只填写某一个字段?

通过字段名称判断:

if (
    field instanceof PdfTextBoxFieldWidget
    && "name".equals(field.getName())
) {
    PdfTextBoxFieldWidget textBox =
        (PdfTextBoxFieldWidget) field;

    textBox.setText("Kaila Smith");
}

为什么下拉框选择的内容不正确?

​setSelectedIndex()​​ 使用从 ​​0​​ 开始的索引。

例如:

comboBox.setSelectedIndex(0);

表示选择第一项,而不是第二项。

如何取消复选框勾选?

将 ​​setChecked()​​ 参数设置为 ​​false​​:

checkBox.setChecked(false);

是否可以批量填写多个 PDF 表单?

可以。可以遍历文件夹中的 PDF 文件,为每个文件创建独立的 ​​PdfDocument​​ 对象,填写后分别保存。

批量处理时应注意:

总结

通过 Java 可以自动读取和填写 PDF 中的交互式表单字段。

在实际项目中,建议先输出字段名称和类型,再根据字段名称分别填写内容。相比依赖字段索引,这种方式在表单模板发生调整后更加稳定。

同时需要确认源 PDF 确实包含可交互表单域。对于扫描件、普通页面或已扁平化表单,需要使用其他方式识别和写入内容。

以上就是Java自动读取和填写PDF中的交互式表单字段的详细内容,更多关于Java自动填充PDF表单的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文