
PDF批量透明签名工具
代码逻辑与使用说明书
VBA版 · 适配WPS/Office

1.1 核心功能定位
本工具是基于VBA开发的轻量级PDF批量签名工具,专门解决传统签名方案中PNG透明签名盖印后出现白底、遮盖正文内容的问题,采用PDF原生SMask透明通道机制实现真正的逐像素透明效果,不依赖任何第三方PDF库,无需安装额外控件,兼容WPS与Microsoft Office 32位/64位版本。
工具采用预处理+批量签名的两步式按钮设计,将耗时的PNG解析操作前置,批量处理阶段复用缓存结果,大幅提升多文件处理速度;采用PDF增量写入技术,不修改原PDF文件任何字节,签名过程零风险。
1.2 核心特性
• 真透明签名:通过PDF标准SMask机制实现,签名透明区域可完整透出底层PDF内容,无白底、无遮盖
• 高性能缓存:签名预处理结果自动缓存,批量处理时仅需解析一次PNG,单文件处理速度提升10倍以上
• 增量写入:所有签名内容以增量方式追加到PDF末尾,不破坏原PDF结构,文件兼容性强
• 批量处理:支持单目录下多PDF文件自动批量签名,无需逐个文件手动操作
• 静默执行:PowerShell预处理窗口完全隐藏,无黑框闪烁,操作体验流畅
• 异常隔离:单个文件处理失败不影响整批任务,原文件不会被损坏
• 零依赖:无需安装Adobe Acrobat、PDF库或其他第三方软件,纯VBA+系统自带PowerShell实现
1.3 适用场景
• 企业合同、单据批量电子签名场景
• 财务、行政、法务部门日常PDF盖章需求
• 需要透明电子签名、避免遮盖正文的场景
• 无管理员权限、无法安装第三方PDF软件的办公环境
二、系统架构与模块职责2.1 整体架构分层
工具采用分层模块化设计,共包含4个标准VBA模块,各模块职责单一、耦合度低,便于后期单独修改维护。整体架构分为界面入口层、核心引擎层、工具支撑层、公共清理层四个层级。
模块名称
层级定位
核心职责
Module1
界面入口层
包含「签名预处理」和「PDF批量签名」两个按钮宏,负责流程调度、参数读取、用户交互,是用户直接操作的入口
InsertPDFSignat
核心引擎层
全部PDF解析、PNG处理、字节操作、PDF对象构建、文件读写逻辑,是工具的核心处理模块
FunctionMoudle
工具支撑层
提供工作表获取工具函数、配置表常量定义,为核心模块提供基础工具能力
PublicModule
公共清理层
提供缓存文件清理公共函数,负责预处理前、批量完成后的缓存文件清理工作

2.2 模块调用关系
模块间调用关系清晰,入口模块单向调用工具模块、核心模块与清理模块,核心模块依赖基础工具模块,无循环依赖:
Module1(按钮入口)
├─→ FunctionMoudle(配置表读取工具)
├─→ InsertPDFSignat(核心PDF签名逻辑)
└─→ PublicModule(缓存文件清理)
└─ InsertPDFSignat 调用 FunctionMoudle 完成基础文件操作
2.3 核心引擎内部结构
核心模块InsertPDFSignat内部按职责细分为6层,从底层API到上层业务逐层调用,便于定位问题:
层级
包含函数与作用
API兼容层
CopyMemory内存拷贝API声明,32位/64位双版本兼容,适配不同版本Office/WPS
文件IO层
NzReadFileBytes、NzWriteFileBytes,基于ADODB.Stream实现二进制文件读写,支持大文件
字节工具层
NzToBytes、NzConcatBytes、NzFindB、NzReadInt等字节级操作函数,提供二进制查找、拼接、整数读取能力
PDF解析层
NzParseTrailer、NzParseXref、NzGetPagesObj、NzFindNthPage、NzParsePageDict,负责解析原PDF结构
PNG处理层
NzIsPngFile、NzParsePngSize、NzEnsurePngPrepared,负责PNG格式校验、尺寸解析、缓存检查与预处理触发
对象构建层
NzBuildAppendEx,负责生成签名所需的4个PDF新对象、重写页面字典、生成新xref表与trailer
三、核心执行流程详解3.1 按钮一:签名预处理流程

