feat: add preprocessing with value mapping to BOM Extraction System
All checks were successful
NTFY Notification / notify (push) Successful in 4s

Add a preprocessing step to the BOM Extraction System to enhance parameter
extraction with mapping values from "对照表" worksheet. For azxs (安装形式)
and lcfw (量程范围), the system now stores both the raw parsed value AND the
mapped value from the lookup table, enabling flexible dual-value matching.

Changes:
- Create M06A_Mapper.bas: New module for value mapping
  - Load azxs/lcfw mappings from "对照表" worksheet
  - Return dual-value format "raw,mapped" (e.g., "A0,径向")
  - Support graceful degradation if "对照表" not found
  - Define constants locally to avoid VBA cross-module reference issues

- Modify M06_ModelParser.bas:
  - Extract raw parameter values first
  - Apply mapping via M06A_Mapper if initialized
  - Store dual values for azxs and lcfw parameters

- Modify M07_BOMMatcher.bas:
  - Update EvaluateCellCondition() to support dual-value matching
  - Split by comma and check if ANY value matches
  - Backward compatible with single-value parameters

- Modify M09_BOMExtractor.bas:
  - Initialize M06A_Mapper during RunBOMExtraction()
  - Add WorksheetExists() helper function
  - Log warning if "对照表" worksheet not found
  - Define MAPPING_SHEET_NAME constant locally

- Modify M04_Config.bas:
  - Add mapping table configuration constants
  - MAPPING_SHEET_NAME, MAPPING_COL_LCFW_KEY, etc.

- Update CLAUDE.md:
  - Document new M06A_Mapper module
  - Update data flow diagram with mapping step
  - Document dual-value matching behavior
  - Update system architecture diagram

- Update docs/RunBOMExtraction_运行机制详解.md:
  - Add M06A_Mapper to all diagrams and documentation
  - Add detailed value mapping section
  - Update sequence diagrams with mapping flow
  - Update parameter examples with dual-value format
  - Bump documentation version to 3.0

Example:
  Input:  Product model "YTHN-100.A0.531.G123.M04.Y3"
  Parse:  azxs="A0", lcfw="M04"
  Map:    azxs="A0,径向", lcfw="M04,高压"
  Match:  BOM库 with azxs="径向" OR "A0" → MATCH

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-02-12 17:52:03 +08:00
parent 21f5f1c299
commit 1d5bad86f7
7 changed files with 626 additions and 47 deletions

View File

@@ -74,6 +74,16 @@ Public Function GetBOMConditionFields() As Variant
)
End Function
' ------------------------------------------------------------------------------
' 映射表配置常量
' ------------------------------------------------------------------------------
Public Const MAPPING_SHEET_NAME As String = "对照表"
Public Const MAPPING_COL_LCFW_KEY As Long = 1 ' A列 - lcfw原始值
Public Const MAPPING_COL_LCFW_VAL As Long = 2 ' B列 - lcfw映射值
Public Const MAPPING_COL_AZXS_KEY As Long = 4 ' D列 - azxs原始值
Public Const MAPPING_COL_AZXS_VAL As Long = 5 ' E列 - azxs映射值
Public Const MAPPING_START_ROW As Long = 3 ' 数据起始行
' 检查列名是否为条件列
Public Function IsConditionField(ByVal colName As String) As Boolean
Dim fields As Variant

View File

