Files
AutoBOM/docs/RunBOMExtraction_运行机制详解.md
Misaka_Company 80bfafa2f2
All checks were successful
NTFY Notification / notify (push) Successful in 3s
docs: add RunBOMExtraction mechanism documentation with Mermaid diagrams
Add comprehensive documentation for BOM extraction system including:
- System architecture and data flow diagrams
- Core process flowchart with detailed decision points
- Module interaction sequence diagram
- Detailed explanations of 5 key modules (M01/M06/M07/M08/M09)
- Data structures (input/BOM library/output/internal)
- Error handling mechanisms and recovery strategies
- 3 practical usage examples
- Quick reference guide

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 14:13:03 +08:00

765 lines
20 KiB
Markdown
Raw 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.
# RunBOMExtraction 运行机制详解
## 目录
1. [系统概述](#系统概述)
2. [系统架构](#系统架构)
3. [数据流图](#数据流图)
4. [核心流程](#核心流程)
5. [模块交互时序图](#模块交互时序图)
6. [关键模块详解](#关键模块详解)
7. [数据结构](#数据结构)
8. [错误处理机制](#错误处理机制)
9. [使用示例](#使用示例)
---
## 系统概述
`RunBOMExtraction` 是BOM自动提取系统的入口函数用于从产品型号中自动提取参数匹配BOM库输出标准BOM清单。
### 主要功能
- **参数提取**: 从复杂的产品型号字符串中解析出7个关键参数
- **智能匹配**: 根据参数在BOM库中查找对应的物料
- **特殊处理**: 针对"部件"类物料的特殊逻辑(组件与子组件的选择)
- **结果输出**: 生成格式化的BOM提取结果表
### 设计特点
- **模块化**: 各功能模块职责清晰,易于维护
- **容错性**: 完善的错误处理机制,不中断处理流程
- **灵活性**: 支持通配符匹配、负向匹配等多种匹配规则
- **可扩展**: 易于添加新的物料类型和匹配规则
---
## 系统架构
```mermaid
graph TB
subgraph "入口层"
M01[M01_Main.bas<br/>RunBOMExtraction]
end
subgraph "协调层"
M09[M09_BOMExtractor.bas<br/>主协调器]
end
subgraph "处理层"
M06[M06_ModelParser.bas<br/>型号解析器]
M07[M07_BOMMatcher.bas<br/>BOM匹配器]
M08[M08_ComponentProcessor.bas<br/>部件处理器]
end
subgraph "配置层"
M04[M04_Config.bas<br/>配置管理]
Logger[clsErrorLogger.cls<br/>错误日志]
end
subgraph "数据源"
Input[产品型号工作表]
BOMLib[BOM库.xlsx]
end
subgraph "输出"
Output[BOM提取结果工作表]
end
M01 --> M09
M09 --> M06
M09 --> M07
M09 --> M08
M09 --> M04
M09 --> Logger
M06 --> Input
M07 --> BOMLib
M08 --> BOMLib
M09 --> Output
style M01 fill:#e1f5ff
style M09 fill:#fff4e1
style M06 fill:#e8f5e9
style M07 fill:#e8f5e9
style M08 fill:#e8f5e9
style Input fill:#f3e5f5
style BOMLib fill:#f3e5f5
style Output fill:#f3e5f5
```
---
## 数据流图
```mermaid
flowchart LR
subgraph "输入阶段"
A[产品型号<br/>YTHN-100.A0.531.G123.M04.Y3] --> B[M06_ModelParser<br/>型号解析]
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]
end
subgraph "匹配阶段"
C1 & C2 & C3 & C4 & C5 & C6 --> D[M07_BOMMatcher<br/>BOM匹配]
D --> E1[接头匹配]
D --> E2[弹性元件匹配]
D --> E3[机芯匹配]
D --> E4[部件匹配]
end
subgraph "特殊处理"
E4 --> F{M08_ComponentProcessor<br/>部件特殊处理}
F -->|优先级1| G1[使用组件]
F -->|优先级2| G2[使用子组件<br/>接头+弹性元件]
end
subgraph "输出阶段"
G1 & G2 & E1 & E2 & E3 --> H[M09_BOMExtractor<br/>结果汇总]
H --> I[BOM提取结果表]
end
style A fill:#ffebee
style I fill:#e8f5e9
style D fill:#fff3e0
style F fill:#fce4ec
```
---
## 核心流程
```mermaid
flowchart TD
Start([开始: RunBOMExtraction]) --> Init[初始化<br/>创建错误日志记录器]
Init --> CheckInput{检查输入工作表}
CheckInput -->|不存在| Error1[返回错误:<br/>未找到产品型号工作表]
CheckInput -->|存在| ReadModels[读取产品型号数据]
ReadModels --> CheckBOM{检查BOM库}
CheckBOM -->|不存在| Error2[返回错误:<br/>未找到BOM库.xlsx]
CheckBOM -->|存在| OpenBOM[打开BOM库工作簿]
OpenBOM --> LoopStart{遍历每个产品型号}
LoopStart --> ParseModel[M06_ModelParser<br/>解析产品型号]
ParseModel --> ParseSuccess{解析成功?}
ParseSuccess -->|失败| LogParseError[记录解析错误<br/>继续下一个型号]
ParseSuccess -->|成功| ExtractParams[提取7个参数]
ExtractParams --> MatchLoop{遍历物料类型}
MatchLoop --> MatchBOM[M07_BOMMatcher<br/>匹配BOM记录]
MatchBOM --> MatchResult{匹配结果}
MatchResult -->|无匹配| LogNoMatch[记录:<br/>未找到匹配物料]
MatchResult -->|多重匹配| LogMultiMatch[记录:<br/>找到多个匹配]
MatchResult -->|唯一匹配| CheckType{物料类型?}
CheckType -->|部件| ProcessComp[M08_ComponentProcessor<br/>处理部件特殊逻辑]
CheckType -->|其他| SaveMaterial[保存物料信息]
ProcessComp --> ValidateComp{验证组件组合}
ValidateComp -->|无效| LogInvalid[记录:<br/>无效组合]
ValidateComp -->|有效| SaveComp[保存组件/子组件]
SaveMaterial & SaveComp --> NextType{还有物料类型?}
LogNoMatch & LogMultiMatch & LogInvalid --> NextType
NextType -->|是| MatchLoop
NextType -->|否| NextModel{还有型号?}
LogParseError --> NextModel
NextModel -->|是| LoopStart
NextModel -->|否| WriteOutput[M09_BOMExtractor<br/>写入结果]
WriteOutput --> CloseBOM[关闭BOM库工作簿]
CloseBOM --> GenReport{有错误?}
GenReport -->|是| ShowWarning[显示警告:<br/>完成但有错误]
GenReport -->|否| ShowSuccess[显示成功:<br/>提取完成]
Error1 & Error2 --> End([结束])
ShowWarning & ShowSuccess --> End
style Start fill:#c8e6c9
style End fill:#ffcdd2
style ParseModel fill:#e1f5fe
style MatchBOM fill:#fff9c4
style ProcessComp fill:#f8bbd9
style Error1 fill:#ffcdd2
style Error2 fill:#ffcdd2
style LogParseError fill:#ffebee
style LogNoMatch fill:#ffebee
style LogMultiMatch fill:#ffebee
style LogInvalid fill:#ffebee
```
---
## 模块交互时序图
```mermaid
sequenceDiagram
participant User as 用户
participant M01 as M01_Main
participant M09 as M09_BOMExtractor
participant M06 as M06_ModelParser
participant M07 as M07_BOMMatcher
participant M08 as M08_ComponentProcessor
participant BOM as BOM库.xlsx
participant Logger as clsErrorLogger
User->>M01: 调用 RunBOMExtraction()
M01->>M09: RunBOMExtraction()
M09->>Logger: 创建错误日志记录器
M09->>M09: 检查产品型号工作表
M09->>M09: 打开BOM库工作簿
loop 遍历每个产品型号
M09->>M06: ParseProductModel(型号字符串)
M06-->>M09: 返回参数字典
alt 解析失败
M09->>Logger: 记录解析错误
else 解析成功
loop 遍历每个物料类型工作表
M09->>BOM: 读取物料类型工作表
M09->>M07: BuildHeaderMapping(工作表)
M07-->>M09: 返回列映射字典
M09->>M07: MatchBOMRecord(工作表, 参数)
M07->>M07: EvaluateCellCondition(每列)
alt 匹配失败
M09->>Logger: 记录匹配失败
else 多重匹配
M09->>Logger: 记录多重匹配
else 唯一匹配
alt 物料类型 = "部件"
M09->>M08: ProcessComponentRecord(行数据)
M08->>M08: ValidateComponentCombination()
alt 验证成功
M08-->>M09: 返回组件/子组件
else 验证失败
M09->>Logger: 记录验证失败
end
else 其他物料类型
M09->>M07: ExtractMaterialInfo(行数据)
M07-->>M09: 返回物料信息
end
end
end
end
end
M09->>M09: WriteExtractionResults(结果集)
M09->>BOM: 关闭BOM库工作簿
alt 有错误
M09-->>M01: 返回警告消息
else 无错误
M09-->>M01: 返回成功消息
end
M01-->>User: 显示结果消息框
```
---
## 关键模块详解
### 1. M01_Main.bas - 入口模块
**职责**: 系统入口,提供简洁的用户接口
```vba
Public Sub RunBOMExtraction()
Dim result As String
result = M09_BOMExtractor.RunBOMExtraction()
MsgBox result, vbInformation, "BOM提取"
End Sub
```
**特点**:
- 极简设计,仅作为调用入口
- 结果通过消息框返回
- 错误处理委托给下层模块
---
### 2. M09_BOMExtractor.bas - 主协调器
**职责**: 整体流程控制,模块调度,结果输出
**核心函数**:
| 函数名 | 职责 |
|--------|------|
| `RunBOMExtraction()` | 主流程控制函数 |
| `ProcessSingleModel()` | 处理单个产品型号 |
| `MatchAllMaterialTypes()` | 匹配所有物料类型 |
| `WriteExtractionResults()` | 输出提取结果 |
**处理流程**:
```
初始化 → 验证输入 → 打开BOM库 → 循环处理型号 → 输出结果 → 清理资源
```
---
### 3. M06_ModelParser.bas - 型号解析器
**职责**: 从产品型号字符串中提取参数
**产品型号格式**:
```
[型号-公称外径].[安装形式].[表壳形式].[过程连接&接液材质].[量程范围].[附加功能]|[扩展信息]
```
**示例**: `YTHN-100.A0.531.G123.M04.Y3|BP-088.2312.B09.0A3`
**提取的参数**:
| 参数 | 描述 | 示例值 | 转换规则 |
|------|------|--------|----------|
| azxs | 安装形式 | A0 | A0/AT/AH → 径向 |
| bkxs | 表壳形式 | 531 | 直接提取 |
| gclj | 过程连接 | G12 | 从G123提取G+首位 |
| jycz | 接液材质 | 3 | 从G123提取末位 |
| lcfw | 量程范围 | M04 | 直接提取 |
| fjgn | 附加功能 | Y3 | 直接提取 |
| gcwj | 公称外径 | 100 | 从YTHN-100提取 |
**核心函数**:
```vba
Public Function ParseProductModel(ByVal modelStr As String) As Object
' 返回包含7个参数的字典
End Function
```
---
### 4. M07_BOMMatcher.bas - BOM匹配器
**职责**: 根据参数在BOM库中查找匹配记录
**匹配规则**:
| 单元格值 | 匹配逻辑 |
|----------|----------|
| 空白 | 通配符,匹配所有 |
| `!value` | 负向匹配,不等于该值 |
| `value` | 精确匹配 |
| `fjgn`列 | 包含匹配value包含在参数中 |
**匹配逻辑**:
```
对于每条记录:
对于每个参数:
IF 单元格为空 THEN 匹配成功
ELSE IF 单元格以"!"开头 THEN
IF 参数 != 去掉"!"的值 THEN 匹配成功
ELSE 匹配失败
ELSE IF 列名 = "fjgn" THEN
IF 参数包含单元格值 THEN 匹配成功
ELSE 匹配失败
ELSE
IF 参数 = 单元格值 THEN 匹配成功
ELSE 匹配失败
END IF
IF 所有参数都匹配成功 THEN 返回该记录
NEXT
```
**匹配要求**:
- 必须有且仅有1条匹配记录
- 0条 = 未找到匹配
- 多条 = 匹配不唯一
---
### 5. M08_ComponentProcessor.bas - 部件处理器
**职责**: 处理"部件"类物料的特殊逻辑
**部件结构**:
```
部件记录包含:
- 自身信息 (物料编码A, 数量A)
- 子组件1 - 接头 (物料编码B, 数量B)
- 子组件2 - 弹性元件 (物料编码C, 数量C)
```
**选择策略**:
```mermaid
flowchart TD
Start([匹配到部件记录]) --> CheckA{检查组件A}
CheckA -->|有库存| UseA[使用组件A]
CheckA -->|无库存| CheckB{检查子组件B+C}
CheckB -->|都有库存| UseBC[使用子组件B+C]
CheckB -->|任一无库存| Error[标记: 缺货]
UseA --> ValidateA{仅组件A?}
ValidateA -->|是| Valid[✓ 有效组合]
ValidateA -->|否| Error1[✗ 无效组合:<br/>不能同时使用组件和子组件]
UseBC --> ValidateBC{有组件A?}
ValidateBC -->|否| Valid
ValidateBC -->|是| Error1
Error & Error1 --> End([结束: 验证失败])
Valid --> End
style Start fill:#e1f5fe
style End fill:#ffebee
style Valid fill:#c8e6c9
style Error fill:#ffcdd2
style Error1 fill:#ffcdd2
```
**有效组合**:
1. ✅ 仅组件A (优先级1)
2. ✅ 仅子组件B + 子组件C (优先级2)
3. ❌ 组件A + 子组件 (无效)
4. ❌ 仅部分子组件 (无效)
---
## 数据结构
### 输入数据结构
**产品型号工作表**:
| 行号 | 列A (型号) | 列B (可选列) |
|------|------------|--------------|
| 1 | 型号 | (表头) |
| 2 | YTHN-100.A0.531.G123.M04.Y3 | ... |
| 3 | YTHN-150.B0.531.G456.M12.Y2 | ... |
---
### BOM库数据结构
**BOM库.xlsx** 包含多个工作表,每个工作表代表一种物料类型。
**通用列结构** (以"接头"为例):
| 列名 | 说明 | 示例值 |
|------|------|--------|
| azxs | 安装形式 | 径向 |
| bkxs | 表壳形式 | 531 |
| gclj | 过程连接 | G12 |
| jycz | 接液材质 | 3 |
| lcfw | 量程范围 | M04 |
| fjgn | 附加功能 | Y3 |
| 物料编码 | 物料唯一标识 | JT-001 |
| 物料名称 | 物料描述名称 | 卡套式接头 |
| 数量 | 默认数量 | 1 |
**"部件"工作表特殊列**:
| 列名 | 说明 |
|------|------|
| 物料编码 | 组件A编码 |
| 数量A | 组件A数量 |
| 物料编码B | 子组件B(接头)编码 |
| 数量B | 子组件B数量 |
| 物料编码C | 子组件C(弹性元件)编码 |
| 数量C | 子组件C数量 |
---
### 输出数据结构
**BOM提取结果工作表** (12列):
| 列号 | 列名 | 说明 | 示例值 |
|------|------|------|--------|
| 1 | 原始产品型号 | 输入的完整型号 | YTHN-100...Y3 |
| 2 | azxs | 安装形式 | 径向 |
| 3 | bkxs | 表壳形式 | 531 |
| 4 | gclj | 过程连接 | G12 |
| 5 | jycz | 接液材质 | 3 |
| 6 | lcfw | 量程范围 | M04 |
| 7 | fjgn | 附加功能 | Y3 |
| 8 | 物料类型 | 接头/弹性元件/机芯/部件/边 | 接头 |
| 9 | 物料名称 | 物料描述 | 卡套式接头 |
| 10 | 物料编码 | 唯一标识 | JT-001 |
| 11 | 物料数量 | 数量 | 1 |
| 12 | 提取备注 | 错误或警告信息 | (空/错误信息) |
**输出格式**:
- 每种物料占一行
- 一个产品型号可能对应多行输出
- 行按物料类型分组
---
### 内部数据结构
**参数字典** (M06_ModelParser输出):
```vba
Dictionary {
"azxs": "径向",
"bkxs": "531",
"gclj": "G12",
"jycz": "3",
"lcfw": "M04",
"fjgn": "Y3",
"gcwj": "100"
}
```
**列映射字典** (M07_BOMMatcher):
```vba
Dictionary {
"azxs": 1,
"bkxs": 2,
"gclj": 3,
...
"物料编码": 10,
"物料名称": 11,
"数量": 12
}
```
**物料信息字典** (M07_BOMMatcher输出):
```vba
Dictionary {
"物料编码": "JT-001",
"物料名称": "卡套式接头",
"数量": 1,
"物料类型": "接头"
}
```
**结果集合** (M09_BOMExtractor汇总):
```vba
Collection {
Array(型号, azxs, bkxs, gclj, jycz, lcfw, fjgn, 物料类型, 物料名称, 物料编码, 数量, 备注),
Array(...), // 第二条物料
...
}
```
---
## 错误处理机制
### 错误分类
| 错误类型 | 级别 | 处理方式 | 示例 |
|----------|------|----------|------|
| 工作表不存在 | 致命 | 立即返回 | 未找到产品型号工作表 |
| BOM库不存在 | 致命 | 立即返回 | 未找到BOM库.xlsx |
| 型号解析失败 | 警告 | 记录错误,跳过 | 型号格式错误 |
| 无匹配记录 | 警告 | 记录错误,继续 | 未找到匹配物料 |
| 多重匹配 | 警告 | 记录错误,继续 | 找到多个匹配 |
| 组件组合无效 | 警告 | 记录错误,继续 | 组件与子组件混用 |
---
### 错误日志机制
```mermaid
flowchart LR
subgraph "错误检测"
A[检测到错误]
end
subgraph "错误记录"
B[clsErrorLogger.LogError]
end
subgraph "错误信息"
C[错误类型]
D[上下文信息]
E[时间戳]
end
subgraph "错误输出"
F[第12列: 提取备注]
G[红色高亮显示]
end
A --> B
B --> C
B --> D
B --> E
C & D & E --> F
F --> G
style A fill:#ffebee
style B fill:#fff3e0
style F fill:#e8f5e9
style G fill:#ffcdd2
```
**clsErrorLogger方法**:
```vba
logger.LogError "ERROR_TYPE", "详细错误信息", "上下文数据"
```
**错误信息格式**:
```
[错误类型] 详细描述
- 行号: X
- 数据: [具体数据]
```
---
### 错误恢复策略
1. **继续处理**: 遇到非致命错误时继续处理下一条记录
2. **错误累积**: 所有错误都记录在日志中
3. **最终报告**: 处理完成后显示汇总报告
4. **部分成功**: 部分记录成功时仍然输出结果
---
## 使用示例
### 示例1: 基本使用
```vba
' 在VBA编辑器中运行
Sub TestBOMExtraction()
Call RunBOMExtraction
End Sub
```
**输入数据**:
| 型号 |
|------|
| YTHN-100.A0.531.G123.M04.Y3 |
**输出结果**:
| 原始产品型号 | 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 | |
---
### 示例2: 部件特殊处理
**场景**: 组件A缺货使用子组件替代
**BOM库记录** ("部件"工作表):
| azxs | bkxs | ... | 物料编码 | 数量A | 物料编码B | 数量B | 物料编码C | 数量C |
|------|------|-----|----------|-------|-----------|-------|-----------|-------|
| 径向 | 531 | ... | BJ-001 | 1 | JT-002 | 2 | MH-003 | 1 |
**假设**: 组件A (BJ-001) 缺货
**处理逻辑**:
1. 检测到组件A缺货
2. 检查子组件B (JT-002) 和C (MH-003) 库存
3. 如果都有库存,使用子组件替代
4. 验证组合: 只有子组件无组件A ✓
**输出结果**:
| 物料类型 | 物料名称 | 物料编码 | 数量 | 备注 |
|----------|----------|----------|------|------|
| 接头 | 卡套式接头 | JT-002 | 2 | (子组件B) |
| 弹性元件 | 膜片 | MH-003 | 1 | (子组件C) |
---
### 示例3: 错误处理
**场景**: 型号解析失败
**输入**:
```
INVALID.MODEL.FORMAT
```
**处理流程**:
1. M06_ModelParser尝试解析
2. 检测到格式不匹配
3. 记录错误到Logger
4. 跳过该型号,继续下一个
**输出**:
| 原始产品型号 | 备注 |
|--------------|------|
| INVALID.MODEL.FORMAT | [解析错误] 型号格式不符合要求,无法提取参数 |
备注单元格会以红色高亮显示。
---
## 附录: 快速参考
### 常用函数速查
| 模块 | 函数 | 用途 |
|------|------|------|
| M01_Main | `RunBOMExtraction()` | 系统入口 |
| M09_BOMExtractor | `RunBOMExtraction()` | 主流程控制 |
| M09_BOMExtractor | `ProcessSingleModel()` | 处理单个型号 |
| M09_BOMExtractor | `MatchAllMaterialTypes()` | 匹配所有物料类型 |
| M06_ModelParser | `ParseProductModel()` | 解析型号参数 |
| M07_BOMMatcher | `MatchBOMRecord()` | 匹配BOM记录 |
| M07_BOMMatcher | `BuildHeaderMapping()` | 构建列映射 |
| M08_ComponentProcessor | `ProcessComponentRecord()` | 处理部件特殊逻辑 |
---
### 配置参数
| 配置项 | 值 | 说明 |
|--------|-----|------|
| 输入工作表名 | "产品型号" | 可含"型号"列 |
| BOM库文件名 | "BOM库.xlsx" | 必须在同一目录 |
| 输出工作表名 | "BOM提取结果" | 自动创建/覆盖 |
| 数据起始行 | 2 | 行1为表头 |
| 支持的物料类型 | 接头, 弹性元件, 机芯, 部件, 边 | 可扩展 |
---
### 相关文档
- [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
**状态**: 初稿完成