Excel VBA 编程 -- 三谈保护知识产权
- 2026-10-29 19:16:28
Excel VBA 编程 -- 三谈保护知识产权前面我们先是讨论了 Excel 密码保护措施的脆弱性,接着介绍了一个尚未成熟的 VBA 编译工具——VBA Padlock,接下来,我们来讨论我们自己所能实现的对 VBA 代码的保护措施。 因为 VBA 代码是以源代码的形式存储在 Excel 文件中的,要实现最高强度的保护,最直接的办法就是将 VBA 源代码编译为机器代码。VBA Padlock 工具就是这个思路,但该工具尚不成熟,而且还需要付费。成本最低的办法就是我们自己将 VBA 源代码转换为某种编译语言,再通过该语言的编译器将其编译为机器代码。 一种比较可行的办法就是将 VBA 代码转换为 Delphi 代码。Delphi 有如下几点优势: 现在,我们以《Excel 编程 -- 再谈访问数据库》中的写入/读出 Access 数据库为例,说明将 VBA 代码转换为 Delphi DLL 的过程。 访问 Access 数据库的例子中包括了类 AceClient 以及 AceTestModule 中的 AceTest、WriteDataToAccess、ReadDataFromAccess 几个过程。 首先,我们在 VS Code 中让 Copilot 做初步转换: 
Copilot 转换成的 Delphi 代码只能作为雏形,还是需要手工打磨,形成最终版本,如下所示: 
VBA 中的 AceClient 类转换为 Delphi 的 TAceClient。Delphi 的 Class 可以定义自己的构造函数,如图所示,TAceClient.Create 构造函数带一个参数,ADBFile。所以,TAceClient 类的实例化可以写成: 不需要再像 VBA 中那样啰嗦。 同样,AceTestModule 也是先通过 Copilot 进行初步转换,再手工打磨成为能够使用的最终版本: 
在这个文件头部,我们看到,AceTest 通过 exports 指令声明为 DLL 中向外呈现的接口,而 WriteDataToAccess 和 ReadDataFromAccess 都只是由 AceTest 调用的内部过程,外部不可见。 AceTest 函数的原型为: 与 VBA 中的 Sub AceTest 不同,改写后的 AceTest 变成了一个函数,且该函数的调用规范遵循 stdcall,这是为了符合 Windows API 的规范。该函数接受两个参数:一个需要操作的工作表名称,一个需要生成的 Access 数据库文件名。 AceTest 的部分实现代码如下: 
仔细查看,其实 Delphi 的代码与 VBA 的代码相似度很高,这也使得 VBA 代码到 Delphi 代码的转换比较容易(相对于转换为 C/C++ 而言)。 下面是 AceOperation.dpr 代码: 
AceOperation.dll 的源代码包含两个模块:AceClient.pas 和 AceTestModule.pas,向外呈现的接口只有一个:AceTest 函数。 为了适应不同环境,可以将编译后的 64 位 DLL 命名为 AceOperation64.dll,而将 32 位的 DLL 命名为 AceOperation32.dll。 下面看如何在 Excel 中使用这个 DLL。 
这是我们的 Excel 数据集。我们的任务是,将这个数据集写入 Access 数据库,然后再读出 Access 数据库中的数据,写入同一个工作表的右侧。 相应的调用 DLL 的 VBA 代码如下: 
首先声明 DLL 中的接口函数 AceTest,然后在 TestIt 过程中调用这个函数 AceTest 来完成我们的任务。此时,除以上几行代码之外,VBAProject 中不再包含其他的 VBA 代码。最后结果如下: 
此图与《Excel 编程 -- 再谈访问数据库》中的结果完全一样。说明我们的转换是成功的。 很多人对于现在还在谈论 Delphi 似乎不以为然,认为 Delphi 已经是明日黄花。其实不然,从我们今天的例子看,Delphi 至少可以作为 VBA 源代码的“保护神”而存在!😄 注:为了节省篇幅,Delphi 代码只显示了一部分。有需要 Delphi 代码的朋友,可以私信索取。 相关阅读 Excel VBA 编程 -- 保护知识产权 Excel VBA 编程 -- 再谈保护知识产权 Excel 编程 -- 再谈访问数据库
Delphi 是一种编译语言,可以编译为机器代码; Delphi 支持 OLE Automation,VBA 代码比较容易转换为 Delphi。


varaClient: TAceClient;beginaClient := TAceClient('MyDb.accdb');// ...end;

function AceTest(const sheet: PWideChar; const db: PWideChar): Boolean; stdcall; 




本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。