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>
This commit is contained in:
@@ -31,33 +31,44 @@ End Sub
|
||||
|
||||
' ========================================
|
||||
' LoadData 方法
|
||||
' 功能: 从Excel工作表加载BOM数据并构建数据结构
|
||||
' 功能: 从[平台配置清单]工作表加载BOM数据并构建数据结构
|
||||
' 参数:
|
||||
' wsConfig - [领料配置]工作表对象,包含类别层级和需要领料的物料
|
||||
' wsPlatform - [平台配置清单]工作表对象,包含完整的物料信息(代号/名称/数量/条件)
|
||||
' wsPlatform - [平台配置清单]工作表对象,包含完整的物料信息和类别配置
|
||||
' 表结构: 行号|模块|代号|名称|数量|选择条件|备注|类别|上层类别|类别选用条件|66代码
|
||||
' 数据从第4行开始(前3行是标题)
|
||||
' 处理步骤:
|
||||
' 1. 从[平台配置清单]加载所有物料的基础信息到dictAllMaterials
|
||||
' 2. 从[领料配置]加载类别信息,筛选需要领料的物料
|
||||
' 3. 建立类别的父子关系,构建层级树
|
||||
' 注意:
|
||||
' - 只有出现在[领料配置]中的物料才会被添加到类别中
|
||||
' - 未在[领料配置]中的物料表示不需要领料
|
||||
' 1. 从[平台配置清单]一次性加载所有物料信息和类别信息
|
||||
' 2. 建立类别的父子关系,构建层级树
|
||||
'
|
||||
' 重要说明:
|
||||
' - 所有数据都从[平台配置清单]读取,不再需要[领料配置]表
|
||||
' - 只有"类别"字段不为空的物料才会被添加到类别中
|
||||
' - "类别选用条件"用于判断该类别是否需要(为空表示总是需要)
|
||||
' - "66代码"是66系统使用的代码
|
||||
' ========================================
|
||||
Public Sub LoadData(wsConfig As Worksheet, wsPlatform As Worksheet)
|
||||
Public Sub LoadData(wsPlatform As Worksheet)
|
||||
Dim i As Long, lastRow As Long
|
||||
Dim mat As clsMaterialItem
|
||||
Dim cat As clsCategory
|
||||
|
||||
' ========================================
|
||||
' 第一步: 从平台配置清单加载所有物料的基础信息
|
||||
' 第一步: 从平台配置清单加载所有物料和类别信息
|
||||
' 说明:
|
||||
' - 读取C列(代号)、D列(名称)、E列(数量)、F列(选择条件)
|
||||
' 读取列说明:
|
||||
' - C列(代号)、D列(名称)、E列(数量)、F列(选择条件)
|
||||
' - H列(类别)、I列(上层类别)、J列(类别选用条件)、K列(66代码)
|
||||
' - 从第4行开始读取(前3行是标题)
|
||||
' - 所有物料存入dictAllMaterials字典,以代号为键
|
||||
' 目的: 建立完整的物料信息库,供后续按代号查询
|
||||
'
|
||||
' 处理逻辑:
|
||||
' 1. 所有物料都存入dictAllMaterials字典(包括无类别的物料)
|
||||
' 2. 只有"类别"字段不为空的物料才创建类别并添加到类别中
|
||||
' 3. 类别对象保存CategorySelectCondition属性
|
||||
' 4. 物料对象保存CategorySelectCondition和Code66属性
|
||||
' ========================================
|
||||
lastRow = wsPlatform.Cells(wsPlatform.Rows.Count, "C").End(xlUp).row
|
||||
|
||||
For i = 4 To lastRow ' 从第4行开始(跳过标题)
|
||||
' 1. 创建物料对象并读取基础信息
|
||||
Set mat = New clsMaterialItem
|
||||
mat.code = Trim(wsPlatform.Cells(i, "C").value & "") ' 物料代号
|
||||
mat.Name = Trim(wsPlatform.Cells(i, "D").value & "") ' 物料名称
|
||||
@@ -66,55 +77,46 @@ Public Sub LoadData(wsConfig As Worksheet, wsPlatform As Worksheet)
|
||||
On Error GoTo 0
|
||||
mat.Condition = Trim(wsPlatform.Cells(i, "F").value & "") ' 选择条件
|
||||
|
||||
' 只保存代号非空的物料
|
||||
' 2. 读取类别相关字段
|
||||
Dim catName As String
|
||||
Dim parentCatName As String
|
||||
Dim catSelectCond As String
|
||||
Dim code66 As String
|
||||
|
||||
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 & "") ' 66代码
|
||||
|
||||
' 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
|
||||
|
||||
' ========================================
|
||||
' 第二步: 从领料配置加载类别信息并建立层级
|
||||
' 说明:
|
||||
' - 读取A列(代号)、C列(类别)、D列(上层类别)
|
||||
' - 从第2行开始读取(第1行是标题)
|
||||
' - 只有出现在此表中的物料才需要领料
|
||||
' 处理逻辑:
|
||||
' 1. 为每个类别创建clsCategory对象
|
||||
' 2. 从dictAllMaterials中查找对应的物料信息
|
||||
' 3. 将物料添加到对应的类别中
|
||||
' ========================================
|
||||
lastRow = wsConfig.Cells(wsConfig.Rows.Count, "A").End(xlUp).row
|
||||
For i = 2 To lastRow ' 从第2行开始
|
||||
Dim code As String, catName As String, parentCatName As String
|
||||
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
|
||||
|
||||
' 将物料添加到类别
|
||||
' 注意: 必须先在dictAllMaterials中查找到完整的物料信息
|
||||
If dictAllMaterials.Exists(code) Then
|
||||
Set mat = dictAllMaterials(code)
|
||||
mat.Category = catName ' 设置物料所属类别
|
||||
mat.ParentCategory = parentCatName ' 设置物料的上层类别
|
||||
dictCategories(catName).AddMaterial mat ' 将物料添加到类别对象中
|
||||
End If
|
||||
|
||||
NextRow:
|
||||
Next i
|
||||
|
||||
' ========================================
|
||||
' 第三步: 建立类别层级关系
|
||||
' 第二步: 建立类别层级关系
|
||||
' 说明:
|
||||
' - 遍历所有类别,根据ParentCategoryName建立父子关系
|
||||
' - 如果类别有父类别,将自己添加到父类别的SubCategories中
|
||||
@@ -662,6 +664,56 @@ Public Function GetMaterialsByCategoryAndModel(modelStr As String, _
|
||||
Set GetMaterialsByCategoryAndModel = result
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' GetRequiredCategories 方法 (私有)
|
||||
' 功能: 根据型号条件确定哪些类别是需要的
|
||||
' 参数:
|
||||
' conditions - 从型号提取的条件字典 (Dictionary对象)
|
||||
' 包含如 lcfw, gclj, jycz 等条件变量
|
||||
' 返回: Collection对象, 包含所有需要的 clsCategory 对象
|
||||
'
|
||||
' 判断逻辑:
|
||||
' 遍历所有类别,对每个类别调用 IsRequiredForModel(conditions) 方法:
|
||||
' - 如果类别选用条件为空 → 该类别总是需要,添加到结果集
|
||||
' - 如果类别选用条件不为空 → 用 conditions 匹配
|
||||
' - 匹配成功 → 添加到结果集
|
||||
' - 匹配失败 → 不添加
|
||||
'
|
||||
' 示例:
|
||||
' 假设型号条件为: lcfw=M16, gclj=M20
|
||||
'
|
||||
' 类别1: CategorySelectCondition = ""
|
||||
' → IsRequiredForModel = True → 添加到结果集
|
||||
'
|
||||
' 类别2: CategorySelectCondition = "lcfw=M02"
|
||||
' → IsRequiredForModel = False → 不添加
|
||||
'
|
||||
' 类别3: CategorySelectCondition = "gclj=M20"
|
||||
' → IsRequiredForModel = True → 添加到结果集
|
||||
'
|
||||
' 用途:
|
||||
' 在 GetValidMaterialsByModel 中,只检查需要的类别是否有物料匹配
|
||||
' 不需要的类别不参与完整性检查
|
||||
' ========================================
|
||||
Private Function GetRequiredCategories(conditions As Object) As collection
|
||||
Dim result As collection
|
||||
Set result = New collection
|
||||
|
||||
' 遍历所有类别
|
||||
Dim key As Variant
|
||||
For Each key In dictCategories.Keys
|
||||
Dim cat As clsCategory
|
||||
Set cat = dictCategories(key)
|
||||
|
||||
' 检查该类别是否需要
|
||||
If cat.IsRequiredForModel(conditions) Then
|
||||
result.Add cat
|
||||
End If
|
||||
Next key
|
||||
|
||||
Set GetRequiredCategories = result
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' ParseModelAndExtractConditions 方法
|
||||
' 功能: 解析型号并返回条件字典(工具方法)
|
||||
@@ -689,23 +741,41 @@ End Function
|
||||
' 参数:
|
||||
' modelStr - 产品型号字符串
|
||||
' 返回: Collection对象
|
||||
' Collection中包含两个元素:
|
||||
' Collection中包含三个元素:
|
||||
' (1) "Materials" - Collection对象,包含所有匹配的 clsMaterialItem 对象
|
||||
' (2) "IsComplete" - Boolean值,指示物料是否完整
|
||||
' (3) "MissingCategories" - Collection对象, 包含所有缺失的类别名称字符串
|
||||
'
|
||||
' 完整性判断规则:
|
||||
' - 对于每个需要领料的类别(顶层类别或其需要领取的子类别)
|
||||
' - 必须有且仅有一个物料被匹配
|
||||
' - 如果某个类别有0个或多于1个物料,则视为不完整
|
||||
' ⭐ 完整性判断规则(重构后):
|
||||
' 第一步: 确定哪些类别是该型号需要的
|
||||
' - 遍历所有类别,检查"类别选用条件"
|
||||
' - 类别选用条件为空 → 该类别总是需要
|
||||
' - 类别选用条件不为空 → 用型号条件匹配,匹配成功才需要
|
||||
'
|
||||
' 第二步: 只检查需要的类别的完整性
|
||||
' - 对于每个需要的类别(顶层类别或其需要领取的子类别)
|
||||
' - 必须有且仅有一个物料被匹配
|
||||
' - 如果某个需要的类别有0个或多于1个物料,则视为不完整
|
||||
' - 不需要的类别不参与完整性检查
|
||||
'
|
||||
' 示例:
|
||||
' 假设型号为 "YTHN-100.A0.532.M203.M16.Y3" (量程M16, 过程连接M20)
|
||||
'
|
||||
' 类别1: CategorySelectCondition = "" → 总是需要
|
||||
' 类别2: CategorySelectCondition = "lcfw=M02" → 不需要(型号量程是M16)
|
||||
' 类别3: CategorySelectCondition = "gclj=M20" → 需要(匹配成功)
|
||||
'
|
||||
' 只有类别1和类别3需要检查完整性,类别2不检查
|
||||
'
|
||||
' 调用示例:
|
||||
' Dim result As Collection
|
||||
' Set result = bomMgr.GetValidMaterialsByModel("YTHN-100.A0.532.M203.M16.Y3")
|
||||
' Dim materials As Collection
|
||||
' Dim isComplete As Boolean
|
||||
' Dim missingCats As Collection
|
||||
' Set materials = result("Materials")
|
||||
' isComplete = result("IsComplete")
|
||||
' Set missingCats = result("MissingCategories")
|
||||
' ========================================
|
||||
Public Function GetValidMaterialsByModel(modelStr As String) As collection
|
||||
Dim result As New collection
|
||||
@@ -732,17 +802,21 @@ Public Function GetValidMaterialsByModel(modelStr As String) As collection
|
||||
' 条件匹配器
|
||||
Dim matcher As New clsConditionMatcher
|
||||
|
||||
' 遍历所有根类别,检查完整性
|
||||
' ⭐ 第一步: 获取需要的类别列表
|
||||
Dim requiredCats As collection
|
||||
Set requiredCats = GetRequiredCategories(conditions)
|
||||
|
||||
' ⭐ 第二步: 只检查需要的类别的完整性
|
||||
isComplete = True
|
||||
|
||||
Dim rootCat As clsCategory
|
||||
Dim reqCat As clsCategory
|
||||
Dim i As Long
|
||||
For i = 1 To rootCategories.Count
|
||||
Set rootCat = rootCategories(i)
|
||||
For i = 1 To requiredCats.Count
|
||||
Set reqCat = requiredCats(i)
|
||||
|
||||
' 检查该类别及其子类别的完整性
|
||||
Dim catResult As Object
|
||||
Set catResult = CheckCategoryCompleteness(rootCat, matcher, conditions)
|
||||
Set catResult = CheckCategoryCompleteness(reqCat, matcher, conditions)
|
||||
|
||||
' 1. 合并匹配到的物料
|
||||
Dim mat As clsMaterialItem
|
||||
@@ -752,7 +826,7 @@ Public Function GetValidMaterialsByModel(modelStr As String) As collection
|
||||
allMaterials.Add mat
|
||||
Next mat
|
||||
|
||||
' 2. 合并缺失的类别 (新增)
|
||||
' 2. 合并缺失的类别
|
||||
Dim missingCollection As collection
|
||||
Set missingCollection = catResult("Missing")
|
||||
Dim missingCatName As Variant
|
||||
@@ -769,7 +843,7 @@ Public Function GetValidMaterialsByModel(modelStr As String) As collection
|
||||
' 返回结果
|
||||
result.Add allMaterials, "Materials"
|
||||
result.Add isComplete, "IsComplete"
|
||||
result.Add allMissingCats, "MissingCategories" ' 新增返回项
|
||||
result.Add allMissingCats, "MissingCategories"
|
||||
|
||||
Set GetValidMaterialsByModel = result
|
||||
End Function
|
||||
|
||||
Reference in New Issue
Block a user