# VBA 自动化测试与精确报错系统 通过代码编织(Code Weaving)技术,实现 VBA 宏的精确到行的代码报错定位。 ## 核心特性 - **精确行号定位**: 捕获 VBA 错误的具体行号,不再只是"发生意外" - **源代码映射**: 通过 Source Map 机制显示出错行的原始代码 - **自动化测试**: 批量执行 VBA 宏并收集结果 - **非侵入式**: 测试过程不修改原始 Excel 文件 - **详细报告**: 提供清晰的测试结果输出 ## 安装依赖 ```bash pip install xlwings pywin32 ``` ## 快速开始 ### 1. 创建演示文件 首先创建一个包含测试代码的 Excel 文件: ```bash python create_demo.py ``` 这将创建 `demo.xlsm` 文件,包含以下测试过程: - `TestErrorProcedure`: 除以零错误 - `TestTypeMismatch`: 类型不匹配错误 - `TestSubscriptError`: 下标越界错误 - `TestSuccessfulProcedure`: 成功执行的测试 ### 2. 运行测试 测试单个过程: ```bash python vba_test_runner.py demo.xlsm Module1 TestSuccessfulProcedure ``` 批量测试多个过程: ```bash python vba_test_runner.py demo.xlsm Module1 TestErrorProcedure TestTypeMismatch TestSubscriptError TestSuccessfulProcedure ``` ## 输出示例 ### 单个测试 **成功时**: ``` [PASS] TestSuccessfulProcedure - Test Passed ``` **失败时**: ``` [FAIL] TestErrorProcedure - Test Failed Error Description: Division by zero Error Line: 30 Source Code: result = x / y ``` ### 批量测试 ``` ===== VBA Batch Test Results ===== [1/4] [FAIL] TestErrorProcedure - Test Failed Error Description: Division by zero Error Line: 30 Source Code: result = x / y [2/4] [FAIL] TestTypeMismatch - Test Failed Error Description: Type mismatch Error Line: 20 Source Code: y = x [3/4] [FAIL] TestSubscriptError - Test Failed Error Description: Subscript out of range Error Line: 40 Source Code: value = arr(5) [4/4] [PASS] TestSuccessfulProcedure - Test Passed ===== Test Summary ===== Passed: 1/4 Failed: 3/4 ``` ## 工作原理 ### 代码编织(Code Weaving) 系统通过以下步骤实现精确报错: 1. **解析 VBA 代码**: 识别所有 Sub/Function 过程 2. **注入行号标签**: 在可执行代码前插入数字标签(10, 20, 30...) 3. **注入错误处理**: 添加 `On Error GoTo` 语句和错误处理块 4. **创建 Source Map**: 维护行号到源代码的映射 ### VBA 行号机制 VBA 的 `Erl` 函数会返回最近执行的行号标签: ```vba 10 x = 10 20 y = 0 30 result = x / y ' Erl 将返回 30 ``` ### 测试流程 ``` 原始 VBA 代码 ↓ 代码编织器注入行号和错误处理 ↓ 注入 _TestLogger 辅助模块 ↓ 热替换目标模块代码 ↓ 执行 VBA 宏 ↓ 从 _TestLogger 读取结果 ↓ 格式化输出 ``` ## 架构设计 ### 模块划分 ``` vba_test_runner.py ├── CodeWeaver (代码编织器类) │ ├── parse_procedures() - 解析 VBA 过程 │ ├── weave_procedure() - 编织单个过程 │ ├── _inject_line_numbers() - 注入行号标签 │ └── _inject_error_handler() - 注入错误处理 │ ├── LoggerInjector (日志模块注入器类) │ ├── inject_or_replace() - 注入或替换 Logger 模块 │ └── LOGGER_MODULE_CODE - Logger 模块的 VBA 代码 │ └── TestRunner (执行控制器类) ├── run_test() - 执行完整测试流程 ├── _get_vba_code() - 读取 VBA 代码 ├── _replace_module_code() - 热替换模块代码 ├── _execute_macro() - 执行宏 └── _get_test_result() - 获取测试结果 ``` ## 关键技术点 ### 行号标签规则 - 使用纯数字标签: `10`, `20`, `30`... (不带冒号) - 只在可执行代码前注入 - 跳过声明区(Dim, Private 等) - 跳过注释行和空行 - 跳过现有的 On Error 语句 ### 错误处理模板 ```vba On Error GoTo Auto_Err_Handler_{proc_name} ... 原有代码 ... Call _TestLogger.LogSuccess() Exit Sub/Function Auto_Err_Handler_{proc_name}: Call _TestLogger.LogError("{proc_name}", Err.Number, Err.Description, Erl) ``` ### 热替换不保存 使用 `wb.Close(SaveChanges=False)` 确保注入的代码不会污染原始文件。 ## 限制和注意事项 1. **信任访问 VBA 项目**: 需要在 Excel 信任中心启用"信任对 VBA 工程对象模型的访问" - 路径: 文件 > 选项 > 信任中心 > 信任中心设置 > 宏设置 > 勾选"信任对 VBA 工程对象模型的访问" 2. **行号标签冲突**: 如果原始代码中已使用相同数值的行号标签,可能会产生冲突 3. **复杂过程**: 对于非常复杂的过程(包含大量 GoTo 语句),可能需要额外处理 4. **只支持标准模块**: 当前版本不支持类模块和窗体模块 ## 扩展开发 ### 添加新的测试过程 在 Excel 文件的 VBA 模块中添加你的测试过程: ```vba Sub YourTestProcedure() ' 你的测试代码 End Sub ``` 然后运行: ```bash python vba_test_runner.py your_file.xlsm Module1 YourTestProcedure ``` ### 自定义 Logger 模块 修改 `LoggerInjector.LOGGER_MODULE_CODE` 可以自定义日志记录逻辑。 ## 常见问题 **Q: 为什么测试后原始文件没有被修改?** A: 系统使用热替换技术,在内存中修改代码,测试完成后使用 `Close(SaveChanges=False)` 不保存更改。 **Q: 如何测试类模块中的方法?** A: 当前版本只支持标准模块。要测试类模块,可以创建一个包装的 Sub 在标准模块中调用类方法。 **Q: 可以捕获运行时警告吗?** A: 当前版本只捕获错误。要捕获警告,需要修改 Logger 模块来处理 `InfoMessage` 事件。 ## 许可证 MIT License ## 贡献 欢迎提交 Issue 和 Pull Request!