1. 前言

关于 Word 文档的读写,前面两篇文章分别进行了一次全面的总结

最全总结 | 聊聊 Python 办公自动化之 Word(上)

最全总结 | 聊聊 Python 办公自动化之 Word(中)

本篇文章作为一个办公自动化 Word 篇的一个补充,写写几个比较实用的办公场景

包含:

  • 页眉页脚处理

  • 合并多个文档

  • 新增数字索引

  • doc 批量转 docx

  • 对比文档差异性

  • 特别内容标注

  • 替换文字内容

2. 页眉页脚

每一个页面章节都包含:页眉页脚

它可以单独设置,每个页面都不一样;也可以全部设置成与首页一样

这个功能,由章节对象中的属性 different_first_page_header_footer 来控制

  • 当值为 True 时,代表页眉页脚不同于首页,每个页面章节的页眉、页脚都可以单独设置

  • 当值为 False 时,所有页面的页眉、页脚都一样

# 1、获取待处理页眉、页脚的章节
header = self.doc.sections[0].header
footer = self.doc.sections[0].footer # True if this section displays a distinct first-page header and footer
# True:页眉页脚不同于首页,每个页面章节的页眉页脚单独设置
# False:每个页面的页眉页脚相同
self.doc.sections[0].different_first_page_header_footer = True

添加页眉页脚包含两种,分别是:普通页眉页脚、自定义样式的页眉页脚

1 - 普通页眉页脚

def add_norm_header_and_footer(header, footer, header_content, footer_content):
"""
增加一个普通的页眉、页脚,并居中显示
:param header_content:
:param footer_content:
:return:
"""
# 新增/修改页眉、页脚
# 注意:一般页眉、页脚里只有一个段落
header.paragraphs[0].text = header_content
footer.paragraphs[0].text = footer_content # 居中显示
header.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 2、新增页眉
# 2.1 普通的页眉、页脚
add_norm_header_and_footer(header, footer, "我是一个页眉", "我是一个页脚")
2 - 自带样式的页眉页脚

2 - 自带样式的页眉页脚

def add_custom_style_header_and_footer(header, footer, header_content, footer_content, style):
"""
新增自定义的页眉、页脚
:param header:
:param footer:
:param header_content:
:param footer_content:
:param style:
:return:
"""
# 注意:style_type=2,否则会报错
header.paragraphs[0].add_run(header_content, style)
footer.paragraphs[0].add_run(footer_content, style) # 2.2 自带样式的页眉、页脚
# 创建一个样式
style_paragraph = create_style(document=self.doc, style_name="style5", style_type=2, font_size=30,
font_color=[0xff, 0x00, 0x00], align=WD_PARAGRAPH_ALIGNMENT.CENTER)
add_custom_style_header_and_footer(header, footer, "我是页眉2", "我是页脚2", style_paragraph)

如果想将文档中所有的页眉、页脚删除掉,只需要 2 个步骤:

  • 遍历文档中所有页面章节,将其 different_first_page_header_footer 属性值设置为 False

  • 设置章节对象页眉页脚的 is_linked_to_previous 属性值为 True

    PS:当 is_linked_to_previous 设置为 True 时,页眉页脚会被删除

def remove_all_header_and_footer(doc):
"""
删除文档中所有页眉和页脚
:param doc:
:return:
"""
for section in doc.sections:
section.different_first_page_header_footer = False
# 当is_linked_to_previous设置为True时,页眉页脚会被删除
section.header.is_linked_to_previous = True
section.footer.is_linked_to_previous = True

3. 合并多个文档

日常工作中,经常会遇到将多个 Word 文档合并成一个文件的需求

这里,可以使用另外一个 Python 依赖库:docxcompose

# 合并多个文件的依赖库
pip3 install docxcompose

使用也非常简单,只需要下面 4 行代码,就能将多个文件进行合并,生成到一个新的文件中去

from docxcompose.composer import Composer

def compose_files(self, files, output_file_path):
"""
合并多个word文件到一个文件中
:param files:待合并文件的列表
:param output_file_path 新的文件路径
:return:
"""
composer = Composer(Document())
for file in files:
composer.append(Document(file)) # 保存到新的文件中
composer.save(output_file_path)

4. 新增数字索引

我们经常需要在文档页脚处添加页面数字索引,可惜 python-docx 并没有提供现有方法

但是,在 stackoverflow 上找到实现的方式

https://stackoverflow.com/questions/56658872/add-page-number-using-python-docx?rq=1

