Excel 每行生成一份 Word:批量做工资条/通知书/聘书

2026-10-05 · 本脚本已实跑验证(3行名单 → 3份文档,逐字复核通过)

人事、行政、班主任最常问的需求:"我有一份Excel名单,要给每个人生成一份Word通知,人名/部门/金额都不一样,难道要复制粘贴50遍吗?" 不用。这就是Word自带的"邮件合并"干的活,但很多人装了Word一辈子没用过那个按钮。这里给纯Python版,免装Word、可跑在服务器上。

场景

名单.xlsx:

姓名  部门    工资   日期
张三  技术部  15000  2026年9月
李四  市场部  12000  2026年9月
王五  财务部  13500  2026年9月

模板.docx 里写占位符:【姓名】您好:您【部门】本月工资为【工资】元。

脚本(实跑通过)

import openpyxl, os
from docx import Document

PLACEHOLDERS = ['【姓名】', '【部门】', '【工资】', '【日期】']

rows = list(openpyxl.load_workbook('名单.xlsx').active
            .iter_rows(min_row=2, values_only=True))
os.makedirs('out', exist_ok=True)
for r in rows:
    d = Document('模板.docx')
    for p in d.paragraphs:
        for run in p.runs:
            for k, v in zip(PLACEHOLDERS, r):
                run.text = run.text.replace(k, str(v))
    d.save(f'out/{r[0]}.docx')

实跑输出:张三.docx / 李四.docx / 王五.docx,复核"张三.docx"正文为「张三您好:您技术部本月工资为15000元,发放日期2026年9月。」——三个占位符全部正确替换。

实跑复现的3个"悄悄错"的坑

坑1:占位符被Word拆进多个run → 替换直接漏掉

这是Word文档处理里最阴的坑。Word会在你打字时随手插入"运行片段(run)"——你在【部】和【门】中间点过一次鼠标,这两个字就分属两个run。逐run替换时每个run里都只占位符的一半,一个都匹配不上,什么也不报错,输出原样保留【部门】。实测:把"【部门】""【工资】"故意拆进3个run,逐run替换后输出仍是「您【部门】本月工资为【工资】元」。

正确做法:先拼接整段再替换,写回第一个run:

for p in d.paragraphs:
    merged = ''.join(r.text for r in p.runs)
    for k, v in pairs:
        merged = merged.replace(k, v)
    if p.runs:
        p.runs[0].text = merged
        for r in p.runs[1:]:
            r.text = ''

(代价是丢失run中间的局部格式;模板里整段同格式时完全没问题。表格单元格要再遍历 table.rows → row.cells → cell.paragraphs。)

坑2:Excel数字读出来变 15000.0

Excel里工资列存的是数字。哪怕显示成"15,000.00",openpyxl读出来是float 15000.0,str()之后通知单上就写着"工资为15000.0元"。实跑确认:单元格值 15000.00 → str 后是 15000.0。工资、编号这类列要么在Excel里设为文本格式,要么代码里做 v = int(v) if v == int(v) else v。

坑3:文件名用姓名,重名直接覆盖

名单里两个"张伟",第二份会静默覆盖第一份——你少发一份通知,没人提醒你。out/{r[0]}.docx 前先检查重名(计数或加工号后缀),或直接用 out/01_张三.docx 带序号命名。

需要现成的?

懒得装Python环境?喵窝提供表格/文档代做服务(¥19.9):把你的Excel和模板发给我们,交付现成的批量脚本+生成的成品文档,包免费重做(虚拟物品交付后不退款;未达承诺免费重做)。
👉 喵窝资源铺 · 服务下单 | 免费资源清单

← 更多干货