feat: add implementation plan for order material extraction functionality

- 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.
This commit is contained in:
Misaka_Company
2026-01-20 10:45:23 +08:00
parent 05601ec1fc
commit bc5ea92c52
6 changed files with 2057 additions and 16 deletions

View File

@@ -19,15 +19,15 @@ Sub TestBOMStructure()
bomMgr.LoadData wsConfig, wsPlatform
' 打印类别树结构到新工作表
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结构"
' 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
@@ -40,7 +40,7 @@ Sub TestBOMStructure()
MsgBox "BOM数据结构加载完成!" & vbCrLf & _
'MsgBox "BOM数据结构加载完成!" & vbCrLf & _
"请查看 'BOM结构' 工作表", vbInformation
End Sub
@@ -139,6 +139,64 @@ Sub GeneratePickingList()
MsgBox "领料清单生成完成!", vbInformation
End Sub
' 示例: 在立即窗口打印领料清单
Sub PrintPickingList()
Dim bomMgr As New clsBOMManager
Dim wsConfig As Worksheet, wsPlatform As Worksheet
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
bomMgr.LoadData wsConfig, wsPlatform
' 打印表头
Debug.Print String(80, "=")
Debug.Print "领料清单"
Debug.Print String(80, "=")
' 遍历所有根类别
Dim rootCats As Collection
Set rootCats = bomMgr.GetRootCategories
Dim cat As clsCategory
Dim Materials As Collection
Dim mat As clsMaterialItem
Dim i As Long, j As Long
Dim totalCount As Long
totalCount = 0
For i = 1 To rootCats.Count
Set cat = rootCats(i)
' 打印类别分隔符
Debug.Print ""
Debug.Print "【类别: " & cat.categoryName & "】"
Debug.Print String(40, "-")
' 默认使用父类别物料
Set Materials = bomMgr.GetMaterialsForPicking(cat.categoryName, True)
For j = 1 To Materials.Count
Set mat = Materials(j)
Debug.Print " " & mat.code & _
String(20 - Len(mat.code), " ") & _
mat.Name & _
" | 数量:" & mat.Quantity & _
" | 条件:" & IIf(mat.Condition = "", "(无)", mat.Condition)
totalCount = totalCount + 1
Next j
Debug.Print " 小计: " & Materials.Count & " 项"
Next i
' 打印汇总
Debug.Print ""
Debug.Print String(80, "=")
Debug.Print "总计: " & totalCount & " 项物料"
Debug.Print String(80, "=")
End Sub
' 示例: 查询特定物料信息
Sub QueryMaterialInfo()
Dim bomMgr As New clsBOMManager

View File

@@ -0,0 +1,545 @@
# 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

View File

@@ -31,6 +31,12 @@
"attributes": {},
"file": "DocumentModules\\Sheet4.cls"
},
"Sheet6.cls": {
"name": "Sheet6",
"type": "DocumentModules",
"attributes": {},
"file": "DocumentModules\\Sheet6.cls"
},
"clsCategory.cls": {
"name": "clsCategory",
"type": "ClassModules",
@@ -54,12 +60,6 @@
"type": "ClassModules",
"attributes": {},
"file": "ClassModules\\clsBOMManager.cls"
},
"Sheet6.cls": {
"name": "Sheet6",
"type": "DocumentModules",
"attributes": {},
"file": "DocumentModules\\Sheet6.cls"
}
}
}