实际应用场景中,我们会遇到需要根据会话内容自动填写表格的情况,比如:pdf 表格。假设根据会话内容已经获得相关信息,下面以填写个人信息为例来说明。
个人信息表格.pdf
填写后的效果:
填写代码如下:
from pdfrw import PdfReader, PdfWriter
import traceback
def fill_personal_info_form(input_path, output_path):
# 待填充数据(匹配文档中的字段项)
text_data = {
"(full_name)": "李四", # 对应文档中“1. 姓名”
"(birth_date)": "1985年8月15日", # 对应“3. 出生日期”
"(id_card)": "310104198508152345", # 对应“4. 身份证号”
"(phone)": "13987654321", # 对应“5. 联系电话”
"(email)": "lisi1985@qq.com", # 对应“6. 电子邮箱”
"(address)": "上海市徐汇区淮海中路789号2号楼1003室" # 对应“7. 居住地址”
}
# 性别单选按钮组目标值(对应文档中“2. 性别”的“男”)
male_value = "male"
try:
input_pdf = PdfReader(input_path)
print(f"✅ 成功读取文件:{input_path}")
print(f"📄 包含 {len(input_pdf.pages)} 页")
found_fields = []
unnamed_annot_count = 0 # 计数无名字段(性别单选按钮组)
gender_male_assigned = False # 标记“男”是否已选中
for page_num, page in enumerate(input_pdf.pages, 1):
print(f"\n--- 处理第 {page_num} 页 ---")
if not page.Annots:
print("⚠️ 无表单字段")
continue
for annot in page.Annots:
# 提取字段名(文本框有明确名称,性别单选按钮可能无名称)
raw_field_name = annot.T.strip() if (annot.T and hasattr(annot.T, 'strip')) else None
# 处理文本框字段(匹配文档中的姓名、出生日期等)
if raw_field_name:
if raw_field_name in text_data:
annot.V = text_data[raw_field_name] # 文本框用V属性赋值
found_fields.append(raw_field_name)
print(f"✏️ 已填充 [{raw_field_name}]:{text_data[raw_field_name]}")
else:
print(f"ℹ️ 跳过字段 [{raw_field_name}]")
# 处理无名字段(性别单选按钮组,文档中含“男”“女”)
else:
unnamed_annot_count += 1
print(f"⚠️ 无名字段(序号:{unnamed_annot_count})")
# 第1个无名字段设为“男”(选中),用AS属性控制单选按钮状态
if not gender_male_assigned and unnamed_annot_count == 1:
annot.AS = male_value # 单选按钮用AS属性设置选中状态
gender_male_assigned = True
print(f"✏️ 已选中第{unnamed_annot_count}个无名字段(男)")
# 第2个无名字段设为“女”(未选中)
elif unnamed_annot_count == 2:
annot.AS = None # 确保“女”未选中
print(f"✏️ 第{unnamed_annot_count}个无名字段(女)设为未选中")
# 填充结果总结
print("\n--- 结果总结 ---")
print(f"✅ 成功填充:{found_fields}")
print(f"✅ 性别“男”选中状态:{'已选中' if gender_male_assigned else '未选中'}")
# 保存文件
output_pdf = PdfWriter()
output_pdf.addpages(input_pdf.pages)
with open(output_path, "wb") as f:
output_pdf.write(f)
print(f"\n💾 保存至:{output_path}")
except Exception as e:
print(f"\n❌ 错误:{str(e)}")
traceback.print_exc()
# 执行填充(输入输出路径可修改)
fill_personal_info_form(
input_path="个人信息表.pdf",
output_path="填写完成的个人信息表.pdf"
)
个人信息表格.pdf生成代码如下:
from reportlab.pdfgen import canvas
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
# 注册Mac系统预装的STHeiti Light字体
# 字体路径为macOS默认路径,无需额外安装
font_path = "/System/Library/Fonts/STHeiti Light.ttc"
font_name = "STHeitiLight" # 自定义字体名称用于引用
pdfmetrics.registerFont(TTFont(font_name, font_path))
# 表单字段使用PDF标准字体(避免非标准字体导致的表单错误)
form_font_name = "Helvetica"
# 初始化PDF画布
c = canvas.Canvas("个人信息表.pdf", pagesize=A4)
width, height = A4 # A4尺寸:宽595,高842
# 绘制标题(使用STHeiti Light字体,中文正常显示)
c.setFont(font_name, 16)
c.drawCentredString(width/2, height-50, "个人信息登记表")
c.setFont(font_name, 12) # 恢复标签字体大小
y_position = height - 100 # 起始Y坐标
spacing = 40 # 行间距
# 1. 姓名
c.drawString(100, y_position, "1. 姓名:") # 中文标签用STHeiti Light
c.acroForm.textfield(
name="full_name",
x=200, y=y_position-20,
width=200, height=20,
borderColor=colors.black,
fillColor=colors.white,
fontName=form_font_name # 表单字段用标准字体
)
y_position -= spacing
# 2. 性别(单选按钮组)
c.drawString(100, y_position, "2. 性别:")
c.acroForm.radio(
name="gender",
value="male",
x=200, y=y_position-10,
size=10
)
c.drawString(220, y_position, "男") # 中文选项用STHeiti Light
c.acroForm.radio(
name="gender",
value="female",
x=280, y=y_position-10,
size=10
)
c.drawString(300, y_position, "女")
y_position -= spacing
# 3. 出生日期
c.drawString(100, y_position, "3. 出生日期:")
c.acroForm.textfield(
name="birth_date",
x=200, y=y_position-20,
width=200, height=20,
borderColor=colors.black,
fontName=form_font_name
)
y_position -= spacing
# 4. 身份证号
c.drawString(100, y_position, "4. 身份证号:")
c.acroForm.textfield(
name="id_card",
x=200, y=y_position-20,
width=300, height=20,
borderColor=colors.black,
fontName=form_font_name
)
y_position -= spacing
# 5. 联系电话
c.drawString(100, y_position, "5. 联系电话:")
c.acroForm.textfield(
name="phone",
x=200, y=y_position-20,
width=200, height=20,
borderColor=colors.black,
fontName=form_font_name
)
y_position -= spacing
# 6. 电子邮箱
c.drawString(100, y_position, "6. 电子邮箱:")
c.acroForm.textfield(
name="email",
x=200, y=y_position-20,
width=300, height=20,
borderColor=colors.black,
fontName=form_font_name
)
y_position -= spacing
# 7. 居住地址
c.drawString(100, y_position, "7. 居住地址:")
c.acroForm.textfield(
name="address",
x=200, y=y_position-20,
width=350, height=20,
borderColor=colors.black,
fontName=form_font_name
)
y_position -= spacing
# 保存PDF
c.save()
print("个人信息表已生成:个人信息表.pdf")
注意:性别竟然找不到对应的(gender),需要特殊处理。
环境为masOS,其它系统字体设置会有所差别。