夜雨聆风学习资料网

ARTICLE · 1053747

VBA 别只会操作 Excel 了!合并、拆分 PDF 这两种方法,一个比一个狠

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 String    Dim drawingPdf As String    Dim modelPdf As String    Dim outputPdf As String    Dim 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 操作符按顺序合并,输出到 outputPdf    shellCommand = "pdftk" & " " & drawingPdf & " " & modelPdf & " cat output " & outputPdf    ' 4. 执行命令(vbHide 表示隐藏命令行窗口)    Shell shellCommand, vbHide    MsgBox "合并命令已发出,请稍后查看输出文件。"End Sub

第三步:拆分 PDF 的 VBA 实现

PDFtk 拆分 PDF 有两种常用方式,分别对应不同的场景。

方式一:burst 逐页拆分

如果你想把一个多页 PDF 的每一页都拆成独立的文件,用 burst 命令 。它会生成 pg_0001.pdf、pg_0002.pdf 等文件 。VBA 实现如下:

Sub SplitPdfByBurst()    Dim sCmd As String    Dim sourcePdf As String    Dim outputPattern As String    sourcePdf = """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 Object    Set 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 String    Dim sourcePdf As String    Dim targetPdf As String    sourcePdf = """C:\temp\原始文件.pdf"""    targetPdf = """C:\temp\提取结果.pdf"""    ' 提取第 1 到 5 页    ' 如果需要多段,可以写成 "1-5 8 10-end"    sCmd = "pdftk " & sourcePdf & " cat 1-5 output " & targetPdf    Dim wsh As Object    Set wsh = CreateObject("WScript.Shell")    wsh.Run sCmd, 0True    MsgBox "页面提取完成!"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 String    files = 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 被删了或路径写错,导致整个流程静默失败。

相关学习资料