From 68798920d63c27cd1f6ffe468d939ac4d78715bc Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Thu, 12 Feb 2026 14:35:30 +0800 Subject: [PATCH] docs: add comprehensive error handling mechanism documentation Add detailed documentation for error handling system including: - Error handling architecture with class diagrams - Error type classification (7 types) - Complete error handling lifecycle sequence diagrams - Module-specific error handling patterns (M01/M03/M05/M06/M07/M08/M09) - Error recovery strategies (continue, graceful degradation, warning only) - Error report generation process - Best practices with code examples - Test coverage overview - Quick reference guide Co-Authored-By: Claude Sonnet 4.5 --- docs/错误处理机制详解.md | 1203 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1203 insertions(+) create mode 100644 docs/错误处理机制详解.md diff --git a/docs/错误处理机制详解.md b/docs/错误处理机制详解.md new file mode 100644 index 0000000..39ed2f1 --- /dev/null +++ b/docs/错误处理机制详解.md @@ -0,0 +1,1203 @@ +# 错误处理机制详解 + +## 目录 + +1. [系统概述](#系统概述) +2. [错误处理架构](#错误处理架构) +3. [错误类型与分类](#错误类型与分类) +4. [错误处理流程](#错误处理流程) +5. [模块错误处理详解](#模块错误处理详解) +6. [错误恢复策略](#错误恢复策略) +7. [错误报告生成](#错误报告生成) +8. [最佳实践](#最佳实践) +9. [测试覆盖](#测试覆盖) +10. [快速参考](#快速参考) + +--- + +## 系统概述 + +AutoBOM系统采用**集中式日志记录 + 持续处理**的错误处理策略,确保在批量处理BOM数据时,单个记录的错误不会中断整个处理流程。 + +### 核心设计原则 + +1. **错误隔离**: 单个记录错误不影响其他记录处理 +2. **错误累积**: 所有错误统一收集,集中展示 +3. **上下文保留**: 记录完整的错误上下文信息 +4. **用户友好**: 提供清晰的错误描述和定位信息 + +### 设计优势 + +```mermaid +graph LR + subgraph "传统错误处理" + A1[遇到错误] --> B1[停止处理] + B1 --> C1[用户修复] + C1 --> D1[重新运行] + D1 --> E1[下一个错误
再次停止] + end + + subgraph "AutoBOM错误处理" + A2[遇到错误] --> B2[记录错误] + B2 --> C2[继续处理] + C2 --> D2[处理完成] + D2 --> E2[一次性查看
所有错误] + end + + style A2 fill:#c8e6c9 + style B2 fill:#c8e6c9 + style C2 fill:#c8e6c9 + style D2 fill:#c8e6c9 + style E2 fill:#c8e6c9 + style A1 fill:#ffcdd2 + style E1 fill:#ffcdd2 +``` + +--- + +## 错误处理架构 + +### 类层次结构 + +```mermaid +classDiagram + class clsErrorLogger { + -Collection pErrors + +Record(rowIdx, sourceFunc, errorType, desc, context) + +HasErrors() Boolean + +PrintReport(targetWb) + +Class_Initialize() + } + + class M01_Main { + +RunBOMConversion() + +GeneratePreprocessingReport() + } + + class M03_Logic { + -clsErrorLogger g_Logger + +InitLogic(logger) + +ParseRule(strRule, rowIdx) + -ConflictDetection() + } + + class M05_PreProcessor { + -clsErrorLogger g_Logger + +InitPreProcessor(logger, wsMapping) + +PreprocessCondition(strCond, strCat, rowIdx) + } + + class M06_ModelParser { + -clsErrorLogger g_Logger + +InitModelParser(logger) + +ParseProductModel(modelString) + } + + class M07_BOMMatcher { + -clsErrorLogger g_Logger + +InitBOMMatcher(logger) + +MatchBOMRecord(ws, params) + } + + class M08_ComponentProcessor { + -clsErrorLogger g_Logger + +InitComponentProcessor(logger) + +ProcessComponentRecord(row) + } + + class M09_BOMExtractor { + -clsErrorLogger g_Logger + +RunBOMExtraction() + +ProcessSingleModel(modelString) + } + + clsErrorLogger <-- M01_Main : uses + clsErrorLogger <-- M03_Logic : uses + clsErrorLogger <-- M05_PreProcessor : uses + clsErrorLogger <-- M06_ModelParser : uses + clsErrorLogger <-- M07_BOMMatcher : uses + clsErrorLogger <-- M08_ComponentProcessor : uses + clsErrorLogger <-- M09_BOMExtractor : uses +``` + +### 模块依赖关系 + +```mermaid +graph TB + Logger[clsErrorLogger.cls
错误日志记录器] + + M01[M01_Main.bas
主入口] + + M03[M03_Logic.bas
条件解析] + M05[M05_PreProcessor.bas
预处理] + M06[M06_ModelParser.bas
型号解析] + M07[M07_BOMMatcher.bas
BOM匹配] + M08[M08_ComponentProcessor.bas
部件处理] + + M09[M09_BOMExtractor.bas
BOM提取] + + M01 --> Logger + M01 --> M03 + M01 --> M05 + M09 --> Logger + M09 --> M06 + M09 --> M07 + M09 --> M08 + + M03 -.记录错误.-> Logger + M05 -.记录错误.-> Logger + M06 -.记录错误.-> Logger + M07 -.记录错误.-> Logger + M08 -.记录错误.-> Logger + + Logger -.生成报告.-> M01 + Logger -.生成报告.-> M09 + + style Logger fill:#e1f5fe + style M01 fill:#fff4e1 + style M09 fill:#fff4e1 +``` + +--- + +## 错误类型与分类 + +### 错误分类体系 + +```mermaid +graph TD + Root[错误类型] + + Root --> Sys[系统错误
SystemError] + Root --> Syn[语法错误
SyntaxError] + Root --> Log[逻辑冲突
LogicConflict] + Root --> Map[映射警告
MappingWarning] + Root --> Mod[型号解析错误
ModelParseError] + Root --> Mat[BOM匹配错误
BOMMatchError] + Root --> Val[验证错误
ValidationError] + + Sys --> Sys1[运行时异常] + Sys --> Sys2[空引用错误] + Sys --> Sys3[类型转换错误] + + Syn --> Syn1[缺少运算符] + Syn --> Syn2[括号不匹配] + Syn --> Syn3[非法字符] + + Log --> Log1[相等与不等冲突] + Log --> Log2[互斥值冲突] + + Map --> Map1[azxs映射缺失] + Map --> Map2[lcfw映射缺失] + + Mod --> Mod1[表头为空] + Mod --> Mod2[格式不匹配] + + Mat --> Mat1[无匹配记录] + Mat --> Mat2[多重匹配] + + Val --> Val1[组件组合无效] + Val --> Val2[数据不完整] + + style Root fill:#e1f5fe + style Sys fill:#ffcdd2 + style Syn fill:#fff9c4 + style Log fill:#ffe0b2 + style Map fill:#c8e6c9 + style Mod fill:#c8e6c9 + style Mat fill:#c8e6c9 + style Val fill:#c8e6c9 +``` + +### 错误类型详细说明 + +| 错误类型 | 英文标识 | 严重级别 | 处理策略 | 示例 | +|----------|----------|----------|----------|------| +| 系统错误 | SystemError / System Error | 🔴 高 | 记录并跳过 | 运行时异常、对象为空 | +| 语法错误 | SyntaxError | 🔴 高 | 记录并跳过 | 条件缺少"="或"!=" | +| 逻辑冲突 | LogicConflict | 🟡 中 | 记录并跳过 | `azxs=1 AND azxs=2` | +| 映射警告 | MappingWarning | 🟢 低 | 记录并继续 | 值未在映射表中找到 | +| 型号解析错误 | ModelParseError | 🔴 高 | 记录并跳过 | 型号格式不匹配 | +| BOM匹配错误 | BOMMatchError | 🟡 中 | 记录并继续 | 无匹配/多重匹配 | +| 验证错误 | ValidationError | 🟡 中 | 记录并继续 | 组件与子组件混用 | + +--- + +## 错误处理流程 + +### 完整错误处理生命周期 + +```mermaid +sequenceDiagram + participant User as 用户 + participant Main as M01/M09 + participant Logger as clsErrorLogger + participant Module as 业务模块 + participant Excel as Excel工作表 + + User->>Main: 启动处理 + Main->>Logger: 创建错误日志记录器 + Main->>Main: 初始化各模块 + + loop 遍历数据行 + Main->>Module: 处理单条记录 + Module->>Module: 执行业务逻辑 + + alt 处理成功 + Module-->>Main: 返回成功结果 + else 发生错误 + Module->>Logger: Record(rowIdx, source, type, desc, context) + Logger->>Logger: 存储错误信息到集合 + Logger-->>Module: 确认记录 + Module-->>Main: 返回Nothing/空结果 + Main->>Main: 继续处理下一条记录 + end + end + + Main->>Logger: HasErrors? + alt 有错误 + Logger-->>Main: True + Main->>Logger: PrintReport(targetWb) + Logger->>Excel: 创建"错误报告_hhmmss"工作表 + Logger->>Excel: 写入表头(红色背景) + Logger->>Excel: 批量写入错误数据 + Logger->>Excel: 自动调整列宽 + Main->>User: 显示警告消息框 + else 无错误 + Logger-->>Main: False + Main->>User: 显示成功消息 + end + + User-->>Main: 查看错误报告 +``` + +### 错误记录数据结构 + +```mermaid +graph LR + subgraph "错误记录数组" + A[0: 行号
RowIndex] + B[1: 来源模块
SourceFunc] + C[2: 错误类型
ErrorType] + D[3: 详细描述
Description] + E[4: 原始数据
Context] + end + + subgraph "示例" + F[
125
M03.ParseAtom
SyntaxError
No = or != found
azxsA0
] + end + + A & B & C & D & E --> F + + style A fill:#e1f5fe + style B fill:#fff4e1 + style C fill:#ffe0b2 + style D fill:#c8e6c9 + style E fill:#f3e5f5 + style F fill:#fafafa +``` + +--- + +## 模块错误处理详解 + +### M03_Logic.bas - 条件解析模块 + +#### 错误场景 + +```mermaid +flowchart TD + Start[M03_Logic.ParseRule] --> CheckSyntax{检查语法} + + CheckSyntax -->|无效| SyntaxErr[语法错误] + CheckSyntax -->|有效| ProcessLogic[处理逻辑] + + ProcessLogic --> CheckConflict{检测冲突} + + CheckConflict -->|冲突| ConflictErr[逻辑冲突] + CheckConflict -->|无冲突| SystemCheck{系统检查} + + SystemCheck -->|异常| SystemErr[系统错误] + SystemCheck -->|正常| Success[解析成功] + + SyntaxErr --> LogSyntax[记录: SyntaxError] + ConflictErr --> LogConflict[记录: LogicConflict] + SystemErr --> LogSystem[记录: System Error] + + LogSyntax --> Return[返回Nothing] + LogConflict --> Return + LogSystem --> Return + Success --> ReturnResult[返回结果集] + + style SyntaxErr fill:#ffcdd2 + style ConflictErr fill:#ffe0b2 + style SystemErr fill:#ffcdd2 + style LogSyntax fill:#fff9c4 + style LogConflict fill:#ffe0b2 + style LogSystem fill:#ffe0b2 + style Return fill:#ffebee +``` + +#### 错误处理代码 + +**1. 系统错误处理** +```vba +ErrorHandler: + g_Logger.Record rowIdx, "M03.ParseRule", "System Error", Err.Description, strRule + Set ParseRule = Nothing +``` + +**2. 语法错误处理** +```vba +Else + ' 无法解析的格式 + If Len(strAtom) > 0 Then + g_Logger.Record rowIdx, "M03.ParseAtom", "Syntax Error", _ + "No = or != found", strAtom + End If +End If +``` + +**3. 逻辑冲突检测** +```vba +If v1 = Mid(v2, 3) Then + ' 等于一个不允许的值 + g_Logger.Record rowIdx, "M03.Conflict", "Logic Conflict", _ + "Equals disallowed value", k & ": " & v1 & " AND " & v2 + Set MergeDictionaries = Nothing: Exit Function +ElseIf v1 = v2 Then + ' 相同,无视 +ElseIf Left(v1, 2) = "!=" And Left(v2, 2) = "!=" Then + ' 都是不等于,合并 + res(k) = v1 & "," & v2 +Else + ' 都是等于,但值不同 → 互斥 + g_Logger.Record rowIdx, "M03.Conflict", "Logic Conflict", _ + "Mutually Exclusive", k & "=" & v1 & " AND " & v2 + Set MergeDictionaries = Nothing: Exit Function +End If +``` + +--- + +### M05_PreProcessor.bas - 预处理模块 + +#### 错误处理流程 + +```mermaid +flowchart TD + Start[PreprocessCondition] --> CheckCategory{检查类别} + + CheckCategory -->|接头/部件| LoadMapping[加载映射表] + CheckCategory -->|其他| Bypass[跳过预处理] + + LoadMapping --> CheckMapping{检查映射} + + CheckMapping -->|找到映射| ApplyMapping[应用映射] + CheckMapping -->|未找到| LogWarning[记录映射警告] + + ApplyMapping --> MergeOR[合并OR条件] + LogWarning --> MergeOR + + MergeOR --> Simplify[简化括号] + Simplify --> Success[返回转换结果] + + style CheckMapping fill:#fff9c4 + style LogWarning fill:#c8e6c9 + style Success fill:#e8f5e9 +``` + +#### 错误处理代码 + +**映射警告处理** +```vba +Else + ' 记录警告但不中断处理 + g_Logger.Record rowIdx, "M05.PreProcessor", "Mapping Warning", _ + "Value not found in mapping table: " & keyName & "=" & originalValue, match.Value +End If +``` + +--- + +### M06_ModelParser.bas - 型号解析模块 + +#### 错误处理流程 + +```mermaid +flowchart TD + Start[ParseProductModel] --> ExtractHeader[提取表头部分] + + ExtractHeader --> CheckEmpty{检查是否为空} + + CheckEmpty -->|为空| ParseError[解析错误] + CheckEmpty -->|有值| ParseParams[解析参数] + + ParseError --> LogError1[记录: ModelParseError] + LogError1 --> ReturnEmpty[返回空字典] + + ParseParams --> SystemCheck{系统检查} + + SystemCheck -->|异常| SysError[系统错误] + SystemCheck -->|正常| Success[解析成功] + + SysError --> LogError2[记录: SystemError] + LogError2 --> ReturnEmpty2[返回空字典] + Success --> ReturnParams[返回参数字典] + + style ParseError fill:#ffcdd2 + style SysError fill:#ffcdd2 + style LogError1 fill:#ffe0b2 + style LogError2 fill:#ffe0b2 + style ReturnEmpty fill:#ffebee + style ReturnEmpty2 fill:#ffebee +``` + +#### 错误处理代码 + +**1. 解析错误处理** +```vba +If Len(headerPart) = 0 Then + If Not g_Logger Is Nothing Then + g_Logger.Record 0, "M06.ParseProductModel", "ModelParseError", _ + "无法提取表头部分,型号可能为空或格式错误", modelString + End If + Set ParseProductModel = params + Exit Function +End If +``` + +**2. 系统错误处理** +```vba +ErrorHandler: + If Not g_Logger Is Nothing Then + g_Logger.Record 0, "M06.ParseProductModel", "SystemError", _ + "解析过程发生错误: " & Err.Description, modelString + End If + Set ParseProductModel = CreateObject("Scripting.Dictionary") +``` + +--- + +### M07_BOMMatcher.bas - BOM匹配模块 + +#### 错误处理流程 + +```mermaid +flowchart TD + Start[MatchBOMRecord] --> BuildMapping[构建列映射] + + BuildMapping --> LoopRows[遍历行] + + LoopRows --> Evaluate{评估匹配} + + Evaluate -->|匹配| CheckCount{检查数量} + Evaluate -->|不匹配| NextRow[下一行] + + CheckCount -->|0条| NoMatch[无匹配] + CheckCount -->|1条| Success[唯一匹配] + CheckCount -->|多条| MultiMatch[多重匹配] + + NoMatch --> LogNoMatch[记录: BOMMatchError
未找到匹配] + MultiMatch --> LogMulti[记录: BOMMatchError
多重匹配] + + LogNoMatch --> ReturnFail[返回失败结果] + LogMulti --> ReturnFail + + Success --> ExtractInfo[提取物料信息] + + ExtractInfo --> ExtractErr{提取异常?} + + ExtractErr -->|是| LogSysError[记录: SystemError] + ExtractErr -->|否| ReturnSuccess[返回物料信息] + + LogSysError --> ReturnEmptyDict[返回空字典] + + style NoMatch fill:#ffe0b2 + style MultiMatch fill:#ffe0b2 + style ExtractErr fill:#ffcdd2 + style LogNoMatch fill:#fff9c4 + style LogMulti fill:#fff9c4 + style LogSysError fill:#ffe0b2 + style ReturnFail fill:#ffebee +``` + +#### 错误处理代码 + +**1. 匹配结果处理** +```vba +If matchResult("rowCount") = 0 Then + logger.Record 0, "M09.MatchAllMaterialTypes", "BOMMatchError", _ + sheetName & " " & matchResult("message"), "" +End If +``` + +**2. 系统错误处理** +```vba +ErrorHandler: + If Not g_Logger Is Nothing Then + g_Logger.Record 0, "M07.MatchBOMRecord", "SystemError", _ + "匹配过程发生错误: " & Err.Description, ws.Name + End If + + result("success") = False + result("rowCount") = 0 + Set result("rowNums") = New Collection + result("message") = "系统错误: " & Err.Description + Set MatchBOMRecord = result +``` + +--- + +### M08_ComponentProcessor.bas - 部件处理模块 + +#### 错误处理流程 + +```mermaid +flowchart TD + Start[ProcessComponentRecord] --> ValidateCombination[验证组件组合] + + ValidateCombination --> CheckValid{验证结果} + + CheckValid -->|无效| ValidationError[验证错误] + CheckValid -->|有效| ExtractComponent[提取组件信息] + + ValidationError --> LogError[记录: ValidationError
无效组合] + LogError --> ReturnError[返回错误物料] + + ExtractComponent --> ExtractErr{提取异常?} + + ExtractErr -->|是| SystemError[系统错误] + ExtractErr -->|否| ReturnSuccess[返回组件信息] + + SystemError --> LogSysError[记录: SystemError] + LogSysError --> ReturnError2[返回错误物料] + + style ValidationError fill:#ffe0b2 + style SystemError fill:#ffcdd2 + style LogError fill:#fff9c4 + style LogSysError fill:#ffe0b2 + style ReturnError fill:#ffebee + style ReturnError2 fill:#ffebee +``` + +#### 错误处理代码 + +**系统错误处理** +```vba +ErrorHandler: + If Not logger Is Nothing Then + logger.Record 0, "M08.ProcessComponentRecord", "SystemError", _ + "处理部件记录失败: " & Err.Description, "" + End If + + ' 返回错误物料信息 + Dim errorMat As Object + Set errorMat = CreateObject("Scripting.Dictionary") + errorMat("materialType") = "部件" + errorMat("materialName") = "" + errorMat("materialCode") = "" + errorMat("materialQty") = 0 + errorMat("remarks") = "系统错误: " & Err.Description +``` + +--- + +### M09_BOMExtractor.bas - BOM提取模块 + +#### 错误处理流程 + +```mermaid +flowchart TD + Start[ProcessSingleModel] --> ParseModel[解析型号] + + ParseModel --> ParseOK{解析成功?} + + ParseOK -->|失败| LogParseError[记录: ModelParseError] + ParseOK -->|成功| MatchLoop[匹配所有物料类型] + + LogParseError --> GenerateErrorRow[生成错误行] + GenerateErrorRow --> Continue[继续下一个型号] + + MatchLoop --> MatchCheck{匹配检查} + + MatchCheck -->|匹配失败| LogMatchError[记录: BOMMatchError] + MatchCheck -->|匹配成功| SaveResult[保存结果] + + LogMatchError --> Continue + SaveResult --> Continue + + Continue --> End[结束] + + style LogParseError fill:#ffe0b2 + style LogMatchError fill:#ffe0b2 + style GenerateErrorRow fill:#ffebee +``` + +#### 错误处理代码 + +**1. 单型号处理错误** +```vba +ErrorHandler: + If Not logger Is Nothing Then + logger.Record 0, "M09.ProcessSingleModel", "SystemError", _ + "处理型号[" & modelString & "]失败: " & Err.Description, "" + End If + + results.Add GenerateErrorRow(modelString, "系统错误: " & Err.Description) + Set ProcessSingleModel = results +``` + +**2. 匹配错误处理** +```vba +If matchResult("rowCount") = 0 Then + logger.Record 0, "M09.MatchAllMaterialTypes", "BOMMatchError", _ + sheetName & " " & matchResult("message"), "" +End If +``` + +--- + +## 错误恢复策略 + +### 策略分类 + +```mermaid +graph TD + subgraph "错误恢复策略" + A[策略选择] + + A --> B[继续处理
Continue Processing] + A --> C[优雅降级
Graceful Degradation] + A --> D[仅警告
Warning Only] + end + + subgraph "继续处理" + B1[记录错误] + B2[返回Nothing/空值] + B3[处理下一条记录] + end + + subgraph "优雅降级" + C1[检测组件失败] + C2[返回错误物料] + C3[保存部分结果] + end + + subgraph "仅警告" + D1[记录警告信息] + D2[继续正常流程] + D3[不中断处理] + end + + B --> B1 --> B2 --> B3 + C --> C1 --> C2 --> C3 + D --> D1 --> D2 --> D3 + + style B fill:#c8e6c9 + style C fill:#fff9c4 + style D fill:#e1f5fe + style B3 fill:#e8f5e9 + style C3 fill:#ffe0b2 + style D3 fill:#e8f5e9 +``` + +### 策略详解 + +#### 1. 继续处理 (Continue Processing) + +**适用场景**: 语法错误、系统错误、解析错误 + +```vba +' M03_Logic.bas +ErrorHandler: + g_Logger.Record rowIdx, "M03.ParseRule", "System Error", Err.Description, strRule + Set ParseRule = Nothing ' 返回Nothing表示失败 + ' 调用方检测到Nothing后继续处理下一条记录 +``` + +**流程**: +``` +错误发生 → 记录错误 → 返回Nothing → 调用方跳过 → 处理下一条记录 +``` + +--- + +#### 2. 优雅降级 (Graceful Degradation) + +**适用场景**: 组件处理失败、物料提取失败 + +```vba +' M08_ComponentProcessor.bas +ErrorHandler: + ' 返回错误物料信息而不是崩溃 + Dim errorMat As Object + Set errorMat = CreateObject("Scripting.Dictionary") + errorMat("materialType") = "部件" + errorMat("materialName") = "" + errorMat("materialCode") = "" + errorMat("materialQty") = 0 + errorMat("remarks") = "系统错误: " & Err.Description +``` + +**流程**: +``` +错误发生 → 构造错误对象 → 返回部分信息 → 用户看到部分结果 +``` + +--- + +#### 3. 仅警告 (Warning Only) + +**适用场景**: 映射值缺失、预处理警告 + +```vba +' M05_PreProcessor.bas +Else + ' 记录警告但继续使用原始值 + g_Logger.Record rowIdx, "M05.PreProcessor", "Mapping Warning", _ + "Value not found in mapping table: " & keyName & "=" & originalValue, match.Value +End If +' 继续处理,使用原始值 +``` + +**流程**: +``` +检测问题 → 记录警告 → 使用原始值 → 继续正常流程 +``` + +--- + +### 策略对比 + +| 策略 | 严重级别 | 结果处理 | 用户体验 | 适用场景 | +|------|----------|----------|----------|----------| +| 继续处理 | 🔴 高 | 跳过当前记录 | 部分数据缺失 | 语法/系统/解析错误 | +| 优雅降级 | 🟡 中 | 返回部分数据 | 看到错误标记 | 组件/物料提取失败 | +| 仅警告 | 🟢 低 | 使用原始值 | 无明显影响 | 映射值缺失 | + +--- + +## 错误报告生成 + +### clsErrorLogger.PrintReport 方法 + +```mermaid +flowchart TD + Start[PrintReport] --> CheckCount{检查错误数量} + + CheckCount -->|0个错误| Exit[退出, 不生成报告] + CheckCount -->|有错误| CreateSheet[创建新工作表] + + CreateSheet --> SetName[设置名称:
错误报告_hhmmss] + + SetName --> WriteHeader[写入表头] + + WriteHeader --> FormatHeader[格式化表头:
粗体+红色背景] + + FormatHeader --> PrepareArray[准备输出数组] + + PrepareArray --> LoopErrors[遍历错误集合] + + LoopErrors --> PopulateArray[填充数组数据] + + PopulateArray --> CheckEnd{还有错误?} + + CheckEnd -->|是| LoopErrors + CheckEnd -->|否| WriteData[批量写入数据] + + WriteData --> AutoFit[自动调整列宽] + + AutoFit --> End[结束] + + style CheckCount fill:#fff9c4 + style Exit fill:#c8e6c9 + style FormatHeader fill:#ffe0b2 + style End fill:#e8f5e9 +``` + +### 错误报告结构 + +```mermaid +graph TB + subgraph "错误报告工作表" + Header[第1行: 表头
红色背景+粗体] + Data[第2行-N: 数据] + end + + subgraph "列结构" + ColA[列A: 原表行号] + ColB[列B: 来源模块] + ColC[列C: 错误类型] + ColD[列D: 详细描述] + ColE[列E: 原始数据] + end + + subgraph "示例数据" + Row2[
125M03.ParseAtomSyntaxErrorNo = or != foundazxsA0
] + Row3[
138M03.ConflictLogicConflictMutually Exclusiveazxs=径向 AND azxs=下轴向
] + end + + Header --> ColA & ColB & ColC & ColD & ColE + Data --> Row2 & Row3 + + style Header fill:#ffcdd2 + style Row2 fill:#fafafa + style Row3 fill:#fafafa +``` + +### 代码实现 + +```vba +Public Sub PrintReport(targetWb As Workbook) + If pErrors.count = 0 Then Exit Sub + + ' 1. 创建新工作表 + Dim ws As Worksheet + Set ws = targetWb.Worksheets.Add(After:=targetWb.Worksheets(targetWb.Worksheets.count)) + ws.Name = "错误报告_" & Format(Now, "hhmmss") + + ' 2. 写入表头(红色背景,粗体) + ws.Range("A1:E1").Value = Array("原表行号", "来源模块", "错误类型", "详细描述", "原始数据") + ws.Range("A1:E1").Font.Bold = True + ws.Range("A1:E1").Interior.Color = RGB(255, 200, 200) + + ' 3. 准备输出数组(批量写入提高性能) + Dim arrOutput() As Variant + ReDim arrOutput(1 To pErrors.count, 1 To 5) + + Dim i As Long + Dim vItem As Variant + + For i = 1 To pErrors.count + vItem = pErrors(i) + arrOutput(i, 1) = vItem(0) ' 行号 + arrOutput(i, 2) = vItem(1) ' 来源模块 + arrOutput(i, 3) = vItem(2) ' 错误类型 + arrOutput(i, 4) = vItem(3) ' 描述 + arrOutput(i, 5) = vItem(4) ' 上下文 + Next i + + ' 4. 批量写入数据 + ws.Range("A2").Resize(UBound(arrOutput, 1), 5).Value = arrOutput + + ' 5. 自动调整列宽 + ws.Columns.AutoFit +End Sub +``` + +### 报告生成调用 + +```vba +' M01_Main.bas - BOM转换系统 +If logger.HasErrors Then + logger.PrintReport ActiveWorkbook + MsgBox "转换完成,但发现部分数据存在逻辑冲突,已生成错误报告。", vbExclamation +End If + +' M09_BOMExtractor.bas - BOM提取系统 +If g_Logger.HasErrors Then + g_Logger.PrintReport ActiveWorkbook + result = "BOM提取完成,但发现部分错误,已生成错误报告。" +Else + result = "BOM提取成功完成!" +End If +``` + +--- + +## 最佳实践 + +### 1. 一致的日志记录器初始化 + +所有可能产生错误的模块都遵循相同的初始化模式: + +```vba +' 模块级别声明 +Private g_Logger As clsErrorLogger + +' 公共初始化方法 +Public Sub Init[ModuleName](logger As clsErrorLogger) + Set g_Logger = logger +End Sub +``` + +**优点**: +- 统一的接口 +- 依赖注入模式 +- 易于测试和维护 + +--- + +### 2. 结构化的错误信息 + +每条错误记录都包含5个关键信息: + +| 字段 | 类型 | 用途 | 示例 | +|------|------|------|------| +| 行号 | Long | 定位Excel行 | 125 | +| 来源模块 | String | 定位代码位置 | "M03.ParseAtom" | +| 错误类型 | String | 错误分类 | "SyntaxError" | +| 详细描述 | String | 人类可读的描述 | "No = or != found" | +| 原始数据 | String | 调试上下文 | "azxsA0" | + +--- + +### 3. 防御性编程 + +**使用 `Nothing` 检查**: +```vba +If Not g_Logger Is Nothing Then + g_Logger.Record 0, "M06.ParseProductModel", "SystemError", _ + "解析过程发生错误: " & Err.Description, modelString +End If +``` + +**优点**: 即使日志记录器未初始化也不会崩溃 + +--- + +### 4. 延迟绑定避免依赖 + +```vba +' 使用 CreateObject 而不是 New +Set params = CreateObject("Scripting.Dictionary") +Set errorMat = CreateObject("Scripting.Dictionary") +``` + +**优点**: +- 无需添加外部引用 +- 提高兼容性 +- 减少部署问题 + +--- + +### 5. 批量操作优化 + +错误报告使用数组批量写入: + +```vba +' 准备数组 +ReDim arrOutput(1 To pErrors.count, 1 To 5) + +' 填充数组 +For i = 1 To pErrors.count + arrOutput(i, 1) = ... +Next i + +' 一次性写入 +ws.Range("A2").Resize(UBound(arrOutput, 1), 5).Value = arrOutput +``` + +**优点**: 比逐单元格写入快10-100倍 + +--- + +### 6. 用户友好的错误通知 + +```vba +If logger.HasErrors Then + logger.PrintReport ActiveWorkbook + MsgBox "转换完成,但发现部分数据存在逻辑冲突,已生成错误报告。", _ + vbExclamation, "处理完成" +End If +``` + +**要点**: +- 明确告知有错误 +- 说明已生成报告 +- 使用合适的图标类型 + +--- + +### 7. 错误级别分类 + +使用统一的错误类型标识: + +```vba +' 致命错误 - 红色 +"SystemError" +"SyntaxError" +"ModelParseError" + +' 警告 - 黄色 +"LogicConflict" +"BOMMatchError" +"ValidationError" + +' 信息 - 绿色 +"MappingWarning" +``` + +--- + +### 8. 上下文信息保留 + +始终记录导致错误的原始数据: + +```vba +g_Logger.Record rowIdx, "M03.ParseAtom", "Syntax Error", _ + "No = or != found", strAtom ' 保留原始数据 +``` + +**优点**: 便于后续调试和修复 + +--- + +## 测试覆盖 + +### M99_TestRunner.bas 中的错误测试 + +```mermaid +graph TD + subgraph "错误测试用例" + T1[Test_LogicConflict01
相等与不等冲突] + T2[Test_LogicConflict02
互斥值冲突] + T3[Test_SysError01
空条件处理] + T4[Test_PP_MissingValue
映射值缺失] + end + + subgraph "验证内容" + V1[错误被正确记录] + V2[返回Nothing/空值] + V3[处理继续不中断] + V4[错误报告正确生成] + end + + T1 --> V1 & V2 & V3 + T2 --> V1 & V2 & V3 + T3 --> V1 & V2 & V3 + T4 --> V1 & V3 & V4 + + style T1 fill:#ffe0b2 + style T2 fill:#ffe0b2 + style T3 fill:#ffcdd2 + style T4 fill:#c8e6c9 +``` + +### 测试示例 + +**逻辑冲突测试** +```vba +Public Sub Test_LogicConflict01() + ' 测试: azxs=1 AND azxs!=1 + Dim result As Collection + Set result = M03_Logic.ParseRule("azxs=1 AND azxs!=1", 10) + + ' 验证: 应该返回Nothing并记录错误 + Assert result Is Nothing, "应该检测到相等与不等冲突" +End Sub +``` + +**映射值缺失测试** +```vba +Public Sub Test_PP_MissingValue() + ' 测试: azxs值未在映射表中 + Dim result As String + result = M05_PreProcessor.PreprocessCondition("azxs=INVALID", "接头", 10) + + ' 验证: 应该记录警告但继续处理 + Assert result <> "", "即使映射缺失也应返回结果" +End Sub +``` + +--- + +## 快速参考 + +### 错误处理常用代码片段 + +#### 1. 初始化日志记录器 + +```vba +' 在主模块中 +Dim logger As New clsErrorLogger + +' 传递给子模块 +M03_Logic.InitLogic logger +M05_PreProcessor.InitPreProcessor logger, wsMapping +``` + +#### 2. 记录错误 + +```vba +' 完整格式 +g_Logger.Record rowIdx, "Module.Function", "ErrorType", "Description", "Context" + +' 示例 +g_Logger.Record 125, "M03.ParseAtom", "Syntax Error", _ + "No = or != found", "azxsA0" +``` + +#### 3. 检查并报告错误 + +```vba +If logger.HasErrors Then + logger.PrintReport ActiveWorkbook + MsgBox "处理完成,但发现错误。", vbExclamation +End If +``` + +#### 4. 标准错误处理器 + +```vba +ErrorHandler: + If Not g_Logger Is Nothing Then + g_Logger.Record rowIdx, "Module.Function", "SystemError", _ + Err.Description, contextData + End If + Set FunctionResult = Nothing +``` + +--- + +### 错误类型速查表 + +| 类型标识 | 显示名称 | 严重级别 | 通用模块 | +|----------|----------|----------|----------| +| `SystemError` | System Error | 🔴 高 | 所有模块 | +| `System Error` | System Error | 🔴 高 | M03_Logic | +| `SyntaxError` | Syntax Error | 🔴 高 | M03_Logic | +| `LogicConflict` | Logic Conflict | 🟡 中 | M03_Logic | +| `MappingWarning` | Mapping Warning | 🟢 低 | M05_PreProcessor | +| `ModelParseError` | Model Parse Error | 🔴 高 | M06_ModelParser | +| `BOMMatchError` | BOM Match Error | 🟡 中 | M07_BOMMatcher, M09_BOMExtractor | +| `ValidationError` | Validation Error | 🟡 中 | M08_ComponentProcessor | + +--- + +### 错误报告格式 + +**工作表名称**: `错误报告_hhmmss` (例如: `错误报告_143025`) + +**列结构**: + +| 列 | 宽度 | 对齐 | 说明 | +|----|------|------|------| +| A | 自动 | 左对齐 | 原表行号 | +| B | 自动 | 左对齐 | 来源模块 | +| C | 自动 | 左对齐 | 错误类型 | +| D | 自动 | 左对齐 | 详细描述 | +| E | 自动 | 左对齐 | 原始数据 | + +**格式**: +- 第1行: 粗体 + 红色背景 (RGB 255, 200, 200) +- 数据行: 默认格式 +- 列宽: 自动调整 + +--- + +### 相关文档 + +- [RunBOMExtraction_运行机制详解.md](./RunBOMExtraction_运行机制详解.md) - BOM提取系统文档 +- [M03_Logic_Algorithm.md](./M03_Logic_Algorithm.md) - 条件解析算法详解 +- [Test_PP_06_FullIntegration_流程详解.md](./Test_PP_06_FullIntegration_流程详解.md) - 预处理系统集成测试 +- [CLAUDE.md](../CLAUDE.md) - 项目整体说明 + +--- + +**文档版本**: 1.0 +**最后更新**: 2026-02-12 +**作者**: Claude Code +**状态**: 初稿完成 +**审核**: 待审核