ARTICLE · 1053747
VBA 别只会操作 Excel 了!合并、拆分 PDF 这两种方法,一个比一个狠
用 VBA 把零散的 PDF 合并成一份,或者把一个多页的 PDF 拆开,这个需求在办公自动化里非常常见。无论是整理扫描件、汇总周报,还是把系统导出的多页单据按页拆分归档,手动拖拽不仅低效,还容易出错。
今天介绍两种纯 VBA 的实现路径:一种借助成熟的外部工具 PDFtk,合并和拆分都能搞定;另一种使用 vbaPDF 库,无需任何安装,直接嵌入代码。
方法一:借助 PDFtk(稳定、推荐)
PDFtk 是一个老牌的命令行 PDF 处理工具,合并用 cat 命令,拆分用 burst 或 cat 命令 。VBA 只需用 Shell 函数调用它即可,代码量极少。
第一步:安装 PDFtk
从官网(https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/)下载 PDFtk Server(免费版)并安装。安装时建议勾选“添加到 PATH”,或者记住它的安装路径(通常在 C:\Program Files (x86)\PDFtk\bin\)。
第二步:合并 PDF 的 VBA 实现
核心逻辑只有一行命令的拼接。假设你要把 C:\Users\USER\Desktop\测试件1.pdf 和 C:\Users\USER\Desktop\测试件2.pdf 合并成测试件合并结果.pdf,可以这样写:
Sub MergePdfsWithPDFtk()Dim pdftkPath As StringDim drawingPdf As StringDim modelPdf As StringDim outputPdf As StringDim shellCommand As String' 1. 设置 pdftk.exe 的完整路径(如果已加入 PATH,直接用 "pdftk" 即可)pdftkPath = """C:\Program Files (x86)\PDFtk\bin\pdftk.exe"""‘pdftkPath = “pdftk”' 2. 设置输入和输出 PDF 的路径(路径含空格时需加双引号)drawingPdf = """C:\Users\USER\Desktop\测试件1.pdf"""modelPdf = """C:\Users\USER\Desktop\测试件2.pdf"""outputPdf = """C:\Users\USER\Desktop\测试件合并结果.pdf"""' 3. 拼接 PDFtk 命令' 用 cat 操作符按顺序合并,输出到 outputPdfshellCommand = "pdftk" & " " & drawingPdf & " " & modelPdf & " cat output " & outputPdf' 4. 执行命令(vbHide 表示隐藏命令行窗口)Shell shellCommand, vbHideMsgBox "合并命令已发出,请稍后查看输出文件。"End Sub
第三步:拆分 PDF 的 VBA 实现
PDFtk 拆分 PDF 有两种常用方式,分别对应不同的场景。
方式一:burst 逐页拆分
如果你想把一个多页 PDF 的每一页都拆成独立的文件,用 burst 命令 。它会生成 pg_0001.pdf、pg_0002.pdf 等文件 。VBA 实现如下:
Sub SplitPdfByBurst()Dim sCmd As StringDim sourcePdf As StringDim outputPattern As StringsourcePdf = """C:\temp\待拆分.pdf"""' %02d 表示两位数字序号,生成 page_01.pdf, page_02.pdf 等outputPattern = """C:\temp\拆分结果\page_%02d.pdf"""sCmd = "pdftk " & sourcePdf & " burst output " & outputPattern' 用 WScript.Shell 的 Run 方法等待执行完毕(PDFtk 拆分较慢)Dim wsh As ObjectSet wsh = CreateObject("WScript.Shell")wsh.Run sCmd, 0, True ' 第三个参数 True 表示等待执行完毕MsgBox "逐页拆分完成!"End Sub
方式二:cat 按页范围提取
如果你只想提取指定的几页(比如第 1-5 页、或者第 3 页和第 7 页),用 cat 命令 。这种方式比 burst 更灵活,不会生成一堆你不需要的单页文件。
Sub SplitPdfByRange()Dim sCmd As StringDim sourcePdf As StringDim targetPdf As StringsourcePdf = """C:\temp\原始文件.pdf"""targetPdf = """C:\temp\提取结果.pdf"""' 提取第 1 到 5 页' 如果需要多段,可以写成 "1-5 8 10-end"sCmd = "pdftk " & sourcePdf & " cat 1-5 output " & targetPdfDim wsh As ObjectSet wsh = CreateObject("WScript.Shell")wsh.Run sCmd, 0, TrueMsgBox "页面提取完成!"End Sub
页码语法很灵活:1-5 表示连续范围,3 表示单页,end 表示最后一页,多个范围之间用空格分隔 。比如 "1-3 5 7-end" 表示提取第 1 到 3 页、第 5 页、以及第 7 页到最后一页。
注意事项
路径里的空格是个坑。 PDFtk 对空格敏感,所有文件路径必须用双引号包裹(在 VBA 字符串里写 """" 来表示一个引号)。否则遇到 Program Files 这样的路径就会解析失败 。
另外,Shell 是异步执行的,代码不会等 PDFtk 跑完就继续往下走。拆分操作尤其要注意这一点:有用户反馈,如果不等 PDFtk 执行完就继续操作文件,会直接失败 。所以上面的拆分代码用了 WScript.Shell 的 .Run 方法并设置 True,确保等待执行完毕再继续。
方法二:使用 vbaPDF(零依赖、轻量)
如果你希望用户什么都不用装,或者你的 PDF 是由 Microsoft Print to PDF 生成的简单文档,vbaPDF 是一个很有意思的选择。
它是一个纯 VBA 库,源码在 GitHub 上开源。核心类是 pdfDocument,但 Main.bas 里已经封装了一个现成的辅助函数 CombinePDFs,调用起来非常方便。
第一步:导入库
从 GitHub 下载 src 目录下的文件,在 VBA 编辑器里导入 Main.bas、pdfDocument.cls 等模块。

第二步:VBA 代码实现
Sub MergeWithVbaPDF()Dim files() As Stringfiles = Array("C:\temp\a.pdf", "C:\temp\b.pdf", "C:\temp\c.pdf")' 直接调用现成的辅助函数CombinePDFs files, "C:\temp\merged.pdf"MsgBox "合并完成!"End Sub
重要限制
vbaPDF 的定位是轻量、简单,它主要针对 Microsoft Print to PDF 生成的 PDF,以及 Adobe Acrobat Reader 保存的线性化 PDF。如果你用 SolidWorks 或其他专业软件导出的 PDF,内部结构可能更复杂,vbaPDF 不一定能正确解析。
另外,vbaPDF 没有提供拆分功能,它主要面向合并场景。如果你需要拆分,还是得用 PDFtk。
维度 | PDFtk | vbaPDF |
用户是否需要安装 | 需要 | 不需要 |
合并功能 | 支持 | 支持 |
拆分功能 | 支持(burst/cat) | 不支持 |
兼容性 | 极强,几乎所有PDF 都能处理 | 有限,主要支持简单PDF |
代码复杂度 | 极低(一行Shell 调用) | 中等(需要导入多个模块) |
适用场景 | 生产环境、批量处理、需要拆分 | 对部署有严格限制的简单合并场景 |
如果你追求稳定可靠、功能完整,用 PDFtk。它的命令行能力远不止合并和拆分,还支持加密、填表、加水印等 。如果你面对的是无法控制用户环境的场景(比如分发给同事的小工具),且只需要合并功能,vbaPDF 值得一试,但一定要先做好兼容性测试。
最后提醒一句:无论用哪种方法,记得在代码里加上文件存在性检查(Dir 函数),避免因为某个 PDF 被删了或路径写错,导致整个流程静默失败。