from docx.oxml.xmlchemy import BaseOxmlElement, ZeroOrOne, ZeroOrMore, OxmlElement
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml import ns def create_element(self, name):
return OxmlElement(name) def create_attribute(self, element, name, value):
element.set(ns.qn(name), value) def add_page_number(self, run):
"""
添加页面索引
:param run:
:return:
"""
fldChar1 = self.create_element('w:fldChar')
self.create_attribute(fldChar1, 'w:fldCharType', 'begin') instrText = self.create_element('w:instrText')
self.create_attribute(instrText, 'xml:space', 'preserve')
instrText.text = "PAGE" fldChar2 = self.create_element('w:fldChar')
self.create_attribute(fldChar2, 'w:fldCharType', 'end') # run._r:class 'docx.oxml.text.run.CT_R'>
run._r.append(fldChar1)
run._r.append(instrText)
run._r.append(fldChar2)

默认生成的数字索引在页脚左下角,并不美观!

因此,这里我们可以使用 第一篇文章 的方法创建一个「文字块样式」,然后以文字块 Run 的形式,添加到页脚的第一个段落中去

# 注意:要设置页眉页脚的对齐方式,必须设置到段落上(文字块不能添加对齐方式)
doc.sections[0].footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 创建一个文字块样式,指定字体名称、大小、颜色
style = create_style(document=doc, style_name="style", style_type=2, font_size=10,
font_color=[0x00, 0x00, 0x00], font_name="黑体")
self.add_page_number(doc.sections[0].footer.paragraphs[0].add_run("", style))
doc.save("./output.docx")
print('添加页码索引成功!')

需要注意的,如果需要设置页面数字索引的对齐方式,必须针对页脚的段落进行设置,修改其 alignment 属性值即可

5. doc 转 docx

python-docx 对 doc 格式的文档不太友好,要处理这类文档,我们需要先将它转换为 docx 格式

对于 Windows 系统,完全可以使用 win32com 这个模块,用命令去调用 Word 应用,打开源文件后,保存了 docx 格式的文件即可

from win32com import client

def doc_to_docx_in_win(path_raw, path_output):
​ """
doc转为docx(win)
:param path_original:
:param path_final:
:return:
"""
# 获取文件的格式后缀
file_suffix = os.path.splitext(path_raw)[1]
if file_suffix == ".doc":
word = client.Dispatch('Word.Application')
# 源文件
doc = word.Documents.Open(path_raw)
# 生成的新文件
doc.SaveAs(path_output, 16)
doc.Close()
word.Quit()
elif file_suffix == ".docx":
shutil.copy(path_raw, path_output)

而对于 Mac/Linux,推荐使用 LibreOffice 去转换文档格式

# 转换格式
./soffice --headless --convert-to docx 源文件.doc --outdir /output/path/

PS:LibreOffice 是一款由社区创造的自由免费办公套件,跨平台,内置的 soffice 可以用于文件转换

以 Mac OS 为例,我们按下面步骤来操作

  • 官网下载 LibreOffice 软件并安装

  • 找到 LibreOffice 软件安装目录,将 soffice 命令所在目录配置到环境变量中

  • 重启 Pycharm

  • 使用 os 模块下的 walk() 函数遍历所有源文件,组成一条 soffice 转换命令

  • 执行转换命令

import os

source = "./doc/"
dest = "./docx/"
g = os.walk(source) # 遍历文件夹
for root, dirs, files in g:
for file in files:
# 源文件完整路径
file_path_raw = os.path.join(root, file)
print(file_path_raw) os.system("soffice --headless --convert-to docx {} --outdir {}".format(file_path_raw, dest))

6. 对比文档差异性

两个 Word 文档的对比也是工作中比较常见的需求了

首先,遍历文档中所有段落,过滤掉空行,获取所有文本内容

# 分别获取段落内容
content1 = ''
content2 = ''
for paragraph in file1.paragraphs:
​ if "" == paragraph.text.strip():
continue
content1 += paragraph.text + '\n' for paragraph in file2.paragraphs:
if "" == paragraph.text.strip():
continue
content2 += paragraph.text + '\n' # 如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。
print("第二个文档数据如下:\n", content1.splitlines(keepends=False))
print("第一个文档数据如下:\n", content1.splitlines(keepends=False))

接着,使用 Python 中的标准依赖库 difflib 对比文字间的差异,最后生成 HTML 差异报告

import codecs
from difflib import HtmlDiff # 差异内容
diff_html = HtmlDiff(wrapcolumn=100).make_file(content1.split("\n"), content2.split("\n")) # 写入到文件中
with codecs.open('./diff_result.html', 'w', encoding='utf-8') as f:
f.write(diff_html)

