Python通過win32com庫操作Word的詳細教程
引言
在 Python 生態(tài)中,操作 Word 文檔的庫有不少,比如 python-docx 主要處理 .docx 格式,而 win32com(即 pywin32)則提供了更為底層的控制能力——它直接調(diào)用微軟 Office 的 COM 接口,這意味著你的 Word 軟件能做什么,win32com 就能做什么。不僅可以讀寫文本,還能操作表格、圖表、域代碼、目錄、格式轉(zhuǎn)換,甚至執(zhí)行查找替換等復雜任務。
不過,使用它也有一些前提和限制:
- 只能在 Windows 系統(tǒng)上運行,并且必須已安裝 Microsoft Word(WPS 或其他打開 Word 的軟件不行)。
- 默認情況下,代碼是單線程的。
- 操作完成后,務必記得關(guān)閉 Word 客戶端(
doc.Close()和word.Quit()),否則 Word 進程會一直留在后臺,需要手動從任務管理器結(jié)束。
win32com 其實是一個通用 COM 客戶端,不僅能操作 Word,還能操作 Excel、PPT、Outlook 等微軟軟件。本文只聚焦于 Word 的操作。
安裝
pip install pywin32
如果遇到常數(shù)(constants)加載異常(例如無法使用 constants.wdReplaceAll),可以嘗試強制重新生成緩存:
import win32com.client as win32
word = win32.gencache.EnsureDispatch('Word.Application') # 替換win32.Dispatch()接口
或者手動刪除緩存文件夾(通常在 %temp%\gen_py 下,例如 C:\Users\用戶名\AppData\Local\Temp\gen_py)。
基礎(chǔ)概念
在深入代碼之前,先了解幾個核心對象:
| 對象 | 說明 |
|---|---|
Application | Word 應用程序本身,通過 win32.Dispatch 獲得 |
Document | 代表一個打開的文檔,通過 Documents.Add 或 Documents.Open 獲取 |
Selection | 當前光標選中的區(qū)域(或光標位置) |
Range | 文檔中的一個連續(xù)區(qū)域(可以不是選中狀態(tài)) |
Paragraph | 段落,由回車符分隔 |
Font / ParagraphFormat | 字體和段落格式 |
1. 新建文檔并寫入文字
使用 Range 對象
import win32com.client as win32
word = win32.Dispatch("Word.Application")
word.Visible = True # True 會顯示 Word 界面(但很快消失)
doc = word.Documents.Add()
range_obj = doc.Range(0, 0)
range_obj.InsertAfter("Hello World from Python!")
# 注意:必須使用絕對路徑,否則會保存到 Word 的默認文件夾
doc.SaveAs(r"D:\your_path\test.docx")
doc.Close()
word.Quit()
使用 Selection 對象(模擬光標)
word = win32.Dispatch("Word.Application")
word.Visible = False
doc = word.Documents.Add()
selection = word.Selection
selection.TypeText("Hello, World!")
selection.TypeParagraph() # 換行(新段落)
selection.TypeText("這是第二行")
doc.SaveAs(r"D:\your_path\test.docx")
doc.Close()
word.Quit()
注意:Range 是一個獨立區(qū)域,不依賴光標;Selection 則代表當前光標位置,常用于模擬用戶操作。
2. 打開文檔,讀取內(nèi)容并追加文字
word = win32.Dispatch("Word.Application")
word.Visible = False
doc = word.Documents.Open(r"D:\your_path\test.docx")
# 遍歷所有段落打印內(nèi)容
for paragraph in doc.Paragraphs:
print(paragraph.Range.Text)
# 在文檔末尾追加內(nèi)容
doc.Content.InsertAfter("\n這是新增的內(nèi)容")
doc.Close()
word.Quit()
注意:直接使用 doc.Content.Text 獲取全文有時會返回異常結(jié)果(如只得到這是第二行, World!),所以推薦遍歷段落。
3. 設(shè)置字體與段落格式
誤區(qū):使用 Selection 設(shè)置字體無效
selection = word.Selection # 字體設(shè)置無效 selection.Font.Name = "微軟雅黑" selection.Font.Size = 16 selection.Font.Bold = True selection.Font.ColorIndex = 6 # 紅色 # 段落設(shè)置有效 selection.ParagraphFormat.Alignment = 1 # 居中(0左 1中 2右 3兩端) selection.ParagraphFormat.LineSpacingRule = 0 # 單倍行距
原因:Selection 只是一個點,設(shè)置字體需要作用于一個區(qū)域。
正確方法:使用 Range 設(shè)置整個文檔
range_obj = doc.Content range_obj.Font.Name = "微軟雅黑" range_obj.Font.Size = 16 range_obj.Font.Bold = True range_obj.Font.ColorIndex = 6 range_obj.ParagraphFormat.Alignment = 1 range_obj.ParagraphFormat.LineSpacingRule = 0
設(shè)置標題樣式
range_obj = doc.Range(0, 0)
range_obj.Text = "第一章 概述"
range_obj.Style = doc.Styles("標題 1") # 英文版可能是 "Heading 1"
4. 插入表格
range_obj = doc.Content range_obj.Collapse(0) # 0 折疊到末尾,1 折疊到開頭 table = doc.Tables.Add(range_obj, NumRows=3, NumColumns=3) # 單元格索引從 1 開始 table.Cell(1,1).Range.Text = "姓名" table.Cell(1,2).Range.Text = "年齡" table.Cell(1,3).Range.Text = "結(jié)果" table.Cell(2,1).Range.Text = "張三" table.Cell(2,2).Range.Text = "25" table.Cell(2,3).Range.Text = "合格"
5. 查找與替換
簡單替換(全文匹配)
find = word.Selection.Find
find.Text = "{{name}}"
find.Replacement.Text = "張三"
find.Execute(Replace=2) # Replace=2 表示全部替換
處理緩存異常問題
緩存異常的顯著表現(xiàn)是無法導入 constants ,同時查找和替換功能也會出現(xiàn)異常??梢燥@式設(shè)置所有參數(shù)來解決問題:
WD_FIND_CONTINUE = 1 # 繼續(xù)查找
WD_REPLACE_ALL = 2 # 全部替換
rng = doc.Content
for old, new in [("{{name}}", "張三"), ("{{date}}", "2026-02-26")]:
rng.Find.Execute(
old, False, False, False, False, False,
True, WD_FIND_CONTINUE, False, new, WD_REPLACE_ALL
)
rng = doc.Content # 重新獲取 Range,避免被移動
6. 插入圖片
range_obj = doc.Content
range_obj.Collapse(0) # 移動到末尾
doc.InlineShapes.AddPicture(
r"D:\your_path\pic1.jpeg",
False, True, range_obj
)
7. 更新目錄
for toc in doc.TablesOfContents:
toc.Update()
8. Word 轉(zhuǎn) PDF 及 doc/docx 互轉(zhuǎn)
doc.ExportAsFixedFormat(
OutputFileName=r"D:\your_path\test.pdf",
ExportFormat=17 # 17 代表 PDF;16 代表 docx;0/1 代表 doc
)
9. 插入域代碼:以日期域為例
range_obj = doc.Content
range_obj.Collapse(0)
field = doc.Fields.Add(
Range=range_obj,
Type=31 # wdFieldDate
)
# 等價寫法(插入空域,再指定代碼)
# field = doc.Fields.Add(
# Range=range_obj,
# Type=constants.wdFieldEmpty,
# Text="DATE \\* MERGEFORMAT"
# )
10. 實例:將純文本圖標簽替換為 SEQ 域
原始文檔:包含“圖 1”、“圖 2”等純文本
目標:替換為域代碼 圖 { SEQ 圖 \* ARABIC },實現(xiàn)自動編號。
word = win32.gencache.EnsureDispatch('Word.Application')
word.Visible = False
doc = word.Documents.Open(r"D:\your_path\instance1.docx")
search_range = doc.Range()
search_range.Find.Text = "圖 [0-9]{1,}"
search_range.Find.Wrap = 0 # wdFindStop,不循環(huán)
search_range.Find.MatchWildcards = True # 通配符匹配
found = search_range.Find.Execute()
while found:
insert_point = search_range.Duplicate # 復制當前 Range
insert_point.Delete() # 刪除原文本
insert_point.InsertAfter("圖 ") # 插入“圖 ”
insert_point.Collapse(Direction=0) # 折疊到末尾
# 插入 SEQ 域
seq_code = 'SEQ 圖 \\* ARABIC'
doc.Fields.Add(insert_point, -1, seq_code, False) # -1 代表 wdFieldEmpty
search_range.Collapse(Direction=0)
found = search_range.Find.Execute()
doc.Fields.Update()
doc.SaveAs(r"D:\your_path\test.docx")
doc.Close()
word.Quit()
11. 復雜實例:帶章節(jié)號的圖標簽(如 圖 1-1、圖 1-2)
原始文檔:包含“圖 1-1”、“圖 1-2”等純文本
目標:替換為 圖 { STYLEREF 1 \s }-{ SEQ 圖 \* ARABIC \s 1 },其中章節(jié)號來自標題1(一級標題)的編號。
word = win32.Dispatch("Word.Application")
word.Visible = False
doc = word.Documents.Open(r"D:\your_path\instance2.docx")
search_range = doc.Range()
search_range.Find.Text = "圖 [0-9]{1,}-[0-9]{1,}"
search_range.Find.Wrap = constants.wdFindStop
search_range.Find.MatchWildcards = True
found = search_range.Find.Execute()
while found:
insert_point = search_range.Duplicate
insert_point.Delete()
insert_point.InsertAfter("圖 ")
insert_point.Collapse(Direction=constants.wdCollapseEnd)
# 插入 STYLEREF 域
styleref_code = 'STYLEREF 1 \\s'
field_styleref = doc.Fields.Add(insert_point, constants.wdFieldEmpty, styleref_code, False)
field_styleref.Update()
# 將光標移動到域之后
field_styleref.Select()
word.Selection.Collapse(Direction=constants.wdCollapseEnd)
insert_point = word.Selection.Range.Duplicate
# 插入連字符
insert_point.InsertAfter("-")
insert_point.Collapse(Direction=constants.wdCollapseEnd)
# 插入 SEQ 域
seq_code = 'SEQ 圖 \\* ARABIC \\s 1'
doc.Fields.Add(insert_point, constants.wdFieldEmpty, seq_code, False)
search_range.Collapse(Direction=constants.wdCollapseEnd)
found = search_range.Find.Execute()
doc.Fields.Update()
doc.SaveAs(r"D:\your_path\test.docx")
doc.Close()
word.Quit()
關(guān)鍵點:
- 使用 Duplicate 復制 Range,避免原對象被后續(xù)操作改變。
- 插入域后需要先更新域(Update()),然后選中它再折疊,才能準確定位到域之后的位置。
- 這些技巧在插入復雜域時非常重要。
總結(jié)
win32com 是操作 Word 的強大工具,幾乎可以實現(xiàn) VBA 能做的所有事情。本文涵蓋了從新建文檔、格式設(shè)置、表格、查找替換、圖片、目錄、格式轉(zhuǎn)換到域代碼操作等常見需求。雖然它有平臺限制(僅 Windows + 已安裝Word軟件),但對于需要深度控制 Word 文檔的自動化任務來說,它是不可或缺的利器。
以上就是Python通過win32com庫操作Word的詳細教程的詳細內(nèi)容,更多關(guān)于Python win32com庫操作Word的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python時間序列數(shù)據(jù)的預處理方法總結(jié)
這篇文章主要介紹了Python時間序列數(shù)據(jù)的預處理方法總結(jié),時間序列數(shù)據(jù)隨處可見,要進行時間序列分析,我們必須先對數(shù)據(jù)進行預處理。時間序列預處理技術(shù)對數(shù)據(jù)建模的準確性有重大影響2022-07-07
python爬蟲系列Selenium定向爬取虎撲籃球圖片詳解
這篇文章主要介紹了python爬蟲系列Selenium定向爬取虎撲籃球圖片詳解,具有一定參考價值,喜歡的朋友可以了解下。2017-11-11
Pandas對數(shù)值進行分箱操作的4種方法總結(jié)
分箱是一種常見的數(shù)據(jù)預處理技術(shù)有時也被稱為分桶或離散化,他可用于將連續(xù)數(shù)據(jù)的間隔分組到“箱”或“桶”中。本文將使用python?Pandas庫對數(shù)值進行分箱的4種方法,感興趣的可以了解一下2022-05-05
Python Flask實現(xiàn)多文件項目打包部署(Linux+Docker+Windows全環(huán)境)指南
針對多?.py?文件的 Flask 項目,本文在原有部署方案基礎(chǔ)上,補充多文件項目結(jié)構(gòu)規(guī)范、Windows 環(huán)境部署、跨平臺打包等核心內(nèi)容,有需要的小伙伴可以了解下2026-01-01
Python中實現(xiàn)遠程調(diào)用(RPC、RMI)簡單例子
說白了,遠程調(diào)用就是將對象名、函數(shù)名、參數(shù)等傳遞給遠程服務器,服務器將處理結(jié)果返回給客戶端2014-04-04

