Files
AutoBOM/docs/错误处理机制详解.md
Misaka_Company 68798920d6
All checks were successful
NTFY Notification / notify (push) Successful in 3s
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 <noreply@anthropic.com>
2026-02-12 14:35:30 +08:00

1204 lines
30 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 错误处理机制详解
## 目录
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[下一个错误<br/>再次停止]
end
subgraph "AutoBOM错误处理"
A2[遇到错误] --> B2[记录错误]
B2 --> C2[继续处理]
C2 --> D2[处理完成]
D2 --> E2[一次性查看<br/>所有错误]
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<br/>错误日志记录器]
M01[M01_Main.bas<br/>主入口]
M03[M03_Logic.bas<br/>条件解析]
M05[M05_PreProcessor.bas<br/>预处理]
M06[M06_ModelParser.bas<br/>型号解析]
M07[M07_BOMMatcher.bas<br/>BOM匹配]
M08[M08_ComponentProcessor.bas<br/>部件处理]
M09[M09_BOMExtractor.bas<br/>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[系统错误<br/>SystemError]
Root --> Syn[语法错误<br/>SyntaxError]
Root --> Log[逻辑冲突<br/>LogicConflict]
Root --> Map[映射警告<br/>MappingWarning]
Root --> Mod[型号解析错误<br/>ModelParseError]
Root --> Mat[BOM匹配错误<br/>BOMMatchError]
Root --> Val[验证错误<br/>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: 行号<br/>RowIndex]
B[1: 来源模块<br/>SourceFunc]
C[2: 错误类型<br/>ErrorType]
D[3: 详细描述<br/>Description]
E[4: 原始数据<br/>Context]
end
subgraph "示例"
F[<table><tr><td>125</td></tr><tr><td>M03.ParseAtom</td></tr><tr><td>SyntaxError</td></tr><tr><td>No = or != found</td></tr><tr><td>azxsA0</td></tr></table>]
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<br/>未找到匹配]
MultiMatch --> LogMulti[记录: BOMMatchError<br/>多重匹配]
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<br/>无效组合]
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[继续处理<br/>Continue Processing]
A --> C[优雅降级<br/>Graceful Degradation]
A --> D[仅警告<br/>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[设置名称:<br/>错误报告_hhmmss]
SetName --> WriteHeader[写入表头]
WriteHeader --> FormatHeader[格式化表头:<br/>粗体+红色背景]
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行: 表头<br/>红色背景+粗体]
Data[第2行-N: 数据]
end
subgraph "列结构"
ColA[列A: 原表行号]
ColB[列B: 来源模块]
ColC[列C: 错误类型]
ColD[列D: 详细描述]
ColE[列E: 原始数据]
end
subgraph "示例数据"
Row2[<table><tr><td>125</td><td>M03.ParseAtom</td><td>SyntaxError</td><td>No = or != found</td><td>azxsA0</td></tr></table>]
Row3[<table><tr><td>138</td><td>M03.Conflict</td><td>LogicConflict</td><td>Mutually Exclusive</td><td>azxs=径向 AND azxs=下轴向</td></tr></table>]
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<br/>相等与不等冲突]
T2[Test_LogicConflict02<br/>互斥值冲突]
T3[Test_SysError01<br/>空条件处理]
T4[Test_PP_MissingValue<br/>映射值缺失]
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
**状态**: 初稿完成
**审核**: 待审核