签名预处理按钮对应宏mynzSignaturePreprocessing,负责提前解析PNG签名,生成缓存文件,避免批量处理时重复启动PowerShell,执行步骤如下:
• 路径定位:自动定位工作簿同目录下的签名图sign.png与预处理脚本PreparePng.ps1
• 存在性校验:检查签名图与脚本是否存在,任一缺失则弹出失败提示并退出
• 旧缓存清理:调用mynzPublicClearCache删除历史残留的.rgb.z/.mask.z缓存文件,避免旧签名缓存被误用
• 静默执行:隐藏窗口启动PowerShell进程,携带-ExecutionPolicy Bypass参数绕过系统执行策略限制,同步等待脚本执行完成
• 结果校验:检查两个缓存文件是否成功生成,校验失败弹出明确的错误提示,包含可能的故障原因
• 完成提示:预处理成功后弹窗提示「签名预处理完成」,此时可开始批量签名操作
3.2 按钮二:PDF批量签名流程

批量签名按钮对应宏mynzSignaturePDF,负责批量处理PDF文件夹内全部文件,完成签名后输出到指定目录,执行步骤如下:
• 路径初始化:自动识别工作簿目录,设定待签目录为工作簿下的PDF文件夹,输出目录为工作簿下的PDF签名文件夹
• 基础校验:校验待签PDF目录、签名图是否存在;输出目录已存在则清空重建,避免新旧文件混杂
• 坐标读取:从ConFig配置表的G20/G21单元格读取签名X/Y坐标,校验坐标是否超出页面边界,坐标非法则提示后退出
• 批量循环:遍历待签目录下所有PDF文件,逐个调用核心签名过程NzInsertPDFSignaturePng,固定签名尺寸100pt×40pt,默认签在文档最后一页
• 结果统计:全部处理完成后弹窗提示成功处理的PDF数量
• 缓存清理:批量处理完成后统一删除缓存文件,保持工作目录整洁
3.3 单PDF核心签名流程
每个PDF文件的签名处理由核心过程NzInsertPDFSignaturePng完成,是整个工具的核心执行链路,步骤如下:
• 文件校验:校验待签PDF、签名PNG是否存在,读取PNG文件头验证是否为合法PNG格式(校验文件头89 50 4E 47标识),解析PNG宽高尺寸
• 缓存检查:判断两个缓存文件是否存在、修改时间是否不早于PNG文件,存在且有效则直接复用缓存,否则自动补做预处理
• PDF结构解析:读取原PDF二进制数据,调用NzParseTrailer解析PDF尾部结构、NzParseXref构建对象偏移表;通过NzGetPagesObj定位页面树根节点,NzCountPages统计总页数,NzFindNthPage定位目标签名页,NzParsePageDict解析页面对象字典
• 签名对象构建:调用NzBuildAppendEx生成4个PDF新对象,构造签名内容流,将签名对象注册到页面资源中
• 增量写入:将原PDF字节与新追加内容拼接,生成新的xref交叉引用表与trailer,写入到输出目录的新PDF文件中
• 异常处理:处理过程中出现错误时,保存错误信息,清理临时资源后抛出异常,由上层循环捕获后继续处理下一个文件
四、核心技术实现原理4.1 PNG透明签名实现机制
PDF文件格式原生不支持带Alpha透明通道的RGBA图像,因此工具采用PDF规范定义的SMask(软遮罩)机制实现真正的透明效果,整个流程分为两个阶段:
第一阶段为PNG通道拆分:由PreparePng.ps1脚本完成,将输入的RGBA格式PNG拆分为两路独立的二进制数据,并使用zlib算法压缩后写入临时文件:
• sign.png.rgb.z:签名颜色数据,每个像素3字节(R、G、B各1字节),按行从上到下排列,对应PDF的彩色图像对象
• sign.png.mask.z:签名透明通道数据,每个像素1字节灰度值(0=完全透明,255=完全不透明),对应PDF的遮罩图像对象
第二阶段为PDF对象写入:在PDF中创建两个独立的图像对象,彩色图像对象通过/SMask属性关联透明遮罩对象,PDF阅读器渲染时会自动根据遮罩的灰度值决定每个像素的透明度,实现逐像素的真透明效果,签名下方的PDF内容可完整透出。
两路数据均采用Flate(zlib)压缩,大幅减小输出PDF体积,压缩比通常可达3:1~5:1。
4.2 缓存加速机制
PNG预处理是整个流程中最耗时的环节,涉及PowerShell进程启动、.NET图像解码、zlib压缩等操作,单次耗时约0.3~1秒。工具通过文件级缓存机制避免重复预处理:
• 预处理操作将拆分结果持久化为磁盘文件,批量处理过程中所有PDF文件复用同一对缓存文件,仅需执行一次预处理
• 缓存有效性校验通过文件修改时间判断:当PNG文件的修改时间晚于缓存文件时,判定缓存过期,自动重新预处理;否则直接复用现有缓存
• 即使跳过预处理按钮直接点击批量签名,第一个PDF处理时也会自动补做预处理,不影响功能正确性,仅首份文件处理速度稍慢
• 批量处理完成后缓存文件统一删除,不残留垃圾文件;若需要多次修改重跑,可手动保留缓存文件进一步提升速度
4.3 PDF增量写入机制
工具采用PDF增量更新技术写入签名,完全不修改原PDF文件的任何字节内容,具备极高的安全性与兼容性:
• 所有新增的签名对象、修改后的页面对象、新的交叉引用表和尾部结构,全部以追加的方式写到原PDF内容的末尾
• 新的trailer中通过/Prev指针指向原PDF的交叉引用表位置,PDF阅读器可正确识别增量更新内容
• 原PDF文件全程为只读状态,即使签名过程中出现异常中断,原文件也不会被损坏,无文件损坏风险
• 增量写入方式生成的PDF完全符合PDF 1.4规范,可被所有主流PDF阅读器正确打开与渲染
4.4 PowerShell静默执行机制
PNG拆分脚本通过WScript.Shell的Run方法调用,采用双保险隐藏窗口策略,执行过程无任何黑框闪烁:
• Run方法第二个参数传入0,表示隐藏PowerShell窗口
• PowerShell启动参数携带-WindowStyle Hidden,双重保证窗口不显示
• 携带-NoProfile参数跳过用户配置文件加载,加快PowerShell启动速度
• Run方法第三个参数传入True,VBA同步等待脚本执行完成后再继续,避免缓存文件未生成就开始读取
• 携带-ExecutionPolicy Bypass参数,绕过系统PowerShell执行策略限制,无需用户手动修改系统设置
五、部署与配置指南5.1 标准目录结构
工具采用目录约定优于配置的设计,所有文件必须按以下结构放置,无需额外配置路径:
工作簿所在文件夹/
├─ 批量签名工具.xlsm (本工具VBA工作簿)
├─ sign.png (透明签名图,必须带Alpha通道)
├─ PreparePng.ps1 (PNG预处理PowerShell脚本)
├─ PDF/ (待签名PDF存放目录,需手动创建)
│ ├─ 合同1.pdf
│ ├─ 合同2.pdf
│ └─ ...
└─ PDF签名/ (签名后PDF输出目录,程序自动创建/清空)
运行过程中会在工作簿目录临时生成sign.png.rgb.z和sign.png.mask.z两个缓存文件,批量处理完成后自动删除,无需手动清理。
5.2 配置表说明
工具所有配置参数均放在工作簿内名为ConFig的工作表中,无需修改代码即可调整:
单元格
参数名
单位
说明
G20
签名X坐标
pt(磅)
签名左下角距离页面左边缘的水平距离
G21
签名Y坐标
pt(磅)
签名左下角距离页面下边缘的垂直距离(注意:PDF坐标原点在页面左下角,不是左上角)
D20
X坐标上限
pt
程序自动校验边界,要求G20 ≤ D20 - 签名宽度(默认100pt)
D21
Y坐标上限
pt
程序自动校验边界,要求G21 ≤ D21 - 签名高度(默认40pt)
常用坐标参考:A4竖版纸张尺寸为595.28pt × 841.89pt,右下角签名推荐坐标X=350,Y=60;右上角签名推荐坐标X=350,Y=750;居中签名推荐X=247,Y=400。