@@ -0,0 +1,210 @@
' ==============================================================================
' 模块: M06A_Mapper
' 职责: 值映射模块为BOM Extraction System提供azxs和lcfw参数映射
'
' 功能:
' - 从"对照表"工作表加载映射数据
' - 将原始值转换为"原始值,映射值"格式
' - 支持azxs安装形式和lcfw量程范围映射
'
' 使用场景:
' 产品型号解析后,调用映射器为参数添加映射值,支持双值匹配
'
' 示例:
' 输入: azxs="A0"
' 输出: azxs="A0,径向"
'
' BOM库中azxs="A0"或"径向"均可匹配成功
' ==============================================================================
Option Explicit
' 模块级常量 - 映射表配置
Private Const MAPPING_COL_LCFW_KEY As Long = 1 ' A列 - lcfw原始值
Private Const MAPPING_COL_LCFW_VAL As Long = 2 ' B列 - lcfw映射值
Private Const MAPPING_COL_AZXS_KEY As Long = 4 ' D列 - azxs原始值
Private Const MAPPING_COL_AZXS_VAL As Long = 5 ' E列 - azxs映射值
Private Const MAPPING_START_ROW As Long = 3 ' 数据起始行
' 模块级变量
Private g_LcfwMapping As Object ' Scripting.Dictionary - lcfw映射表
Private g_AzxsMapping As Object ' Scripting.Dictionary - azxs映射表
Private g_Logger As clsErrorLogger
Private g_IsInitialized As Boolean
' ------------------------------------------------------------------------------
' 初始化映射器
'
' 输入:
' logger - 错误记录器
' wsMapping - 对照表工作表
'
' 说明:
' 从对照表工作表加载lcfw和azxs映射数据
' - lcfw映射: A列:B列 (M01->低压, M12->高压)
' - azxs映射: D列:E列 (A0->径向, AT->径向, etc.)
' ------------------------------------------------------------------------------
Public Sub InitMapper(logger As clsErrorLogger, wsMapping As Worksheet)
Set g_Logger = logger
Set g_LcfwMapping = CreateObject("Scripting.Dictionary")
Set g_AzxsMapping = CreateObject("Scripting.Dictionary")
' 从[对照表]加载映射
Call LoadLcfwMapping(wsMapping)
Call LoadAzxsMapping(wsMapping)
g_IsInitialized = True
End Sub
' ------------------------------------------------------------------------------
' 检查是否已初始化
' ------------------------------------------------------------------------------
Public Function IsInitialized() As Boolean
IsInitialized = g_IsInitialized
End Function
' ------------------------------------------------------------------------------
' 映射azxs值
'
' 输入:
' rawValue - 原始azxs值如"A0"
'
' 输出:
' String - "raw,mapped"格式(如"A0,径向")或原始值(如果未找到映射)
'
' 示例:
' MapAzxs("A0") = "A0,径向"
' MapAzxs("AT") = "AT,径向"
' MapAzxs("XX") = "XX" (未找到映射)
' ------------------------------------------------------------------------------
Public Function MapAzxs(ByVal rawValue As String) As String
rawValue = Trim(rawValue)
' 如果未初始化或值为空,直接返回原始值
If Not g_IsInitialized Or Len(rawValue) = 0 Then
MapAzxs = rawValue
Exit Function
End If
' 查找映射值
If g_AzxsMapping.Exists(rawValue) Then
Dim mappedValue As String
mappedValue = g_AzxsMapping(rawValue)
MapAzxs = rawValue & "," & mappedValue
Else
' 未找到映射,返回原始值
MapAzxs = rawValue
End If
End Function
' ------------------------------------------------------------------------------
' 映射lcfw值
'
' 输入:
' rawValue - 原始lcfw值如"M01"
'
' 输出:
' String - "raw,mapped"格式(如"M01,低压")或原始值(如果未找到映射)
'
' 示例:
' MapLcfw("M01") = "M01,低压"
' MapLcfw("M12") = "M12,高压"
' MapLcfw("XX") = "XX" (未找到映射)
' ------------------------------------------------------------------------------
Public Function MapLcfw(ByVal rawValue As String) As String
rawValue = Trim(rawValue)
' 如果未初始化或值为空,直接返回原始值
If Not g_IsInitialized Or Len(rawValue) = 0 Then
MapLcfw = rawValue
Exit Function
End If
' 查找映射值
If g_LcfwMapping.Exists(rawValue) Then
Dim mappedValue As String
mappedValue = g_LcfwMapping(rawValue)
MapLcfw = rawValue & "," & mappedValue
Else
' 未找到映射,返回原始值
MapLcfw = rawValue
End If
End Function
' ------------------------------------------------------------------------------
' 加载lcfw映射从A列:B列列1:2
'
' 数据格式:
' Row 3+: M01 | 低压
' M12 | 高压
' etc.
' ------------------------------------------------------------------------------
Private Sub LoadLcfwMapping(wsMapping As Worksheet)
Dim lastRow As Long
lastRow = wsMapping.Cells(wsMapping.Rows.count, 1).End(xlUp).row
Dim i As Long
Dim key As String, val As String
' 从第3行开始读取
For i = MAPPING_START_ROW To lastRow
key = Trim(CStr(wsMapping.Cells(i, MAPPING_COL_LCFW_KEY).Value))
val = Trim(CStr(wsMapping.Cells(i, MAPPING_COL_LCFW_VAL).Value))
If Len(key) > 0 And Len(val) > 0 Then
If Not g_LcfwMapping.Exists(key) Then
g_LcfwMapping.Add key, val
End If
End If
Next i
End Sub
' ------------------------------------------------------------------------------
' 加载azxs映射从D列:E列列4:5
'
' 数据格式:
' Row 3+: A0 | 径向
' AT | 径向
' B0 | 下轴向
' etc.
' ------------------------------------------------------------------------------
Private Sub LoadAzxsMapping(wsMapping As Worksheet)
Dim lastRow As Long
lastRow = wsMapping.Cells(wsMapping.Rows.count, MAPPING_COL_AZXS_KEY).End(xlUp).row
Dim i As Long
Dim key As String, val As String
' 从第3行开始读取
For i = MAPPING_START_ROW To lastRow
key = Trim(CStr(wsMapping.Cells(i, MAPPING_COL_AZXS_KEY).Value))
val = Trim(CStr(wsMapping.Cells(i, MAPPING_COL_AZXS_VAL).Value))
If Len(key) > 0 And Len(val) > 0 Then
If Not g_AzxsMapping.Exists(key) Then
g_AzxsMapping.Add key, val
End If
End If
Next i
End Sub
' ------------------------------------------------------------------------------
' 测试辅助函数获取lcfw映射值
' ------------------------------------------------------------------------------
Public Function GetLcfwMappedValue(key As String) As String
If g_LcfwMapping.Exists(key) Then
GetLcfwMappedValue = g_LcfwMapping(key)
Else
GetLcfwMappedValue = ""
End If
End Function
' ------------------------------------------------------------------------------
' 测试辅助函数获取azxs映射值
' ------------------------------------------------------------------------------
Public Function GetAzxsMappedValue(key As String) As String
If g_AzxsMapping.Exists(key) Then
GetAzxsMappedValue = g_AzxsMapping(key)
Else
GetAzxsMappedValue = ""
End If
End Function

