Files
AutoBOM/docs/提取备注数据来源.md
Misaka_Company 04099d25bc docs: add extraction remarks data source documentation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 09:58:29 +08:00

13 KiB
Raw Permalink Blame History

提取备注字段数据来源分析

文档生成时间: 2026-03-13
入口函数: MainModule.ProcessProductModels()
输出位置: BOM 提取结果 工作表的"提取备注"列(最后一列)


核心数据流图

flowchart TD
    A[ProcessProductModels<br/>主入口] --> B[ProcessSingleModel<br/>处理单个型号]
    
    B --> C{解析产品型号<br/>parser.Parse}
    
    C -->|解析失败 | D["extractNote = <br/>解析失败: + ErrorMessage"]
    C -->|解析成功 | E[BomExtractor.ExtractBom<br/>提取 BOM]
    
    E --> F[DetermineRequiredCategories<br/>确定必需类别]
    F --> G[MatchItems<br/>匹配物料]
    
    G --> H{匹配数量?}
    H -->|0 条 | I[不立即报错<br/>移交 ValidateResult]
    H -->|1 条 | J[正常添加到结果集]
    H -->|多条 | K["记录错误到 pErrorMessages<br/>类别 X 匹配到多条物料 N 条"]
    K --> L[设置 item.MatchError<br/>并添加所有匹配项]
    
    I --> M[ValidateResult<br/>双向覆盖检查]
    L --> M
    J --> M
    
    M --> N{必需类别存在?}
    N -->|被子类覆盖 | O[视为正常<br/>不报错]
    N -->|被父类覆盖 | O
    N -->|确实缺失 | P["记录错误<br/>必需类别 X 未匹配"]
    
    O --> Q[GetErrorSummary<br/>汇总错误]
    P --> Q
    
    Q --> R{bomErrors 为空?}
    R -->|非空 | S[extractNote = bomErrors]
    R -->|空 | T[extractNote 保持空]
    
    S --> U{matchedItems 为空?}
    T --> U
    
    U -->|是 | V{extractNote 为空?}
    U -->|否 | W[遍历每个 item]
    
    V -->|是 | X["extractNote = <br/>未匹配到任何物料"]
    V -->|否 | Y[保持现有 extractNote]
    
    X --> Z1[CreateOutputRowArray<br/>创建输出行]
    Y --> Z1
    
    W --> AA[For Each item<br/>itemNote = extractNote]
    AA --> AB{item.MatchError<br/>非空?}
    AB -->|是 | AC["拼接itemNote += <br/>; + MatchError"]
    AB -->|否 | AD[保持 itemNote]
    
    AC --> AE[CreateOutputRowArray<br/>创建输出行]
    AD --> AE
    
    Z1 --> AF[输出到 BOM 提取结果<br/>提取备注列]
    AE --> AF
    
    style D fill:#ff6b6b
    style K fill:#ffa94d
    style P fill:#ff6b6b
    style X fill:#51cf66
    style AF fill:#339af0,color:#fff

详细数据来源

来源 1: 产品型号解析失败

位置: MainModule.bas 第 184-188 行
触发条件: ProductModelParser.Parse() 返回 False
错误来源: ProductModelParser.ErrorMessage

' MainModule.bas:184-188
If Not parser.Parse(modelString) Then
    ' 解析失败
    extractNote = "解析失败:" & parser.ErrorMessage
    outputData.Add CreateOutputRowArray(..., extractNote, Nothing)
    Exit Sub
End If

