当前位置: 代码网 > it编程>前端脚本>Python > Python通过win32com库操作Word的详细教程

Python通过win32com库操作Word的详细教程

2026年03月06日 Python 我要评论
引言在 python 生态中,操作 word 文档的库有不少,比如 python-docx 主要处理 .docx 格式,而 win32com(即 pywin32)则提供了更为底层的控制能力&mdash

引言

在 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)。

基础概念

在深入代码之前,先了解几个核心对象:

对象说明
applicationword 应用程序本身,通过 win32.dispatch 获得
document代表一个打开的文档,通过 documents.adddocuments.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的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com