夜雨聆风学习资料网

ARTICLE · 1195305

python-批量把 Word 转成 PDF:有 Word 用 Word,只有 WPS 也能跑

python-批量把 Word 转成 PDF:有 Word 用 Word,只有 WPS 也能跑

在日常办公中,批量把 Word 文档转成 PDF 是非常高频的需求。合同、标书、报告、简历、制度文件、验收材料,最后往往都要统一转成 PDF,方便归档、打印和分发。

如果只有几个文件,手动打开 Word 或 WPS,点“另存为 PDF”还能接受。但一旦遇到几十个甚至上百个文档,手动操作不仅慢,还容易漏文件、覆盖文件,甚至因为排版差异导致导出结果不一致。

今天这篇文章就来一起学习和探讨:用 Python 调用本地办公软件的导出能力,批量把 .doc、.docx 转成 PDF。

方案选择

在 Python 中将 Word 转换为 PDF,主要有 4 种主流方案:

  1. docx2pdf:使用 Windows/macOS,依赖系统的 Word 能力,如 Microsoft Word 或者 LibreOffice,转换质量高;
  2. pywin32/comtypes:调用 COM 接口,转换质量高;
  3. LibreOffice 命令行(或 subprocess 调用),支持 Linux 服务器,跨平台,质量中等;
  4. 商业库(如 Aspose.Words、GroupDocs):付费,无外部依赖,质量高。

为什么推荐“调用本地 Word / WPS”?

Python 处理 Word 文档时,很多人第一反应是 python-docx。但它主要适合读取、修改文档内容,并不能直接生成高质量 PDF。如果希望 PDF 的排版、表格、页眉页脚、字体、分页都尽量还原,最稳妥的办法仍然是调用本地办公软件自身的导出引擎。同时,对于一般的办公场景下,多数都会安装 Microsoft Word 或者 WPS:

  • 装了 Microsoft Word:调用 Word.Application
  • 只装了 WPS Office:调用 Kwps.Application
  • 两者都装:优先使用 Word,失败再降级到 WPS

这种方式本质上是让 Python 替我们完成“打开文档 → 另存为 PDF → 关闭文档”的重复动作,所以保真度通常比纯解析方案更高。

环境准备

运行脚本前,需要满足以下条件:

  • 操作系统为 Windows
  • 已安装 Microsoft Word 或 WPS Office
  • Python 已安装 pywin32 安装依赖:
pip install pywin32

注意事项:

  • 如果电脑只装了 WPS,建议使用较新版本;部分精简版可能未正确注册 COM 组件。
  • 脚本运行时尽量不要手动打开大量 Word/WPS 文档,避免文件占用冲突。
  • 如果 WPS 启动失败,可以尝试确认 WPS 是否正常安装,或重新安装完整版 WPS。

完整代码:

自动识别 Word / WPS,下面这份脚本可以同时处理单个文件、整个文件夹,并自动判断当前环境可用的文档引擎。 

