跳到主要内容
Python 办公自动化:Word 文档操作与报告生成 | 极客日志
Python
Python 办公自动化:Word 文档操作与报告生成 介绍使用 Python 进行 Word 文档自动化的方法。涵盖 python-docx、win32com、mailmerge 和 matplotlib 库的安装与使用。内容包括新建与编辑文档、格式转换(doc 转 docx、word 转 pdf)、表格处理、图片插入、图表绘制以及批量生成合同等场景。通过实际案例演示如何读取 Excel 数据并生成包含统计图表的 Word 分析报告,实现办公流程自动化。
极光 发布于 2025/2/7 更新于 2026/6/2 24 浏览Python 办公自动化:Word 文档操作指南
环境安装
使用 Python 操作 Word 文档主要涉及写操作,也有部分读操作。本次教程将讲解以下 4 个库的安装与使用。
升级 pip
python -m pip install -U pip setuptools
python-docx
大部分操作使用此库。
安装方法:
pip install python-docx
使用方法:
from docx import Document
from docx.shared import Inches
官方文档: https://python-docx.readthedocs.io/en/latest/index.html
win32com
主要用于 doc 转 docx 格式转换及调用本地 Word 应用。
安装方法:
pip install pypiwin32
使用方法:
import win32com
from win32com.client import Dispatch, constants
官方文档: https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.word?view=word-pia
mailmerge
用于按照模板生成大量同类型文档。
安装方法:
pip install docx-mailmerge
使用方法:
from mailmerge import MailMerge
官方文档: https://pypi.org/project/docx-mailmerge/
matplotlib
Python 绘图库,本期简单讲解。
安装方法:
pip install matplotlib
import matplotlib.pyplot as plt
Python_docx 新建文档
示例代码 from docx import Document
document = Document()
document.save('new.docx' )
函数封装示例 from docx import Document
def GenerateNewWord (filename ):
document = Document()
document.save(filename)
if __name__ == "__main__" :
print ("大家好!我们今天开始学习 word 文档自动化" )
print ("我们先来直接生成一个名为 new.docx 的文档" )
document = Document()
document.save('new.docx' )
print ("没错,里面什么都没有" )
print ("我们使用函数生成一个 word 文档试试" )
newname = '使用函数生成的文档.docx'
GenerateNewWord(newname)
Python_docx 编辑已存在文档 很多时候需要在已存在的 Word 文档上添加内容。
from docx import Document
document = Document('exist.docx' )
document.save('new.docx' )
这三行代码即可完成旧文档的复制。如需修改,直接在加载后添加内容即可。
win32com 将 doc 转为 docx 利用 win32com 可以调用本地 Word 应用程序进行格式转换。
import os
from win32com import client as wc
def TransDocToDocx (oldDocName, newDocxName ):
print ("我是 TransDocToDocx 函数" )
word = wc.Dispatch('Word.Application' )
doc = word.Documents.Open(oldDocName)
doc.SaveAs(newDocxName, 12 )
doc.Close()
word.Quit()
print ("生成完毕!" )
if __name__ == "__main__" :
currentPath = os.getcwd()
print ("当前路径为:" , currentPath)
docName = os.path.join(currentPath, '旧 doc 格式文档.doc' )
print ("docFilePath = " , docName)
docxName = os.path.join(currentPath, '新生成 docx 格式文档.docx' )
TransDocToDocx(docName, docxName)
win32com 操作 Word
打开新的 Word 文档并添加内容 import win32com
from win32com.client import Dispatch, constants
import os
def funOpenNewFile ():
word = Dispatch('Word.Application' )
word.Visible = 1
word.DisplayAlerts = 0
doc = word.Documents.Add()
myRange1 = doc.Range(0 , 0 )
myRange1.InsertBefore('Hello word\n' )
myRange2 = doc.Range()
myRange2.InsertAfter('Bye word\n' )
i = 0
myRange3 = doc.Range(0 , i)
myRange3.InsertAfter("what's up, bro?\n" )
doc.SaveAs(os.getcwd() + "\\funOpenNewFile.docx" )
doc.Close()
word.Quit()
if __name__ == '__main__' :
print ("当前文件路径名:" , os.getcwd())
print ("调用 funOpenNewFile()" )
funOpenNewFile()
打开已存在 Word 文档并添加内容 import win32com
from win32com.client import Dispatch, constants
import os
def funOpenExistFile ():
word = Dispatch('Word.Application' )
word.Visible = 1
word.DisplayAlerts = 0
doc = word.Documents.Open(os.getcwd() + "\\3.1 win32com 测试.docx" )
myRange1 = doc.Range(0 , 0 )
myRange1.InsertBefore('Hello word\n' )
myRange2 = doc.Range()
myRange2.InsertAfter('Bye word\n' )
i = 0
myRange3 = doc.Range(0 , i)
myRange3.InsertAfter("what's up, bro?\n" )
doc.SaveAs(os.getcwd() + "\\funOpenExistFile.docx" )
doc.Close()
word.Quit()
if __name__ == '__main__' :
print ("当前文件路径名:" , os.getcwd())
print ("调用 funOpenExistFile()" )
funOpenExistFile()
转换 Word 为 PDF import win32com
from win32com.client import Dispatch, constants
import os
def funGeneratePDF ():
word = Dispatch("Word.Application" )
word.Visible = 0
word.DisplayAlerts = 0
doc = word.Documents.Open(os.getcwd() + "\\3.3 win32com 转换 word 为 pdf 等格式.docx" )
doc.SaveAs(os.getcwd() + "\\3.3 win32com 转换 word 为 pdf 等格式.pdf" , 17 )
doc.Close()
word.Quit()
if __name__ == '__main__' :
funGeneratePDF()
Python_docx 操作 Word
官方例程解析 from docx import Document
from docx.shared import Inches
document = Document('exist.docx' )
document.add_heading('Document Title' , 0 )
p = document.add_paragraph('A plain paragraph having some ' )
p.add_run('bold' ).bold = True
p.add_run(' and some ' )
p.add_run('italic.' ).italic = True
等级 1-9 也就是标题 1-标题 9,可以在旧文档中将标题格式设置好,使用 Python-docx 打开旧文档,再添加相应等级标题即可。
document.add_heading('Heading, level 1' , level=1 )
document.add_paragraph('Intense Quote' , style='Intense Quote' )
p = document.add_paragraph('Intense Quote' )
p.style = 'Intense Quote'
document.add_paragraph('first item in unordered list' , style='List Bullet' )
document.add_paragraph('first item in ordered list' , style='List Number' )
第一个参数为图片路径,需要正确无误;第二个参数为图片大小,单位英寸。
document.add_picture('countrygarden.png' , width=Inches(1.25 ))
table = document.add_table(rows=1 , cols=3 )
hdr_cells = table.rows[0 ].cells
hdr_cells[0 ].text = 'Qty'
hdr_cells[1 ].text = 'Id'
hdr_cells[2 ].text = 'Desc'
for qty, id , desc in records:
row_cells = table.add_row().cells
row_cells[0 ].text = str (qty)
row_cells[1 ].text = id
row_cells[2 ].text = desc
table.style = 'LightShading-Accent1'
document.add_page_break()
document.save('4.1 Python-docx 官方例程.docx' )
表格样式设置 from docx.enum.style import WD_STYLE_TYPE
from docx import Document
document = Document()
styles = document.styles
for s in styles:
if s.type == WD_STYLE_TYPE.TABLE:
document.add_paragraph("表格样式 : " + s.name)
table = document.add_table(3 , 3 , style=s)
heading_cells = table.rows[0 ].cells
heading_cells[0 ].text = '第一列内容'
heading_cells[1 ].text = '第二列内容'
heading_cells[2 ].text = '第三列内容'
document.add_paragraph("\n" )
document.save('4.3 所有表格样式.docx' )
docx & matplotlib 自动生成数据分析报告
数据获取 import xlrd
xlsx = xlrd.open_workbook('./3_1 xlrd 读取 操作练习.xlsx' )
table = xlsx.sheet_by_index(0 )
value = table.cell_value(2 , 1 )
print ("第 3 行 2 列值为" , value)
nrows = table.nrows
print ("表格一共有" , nrows, "行" )
name_list = [str (table.cell_value(i, 3 )) for i in range (1 , nrows)]
print ("第 4 列所有的值:" , name_list)
编写数据获取代码 def GetExcelInfo ():
print ("开始获取表格内容信息" )
xlsx = xlrd.open_workbook('学生成绩表格.xlsx' )
sheet = xlsx.sheet_by_index(0 )
nrows = sheet.nrows
print ("一共 " , nrows, " 行数据" )
nameList = [str (sheet.cell_value(i, 1 )) for i in range (1 , nrows)]
scoreList = [int (sheet.cell_value(i, 3 )) for i in range (1 , nrows)]
return nameList, scoreList
柱状图生成 将获取的姓名和成绩使用字典数据结构关联起来,再对其排序。
scoreDictionary = dict (zip (nameList, scoreList))
scoreOrder = sorted (scoreDictionary.items(), key=lambda x: x[1 ], reverse=True )
def GenerateScorePic (scoreList ):
xNameList = [str (studentInfo[0 ]) for studentInfo in scoreList]
yScoreList = [int (studentInfo[1 ]) for studentInfo in scoreList]
matplotlib.rcParams['font.sans-serif' ] = ['SimHei' ]
plt.figure(figsize=(10 , 5 ))
plt.bar(x=xNameList, height=yScoreList, label='学生成绩' , color='steelblue' , alpha=0.8 )
for x1, yy in scoreList:
plt.text(x1, yy + 1 , str (yy), ha='center' , va='bottom' , fontsize=16 , rotation=0 )
plt.title("学生成绩柱状图" )
plt.xlabel("学生姓名" )
plt.ylabel("学生成绩" )
plt.legend()
plt.xticks(rotation=90 )
plt.gcf().subplots_adjust(bottom=0.25 )
plt.savefig("studentScore.jpg" )
plt.show()
生成最终报告 def GenerateScoreReport (scoreOrder, picPath ):
document = Document()
document.add_heading('数据分析报告' , 0 )
p1 = document.add_paragraph("分数排在第一的学生姓名为:" )
p1.add_run(scoreOrder[0 ][0 ]).bold = True
p1.add_run(" 分数为:" )
p1.add_run(str (scoreOrder[0 ][1 ])).italic = True
p2 = document.add_paragraph("共有:" )
p2.add_run(str (len (scoreOrder))).bold = True
p2.add_run(" 名学生参加了考试,学生考试的总体情况:" )
table = document.add_table(rows=1 , cols=2 )
table.style = 'Medium Grid 1 Accent 1'
hdr_cells = table.rows[0 ].cells
hdr_cells[0 ].text = '学生姓名'
hdr_cells[1 ].text = '学生分数'
for studentName, studentScore in scoreOrder:
row_cells = table.add_row().cells
row_cells[0 ].text = studentName
row_cells[1 ].text = str (studentScore)
document.add_picture(picPath, width=Inches(6 ))
document.save('学生成绩报告.docx' )
完整代码 import xlrd
import matplotlib
import matplotlib.pyplot as plt
from docx import Document
from docx.shared import Inches
def GetExcelInfo ():
print ("开始获取表格内容信息" )
xlsx = xlrd.open_workbook('学生成绩表格.xlsx' )
sheet = xlsx.sheet_by_index(0 )
nrows = sheet.nrows
print ("一共 " , nrows, " 行数据" )
nameList = [str (sheet.cell_value(i, 1 )) for i in range (1 , nrows)]
scoreList = [int (sheet.cell_value(i, 3 )) for i in range (1 , nrows)]
return nameList, scoreList
def GenerateScorePic (scoreList ):
xNameList = [str (studentInfo[0 ]) for studentInfo in scoreList]
yScoreList = [int (studentInfo[1 ]) for studentInfo in scoreList]
matplotlib.rcParams['font.sans-serif' ] = ['SimHei' ]
plt.figure(figsize=(10 , 5 ))
plt.bar(x=xNameList, height=yScoreList, label='学生成绩' , color='steelblue' , alpha=0.8 )
for x1, yy in scoreList:
plt.text(x1, yy + 1 , str (yy), ha='center' , va='bottom' , fontsize=16 , rotation=0 )
plt.title("学生成绩柱状图" )
plt.xlabel("学生姓名" )
plt.ylabel("学生成绩" )
plt.legend()
plt.xticks(rotation=90 )
plt.gcf().subplots_adjust(bottom=0.25 )
plt.savefig("studentScore.jpg" )
plt.show()
def GenerateScoreReport (scoreOrder, picPath ):
document = Document()
document.add_heading('数据分析报告' , 0 )
p1 = document.add_paragraph("分数排在第一的学生姓名为:" )
p1.add_run(scoreOrder[0 ][0 ]).bold = True
p1.add_run(" 分数为:" )
p1.add_run(str (scoreOrder[0 ][1 ])).italic = True
p2 = document.add_paragraph("共有:" )
p2.add_run(str (len (scoreOrder))).bold = True
p2.add_run(" 名学生参加了考试,学生考试的总体情况:" )
table = document.add_table(rows=1 , cols=2 )
table.style = 'Medium Grid 1 Accent 1'
hdr_cells = table.rows[0 ].cells
hdr_cells[0 ].text = '学生姓名'
hdr_cells[1 ].text = '学生分数'
for studentName, studentScore in scoreOrder:
row_cells = table.add_row().cells
row_cells[0 ].text = studentName
row_cells[1 ].text = str (studentScore)
document.add_picture(picPath, width=Inches(6 ))
document.save('学生成绩报告.docx' )
if __name__ == "__main__" :
nameList, scoreList = GetExcelInfo()
scoreDictionary = dict (zip (nameList, scoreList))
scoreOrder = sorted (scoreDictionary.items(), key=lambda x: x[1 ], reverse=True )
GenerateScorePic(scoreOrder)
picPath = "studentScore.jpg"
GenerateScoreReport(scoreOrder, picPath)
print ("任务完成,报表生成完毕!" )
Python_docx 修改旧 Word 文档
读取 Word 文档的内容 from docx import Document
if __name__ == "__main__" :
document = Document('6 学生成绩报告.docx' )
for p in document.paragraphs:
print ("paragraphs:" , p.text)
for p in document.paragraphs:
if p.style.name == 'Heading 1' :
print ("Heading 1:" , p.text)
for p in document.paragraphs:
if p.style.name == 'Normal' :
print ("Normal:" , p.text)
document.save('修改后的报告.docx' )
读取 docx 中表格内容 from docx import Document
if __name__ == "__main__" :
document = Document('6 学生成绩报告.docx' )
for tb in document.tables:
for i, row in enumerate (tb.rows):
for j, cell in enumerate (row.cells):
text = ''
for p in cell.paragraphs:
text += p.text
print (f'第{i} 行,第{j} 列的内容{text} ' )
document.save('修改后的报告.docx' )
修改 Word 中的内容 from docx import Document
if __name__ == "__main__" :
document = Document('6 学生成绩报告.docx' )
for p in document.paragraphs:
p.text = "修改后的段落内容"
for tb in document.tables:
for i, row in enumerate (tb.rows):
for j, cell in enumerate (row.cells):
text = ''
for p in cell.paragraphs:
p.text = ("第" , str (i), "行" , str (j), "列" )
print (f'第{i} 行,第{j} 列的内容{text} ' )
document.save('6.4 修改后的报告.docx' )
docx-mailmerge 自动生成万份劳动合同
创建合同模板
生成单份证明 from mailmerge import MailMerge
template = '薪资证明模板.docx'
document = MailMerge(template)
document.merge(
name='唐星' ,
id ='1010101010' ,
year='2020' ,
salary='99999' ,
job='嵌入式软件开发工程师'
)
document.write('生成的 1 份证明.docx' )
批量生成证明 from mailmerge import MailMerge
from datetime import datetime
def GenerateCertify (templateName, newName ):
document = MailMerge(templateName)
document.merge(
name='唐星' ,
id ='1010101010' ,
year='2020' ,
salary='99999' ,
job='嵌入式软件开发工程师'
)
document.write(newName)
if __name__ == "__main__" :
templateName = '薪资证明模板.docx'
startTime = datetime.now()
for i in range (10000 ):
newName = f'./10000 份证明/薪资证明{i} .docx'
GenerateCertify(templateName, newName)
endTime = datetime.now()
allSeconds = (endTime - startTime).seconds
print ("生成 10000 份合同一共用时:" , str (allSeconds), "秒" )
print ("程序结束!" )
相关免费在线工具 curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online