7. 特别内容标注

我们经常需要对文档中部分重要内容进行特别标注

比如,我们需要对文档中包含「 微信 」的文字块或单元格,标为红色并加粗显示

1 - 段落内容

只需要遍历出段落中所有文字块 Run,直接修改文字块的 Font 属性即可

doc = Document(file)

# 关键字的文字块或单元格标红,并加粗
# 1、修改段落中包含关键字的文件块的样式
for paragraph in doc.paragraphs:
for run in paragraph.runs:
if keyword in run.text:
# 修改颜色为红色,并加粗显示
run.font.bold = True
run.font.color.rgb = RGBColor(255, 0, 0)

2 - 表格内容

设置满足条件的单元格样式有点特别,需要经过下面 4 个步骤

  • 获取单元格对象,获取单元格文本内容,并临时保存

  • 清空单元格数据

  • 单元格对象追加一个段落和一个文字块 Run,返回一个文字块对象

  • 设置文字块对象样式,标红并加粗

tables = [table for table in doc.tables]
for table in tables:
for row in table.rows:
for cell in row.cells:
if keyword in cell.text:
# 原内容
content_raw = cell.text
# 清空单元格数据
cell.text = ""
# 追加数据进去,并设置样式
run = cell.paragraphs[0].add_run(content_raw)
run.font.color.rgb = RGBColor(255, 0, 0)
run.font.bold = True

8. 替换文字内容

有时候,我们需要将文档中某个关键字全部替换成一个新的内容

这时候,我们可以遍历所有段落和表格,使用 replace() 函数对段落文本和单元格内容进行替换

def replace_content(self, old_content, new_content):
​ """
替换文档中所有内容
:param old_content:旧的内容
:param new_content:新的内容
:return:
"""
# 替换段落
for paragraph in self.doc.paragraphs:
if old_content in paragraph.text:
# 替换内容后,重新设置进去
paragraph.text = paragraph.text.replace(old_content, new_content) # 替换表格
# document.tables[表格索引].rows[行索引].cells[单元格列索引].text = “新的数据”。
tables = [table for table in self.doc.tables]
for table in tables:
for row in table.rows:
for cell in row.cells:
if old_content in cell.text:
# 重新设置单元格内容
cell.text = cell.text.replace(old_content, new_content) # 保存到一个新的文件中
self.doc.save('./new.docx')

9. 最后

到此,Python 自动化 Word 篇的内容全部结束了!

如果实际工作中,有一些其他的业务场景文中没有覆盖到,可以在文末进行留言,后面办公自动化实战篇可能会提供对应的解决方案!

要获取全部源码,关注公众号「 AirPython 」,后台回复「 word 」即可获得全部源码

如果你觉得文章还不错,请大家 点赞、分享、留言下,因为这将是我持续输出更多优质文章的最强动力!

推荐阅读

最全总结 | 聊聊 Python 办公自动化之 Excel(上)

最全总结 | 聊聊 Python 办公自动化之 Excel(中)

最全总结 | 聊聊 Python 办公自动化之 Excel(下)

最全总结 | 聊聊 Python 办公自动化之 Word(上)

最全总结 | 聊聊 Python 办公自动化之 Word(中)

