diff --git a/docs/RunBOMExtraction_运行机制详解.md b/docs/RunBOMExtraction_运行机制详解.md
index 2a97639..c9d081d 100644
--- a/docs/RunBOMExtraction_运行机制详解.md
+++ b/docs/RunBOMExtraction_运行机制详解.md
@@ -8,9 +8,10 @@
4. [核心流程](#核心流程)
5. [模块交互时序图](#模块交互时序图)
6. [关键模块详解](#关键模块详解)
-7. [数据结构](#数据结构)
-8. [错误处理机制](#错误处理机制)
-9. [使用示例](#使用示例)
+7. [两阶段验证架构详解](#两阶段验证架构详解)
+8. [数据结构](#数据结构)
+9. [错误处理机制](#错误处理机制)
+10. [使用示例](#使用示例)
---
@@ -20,7 +21,7 @@
### 主要功能
-- **参数提取**: 从复杂的产品型号字符串中解析出7个关键参数
+- **参数提取**: 从复杂的产品型号字符串中解析出8个关键参数
- **智能匹配**: 根据参数在BOM库中查找对应的物料
- **特殊处理**: 针对"部件"类物料的特殊逻辑(组件与子组件的选择)
- **结果输出**: 生成格式化的BOM提取结果表
@@ -28,7 +29,8 @@
### 设计特点
- **模块化**: 各功能模块职责清晰,易于维护
-- **容错性**: 完善的错误处理机制,不中断处理流程
+- **两阶段验证**: 将匹配收集与验证分离,支持跨工作表验证规则
+- **容错性**: 完善的错误处理机制,区分错误(阻塞)和警告(非阻塞)
- **灵活性**: 支持通配符匹配、负向匹配等多种匹配规则
- **可扩展**: 易于添加新的物料类型和匹配规则
@@ -93,6 +95,10 @@ graph TB
## 数据流图
+**关键架构:两阶段验证(Two-Phase Validation)**
+
+BOM提取系统采用**两阶段验证架构**,将匹配结果的收集与验证分离:
+
```mermaid
flowchart LR
subgraph "输入阶段"
@@ -100,44 +106,58 @@ flowchart LR
end
subgraph "解析阶段"
- B --> C1[azxs: A0→径向]
- B --> C2[bkxs: 531]
- B --> C3[gclj: G12]
- B --> C4[jycz: 3]
- B --> C5[lcfw: M04]
- B --> C6[fjgn: Y3]
- B --> C7[gcwj: 100]
+ B --> C0[提取表头
去除管道符后内容]
+ C0 --> C1[按.分割成段]
+ C1 --> C2[xh: YTHN]
+ C1 --> C3[gcwj: 100]
+ C1 --> C4[azxs: A0]
+ C1 --> C5[bkxs: 531]
+ C1 --> C6[gclj: G12
jycz: 3]
+ C1 --> C7[lcfw: M04]
+ C1 --> C8[fjgn: Y3]
end
- subgraph "匹配阶段"
- C1 & C2 & C3 & C4 & C5 & C6 --> D[M07_BOMMatcher
BOM匹配]
- D --> E1[接头匹配]
- D --> E2[弹性元件匹配]
- D --> E3[机芯匹配]
- D --> E4[部件匹配]
+ subgraph "Phase 1: 收集阶段(不记录错误)"
+ C2 & C3 & C4 & C5 & C6 & C7 & C8 --> D[遍历所有BOM库工作表]
+ D --> E1[接头工作表
MatchBOMRecord]
+ D --> E2[弹性元件工作表
MatchBOMRecord]
+ D --> E3[机芯工作表
MatchBOMRecord]
+ D --> E4[部件工作表
MatchBOMRecord + M08_ComponentProcessor]
+ E1 --> F1[存储匹配结果
不记录错误]
+ E2 --> F2[存储匹配结果
不记录错误]
+ E3 --> F3[存储匹配结果
不记录错误]
+ E4 --> F4[存储匹配结果
不记录错误]
end
- subgraph "特殊处理"
- E4 --> F{M08_ComponentProcessor
部件特殊处理}
- F -->|优先级1| G1[使用组件]
- F -->|优先级2| G2[使用子组件
接头+弹性元件]
+ subgraph "Phase 2: 验证阶段(跨工作表验证)"
+ F1 & F2 & F3 & F4 --> G[ValidateAllMatchResults
统一验证所有结果]
+ G --> G1{非特殊工作表
必须恰好1条}
+ G --> G2{部件/接头/弹性元件
特殊规则验证}
+ G1 --> H1[记录错误/警告]
+ G2 --> H1
end
- subgraph "输出阶段"
- G1 & G2 & E1 & E2 & E3 --> H[M09_BOMExtractor
结果汇总]
- H --> I[BOM提取结果表]
+ subgraph "Phase 3: 生成输出"
+ H1 --> I[收集验证通过的物料]
+ I --> J[BOM提取结果表]
end
style A fill:#ffebee
- style I fill:#e8f5e9
- style D fill:#fff3e0
- style F fill:#fce4ec
+ style J fill:#e8f5e9
+ style D fill:#e3f2fd
+ style G fill:#fff3e0
+ style F1 fill:#e8f5e9
+ style F2 fill:#e8f5e9
+ style F3 fill:#e8f5e9
+ style F4 fill:#e8f5e9
```
---
## 核心流程
+**关键架构:两阶段验证(Two-Phase Validation)**
+
```mermaid
flowchart TD
Start([开始: RunBOMExtraction]) --> Init[初始化
创建错误日志记录器]
@@ -156,30 +176,40 @@ flowchart TD
ParseModel --> ParseSuccess{解析成功?}
ParseSuccess -->|失败| LogParseError[记录解析错误
继续下一个型号]
- ParseSuccess -->|成功| ExtractParams[提取7个参数]
+ ParseSuccess -->|成功| ExtractParams[提取8个参数]
- ExtractParams --> MatchLoop{遍历物料类型}
+ ExtractParams --> Phase1[Phase 1: 收集匹配结果]
- MatchLoop --> MatchBOM[M07_BOMMatcher
匹配BOM记录]
+ Phase1 --> CollectLoop[遍历所有BOM库工作表]
+ CollectLoop --> MatchBOM[M07_BOMMatcher
匹配BOM记录]
+ MatchBOM --> IsComponent{是部件工作表?}
- MatchBOM --> MatchResult{匹配结果}
+ IsComponent -->|是| ProcessComp[M08_ComponentProcessor
处理部件特殊逻辑]
+ IsComponent -->|否| StoreResult[存储匹配结果
不记录错误]
+ ProcessComp --> StoreCompResult[存储部件结果
不记录错误]
- MatchResult -->|无匹配| LogNoMatch[记录:
未找到匹配物料]
- MatchResult -->|多重匹配| LogMultiMatch[记录:
找到多个匹配]
- MatchResult -->|唯一匹配| CheckType{物料类型?}
+ StoreResult --> NextSheet{还有工作表?}
+ StoreCompResult --> NextSheet
- CheckType -->|部件| ProcessComp[M08_ComponentProcessor
处理部件特殊逻辑]
- CheckType -->|其他| SaveMaterial[保存物料信息]
+ NextSheet -->|是| CollectLoop
+ NextSheet -->|否| Phase2[Phase 2: 验证匹配结果]
- ProcessComp --> ValidateComp{验证组件组合}
- ValidateComp -->|无效| LogInvalid[记录:
无效组合]
- ValidateComp -->|有效| SaveComp[保存组件/子组件]
+ Phase2 --> ValidateAll[ValidateAllMatchResults
跨工作表验证]
+ ValidateAll --> NonSpecial{验证非特殊工作表}
+ NonSpecial --> Special{验证部件/接头/弹性元件}
- SaveMaterial & SaveComp --> NextType{还有物料类型?}
- LogNoMatch & LogMultiMatch & LogInvalid --> NextType
+ Special --> HasErrors{有错误?}
+ HasErrors -->|是| RecordErrors[记录错误]
+ HasErrors -->|否| HasWarnings{有警告?}
- NextType -->|是| MatchLoop
- NextType -->|否| NextModel{还有型号?}
+ HasWarnings -->|是| RecordWarnings[记录警告]
+ HasWarnings -->|否| Phase3[Phase 3: 生成物料集合]
+ RecordErrors --> Phase3
+ RecordWarnings --> Phase3
+
+ Phase3 --> CollectMaterials[收集所有物料]
+ CollectMaterials --> GenerateRows[生成输出行]
+ GenerateRows --> NextModel{还有型号?}
LogParseError --> NextModel
@@ -200,18 +230,23 @@ flowchart TD
style ParseModel fill:#e1f5fe
style MatchBOM fill:#fff9c4
style ProcessComp fill:#f8bbd9
+ style Phase1 fill:#e3f2fd
+ style Phase2 fill:#fff3e0
+ style Phase3 fill:#e8f5e9
+ style ValidateAll fill:#ffe082
style Error1 fill:#ffcdd2
style Error2 fill:#ffcdd2
style LogParseError fill:#ffebee
- style LogNoMatch fill:#ffebee
- style LogMultiMatch fill:#ffebee
- style LogInvalid fill:#ffebee
+ style RecordErrors fill:#ffcdd2
+ style RecordWarnings fill:#fff9c4
```
---
## 模块交互时序图
+**关键架构:两阶段验证(Two-Phase Validation)**
+
```mermaid
sequenceDiagram
participant User as 用户
@@ -237,34 +272,51 @@ sequenceDiagram
alt 解析失败
M09->>Logger: 记录解析错误
else 解析成功
- loop 遍历每个物料类型工作表
- M09->>BOM: 读取物料类型工作表
- M09->>M07: BuildHeaderMapping(工作表)
- M07-->>M09: 返回列映射字典
+ Note over M09: Phase 1: 收集匹配结果(不记录错误)
- M09->>M07: MatchBOMRecord(工作表, 参数)
- M07->>M07: EvaluateCellCondition(每列)
+ loop 遍历每个BOM库工作表
+ M09->>BOM: 读取工作表
- alt 匹配失败
- M09->>Logger: 记录匹配失败
- else 多重匹配
- M09->>Logger: 记录多重匹配
- else 唯一匹配
- alt 物料类型 = "部件"
+ alt 工作表 = "部件"
+ M09->>M07: MatchBOMRecord(工作表, 参数)
+ M07-->>M09: 返回匹配结果
+
+ alt 匹配成功
M09->>M08: ProcessComponentRecord(行数据)
- M08->>M08: ValidateComponentCombination()
-
- alt 验证成功
- M08-->>M09: 返回组件/子组件
- else 验证失败
- M09->>Logger: 记录验证失败
- end
- else 其他物料类型
- M09->>M07: ExtractMaterialInfo(行数据)
- M07-->>M09: 返回物料信息
+ M08-->>M09: 返回组件/子组件
+ M09->>M09: 存储匹配结果(不记录错误)
end
+ else 其他工作表
+ M09->>M07: MatchBOMRecord(工作表, 参数)
+ M07-->>M09: 返回匹配结果
+ M09->>M09: 存储匹配结果(不记录错误)
end
end
+
+ Note over M09: Phase 2: 统一验证所有结果
+
+ M09->>M09: ValidateAllMatchResults(所有结果)
+
+ alt 验证非特殊工作表
+ M09->>M09: 检查rowCount = 1
+ alt rowCount != 1
+ M09->>Logger: 记录错误
+ end
+ end
+
+ alt 验证部件/接头/弹性元件
+ M09->>M09: 检查跨工作表冲突
+ alt 有冲突
+ M09->>Logger: 记录警告
+ end
+ alt 组合无效
+ M09->>Logger: 记录错误
+ end
+ end
+
+ Note over M09: Phase 3: 生成物料集合
+
+ M09->>M09: 收集所有验证通过的物料
end
end
@@ -313,17 +365,166 @@ End Sub
|--------|------|
| `RunBOMExtraction()` | 主流程控制函数 |
| `ProcessSingleModel()` | 处理单个产品型号 |
-| `MatchAllMaterialTypes()` | 匹配所有物料类型 |
+| `MatchAllMaterialTypesWithValidation()` | 匹配所有物料类型(两阶段验证) |
+| `ValidateAllMatchResults()` | 统一验证所有匹配结果(跨工作表规则) |
| `WriteExtractionResults()` | 输出提取结果 |
**处理流程**:
```
-初始化 → 验证输入 → 打开BOM库 → 循环处理型号 → 输出结果 → 清理资源
+初始化 → 验证输入 → 打开BOM库 → 循环处理型号(Phase 1收集→Phase 2验证→Phase 3生成) → 输出结果 → 清理资源
```
+**两阶段验证架构**:
+
+该模块实现了关键的**两阶段验证架构**,将匹配与验证分离:
+
+1. **Phase 1 - 收集阶段** (`MatchAllMaterialTypesWithValidation`):
+ - 遍历所有BOM库工作表
+ - 调用 `M07_BOMMatcher.MatchBOMRecord()` 获取匹配结果
+ - 对于"部件"工作表,额外调用 `M08_ComponentProcessor.ProcessComponentRecord()`
+ - **关键点:不记录任何错误**,仅收集原始匹配结果
+ - 存储每个工作表的:success、rowCount、rowNums、materials
+
+2. **Phase 2 - 验证阶段** (`ValidateAllMatchResults`):
+ - 统一验证所有收集到的匹配结果
+ - 应用跨工作表验证规则
+ - 区分错误(blocking)和警告(non-blocking)
+ - 记录所有错误和警告到Logger
+
+3. **Phase 3 - 生成阶段**:
+ - 根据验证结果生成最终物料集合
+ - 即使验证失败,也返回物料用于错误显示
+
---
-### 3. M06_ModelParser.bas - 型号解析器
+### 3. 两阶段验证架构详解
+
+#### 为什么需要两阶段验证?
+
+在BOM提取系统中,"部件"、"接头"、"弹性元件"三个工作表之间存在复杂的互斥和替代关系:
+
+- **部件表**可能返回:1个组件 或 1个接头+1个弹性元件
+- **接头表**可能返回:1个接头
+- **弹性元件表**可能返回:1个弹性元件
+
+如果立即记录错误,无法判断全局情况。例如:
+- 部件表返回了组件,但接头表也匹配到接头 → 这是冲突,应该警告而非错误
+- 部件表返回了接头+弹性元件,但独立表也匹配到 → 这是冲突,应该警告而非错误
+
+#### Phase 1: 收集阶段(不记录错误)
+
+**代码位置**: `M09_BOMExtractor.MatchAllMaterialTypesWithValidation()` (lines 387-541)
+
+**流程**:
+```vba
+For Each ws In bomWb.Worksheets
+ If ws.Name = "部件" Then
+ ' 1. 标准匹配
+ Set bomMatchResult = M07_BOMMatcher.MatchBOMRecord(ws, params)
+ ' 2. 部件特殊处理
+ Set componentMaterials = M08_ComponentProcessor.ProcessComponentRecord(...)
+ ' 3. 存储结果(不记录错误)
+ matchResult("success") = bomMatchResult("success")
+ matchResult("rowCount") = bomMatchResult("rowCount")
+ matchResult("materials") = componentMaterials
+ Else
+ ' 标准匹配
+ Set bomMatchResult = M07_BOMMatcher.MatchBOMRecord(ws, params)
+ ' 存储结果(不记录错误)
+ End If
+ resultsDict.Add ws.Name, matchResult
+Next ws
+```
+
+**关键点**:
+- 即使匹配失败(rowCount=0),也不记录错误
+- 即使多重匹配(rowCount>1),也不记录错误
+- 只存储原始数据供Phase 2使用
+
+#### Phase 2: 验证阶段(跨工作表验证)
+
+**代码位置**: `M09_BOMExtractor.ValidateAllMatchResults()` (lines 566-760)
+
+**验证规则**:
+
+##### 1. 基础规则(非特殊工作表)
+
+```
+非特殊工作表必须恰好匹配1条记录:
+- rowCount = 0 → 错误
+- rowCount = 1 → 正常
+- rowCount > 1 → 错误
+```
+
+特殊工作表列表:`["部件", "接头", "弹性元件"]`
+
+##### 2. 跨工作表规则(部件/接头/弹性元件)
+
+**情况A**: 部件表返回了组件(1个部件物料)
+```
+如果部件表返回了组件:
+ 接头表有匹配 → 警告:"存在[部件]物料,但[接头]工作表也匹配到X条记录,已忽略"
+ 弹性元件表有匹配 → 警告:"存在[部件]物料,但[弹性元件]工作表也匹配到X条记录,已忽略"
+```
+
+**情况B**: 部件表返回了子件(接头+弹性元件)
+```
+如果部件表返回了接头+弹性元件:
+ 接头表有匹配 → 警告:"[部件]工作表已返回接头,但[接头]工作表也匹配到X条记录,已忽略"
+ 弹性元件表有匹配 → 警告:"[部件]工作表已返回弹性元件,但[弹性元件]工作表也匹配到X条记录,已忽略"
+```
+
+**情况C**: 部件表没有返回物料
+```
+如果部件表rowCount=0:
+ 接头表=0 或 弹性元件表=0 → 错误:"部件、接头、弹性元件均未匹配或组合不完整"
+ 接头表>1 → 错误:"[接头]工作表匹配到X条记录"
+ 弹性元件表>1 → 错误:"[弹性元件]工作表匹配到X条记录"
+```
+
+**情况D**: 部件表多重匹配
+```
+部件表rowCount > 1 → 错误:"[部件]工作表匹配到X条记录"
+```
+
+##### 3. 错误与警告的区别
+
+| 类型 | 是否阻塞 | Logger方法 | 颜色 |
+|------|---------|-----------|------|
+| 错误 | 是 | `logger.Record()` | 红色 |
+| 警告 | 否 | `logger.RecordWarning()` | 黄色 |
+
+#### Phase 3: 生成阶段
+
+**代码位置**: `M09_BOMExtractor.MatchAllMaterialTypesWithValidation()` (lines 495-525)
+
+**流程**:
+```vba
+If validationResult("valid") Then
+ ' 验证通过:收集所有物料
+ For Each result In resultsDict
+ For Each mat In result("materials")
+ allMaterials.Add mat
+ Next mat
+ Next result
+Else
+ ' 验证失败:仍然收集物料(用于错误显示)
+ For Each result In resultsDict
+ For Each mat In result("materials")
+ allMaterials.Add mat
+ Next mat
+ Next result
+End If
+```
+
+**关键点**:
+- 即使验证失败,仍然返回所有物料
+- 错误信息会显示在输出行的"提取备注"列
+- 用户可以看到匹配到什么物料以及为什么出错
+
+---
+
+### 4. M06_ModelParser.bas - 型号解析器
**职责**: 从产品型号字符串中提取参数
@@ -338,25 +539,26 @@ End Sub
| 参数 | 描述 | 示例值 | 转换规则 |
|------|------|--------|----------|
-| azxs | 安装形式 | A0 | A0/AT/AH → 径向 |
+| xh | 型号 | YTHN | 从YTHN-100提取横线前部分 |
+| gcwj | 公称外径 | 100 | 从YTHN-100提取横线后数字 |
+| azxs | 安装形式 | A0 | 直接提取,无转换 |
| bkxs | 表壳形式 | 531 | 直接提取 |
-| gclj | 过程连接 | G12 | 从G123提取G+首位 |
+| gclj | 过程连接 | G12 | 从G123去除末位 |
| jycz | 接液材质 | 3 | 从G123提取末位 |
| lcfw | 量程范围 | M04 | 直接提取 |
-| fjgn | 附加功能 | Y3 | 直接提取 |
-| gcwj | 公称外径 | 100 | 从YTHN-100提取 |
+| fjgn | 附加功能 | Y3 | 直接提取(多段用逗号连接) |
**核心函数**:
```vba
Public Function ParseProductModel(ByVal modelStr As String) As Object
- ' 返回包含7个参数的字典
+ ' 返回包含8个参数的字典
End Function
```
---
-### 4. M07_BOMMatcher.bas - BOM匹配器
+### 5. M07_BOMMatcher.bas - BOM匹配器
**职责**: 根据参数在BOM库中查找匹配记录
@@ -397,7 +599,7 @@ NEXT
---
-### 5. M08_ComponentProcessor.bas - 部件处理器
+### 6. M08_ComponentProcessor.bas - 部件处理器
**职责**: 处理"部件"类物料的特殊逻辑
@@ -469,7 +671,7 @@ flowchart TD
| 列名 | 说明 | 示例值 |
|------|------|--------|
-| azxs | 安装形式 | 径向 |
+| azxs | 安装形式 | A0 |
| bkxs | 表壳形式 | 531 |
| gclj | 过程连接 | G12 |
| jycz | 接液材质 | 3 |
@@ -499,7 +701,7 @@ flowchart TD
| 列号 | 列名 | 说明 | 示例值 |
|------|------|------|--------|
| 1 | 原始产品型号 | 输入的完整型号 | YTHN-100...Y3 |
-| 2 | azxs | 安装形式 | 径向 |
+| 2 | azxs | 安装形式 | A0 |
| 3 | bkxs | 表壳形式 | 531 |
| 4 | gclj | 过程连接 | G12 |
| 5 | jycz | 接液材质 | 3 |
@@ -523,13 +725,14 @@ flowchart TD
**参数字典** (M06_ModelParser输出):
```vba
Dictionary {
- "azxs": "径向",
+ "xh": "YTHN",
+ "gcwj": "100",
+ "azxs": "A0",
"bkxs": "531",
"gclj": "G12",
"jycz": "3",
"lcfw": "M04",
- "fjgn": "Y3",
- "gcwj": "100"
+ "fjgn": "Y3"
}
```
@@ -579,6 +782,53 @@ Collection {
| 无匹配记录 | 警告 | 记录错误,继续 | 未找到匹配物料 |
| 多重匹配 | 警告 | 记录错误,继续 | 找到多个匹配 |
| 组件组合无效 | 警告 | 记录错误,继续 | 组件与子组件混用 |
+| 跨工作表冲突 | 警告 | 记录警告,继续 | 部件表与接头表同时匹配 |
+
+---
+
+### 两阶段验证错误处理
+
+#### Phase 1: 收集阶段(不记录错误)
+
+在收集阶段,系统**不记录任何错误**,原因如下:
+
+1. **需要全局信息**: 判断是否为错误需要看所有工作表的匹配结果
+2. **避免误报**: 部件表返回组件时,接头表也匹配是警告而非错误
+3. **优先级处理**: 部件表的返回优先级高于独立表
+
+示例:
+```vba
+' Phase 1 收集阶段 - 不记录错误
+Set matchResult = M07_BOMMatcher.MatchBOMRecord(ws, params)
+' 即使 matchResult("rowCount") = 0 或 > 1,也不记录错误
+resultsDict.Add ws.Name, matchResult
+```
+
+#### Phase 2: 验证阶段(记录错误和警告)
+
+在验证阶段,系统根据**跨工作表规则**统一验证:
+
+**错误示例**(阻塞,红色):
+```
+[接头] 未匹配到记录
+[机芯] 匹配到2条记录
+部件、接头、弹性元件均未匹配或组合不完整
+```
+
+**警告示例**(非阻塞,黄色):
+```
+存在[部件]物料,但[接头]工作表也匹配到1条记录,已忽略
+[部件]工作表已返回弹性元件,但[弹性元件]工作表也匹配到1条记录,已忽略
+```
+
+**Logger调用**:
+```vba
+' 记录错误(阻塞)
+logger.Record 0, "M09.ValidateAllMatchResults", "BOMMatchError", errorMessage, ""
+
+' 记录警告(非阻塞)
+logger.RecordWarning 0, "M09.ValidateAllMatchResults", "ComponentConflict", warningMessage, ""
+```
---
@@ -587,41 +837,59 @@ Collection {
```mermaid
flowchart LR
subgraph "错误检测"
- A[检测到错误]
+ A[检测到错误/警告]
+ end
+
+ subgraph "两阶段验证"
+ B1[Phase 1: 收集
不记录错误]
+ B2[Phase 2: 验证
记录错误和警告]
end
subgraph "错误记录"
- B[clsErrorLogger.LogError]
+ C[clsErrorLogger]
+ C1[logger.Record
错误(红色)]
+ C2[logger.RecordWarning
警告(黄色)]
end
subgraph "错误信息"
- C[错误类型]
- D[上下文信息]
- E[时间戳]
+ D[错误类型]
+ E[上下文信息]
+ F[时间戳]
end
subgraph "错误输出"
- F[第12列: 提取备注]
- G[红色高亮显示]
+ G[第12列: 提取备注]
+ H[红色高亮(错误)]
+ I[黄色高亮(警告)]
end
- A --> B
- B --> C
- B --> D
- B --> E
- C & D & E --> F
- F --> G
+ A --> B1
+ B1 --> B2
+ B2 --> C
+ C --> C1
+ C --> C2
+ C1 & C2 --> D & E & F
+ D & E & F --> G
+ G --> H
+ G --> I
style A fill:#ffebee
- style B fill:#fff3e0
- style F fill:#e8f5e9
- style G fill:#ffcdd2
+ style B1 fill:#e3f2fd
+ style B2 fill:#fff3e0
+ style C fill:#fff9c4
+ style G fill:#e8f5e9
+ style H fill:#ffcdd2
+ style I fill:#fff59d
```
**clsErrorLogger方法**:
```vba
-logger.LogError "ERROR_TYPE", "详细错误信息", "上下文数据"
+' 记录错误(阻塞)
+logger.Record rowIndex, sourceModule, errorType, description, context
+
+' 记录警告(非阻塞)
+logger.RecordWarning rowIndex, sourceModule, warningType, description, context
```
**错误信息格式**:
@@ -639,6 +907,7 @@ logger.LogError "ERROR_TYPE", "详细错误信息", "上下文数据"
2. **错误累积**: 所有错误都记录在日志中
3. **最终报告**: 处理完成后显示汇总报告
4. **部分成功**: 部分记录成功时仍然输出结果
+5. **两阶段验证**: Phase 1不中断,Phase 2统一验证
---
@@ -663,9 +932,9 @@ End Sub
| 原始产品型号 | azxs | bkxs | gclj | jycz | lcfw | fjgn | 物料类型 | 物料名称 | 物料编码 | 数量 | 备注 |
|--------------|------|------|------|------|------|------|----------|----------|----------|------|------|
-| YTHN-100...Y3 | 径向 | 531 | G12 | 3 | M04 | Y3 | 接头 | 卡套式接头 | JT-001 | 1 | |
-| YTHN-100...Y3 | 径向 | 531 | G12 | 3 | M04 | Y3 | 弹性元件 | 膜片 | MH-002 | 1 | |
-| YTHN-100...Y3 | 径向 | 531 | G12 | 3 | M04 | Y3 | 机芯 | 齿轮机构 | JX-003 | 1 | |
+| YTHN-100...Y3 | A0 | 531 | G12 | 3 | M04 | Y3 | 接头 | 卡套式接头 | JT-001 | 1 | |
+| YTHN-100...Y3 | A0 | 531 | G12 | 3 | M04 | Y3 | 弹性元件 | 膜片 | MH-002 | 1 | |
+| YTHN-100...Y3 | A0 | 531 | G12 | 3 | M04 | Y3 | 机芯 | 齿轮机构 | JX-003 | 1 | |
---
@@ -677,7 +946,7 @@ End Sub
| azxs | bkxs | ... | 物料编码 | 数量A | 物料编码B | 数量B | 物料编码C | 数量C |
|------|------|-----|----------|-------|-----------|-------|-----------|-------|
-| 径向 | 531 | ... | BJ-001 | 1 | JT-002 | 2 | MH-003 | 1 |
+| A0 | 531 | ... | BJ-001 | 1 | JT-002 | 2 | MH-003 | 1 |
**假设**: 组件A (BJ-001) 缺货
@@ -730,7 +999,8 @@ INVALID.MODEL.FORMAT
| M01_Main | `RunBOMExtraction()` | 系统入口 |
| M09_BOMExtractor | `RunBOMExtraction()` | 主流程控制 |
| M09_BOMExtractor | `ProcessSingleModel()` | 处理单个型号 |
-| M09_BOMExtractor | `MatchAllMaterialTypes()` | 匹配所有物料类型 |
+| M09_BOMExtractor | `MatchAllMaterialTypesWithValidation()` | 匹配所有物料类型(两阶段验证) |
+| M09_BOMExtractor | `ValidateAllMatchResults()` | 统一验证所有匹配结果(跨工作表规则) |
| M06_ModelParser | `ParseProductModel()` | 解析型号参数 |
| M07_BOMMatcher | `MatchBOMRecord()` | 匹配BOM记录 |
| M07_BOMMatcher | `BuildHeaderMapping()` | 构建列映射 |
@@ -758,7 +1028,11 @@ INVALID.MODEL.FORMAT
---
-**文档版本**: 1.0
+**文档版本**: 2.0
**最后更新**: 2026-02-12
**作者**: Claude Code
-**状态**: 初稿完成
+**状态**: 更新完成 - 新增两阶段验证架构文档
+
+**版本历史**:
+- v2.0 (2026-02-12): 重大更新 - 添加两阶段验证架构详解,更新数据流图、核心流程图、模块交互时序图
+- v1.0 (2026-02-12): 初稿完成