feat: add preprocessing with value mapping to BOM Extraction System
All checks were successful
NTFY Notification / notify (push) Successful in 4s

Add a preprocessing step to the BOM Extraction System to enhance parameter
extraction with mapping values from "对照表" worksheet. For azxs (安装形式)
and lcfw (量程范围), the system now stores both the raw parsed value AND the
mapped value from the lookup table, enabling flexible dual-value matching.

Changes:
- Create M06A_Mapper.bas: New module for value mapping
  - Load azxs/lcfw mappings from "对照表" worksheet
  - Return dual-value format "raw,mapped" (e.g., "A0,径向")
  - Support graceful degradation if "对照表" not found
  - Define constants locally to avoid VBA cross-module reference issues

- Modify M06_ModelParser.bas:
  - Extract raw parameter values first
  - Apply mapping via M06A_Mapper if initialized
  - Store dual values for azxs and lcfw parameters

- Modify M07_BOMMatcher.bas:
  - Update EvaluateCellCondition() to support dual-value matching
  - Split by comma and check if ANY value matches
  - Backward compatible with single-value parameters

- Modify M09_BOMExtractor.bas:
  - Initialize M06A_Mapper during RunBOMExtraction()
  - Add WorksheetExists() helper function
  - Log warning if "对照表" worksheet not found
  - Define MAPPING_SHEET_NAME constant locally

- Modify M04_Config.bas:
  - Add mapping table configuration constants
  - MAPPING_SHEET_NAME, MAPPING_COL_LCFW_KEY, etc.

- Update CLAUDE.md:
  - Document new M06A_Mapper module
  - Update data flow diagram with mapping step
  - Document dual-value matching behavior
  - Update system architecture diagram

- Update docs/RunBOMExtraction_运行机制详解.md:
  - Add M06A_Mapper to all diagrams and documentation
  - Add detailed value mapping section
  - Update sequence diagrams with mapping flow
  - Update parameter examples with dual-value format
  - Bump documentation version to 3.0

Example:
  Input:  Product model "YTHN-100.A0.531.G123.M04.Y3"
  Parse:  azxs="A0", lcfw="M04"
  Map:    azxs="A0,径向", lcfw="M04,高压"
  Match:  BOM库 with azxs="径向" OR "A0" → MATCH

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-02-12 17:52:03 +08:00
parent 21f5f1c299
commit 1d5bad86f7
7 changed files with 626 additions and 47 deletions

View File

