引言
在 python 生态中,操作 word 文档的库有不少,比如 python-docx 主要处理 .docx 格式,而 win32com(即 pywin32)则提供了更为底层的控制能力——它直接调用微软 office 的 com 接口,这意味着你的 word 软件能做什么,win32com 就能做什么。不仅可以读写文本,还能操作表格、图表、域代码、目录、格式转换,甚至执行查找替换等复杂任务。
不过,使用它也有一些前提和限制:
- 只能在 windows 系统上运行,并且必须已安装 microsoft word(wps 或其他打开 word 的软件不行)。
- 默认情况下,代码是单线程的。
- 操作完成后,务必记得关闭 word 客户端(
doc.close()和word.quit()),否则 word 进程会一直留在后台,需要手动从任务管理器结束。
win32com 其实是一个通用 com 客户端,不仅能操作 word,还能操作 excel、ppt、outlook 等微软软件。本文只聚焦于 word 的操作。
安装
pip install pywin32
如果遇到常数(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)。
基础概念
在深入代码之前,先了解几个核心对象:
| 对象 | 说明 |
|---|---|
application | word 应用程序本身,通过 win32.dispatch 获得 |
document | 代表一个打开的文档,通过 documents.add 或 documents.open 获取 |
selection | 当前光标选中的区域(或光标位置) |
range | 文档中的一个连续区域(可以不是选中状态) |
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 是一个独立区域,不依赖光标;selection 则代表当前光标位置,常用于模拟用户操作。
2. 打开文档,读取内容并追加文字
word = win32.dispatch("word.application")
word.visible = false
doc = word.documents.open(r"d:\your_path\test.docx")
# 遍历所有段落打印内容
for paragraph in doc.paragraphs:
print(paragraph.range.text)
# 在文档末尾追加内容
doc.content.insertafter("\n这是新增的内容")
doc.close()
word.quit()
注意:直接使用 doc.content.text 获取全文有时会返回异常结果(如只得到这是第二行, world!),所以推荐遍历段落。
3. 设置字体与段落格式
误区:使用 selection 设置字体无效
selection = word.selection # 字体设置无效 selection.font.name = "微软雅黑" selection.font.size = 16 selection.font.bold = true selection.font.colorindex = 6 # 红色 # 段落设置有效 selection.paragraphformat.alignment = 1 # 居中(0左 1中 2右 3两端) selection.paragraphformat.linespacingrule = 0 # 单倍行距
原因:selection 只是一个点,设置字体需要作用于一个区域。
正确方法:使用 range 设置整个文档
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
设置标题样式
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 = "结果" 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 表示全部替换
处理缓存异常问题
缓存异常的显著表现是无法导入 constants ,同时查找和替换功能也会出现异常。可以显式设置所有参数来解决问题:
wd_find_continue = 1 # 继续查找
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 转 pdf 及 doc/docx 互转
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 },实现自动编号。
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,不循环
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. 复杂实例:带章节号的图标签(如 图 1-1、图 1-2)
原始文档:包含“图 1-1”、“图 1-2”等纯文本
目标:替换为 图 { styleref 1 \s }-{ seq 图 \* arabic \s 1 },其中章节号来自标题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()
关键点:
- 使用 duplicate 复制 range,避免原对象被后续操作改变。
- 插入域后需要先更新域(update()),然后选中它再折叠,才能准确定位到域之后的位置。
- 这些技巧在插入复杂域时非常重要。
总结
win32com 是操作 word 的强大工具,几乎可以实现 vba 能做的所有事情。本文涵盖了从新建文档、格式设置、表格、查找替换、图片、目录、格式转换到域代码操作等常见需求。虽然它有平台限制(仅 windows + 已安装word软件),但对于需要深度控制 word 文档的自动化任务来说,它是不可或缺的利器。
以上就是python通过win32com库操作word的详细教程的详细内容,更多关于python win32com库操作word的资料请关注代码网其它相关文章!
发表评论