最全总结 | 聊聊 Python 办公自动化之 Word(下)的更多相关文章

  1. 最全总结 | 聊聊 Python 办公自动化之 Word(中)

    1. 前言 上一篇文章,对 Word 写入数据的一些常见操作进行了总结 最全总结 | 聊聊 Python 办公自动化之 Word(上) 相比写入数据,读取数据同样很实用! 本篇文章,将谈谈如何全面读取 ...

  2. 最全总结 | 聊聊 Python 办公自动化之 Word(上)

    1. 前言 日常自动化办公中,使用 Python 真的能做到事半功倍! 在上一个系列中,我们对 Python 操作 Excel 进行了一次全面总结 最全总结 | 聊聊 Python 办公自动化之 Ex ...

  3. 最全总结 | 聊聊 Python 办公自动化之 PDF(上)

    1. 前言 自动化办公,非 Python 莫属! 从本篇文章开始,我们继续聊聊自动化办公中另外一个常用系列:PPT 2. 准备一下 Python 操作 PPT 最强大的依赖库是:python-pptx ...

  4. 最全总结 | 聊聊 Python 办公自动化之 PPT(中)

    1. 前言 上一篇文章简单地介绍了 PPT 的文档结构,并使用 python-pptx 这个依赖库完成对 PPT 文档最基本的操作 最全总结 | 聊聊 Python 办公自动化之 PPT(上) 作为 ...

  5. 最全总结 | 聊聊 Python 办公自动化之 Excel(中)

    1. 前言 上一篇文章中,我们聊到使用 xlrd.xlwt.xlutils 这一组合操作 Excel 的方法 最全总结 | 聊聊 Python 办公自动化之 Excel(上) ​本篇文章将继续聊另外一 ...

  6. 最全总结 | 聊聊 Python 办公自动化之 Excel(下)

    1. 前言 前面谈到 Python 处理 Excel 文件最常见的两种方式,即:xlrd/xlwt.openpyxl ​其中, xlrd/xlwt 这一组合,xlrd 可以负责读取数据,而 xlwt ...

  7. 最全总结 | 聊聊 Python 办公自动化之 Excel(上)

    1. 前言 在我们日常工作中,经常会使用 Word.Excel.PPT.PDF 等办公软件 但是,经常会遇到一些重复繁琐的事情,这时候手工操作显得效率极其低下:通过 Python 实现办公自动化变的很 ...

  8. 最全总结 | 聊聊 Python 数据处理全家桶(PgSQL篇)

    1. 前言 大家好,我是安果! Python 数据处理全家桶,截止到现在,一共写过 6 篇文章,有兴趣的小伙伴可以去了解一下! 最全总结 | 聊聊 Python 数据处理全家桶(Mysql 篇) 最全 ...

  9. 最全总结 | 聊聊 Python 数据处理全家桶(Mysql 篇)

    1. 前言 在爬虫.自动化.数据分析.软件测试.Web 等日常操作中,除 JSON.YAML.XML 外,还有一些数据经常会用到,比如:Mysql.Sqlite.Redis.MongoDB.Memch ...

随机推荐

  1. 【2】TensorFlow光速入门-数据预处理(得到数据集)

    本文地址:https://www.cnblogs.com/tujia/p/13862351.html 系列文章: [0]TensorFlow光速入门-序 [1]TensorFlow光速入门-tenso ...

  2. Hbase实用技巧:全量+增量数据的迁移方法

    摘要:本文介绍了一种Hbase迁移的方法,可以在一些特定场景下运用. 背景 在Hbase使用过程中,使用的Hbase集群经常会因为某些原因需要数据迁移.大多数情况下,可以跟用户协商用离线的方式进行迁移 ...

  3. Linux系统搭建Hadoop集群

    一.环境说明 IP地址 主机名 备注 操作系统 192.168.92.11 hserver1 namenode Ubuntu 16.04 192.168.92.12 hserver2 datanode ...

  4. 关于oracle监听程序的相关问题及解决方法

    1.查看监听程序是否启动 打开cmd窗口,cmd用管理员运行,否则无法执行启动与停止监听命令 lsnrctl status查看运行状态 lsnrctl stop停止监听 lsnrctl start启动 ...

  5. 深入探究ASP.NET Core Startup初始化

    前言 Startup类相信大家都比较熟悉,在我们使用ASP.NET Core开发过程中经常用到的类,我们通常使用它进行IOC服务注册,配置中间件信息等.虽然它不是必须的,但是将这些操作统一在Start ...

  6. 【译】Ringbahn的两个内存Bug

    原文链接:https://without.boats/blog/two-memory-bugs-from-ringbahn/ 原文标题:Two Memory Bugs From Ringbahn 公众 ...

  7. GDB调试基础使用方法

    尽管目前使用的VS code可以使用插件一键构建和运行程序,但GDB作为调试利器,还是值得花时间去学习的. 概述 GDB(GNU Debugger) 是一个由GNU开源组织发布的.UNIX/LINUX ...

  8. How to using expression setup BackgroundColor AX2012 SSRS Report[AX2012]

    tile label using [#99ccff] property BackgroundColor - > expression =Iif(Fields!Flag.Value = " ...

  9. 重温Java泛型,带你更深入地理解它,更好的使用它!

    1. 引言 jdk5.0中引入了Java泛型,目的是减少错误,并在类型上添加额外的抽象层. 本文将简要介绍Java中的泛型.泛型背后的目标以及如何使用泛型来提高代码的质量. 2. 为什么要用泛型? 设 ...

  10. 使用arm-none-eabi-gdb报错error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory

    使用arm-none-eabi-gdb报错error while loading shared libraries: libncurses.so.5: cannot open shared objec ...