5.3 签名图要求

• 格式要求:必须为标准PNG格式,不支持JPG、BMP等其他格式
• 透明要求:必须带真实Alpha透明通道,白底照片直接修改后缀为PNG无法实现透明效果,需使用抠图工具去除背景
• 尺寸建议:宽高比建议为2.5:1(与默认签名尺寸100:40匹配),避免签名拉伸变形
• 文件名要求:默认文件名为sign.png,放在工作簿同目录;如需修改文件名可在Module1头部修改Signature常量

5.4 PDF文件要求
• 格式要求:支持PDF 1.4及以下标准格式,不支持PDF 1.5+采用压缩xref流格式的文件(可通过Microsoft Print to PDF重新打印生成标准格式PDF)
• 权限要求:待签PDF文件不能被其他程序(如Adobe Reader、WPS)占用,否则读取会失败
• 损坏文件:损坏的PDF文件会被自动跳过,不影响其他文件处理
六、标准操作流程标准操作分为5个步骤,正常情况下全程无需修改代码:
步骤1:部署文件
• 将工具工作簿、sign.png签名图、PreparePng.ps1脚本放在同一文件夹下
• 在该文件夹下创建名为PDF的子文件夹,将所有需要签名的PDF文件放入此目录

Pdf 文件夹:

待签名的文件:

