Files
AutoBOM/reference_docs/clsBOMManager_LoadData流程分析-v2(整合后).md
Misaka_Company a9b3188d23 refactor: integrate [领料配置] into [平台配置清单] and add category selection conditions
Major changes:
- Remove dependency on separate [领料配置] sheet
- Load all data from [平台配置清单] in a single pass
- Add "类别选用条件" (CategorySelectCondition) field to support dynamic category filtering
- Add "66代码" (Code66) field for 66-system integration
- Refactor completeness check logic to only verify required categories

Data model changes:
- clsMaterialItem: Add CategorySelectCondition and Code66 properties
- clsCategory: Add CategorySelectCondition property and IsRequiredForModel() method
- clsBOMManager: Refactor LoadData() to use single data source
- clsBOMManager: Add GetRequiredCategories() method
- clsBOMManager: Update GetValidMaterialsByModel() to use category selection conditions

New workflow:
- LoadData() now takes only wsPlatform parameter (removed wsConfig)
- Categories are filtered by "类别选用条件" before completeness check
- Categories with empty selection condition are always required
- Categories with non-empty condition are checked against model specifications

Documentation:
- Update CLAUDE.md with new sheet structure
- Add comprehensive refactoring plan document
- Add v2.0 LoadData flow analysis with Mermaid diagrams
- Add platform configuration sheet reference

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-29 10:25:28 +08:00

