diff --git a/VBA_BOMConverter/Modules/M09_BOMExtractor.bas b/VBA_BOMConverter/Modules/M09_BOMExtractor.bas index 2176fb3..c7a2c8e 100644 --- a/VBA_BOMConverter/Modules/M09_BOMExtractor.bas +++ b/VBA_BOMConverter/Modules/M09_BOMExtractor.bas @@ -492,26 +492,32 @@ Private Function MatchAllMaterialTypesWithValidation( _ matchResult("rowCount") = bomMatchResult("rowCount") Set matchResult("rowNums") = bomMatchResult("rowNums") - ' 如果匹配成功,提取物料信息 - If bomMatchResult("success") Then - Dim rowNum As Long - rowNum = bomMatchResult("rowNums")(1) - Debug.Print " -> 匹配行号: " & rowNum - + ' 提取物料信息(支持多条匹配) + If bomMatchResult("rowCount") > 0 Then + ' 步骤1: 构建表头映射(只需构建一次) Dim headerMap As Object Set headerMap = M07_BOMMatcher.BuildWorksheetHeaderMap(ws) - Dim materialInfo As Object - Set materialInfo = M07_BOMMatcher.ExtractMaterialInfo(ws, rowNum, headerMap) + ' 步骤2: 遍历所有匹配行 + Dim i As Long + Dim rowNum As Long + For i = 1 To bomMatchResult("rowCount") + rowNum = bomMatchResult("rowNums")(i) + Debug.Print " -> 处理匹配行 " & i & "/" & bomMatchResult("rowCount") & ": 行号=" & rowNum - Debug.Print " -> 提取结果: 名称=[" & materialInfo("materialName") & "] 编码=[" & materialInfo("materialCode") & "] 数量=[" & materialInfo("materialQty") & "]" + ' 步骤3: 提取物料信息 + Dim materialInfo As Object + Set materialInfo = M07_BOMMatcher.ExtractMaterialInfo(ws, rowNum, headerMap) - If Not materialInfo Is Nothing Then - matchResult("materials").Add materialInfo - Debug.Print " -> 已添加到匹配结果" - Else - Debug.Print " -> ERROR: materialInfo为Nothing" - End If + If Not materialInfo Is Nothing Then + matchResult("materials").Add materialInfo + Debug.Print " 已添加: 名称=[" & materialInfo("materialName") & "] 编码=[" & materialInfo("materialCode") & "]" + Else + Debug.Print " ERROR: materialInfo为Nothing" + End If + Next i + + Debug.Print " -> 共添加 " & matchResult("materials").Count & " 个物料" End If End If diff --git a/docs/Multiple_Match_Materials_Fix.md b/docs/Multiple_Match_Materials_Fix.md new file mode 100644 index 0000000..14dec9c --- /dev/null +++ b/docs/Multiple_Match_Materials_Fix.md @@ -0,0 +1,161 @@ +# Fix: Multiple Match Materials Now Appear in BOM Output + +## Problem + +When a product model matched **multiple materials of the same type** (e.g., 2 records in "机芯" sheet), those materials **did NOT appear** in the [BOM提取结果] worksheet. Only an error appeared in the error report. + +**Expected**: All matched materials should appear with error message in "提取备注" column. +**Actual**: Materials were completely missing from output. + +## Root Cause + +**File**: `VBA_BOMConverter/Modules/M09_BOMExtractor.bas` +**Function**: `MatchAllMaterialTypesWithValidation()` +**Lines**: 496-515 (before fix) + +### Bug Description + +The original code only extracted materials when `bomMatchResult("success") = True`: + +```vba +' OLD BUGGY CODE +If bomMatchResult("success") Then + rowNum = bomMatchResult("rowNums")(1) ' Only first match + Set materialInfo = M07_BOMMatcher.ExtractMaterialInfo(ws, rowNum, headerMap) + matchResult("materials").Add materialInfo ' Only one material +End If +``` + +**Problem Flow**: +1. M07_BOMMatcher finds 2 matching rows → Returns `success=False, rowCount=2, rowNums={row5, row8}` +2. Line 496 checks `If bomMatchResult("success")` → **FALSE** (because rowCount > 1) +3. Lines 497-514 **SKIPPED** → No materials extracted +4. `matchResult("materials")` remains **EMPTY** +5. Phase 3 tries to collect materials but finds empty collection +6. **Result**: No materials in output, only error in error report + +## Solution + +Changed the condition from checking `success` to checking `rowCount > 0`, and added a loop to process **all matching rows**. + +### Code Changes + +**File**: `VBA_BOMConverter/Modules/M09_BOMExtractor.bas` +**Lines**: 495-521 + +```vba +' NEW FIXED CODE +' 提取物料信息(支持多条匹配) +If bomMatchResult("rowCount") > 0 Then + ' 步骤1: 构建表头映射(只需构建一次) + Dim headerMap As Object + Set headerMap = M07_BOMMatcher.BuildWorksheetHeaderMap(ws) + + ' 步骤2: 遍历所有匹配行 + Dim i As Long + Dim rowNum As Long + For i = 1 To bomMatchResult("rowCount") + rowNum = bomMatchResult("rowNums")(i) + Debug.Print " -> 处理匹配行 " & i & "/" & bomMatchResult("rowCount") & ": 行号=" & rowNum + + ' 步骤3: 提取物料信息 + Dim materialInfo As Object + Set materialInfo = M07_BOMMatcher.ExtractMaterialInfo(ws, rowNum, headerMap) + + If Not materialInfo Is Nothing Then + matchResult("materials").Add materialInfo + Debug.Print " 已添加: 名称=[" & materialInfo("materialName") & "] 编码=[" & materialInfo("materialCode") & "]" + Else + Debug.Print " ERROR: materialInfo为Nothing" + End If + Next i + + Debug.Print " -> 共添加 " & matchResult("materials").Count & " 个物料" +End If +``` + +### Key Improvements + +1. **Changed condition**: `If bomMatchResult("success")` → `If bomMatchResult("rowCount") > 0` + - Now processes materials even when there are multiple matches (success=False) + +2. **Added loop**: `For i = 1 To bomMatchResult("rowCount")` + - Processes ALL matching rows instead of just the first one + +3. **Optimized performance**: Moved `BuildWorksheetHeaderMap()` outside the loop + - Build header map once, reuse for all rows in the same worksheet + +4. **Enhanced logging**: Added detailed debug prints + - Shows which row is being processed + - Shows total count of materials added + +## Test Cases + +### 1. Single Match Scenario (Current Working Case) +- **Input**: Product matches exactly 1 record in "机芯" sheet +- **Expected**: 1 material row appears in output with no error message +- **Status**: ✅ Should still work (rowCount=1, loop runs once) + +### 2. Multiple Match Scenario (Fixed Bug) +- **Input**: Product matches 2 records in "机芯" sheet +- **Expected**: + - 2 material rows appear in [BOM提取结果] + - Both show "机芯 匹配到2条记录" in 提取备注 column + - Error report also logs the error +- **Status**: ✅ Now fixed (loop runs twice) + +### 3. No Match Scenario +- **Input**: Product matches 0 records in "机芯" sheet +- **Expected**: Error message in error report, no materials for that type +- **Status**: ✅ Should still work (rowCount=0, loop doesn't run) + +### 4. Component Sheet Scenario +- **Input**: Product matches component sheet (uses different code path) +- **Expected**: No regression, component handling still works correctly +- **Status**: ✅ Not affected (uses lines 452-484, different code path) + +## Impact Analysis + +### Affected Components: +- ✅ **"机芯" (Movement)** - Primary fix target +- ✅ **"边" (Edge)** - Will also benefit from fix +- ✅ **Any other non-special sheets** - All use this code path + +### Not Affected: +- ✅ **"部件" (Component)** - Uses separate code path (lines 452-484) +- ✅ **"接头" (Joint) / "弹性元件" (Element)** from component sheet + +### Risk Assessment: **LOW** +- Change is isolated to one specific code block +- Only affects material collection logic when rowCount > 0 +- Component sheet (complex logic) uses different code path +- Single-match case (rowCount = 1) still works the same way +- No change to validation logic or error reporting + +## Benefits + +1. **Visibility**: Users can now see ALL matched materials when ambiguity occurs +2. **Debugging**: Easier to identify why multiple matches occurred +3. **Manual Resolution**: Users can manually select correct material from output +4. **Data Quality**: Highlights ambiguous BOM library entries that need cleanup + +## Verification Steps + +1. Open YTHN-100.xlsm workbook +2. Ensure BOM库.xlsx exists with test data (create 2 records in "机芯" sheet with same matching criteria) +3. Run `M09_BOMExtractor.RunBOMExtraction()` +4. Check [BOM提取结果] worksheet: + - ✅ Both matched materials should appear + - ✅ "提取备注" column should show "机芯 匹配到2条记录" on both rows + - ✅ Error report should also log the error +5. Verify single-match sheets still work correctly + +## Related Files + +- **Modified**: `VBA_BOMConverter/Modules/M09_BOMExtractor.bas` (lines 495-521) +- **Related**: `VBA_BOMConverter/Modules/M07_BOMMatcher.bas` (no changes needed) +- **Related**: `VBA_BOMConverter/Modules/M08_ComponentProcessor.bas` (no changes needed) + +## Date + +**Implemented**: 2025-02-26