用Python批量生成Word报表:Pandas + python-docx实战指南
在日常办公中,我们经常遇到这样的场景:有一份Word合同或报告模板,里面有很多占位符(如{姓名}、{金额}),同时有一张Excel表格存储了所有需要填充的数据。如果只有三五份文档,手动复制粘贴还能忍受;但如果有成百上千份,那简直就是工作者的噩梦。
今天,我们就用Python的pandas和python-docx库,写一个批量生成Word文档的小工具。即使你刚接触Pandas,也能轻松看懂并应用到实际工作中。
一、代码功能与使用场景
核心功能:读取一个Word模板文件(内含占位符,比如{姓名}、{部门}),再读取一个Excel数据文件(每行代表一份文档的填充数据),自动为Excel中的每一行生成一份填充好的Word文档,并以Excel中指定的file_name列作为文件名保存。
二、完整代码速览
from docx import Documentimport pandas as pd# 获取模板文件def getMbData(path):doc = Document(path)all_paragraphs = doc.paragraphsall_tables = doc.tablesreturn all_paragraphs, all_tables, doc# 获取Excel数据(待填充的真实数据)def getRealData(path):dr = pd.read_excel(path)return dr# 获取Excel数据的列名def getColumns(dr: pd.DataFrame):columns = dr.columnsreturn columns#生成文档def generaterFile(path_mb,path_data):dr = pd.read_excel(path_data)columns = getColumns(dr)for i in range(len(dr)):all_paragraphs, all_tables, doc = getMbData(path_mb)for j in columns:for paragraph in all_paragraphs:for run in paragraph.runs:run.text = run.text.replace(j, str(dr.loc[i, j]))for tab in all_tables:for row in tab.rows:for cell in row.cells:cell.text = cell.text.replace(j, str(dr.loc[i, j]))doc.save(f’./datafile/generate/{dr.loc[i, ‘file_name’]}.docx’)if __name__==’__main__’:generaterFile(‘./datafile/mb.docx’,’./datafile/data.xlsx’)
三、代码分块解析
1.导入必要的库
from docx import Document
import pandas as pd
pandas:用于读取Excel表格,我们主要用它的DataFrame结构。
2.读取Word模板函数
def getMbData(path):
doc= Document(path)
all_paragraphs= doc.paragraphs# 所有段落
all_tables= doc.tables# 所有表格
return all_paragraphs, all_tables, doc
这个函数的作用是打开Word模板,把里面的所有段落和所有表格分别提取出来。
为什么要区分段落和表格?因为Word中的文字可能出现在普通段落里,也可能出现在表格的单元格中。我们后面需要遍历这两部分才能做到全文替换。
3.读取Excel数据函数
def getRealData(path):
dr= pd.read_excel(path)
return dr
直接用pd.read_excel将Excel文件读成DataFrame。假设Excel长这样:
file_name 姓名 部门 金额
张三_工资单 张三 销售部 5000
李四_工资单 李四 技术部 7000
file_name列用于生成最终文档的文件名,其余列对应Word模板中的占位符。
4.获取列名函数
def getColumns(dr: pd.DataFrame):
columns= dr.columns
return columns
简单返回DataFrame的所有列名。这些列名就是Word模板中需要被替换的“标签”。
5.核心生成函数
def generaterFile(path_mb, path_data):
dr= pd.read_excel(path_data)
columns= getColumns(dr)
fori in range(len(dr)):
#每一轮都要重新加载模板(保证模板不被上一轮修改)
all_paragraphs,all_tables, doc = getMbData(path_mb)
forj in columns:
#替换段落中的占位符
forparagraph in all_paragraphs:
forrun in paragraph.runs:
run.text= run.text.replace(j, str(dr.loc[i, j]))
#替换表格中的占位符
fortab in all_tables:
forrow in tab.rows:
forcell in row.cells:
cell.text= cell.text.replace(j, str(dr.loc[i, j]))
#保存生成的文件
doc.save(f’./datafile/generate/{dr.loc[i,“file_name”]}.docx’)
逐层拆解:
外层循环for i in range(len(dr)):遍历Excel的每一行,每一行生成一份文档。
重新加载模板:每次循环都重新读取mb.docx,避免上一轮的修改污染下一轮。
内层循环for j in columns:遍历当前行的每一个列名(也就是占位符,比如{姓名})。
替换段落:doc.paragraphs获取所有段落;每个段落又有多个runs(具有相同格式的连续文本块)。这里对每个run的文本执行replace,把占位符替换成当前行的实际值。
替换表格:同理,遍历所有表格的所有行所有单元格,执行替换。
保存文件:文件名从当前行的file_name列取值,保存到./datafile/generate/目录下。
注意:代码中str(dr.loc[i, j])将Excel单元格的值转为字符串,避免数字、日期等类型报错。
四、运行结果展示
word模板文件中包含内容:
尊敬的{部门}{姓名}:您本月的工资为{金额}元
Excel中的真实数据为:
file_name 姓名 部门 金额
张三_工资单 张三 销售部 5000
李四_工资单 李四 技术部 7000
在generate文件夹下会生成文件:
张三_工资单.docx
李四_工资单.docx
打开文件内容显示:
尊敬的{销售部}{张三}:您本月的工资为{5000}元
五、常见问题与注意事项
1.占位符没有替换成功?
检查占位符是否完全一致:Excel的列名必须和Word中的占位符文本一模一样(包括大小写、空格)。
检查Word中的占位符是否跨Run:例如{姓名}可能被拆成{、姓名、}三个run,导致替换失败。解决方案:手动在Word中将占位符选中,设置成同一格式(或重新输入),确保它在同一个run中。
2.替换后格式丢失怎么办?
run.text替换会保留run的原有格式(字体、大小、颜色等)。但如果占位符跨run,替换逻辑可能无法覆盖全。保险做法:整个段落整体替换(但会丢失段落内不同格式),本例按run替换是较安全的方式。
3.Excel中的日期变成奇怪的数字?
Excel存储日期为数字序列(如44810代表2022-09-01)。替换前需要用pd.to_datetime格式化。可在循环内添加:
value = dr.loc[i, j]
if isinstance(value, pd.Timestamp):
value = value.strftime(‘%Y-%m-%d’)
4.路径和文件夹不存在?
保存文件前,请确保./datafile/generate/目录已经存在,否则会报FileNotFoundError。可以在代码开头添加:
import os
os.makedirs(‘./datafile/generate/’, exist_ok=True)
六 总结
本文我们用不到50行代码,实现了一个自动批量生成Word文档的工具。核心思想很简单:
1用pandas读取结构化数据(Excel);
2用python-docx解析Word模板;
3遍历数据每一行,将模板中的占位符替换成真实数据;
4另存为新文档。
这个模式可以灵活迁移到任何“模板+数据”的场景,比如批量生成HTML邮件、PDF报告(先做Word再转PDF)等。掌握了Pandas的数据处理能力和python-docx的文档操作,办公自动化的大门就向你敞开了。
动手试一试吧!找一份你手头的Word模板和Excel数据,改改路径运行一下——你会惊讶于Python带来的效率提升。如果遇到问题,欢迎在评论区留言交流。
夜雨聆风