import globimport osfrom pathlib import Pathfrom win32com.client import DispatchExdef detect_engine():    """    自动检测当前环境可用的文档引擎:    优先 Microsoft Word,其次 WPS。    """    try:        app = DispatchEx("Word.Application")        app.Quit()        return "word"    except Exception as ex:        print(f"检测 Word 引擎时出错:{ex}")        pass    try:        app = DispatchEx("Kwps.Application")        app.Quit()        return "wps"    except Exception as ex:        print(f"检测 WPS 引擎时出错:{ex}")        return Nonedef word_to_pdf(input_path, output_path=None, engine=None):    """    将单个 Word 文档或指定文件夹下的所有 Word 文档转换为 PDF。    :param input_path: Word 文件路径或文件夹路径    :param output_path: 输出 PDF 的文件夹路径,默认输出到原文件同级目录    :param engine: 指定引擎,可选 "word" / "wps",为 None 时自动检测    """    if engine is None:        engine = detect_engine()    if engine == "word":        prog_id = "Word.Application"    elif engine == "wps":        prog_id = "Kwps.Application"    else:        print("未检测到可用的 Microsoft Word 或 WPS,请确认已安装办公软件。")        return    try:        if os.path.isfile(input_path):            files = [input_path]        elif os.path.isdir(input_path):            files = glob.glob(os.path.join(input_path, "*.docx")) + glob.glob(                os.path.join(input_path, "*.doc")            )        else:            print("输入路径无效!")            return        # 去重并保持顺序        files = list(dict.fromkeys(files))        if not files:            print("未找到 Word 文档!")            return        if output_path is None:            output_dir = (                os.path.dirname(input_path)                if os.path.isfile(input_path)                else input_path            )        else:            output_dir = output_path            Path(output_dir).mkdir(parents=True, exist_ok=True)        print(f"当前引擎:{engine}")        print(f"开始转换,共 {len(files)} 个文件 ...")        success = 0        fail = 0        for file in files:            file_name = os.path.basename(file)            name_without_ext = Path(file).stem            pdf_path = os.path.join(output_dir, f"{name_without_ext}.pdf")            app = None            doc = None            try:                # 为每个文件创建独立实例,避免关闭文档后复用失效的 COM 集合。                app = DispatchEx(prog_id)                app.Visible = False                app.DisplayAlerts = 0                doc = app.Documents.Open(                    file,                    ConfirmConversions=False,                    ReadOnly=True,                    AddToRecentFiles=False,                )                # 17 代表 PDF 格式                doc.ExportAsFixedFormat(pdf_path, 17)                success += 1                print(f"成功:{file_name} -> {os.path.basename(pdf_path)}")            except Exception as ex:                fail += 1                print(f"失败:{file_name},错误信息:{ex!r}")            finally:                app_closed = False                if app:                    try:                        app.Quit()                        app_closed = True                    except Exception as ex:                        print(f"关闭文档引擎时出错:{ex}")                if doc and not app_closed:                    try:                        doc.Close(SaveChanges=0)                    except Exception as ex:                        print(f"关闭文档时出错:{ex}")        print(f"转换结束:成功 {success} 个,失败 {fail} 个")    finally:        print("已关闭文档引擎。")if __name__ == "__main__":    # 示例:把当前文件夹下的所有 Word 文档转成 PDF    word_to_pdf(r"D:\Test\test_py\words")

代码关键点解析:

  1. 自动识别 Word / WPSdetect_engine() 会先尝试启动 Word.Application,失败后再尝试 Kwps.Application。这样同一份脚本在装了 Word、只装 WPS,或两者都装的电脑上都能运行。
  2. WPS 的核心区别 Microsoft Word 使用:
    Dispatch("Word.Application")

    WPS 文字使用:

    Dispatch("Kwps.Application")

    如果只安装 WPS,把引擎切换成 Kwps.Application 即可。

  3. 注意资源的释放:在使用COM场景下,资源释放是一个长久以来都需要注意的问题。

FileFormat=17 的含义:

17 是 PDF 格式常量,表示把文档保存为 PDF。这个参数在 Word 和 WPS 的 COM 接口中通常都可以使用。

资源释放很重要

COM 自动化会启动真实的 Word/WPS 进程。脚本结束后必须调用 Quit(),否则后台可能残留 WINWORD.EXE 或 wps.exe 进程。

文件去重与路径处理

脚本同时匹配 .doc 和 .docx,并通过 dict.fromkeys 去重。输出目录不存在时会自动创建,避免手动新建文件夹。

常见问题排查

问题
可能原因
解决办法
提示找不到 Kwps.Application
WPS 未安装、版本过旧或 COM 未注册
安装/重装完整版 WPS,重启电脑后再试
转换后 PDF 排版异常
字体缺失、版式复杂
在目标电脑安装文档所用字体
某个文件转换失败
文件损坏、被占用或路径异常
关闭占用程序,单独测试该文件
后台残留 Word/WPS 进程
未正确退出应用
使用 try/finally 确保 Quit() 执行
脚本运行后卡住
文档弹出“启用编辑”等弹窗
尽量使用本地文件,避免从压缩包、网盘直接打开

还可以怎么扩展

如果想继续增强,可以考虑:

  • 增加日志文件,记录每个文件的转换结果;
  • 支持按日期生成输出文件夹,避免覆盖旧文件;
  • 对失败文件自动重试一次;
  • 扩展支持 Excel、PPT 转 PDF;
  • 打包成 .exe,交给不会 Python 的同事直接使用。

小结

批量把 Word 转成 PDF,关键不是去解析文档内容,而是让本地办公软件替我们完成“另存为 PDF”。装了 Microsoft Word,就调用 Word.Application;只有 WPS,就调用 Kwps.Application。 对于经常处理合同、标书、报告、简历、制度文档的人来说,这种小工具非常实用。它不需要复杂依赖,也不需要上传到第三方平台,所有转换都在本地完成,既方便又安全。

如果你也想做一整套办公自动化脚本,比如批量加水印、合并 PDF、按文件名自动归档,可以在评论区说说你的场景。

相关学习资料