531 lines
16 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.
# clsBOMManager.LoadData 方法流程分析 (v2.0 - 整合后版本)
## 方法概述
`LoadData``clsBOMManager` 类的核心方法,负责从 [平台配置清单] 工作表加载 BOM 数据并构建完整的层级数据结构。
**v2.0 变更说明**
- 移除了 [领料配置] 表的依赖
- 所有配置数据统一从 [平台配置清单] 读取
- 新增"类别选用条件"字段,支持动态判断类别是否需要
- 新增"66代码"字段
## 方法签名
```vba
Public Sub LoadData(wsPlatform As Worksheet)
```
### 参数说明
| 参数 | 类型 | 说明 |
|------|------|------|
| `wsPlatform` | Worksheet | [平台配置清单]工作表,包含完整的物料信息和类别配置 |
## 整体流程图
```mermaid
flowchart TD
Start([开始 LoadData]) --> Step1[第一步: 从平台配置清单加载所有物料和类别信息]
Step1 --> Step2[第二步: 建立类别层级关系]
Step2 --> End([结束])
style Start fill:#e1f5e1
style End fill:#ffe1e1
style Step1 fill:#e1f0ff
style Step2 fill:#fff4e1
```
## 详细流程分析
### 第一步:从平台配置清单加载所有物料和类别信息
```mermaid
flowchart TD
S1_Start([开始第一步]) --> S1_Init[初始化: 获取最后一行行号]
S1_Init --> S1_Loop{循环 i = 4 到 lastRow}
S1_Loop -->|i += 1| S1_ReadMat[读取物料基础信息<br/>C列:代号, D列:名称<br/>E列:数量, F列:选择条件]
S1_ReadMat --> S1_ReadCat[读取类别信息<br/>H列:类别, I列:上层类别<br/>J列:类别选用条件, K列:66代码]
S1_ReadCat --> S1_CreateMat[创建 clsMaterialItem 对象]
S1_CreateMat --> S1_SetMatProps[设置物料属性<br/>code, Name, Quantity, Condition<br/>Category, ParentCategory<br/>CategorySelectCondition, Code66]
S1_SetMatProps --> S1_SaveMat[保存到 dictAllMaterials]
S1_SaveMat --> S1_CheckCat{类别字段<br/>是否为空?}
S1_CheckCat -->|否, 有类别| S1_EnsureCat{类别对象<br/>是否存在?}
S1_CheckCat -->|是, 无类别| S1_Next
S1_EnsureCat -->|不存在| S1_CreateCat[创建新类别对象<br/>设置 categoryName, ParentCategoryName<br/>CategorySelectCondition]
S1_EnsureCat -->|已存在| S1_AddMat
S1_CreateCat --> S1_AddMat[将物料添加到类别]
S1_AddMat --> S1_Next
S1_Next --> S1_Loop
S1_Loop -->|i > lastRow| S1_End([第一步完成])
style S1_Start fill:#e1f5e1
style S1_End fill:#ffe1e1
style S1_CreateCat fill:#bbdefb
style S1_AddMat fill:#c8e6c9
style S1_CheckCat fill:#fff9c4
```
**数据来源**[平台配置清单] 工作表
| 列 | 字段 | 说明 |
|----|------|------|
| C | code | 物料代号 |
| D | Name | 物料名称 |
| E | Quantity | 物料数量 |
| F | Condition | 选择条件 |
| H | Category | 类别名称 |
| I | ParentCategoryName | 上层类别名称 |
| J | CategorySelectCondition | 类别选用条件 |
| K | Code66 | 66系统代码 |
**数据结构**
```
dictAllMaterials: Dictionary<String, clsMaterialItem>
├── "01011009557" → clsMaterialItem{
│ code: "01011009557"
│ Name: "径向低压接头部件"
│ Quantity: 1.0
│ Condition: "gclj=M20 AND jycz=1"
│ Category: "部件"
│ ParentCategory: ""
│ CategorySelectCondition: ""
│ Code66: "66021009557"
│ }
└── ...
dictCategories: Dictionary<String, clsCategory>
├── "部件" → clsCategory{
│ categoryName: "部件"
│ ParentCategoryName: ""
│ CategorySelectCondition: ""
│ materials: Collection<clsMaterialItem>
│ SubCategories: Collection<clsCategory>
│ }
└── ...
```
**关键代码**
```vba
lastRow = wsPlatform.Cells(wsPlatform.Rows.Count, "C").End(xlUp).row
For i = 4 To lastRow
' 1. 创建物料对象并读取基础信息
Set mat = New clsMaterialItem
mat.code = Trim(wsPlatform.Cells(i, "C").value & "")
mat.Name = Trim(wsPlatform.Cells(i, "D").value & "")
mat.Quantity = CDbl(wsPlatform.Cells(i, "E").value)
mat.Condition = Trim(wsPlatform.Cells(i, "F").value & "")
' 2. 读取类别相关字段
catName = Trim(wsPlatform.Cells(i, "H").value & "")
parentCatName = Trim(wsPlatform.Cells(i, "I").value & "")
catSelectCond = Trim(wsPlatform.Cells(i, "J").value & "")
code66 = Trim(wsPlatform.Cells(i, "K").value & "")
' 3. 保存到物料对象
mat.Category = catName
mat.ParentCategory = parentCatName
mat.CategorySelectCondition = catSelectCond
mat.Code66 = code66
' 4. 保存到字典(所有物料都保存)
If mat.code <> "" Then
Set dictAllMaterials(mat.code) = mat
End If
' 5. 如果有类别,创建或更新类别对象
If catName <> "" Then
If Not dictCategories.Exists(catName) Then
Set cat = New clsCategory
cat.categoryName = catName
cat.ParentCategoryName = parentCatName
cat.CategorySelectCondition = catSelectCond
Set dictCategories(catName) = cat
End If
dictCategories(catName).AddMaterial mat
End If
Next i
```
**与 v1.0 的区别**
| 特性 | v1.0 (旧版本) | v2.0 (新版本) |
|------|--------------|--------------|
| 数据源 | [平台配置清单] + [领料配置] | 仅 [平台配置清单] |
| 加载步骤 | 3步 (先物料,后类别,再层级) | 2步 (物料类别一起加载,再层级) |
| 参数 | wsConfig, wsPlatform | wsPlatform |
| 类别选用条件 | 不支持 | 支持 |
| 66代码 | 不支持 | 支持 |
---
### 第二步:建立类别层级关系
```mermaid
flowchart TD
S2_Start([开始第二步]) --> S2_Loop{遍历 dictCategories<br/>所有键}
S2_Loop -->|下一个键| S2_GetCat[获取类别对象 cat]
S2_GetCat --> S2_CheckParent{ParentCategoryName<br/>是否为空?}
S2_CheckParent -->|否, 有父类别| S2_ParentExists{父类别<br/>存在?}
S2_CheckParent -->|是, 无父类别| S2_AddRoot[添加到 rootCategories<br/>作为根类别]
S2_ParentExists -->|是| S2_AddSub[添加到父类别的<br/>SubCategories 集合]
S2_ParentExists -->|否| S2_Orphan[父类别不存在<br/>跳过建立关系]
S2_AddRoot --> S2_Next
S2_AddSub --> S2_Next
S2_Orphan --> S2_Next
S2_Next --> S2_Loop
S2_Loop -->|遍历完成| S2_End([第二步完成])
style S2_Start fill:#e1f5e1
style S2_End fill:#ffe1e1
style S2_AddRoot fill:#ffccbc
style S2_AddSub fill:#b2dfdb
```
**数据结构**
```
rootCategories: Collection<clsCategory>
├── "表壳" (根类别)
│ └── CategorySelectCondition: "" (总是需要)
├── "部件" (根类别)
│ └── CategorySelectCondition: "" (总是需要)
│ └── SubCategories:
│ ├── "接头" (子类别)
│ │ └── CategorySelectCondition: "gclj=M20" (条件性需要)
│ └── "弹性元件" (子类别)
│ └── CategorySelectCondition: "lcfw=M02" (条件性需要)
└── "机芯" (根类别)
└── CategorySelectCondition: "jycz=1" (条件性需要)
```
**关键代码**
```vba
For Each key In dictCategories.Keys
Set cat = dictCategories(key)
If cat.ParentCategoryName <> "" Then
If dictCategories.Exists(cat.ParentCategoryName) Then
Set parentCat = dictCategories(cat.ParentCategoryName)
parentCat.AddSubCategory cat
End If
Else
rootCategories.Add cat, cat.categoryName
End If
Next key
```
**说明**:此步骤与 v1.0 版本相同,未发生变化。
---
## 数据结构总结
### 类的私有成员变量
```mermaid
classDiagram
class clsBOMManager {
-dictCategories: Dictionary
-dictAllMaterials: Dictionary
-rootCategories: Collection
+LoadData(wsPlatform)
+GetRootCategories() Collection
+GetCategory(categoryName) clsCategory
+GetRequiredCategories(conditions) Collection
+GetValidMaterialsByModel(modelStr) Collection
}
class clsCategory {
+categoryName: String
+ParentCategoryName: String
+CategorySelectCondition: String
+materials: Collection
+SubCategories: Collection
+IsLeafCategory: Boolean
+AddMaterial(mat)
+AddSubCategory(cat)
+IsRequiredForModel(conditions) Boolean
+HasSubCategories() Boolean
}
class clsMaterialItem {
+code: String
+Name: String
+Quantity: Double
+Condition: String
+Category: String
+ParentCategory: String
+CategorySelectCondition: String
+Code66: String
}
clsBOMManager "1" --> "*" clsCategory : 管理
clsCategory "1" --> "*" clsMaterialItem : 包含
clsCategory "1" --> "*" clsCategory : 父子关系
```
### 三个核心数据容器
| 数据容器 | 类型 | 键/索引 | 值 | 用途 |
|---------|------|---------|-----|------|
| `dictAllMaterials` | Dictionary | 物料代号 (String) | clsMaterialItem | 快速查找任意物料的完整信息 |
| `dictCategories` | Dictionary | 类别名称 (String) | clsCategory | 快速查找任意类别 |
| `rootCategories` | Collection | 索引 (Long) | clsCategory | 遍历完整的类别树结构 |
---
## 流程时序图
```mermaid
sequenceDiagram
participant Caller as 调用者
participant LoadData as LoadData方法
participant WSPlatform as [平台配置清单]
participant DictMat as dictAllMaterials
participant DictCat as dictCategories
participant RootCats as rootCategories
Caller->>LoadData: LoadData(wsPlatform)
Note over LoadData, WSPlatform: 第一步: 加载物料和类别信息
LoadData->>WSPlatform: 读取第4-末行
WSPlatform-->>LoadData: 返回物料和类别数据
loop 每一行数据
LoadData->>DictMat: 创建/添加物料 (包含新字段)
alt 类别字段不为空
LoadData->>DictCat: 类别存在?
alt 类别不存在
LoadData->>DictCat: 创建新类别(含类别选用条件)
end
LoadData->>DictCat: 添加物料到类别
end
end
Note over LoadData, RootCats: 第二步: 构建层级树
loop 遍历所有类别
LoadData->>DictCat: 获取类别
alt 有父类别
LoadData->>DictCat: 添加到父类别的SubCategories
else 无父类别
LoadData->>RootCats: 添加为根类别
end
end
LoadData-->>Caller: 完成
```
---
## 重要业务规则
### 1. 物料筛选规则
- ✅ 类别字段不为空的物料 → **需要领料**,会被添加到类别中
- ❌ 类别字段为空的物料 → **不需要领料**,仅在 `dictAllMaterials` 中保存
### 2. 类别选用条件规则v2.0 新增)
- ✅ 类别选用条件为空 → 该类别**总是需要**(无条件限制)
- ⚡ 类别选用条件不为空 → 需要用型号条件去匹配
- 匹配成功 → 该类别需要
- 匹配失败 → 该类别不需要
### 3. 类别层级规则
- 根类别:`ParentCategoryName` 为空字符串 `""`
- 子类别:`ParentCategoryName` 指向父类别名称
- 层级深度:无限制(支持任意深度的树形结构)
### 4. 数据一致性
- 所有物料必须从 [平台配置清单] 读取
- 类别字段和类别选用条件字段同时存在
- 一个物料只能属于一个类别
---
## 使用示例
### 调用 LoadData
```vba
Dim bomMgr As New clsBOMManager
Dim wsPlatform As Worksheet
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
' 加载数据 (v2.0 只需要一个参数)
Call bomMgr.LoadData(wsPlatform)
' 获取根类别
Dim rootCats As Collection
Set rootCats = bomMgr.GetRootCategories()
' 遍历所有根类别
Dim i As Long
For i = 1 To rootCats.Count
Debug.Print "根类别: " & rootCats(i).categoryName
Debug.Print "类别选用条件: " & rootCats(i).CategorySelectCondition
Next i
```
### 使用类别选用条件
```vba
' 解析型号并提取条件
Dim conditions As Object
Set conditions = bomMgr.ParseModelAndExtractConditions("YTHN-100.A0.532.M203.M16.Y3")
' 获取需要的类别
Dim requiredCats As Collection
Set requiredCats = bomMgr.GetRequiredCategories(conditions)
' 遍历需要的类别
Dim cat As clsCategory
For Each cat In requiredCats
Debug.Print "需要的类别: " & cat.categoryName
Next cat
```
---
## 执行后的数据结构示例
假设加载后的数据结构如下:
```
型号: YTHN-100.A0.532.M203.M16.Y3
提取的条件: lcfw=M16, gclj=M20, jycz=1, azxs=A0
dictAllMaterials:
{
"01011009557" → {
code: "01011009557",
Name: "径向低压接头部件",
Quantity: 1.0,
Condition: "gclj=M20 AND jycz=1 AND lcfw=M01",
Category: "部件",
ParentCategory: "",
CategorySelectCondition: "",
Code66: "66021009557"
}
}
dictCategories:
{
"部件" → {
categoryName: "部件",
ParentCategoryName: "",
CategorySelectCondition: "",
materials: [...],
SubCategories: ["接头", "弹性元件"]
},
"接头" → {
categoryName: "接头",
ParentCategoryName: "部件",
CategorySelectCondition: "gclj=M20", ← 类别选用条件
materials: [...],
SubCategories: []
},
"机芯" → {
categoryName: "机芯",
ParentCategoryName: "",
CategorySelectCondition: "jycz=1", ← 类别选用条件
materials: [...],
SubCategories: []
}
}
判断哪些类别需要:
- "部件" → CategorySelectCondition="" → 总是需要 ✓
- "接头" → CategorySelectCondition="gclj=M20" → 型号有gclj=M20 → 需要 ✓
- "机芯" → CategorySelectCondition="jycz=1" → 型号有jycz=1 → 需要 ✓
requiredCategories = ["部件", "接头", "机芯"]
```
---
## 错误处理
LoadData 方法本身不包含显式的错误处理(`On Error`),依赖以下机制:
1. **空值处理**:使用 `& ""` 确保字符串转换不会失败
2. **类型转换**:使用 `CDbl()` 时没有错误处理,假设数据格式正确
3. **跳过机制**:物料代号为空时,不保存到字典
4. **存在性检查**:使用 `Dictionary.Exists()` 避免键不存在错误
---
## 相关方法
LoadData 执行后,可以使用以下方法访问数据:
| 方法 | 说明 | v2.0变化 |
|------|------|---------|
| `GetRootCategories()` | 获取所有顶层类别 | 无变化 |
| `GetCategory(categoryName)` | 根据名称获取类别对象 | 无变化 |
| `GetRequiredCategories(conditions)` | ⭐ 获取需要的类别列表 | 新增 |
| `GetValidMaterialsByModel()` | 获取物料并检查完整性 | ⭐ 已重构,使用类别选用条件 |
| `GetMaterialsByModel()` | 根据型号获取物料 | 无变化 |
| `PrintCategoryTree()` | 打印类别树(调试用) | 无变化 |
---
## 迁移指南 (v1.0 → v2.0)
### 代码变更
**旧代码 (v1.0)**
```vba
Dim wsConfig As Worksheet
Dim wsPlatform As Worksheet
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
Call bomMgr.LoadData(wsConfig, wsPlatform) ' 两个参数
```
**新代码 (v2.0)**
```vba
Dim wsPlatform As Worksheet
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
Call bomMgr.LoadData(wsPlatform) ' 一个参数
```
### 数据变更
**旧表结构**
- [领料配置]: A列=代号, C列=类别, D列=上层类别
- [平台配置清单]: C列=代号, D列=名称, E列=数量, F列=选择条件
**新表结构**
- [平台配置清单]: C列=代号, D列=名称, E列=数量, F列=选择条件
H列=类别, I列=上层类别, J列=类别选用条件, K列=66代码
### 逻辑变更
**完整性检查逻辑**
- **v1.0**: 所有根类别都必须匹配到物料
- **v2.0**: 只检查需要的类别(通过类别选用条件判断)
---
## 总结
`LoadData` 方法v2.0)通过两个阶段构建完整的 BOM 数据结构:
1. **数据加载**:从 [平台配置清单] 一次性加载所有物料和类别信息包括新增的类别选用条件和66代码
2. **结构构建**:构建类别的树形层级关系
v2.0 的主要改进:
- ✅ 简化数据源:从一个表读取所有数据
- ✅ 支持动态类别判断:通过类别选用条件
- ✅ 更精确的完整性检查:只检查需要的类别
- ✅ 支持66系统新增66代码字段
最终形成的数据结构支持:
- 快速按代号查找物料
- 快速按类别查找物料
- 遍历完整的类别树
- 根据型号动态确定需要的类别
- 支持父类别/子类别的领料逻辑