- Introduced a comprehensive document detailing the project overview, goals, core functionalities, and technical architecture for the order material extraction feature. - Defined the product model coding rules and extraction logic for selection conditions. - Designed class structures for model parsing, condition evaluation, and order material list management. - Outlined implementation steps, testing plans, and risk assessments for the development process.
546 lines
15 KiB
Markdown
546 lines
15 KiB
Markdown
# clsBOMManager 类使用说明
|
||
|
||
## 概述
|
||
|
||
`clsBOMManager` 是 AutoBOM 系统的核心控制器类,负责管理整个 BOM(物料清单)数据结构。它从 Excel 工作表加载数据,构建层级化的类别树,并提供物料查询和领料逻辑处理功能。
|
||
|
||
---
|
||
|
||
## 类初始化
|
||
|
||
```vba
|
||
Dim bomMgr As New clsBOMManager
|
||
```
|
||
|
||
创建实例时,会自动初始化以下内部数据结构:
|
||
- `dictCategories` - 类别字典(类别名称 → clsCategory 对象)
|
||
- `dictAllMaterials` - 物料字典(物料代号 → clsMaterialItem 对象)
|
||
- `rootCategories` - 根类别集合(顶层类别)
|
||
|
||
---
|
||
|
||
## 公开方法
|
||
|
||
### 1. LoadData 方法
|
||
|
||
**功能**:从 Excel 工作表加载 BOM 数据并构建数据结构
|
||
|
||
**语法**:
|
||
```vba
|
||
Public Sub LoadData(wsConfig As Worksheet, wsPlatform As Worksheet)
|
||
```
|
||
|
||
**参数**:
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| wsConfig | Worksheet | 领料配置工作表,定义类别层级和需要领料的物料 |
|
||
| wsPlatform | Worksheet | 平台配置清单工作表,包含完整的物料信息 |
|
||
|
||
**数据要求**:
|
||
|
||
**领料配置** 工作表格式:
|
||
- **第 1 行**:标题行
|
||
- **第 2 行起**:数据行
|
||
- A 列:物料代号
|
||
- C 列:类别名称
|
||
- D 列:上层类别名称
|
||
|
||
**平台配置清单** 工作表格式:
|
||
- **第 1-3 行**:标题行
|
||
- **第 4 行起**:数据行
|
||
- C 列:物料代号
|
||
- D 列:物料名称
|
||
- E 列:物料数量
|
||
- F 列:选择条件
|
||
|
||
**处理逻辑**:
|
||
1. 从"平台配置清单"加载所有物料的基础信息到 `dictAllMaterials`
|
||
2. 从"领料配置"加载类别信息,筛选需要领料的物料
|
||
3. 建立类别的父子关系,构建层级树
|
||
|
||
**重要说明**:
|
||
- 只有出现在"领料配置"中的物料才会被添加到类别中
|
||
- 未在"领料配置"中的物料表示不需要领料,但仍存在于物料字典中
|
||
|
||
**使用示例**:
|
||
```vba
|
||
Dim bomMgr As New clsBOMManager
|
||
Dim wsConfig As Worksheet
|
||
Dim wsPlatform As Worksheet
|
||
|
||
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
|
||
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
|
||
|
||
bomMgr.LoadData wsConfig, wsPlatform
|
||
```
|
||
|
||
---
|
||
|
||
### 2. GetRootCategories 方法
|
||
|
||
**功能**:获取所有顶层类别的集合
|
||
|
||
**语法**:
|
||
```vba
|
||
Public Function GetRootCategories() As Collection
|
||
```
|
||
|
||
**返回值**:
|
||
- `Collection` 对象,包含所有无父类别的 `clsCategory` 对象
|
||
|
||
**用途**:
|
||
- 遍历整个 BOM 结构时的入口点
|
||
- 生成领料清单时遍历所有根类别
|
||
|
||
**使用示例**:
|
||
```vba
|
||
Dim rootCats As Collection
|
||
Dim cat As clsCategory
|
||
Dim i As Long
|
||
|
||
Set rootCats = bomMgr.GetRootCategories()
|
||
|
||
For i = 1 To rootCats.Count
|
||
Set cat = rootCats(i)
|
||
Debug.Print "根类别: " & cat.categoryName
|
||
Debug.Print " 物料数: " & cat.Materials.Count
|
||
Debug.Print " 子类别数: " & cat.SubCategories.Count
|
||
Next i
|
||
```
|
||
|
||
---
|
||
|
||
### 3. GetCategory 方法
|
||
|
||
**功能**:根据类别名称获取类别对象
|
||
|
||
**语法**:
|
||
```vba
|
||
Public Function GetCategory(categoryName As String) As clsCategory
|
||
```
|
||
|
||
**参数**:
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| categoryName | String | 要查询的类别名称 |
|
||
|
||
**返回值**:
|
||
- 找到时:返回 `clsCategory` 对象
|
||
- 未找到时:返回 `Nothing`
|
||
|
||
**用途**:快速查找特定类别及其下的物料
|
||
|
||
**使用示例**:
|
||
```vba
|
||
Dim cat As clsCategory
|
||
Set cat = bomMgr.GetCategory("部件")
|
||
|
||
If Not cat Is Nothing Then
|
||
Debug.Print "类别: " & cat.categoryName
|
||
Debug.Print "父类别: " & cat.ParentCategoryName
|
||
Debug.Print "物料数: " & cat.Materials.Count
|
||
Debug.Print "是否叶子类别: " & cat.IsLeafCategory
|
||
End If
|
||
```
|
||
|
||
---
|
||
|
||
### 4. GetMaterialsForPicking 方法
|
||
|
||
**功能**:获取某类别下需要领料的物料清单(支持层级逻辑)
|
||
|
||
**语法**:
|
||
```vba
|
||
Public Function GetMaterialsForPicking(categoryName As String, _
|
||
Optional useParent As Boolean = True) As Collection
|
||
```
|
||
|
||
**参数**:
|
||
| 参数 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| categoryName | String | - | 类别名称 |
|
||
| useParent | Boolean | True | 领料方式:True=父类别物料,False=子类别物料 |
|
||
|
||
**返回值**:
|
||
- `Collection` 对象,包含 `clsMaterialItem` 对象
|
||
|
||
**业务逻辑说明**:
|
||
|
||
#### 父类别模式 (useParent=True)
|
||
- 这是**默认的领料方式**
|
||
- 直接返回当前类别下的所有物料
|
||
- 即使该类别有子类别,也仍然返回父类别物料
|
||
- 用于领取组装好的部件
|
||
|
||
**示例**:
|
||
```vba
|
||
' 获取"部件"类别的父类别物料
|
||
Set materials = bomMgr.GetMaterialsForPicking("部件", True)
|
||
' 返回:低压接头部件、高压接头部件等组装好的部件
|
||
```
|
||
|
||
#### 子类别模式 (useParent=False)
|
||
- 这是**库存不足时的替代方案**
|
||
- 如果当前类别有子类别,递归获取所有子类别的物料
|
||
- 如果当前类别是叶子类别(无子类别),返回本类别物料
|
||
- 用于父类别库存不足,需要领取零件自行组装的情况
|
||
|
||
**示例**:
|
||
```vba
|
||
' 获取"部件"类别的子类别展开物料
|
||
Set materials = bomMgr.GetMaterialsForPicking("部件", False)
|
||
' 返回:径向低压接头、弹簧管、螺旋管等零件
|
||
```
|
||
|
||
**层级结构示例**:
|
||
|
||
```
|
||
部件 (父类别)
|
||
├── 低压接头部件 (物料)
|
||
├── 高压接头部件 (物料)
|
||
└── 接头 (子类别)
|
||
├── 径向低压接头 (物料)
|
||
├── 轴向高压接头 (物料)
|
||
└── 弹性元件 (孙类别)
|
||
└── 弹簧管 (物料)
|
||
```
|
||
|
||
**使用示例**:
|
||
```vba
|
||
Dim materials As Collection
|
||
Dim mat As clsMaterialItem
|
||
Dim i As Long
|
||
|
||
' 默认使用父类别物料
|
||
Set materials = bomMgr.GetMaterialsForPicking("部件", True)
|
||
Debug.Print "父类别物料数: " & materials.Count
|
||
|
||
For i = 1 To materials.Count
|
||
Set mat = materials(i)
|
||
Debug.Print mat.code & " - " & mat.Name & _
|
||
" | 数量:" & mat.Quantity & _
|
||
" | 条件:" & mat.Condition
|
||
Next i
|
||
|
||
' 库存不足时,使用子类别物料
|
||
Set materials = bomMgr.GetMaterialsForPicking("部件", False)
|
||
Debug.Print "子类别展开物料数: " & materials.Count
|
||
```
|
||
|
||
---
|
||
|
||
### 5. PrintCategoryTree 方法
|
||
|
||
**功能**:将类别树结构打印到工作表(用于调试和查看)
|
||
|
||
**语法**:
|
||
```vba
|
||
Public Sub PrintCategoryTree(ws As Worksheet)
|
||
```
|
||
|
||
**参数**:
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| ws | Worksheet | 输出的目标工作表对象 |
|
||
|
||
**输出格式**:
|
||
- 第 1 列:类别名称(带缩进显示层级)
|
||
- 第 2 列:物料数量信息
|
||
- 第 3 列:选择条件
|
||
|
||
**缩进规则**:每层级 2 个空格
|
||
|
||
**输出示例**:
|
||
```
|
||
表壳 (物料数:1)
|
||
- 01091004312 表壳(本色) 数量:1 条件:
|
||
部件 (物料数:20)
|
||
- 01011019001 低压接头部件 数量:1 条件:lcfw=M02...
|
||
接头 (物料数:18)
|
||
- 01081013833 径向低压接头 数量:1 条件:gclj=Z12...
|
||
```
|
||
|
||
**使用示例**:
|
||
```vba
|
||
Dim wsOutput As Worksheet
|
||
|
||
' 创建新工作表
|
||
On Error Resume Next
|
||
Application.DisplayAlerts = False
|
||
ThisWorkbook.Worksheets("BOM结构").Delete
|
||
Application.DisplayAlerts = True
|
||
On Error GoTo 0
|
||
|
||
Set wsOutput = ThisWorkbook.Worksheets.Add
|
||
wsOutput.Name = "BOM结构"
|
||
|
||
' 打印类别树
|
||
bomMgr.PrintCategoryTree wsOutput
|
||
```
|
||
|
||
---
|
||
|
||
## 典型使用场景
|
||
|
||
### 场景 1:生成领料清单
|
||
|
||
```vba
|
||
Sub GeneratePickingList()
|
||
Dim bomMgr As New clsBOMManager
|
||
Dim wsConfig As Worksheet, wsPlatform As Worksheet
|
||
Dim wsPickList As Worksheet
|
||
Dim rootCats As Collection
|
||
Dim cat As clsCategory
|
||
Dim materials As Collection
|
||
Dim mat As clsMaterialItem
|
||
Dim row As Long
|
||
Dim i As Long, j As Long
|
||
|
||
' 1. 加载数据
|
||
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
|
||
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
|
||
bomMgr.LoadData wsConfig, wsPlatform
|
||
|
||
' 2. 创建输出工作表
|
||
Application.DisplayAlerts = False
|
||
On Error Resume Next
|
||
ThisWorkbook.Worksheets("领料清单").Delete
|
||
On Error GoTo 0
|
||
Application.DisplayAlerts = True
|
||
|
||
Set wsPickList = ThisWorkbook.Worksheets.Add
|
||
wsPickList.Name = "领料清单"
|
||
|
||
' 3. 写入表头
|
||
row = 1
|
||
wsPickList.Cells(row, 1).Value = "代号"
|
||
wsPickList.Cells(row, 2).Value = "名称"
|
||
wsPickList.Cells(row, 3).Value = "类别"
|
||
wsPickList.Cells(row, 4).Value = "数量"
|
||
wsPickList.Cells(row, 5).Value = "选择条件"
|
||
wsPickList.Cells(row, 6).Value = "领料方式"
|
||
row = row + 1
|
||
|
||
' 4. 遍历所有根类别并生成清单
|
||
Set rootCats = bomMgr.GetRootCategories
|
||
|
||
For i = 1 To rootCats.Count
|
||
Set cat = rootCats(i)
|
||
' 默认使用父类别物料
|
||
Set materials = bomMgr.GetMaterialsForPicking(cat.categoryName, True)
|
||
|
||
For j = 1 To materials.Count
|
||
Set mat = materials(j)
|
||
wsPickList.Cells(row, 1).Value = mat.code
|
||
wsPickList.Cells(row, 2).Value = mat.Name
|
||
wsPickList.Cells(row, 3).Value = mat.Category
|
||
wsPickList.Cells(row, 4).Value = mat.Quantity
|
||
wsPickList.Cells(row, 5).Value = mat.Condition
|
||
wsPickList.Cells(row, 6).Value = "父类别"
|
||
row = row + 1
|
||
Next j
|
||
Next i
|
||
|
||
' 5. 格式化表格
|
||
wsPickList.Range("A1:F1").Font.Bold = True
|
||
wsPickList.Columns("A:F").AutoFit
|
||
|
||
MsgBox "领料清单生成完成!", vbInformation
|
||
End Sub
|
||
```
|
||
|
||
### 场景 2:查询特定类别信息
|
||
|
||
```vba
|
||
Sub QueryCategoryInfo()
|
||
Dim bomMgr As New clsBOMManager
|
||
Dim wsConfig As Worksheet, wsPlatform As Worksheet
|
||
Dim cat As clsCategory
|
||
Dim mat As clsMaterialItem
|
||
Dim subCat As clsCategory
|
||
Dim i As Long
|
||
|
||
' 加载数据
|
||
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
|
||
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
|
||
bomMgr.LoadData wsConfig, wsPlatform
|
||
|
||
' 查询特定类别
|
||
Set cat = bomMgr.GetCategory("部件")
|
||
|
||
If Not cat Is Nothing Then
|
||
Debug.Print "========== 类别信息 =========="
|
||
Debug.Print "类别名称: " & cat.categoryName
|
||
Debug.Print "父类别: " & cat.ParentCategoryName
|
||
Debug.Print "物料数量: " & cat.Materials.Count
|
||
Debug.Print "子类别数量: " & cat.SubCategories.Count
|
||
Debug.Print "是否叶子类别: " & cat.IsLeafCategory
|
||
Debug.Print ""
|
||
|
||
' 列出所有物料
|
||
Debug.Print "---------- 物料列表 ----------"
|
||
For i = 1 To cat.Materials.Count
|
||
Set mat = cat.Materials(i)
|
||
Debug.Print " " & mat.code & ": " & mat.Name & _
|
||
" (数量:" & mat.Quantity & _
|
||
", 条件:" & mat.Condition & ")"
|
||
Next i
|
||
Debug.Print ""
|
||
|
||
' 列出所有子类别
|
||
Debug.Print "---------- 子类别列表 ----------"
|
||
For i = 1 To cat.SubCategories.Count
|
||
Set subCat = cat.SubCategories(i)
|
||
Debug.Print " " & subCat.categoryName & _
|
||
" (物料数:" & subCat.Materials.Count & ")"
|
||
Next i
|
||
Else
|
||
Debug.Print "类别不存在"
|
||
End If
|
||
End Sub
|
||
```
|
||
|
||
### 场景 3:根据库存情况选择领料方式
|
||
|
||
```vba
|
||
Sub SmartPicking()
|
||
Dim bomMgr As New clsBOMManager
|
||
Dim materials As Collection
|
||
Dim mat As clsMaterialItem
|
||
Dim categoryName As String
|
||
Dim i As Long
|
||
|
||
' 加载数据
|
||
bomMgr.LoadData _
|
||
ThisWorkbook.Worksheets("领料配置"), _
|
||
ThisWorkbook.Worksheets("平台配置清单")
|
||
|
||
categoryName = "部件"
|
||
|
||
' 尝试获取父类别物料
|
||
Set materials = bomMgr.GetMaterialsForPicking(categoryName, True)
|
||
|
||
' 检查库存是否充足(这里需要连接实际的库存系统)
|
||
Dim isStockSufficient As Boolean
|
||
isStockSufficient = CheckStock(materials) ' 假设的库存检查函数
|
||
|
||
If isStockSufficient Then
|
||
Debug.Print "使用父类别领料方式"
|
||
Else
|
||
Debug.Print "父类别库存不足,改用子类别领料方式"
|
||
Set materials = bomMgr.GetMaterialsForPicking(categoryName, False)
|
||
End If
|
||
|
||
' 输出物料清单
|
||
For i = 1 To materials.Count
|
||
Set mat = materials(i)
|
||
Debug.Print mat.code & " " & mat.Name
|
||
Next i
|
||
End Sub
|
||
```
|
||
|
||
---
|
||
|
||
## 辅助类说明
|
||
|
||
### clsCategory 类
|
||
|
||
表示物料类别及其层级关系。
|
||
|
||
**公共属性**:
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| categoryName | String | 类别名称 |
|
||
| ParentCategoryName | String | 父类别名称 |
|
||
| Materials | Collection | 该类别下的物料集合 |
|
||
| SubCategories | Collection | 子类别集合 |
|
||
| IsLeafCategory | Boolean | 是否为叶子类别(无子类别) |
|
||
|
||
**公共方法**:
|
||
- `AddMaterial(mat As clsMaterialItem)` - 添加物料
|
||
- `AddSubCategory(cat As clsCategory)` - 添加子类别
|
||
- `GetMaterial(code As String) As clsMaterialItem` - 获取指定代号的物料
|
||
- `HasSubCategories() As Boolean` - 检查是否有子类别
|
||
|
||
### clsMaterialItem 类
|
||
|
||
表示单个物料项。
|
||
|
||
**公共属性**:
|
||
| 属性 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| code | String | 物料代号 |
|
||
| Name | String | 物料名称 |
|
||
| Quantity | Double | 物料数量 |
|
||
| Condition | String | 选择条件 |
|
||
| Category | String | 所属类别 |
|
||
| ParentCategory | String | 上层类别 |
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
1. **数据加载顺序**:必须先调用 `LoadData()` 方法,才能使用其他查询方法
|
||
|
||
2. **工作表名称**:确保工作表名称与代码中的名称一致:
|
||
- "领料配置"
|
||
- "平台配置清单"
|
||
|
||
3. **空值处理**:使用 `GetCategory()` 方法时,务必检查返回值是否为 `Nothing`
|
||
|
||
4. **领料方式选择**:
|
||
- 正常情况使用 `useParent=True`(领取组装好的部件)
|
||
- 仅在库存不足时使用 `useParent=False`(领取零件自行组装)
|
||
|
||
5. **数据一致性**:修改 Excel 数据后,需要重新调用 `LoadData()` 重新加载数据
|
||
|
||
6. **内存管理**:使用完毕后,VBA 会自动清理对象,无需手动释放
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 如何判断某个类别是否存在?
|
||
```vba
|
||
Dim cat As clsCategory
|
||
Set cat = bomMgr.GetCategory("类别名")
|
||
|
||
If Not cat Is Nothing Then
|
||
' 类别存在
|
||
Else
|
||
' 类别不存在
|
||
End If
|
||
```
|
||
|
||
### Q2: 如何获取所有类别的名称?
|
||
```vba
|
||
Sub ListAllCategories()
|
||
' 需要递归遍历所有类别
|
||
' 可以使用 PrintCategoryTree 方法输出到工作表查看
|
||
End Sub
|
||
```
|
||
|
||
### Q3: 父类别和子类别物料有什么区别?
|
||
- **父类别物料**:组装好的成品部件,如"低压接头部件"
|
||
- **子类别物料**:组成部件的零件,如"径向低压接头"、"弹簧管"等
|
||
|
||
### Q4: 如何处理物料选择条件?
|
||
```vba
|
||
Dim mat As clsMaterialItem
|
||
' ...
|
||
If mat.Condition <> "" Then
|
||
' 根据条件选择合适的物料
|
||
' 条件格式如:lcfw=M02;gclj=Z12
|
||
' 需要根据产品配置解析这些条件
|
||
End If
|
||
```
|
||
|
||
---
|
||
|
||
## 版本信息
|
||
|
||
- **类名称**:clsBOMManager
|
||
- **版本**:1.0
|
||
- **最后更新**:2025
|
||
- **依赖类**:clsCategory, clsMaterialItem
|