可能的错误消息(来自 ProductModelParser.cls:

错误场景 错误消息示例 源码位置
缺少表头部分 型号格式错误:缺少表头部分 Parse() L73
缺少'-'分隔符 表头格式错误:缺少'-'分隔符 ParseHeader() L108
表头结构不完整 表头结构不完整:缺少必要字段 ParseHeader() L114
过程连接代码格式错误 过程连接代码格式错误:长度不足 ExtractConnectionAndMaterial() L205
最后一位不是数字 过程连接代码格式错误:最后一位不是数字 ExtractConnectionAndMaterial() L213
解析异常 解析表头异常:[VBA 错误描述] ParseHeader() ErrorHandler L131

来源 2: BOM 提取器错误汇总

位置: MainModule.bas 第 197-200 行
触发条件: BomExtractor.GetErrorSummary() 返回非空字符串
错误来源: BomExtractor.pErrorMessages 集合

' MainModule.bas:197-200
Dim bomErrors As String
bomErrors = BomExtractor.GetErrorSummary
If bomErrors <> "" Then
    extractNote = bomErrors
End If

错误汇总逻辑BomExtractor.cls L471-481:

Public Function GetErrorSummary() As String
    If pErrorMessages.Count = 0 Then
        GetErrorSummary = ""
    Else
        Dim result As String
        Dim msg As Variant
        For Each msg In pErrorMessages
            result = result & CStr(msg) & "; "  ' 使用"; " 连接
        Next msg
        GetErrorSummary = result
    End If
End Function

来源 3: 多匹配错误

位置: BomExtractor.cls 第 247-258 行
触发条件: 同一类别匹配到多条物料
错误消息: 类别 [X] 匹配到多条物料 (N 条)

' BomExtractor.cls:247-258
ElseIf categoryMatches.Count = 1 Then
    ' 正常:匹配到 1 条
    pMatchedItems.Add categoryMatches(1)
Else
    ' 异常:匹配到多条
    Dim multiMsg As String
    multiMsg = "类别 [" & category & "] 匹配到多条物料 (" & categoryMatches.Count & "条)"
    pErrorMessages.Add multiMsg
    
    ' 临时处理:输出所有匹配的
    Dim tempItem As BomItem
    For Each tempItem In categoryMatches
        tempItem.MatchError = multiMsg  ' ← 设置到 item
        pMatchedItems.Add tempItem
    Next tempItem
End If

特性:

  • 错误同时添加到 pErrorMessages(进入 GetErrorSummary
  • 同时设置到 item.MatchError(逐行附加)
  • 输出所有匹配项,但每条都带警告

来源 4: 必需类别缺失

位置: BomExtractor.cls 第 449-451 行
触发条件: ValidateResult 检测到必需类别未匹配且无覆盖
错误消息: 必需类别 [X] 未匹配

' BomExtractor.cls:449-451
If Not isResolved Then
    pErrorMessages.Add "必需类别 [" & category & "] 未匹配"
End If

双向覆盖检查逻辑:

flowchart LR
    A[必需类别 X 缺失] --> B{检查 1: 有父类?}
    B -->|是 | C{父类别已匹配?}
    C -->|是 | D[被父类覆盖<br/>不报错]
    C -->|否 | E[检查 2]
    B -->|否 | E
    
    E --> F{检查 2: 有子类?}
    F -->|是 | G{所有子类都匹配?}
    G -->|是 | H[被子类覆盖<br/>不报错]
    G -->|否 | I[确实缺失<br/>报错]
    F -->|否 | I
    
    D --> J[Continue]
    H --> J
    I --> K[添加到 pErrorMessages]
    
    style D fill:#51cf66
    style H fill:#51cf66
    style K fill:#ff6b6b

覆盖场景示例:

场景 父类别 子类别 1 子类别 2 结果
总成优先 部件 (1 条) 接头 (2 条) 弹性元件 (1 条) 输出"部件",子类不报错
散件满足 部件 (缺失) 接头 (2 条) 弹性元件 (1 条) 输出子类,父类不报错
确实缺失 部件 (缺失) 接头 (缺失) 弹性元件 (1 条) 报错:"必需类别 [接头] 未匹配"

来源 5: 无匹配物料

位置: MainModule.bas 第 203-208 行
触发条件: matchedItems.Count = 0extractNote 为空
错误消息: 未匹配到任何物料

' MainModule.bas:203-208
If matchedItems.Count = 0 Then
    ' 没有匹配项
    If extractNote = "" Then
        extractNote = "未匹配到任何物料"
    End If
    outputData.Add CreateOutputRowArray(..., extractNote, Nothing)

注意: 如果已有其他错误(如解析错误),则不会覆盖。


来源 6: 物料级 MatchError

位置: MainModule.bas 第 215-223 行
触发条件: BomItem.MatchError 非空
错误来源: 由 BomExtractor.MatchItems() 设置(见来源 3

' MainModule.bas:215-223
For Each item In matchedItems
    Dim itemNote As String
    itemNote = extractNote
    
    ' 添加物料特定的错误
    If item.MatchError <> "" Then
        If itemNote <> "" Then itemNote = itemNote & "; "
        itemNote = itemNote & item.MatchError
    End If
    
    ' ... 添加到输出
Next item

特性:

  • 每条 BOM 物料单独输出时附加
  • 使用 "; " 分隔符拼接
  • 首行继承全局 extractNote,后续行只继承不含物料级错误

错误消息拼接规则

sequenceDiagram
    participant M as MainModule
    participant P as ProductModelParser
    participant E as BomExtractor
    participant I as BomItem
    
    M->>P: Parse modelString
    alt 解析失败
        P-->>M: 返回 ErrorMessage
        Note over M: extractNote = 解析失败 + ErrorMessage
        M->>M: 输出单行后结束
    else 解析成功
        M->>E: ExtractBom conditions
        Note over E: 收集错误到 pErrorMessages
        Note over E: 设置 item.MatchError
        E-->>M: GetErrorSummary
        
        alt bomErrors 非空
            Note over M: extractNote = bomErrors
        else bomErrors 为空
            Note over M: extractNote 保持空
        end
        
        alt matchedItems = 0
            Note over M: 设为 未匹配到任何物料
            M->>M: 输出单行后结束
        else matchedItems > 0
            loop For Each item
                M->>M: itemNote = extractNote
                alt item.MatchError 非空
                    Note over M: itemNote += MatchError
                end
                M->>M: CreateOutputRowArray
            end
        end
    end
    
    Note over M: 输出到提取备注列

拼接规则总结:

场景 拼接方式 示例
全局错误汇总 分号连接 错误 1; 错误 2
物料级附加 检查非空后加分号 extractNote + MatchError
多类别缺失 逐个添加到集合后汇总 必需类别 A 未匹配; 必需类别 B 未匹配
解析失败 + 其他 解析失败时立即退出不叠加 解析失败:...

输出列定义

位置: MainModule.bas 第 270 行

' MainModule.bas:242-270
Private Sub WriteOutputHeader(ws As Worksheet)
    ' ... 前面的列 ...
    ws.Cells(1, col).Value = "66 代码": col = col + 1
    ws.Cells(1, col).Value = "提取备注": col = col + 1  ' ← 最后一列
End Sub

数据写入: CreateOutputRowArray() 函数的最后一个元素

' MainModule.bas:283-339
Private Function CreateOutputRowArray(..., note As String, ...) As Variant()
    ' ... 填充前面的列 ...
    
    ' 备注(最后一列)
    rowData(col) = note
    
    CreateOutputRowArray = rowData
End Function

完整错误消息类型汇总表

错误类型 错误消息模板 触发条件 源码位置 是否可叠加
解析错误 解析失败:[具体原因] Parse() 失败 MainModule.bas:186 单独输出
多匹配 类别 [X] 匹配到多条物料 (N 条) 同类别匹配>1 BomExtractor.cls:250 可叠加
必需类别缺失 必需类别 [X] 未匹配 ValidateResult 检测缺失 BomExtractor.cls:450 可叠加
无匹配 未匹配到任何物料 matchedItems.Count = 0 MainModule.bas:207 仅当无其他错误
物料级多匹配 类别 [X] 匹配到多条物料 (N 条) item.MatchError MainModule.bas:221 逐行附加

典型输出示例

示例 1: 解析失败

产品型号Y-100-M203.316SS
提取备注:解析失败:表头结构不完整:缺少必要字段

示例 2: 正常匹配(无错误)

产品型号Y-100-M203.316SS.L100.N2
提取备注:(空)

示例 3: 多匹配错误

产品型号Y-100-M203.316SS.L100.N2
提取备注:类别 [接液材质] 匹配到多条物料 (3 条); 类别 [量程范围] 匹配到多条物料 (2 条);

示例 4: 必需类别缺失

产品型号Y-100-M203.316SS.L100.N2
提取备注:必需类别 [安装形式] 未匹配; 必需类别 [表壳形式] 未匹配;

示例 5: 无匹配

产品型号INVALID-MODEL
提取备注:未匹配到任何物料

示例 6: 物料级错误附加

产品型号Y-100-M203.316SS.L100.N2
行号 | 类别 | 提取备注
-----|------|----------
1    | 接头 | 类别 [接液材质] 匹配到多条物料 (3 条); 类别 [接液材质] 匹配到多条物料 (3 条);
2    | 弹性元件 | 类别 [接液材质] 匹配到多条物料 (3 条);

关键代码路径索引

功能 文件 行号范围
主入口 MainModule.bas 20-150
单型号处理 MainModule.bas 161-235
输出表头定义 MainModule.bas 242-271
行数据创建 MainModule.bas 283-339
型号解析 ProductModelParser.cls 60-91
BOM 提取 BomExtractor.cls 130-152
匹配物料 BomExtractor.cls 208-261
总成逻辑 BomExtractor.cls 270-367
结果验证 BomExtractor.cls 376-455
错误汇总 BomExtractor.cls 471-482
物料数据模型 BomItem.cls 1-89

设计特点

优点:

  1. 错误信息分层清晰(解析层、匹配层、验证层)
  2. 支持多错误叠加,不丢失任何警告
  3. 双向覆盖检查避免误报(总成/散件场景)
  4. 物料级错误逐行附加,便于定位问题

⚠️ 注意事项:

  1. 解析失败时立即退出,不执行后续 BOM 提取
  2. 多匹配错误会输出所有匹配项(数据不确定时保留全部)
  3. 错误消息使用 "; " 分隔,末尾可能有多余分隔符
  4. "未匹配到任何物料"仅在无其他错误时显示

文档结束