关于 Word 文档的读写,前面两篇文章分别进行了一次全面的总结html
最全总结 | 聊聊 Python 办公自动化之 Word(上)python
最全总结 | 聊聊 Python 办公自动化之 Word(中)微信
本篇文章做为一个办公自动化 Word 篇的一个补充,写写几个比较实用的办公场景app
包含:composer
页眉页脚处理less
合并多个文档函数
新增数字索引字体
doc 批量转 docxui
对比文档差别性this
特别内容标注
替换文字内容
每个页面章节都包含:页眉页脚
它能够单独设置,每一个页面都不同;也能够所有设置成与首页同样
这个功能,由章节对象中的属性 different_first_page_header_footer 来控制
当值为 True 时,表明页眉页脚不一样于首页,每一个页面章节的页眉、页脚均可以单独设置
当值为 False 时,全部页面的页眉、页脚都同样
# 一、获取待处理页眉、页脚的章节 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.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
平常工做中,常常会遇到将多个 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)
咱们常常须要在文档页脚处添加页面数字索引,惋惜 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 属性值便可
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))
两个 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)
咱们常常须要对文档中部分重要内容进行特别标注
好比,咱们须要对文档中包含「 微信 」的文字块或单元格,标为红色并加粗显示
1 - 段落内容
只须要遍历出段落中全部文字块 Run,直接修改文字块的 Font 属性便可
doc = Document(file) # 关键字的文字块或单元格标红,并加粗 # 一、修改段落中包含关键字的文件块的样式 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
有时候,咱们须要将文档中某个关键字所有替换成一个新的内容
这时候,咱们能够遍历全部段落和表格,使用 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')
到此,Python 自动化 Word 篇的内容所有结束了!
若是实际工做中,有一些其余的业务场景文中没有覆盖到,能够在文末进行留言,后面办公自动化实战篇可能会提供对应的解决方案!
要获取所有源码,关注公众号「 AirPython 」,后台回复「 word 」便可得到所有源码
若是你以为文章还不错,请你们 点赞、分享、留言下,由于这将是我持续输出更多优质文章的最强动力!
推荐阅读
最全总结 | 聊聊 Python 办公自动化之 Excel(上)
最全总结 | 聊聊 Python 办公自动化之 Excel(中)
最全总结 | 聊聊 Python 办公自动化之 Excel(下)