關於 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(下)