9、【办公自动化】Python实现Word文件的批量操作

时间:2022-11-06 15:57:29

说明

上一篇介绍了【Python 实现 PDF 文件的批量操作】,这篇将介绍通过 Python 实现 Word 文档的批量操作。Word 作为日常办公重要且常用的文档之一,经常也会遇到一些繁琐的操作场景,比如批量生成某一类型的 Word 文档,批量对 Word 文档的关键字进行标注、替换或者删除,批量将 Word 文档转换成其他格式的文件等。为了提升工作的效率,通过 Python 解决这些场景的方式,有必要了解下。

Word 文件的后缀有.doc 和 .docx 格式,以下模块支持 word 文档的读写:

  • python-docx:只支持.docx 格式,但可以将 .doc 转成 .docx 格式,从而间接支持 .doc 格式;
  • pywin32:调用系统的word功能,可以同时支持.doc 和 .docx 格式;

接下来,使用会涉及到这两个模块的使用,可以通过 pip 命令先下载这些模块,

pip install python-docx
pip install pywin32

需要注意,python-docx 模块在 import 时,名称是 docx;pywin32 模块在导入时,名称是win32com。

1、批量生成Word文档

我们知道,在平时办公中,如果使用 Word 文档的 "邮件合并" 功能,可以批量制作一些主要内容相同、只是部分数据不一样的文档,比如邀请函、通知单、采购合同、成绩单等。Python 也可以实现类似的功能,通过套用指定的模板批量生成 Word 文档。

以邀请函的批量制作为例,首先准备一份模板,内容如下:

9、【办公自动化】Python实现Word文件的批量操作

邀请函中需要替换的字段都用 英文单词 标记,而填充到模板中的具体信息,可以放在 Excel 表格保存,需要注意的是,Excel 表格各列的标题必须与模板中的字段名保持一致,如下:

9、【办公自动化】Python实现Word文件的批量操作

代码实现的思路也比较简单:从 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)

效果如下:

9、【办公自动化】Python实现Word文件的批量操作 打开其中的一个 Word 文档,验证替换效果,如下:

9、【办公自动化】Python实现Word文件的批量操作

完美~~

2、批量操作Wor文档的关键词

2.1 批量标注关键词

有时候,我们可能比较关心 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 文档说明,有几十页之多,说实话每个人可能不会去耐心看完的!而我比较关心'旷工', '迟到', '早退', '加班'等关键词信息,这里通过批量标注,来选择性的阅读。测试效果,如下:

9、【办公自动化】Python实现Word文件的批量操作

打开【关键词批量标注_公司考勤制度(参考).docx】,看一下:

9、【办公自动化】Python实现Word文件的批量操作

以后阅读这种长篇的 Word 文档,通过批量标注的方式就可以提升效率了~~

2.2 批量替换/删除关键词

有了批量标注 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 文档为例:

9、【办公自动化】Python实现Word文件的批量操作

 打开【关键词批量替换_公司考勤制度(参考).docx】,效果如下:

9、【办公自动化】Python实现Word文件的批量操作

效果看上去还不错,如果批量删除的话,就更简单了,把 colorList 都用空字符串填充即可。

3、批量将Word文件转成其他格式文件

3.1 Word 转 txt

这里,使用 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()

转换效果,如下:

9、【办公自动化】Python实现Word文件的批量操作

需要注意,如果 Word 文档含有图片、表格、图表等特殊区域元素的话,这些是不会被转储到 txt 文件的!!

3.2 Word 转 PDF

批量将 Word 文档转换成 PDF 文件,在之前的文章详细说明过,可以参考 4、【办公自动化】Python实现Word转PDF ,这里不再赘述了。

3.3 Word 转 图片

有时候,我们可能还会遇到将 Word 文档内容直接贴出来,而不是发送 Word 文档。比如,写博客文章时贴图,又比如 PPT 引用图片等场景。这样的话,靠截图可以简单实现,如果 Word 文档页数很多,一张张截图未免太麻烦了,这时候将 Word 文档转换成图片才是明智之举。

如何将 Word 文档转换成图片呢?有个可行的思路,如下:

  • 先将 Word 转换成 PDF;
  • 再利用 PDF 的 pdfplumber 模块的 to_inmage() 方法转换成图片;
  • 最后为了满足转换不同格式的图片,可编写个图片格式转换器。

第一步,就是 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 格式,转换后的效果,如下:

9、【办公自动化】Python实现Word文件的批量操作

 经过这三步,就可以轻松实现 Word 转换成图片的需求了,so easy啊!