@@ -50,6 +50,7 @@ graph TB
subgraph "处理层"
M06[M06_ModelParser.bas<br/>型号解析器]
M06A[M06A_Mapper.bas<br/>值映射器]
M07[M07_BOMMatcher.bas<br/>BOM匹配器]
M08[M08_ComponentProcessor.bas<br/>部件处理器]
end
@@ -61,6 +62,7 @@ graph TB
subgraph "数据源"
Input[产品型号工作表]
Mapping[对照表工作表]
BOMLib[BOM库.xlsx]
end
@@ -70,12 +72,15 @@ graph TB
M01 --> M09
M09 --> M06
M09 --> M06A
M09 --> M07
M09 --> M08
M09 --> M04
M09 --> Logger
M06 --> Input
M06A --> Mapping
M06 --> M06A
M07 --> BOMLib
M08 --> BOMLib
@@ -84,9 +89,11 @@ graph TB
style M01 fill:#e1f5ff
style M09 fill:#fff4e1
style M06 fill:#e8f5e9
style M06A fill:#f8bbd9
style M07 fill:#e8f5e9
style M08 fill:#e8f5e9
style Input fill:#f3e5f5
style Mapping fill:#fff9c4
style BOMLib fill:#f3e5f5
style Output fill:#f3e5f5
```
@@ -95,9 +102,9 @@ graph TB
## 数据流图
**关键架构两阶段验证Two-Phase Validation**
**关键架构两阶段验证Two-Phase Validation+ 值映射Value Mapping**
BOM提取系统采用**两阶段验证架构**,将匹配结果的收集与验证分离:
BOM提取系统采用**两阶段验证架构**,将匹配结果的收集与验证分离,并集成**值映射功能**以支持灵活的参数匹配
```mermaid
flowchart LR
@@ -117,10 +124,17 @@ flowchart LR
C1 --> C8[fjgn: Y3]
end
subgraph "值映射阶段"
C4 --> M1[M06A_Mapper.MapAzxs<br/>A0 → A0,径向]
C7 --> M2[M06A_Mapper.MapLcfw<br/>M04 → M04,高压]
M1 --> P1[azxs: A0,径向<br/>双值格式]
M2 --> P2[lcfw: M04,高压<br/>双值格式]
end
subgraph "Phase 1: 收集阶段(不记录错误)"
C2 & C3 & C4 & C5 & C6 & C7 & C8 --> D[遍历所有BOM库工作表]
D --> E1[接头工作表<br/>MatchBOMRecord]
D --> E2[弹性元件工作表<br/>MatchBOMRecord]
C2 & C3 & P1 & C5 & C6 & P2 & C8 --> D[遍历所有BOM库工作表]
D --> E1[接头工作表<br/>MatchBOMRecord<br/>支持双值匹配]
D --> E2[弹性元件工作表<br/>MatchBOMRecord<br/>支持双值匹配]
D --> E3[机芯工作表<br/>MatchBOMRecord]
D --> E4[部件工作表<br/>MatchBOMRecord + M08_ComponentProcessor]
E1 --> F1[存储匹配结果<br/>不记录错误]
@@ -150,13 +164,17 @@ flowchart LR
style F2 fill:#e8f5e9
style F3 fill:#e8f5e9
style F4 fill:#e8f5e9
style M1 fill:#f8bbd9
style M2 fill:#f8bbd9
style P1 fill:#fff9c4
style P2 fill:#fff9c4
```
---
## 核心流程
**关键架构两阶段验证Two-Phase Validation**
**关键架构两阶段验证Two-Phase Validation+ 值映射Value Mapping**
```mermaid
flowchart TD
@@ -170,18 +188,28 @@ flowchart TD
CheckBOM -->|不存在| Error2[返回错误:<br/>未找到BOM库.xlsx]
CheckBOM -->|存在| OpenBOM[打开BOM库工作簿]
OpenBOM --> LoopStart{遍历每个产品型号}
OpenBOM --> InitModules[初始化各模块<br/>M06_ModelParser<br/>M07_BOMMatcher<br/>M08_ComponentProcessor]
InitModules --> InitMapper{对照表存在?}
InitMapper -->|是| InitMapperYes[初始化M06A_Mapper<br/>加载映射数据]
InitMapper -->|否| InitMapperNo[记录警告<br/>仅使用原始值]
InitMapperYes --> LoopStart{遍历每个产品型号}
InitMapperNo --> LoopStart
LoopStart --> ParseModel[M06_ModelParser<br/>解析产品型号]
ParseModel --> ParseSuccess{解析成功?}
ParseSuccess -->|失败| LogParseError[记录解析错误<br/>继续下一个型号]
ParseSuccess -->|成功| ExtractParams[提取8个参数]
ParseSuccess -->|成功| ExtractParams[提取原始参数]
ExtractParams --> Phase1[Phase 1: 收集匹配结果]
ExtractParams --> ApplyMapping{映射器已初始化?}
ApplyMapping -->|是| MapValues[M06A_Mapper<br/>应用值映射<br/>azxs, lcfw]
ApplyMapping -->|否| UseRawValues[使用原始值]
MapValues --> Phase1[Phase 1: 收集匹配结果]
UseRawValues --> Phase1
Phase1 --> CollectLoop[遍历所有BOM库工作表]
CollectLoop --> MatchBOM[M07_BOMMatcher<br/>匹配BOM记录]
CollectLoop --> MatchBOM[M07_BOMMatcher<br/>匹配BOM记录<br/>支持双值匹配]
MatchBOM --> IsComponent{是部件工作表?}
IsComponent -->|是| ProcessComp[M08_ComponentProcessor<br/>处理部件特殊逻辑]
@@ -228,6 +256,7 @@ flowchart TD
style Start fill:#c8e6c9
style End fill:#ffcdd2
style ParseModel fill:#e1f5fe
style MapValues fill:#f8bbd9
style MatchBOM fill:#fff9c4
style ProcessComp fill:#f8bbd9
style Phase1 fill:#e3f2fd
@@ -239,6 +268,8 @@ flowchart TD
style LogParseError fill:#ffebee
style RecordErrors fill:#ffcdd2
style RecordWarnings fill:#fff9c4
style InitMapperYes fill:#e8f5e9
style InitMapperNo fill:#fff9c4
```
---
@@ -253,9 +284,11 @@ sequenceDiagram
participant M01 as M01_Main
participant M09 as M09_BOMExtractor
participant M06 as M06_ModelParser
participant M06A as M06A_Mapper
participant M07 as M07_BOMMatcher
participant M08 as M08_ComponentProcessor
participant BOM as BOM库.xlsx
participant Mapping as 对照表.xlsx
participant Logger as clsErrorLogger
User->>M01: 调用 RunBOMExtraction()
@@ -265,9 +298,33 @@ sequenceDiagram
M09->>M09: 检查产品型号工作表
M09->>M09: 打开BOM库工作簿
M09->>M06: InitModelParser(logger)
M09->>M07: InitBOMMatcher(logger)
M09->>M08: InitComponentProcessor(logger)
alt 对照表存在
M09->>Mapping: 获取对照表工作表
M09->>M06A: InitMapper(logger, wsMapping)
M06A->>Mapping: 加载映射数据<br/>azxs: A0→径向, etc.<br/>lcfw: M01→低压, etc.
Mapping-->>M06A: 映射数据加载完成
M06A-->>M09: 映射器初始化完成
else 对照表不存在
M09->>Logger: 记录警告<br/>"未找到对照表工作表"
end
loop 遍历每个产品型号
M09->>M06: ParseProductModel(型号字符串)
M06-->>M09: 返回参数字典
M06->>M06: 提取原始参数<br/>azxs="A0", lcfw="M04"
alt 映射器已初始化
M06->>M06A: MapAzxs("A0")
M06A-->>M06: "A0,径向"
M06->>M06A: MapLcfw("M04")
M06A-->>M06: "M04,高压"
M06->>M06: 组装双值参数
end
M06-->>M09: 返回参数字典<br/>(含映射值)
alt 解析失败
M09->>Logger: 记录解析错误
@@ -279,6 +336,7 @@ sequenceDiagram
alt 工作表 = "部件"
M09->>M07: MatchBOMRecord(工作表, 参数)
Note over M07: 支持双值匹配<br/>azxs="A0,径向" 可匹配 "A0" 或 "径向"
M07-->>M09: 返回匹配结果
alt 匹配成功
@@ -288,6 +346,7 @@ sequenceDiagram
end
else 其他工作表
M09->>M07: MatchBOMRecord(工作表, 参数)
Note over M07: 支持双值匹配
M07-->>M09: 返回匹配结果
M09->>M09: 存储匹配结果(不记录错误)
end
@@ -524,7 +583,89 @@ End If
---
### 4. M06_ModelParser.bas - 型号解析
### 4. M06A_Mapper.bas - 值映射
**职责**: 为参数值添加映射值,支持双值匹配
**映射表配置** (M04_Config):
| 配置项 | 值 | 说明 |
|--------|-----|------|
| `MAPPING_SHEET_NAME` | "对照表" | 映射表工作表名称 |
| `MAPPING_COL_LCFW_KEY` | 1 (A列) | lcfw原始值列 |
| `MAPPING_COL_LCFW_VAL` | 2 (B列) | lcfw映射值列 |
| `MAPPING_COL_AZXS_KEY` | 4 (D列) | azxs原始值列 |
| `MAPPING_COL_AZXS_VAL` | 5 (E列) | azxs映射值列 |
| `MAPPING_START_ROW` | 3 | 数据起始行 |
**映射数据结构**:
**对照表** 工作表格式:
| 行号 | A列 (lcfw key) | B列 (lcfw val) | D列 (azxs key) | E列 (azxs val) |
|------|----------------|----------------|----------------|----------------|
| 1-2 | (表头) | (表头) | (表头) | (表头) |
| 3 | M01 | 低压 | A0 | 径向 |
| 4 | M12 | 高压 | AT | 径向 |
| 5 | - | - | B0 | 下轴向 |
**核心功能**:
```vba
' 初始化映射器
Public Sub InitMapper(logger As clsErrorLogger, wsMapping As Worksheet)
' 映射azxs值
Public Function MapAzxs(ByVal rawValue As String) As String
' 输入: "A0"
' 输出: "A0,径向"
' 映射lcfw值
Public Function MapLcfw(ByVal rawValue As String) As String
' 输入: "M01"
' 输出: "M01,低压"
```
**双值格式匹配**:
参数存储为双值格式后在BOM匹配时支持灵活匹配
| 参数值 | BOM库值 | 匹配结果 | 原因 |
|--------|---------|----------|------|
| `azxs="A0,径向"` | `azxs=A0` | ✅ 匹配 | 参数包含"A0" |
| `azxs="A0,径向"` | `azxs=径向` | ✅ 匹配 | 参数包含"径向" |
| `azxs="A0,径向"` | `azxs=AT` | ❌ 不匹配 | 参数不包含"AT" |
**优雅降级**:
如果"对照表"工作表不存在:
- 系统记录警告(非阻塞)
- 继续使用原始值进行匹配
- 功能正常运行,仅失去映射增强
**未映射值处理**:
如果值在映射表中不存在:
- 仅返回原始值(无逗号)
- 匹配时退化为精确匹配
- 不影响其他参数的匹配
**示例流程**:
```
1. 产品型号: YTHN-100.A0.531.G123.M04.Y3
2. M06_ModelParser提取: azxs="A0", lcfw="M04"
3. M06A_Mapper映射:
- azxs: "A0" → "A0,径向"
- lcfw: "M04" → "M04,高压"
4. BOM库匹配:
- BOM库有azxs="径向" → 匹配成功
- BOM库有lcfw="高压" → 匹配成功
```
---
### 5. M06_ModelParser.bas - 型号解析器
**职责**: 从产品型号字符串中提取参数
@@ -537,28 +678,47 @@ End If
**提取的参数**:
| 参数 | 描述 | 示例值 | 转换规则 |
|------|------|--------|----------|
| xh | 型号 | YTHN | 从YTHN-100提取横线前部分 |
| gcwj | 公称外径 | 100 | 从YTHN-100提取横线后数字 |
| azxs | 安装形式 | A0 | 直接提取,无转换 |
| bkxs | 表壳形式 | 531 | 直接提取 |
| gclj | 过程连接 | G12 | 从G123去除末位 |
| jycz | 接液材质 | 3 | 从G123提取末位 |
| lcfw | 量程范围 | M04 | 直接提取 |
| fjgn | 附加功能 | Y3 | 直接提取多段用逗号连接) |
| 参数 | 描述 | 原始值 | 映射后值 | 转换规则 |
|------|------|--------|----------|----------|
| xh | 型号 | YTHN | YTHN | 从YTHN-100提取横线前部分(无映射) |
| gcwj | 公称外径 | 100 | 100 | 从YTHN-100提取横线后数字(无映射) |
| azxs | 安装形式 | A0 | A0,径向 | 直接提取然后应用M06A_Mapper映射 |
| bkxs | 表壳形式 | 531 | 531 | 直接提取(无映射) |
| gclj | 过程连接 | G12 | G12 | 从G123去除末位(无映射) |
| jycz | 接液材质 | 3 | 3 | 从G123提取末位(无映射) |
| lcfw | 量程范围 | M04 | M04,高压 | 直接提取然后应用M06A_Mapper映射 |
| fjgn | 附加功能 | Y3 | Y3 | 直接提取多段用逗号连接(无映射 |
**值映射集成**:
```vba
' 1. 提取原始值
azxsRaw = ExtractAzxs(segments(1)) ' "A0"
lcfwRaw = ExtractLcfw(segments(4)) ' "M04"
' 2. 应用映射(如果映射器已初始化)
If M06A_Mapper.IsInitialized() Then
params("azxs") = M06A_Mapper.MapAzxs(azxsRaw) ' "A0,径向"
params("lcfw") = M06A_Mapper.MapLcfw(lcfwRaw) ' "M04,高压"
Else
' 映射器未初始化,使用原始值
params("azxs") = azxsRaw ' "A0"
params("lcfw") = lcfwRaw ' "M04"
End If
```
**核心函数**:
```vba
Public Function ParseProductModel(ByVal modelStr As String) As Object
' 返回包含8个参数的字典
' 如果M06A_Mapper已初始化azxs和lcfw将包含映射值
End Function
```
---
### 5. M07_BOMMatcher.bas - BOM匹配器
### 6. M07_BOMMatcher.bas - BOM匹配器
**职责**: 根据参数在BOM库中查找匹配记录
@@ -568,9 +728,44 @@ End Function
|----------|----------|
| 空白 | 通配符,匹配所有 |
| `!value` | 负向匹配,不等于该值 |
| `value` | 精确匹配 |
| `value` | 精确匹配或双值匹配 |
| `fjgn`列 | 包含匹配value包含在参数中 |
**双值匹配** (新增功能):
当参数包含映射值时(如`azxs="A0,径向"`),支持灵活匹配:
```
' EvaluateCellCondition函数逻辑
IF paramValue包含逗号 THEN
' 拆分为多个值
paramValues = Split(paramValue, ",")
' 只要任意一个值匹配单元格值,即认为匹配
FOR EACH pv IN paramValues
IF pv = cellStr THEN
RETURN True ' 匹配成功
END IF
NEXT
RETURN False ' 所有值都不匹配
ELSE
' 单值精确匹配
RETURN (paramValue = cellStr)
END IF
```
**双值匹配示例**:
| 参数值 | BOM库单元格值 | 匹配结果 | 说明 |
|--------|---------------|----------|------|
| `azxs="A0,径向"` | `azxs=A0` | ✅ 匹配 | 参数包含"A0" |
| `azxs="A0,径向"` | `azxs=径向` | ✅ 匹配 | 参数包含"径向" |
| `azxs="A0,径向"` | `azxs=AT` | ❌ 不匹配 | 参数不包含"AT" |
| `lcfw="M01,低压"` | `lcfw=M01` | ✅ 匹配 | 参数包含"M01" |
| `lcfw="M01,低压"` | `lcfw=低压` | ✅ 匹配 | 参数包含"低压" |
| `lcfw="M01,低压"` | `lcfw=高压` | ❌ 不匹配 | 参数不包含"高压" |
**匹配逻辑**:
```
@@ -583,7 +778,14 @@ End Function
ELSE IF 列名 = "fjgn" THEN
IF 参数包含单元格值 THEN 匹配成功
ELSE 匹配失败
ELSE IF 参数包含逗号 THEN
' 双值匹配:检查任意一个值是否匹配
FOR EACH pv IN Split(参数, ",")
IF pv = 单元格值 THEN 匹配成功
NEXT
匹配失败
ELSE
' 单值精确匹配
IF 参数 = 单元格值 THEN 匹配成功
ELSE 匹配失败
END IF
@@ -597,9 +799,13 @@ NEXT
- 0条 = 未找到匹配
- 多条 = 匹配不唯一
**向后兼容**:
- 单值参数(无逗号)退化为精确匹配
- 不影响现有的非映射参数
---
### 6. M08_ComponentProcessor.bas - 部件处理器
### 7. M08_ComponentProcessor.bas - 部件处理器
**职责**: 处理"部件"类物料的特殊逻辑
@@ -727,15 +933,17 @@ flowchart TD
Dictionary {
"xh": "YTHN",
"gcwj": "100",
"azxs": "A0",
"azxs": "A0,径向", // 双值格式(原始值,映射值)
"bkxs": "531",
"gclj": "G12",
"jycz": "3",
"lcfw": "M04",
"lcfw": "M04,高压", // 双值格式(原始值,映射值)
"fjgn": "Y3"
}
```
**注意**: 如果M06A_Mapper未初始化或值未找到映射则退化为单值格式。
**列映射字典** (M07_BOMMatcher):
```vba
Dictionary {
@@ -1002,7 +1210,11 @@ INVALID.MODEL.FORMAT
| M09_BOMExtractor | `MatchAllMaterialTypesWithValidation()` | 匹配所有物料类型(两阶段验证) |
| M09_BOMExtractor | `ValidateAllMatchResults()` | 统一验证所有匹配结果(跨工作表规则) |
| M06_ModelParser | `ParseProductModel()` | 解析型号参数 |
| M07_BOMMatcher | `MatchBOMRecord()` | 匹配BOM记录 |
| M06A_Mapper | `InitMapper()` | 初始化值映射器 |
| M06A_Mapper | `MapAzxs()` | 映射azxs参数值 |
| M06A_Mapper | `MapLcfw()` | 映射lcfw参数值 |
| M07_BOMMatcher | `MatchBOMRecord()` | 匹配BOM记录支持双值匹配 |
| M07_BOMMatcher | `EvaluateCellCondition()` | 评估单元格条件(支持双值匹配) |
| M07_BOMMatcher | `BuildHeaderMapping()` | 构建列映射 |
| M08_ComponentProcessor | `ProcessComponentRecord()` | 处理部件特殊逻辑 |
@@ -1013,10 +1225,13 @@ INVALID.MODEL.FORMAT
| 配置项 | 值 | 说明 |
|--------|-----|------|
| 输入工作表名 | "产品型号" | 可含"型号"列 |
| 映射表工作表名 | "对照表" | 可选,用于值映射 |
| BOM库文件名 | "BOM库.xlsx" | 必须在同一目录 |
| 输出工作表名 | "BOM提取结果" | 自动创建/覆盖 |
| 数据起始行 | 2 | 行1为表头 |
| 映射表数据起始行 | 3 | 行1-2为表头 |
| 支持的物料类型 | 接头, 弹性元件, 机芯, 部件, 边 | 可扩展 |
| 支持的映射参数 | azxs, lcfw | 从对照表加载映射 |
---
@@ -1028,11 +1243,12 @@ INVALID.MODEL.FORMAT
---
**文档版本**: 2.0
**文档版本**: 3.0
**最后更新**: 2026-02-12
**作者**: Claude Code
**状态**: 更新完成 - 新增两阶段验证架构文档
**状态**: 更新完成 - 新增值映射功能文档
**版本历史**:
- v3.0 (2026-02-12): 重大更新 - 添加值映射M06A_Mapper功能文档更新架构图、数据流图、核心流程图、模块交互时序图
- v2.0 (2026-02-12): 重大更新 - 添加两阶段验证架构详解,更新数据流图、核心流程图、模块交互时序图
- v1.0 (2026-02-12): 初稿完成