Python填写PDF表单字段:自动批量填合同
用Python的PyMuPDF读取PDF表单字段并批量填充,支持文本框、复选框、下拉框,填完另存为新文件,适合批量生成合同、申请表、报名表。
场景痛点
公司有一份固定模板的PDF合同或申请表,每次要手动打开Adobe Reader,在各个字段里填客户名、金额、日期,几十份下来手都软。其实PDF表单(AcroForm)里每个字段都有名字,用Python读出来、按字典填值、另存为新文件,一次能批量生成几百份。
用到的库
pip install pymupdf
完整代码
# -*- coding: utf-8 -*-
"""
读取 PDF 表单字段,按字典批量填充,另存为新 PDF。
"""
import fitz # PyMuPDF
from pathlib import Path
def list_form_fields(pdf_path: str):
"""打印 PDF 里所有表单字段名和当前值,方便先摸清楚字段名。"""
doc = fitz.open(pdf_path)
print(f"=== {pdf_path} 的表单字段 ===")
for page in doc:
for widget in page.widgets():
print(f" 字段名: {widget.field_name!r:30} 类型: {widget.field_type_string:10} 当前值: {widget.field_value!r}")
doc.close()
def fill_pdf_form(template_pdf: str, output_pdf: str, data: dict):
"""
template_pdf: 带表单的 PDF 模板
output_pdf: 填好后另存的文件
data: {字段名: 值},如 {"customer": "张三", "amount": "12800"}
"""
doc = fitz.open(template_pdf)
for page in doc:
for widget in page.widgets():
field_name = widget.field_name
if field_name in data:
widget.field_value = str(data[field_name])
# 标记为已修改,保存时才会写进去
widget.update()
# 保存时把表单字段扁平化(flatten),填好的值变成普通文字,
# 别人打开不能再改;不想扁平化就去掉这个参数
doc.save(output_pdf, garbage=3, deflate=True)
doc.close()
print(f"已生成:{output_pdf}")
def batch_fill(template_pdf: str, output_dir: str, records: list):
"""
records: 一组字典,每个字典是一份要填的数据
"""
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
for idx, record in enumerate(records, start=1):
# 用客户名或序号命名输出文件
name = record.get("customer", f"doc_{idx:03d}")
out_file = out / f"{name}.pdf"
fill_pdf_form(template_pdf, str(out_file), record)
if __name__ == "__main__":
# 第一步:先跑这个,看清楚模板里的字段名
list_form_fields("contract_template.pdf")
# 第二步:按字段名填数据
batch_fill(
template_pdf="contract_template.pdf",
output_dir="filled_contracts",
records=[
{"customer": "张三", "amount": "12800", "date": "2026-09-14"},
{"customer": "李四", "amount": "25600", "date": "2026-09-14"},
{"customer": "王五", "amount": "8900", "date": "2026-09-14"},
],
)
代码讲解
page.widgets()遍历当前页所有表单控件,每个widget有field_name(字段名)、field_type_string(类型:Text/CheckBox/ComboBox)、field_value(当前值)。list_form_fields()是调试用的,第一次拿到模板先跑一遍,把所有字段名打印出来,再照着写data字典,避免猜错字段名。widget.field_value = "..."直接赋值,然后必须调widget.update(),PyMuPDF才会把修改写回文档。- 复选框的填值是
"Yes"或"Off",下拉框要填选项里存在的值,否则保存后不显示。 - 保存时不加
flatten参数,填好的PDF仍然是可编辑表单;加了flatten=True(在save里传)就把值"烤"进页面,别人改不了。
运行结果
先跑list_form_fields看到模板里有哪些字段名,然后照着填数据。跑完filled_contracts/目录下生成张三.pdf、李四.pdf、王五.pdf,打开后客户名、金额、日期都已经填好。
注意事项
- 不是所有PDF都有表单字段。扫描件PDF、Word另存的PDF通常没有可填字段,这种情况要用"在指定位置插入文字"的方案。
- 字段名是PDF制作者在Acrobat里起的,可能是
Text1、customer_1这种,必须先list_form_fields看清楚,不能猜。 - 中文字段值在某些旧版PDF阅读器里可能显示不全,用最新版Adobe Reader或浏览器打开验证。
- 批量生成合同时,模板文件本身不要被修改,脚本只读模板、输出到新目录。

更新时间:2026-09-14 21:38:18