上一篇介绍了【Python 实现 PDF 文件的批量操作】,这篇将介绍通过 Python 实现 Word 文档的批量操作。Word 作为日常办公重要且常用的文档之一,经常也会遇到一些繁琐的操作场景,比如批量生成某一类型的 Word 文档,批量对 Word 文档的关键字进行标注、替换或者删除,批量将 Word 文档转换成其他格式的文件等。为了提升工作的效率,通过 Python 解决这些场景的方式,有必要了解下。
Word 文件的后缀有.doc 和 .docx 格式,以下模块支持 word 文档的读写:
接下来,使用会涉及到这两个模块的使用,可以通过 pip 命令先下载这些模块,
pip install python-docx
pip install pywin32
需要注意,python-docx 模块在 import 时,名称是 docx;pywin32 模块在导入时,名称是win32com。
我们知道,在平时办公中,如果使用 Word 文档的 "邮件合并" 功能,可以批量制作一些主要内容相同、只是部分数据不一样的文档,比如邀请函、通知单、采购合同、成绩单等。Python 也可以实现类似的功能,通过套用指定的模板批量生成 Word 文档。
以邀请函的批量制作为例,首先准备一份模板,内容如下:
邀请函中需要替换的字段都用 英文单词 标记,而填充到模板中的具体信息,可以放在 Excel 表格保存,需要注意的是,Excel 表格各列的标题必须与模板中的字段名保持一致,如下:
代码实现的思路也比较简单:从 Excel 表格中逐行读取数据,然后在 Word 模板文档中查找对应的字段进行替换,最后保存替换后的 Word 文档,完成邀请函的批量制作。
引入的模块:
from docx import Document
from openpyxl import load_workbook
自定义替换标记内容的方法,如下:
def process_replace(doc, header, data):
# 段落(不支持表格文本)、具有相同样式的一段连续文本、文本内容
paragraphs = doc.paragraphs
# print("paragraphs is not null.")
if len(paragraphs) > 0:
for paragraph in paragraphs:
runs = paragraph.runs
if len(runs) > 0:
for run in runs:
run.text = run.text.replace(header, data)
print(f"run.text: { run.text}")
# 含表格的文本
tables = doc.tables
if len(tables) > 0:
# print("tables is not null.")
for table in tables:
rows = table.rows
if len(rows) > 0:
for row in rows:
cells = row.cells
if len(cells) > 0:
for cell in cells:
cell.text = cell.text.replace(header, data)
读取 Excel ,经过替换处理后,批量生成带公司名称的 Word 文档:
def process(doc_path, excel_path):
wb = load_workbook(excel_path)
sheet = wb.active
for row in range(2, sheet.max_row + 1):
doc = Document(doc_path)
for col in range(1, sheet.max_column + 1):
# 表头和数据
header = str(sheet.cell(row=1, column=col).value)
data = str(sheet.cell(row=row, column=col).value)
# 更新word文档
process_replace(doc, header, data)
# 批量保存,使用excel的第6列的【公司】作为word文档的后缀名称
column_name = str(sheet.cell(row=row, column=6).value)
doc.save(f'{base_path}{column_name}邀请函.docx')
测试如下:
if __name__ == '__main__':
base_path = "D:\\XXX\\test-word\\doc_invitation\\"
doc_path = base_path + "邀请函.docx"
excel_path = base_path + "邀请函的明细.xlsx"
process(doc_path, excel_path)
效果如下:
完美~~
有时候,我们可能比较关心 Word 文档里的某些关键词,如果搜索一篇几十页的文档的话,每次只能查找一个关键词,极不方便,有没有办法将我们关心的关键词列表在文档显著的标注出来呢?这样翻看的时候,既能抓住重点,也能避免漏掉关键信息的说明。
基于这种需求场景,接下来使用 Python 实现对 Word 文档的关键词进行批量标注。思路是,使用win32com 模块模拟打开 Word 文档的过程,并在此过程中对指定的关键词列表进行查找和样式标记,全部查找并标注完成后,调用另存为方法对新的 Word 文档保存。
首先,导入相关依赖:
import win32com.client
接着,开始编码实现,如下:
def tag_word(wordPath, newWordPath,keywordList):
# 打开office窗口,并设置隐藏(后台运行),之后就可以打开Word文档了
app = win32com.client.gencache.EnsureDispatch('Word.Application')
app.Visible = False
word = app.Documents.Open(wordPath)
# 设置样式
constants = win32com.client.constants
colorList = [constants.wdRed, constants.wdYellow, constants.wdBlue, constants.wdGreen]
process_style(app, constants, keywordList, colorList)
# 另存为新Word文档
word.SaveAs(newWordPath)
# 关闭
word.Close()
app.Quit()
在设置样式时,可自定义设置要标注的样式,如下:
def process_style(app, constants, keywordList, colorList):
if len(keywordList) > 0 and len(colorList) and len(keywordList) == len(colorList):
for keyword, color in zip(keywordList, colorList):
app.Options.DefaultHighlightColorIndex = color
obj = app.Selection.Find
obj.ClearFormatting()
obj.Text = keyword
obj.Replacement.ClearFormatting()
obj.Replacement.Text = keyword
obj.Replacement.Font.Bold = True #设置加粗
obj.Replacement.Font.Italic = True #设置斜体
obj.Replacement.Font.Underline = constants.wdUnderlineDouble #设置下划线
obj.Replacement.Highlight = True #高亮显示
obj.Execute(Replace=constants.wdReplaceAll)
然后,就可以测试了,测试代码如下:
if __name__ == '__main__':
basePath = 'D:\\XXX\\test-word\\doc_tag\\'
wordPath = basePath + '公司考勤制度(参考).docx'
newWordPath = basePath + '关键词批量标注_公司考勤制度(参考).docx'
keywordList = ['旷工', '迟到', '早退', '加班']
tag_word(wordPath, newWordPath, keywordList)
在网上搜索了一篇关于考勤制度的 Word 文档说明,有几十页之多,说实话每个人可能不会去耐心看完的!而我比较关心'旷工', '迟到', '早退', '加班'等关键词信息,这里通过批量标注,来选择性的阅读。测试效果,如下:
打开【关键词批量标注_公司考勤制度(参考).docx】,看一下:
以后阅读这种长篇的 Word 文档,通过批量标注的方式就可以提升效率了~~
有了批量标注 Word 文档关键词的思路之后,实现批量替换/删除就很简单了,其实就是将 colorList 里颜色常量,修改成替换后的关键词,如下:
replaceList = ["KG", "CD", "ZT", "JB"]
样式设置的话,略做修改:
def process_replace(app, constants, keywordList, replaceList):
if len(keywordList) > 0 and len(replaceList) and len(keywordList) == len(replaceList):
for old_kw, replace_kw in zip(keywordList, replaceList):
obj = app.Selection.Find
obj.ClearFormatting()
obj.Text = old_kw #原关键词
obj.Replacement.ClearFormatting()
obj.Replacement.Text = replace_kw #替换后的关键词
obj.Replacement.Font.Bold = True
obj.Replacement.Font.Italic = True
obj.Replacement.Font.Underline = constants.wdUnderlineDouble
obj.Replacement.Highlight = True
obj.Execute(Replace=constants.wdReplaceAll)
仍以考勤制度的 Word 文档为例:
打开【关键词批量替换_公司考勤制度(参考).docx】,效果如下:
效果看上去还不错,如果批量删除的话,就更简单了,把 colorList 都用空字符串填充即可。
这里,使用 win32com 模块,通过 SaveAs("输出路径", 2) 核心 API 即可实现 Word 转 txt。思路是 模拟打开 Word 文档,并另存为... 的操作过程。实现如下:
import win32com.client
def doc2txt(wordPath, txtPath):
# 打开office,再打开word
app = win32com.client.Dispatch('Word.Application')
word = app.Documents.Open(wordPath)
# 转储到其他文件:2为txt,空为原格式
word.SaveAs(txtPath, 2)
print("文件转储成功!!!")
# 关闭连接
word.Close()
app.Quit()
转换效果,如下:
需要注意,如果 Word 文档含有图片、表格、图表等特殊区域元素的话,这些是不会被转储到 txt 文件的!!
批量将 Word 文档转换成 PDF 文件,在之前的文章详细说明过,可以参考 4、【办公自动化】Python实现Word转PDF ,这里不再赘述了。
有时候,我们可能还会遇到将 Word 文档内容直接贴出来,而不是发送 Word 文档。比如,写博客文章时贴图,又比如 PPT 引用图片等场景。这样的话,靠截图可以简单实现,如果 Word 文档页数很多,一张张截图未免太麻烦了,这时候将 Word 文档转换成图片才是明智之举。
如何将 Word 文档转换成图片呢?有个可行的思路,如下:
第一步,就是 4.2 描述的场景,第二步在上篇的【提取PDF文件的内容】的【提取图片】有说明过,这些都是验证过并现成的,不再赘述了。
这里,重点实现下图片格式转换器,前面都是默认的 .png 格式,如果转成其他格式,可以自定义实现,如下:
from pathlib import Path
from PIL import Image
src_format = input("请输入要转换的图片格式: ")
desc_format = input("请输入转换后的图片格式: ")
path = input('请输入要转换的图片所在的路径:')
# 输出路径
desc_dir = Path(path + "convert\\")
# 自定义转换
for i in list(Path(path).glob(f"*.{src_format}")):
desc_file = (desc_dir / i.name).with_suffix(f".{desc_format}")
Image.open(i).save(desc_file)
print(f'{i.name} 已转换成{desc_format}')
测试用的图片默认的是 .jpg,需要转换成 .png 或 .bmp 格式,转换后的效果,如下:
经过这三步,就可以轻松实现 Word 转换成图片的需求了,so easy啊!