docs: reorganize documentation structure and add analysis guidelines
- Move existing documentation files to reference_docs/ directory - Add documentation guidelines section to CLAUDE.md - Add clsBOMManager LoadData flow analysis with Mermaid diagrams Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
12
CLAUDE.md
12
CLAUDE.md
@@ -130,6 +130,18 @@ Run tests from the VBA editor or Excel macros:
|
||||
- `布莱迪公司压力表产品选型大表.md` - Complete product model numbering system (716 lines, Chinese)
|
||||
- `VBA/clsBOMManager使用说明.md` - API documentation and usage examples for clsBOMManager (546 lines, Chinese)
|
||||
|
||||
### Documentation Guidelines
|
||||
|
||||
**Analysis Documents**
|
||||
- When analyzing VBA code, modules, or methods (e.g., creating flow diagrams, architecture explanations), save all generated analysis documents to the `reference_docs/` directory
|
||||
- Use descriptive filenames that clearly indicate the content (e.g., `clsBOMManager_LoadData流程分析.md`)
|
||||
- Prefer using Mermaid diagrams for visualizing:
|
||||
- Flowcharts (method execution flow)
|
||||
- Sequence diagrams (interactions between objects)
|
||||
- Class diagrams (relationships between classes)
|
||||
- State diagrams (state transitions)
|
||||
- Keep analysis documents in Chinese when the original code comments are in Chinese
|
||||
|
||||
## Module Registry
|
||||
|
||||
`VBA/vba_metadata.json` maps VBA module names to their file locations in the repository. Update this file when:
|
||||
|
||||
439
reference_docs/clsBOMManager_LoadData流程分析.md
Normal file
439
reference_docs/clsBOMManager_LoadData流程分析.md
Normal file
@@ -0,0 +1,439 @@
|
||||
# clsBOMManager.LoadData 方法流程分析
|
||||
|
||||
## 方法概述
|
||||
|
||||
`LoadData` 是 `clsBOMManager` 类的核心方法,负责从 Excel 工作表加载 BOM 数据并构建完整的层级数据结构。
|
||||
|
||||
## 方法签名
|
||||
|
||||
```vba
|
||||
Public Sub LoadData(wsConfig As Worksheet, wsPlatform As Worksheet)
|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `wsConfig` | Worksheet | [领料配置]工作表,包含类别层级和需要领料的物料 |
|
||||
| `wsPlatform` | Worksheet | [平台配置清单]工作表,包含完整的物料信息 |
|
||||
|
||||
## 整体流程图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始 LoadData]) --> Step1[第一步: 加载物料基础信息]
|
||||
Step1 --> Step2[第二步: 加载类别信息并关联物料]
|
||||
Step2 --> Step3[第三步: 建立类别层级关系]
|
||||
Step3 --> End([结束])
|
||||
|
||||
style Start fill:#e1f5e1
|
||||
style End fill:#ffe1e1
|
||||
style Step1 fill:#e1f0ff
|
||||
style Step2 fill:#fff4e1
|
||||
style Step3 fill:#f0e1ff
|
||||
```
|
||||
|
||||
## 详细流程分析
|
||||
|
||||
### 第一步:从平台配置清单加载所有物料的基础信息
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S1_Start([开始第一步]) --> S1_Init[初始化: 获取最后一行行号]
|
||||
S1_Init --> S1_Loop{循环 i = 4 到 lastRow}
|
||||
S1_Loop -->|i += 1| S1_Read[读取第 i 行数据]
|
||||
S1_Read --> S1_Create[创建 clsMaterialItem 对象]
|
||||
S1_Create --> S1_Assign[赋值: code, Name, Quantity, Condition]
|
||||
S1_Assign --> S1_Check{code 是否非空?}
|
||||
S1_Check -->|是| S1_Add[添加到 dictAllMaterials<br/>键: code, 值: mat]
|
||||
S1_Check -->|否| S1_Next[跳过]
|
||||
S1_Add --> S1_Next
|
||||
S1_Next --> S1_Loop
|
||||
S1_Loop -->|i > lastRow| S1_End([第一步完成])
|
||||
|
||||
style S1_Start fill:#e1f5e1
|
||||
style S1_End fill:#ffe1e1
|
||||
style S1_Add fill:#c8e6c9
|
||||
style S1_Check fill:#fff9c4
|
||||
```
|
||||
|
||||
**数据来源**:[平台配置清单] 工作表
|
||||
|
||||
| 列 | 字段 | 说明 |
|
||||
|----|------|------|
|
||||
| C | code | 物料代号 |
|
||||
| D | Name | 物料名称 |
|
||||
| E | Quantity | 物料数量 |
|
||||
| F | Condition | 选择条件 |
|
||||
|
||||
**数据结构**:
|
||||
```
|
||||
dictAllMaterials: Dictionary<String, clsMaterialItem>
|
||||
├── "01011019001" → clsMaterialItem{code, Name, Quantity, Condition}
|
||||
├── "01081013833" → clsMaterialItem{...}
|
||||
└── ...
|
||||
```
|
||||
|
||||
**关键代码**:
|
||||
```vba
|
||||
lastRow = wsPlatform.Cells(wsPlatform.Rows.Count, "C").End(xlUp).row
|
||||
For i = 4 To lastRow
|
||||
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 & "")
|
||||
|
||||
If mat.code <> "" Then
|
||||
Set dictAllMaterials(mat.code) = mat
|
||||
End If
|
||||
Next i
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 第二步:从领料配置加载类别信息并关联物料
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S2_Start([开始第二步]) --> S2_Init[初始化: 获取最后一行行号]
|
||||
S2_Init --> S2_Loop{循环 i = 2 到 lastRow}
|
||||
S2_Loop -->|i += 1| S2_Read[读取第 i 行数据<br/>code, catName, parentCatName]
|
||||
S2_Read --> S2_CheckCode{code 是否为空?}
|
||||
S2_CheckCode -->|是| S2_NextRow[跳到下一行]
|
||||
S2_CheckCode -->|否| S2_CheckCat{类别是否已存在?}
|
||||
S2_CheckCat -->|否| S2_CreateCat[创建新的 clsCategory 对象<br/>设置 categoryName 和 ParentCategoryName<br/>添加到 dictCategories]
|
||||
S2_CheckCat -->|是| S2_Exists[类别已存在]
|
||||
S2_CreateCat --> S2_CheckMat{物料在<br/>dictAllMaterials?}
|
||||
S2_Exists --> S2_CheckMat
|
||||
S2_CheckMat -->|是| S2_UpdateMat[更新物料信息:<br/>mat.Category = catName<br/>mat.ParentCategory = parentCatName<br/>添加到类别 materials 集合]
|
||||
S2_CheckMat -->|否| S2_SkipMat[物料不在库中,跳过]
|
||||
S2_UpdateMat --> S2_NextRow
|
||||
S2_SkipMat --> S2_NextRow
|
||||
S2_NextRow --> S2_Loop
|
||||
S2_Loop -->|i > lastRow| S2_End([第二步完成])
|
||||
|
||||
style S2_Start fill:#e1f5e1
|
||||
style S2_End fill:#ffe1e1
|
||||
style S2_CreateCat fill:#bbdefb
|
||||
style S2_UpdateMat fill:#c8e6c9
|
||||
style S2_CheckCat fill:#fff9c4
|
||||
style S2_CheckMat fill:#fff9c4
|
||||
```
|
||||
|
||||
**数据来源**:[领料配置] 工作表
|
||||
|
||||
| 列 | 字段 | 说明 |
|
||||
|----|------|------|
|
||||
| A | code | 物料代号 |
|
||||
| C | catName | 类别名称 |
|
||||
| D | parentCatName | 上层类别名称 |
|
||||
|
||||
**数据结构**:
|
||||
```
|
||||
dictCategories: Dictionary<String, clsCategory>
|
||||
├── "表壳" → clsCategory{categoryName, materials[], SubCategories[]}
|
||||
├── "部件" → clsCategory{...}
|
||||
└── ...
|
||||
```
|
||||
|
||||
**关键代码**:
|
||||
```vba
|
||||
lastRow = wsConfig.Cells(wsConfig.Rows.Count, "A").End(xlUp).row
|
||||
For i = 2 To lastRow
|
||||
code = Trim(wsConfig.Cells(i, "A").value & "")
|
||||
catName = Trim(wsConfig.Cells(i, "C").value & "")
|
||||
parentCatName = Trim(wsConfig.Cells(i, "D").value & "")
|
||||
|
||||
If code = "" Then GoTo NextRow
|
||||
|
||||
If Not dictCategories.Exists(catName) Then
|
||||
Set cat = New clsCategory
|
||||
cat.categoryName = catName
|
||||
cat.ParentCategoryName = parentCatName
|
||||
Set dictCategories(catName) = cat
|
||||
End If
|
||||
|
||||
If dictAllMaterials.Exists(code) Then
|
||||
Set mat = dictAllMaterials(code)
|
||||
mat.Category = catName
|
||||
mat.ParentCategory = parentCatName
|
||||
dictCategories(catName).AddMaterial mat
|
||||
End If
|
||||
Next i
|
||||
```
|
||||
|
||||
**业务逻辑说明**:
|
||||
- 只有出现在 [领料配置] 中的物料才会被添加到类别中
|
||||
- 未在 [领料配置] 中的物料表示不需要领料
|
||||
|
||||
---
|
||||
|
||||
### 第三步:建立类别层级关系
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S3_Start([开始第三步]) --> S3_Loop{遍历 dictCategories<br/>所有键}
|
||||
S3_Loop -->|下一个键| S3_GetCat[获取类别对象 cat]
|
||||
S3_GetCat --> S3_CheckParent{ParentCategoryName<br/>是否为空?}
|
||||
S3_CheckParent -->|否, 有父类别| S3_ParentExists{父类别<br/>存在?}
|
||||
S3_CheckParent -->|是, 无父类别| S3_AddRoot[添加到 rootCategories<br/>作为根类别]
|
||||
S3_ParentExists -->|是| S3_AddSub[添加到父类别的<br/>SubCategories 集合]
|
||||
S3_ParentExists -->|否| S3_Orphan[父类别不存在<br/>跳过建立关系]
|
||||
S3_AddRoot --> S3_Next
|
||||
S3_AddSub --> S3_Next
|
||||
S3_Orphan --> S3_Next
|
||||
S3_Next --> S3_Loop
|
||||
S3_Loop -->|遍历完成| S3_End([第三步完成])
|
||||
|
||||
style S3_Start fill:#e1f5e1
|
||||
style S3_End fill:#ffe1e1
|
||||
style S3_AddRoot fill:#ffccbc
|
||||
style S3_AddSub fill:#b2dfdb
|
||||
```
|
||||
|
||||
**数据结构**:
|
||||
```
|
||||
rootCategories: Collection<clsCategory>
|
||||
├── "表壳" (根类别)
|
||||
├── "部件" (根类别)
|
||||
│ └── SubCategories:
|
||||
│ ├── "接头" (子类别)
|
||||
│ └── "弹性元件" (子类别)
|
||||
└── "机芯" (根类别)
|
||||
```
|
||||
|
||||
**关键代码**:
|
||||
```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
|
||||
```
|
||||
|
||||
**层级关系构建逻辑**:
|
||||
1. 遍历所有类别
|
||||
2. 如果类别有父类别 → 建立父子关系(调用父类别的 `AddSubCategory` 方法)
|
||||
3. 如果类别无父类别 → 作为根类别,添加到 `rootCategories`
|
||||
|
||||
---
|
||||
|
||||
## 数据结构总结
|
||||
|
||||
### 类的私有成员变量
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class clsBOMManager {
|
||||
-dictCategories: Dictionary
|
||||
-dictAllMaterials: Dictionary
|
||||
-rootCategories: Collection
|
||||
+LoadData(wsConfig, wsPlatform)
|
||||
+GetRootCategories() Collection
|
||||
+GetCategory(categoryName) clsCategory
|
||||
}
|
||||
|
||||
class clsCategory {
|
||||
+categoryName: String
|
||||
+ParentCategoryName: String
|
||||
+materials: Collection
|
||||
+SubCategories: Collection
|
||||
+AddMaterial(mat)
|
||||
+AddSubCategory(cat)
|
||||
+HasSubCategories: Boolean
|
||||
}
|
||||
|
||||
class clsMaterialItem {
|
||||
+code: String
|
||||
+Name: String
|
||||
+Quantity: Double
|
||||
+Condition: String
|
||||
+Category: String
|
||||
+ParentCategory: 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 WSConfig as [领料配置]
|
||||
participant DictMat as dictAllMaterials
|
||||
participant DictCat as dictCategories
|
||||
participant RootCats as rootCategories
|
||||
|
||||
Caller->>LoadData: LoadData(wsConfig, wsPlatform)
|
||||
|
||||
Note over LoadData, WSPlatform: 第一步: 加载物料库
|
||||
LoadData->>WSPlatform: 读取第4-末行, C-F列
|
||||
WSPlatform-->>LoadData: 返回物料数据
|
||||
loop 每一行物料
|
||||
LoadData->>DictMat: 添加物料 (代号→对象)
|
||||
end
|
||||
|
||||
Note over LoadData, WSConfig: 第二步: 建立类别与物料关联
|
||||
LoadData->>WSConfig: 读取第2-末行, A/C/D列
|
||||
WSConfig-->>LoadData: 返回类别配置
|
||||
loop 每一行配置
|
||||
LoadData->>DictCat: 类别存在?
|
||||
alt 类别不存在
|
||||
LoadData->>DictCat: 创建新类别
|
||||
end
|
||||
LoadData->>DictMat: 查找物料信息
|
||||
alt 物料存在
|
||||
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. 类别层级规则
|
||||
- 根类别:`ParentCategoryName` 为空字符串 `""`
|
||||
- 子类别:`ParentCategoryName` 指向父类别名称
|
||||
- 层级深度:无限制(支持任意深度的树形结构)
|
||||
|
||||
### 3. 数据一致性
|
||||
- 所有物料必须先在 [平台配置清单] 中定义
|
||||
- [领料配置] 中的物料代号必须在 `dictAllMaterials` 中存在
|
||||
- 如果不存在,该物料会被跳过(不会报错)
|
||||
|
||||
---
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 调用 LoadData
|
||||
|
||||
```vba
|
||||
Dim bomMgr As New clsBOMManager
|
||||
Dim wsConfig As Worksheet
|
||||
Dim wsPlatform As Worksheet
|
||||
|
||||
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
|
||||
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
|
||||
|
||||
' 加载数据
|
||||
Call bomMgr.LoadData(wsConfig, wsPlatform)
|
||||
|
||||
' 获取根类别
|
||||
Dim rootCats As Collection
|
||||
Set rootCats = bomMgr.GetRootCategories()
|
||||
|
||||
' 遍历所有根类别
|
||||
Dim i As Long
|
||||
For i = 1 To rootCats.Count
|
||||
Debug.Print "根类别: " & rootCats(i).categoryName
|
||||
Next i
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 执行后的数据结构示例
|
||||
|
||||
假设加载后的数据结构如下:
|
||||
|
||||
```
|
||||
dictAllMaterials:
|
||||
{
|
||||
"01091004312" → {code: "01091004312", Name: "表壳(本色)", Quantity: 1, Condition: ""},
|
||||
"01011019001" → {code: "01011019001", Name: "低压接头部件", Quantity: 1, Condition: "lcfw=M02"},
|
||||
"01081013833" → {code: "01081013833", Name: "径向低压接头", Quantity: 1, Condition: "gclj=Z12"}
|
||||
}
|
||||
|
||||
dictCategories:
|
||||
{
|
||||
"表壳" → {categoryName: "表壳", ParentCategoryName: "", materials: [01091004312], SubCategories: []},
|
||||
"部件" → {categoryName: "部件", ParentCategoryName: "", materials: [01011019001], SubCategories: ["接头", "弹性元件"]},
|
||||
"接头" → {categoryName: "接头", ParentCategoryName: "部件", materials: [01081013833], SubCategories: []}
|
||||
}
|
||||
|
||||
rootCategories:
|
||||
[
|
||||
"表壳" (clsCategory),
|
||||
"部件" (clsCategory),
|
||||
"机芯" (clsCategory)
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
LoadData 方法本身不包含显式的错误处理(`On Error`),依赖以下机制:
|
||||
|
||||
1. **空值处理**:使用 `& ""` 确保字符串转换不会失败
|
||||
2. **类型转换**:使用 `CDbl()` 时没有错误处理,假设数据格式正确
|
||||
3. **跳过机制**:物料代号为空时,使用 `GoTo NextRow` 跳过
|
||||
4. **存在性检查**:使用 `Dictionary.Exists()` 避免键不存在错误
|
||||
|
||||
---
|
||||
|
||||
## 相关方法
|
||||
|
||||
LoadData 执行后,可以使用以下方法访问数据:
|
||||
|
||||
| 方法 | 说明 |
|
||||
|------|------|
|
||||
| `GetRootCategories()` | 获取所有顶层类别 |
|
||||
| `GetCategory(categoryName)` | 根据名称获取类别对象 |
|
||||
| `GetMaterialsByModel()` | 根据型号获取物料 |
|
||||
| `GetValidMaterialsByModel()` | 获取物料并检查完整性 |
|
||||
| `PrintCategoryTree()` | 打印类别树(调试用) |
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
`LoadData` 方法通过三个阶段构建完整的 BOM 数据结构:
|
||||
|
||||
1. **数据收集**:从 [平台配置清单] 收集所有物料基础信息
|
||||
2. **数据关联**:从 [领料配置] 建立类别与物料的关联
|
||||
3. **结构构建**:构建类别的树形层级关系
|
||||
|
||||
最终形成的数据结构支持:
|
||||
- 快速按代号查找物料
|
||||
- 快速按类别查找物料
|
||||
- 遍历完整的类别树
|
||||
- 支持父类别/子类别的领料逻辑
|
||||
Reference in New Issue
Block a user