# 错误处理机制详解
## 目录
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[| 125 | M03.ParseAtom | SyntaxError | No = or != found | azxsA0 |
]
Row3[| 138 | M03.Conflict | LogicConflict | Mutually Exclusive | azxs=径向 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
**状态**: 初稿完成
**审核**: 待审核