View File

@@ -96,27 +96,63 @@ Public Function ParseProductModel(ByVal modelString As String) As Object
' 步骤5: 提取各参数
' 注意segments(0)是"型号-公称外径"需要从segments(1)开始提取参数
' 提取原始值
Dim azxsRaw As String, bkxsRaw As String
Dim gcljRaw As String, jyczRaw As String
Dim lcfwRaw As String, fjgnRaw As String
If UBound(segments) - LBound(segments) + 1 >= 2 Then
params("azxs") = ExtractAzxs(segments(1))
azxsRaw = ExtractAzxs(segments(1))
End If
If UBound(segments) - LBound(segments) + 1 >= 3 Then
params("bkxs") = ExtractBkxs(segments(2))
bkxsRaw = ExtractBkxs(segments(2))
End If
If UBound(segments) - LBound(segments) + 1 >= 4 Then
Dim gclj As String, jycz As String
Call ExtractGcljAndJycz(segments(3), gclj, jycz)
params("gclj") = gclj
params("jycz") = jycz
Call ExtractGcljAndJycz(segments(3), gcljRaw, jyczRaw)
End If
If UBound(segments) - LBound(segments) + 1 >= 5 Then
params("lcfw") = ExtractLcfw(segments(4))
lcfwRaw = ExtractLcfw(segments(4))
End If
If UBound(segments) - LBound(segments) + 1 >= 6 Then
params("fjgn") = ExtractFjgn(segments, 5)
fjgnRaw = ExtractFjgn(segments, 5)
End If
' 步骤6: 应用映射(如果映射器已初始化)
If M06A_Mapper.IsInitialized() Then
' 应用azxs和lcfw映射返回双值格式raw,mapped
If Len(azxsRaw) > 0 Then
params("azxs") = M06A_Mapper.MapAzxs(azxsRaw)
End If
If Len(lcfwRaw) > 0 Then
params("lcfw") = M06A_Mapper.MapLcfw(lcfwRaw)
End If
Else
' 映射器未初始化,使用原始值
If Len(azxsRaw) > 0 Then
params("azxs") = azxsRaw
End If
If Len(lcfwRaw) > 0 Then
params("lcfw") = lcfwRaw
End If
End If
' 添加其他参数(不需要映射)
If Len(bkxsRaw) > 0 Then
params("bkxs") = bkxsRaw
End If
If Len(gcljRaw) > 0 Then
params("gclj") = gcljRaw
End If
If Len(jyczRaw) > 0 Then
params("jycz") = jyczRaw
End If
If Len(fjgnRaw) > 0 Then
params("fjgn") = fjgnRaw
End If
Set ParseProductModel = params

