docs: expand AutoBOM architecture and implementation details
Refine project overview to include specific business context (Blaidy Company) and the main workbook file. Restructure the architecture section into a layered object-oriented design (Data, Processing, Application layers) and define the responsibilities of core VBA classes. Add new technical documentation sections covering: - Model number format parsing structure - Condition expression language syntax - Category hierarchy logic and picking strategies - Material matching pipeline flow Include VBA code examples for key methods such as CollectAllMaterials and GetMaterialsByCategoryAndModel to illustrate recursive traversal and material retrieval logic. Clarify the structure of key Excel configuration sheets.
This commit is contained in:
@@ -16,7 +16,7 @@ Private dictCategories As Object ' Dictionary对象: 类别名称 -> clsCateg
|
||||
' 作用: 快速查找任意类别
|
||||
Private dictAllMaterials As Object ' Dictionary对象: 物料代号 -> clsMaterialItem对象
|
||||
' 作用: 快速查找任意物料
|
||||
Private rootCategories As Collection ' Collection: 存储所有顶层类别(无父类别的类别)
|
||||
Private rootCategories As collection ' Collection: 存储所有顶层类别(无父类别的类别)
|
||||
' 作用: 遍历完整的类别树结构
|
||||
|
||||
' ========================================
|
||||
@@ -26,7 +26,7 @@ Private rootCategories As Collection ' Collection: 存储所有顶层类别(无
|
||||
Private Sub Class_Initialize()
|
||||
Set dictCategories = CreateObject("Scripting.Dictionary")
|
||||
Set dictAllMaterials = CreateObject("Scripting.Dictionary")
|
||||
Set rootCategories = New Collection
|
||||
Set rootCategories = New collection
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
@@ -59,12 +59,12 @@ Public Sub LoadData(wsConfig As Worksheet, wsPlatform As Worksheet)
|
||||
lastRow = wsPlatform.Cells(wsPlatform.Rows.Count, "C").End(xlUp).row
|
||||
For i = 4 To lastRow ' 从第4行开始(跳过标题)
|
||||
Set mat = New clsMaterialItem
|
||||
mat.code = Trim(wsPlatform.Cells(i, "C").Value & "") ' 物料代号
|
||||
mat.Name = Trim(wsPlatform.Cells(i, "D").Value & "") ' 物料名称
|
||||
mat.code = Trim(wsPlatform.Cells(i, "C").value & "") ' 物料代号
|
||||
mat.Name = Trim(wsPlatform.Cells(i, "D").value & "") ' 物料名称
|
||||
On Error Resume Next
|
||||
mat.Quantity = CDbl(wsPlatform.Cells(i, "E").Value) ' 物料数量
|
||||
mat.Quantity = CDbl(wsPlatform.Cells(i, "E").value) ' 物料数量
|
||||
On Error GoTo 0
|
||||
mat.Condition = Trim(wsPlatform.Cells(i, "F").Value & "") ' 选择条件
|
||||
mat.Condition = Trim(wsPlatform.Cells(i, "F").value & "") ' 选择条件
|
||||
|
||||
' 只保存代号非空的物料
|
||||
If mat.code <> "" Then
|
||||
@@ -86,9 +86,9 @@ Public Sub LoadData(wsConfig As Worksheet, wsPlatform As Worksheet)
|
||||
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 & "") ' 上层类别名称
|
||||
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
|
||||
@@ -155,7 +155,7 @@ End Sub
|
||||
' Debug.Print cats(i).CategoryName
|
||||
' Next i
|
||||
' ========================================
|
||||
Public Function GetRootCategories() As Collection
|
||||
Public Function GetRootCategories() As collection
|
||||
Set GetRootCategories = rootCategories
|
||||
End Function
|
||||
|
||||
@@ -208,9 +208,9 @@ End Function
|
||||
' ' 返回: 径向低压接头、弹簧管、螺旋管等零件
|
||||
' ========================================
|
||||
Public Function GetMaterialsForPicking(categoryName As String, _
|
||||
Optional useParent As Boolean = True) As Collection
|
||||
Dim result As Collection
|
||||
Set result = New Collection
|
||||
Optional useParent As Boolean = True) As collection
|
||||
Dim result As collection
|
||||
Set result = New collection
|
||||
|
||||
' 查找指定类别
|
||||
Dim cat As clsCategory
|
||||
@@ -232,8 +232,8 @@ Public Function GetMaterialsForPicking(categoryName As String, _
|
||||
' - 这是正常情况下的领料方式(领取组装好的部件)
|
||||
' ========================================
|
||||
Dim m As clsMaterialItem
|
||||
For i = 1 To cat.Materials.Count
|
||||
Set m = cat.Materials(i)
|
||||
For i = 1 To cat.materials.Count
|
||||
Set m = cat.materials(i)
|
||||
result.Add m
|
||||
Next i
|
||||
Else
|
||||
@@ -253,7 +253,7 @@ Public Function GetMaterialsForPicking(categoryName As String, _
|
||||
Dim j As Long
|
||||
For j = 1 To cat.SubCategories.Count
|
||||
Set subCat = cat.SubCategories(j)
|
||||
Dim subMats As Collection
|
||||
Dim subMats As collection
|
||||
' 递归调用,继续展开子类别
|
||||
Set subMats = GetMaterialsForPicking(subCat.categoryName, False)
|
||||
Dim k As Long
|
||||
@@ -263,8 +263,8 @@ Public Function GetMaterialsForPicking(categoryName As String, _
|
||||
Next j
|
||||
Else
|
||||
' 叶子类别,返回本类别物料
|
||||
For i = 1 To cat.Materials.Count
|
||||
Set m = cat.Materials(i)
|
||||
For i = 1 To cat.materials.Count
|
||||
Set m = cat.materials(i)
|
||||
result.Add m
|
||||
Next i
|
||||
End If
|
||||
@@ -297,7 +297,7 @@ End Function
|
||||
Public Sub PrintCategoryTree(ws As Worksheet)
|
||||
Dim row As Long
|
||||
row = 1
|
||||
ws.Cells(row, 1).Value = "类别层级结构"
|
||||
ws.Cells(row, 1).value = "类别层级结构"
|
||||
row = row + 1
|
||||
|
||||
' 遍历所有根类别,递归打印整个树
|
||||
@@ -329,19 +329,19 @@ Private Sub PrintCategory(ws As Worksheet, cat As clsCategory, _
|
||||
indent = String(level * 2, " ")
|
||||
|
||||
' 打印类别名称和物料数量统计
|
||||
ws.Cells(row, 1).Value = indent & cat.categoryName & _
|
||||
" (物料数:" & cat.Materials.Count & ")"
|
||||
ws.Cells(row, 1).value = indent & cat.categoryName & _
|
||||
" (物料数:" & cat.materials.Count & ")"
|
||||
row = row + 1
|
||||
|
||||
' 打印该类别下的所有物料
|
||||
Dim mat As clsMaterialItem
|
||||
Dim i As Long
|
||||
For i = 1 To cat.Materials.Count
|
||||
Set mat = cat.Materials(i)
|
||||
For i = 1 To cat.materials.Count
|
||||
Set mat = cat.materials(i)
|
||||
' 物料行额外缩进2个空格,并加上"- "前缀
|
||||
ws.Cells(row, 1).Value = indent & " - " & mat.code & " " & mat.Name
|
||||
ws.Cells(row, 2).Value = "数量:" & mat.Quantity
|
||||
ws.Cells(row, 3).Value = "条件:" & mat.Condition
|
||||
ws.Cells(row, 1).value = indent & " - " & mat.code & " " & mat.Name
|
||||
ws.Cells(row, 2).value = "数量:" & mat.Quantity
|
||||
ws.Cells(row, 3).value = "条件:" & mat.Condition
|
||||
row = row + 1
|
||||
Next i
|
||||
|
||||
@@ -353,4 +353,181 @@ Private Sub PrintCategory(ws As Worksheet, cat As clsCategory, _
|
||||
' 递归调用,层级加1
|
||||
Call PrintCategory(ws, subCat, row, level + 1)
|
||||
Next j
|
||||
End Sub
|
||||
End Sub
|
||||
' ========================================
|
||||
' GetMaterialsByModel 方法
|
||||
' 功能: 根据产品型号获取符合条件的物料清单
|
||||
' 参数:
|
||||
' modelStr - 产品型号字符串
|
||||
' categoryName - 可选,指定类别名称。为空则返回所有类别的物料
|
||||
' 返回: Collection对象,包含符合条件的clsMaterialItem对象
|
||||
' 示例:
|
||||
' Set materials = bomMgr.GetMaterialsByModel("YTHN-100.A0.532.M203.M16.Y3")
|
||||
' Set materials = bomMgr.GetMaterialsByModel("YTHN-100.A0.532.M203.M16.Y3", "部件")
|
||||
' ========================================
|
||||
Public Function GetMaterialsByModel(modelStr As String, _
|
||||
Optional categoryName As String = "") As collection
|
||||
Dim result As collection
|
||||
Set result = New collection
|
||||
|
||||
' 1. 解析型号
|
||||
Dim parser As New clsModelParser
|
||||
If Not parser.ParseModel(modelStr) Then
|
||||
Debug.Print "型号解析失败: " & parser.ErrorMessage
|
||||
Set GetMaterialsByModel = result
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 2. 提取条件
|
||||
Dim extractor As New clsConditionExtractor
|
||||
Dim conditions As Object
|
||||
Set conditions = extractor.ExtractConditions(parser)
|
||||
|
||||
' 调试输出
|
||||
Debug.Print "【型号】: " & modelStr
|
||||
Debug.Print "【提取的条件】:"
|
||||
Dim key As Variant
|
||||
For Each key In conditions.Keys
|
||||
Debug.Print " " & key & " = " & conditions(key)
|
||||
Next key
|
||||
Debug.Print ""
|
||||
|
||||
' 3. 创建条件匹配器
|
||||
Dim matcher As New clsConditionMatcher
|
||||
|
||||
' 4. 获取要筛选的物料范围
|
||||
Dim materialsToFilter As collection
|
||||
Set materialsToFilter = New collection
|
||||
|
||||
If categoryName <> "" Then
|
||||
' 指定类别:获取该类别的所有物料
|
||||
Dim cat As clsCategory
|
||||
Set cat = GetCategory(categoryName)
|
||||
If Not cat Is Nothing Then
|
||||
Dim i As Long
|
||||
For i = 1 To cat.materials.Count
|
||||
materialsToFilter.Add cat.materials(i)
|
||||
Next i
|
||||
End If
|
||||
Else
|
||||
' 未指定类别:获取所有根类别的物料
|
||||
Dim rootCat As clsCategory
|
||||
Dim j As Long
|
||||
For j = 1 To rootCategories.Count
|
||||
Set rootCat = rootCategories(j)
|
||||
' 递归获取所有物料
|
||||
Call CollectAllMaterials(rootCat, materialsToFilter)
|
||||
Next j
|
||||
End If
|
||||
|
||||
' 5. 筛选符合条件的物料
|
||||
Dim mat As clsMaterialItem
|
||||
Dim matchCount As Long
|
||||
matchCount = 0
|
||||
|
||||
For Each mat In materialsToFilter
|
||||
' 使用条件匹配器判断
|
||||
If matcher.IsMatch(mat.Condition, conditions) Then
|
||||
result.Add mat
|
||||
matchCount = matchCount + 1
|
||||
|
||||
' 调试输出
|
||||
Debug.Print "【匹配】 " & mat.code & " - " & mat.Name & _
|
||||
" | 条件: " & IIf(mat.Condition = "", "(无)", mat.Condition)
|
||||
End If
|
||||
Next mat
|
||||
|
||||
Debug.Print "共匹配 " & matchCount & " 个物料"
|
||||
Debug.Print String(60, "=")
|
||||
|
||||
Set GetMaterialsByModel = result
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' CollectAllMaterials 方法 (私有)
|
||||
' 功能: 递归收集类别及其所有子类别的物料
|
||||
' 参数:
|
||||
' cat - 类别对象
|
||||
' collection - 用于存储物料的Collection
|
||||
' ========================================
|
||||
Private Sub CollectAllMaterials(cat As clsCategory, collection As collection)
|
||||
Dim i As Long
|
||||
|
||||
' 添加当前类别的所有物料
|
||||
For i = 1 To cat.materials.Count
|
||||
collection.Add cat.materials(i)
|
||||
Next i
|
||||
|
||||
' 递归处理子类别
|
||||
Dim subCat As clsCategory
|
||||
Dim j As Long
|
||||
For j = 1 To cat.SubCategories.Count
|
||||
Set subCat = cat.SubCategories(j)
|
||||
Call CollectAllMaterials(subCat, collection)
|
||||
Next j
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' GetMaterialsByCategoryAndModel 方法
|
||||
' 功能: 根据类别和型号获取物料(使用父类别或子类别逻辑)
|
||||
' 参数:
|
||||
' modelStr - 产品型号字符串
|
||||
' categoryName - 类别名称
|
||||
' useParent - True=使用父类别物料,False=使用子类别物料
|
||||
' 返回: Collection对象,包含符合条件的clsMaterialItem对象
|
||||
' 说明: 这是 GetMaterialsForPicking 和 GetMaterialsByModel 的结合
|
||||
' ========================================
|
||||
Public Function GetMaterialsByCategoryAndModel(modelStr As String, _
|
||||
categoryName As String, _
|
||||
Optional useParent As Boolean = True) As collection
|
||||
Dim result As collection
|
||||
Set result = New collection
|
||||
|
||||
' 1. 解析型号并提取条件
|
||||
Dim parser As New clsModelParser
|
||||
If Not parser.ParseModel(modelStr) Then
|
||||
Set GetMaterialsByCategoryAndModel = result
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
Dim extractor As New clsConditionExtractor
|
||||
Dim conditions As Object
|
||||
Set conditions = extractor.ExtractConditions(parser)
|
||||
|
||||
' 2. 获取类别的物料(根据 useParent 参数)
|
||||
Dim materialsToFilter As collection
|
||||
Set materialsToFilter = GetMaterialsForPicking(categoryName, useParent)
|
||||
|
||||
' 3. 筛选符合条件的物料
|
||||
Dim matcher As New clsConditionMatcher
|
||||
Dim mat As clsMaterialItem
|
||||
|
||||
For Each mat In materialsToFilter
|
||||
If matcher.IsMatch(mat.Condition, conditions) Then
|
||||
result.Add mat
|
||||
End If
|
||||
Next mat
|
||||
|
||||
Set GetMaterialsByCategoryAndModel = result
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' ParseModelAndExtractConditions 方法
|
||||
' 功能: 解析型号并返回条件字典(工具方法)
|
||||
' 参数: modelStr - 产品型号字符串
|
||||
' 返回: Dictionary对象,包含提取的条件
|
||||
' 用途: 供外部调用,用于查看提取的条件
|
||||
' ========================================
|
||||
Public Function ParseModelAndExtractConditions(modelStr As String) As Object
|
||||
Dim parser As New clsModelParser
|
||||
Dim extractor As New clsConditionExtractor
|
||||
Dim conditions As Object
|
||||
|
||||
If parser.ParseModel(modelStr) Then
|
||||
Set conditions = extractor.ExtractConditions(parser)
|
||||
Else
|
||||
Set conditions = CreateObject("Scripting.Dictionary")
|
||||
End If
|
||||
|
||||
Set ParseModelAndExtractConditions = conditions
|
||||
End Function
|
||||
@@ -6,19 +6,19 @@ Option Explicit
|
||||
|
||||
Public categoryName As String
|
||||
Public ParentCategoryName As String
|
||||
Public Materials As Collection ' 存储 clsMaterialItem 对象
|
||||
Public SubCategories As Collection ' 存储子类别 clsCategory 对象
|
||||
Public materials As collection ' 存储 clsMaterialItem 对象
|
||||
Public SubCategories As collection ' 存储子类别 clsCategory 对象
|
||||
Public IsLeafCategory As Boolean ' 是否叶子类别(无子类别)
|
||||
|
||||
Private Sub Class_Initialize()
|
||||
Set Materials = New Collection
|
||||
Set SubCategories = New Collection
|
||||
Set materials = New collection
|
||||
Set SubCategories = New collection
|
||||
IsLeafCategory = True
|
||||
End Sub
|
||||
|
||||
' 添加物料
|
||||
Public Sub AddMaterial(mat As clsMaterialItem)
|
||||
Materials.Add mat, mat.code
|
||||
materials.Add mat, mat.code
|
||||
End Sub
|
||||
|
||||
' 添加子类别
|
||||
@@ -30,7 +30,7 @@ End Sub
|
||||
' 获取物料(按代号)
|
||||
Public Function GetMaterial(code As String) As clsMaterialItem
|
||||
On Error Resume Next
|
||||
Set GetMaterial = Materials(code)
|
||||
Set GetMaterial = materials(code)
|
||||
On Error GoTo 0
|
||||
End Function
|
||||
|
||||
|
||||
234
VBA/ClassModules/clsConditionExtractor.cls
Normal file
234
VBA/ClassModules/clsConditionExtractor.cls
Normal file
@@ -0,0 +1,234 @@
|
||||
' ========================================
|
||||
' 类模块: clsConditionExtractor
|
||||
' 用途: 从型号解析器中提取物料选择条件
|
||||
' ========================================
|
||||
Option Explicit
|
||||
|
||||
' ========================================
|
||||
' 私有成员变量
|
||||
' ========================================
|
||||
Private m_Conditions As Object ' Dictionary: 变量名 -> 条件值
|
||||
Private m_ExtractionRules As Object ' Dictionary: 提取规则配置
|
||||
|
||||
' ========================================
|
||||
' 类初始化
|
||||
' ========================================
|
||||
Private Sub Class_Initialize()
|
||||
Set m_Conditions = CreateObject("Scripting.Dictionary")
|
||||
Set m_ExtractionRules = CreateObject("Scripting.Dictionary")
|
||||
|
||||
' 初始化提取规则
|
||||
InitializeRules
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' InitializeRules 方法 (私有)
|
||||
' 功能: 初始化条件提取规则
|
||||
' 说明: 这里配置所有需要提取的条件及其提取方法
|
||||
' ========================================
|
||||
Private Sub InitializeRules()
|
||||
' 规则格式: Dictionary(变量名) = Array(源字段, 提取方法)
|
||||
|
||||
' 规则1: 过程连接 (gclj)
|
||||
' 从 ConnectionCode 中提取,去掉最后一位数字
|
||||
m_ExtractionRules("gclj") = Array("ConnectionCode", "RemoveLastDigit")
|
||||
|
||||
' 规则2: 接液材质 (jycz)
|
||||
' 从 ConnectionCode 中提取,取最后一位数字
|
||||
m_ExtractionRules("jycz") = Array("ConnectionCode", "GetLastDigit")
|
||||
|
||||
' 规则3: 量程范围 (lcfw)
|
||||
' 从 RangeCode 中直接提取
|
||||
m_ExtractionRules("lcfw") = Array("RangeCode", "Direct")
|
||||
|
||||
' 未来可以在这里添加更多提取规则...
|
||||
' 例如:
|
||||
' m_ExtractionRules("bplx") = Array("DialCode", "Direct") ' 表盘类型
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' ExtractConditions 方法
|
||||
' 功能: 从型号解析器中提取所有条件
|
||||
' 参数: parser - clsModelParser对象
|
||||
' 返回: Dictionary对象,包含所有提取的条件
|
||||
' ========================================
|
||||
Public Function ExtractConditions(parser As clsModelParser) As Object
|
||||
' 清空现有条件
|
||||
Set m_Conditions = CreateObject("Scripting.Dictionary")
|
||||
|
||||
' 验证解析器有效性
|
||||
If Not parser.IsValid Then
|
||||
Set ExtractConditions = m_Conditions
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 遍历所有提取规则
|
||||
Dim varName As Variant
|
||||
For Each varName In m_ExtractionRules.Keys
|
||||
Dim ruleInfo As Variant
|
||||
ruleInfo = m_ExtractionRules(varName)
|
||||
|
||||
Dim sourceField As String
|
||||
Dim extractMethod As String
|
||||
sourceField = ruleInfo(0)
|
||||
extractMethod = ruleInfo(1)
|
||||
|
||||
' 提取条件值
|
||||
Dim conditionValue As String
|
||||
conditionValue = ExtractValue(parser, sourceField, extractMethod)
|
||||
|
||||
' 添加到条件字典
|
||||
If conditionValue <> "" Then
|
||||
m_Conditions(CStr(varName)) = conditionValue
|
||||
End If
|
||||
Next varName
|
||||
|
||||
Set ExtractConditions = m_Conditions
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' ExtractValue 方法 (私有)
|
||||
' 功能: 根据规则从解析器中提取单个值
|
||||
' 参数:
|
||||
' parser - clsModelParser对象
|
||||
' sourceField - 源字段名称
|
||||
' extractMethod - 提取方法名称
|
||||
' 返回: 提取的条件值
|
||||
' ========================================
|
||||
Private Function ExtractValue(parser As clsModelParser, _
|
||||
sourceField As String, _
|
||||
extractMethod As String) As String
|
||||
Dim sourceValue As String
|
||||
|
||||
' 获取源字段值
|
||||
Select Case sourceField
|
||||
Case "ConnectionCode"
|
||||
sourceValue = parser.ConnectionCode
|
||||
Case "RangeCode"
|
||||
sourceValue = parser.RangeCode
|
||||
Case "ModelType"
|
||||
sourceValue = parser.ModelType
|
||||
Case "Diameter"
|
||||
sourceValue = parser.Diameter
|
||||
Case "InstallForm"
|
||||
sourceValue = parser.InstallForm
|
||||
Case "ShellForm"
|
||||
sourceValue = parser.ShellForm
|
||||
Case "Characteristics"
|
||||
sourceValue = parser.Characteristics
|
||||
Case Else
|
||||
sourceValue = ""
|
||||
End Select
|
||||
|
||||
' 应用提取方法
|
||||
Select Case extractMethod
|
||||
Case "Direct"
|
||||
' 直接使用
|
||||
ExtractValue = sourceValue
|
||||
|
||||
Case "RemoveLastDigit"
|
||||
' 去掉最后一位字符
|
||||
If Len(sourceValue) > 1 Then
|
||||
ExtractValue = Left(sourceValue, Len(sourceValue) - 1)
|
||||
Else
|
||||
ExtractValue = sourceValue
|
||||
End If
|
||||
|
||||
Case "GetLastDigit"
|
||||
' 取最后一位字符
|
||||
If Len(sourceValue) > 0 Then
|
||||
ExtractValue = Right(sourceValue, 1)
|
||||
Else
|
||||
ExtractValue = ""
|
||||
End If
|
||||
|
||||
Case "GetFirstChar"
|
||||
' 取第一个字符
|
||||
If Len(sourceValue) > 0 Then
|
||||
ExtractValue = Left(sourceValue, 1)
|
||||
Else
|
||||
ExtractValue = ""
|
||||
End If
|
||||
|
||||
Case Else
|
||||
' 未知方法,返回空
|
||||
ExtractValue = ""
|
||||
End Select
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' GetConditionValue 方法
|
||||
' 功能: 获取单个条件值
|
||||
' 参数: varName - 变量名
|
||||
' 返回: 条件值,如果不存在返回空字符串
|
||||
' ========================================
|
||||
Public Function GetConditionValue(varName As String) As String
|
||||
If m_Conditions.Exists(varName) Then
|
||||
GetConditionValue = m_Conditions(varName)
|
||||
Else
|
||||
GetConditionValue = ""
|
||||
End If
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' AddCondition 方法
|
||||
' 功能: 手动添加条件 (用于特殊情况)
|
||||
' 参数:
|
||||
' varName - 变量名
|
||||
' value - 条件值
|
||||
' ========================================
|
||||
Public Sub AddCondition(varName As String, value As String)
|
||||
m_Conditions(varName) = value
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' GetConditions 属性
|
||||
' 功能: 获取所有条件的Dictionary对象
|
||||
' ========================================
|
||||
Public Property Get conditions() As Object
|
||||
Set conditions = m_Conditions
|
||||
End Property
|
||||
|
||||
' ========================================
|
||||
' ToString 方法
|
||||
' 功能: 返回条件的字符串表示 (用于调试)
|
||||
' ========================================
|
||||
Public Function ToString() As String
|
||||
Dim result As String
|
||||
result = "【提取的条件】" & vbCrLf
|
||||
|
||||
If m_Conditions.Count = 0 Then
|
||||
result = result & " (无条件)" & vbCrLf
|
||||
Else
|
||||
Dim key As Variant
|
||||
For Each key In m_Conditions.Keys
|
||||
result = result & " " & key & " = " & m_Conditions(key) & vbCrLf
|
||||
Next key
|
||||
End If
|
||||
|
||||
ToString = result
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' AddExtractionRule 方法
|
||||
' 功能: 动态添加新的提取规则 (用于扩展)
|
||||
' 参数:
|
||||
' varName - 变量名
|
||||
' sourceField - 源字段名称
|
||||
' extractMethod - 提取方法名称
|
||||
' 示例: extractor.AddExtractionRule "bplx", "DialCode", "Direct"
|
||||
' ========================================
|
||||
Public Sub AddExtractionRule(varName As String, _
|
||||
sourceField As String, _
|
||||
extractMethod As String)
|
||||
m_ExtractionRules(varName) = Array(sourceField, extractMethod)
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' GetExtractionRules 方法
|
||||
' 功能: 获取当前所有提取规则 (用于调试)
|
||||
' 返回: Dictionary对象
|
||||
' ========================================
|
||||
Public Function GetExtractionRules() As Object
|
||||
Set GetExtractionRules = m_ExtractionRules
|
||||
End Function
|
||||
250
VBA/ClassModules/clsConditionMatcher.cls
Normal file
250
VBA/ClassModules/clsConditionMatcher.cls
Normal file
@@ -0,0 +1,250 @@
|
||||
' ========================================
|
||||
' 类模块: clsConditionMatcher
|
||||
' 用途: 解析物料的选择条件表达式,并判断是否匹配
|
||||
' 支持: AND, OR, NOT(!=), 括号优先级
|
||||
' ========================================
|
||||
Option Explicit
|
||||
|
||||
' ========================================
|
||||
' IsMatch 方法
|
||||
' 功能: 判断条件表达式是否匹配
|
||||
' 参数:
|
||||
' conditionExpr - 条件表达式字符串
|
||||
' conditions - Dictionary对象,包含变量名->值的映射
|
||||
' 返回: Boolean - 是否匹配
|
||||
' 示例:
|
||||
' IsMatch("lcfw=M16 AND gclj=M20", conditions) -> True/False
|
||||
' ========================================
|
||||
Public Function IsMatch(conditionExpr As String, conditions As Object) As Boolean
|
||||
On Error GoTo ErrorHandler
|
||||
|
||||
' 空条件表示无条件,始终匹配
|
||||
If Trim(conditionExpr) = "" Then
|
||||
IsMatch = True
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 解析并计算表达式
|
||||
IsMatch = EvaluateExpression(Trim(conditionExpr), conditions)
|
||||
Exit Function
|
||||
|
||||
ErrorHandler:
|
||||
' 出错时返回False(保守处理)
|
||||
Debug.Print "条件匹配出错: " & conditionExpr & " - " & Err.description
|
||||
IsMatch = False
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' EvaluateExpression 方法 (私有)
|
||||
' 功能: 递归计算逻辑表达式
|
||||
' 优先级: 括号 > NOT(!=) > AND > OR
|
||||
' ========================================
|
||||
Private Function EvaluateExpression(expr As String, conditions As Object) As Boolean
|
||||
expr = Trim(expr)
|
||||
|
||||
' 处理括号 (最高优先级)
|
||||
If InStr(expr, "(") > 0 Then
|
||||
EvaluateExpression = EvaluateWithParentheses(expr, conditions)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 处理 OR (最低优先级)
|
||||
If InStr(expr, " OR ") > 0 Then
|
||||
EvaluateExpression = EvaluateOR(expr, conditions)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 处理 AND (中等优先级)
|
||||
If InStr(expr, " AND ") > 0 Then
|
||||
EvaluateExpression = EvaluateAND(expr, conditions)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 处理单个条件 (最高优先级)
|
||||
EvaluateExpression = EvaluateSimpleCondition(expr, conditions)
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' EvaluateWithParentheses 方法 (私有)
|
||||
' 功能: 处理包含括号的表达式
|
||||
' 策略: 找到最内层括号,递归计算,然后替换为结果
|
||||
' ========================================
|
||||
Private Function EvaluateWithParentheses(expr As String, conditions As Object) As Boolean
|
||||
Dim pos As Long, level As Long, startPos As Long
|
||||
Dim i As Long
|
||||
Dim innerExpr As String
|
||||
Dim innerResult As Boolean
|
||||
Dim newExpr As String
|
||||
|
||||
' 查找最内层的括号对
|
||||
startPos = 0
|
||||
level = 0
|
||||
|
||||
For i = 1 To Len(expr)
|
||||
If Mid(expr, i, 1) = "(" Then
|
||||
If level = 0 Then startPos = i
|
||||
level = level + 1
|
||||
ElseIf Mid(expr, i, 1) = ")" Then
|
||||
level = level - 1
|
||||
If level = 0 And startPos > 0 Then
|
||||
' 找到一对括号
|
||||
innerExpr = Mid(expr, startPos + 1, i - startPos - 1)
|
||||
innerResult = EvaluateExpression(innerExpr, conditions)
|
||||
|
||||
' 替换括号部分为结果
|
||||
newExpr = Left(expr, startPos - 1) & _
|
||||
IIf(innerResult, "TRUE", "FALSE") & _
|
||||
Mid(expr, i + 1)
|
||||
|
||||
' 递归处理剩余部分
|
||||
EvaluateWithParentheses = EvaluateExpression(newExpr, conditions)
|
||||
Exit Function
|
||||
End If
|
||||
End If
|
||||
Next i
|
||||
|
||||
' 如果没有找到有效括号,直接计算
|
||||
EvaluateWithParentheses = EvaluateExpression(expr, conditions)
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' EvaluateOR 方法 (私有)
|
||||
' 功能: 处理 OR 逻辑运算
|
||||
' 规则: 任一为真则为真
|
||||
' ========================================
|
||||
Private Function EvaluateOR(expr As String, conditions As Object) As Boolean
|
||||
Dim parts() As String
|
||||
Dim part As Variant
|
||||
|
||||
' 按 OR 分割
|
||||
parts = Split(expr, " OR ")
|
||||
|
||||
' 任一部分为真则返回真
|
||||
For Each part In parts
|
||||
If EvaluateExpression(Trim(CStr(part)), conditions) Then
|
||||
EvaluateOR = True
|
||||
Exit Function
|
||||
End If
|
||||
Next part
|
||||
|
||||
EvaluateOR = False
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' EvaluateAND 方法 (私有)
|
||||
' 功能: 处理 AND 逻辑运算
|
||||
' 规则: 全部为真才为真
|
||||
' ========================================
|
||||
Private Function EvaluateAND(expr As String, conditions As Object) As Boolean
|
||||
Dim parts() As String
|
||||
Dim part As Variant
|
||||
|
||||
' 按 AND 分割
|
||||
parts = Split(expr, " AND ")
|
||||
|
||||
' 全部部分为真才返回真
|
||||
For Each part In parts
|
||||
If Not EvaluateExpression(Trim(CStr(part)), conditions) Then
|
||||
EvaluateAND = False
|
||||
Exit Function
|
||||
End If
|
||||
Next part
|
||||
|
||||
EvaluateAND = True
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' EvaluateSimpleCondition 方法 (私有)
|
||||
' 功能: 计算单个条件表达式
|
||||
' 支持: = (等于), != (不等于)
|
||||
' 格式: varName=value 或 varName!=value
|
||||
' ========================================
|
||||
Private Function EvaluateSimpleCondition(cond As String, conditions As Object) As Boolean
|
||||
cond = Trim(cond)
|
||||
|
||||
' 处理特殊值 TRUE/FALSE (括号计算的结果)
|
||||
If UCase(cond) = "TRUE" Then
|
||||
EvaluateSimpleCondition = True
|
||||
Exit Function
|
||||
ElseIf UCase(cond) = "FALSE" Then
|
||||
EvaluateSimpleCondition = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
Dim varName As String
|
||||
Dim expectedValue As String
|
||||
Dim actualValue As String
|
||||
Dim isNotEqual As Boolean
|
||||
|
||||
' 判断是 != 还是 =
|
||||
If InStr(cond, "!=") > 0 Then
|
||||
isNotEqual = True
|
||||
Dim parts1() As String
|
||||
parts1 = Split(cond, "!=")
|
||||
If UBound(parts1) < 1 Then
|
||||
EvaluateSimpleCondition = False
|
||||
Exit Function
|
||||
End If
|
||||
varName = Trim(parts1(0))
|
||||
expectedValue = Trim(parts1(1))
|
||||
ElseIf InStr(cond, "=") > 0 Then
|
||||
isNotEqual = False
|
||||
Dim parts2() As String
|
||||
parts2 = Split(cond, "=")
|
||||
If UBound(parts2) < 1 Then
|
||||
EvaluateSimpleCondition = False
|
||||
Exit Function
|
||||
End If
|
||||
varName = Trim(parts2(0))
|
||||
expectedValue = Trim(parts2(1))
|
||||
Else
|
||||
' 无效的条件格式
|
||||
EvaluateSimpleCondition = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 获取实际值
|
||||
If conditions.Exists(varName) Then
|
||||
actualValue = Trim(CStr(conditions(varName)))
|
||||
Else
|
||||
actualValue = ""
|
||||
End If
|
||||
|
||||
' 比较值 (不区分大小写)
|
||||
Dim isEqual As Boolean
|
||||
isEqual = (UCase(actualValue) = UCase(expectedValue))
|
||||
|
||||
' 返回结果
|
||||
If isNotEqual Then
|
||||
EvaluateSimpleCondition = Not isEqual
|
||||
Else
|
||||
EvaluateSimpleCondition = isEqual
|
||||
End If
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' TestExpression 方法
|
||||
' 功能: 测试表达式是否有效 (用于调试)
|
||||
' 参数: expr - 表达式字符串
|
||||
' 返回: String - "有效" 或 错误信息
|
||||
' ========================================
|
||||
Public Function TestExpression(expr As String) As String
|
||||
On Error GoTo ErrorHandler
|
||||
|
||||
' 创建测试条件
|
||||
Dim testConditions As Object
|
||||
Set testConditions = CreateObject("Scripting.Dictionary")
|
||||
testConditions("gclj") = "M20"
|
||||
testConditions("jycz") = "3"
|
||||
testConditions("lcfw") = "M16"
|
||||
|
||||
' 尝试计算
|
||||
Dim result As Boolean
|
||||
result = IsMatch(expr, testConditions)
|
||||
|
||||
TestExpression = "有效 (结果: " & IIf(result, "True", "False") & ")"
|
||||
Exit Function
|
||||
|
||||
ErrorHandler:
|
||||
TestExpression = "无效: " & Err.description
|
||||
End Function
|
||||
229
VBA/ClassModules/clsModelParser.cls
Normal file
229
VBA/ClassModules/clsModelParser.cls
Normal file
@@ -0,0 +1,229 @@
|
||||
' ========================================
|
||||
' 类模块: clsModelParser
|
||||
' 用途: 解析产品型号,提取各部分代码
|
||||
' 示例: YTHN-100.A0.532.M203.M16.Y3|BP-095.2312.M16.PA3
|
||||
' ========================================
|
||||
Option Explicit
|
||||
|
||||
' ========================================
|
||||
' 公共属性
|
||||
' ========================================
|
||||
Public RawModel As String ' 原始完整型号
|
||||
Public HeaderModel As String ' 表头型号部分
|
||||
Public DialModel As String ' 表盘型号部分
|
||||
Public AccessoryModel As String ' 附件型号部分
|
||||
Public FlangeModel As String ' 法兰隔膜型号部分
|
||||
|
||||
' 表头各部分
|
||||
Public ModelType As String ' 型号 (如 YTHN)
|
||||
Public Diameter As String ' 公称外径 (如 100)
|
||||
Public InstallForm As String ' 安装形式 (如 A0)
|
||||
Public ShellForm As String ' 壳体形式 (如 532)
|
||||
Public ConnectionCode As String ' 过程连接&材质代码 (如 M203)
|
||||
Public RangeCode As String ' 量程范围代码 (如 M16)
|
||||
Public Characteristics As String ' 仪表特性 (如 Y3)
|
||||
|
||||
' ========================================
|
||||
' 私有变量
|
||||
' ========================================
|
||||
Private m_IsValid As Boolean ' 解析是否成功
|
||||
Private m_ErrorMessage As String ' 错误信息
|
||||
|
||||
' ========================================
|
||||
' ParseModel 方法
|
||||
' 功能: 解析产品型号字符串
|
||||
' 参数: modelStr - 完整的产品型号字符串
|
||||
' 返回: Boolean - 解析是否成功
|
||||
' 示例: parser.ParseModel("YTHN-100.A0.532.M203.M16.Y3|BP-095.2312.M16.PA3")
|
||||
' ========================================
|
||||
Public Function ParseModel(modelStr As String) As Boolean
|
||||
On Error GoTo ErrorHandler
|
||||
|
||||
' 初始化
|
||||
m_IsValid = False
|
||||
m_ErrorMessage = ""
|
||||
RawModel = Trim(modelStr)
|
||||
|
||||
' 验证输入
|
||||
If RawModel = "" Then
|
||||
m_ErrorMessage = "型号字符串为空"
|
||||
ParseModel = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 第一步: 按 | 分割各部分
|
||||
Dim parts() As String
|
||||
parts = Split(RawModel, "|")
|
||||
|
||||
If UBound(parts) >= 0 Then HeaderModel = Trim(parts(0))
|
||||
If UBound(parts) >= 1 Then DialModel = Trim(parts(1))
|
||||
If UBound(parts) >= 2 Then AccessoryModel = Trim(parts(2))
|
||||
If UBound(parts) >= 3 Then FlangeModel = Trim(parts(3))
|
||||
|
||||
' 第二步: 解析表头部分 (必须存在)
|
||||
If HeaderModel = "" Then
|
||||
m_ErrorMessage = "表头型号为空"
|
||||
ParseModel = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 解析表头
|
||||
If Not ParseHeader(HeaderModel) Then
|
||||
ParseModel = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
m_IsValid = True
|
||||
ParseModel = True
|
||||
Exit Function
|
||||
|
||||
ErrorHandler:
|
||||
m_ErrorMessage = "解析出错: " & Err.description
|
||||
m_IsValid = False
|
||||
ParseModel = False
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' ParseHeader 方法 (私有)
|
||||
' 功能: 解析表头型号部分
|
||||
' 格式: [型号]-[公称外径].[安装形式].[壳体形式].[过程连接&材质].[量程范围].[仪表特性]
|
||||
' 示例: YTHN-100.A0.532.M203.M16.Y3
|
||||
' ========================================
|
||||
Private Function ParseHeader(headerStr As String) As Boolean
|
||||
On Error GoTo ErrorHandler
|
||||
|
||||
' 按 - 分割型号和参数部分
|
||||
Dim mainParts() As String
|
||||
mainParts = Split(headerStr, "-")
|
||||
|
||||
If UBound(mainParts) < 1 Then
|
||||
m_ErrorMessage = "表头格式错误: 缺少 - 分隔符"
|
||||
ParseHeader = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 提取型号
|
||||
ModelType = Trim(mainParts(0))
|
||||
|
||||
' 按 . 分割参数部分
|
||||
Dim params() As String
|
||||
params = Split(mainParts(1), ".")
|
||||
|
||||
' 验证参数数量 (至少应该有5个部分)
|
||||
If UBound(params) < 4 Then
|
||||
m_ErrorMessage = "表头参数不足: 需要至少5个参数段"
|
||||
ParseHeader = False
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 提取各参数
|
||||
Diameter = Trim(params(0)) ' 公称外径
|
||||
InstallForm = Trim(params(1)) ' 安装形式
|
||||
ShellForm = Trim(params(2)) ' 壳体形式
|
||||
ConnectionCode = Trim(params(3)) ' 过程连接&材质
|
||||
RangeCode = Trim(params(4)) ' 量程范围
|
||||
|
||||
' 仪表特性 (可选)
|
||||
If UBound(params) >= 5 Then
|
||||
Characteristics = Trim(params(5))
|
||||
Else
|
||||
Characteristics = ""
|
||||
End If
|
||||
|
||||
ParseHeader = True
|
||||
Exit Function
|
||||
|
||||
ErrorHandler:
|
||||
m_ErrorMessage = "解析表头出错: " & Err.description
|
||||
ParseHeader = False
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' GetThreadCode 方法
|
||||
' 功能: 从过程连接代码中提取螺纹代码
|
||||
' 规则: 去掉最后一位数字
|
||||
' 示例: M203 -> M20
|
||||
' ========================================
|
||||
Public Function GetThreadCode() As String
|
||||
If ConnectionCode = "" Then
|
||||
GetThreadCode = ""
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 去掉最后一位字符 (假设最后一位是材质代码)
|
||||
If Len(ConnectionCode) > 1 Then
|
||||
GetThreadCode = Left(ConnectionCode, Len(ConnectionCode) - 1)
|
||||
Else
|
||||
GetThreadCode = ConnectionCode
|
||||
End If
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' GetMaterialCode 方法
|
||||
' 功能: 从过程连接代码中提取材质代码
|
||||
' 规则: 取最后一位数字
|
||||
' 示例: M203 -> 3
|
||||
' ========================================
|
||||
Public Function GetMaterialCode() As String
|
||||
If ConnectionCode = "" Then
|
||||
GetMaterialCode = ""
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' 取最后一位字符
|
||||
GetMaterialCode = Right(ConnectionCode, 1)
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' GetRangeCode 方法
|
||||
' 功能: 获取量程代码
|
||||
' 规则: 直接返回
|
||||
' 示例: M16 -> M16
|
||||
' ========================================
|
||||
Public Function GetRangeCode() As String
|
||||
GetRangeCode = RangeCode
|
||||
End Function
|
||||
|
||||
' ========================================
|
||||
' IsValid 属性
|
||||
' 功能: 返回解析是否成功
|
||||
' ========================================
|
||||
Public Property Get IsValid() As Boolean
|
||||
IsValid = m_IsValid
|
||||
End Property
|
||||
|
||||
' ========================================
|
||||
' ErrorMessage 属性
|
||||
' 功能: 返回错误信息
|
||||
' ========================================
|
||||
Public Property Get ErrorMessage() As String
|
||||
ErrorMessage = m_ErrorMessage
|
||||
End Property
|
||||
|
||||
' ========================================
|
||||
' ToString 方法
|
||||
' 功能: 返回解析结果的字符串表示 (用于调试)
|
||||
' ========================================
|
||||
Public Function ToString() As String
|
||||
Dim result As String
|
||||
result = "【型号解析结果】" & vbCrLf
|
||||
result = result & "原始型号: " & RawModel & vbCrLf
|
||||
result = result & "表头型号: " & HeaderModel & vbCrLf
|
||||
result = result & "表盘型号: " & DialModel & vbCrLf
|
||||
result = result & vbCrLf
|
||||
result = result & "【表头各部分】" & vbCrLf
|
||||
result = result & " 型号: " & ModelType & vbCrLf
|
||||
result = result & " 公称外径: " & Diameter & vbCrLf
|
||||
result = result & " 安装形式: " & InstallForm & vbCrLf
|
||||
result = result & " 壳体形式: " & ShellForm & vbCrLf
|
||||
result = result & " 过程连接&材质: " & ConnectionCode & vbCrLf
|
||||
result = result & " 量程范围: " & RangeCode & vbCrLf
|
||||
result = result & " 仪表特性: " & Characteristics & vbCrLf
|
||||
result = result & vbCrLf
|
||||
result = result & "【提取代码】" & vbCrLf
|
||||
result = result & " 螺纹代码: " & GetThreadCode() & vbCrLf
|
||||
result = result & " 材质代码: " & GetMaterialCode() & vbCrLf
|
||||
result = result & " 量程代码: " & GetRangeCode() & vbCrLf
|
||||
|
||||
ToString = result
|
||||
End Function
|
||||
@@ -1,6 +1,6 @@
|
||||
' ========================================
|
||||
' 模块: modBOMTest
|
||||
' 用途: 测试和使用BOM数据结构-同步测试2
|
||||
' 用途: 测试和使用BOM数据结构
|
||||
' ========================================
|
||||
Option Explicit
|
||||
|
||||
@@ -19,19 +19,19 @@ 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
|
||||
|
||||
Dim cats As Collection
|
||||
Dim cats As collection
|
||||
Dim i As Integer
|
||||
Set cats = bomMgr.GetRootCategories()
|
||||
For i = 1 To cats.Count
|
||||
@@ -40,7 +40,7 @@ Sub TestBOMStructure()
|
||||
|
||||
|
||||
|
||||
'MsgBox "BOM数据结构加载完成!" & vbCrLf & _
|
||||
MsgBox "BOM数据结构加载完成!" & vbCrLf & _
|
||||
"请查看 'BOM结构' 工作表", vbInformation
|
||||
End Sub
|
||||
|
||||
@@ -55,19 +55,19 @@ Sub GetCategoryMaterials()
|
||||
bomMgr.LoadData wsConfig, wsPlatform
|
||||
|
||||
' 获取"部件"类别的物料(使用父类别)
|
||||
Dim Materials As Collection
|
||||
Set Materials = bomMgr.GetMaterialsForPicking("部件", True)
|
||||
Dim materials As collection
|
||||
Set materials = bomMgr.GetMaterialsForPicking("部件", True)
|
||||
|
||||
Debug.Print "部件类别物料数量(父类别): " & Materials.Count
|
||||
Debug.Print "部件类别物料数量(父类别): " & materials.Count
|
||||
|
||||
' 获取"部件"类别的物料(使用子类别)
|
||||
Set Materials = bomMgr.GetMaterialsForPicking("部件", False)
|
||||
Set materials = bomMgr.GetMaterialsForPicking("部件", False)
|
||||
|
||||
Debug.Print "部件类别物料数量(子类别展开): " & Materials.Count
|
||||
Debug.Print "部件类别物料数量(子类别展开): " & materials.Count
|
||||
|
||||
' 遍历物料
|
||||
Dim mat As clsMaterialItem
|
||||
For Each mat In Materials
|
||||
For Each mat In materials
|
||||
Debug.Print mat.code & " - " & mat.Name & _
|
||||
" | 数量:" & mat.Quantity & _
|
||||
" | 条件:" & mat.Condition
|
||||
@@ -98,36 +98,36 @@ Sub GeneratePickingList()
|
||||
' 写入表头
|
||||
Dim row As Long
|
||||
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 = "领料方式"
|
||||
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
|
||||
|
||||
' 遍历所有根类别
|
||||
Dim rootCats As Collection
|
||||
Dim rootCats As collection
|
||||
Set rootCats = bomMgr.GetRootCategories
|
||||
|
||||
Dim cat As clsCategory
|
||||
Dim Materials As Collection
|
||||
Dim materials As collection
|
||||
Dim mat As clsMaterialItem
|
||||
Dim i As Long, j As Long
|
||||
|
||||
For i = 1 To rootCats.Count
|
||||
Set cat = rootCats(i)
|
||||
' 默认使用父类别物料
|
||||
Set Materials = bomMgr.GetMaterialsForPicking(cat.categoryName, True)
|
||||
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 = "父类别"
|
||||
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
|
||||
@@ -139,64 +139,6 @@ 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
|
||||
@@ -214,15 +156,15 @@ Sub QueryMaterialInfo()
|
||||
If Not cat Is Nothing Then
|
||||
Debug.Print "类别: " & cat.categoryName
|
||||
Debug.Print "父类别: " & cat.ParentCategoryName
|
||||
Debug.Print "物料数: " & cat.Materials.Count
|
||||
Debug.Print "物料数: " & cat.materials.Count
|
||||
Debug.Print "子类别数: " & cat.SubCategories.Count
|
||||
Debug.Print "是否叶子类别: " & cat.IsLeafCategory
|
||||
|
||||
' 列出所有物料
|
||||
Dim mat As clsMaterialItem
|
||||
Dim i As Long
|
||||
For i = 1 To cat.Materials.Count
|
||||
Set mat = cat.Materials(i)
|
||||
For i = 1 To cat.materials.Count
|
||||
Set mat = cat.materials(i)
|
||||
Debug.Print " - " & mat.code & ": " & mat.Name
|
||||
Next i
|
||||
|
||||
@@ -232,7 +174,7 @@ Sub QueryMaterialInfo()
|
||||
For j = 1 To cat.SubCategories.Count
|
||||
Set subCat = cat.SubCategories(j)
|
||||
Debug.Print " 子类别: " & subCat.categoryName & _
|
||||
" (物料数:" & subCat.Materials.Count & ")"
|
||||
" (物料数:" & subCat.materials.Count & ")"
|
||||
Next j
|
||||
End If
|
||||
End Sub
|
||||
375
VBA/Modules/modModelParserExamples.bas
Normal file
375
VBA/Modules/modModelParserExamples.bas
Normal file
@@ -0,0 +1,375 @@
|
||||
' ========================================
|
||||
' 模块: modModelParserExamples
|
||||
' 用途: 型号解析与物料匹配的实际应用示例
|
||||
' ========================================
|
||||
Option Explicit
|
||||
|
||||
' ========================================
|
||||
' 示例1: 根据型号生成完整的领料清单
|
||||
' ========================================
|
||||
Sub Example1_GeneratePickingListByModel()
|
||||
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
|
||||
|
||||
' 产品型号
|
||||
Dim modelStr As String
|
||||
modelStr = "YTHN-100.A0.532.M203.M16.Y3|BP-095.2312.M16.PA3"
|
||||
|
||||
' 创建领料清单工作表
|
||||
Dim wsPickList As Worksheet
|
||||
On Error Resume Next
|
||||
Application.DisplayAlerts = False
|
||||
ThisWorkbook.Worksheets("型号领料清单").Delete
|
||||
Application.DisplayAlerts = True
|
||||
On Error GoTo 0
|
||||
|
||||
Set wsPickList = ThisWorkbook.Worksheets.Add
|
||||
wsPickList.Name = "型号领料清单"
|
||||
|
||||
' 写入表头
|
||||
Dim row As Long
|
||||
row = 1
|
||||
wsPickList.Cells(row, 1).value = "产品型号"
|
||||
wsPickList.Cells(row, 2).value = modelStr
|
||||
row = row + 1
|
||||
|
||||
' 提取条件并显示
|
||||
Dim conditions As Object
|
||||
Set conditions = bomMgr.ParseModelAndExtractConditions(modelStr)
|
||||
wsPickList.Cells(row, 1).value = "提取条件"
|
||||
Dim condStr As String
|
||||
Dim key As Variant
|
||||
For Each key In conditions.Keys
|
||||
condStr = condStr & key & "=" & conditions(key) & "; "
|
||||
Next key
|
||||
wsPickList.Cells(row, 2).value = condStr
|
||||
row = row + 2
|
||||
|
||||
' 表头
|
||||
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 = "匹配状态"
|
||||
wsPickList.Range("A" & row & ":F" & row).Font.Bold = True
|
||||
row = row + 1
|
||||
|
||||
' 遍历所有根类别
|
||||
Dim rootCats As collection
|
||||
Set rootCats = bomMgr.GetRootCategories
|
||||
|
||||
Dim cat As clsCategory
|
||||
Dim materials As collection
|
||||
Dim mat As clsMaterialItem
|
||||
Dim i As Long
|
||||
|
||||
For i = 1 To rootCats.Count
|
||||
Set cat = rootCats(i)
|
||||
|
||||
' 获取该类别符合条件的物料
|
||||
Set materials = bomMgr.GetMaterialsByModel(modelStr, cat.categoryName)
|
||||
|
||||
' 写入物料
|
||||
Dim j As Long
|
||||
For j = 1 To materials.Count
|
||||
Set mat = materials(j)
|
||||
wsPickList.Cells(row, 1).value = cat.categoryName
|
||||
wsPickList.Cells(row, 2).value = mat.code
|
||||
wsPickList.Cells(row, 3).value = mat.Name
|
||||
wsPickList.Cells(row, 4).value = mat.Quantity
|
||||
wsPickList.Cells(row, 5).value = IIf(mat.Condition = "", "(无条件)", mat.Condition)
|
||||
wsPickList.Cells(row, 6).value = "?"
|
||||
row = row + 1
|
||||
Next j
|
||||
Next i
|
||||
|
||||
' 格式化
|
||||
wsPickList.Columns("A:F").AutoFit
|
||||
|
||||
MsgBox "领料清单生成完成!" & vbCrLf & _
|
||||
"请查看工作表: 型号领料清单", vbInformation
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 示例2: 批量处理多个型号
|
||||
' ========================================
|
||||
Sub Example2_BatchProcessModels()
|
||||
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
|
||||
|
||||
' 型号列表
|
||||
Dim models() As String
|
||||
models = Split("YTHN-100.A0.532.M203.M16.Y3|BP-095.2312.M16.PA3," & _
|
||||
"YTHN-100.A0.532.M203.M02.Y3|BP-095.2312.M02.PA3," & _
|
||||
"YTHN-100.A0.532.M203.M12.Y3|BP-095.2312.M12.PA3", ",")
|
||||
|
||||
' 创建汇总表
|
||||
Dim wsReport As Worksheet
|
||||
On Error Resume Next
|
||||
Application.DisplayAlerts = False
|
||||
ThisWorkbook.Worksheets("批量型号汇总").Delete
|
||||
Application.DisplayAlerts = True
|
||||
On Error GoTo 0
|
||||
|
||||
Set wsReport = ThisWorkbook.Worksheets.Add
|
||||
wsReport.Name = "批量型号汇总"
|
||||
|
||||
' 表头
|
||||
Dim row As Long
|
||||
row = 1
|
||||
wsReport.Cells(row, 1).value = "型号"
|
||||
wsReport.Cells(row, 2).value = "提取条件"
|
||||
wsReport.Cells(row, 3).value = "匹配物料数"
|
||||
wsReport.Cells(row, 4).value = "部件物料"
|
||||
wsReport.Range("A1:D1").Font.Bold = True
|
||||
row = row + 1
|
||||
|
||||
' 处理每个型号
|
||||
Dim modelStr As String
|
||||
Dim i As Long
|
||||
|
||||
For i = LBound(models) To UBound(models)
|
||||
modelStr = Trim(models(i))
|
||||
If modelStr <> "" Then
|
||||
' 提取条件
|
||||
Dim conditions As Object
|
||||
Set conditions = bomMgr.ParseModelAndExtractConditions(modelStr)
|
||||
|
||||
Dim condStr As String
|
||||
condStr = ""
|
||||
Dim key As Variant
|
||||
For Each key In conditions.Keys
|
||||
condStr = condStr & key & "=" & conditions(key) & "; "
|
||||
Next key
|
||||
|
||||
' 获取物料
|
||||
Dim materials As collection
|
||||
Set materials = bomMgr.GetMaterialsByModel(modelStr, "部件")
|
||||
|
||||
' 写入结果
|
||||
wsReport.Cells(row, 1).value = modelStr
|
||||
wsReport.Cells(row, 2).value = condStr
|
||||
wsReport.Cells(row, 3).value = materials.Count
|
||||
|
||||
' 列出部件物料
|
||||
Dim matList As String
|
||||
matList = ""
|
||||
Dim mat As clsMaterialItem
|
||||
For Each mat In materials
|
||||
matList = matList & mat.code & "(" & mat.Name & "); "
|
||||
Next mat
|
||||
wsReport.Cells(row, 4).value = matList
|
||||
|
||||
row = row + 1
|
||||
End If
|
||||
Next i
|
||||
|
||||
' 格式化
|
||||
wsReport.Columns("A:D").AutoFit
|
||||
|
||||
MsgBox "批量处理完成!", vbInformation
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 示例3: 查询并显示某个型号的详细信息
|
||||
' ========================================
|
||||
Sub Example3_ShowModelDetails()
|
||||
' 弹出输入框
|
||||
Dim modelStr As String
|
||||
modelStr = InputBox("请输入产品型号:", "型号查询", _
|
||||
"YTHN-100.A0.532.M203.M16.Y3")
|
||||
|
||||
If modelStr = "" Then Exit Sub
|
||||
|
||||
' 解析型号
|
||||
Dim parser As New clsModelParser
|
||||
If Not parser.ParseModel(modelStr) Then
|
||||
MsgBox "型号解析失败: " & parser.ErrorMessage, vbCritical
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
' 提取条件
|
||||
Dim extractor As New clsConditionExtractor
|
||||
Dim conditions As Object
|
||||
Set conditions = extractor.ExtractConditions(parser)
|
||||
|
||||
' 显示详细信息
|
||||
Dim msg As String
|
||||
msg = "【型号解析结果】" & vbCrLf & vbCrLf
|
||||
msg = msg & "原始型号: " & parser.RawModel & vbCrLf
|
||||
msg = msg & "表头型号: " & parser.HeaderModel & vbCrLf
|
||||
msg = msg & "表盘型号: " & parser.DialModel & vbCrLf & vbCrLf
|
||||
|
||||
msg = msg & "【表头各部分】" & vbCrLf
|
||||
msg = msg & "型号: " & parser.ModelType & vbCrLf
|
||||
msg = msg & "公称外径: " & parser.Diameter & vbCrLf
|
||||
msg = msg & "安装形式: " & parser.InstallForm & vbCrLf
|
||||
msg = msg & "壳体形式: " & parser.ShellForm & vbCrLf
|
||||
msg = msg & "过程连接&材质: " & parser.ConnectionCode & vbCrLf
|
||||
msg = msg & "量程范围: " & parser.RangeCode & vbCrLf
|
||||
msg = msg & "仪表特性: " & parser.Characteristics & vbCrLf & vbCrLf
|
||||
|
||||
msg = msg & "【提取的物料选择条件】" & vbCrLf
|
||||
Dim key As Variant
|
||||
For Each key In conditions.Keys
|
||||
msg = msg & key & " = " & conditions(key) & vbCrLf
|
||||
Next key
|
||||
|
||||
MsgBox msg, vbInformation, "型号详细信息"
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 示例4: 对比两个型号的差异
|
||||
' ========================================
|
||||
Sub Example4_CompareModels()
|
||||
Dim model1 As String, model2 As String
|
||||
|
||||
model1 = InputBox("请输入第一个型号:", "型号对比", _
|
||||
"YTHN-100.A0.532.M203.M16.Y3")
|
||||
If model1 = "" Then Exit Sub
|
||||
|
||||
model2 = InputBox("请输入第二个型号:", "型号对比", _
|
||||
"YTHN-100.A0.532.M203.M02.Y3")
|
||||
If model2 = "" Then Exit Sub
|
||||
|
||||
' 解析两个型号
|
||||
Dim parser1 As New clsModelParser
|
||||
Dim parser2 As New clsModelParser
|
||||
Dim extractor As New clsConditionExtractor
|
||||
|
||||
parser1.ParseModel model1
|
||||
parser2.ParseModel model2
|
||||
|
||||
Dim cond1 As Object, cond2 As Object
|
||||
Set cond1 = extractor.ExtractConditions(parser1)
|
||||
|
||||
Set extractor = New clsConditionExtractor
|
||||
Set cond2 = extractor.ExtractConditions(parser2)
|
||||
|
||||
' 对比
|
||||
Dim msg As String
|
||||
msg = "【型号对比】" & vbCrLf & vbCrLf
|
||||
msg = msg & "型号1: " & model1 & vbCrLf
|
||||
msg = msg & "型号2: " & model2 & vbCrLf & vbCrLf
|
||||
|
||||
msg = msg & "【条件差异】" & vbCrLf
|
||||
Dim key As Variant
|
||||
Dim allKeys As Object
|
||||
Set allKeys = CreateObject("Scripting.Dictionary")
|
||||
|
||||
For Each key In cond1.Keys
|
||||
allKeys(key) = True
|
||||
Next key
|
||||
For Each key In cond2.Keys
|
||||
allKeys(key) = True
|
||||
Next key
|
||||
|
||||
For Each key In allKeys.Keys
|
||||
Dim val1 As String, val2 As String
|
||||
val1 = ""
|
||||
val2 = ""
|
||||
|
||||
If cond1.Exists(key) Then val1 = cond1(key)
|
||||
If cond2.Exists(key) Then val2 = cond2(key)
|
||||
|
||||
If val1 <> val2 Then
|
||||
msg = msg & key & ": " & val1 & " → " & val2 & " ?" & vbCrLf
|
||||
Else
|
||||
msg = msg & key & ": " & val1 & " ?" & vbCrLf
|
||||
End If
|
||||
Next key
|
||||
|
||||
MsgBox msg, vbInformation, "型号对比结果"
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 示例5: 验证物料选择条件的有效性
|
||||
' ========================================
|
||||
Sub Example5_ValidateMaterialConditions()
|
||||
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
|
||||
|
||||
' 创建验证结果表
|
||||
Dim wsValidation As Worksheet
|
||||
On Error Resume Next
|
||||
Application.DisplayAlerts = False
|
||||
ThisWorkbook.Worksheets("条件验证结果").Delete
|
||||
Application.DisplayAlerts = True
|
||||
On Error GoTo 0
|
||||
|
||||
Set wsValidation = ThisWorkbook.Worksheets.Add
|
||||
wsValidation.Name = "条件验证结果"
|
||||
|
||||
' 表头
|
||||
Dim row As Long
|
||||
row = 1
|
||||
wsValidation.Cells(row, 1).value = "代号"
|
||||
wsValidation.Cells(row, 2).value = "名称"
|
||||
wsValidation.Cells(row, 3).value = "选择条件"
|
||||
wsValidation.Cells(row, 4).value = "验证结果"
|
||||
wsValidation.Range("A1:D1").Font.Bold = True
|
||||
row = row + 1
|
||||
|
||||
' 获取所有根类别
|
||||
Dim rootCats As collection
|
||||
Set rootCats = bomMgr.GetRootCategories
|
||||
|
||||
Dim cat As clsCategory
|
||||
Dim materials As collection
|
||||
Dim mat As clsMaterialItem
|
||||
Dim matcher As New clsConditionMatcher
|
||||
Dim i As Long
|
||||
|
||||
' 遍历所有物料
|
||||
For i = 1 To rootCats.Count
|
||||
Set cat = rootCats(i)
|
||||
Set materials = New collection
|
||||
|
||||
' 收集该类别的所有物料
|
||||
Dim j As Long
|
||||
For j = 1 To cat.materials.Count
|
||||
materials.Add cat.materials(j)
|
||||
Next j
|
||||
|
||||
' 验证每个物料的条件
|
||||
For Each mat In materials
|
||||
wsValidation.Cells(row, 1).value = mat.code
|
||||
wsValidation.Cells(row, 2).value = mat.Name
|
||||
wsValidation.Cells(row, 3).value = IIf(mat.Condition = "", "(无)", mat.Condition)
|
||||
|
||||
If mat.Condition = "" Then
|
||||
wsValidation.Cells(row, 4).value = "? 无条件"
|
||||
Else
|
||||
Dim validResult As String
|
||||
validResult = matcher.TestExpression(mat.Condition)
|
||||
wsValidation.Cells(row, 4).value = validResult
|
||||
End If
|
||||
|
||||
row = row + 1
|
||||
Next mat
|
||||
Next i
|
||||
|
||||
' 格式化
|
||||
wsValidation.Columns("A:D").AutoFit
|
||||
|
||||
MsgBox "条件验证完成!", vbInformation
|
||||
End Sub
|
||||
309
VBA/Modules/modModelParserTest.bas
Normal file
309
VBA/Modules/modModelParserTest.bas
Normal file
@@ -0,0 +1,309 @@
|
||||
' ========================================
|
||||
' 模块: modModelParserTest
|
||||
' 用途: 测试型号解析和物料匹配功能
|
||||
' ========================================
|
||||
Option Explicit
|
||||
|
||||
' ========================================
|
||||
' 测试1: 型号解析器基础功能
|
||||
' ========================================
|
||||
Sub Test1_ModelParser()
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print "测试1: 型号解析器基础功能"
|
||||
Debug.Print String(80, "=")
|
||||
|
||||
Dim parser As New clsModelParser
|
||||
Dim modelStr As String
|
||||
|
||||
' 测试用例1: 完整型号
|
||||
modelStr = "YTHN-100.A0.532.M203.M16.Y3|BP-095.2312.M16.PA3"
|
||||
Debug.Print "【测试用例1】完整型号"
|
||||
Debug.Print "输入: " & modelStr
|
||||
|
||||
If parser.ParseModel(modelStr) Then
|
||||
Debug.Print parser.ToString()
|
||||
Debug.Print "? 解析成功"
|
||||
Else
|
||||
Debug.Print "? 解析失败: " & parser.ErrorMessage
|
||||
End If
|
||||
|
||||
Debug.Print ""
|
||||
|
||||
' 测试用例2: 仅表头
|
||||
modelStr = "YTHN-100.A0.532.M203.M16.Y3"
|
||||
Debug.Print "【测试用例2】仅表头"
|
||||
Debug.Print "输入: " & modelStr
|
||||
|
||||
If parser.ParseModel(modelStr) Then
|
||||
Debug.Print " 螺纹代码: " & parser.GetThreadCode()
|
||||
Debug.Print " 材质代码: " & parser.GetMaterialCode()
|
||||
Debug.Print " 量程代码: " & parser.GetRangeCode()
|
||||
Debug.Print "? 解析成功"
|
||||
Else
|
||||
Debug.Print "? 解析失败: " & parser.ErrorMessage
|
||||
End If
|
||||
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print ""
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 测试2: 条件提取器
|
||||
' ========================================
|
||||
Sub Test2_ConditionExtractor()
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print "测试2: 条件提取器"
|
||||
Debug.Print String(80, "=")
|
||||
|
||||
Dim parser As New clsModelParser
|
||||
Dim extractor As New clsConditionExtractor
|
||||
Dim modelStr As String
|
||||
|
||||
modelStr = "YTHN-100.A0.532.M203.M16.Y3"
|
||||
Debug.Print "输入型号: " & modelStr
|
||||
|
||||
If parser.ParseModel(modelStr) Then
|
||||
Dim conditions As Object
|
||||
Set conditions = extractor.ExtractConditions(parser)
|
||||
|
||||
Debug.Print extractor.ToString()
|
||||
|
||||
' 验证提取结果
|
||||
Debug.Print "【验证】"
|
||||
Debug.Print " gclj = " & extractor.GetConditionValue("gclj") & _
|
||||
IIf(extractor.GetConditionValue("gclj") = "M20", " ?", " ?")
|
||||
Debug.Print " jycz = " & extractor.GetConditionValue("jycz") & _
|
||||
IIf(extractor.GetConditionValue("jycz") = "3", " ?", " ?")
|
||||
Debug.Print " lcfw = " & extractor.GetConditionValue("lcfw") & _
|
||||
IIf(extractor.GetConditionValue("lcfw") = "M16", " ?", " ?")
|
||||
Else
|
||||
Debug.Print "? 型号解析失败"
|
||||
End If
|
||||
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print ""
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 测试3: 条件匹配器
|
||||
' ========================================
|
||||
Sub Test3_ConditionMatcher()
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print "测试3: 条件匹配器"
|
||||
Debug.Print String(80, "=")
|
||||
|
||||
Dim matcher As New clsConditionMatcher
|
||||
Dim conditions As Object
|
||||
Set conditions = CreateObject("Scripting.Dictionary")
|
||||
conditions("gclj") = "M20"
|
||||
conditions("jycz") = "3"
|
||||
conditions("lcfw") = "M16"
|
||||
|
||||
Debug.Print "【测试条件】"
|
||||
Debug.Print " gclj = M20"
|
||||
Debug.Print " jycz = 3"
|
||||
Debug.Print " lcfw = M16"
|
||||
Debug.Print ""
|
||||
|
||||
' 测试用例
|
||||
Dim testCases As Variant
|
||||
testCases = Array( _
|
||||
Array("", True, "空条件"), _
|
||||
Array("lcfw=M16", True, "简单等于"), _
|
||||
Array("lcfw=M17", False, "简单不匹配"), _
|
||||
Array("lcfw=M16 AND gclj=M20", True, "AND 全真"), _
|
||||
Array("lcfw=M16 AND gclj=M10", False, "AND 一假"), _
|
||||
Array("lcfw=M16 OR lcfw=M17", True, "OR 一真"), _
|
||||
Array("lcfw=M15 OR lcfw=M17", False, "OR 全假"), _
|
||||
Array("gclj!=M10", True, "不等于 真"), _
|
||||
Array("gclj!=M20", False, "不等于 假"), _
|
||||
Array("lcfw=M02 AND gclj!=M20", False, "复合条件1"), _
|
||||
Array("lcfw=M16 AND gclj!=M10", True, "复合条件2"), _
|
||||
Array("gclj=M20 AND (lcfw=M16 OR lcfw=M17)", True, "括号优先级1"), _
|
||||
Array("gclj=M20 AND (lcfw=M15 OR lcfw=M17)", False, "括号优先级2") _
|
||||
)
|
||||
|
||||
Dim i As Long
|
||||
Dim testCase As Variant
|
||||
Dim expr As String
|
||||
Dim expected As Boolean
|
||||
Dim actual As Boolean
|
||||
Dim description As String
|
||||
Dim passCount As Long
|
||||
Dim failCount As Long
|
||||
|
||||
passCount = 0
|
||||
failCount = 0
|
||||
|
||||
Debug.Print "【测试用例】"
|
||||
For i = LBound(testCases) To UBound(testCases)
|
||||
testCase = testCases(i)
|
||||
expr = testCase(0)
|
||||
expected = testCase(1)
|
||||
description = testCase(2)
|
||||
|
||||
actual = matcher.IsMatch(expr, conditions)
|
||||
|
||||
If actual = expected Then
|
||||
Debug.Print " ? " & description & ": " & IIf(expr = "", "(空)", expr)
|
||||
passCount = passCount + 1
|
||||
Else
|
||||
Debug.Print " ? " & description & ": " & expr
|
||||
Debug.Print " 预期: " & expected & ", 实际: " & actual
|
||||
failCount = failCount + 1
|
||||
End If
|
||||
Next i
|
||||
|
||||
Debug.Print ""
|
||||
Debug.Print "【统计】"
|
||||
Debug.Print " 通过: " & passCount
|
||||
Debug.Print " 失败: " & failCount
|
||||
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print ""
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 测试4: 完整流程 - 根据型号获取物料
|
||||
' ========================================
|
||||
Sub Test4_GetMaterialsByModel()
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print "测试4: 根据型号获取物料(完整流程)"
|
||||
Debug.Print String(80, "=")
|
||||
|
||||
' 加载BOM数据
|
||||
Dim bomMgr As New clsBOMManager
|
||||
Dim wsConfig As Worksheet
|
||||
Dim wsPlatform As Worksheet
|
||||
|
||||
On Error Resume Next
|
||||
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
|
||||
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
|
||||
On Error GoTo 0
|
||||
|
||||
If wsConfig Is Nothing Or wsPlatform Is Nothing Then
|
||||
Debug.Print "? 错误: 找不到必需的工作表"
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
bomMgr.LoadData wsConfig, wsPlatform
|
||||
Debug.Print "? BOM数据加载完成"
|
||||
Debug.Print ""
|
||||
|
||||
' 测试型号
|
||||
Dim modelStr As String
|
||||
modelStr = "YTHN-100.A0.532.M203.M16.Y3|BP-095.2312.M16.PA3"
|
||||
|
||||
' 获取"部件"类别的符合条件的物料
|
||||
Dim materials As collection
|
||||
Set materials = bomMgr.GetMaterialsByModel(modelStr, "部件")
|
||||
|
||||
Debug.Print ""
|
||||
Debug.Print "【结果验证】"
|
||||
If materials.Count = 1 Then
|
||||
Dim mat As clsMaterialItem
|
||||
Set mat = materials(1)
|
||||
If mat.code = "01011019018" And mat.Name = "高压接头部件" Then
|
||||
Debug.Print "? 测试通过!成功匹配到正确的物料"
|
||||
Debug.Print " 代号: " & mat.code
|
||||
Debug.Print " 名称: " & mat.Name
|
||||
Debug.Print " 条件: " & mat.Condition
|
||||
Else
|
||||
Debug.Print "? 匹配到的物料不正确"
|
||||
End If
|
||||
Else
|
||||
Debug.Print "? 匹配数量不正确,预期1个,实际" & materials.Count & "个"
|
||||
End If
|
||||
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print ""
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 测试5: 获取所有类别的符合条件的物料
|
||||
' ========================================
|
||||
Sub Test5_GetAllMaterialsByModel()
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print "测试5: 获取所有类别的符合条件的物料"
|
||||
Debug.Print String(80, "=")
|
||||
|
||||
' 加载BOM数据
|
||||
Dim bomMgr As New clsBOMManager
|
||||
Dim wsConfig As Worksheet
|
||||
Dim wsPlatform As Worksheet
|
||||
|
||||
On Error Resume Next
|
||||
Set wsConfig = ThisWorkbook.Worksheets("领料配置")
|
||||
Set wsPlatform = ThisWorkbook.Worksheets("平台配置清单")
|
||||
On Error GoTo 0
|
||||
|
||||
If wsConfig Is Nothing Or wsPlatform Is Nothing Then
|
||||
Debug.Print "? 错误: 找不到必需的工作表"
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
bomMgr.LoadData wsConfig, wsPlatform
|
||||
|
||||
' 测试型号
|
||||
Dim modelStr As String
|
||||
modelStr = "YTHN-100.A0.532.M203.M16.Y3"
|
||||
|
||||
' 获取所有类别的符合条件的物料
|
||||
Dim materials As collection
|
||||
Set materials = bomMgr.GetMaterialsByModel(modelStr)
|
||||
|
||||
Debug.Print ""
|
||||
Debug.Print "【匹配结果汇总】"
|
||||
Debug.Print " 共匹配 " & materials.Count & " 个物料"
|
||||
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print ""
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 运行所有测试
|
||||
' ========================================
|
||||
Sub RunAllTests()
|
||||
Debug.Print vbCrLf & vbCrLf
|
||||
Debug.Print "╔" & String(78, "═") & "╗"
|
||||
Debug.Print "║" & Space(20) & "型号解析与物料匹配 - 完整测试套件" & Space(20) & "║"
|
||||
Debug.Print "╚" & String(78, "═") & "╝"
|
||||
Debug.Print ""
|
||||
|
||||
Test1_ModelParser
|
||||
Test2_ConditionExtractor
|
||||
Test3_ConditionMatcher
|
||||
Test4_GetMaterialsByModel
|
||||
Test5_GetAllMaterialsByModel
|
||||
|
||||
Debug.Print "╔" & String(78, "═") & "╗"
|
||||
Debug.Print "║" & Space(30) & "所有测试完成" & Space(30) & "║"
|
||||
Debug.Print "╚" & String(78, "═") & "╝"
|
||||
End Sub
|
||||
|
||||
' ========================================
|
||||
' 测试6: 条件提取规则展示
|
||||
' ========================================
|
||||
Sub Test6_ShowExtractionRules()
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print "测试6: 当前配置的条件提取规则"
|
||||
Debug.Print String(80, "=")
|
||||
|
||||
Dim extractor As New clsConditionExtractor
|
||||
Dim rules As Object
|
||||
Set rules = extractor.GetExtractionRules()
|
||||
|
||||
Debug.Print "【提取规则配置】"
|
||||
Dim key As Variant
|
||||
For Each key In rules.Keys
|
||||
Dim ruleInfo As Variant
|
||||
ruleInfo = rules(key)
|
||||
Debug.Print " 变量名: " & key
|
||||
Debug.Print " 源字段: " & ruleInfo(0)
|
||||
Debug.Print " 提取方法: " & ruleInfo(1)
|
||||
Debug.Print ""
|
||||
Next key
|
||||
|
||||
Debug.Print String(80, "=")
|
||||
Debug.Print ""
|
||||
End Sub
|
||||
@@ -31,12 +31,6 @@
|
||||
"attributes": {},
|
||||
"file": "DocumentModules\\Sheet4.cls"
|
||||
},
|
||||
"Sheet6.cls": {
|
||||
"name": "Sheet6",
|
||||
"type": "DocumentModules",
|
||||
"attributes": {},
|
||||
"file": "DocumentModules\\Sheet6.cls"
|
||||
},
|
||||
"clsCategory.cls": {
|
||||
"name": "clsCategory",
|
||||
"type": "ClassModules",
|
||||
@@ -60,6 +54,42 @@
|
||||
"type": "ClassModules",
|
||||
"attributes": {},
|
||||
"file": "ClassModules\\clsBOMManager.cls"
|
||||
},
|
||||
"Sheet6.cls": {
|
||||
"name": "Sheet6",
|
||||
"type": "DocumentModules",
|
||||
"attributes": {},
|
||||
"file": "DocumentModules\\Sheet6.cls"
|
||||
},
|
||||
"clsModelParser.cls": {
|
||||
"name": "clsModelParser",
|
||||
"type": "ClassModules",
|
||||
"attributes": {},
|
||||
"file": "ClassModules\\clsModelParser.cls"
|
||||
},
|
||||
"clsConditionExtractor.cls": {
|
||||
"name": "clsConditionExtractor",
|
||||
"type": "ClassModules",
|
||||
"attributes": {},
|
||||
"file": "ClassModules\\clsConditionExtractor.cls"
|
||||
},
|
||||
"clsConditionMatcher.cls": {
|
||||
"name": "clsConditionMatcher",
|
||||
"type": "ClassModules",
|
||||
"attributes": {},
|
||||
"file": "ClassModules\\clsConditionMatcher.cls"
|
||||
},
|
||||
"modModelParserTest.bas": {
|
||||
"name": "modModelParserTest",
|
||||
"type": "Modules",
|
||||
"attributes": {},
|
||||
"file": "Modules\\modModelParserTest.bas"
|
||||
},
|
||||
"modModelParserExamples.bas": {
|
||||
"name": "modModelParserExamples",
|
||||
"type": "Modules",
|
||||
"attributes": {},
|
||||
"file": "Modules\\modModelParserExamples.bas"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user