如何填写PDF表格的例子

发布于:2025-08-04 ⋅ 阅读:(11) ⋅ 点赞:(0)

        实际应用场景中,我们会遇到需要根据会话内容自动填写表格的情况,比如: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,其它系统字体设置会有所差别。


网站公告

今日签到

点亮在社区的每一天
去签到