View File

@@ -257,7 +257,27 @@ Public Function EvaluateCellCondition( _
Exit Function
End If
' 精确匹配
' 支持双值匹配(如 "A0,径向" 可以匹配 "A0" 或 "径向"
' 检查参数值是否包含逗号(表示有映射值)
If InStr(paramValue, ",") > 0 Then
Dim paramValues As Variant
paramValues = Split(paramValue, ",")
' 只要参数中的任意一个值匹配单元格值,即认为匹配
Dim i As Long
For i = LBound(paramValues) To UBound(paramValues)
If Trim(CStr(paramValues(i))) = cellStr Then
EvaluateCellCondition = True
Exit Function
End If
Next i
' 所有值都不匹配
EvaluateCellCondition = False
Exit Function
End If
' 单值精确匹配
EvaluateCellCondition = (paramValue = cellStr)
Exit Function

View File

@@ -21,6 +21,9 @@
' ==============================================================================
Option Explicit
' 模块级常量 - 映射表配置
Private Const MAPPING_SHEET_NAME As String = "对照表"
' 模块级变量
Private g_Logger As clsErrorLogger
Private g_BOMWorkbook As Workbook
@@ -92,6 +95,18 @@ Public Function RunBOMExtraction() As String
M07_BOMMatcher.InitBOMMatcher g_Logger
M08_ComponentProcessor.InitComponentProcessor g_Logger
' 初始化映射器(新增)
If WorksheetExists(MAPPING_SHEET_NAME) Then
Dim wsMapping As Worksheet
Set wsMapping = ThisWorkbook.Sheets(MAPPING_SHEET_NAME)
M06A_Mapper.InitMapper g_Logger, wsMapping
Else
If Not g_Logger Is Nothing Then
g_Logger.RecordWarning 0, "M09.RunBOMExtraction", "MappingTableMissing", _
"未找到对照表工作表azxs和lcfw将仅使用原始值匹配", ""
End If
End If
' 步骤4: 处理每个产品型号
Application.StatusBar = "正在处理产品型号..."
@@ -1026,4 +1041,21 @@ Private Function OpenBOMLibrary() As Workbook
ErrorHandler:
Set OpenBOMLibrary = Nothing
End Function
' ------------------------------------------------------------------------------
' 检查工作表是否存在
'
' 输入:
' sheetName - 工作表名称
'
' 输出:
' Boolean - True表示工作表存在False表示不存在
' ------------------------------------------------------------------------------
Private Function WorksheetExists(ByVal sheetName As String) As Boolean
On Error Resume Next
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(sheetName)
WorksheetExists = Not ws Is Nothing
On Error GoTo 0
End Function