步骤2:配置签名位置
• 打开工作簿,切换到ConFig工作表
• 在G20单元格输入签名X坐标,G21单元格输入签名Y坐标,单位为pt
• 确保坐标值不超过D20、D21单元格定义的边界值

步骤3:执行签名预处理
• 点击工作表上的「签名预处理」按钮
• 等待弹出「签名预处理完成」提示框(首次执行约0.5~1秒)
• 若弹出错误提示,按提示排查文件路径、签名格式等问题


步骤4:执行批量签名

• 点击工作表上的「PDF批量签名」按钮
• 等待批量处理完成,过程中不要打开PDF目录下的文件
• 处理完成后弹出「共处理N份PDF」的提示框

步骤5:获取结果
• 打开工作簿目录下自动生成的PDF签名文件夹
• 所有签名完成的PDF均在此目录中,打开验证签名位置与透明效果
签名后的文件夹:

签名后的文件:

说明:可以跳过步骤3直接执行批量签名,第一个PDF处理时会自动执行预处理,仅首份文件速度稍慢,不影响最终结果。
七、参数修改指南所有常用参数均可直接定位到代码对应位置修改,无需理解全部核心逻辑,修改位置与参数说明如下:
修改需求
代码位置
修改说明
修改签名尺寸
mynzSignaturePDF中NzInsertPDFSignaturePng调用处
原参数为100, 40,分别对应签名宽度、高度,单位为pt,直接修改为需要的尺寸即可
修改签名页码
mynzSignaturePDF中NzInsertPDFSignaturePng调用处
最后一个参数默认为-1,表示签在最后一页;改为正整数则签在对应页码(从1开始)
修改待签目录名
mynzSignaturePDF开头
原目录名为"PDF",修改为需要的文件夹名称即可
修改输出目录名
mynzSignaturePDF开头
原目录名为"PDF签名",修改为需要的文件夹名称即可
修改签名图文件名
Module1模块头部常量定义
原常量Signature = "sign.png",修改为实际签名图文件名即可
修改预处理脚本名
签名预处理按钮代码内
原脚本名为"PreparePng.ps1",修改为实际脚本文件名即可《不用动》
修改坐标读取单元格
mynzSignaturePDF坐标读取段
原代码读取Range("G20")和Range("G21"),修改为实际使用的单元格地址即可
修改配置表名
FunctionMoudle模块头部常量
原常量SHEET_NAME = "ConFig",修改为实际配置表名称即可
注意:修改文件名、目录名时注意保留双引号,不要删除引号;修改尺寸参数时保持参数顺序为宽度在前、高度在后。
八、错误提示与问题排查工具所有错误均会弹出明确的中文提示,常见错误原因与解决方法如下:
错误提示
原因与解决方法
预处理失败:未找到签名文件sign.png
工作簿目录下缺少sign.png签名图,检查文件名是否正确、是否放在工作簿同目录下
预处理失败:未找到预处理脚本PreparePng.ps1
工作簿目录下缺少PreparePng.ps1脚本,检查文件是否存在、文件名是否正确
PNG预处理失败,PowerShell返回码:1
PowerShell脚本执行失败,通常原因:签名图不是带透明通道的标准PNG、脚本损坏、文件被占用;可尝试重新导出PNG、替换脚本文件
PDF目录不存在,请在工作簿同目录创建PDF文件夹
工作簿下没有创建名为PDF的待签目录,手动创建该文件夹并放入待签PDF即可
签名坐标超出边界,请在ConFig表G20/G21重新设置
填入的坐标会导致签名超出PDF页面范围,调小G20/G21的数值即可;注意Y坐标是从页底往上计算
不是合法的PNG文件
签名图格式错误或文件损坏,检查是否为标准PNG格式,重新导出签名图即可
不支持压缩xref流的PDF,请用Microsoft Print to PDF重新打印
原PDF为高版本压缩格式,打开PDF后选择打印→打印机选择Microsoft Print to PDF,重新生成标准格式PDF即可
签名后出现白底遮盖正文
签名PNG没有真实Alpha透明通道,使用抠图工具去除签名背景,重新导出为带透明的PNG即可
签名位置不对/偏移
坐标计算错误,注意Y坐标是从页面底部往上计算,不是从顶部往下;调整G20/G21数值即可
签名被拉伸变形
签名图宽高比与设置的签名尺寸宽高比不匹配,调整签名尺寸参数或裁剪签名图使比例一致即可
备注:此资料为“VBA语言専攻”资料推广课,售价19.9元。可在网站、微信购买。















