# VBA 模組原始碼 # 來源:全機型_日報表.xlsm # 提取工具:olevba 0.60.2 # 提取時間:2026-04-07 --- ## Module19.bas - NT() ```vba Function NT(Number As Integer) As String NT = Split(Cells(1, Number).Address, "$")(1) End Function ``` --- ## Module7.bas - ra() ```vba Function ra(inputText As String) As String Dim regEx As Object Dim matches As Object Set regEx = CreateObject("VBScript.RegExp") With regEx .pattern = "[A-Z0-9-]{6,25}" .Global = True End With Set matches = regEx.Execute(inputText) If matches.Count > 0 Then ra = matches(0).Value Else ra = "NO" End If End Function ``` --- ## Module5.bas - A() ```vba Sub A() Call B Call Q End Sub ``` --- ## Module6.bas - B() ```vba Sub B() Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Application.EnableEvents = False Dim wsFocest As Worksheet, wsBOM As Worksheet, wsOutput As Worksheet, wsUnmatched As Worksheet Dim lastRowF As Long, lastRowB As Long, lastRowO As Long, lastRowU As Long Dim i As Long, j As Long, k As Long, col As Long Dim keyPart As String, material As String, usage As Double Dim lic As Double, focestCol1 As String, focestCol2 As String Dim weekValues(1 To 56) As Double Dim dictBOM As Object, dictUnmatched As Object Dim materialData As Variant Dim key As Variant Set dictBOM = CreateObject("Scripting.Dictionary") Set dictUnmatched = CreateObject("Scripting.Dictionary") ' Set worksheets Set wsFocest = ThisWorkbook.Sheets("FCST") Set wsBOM = ThisWorkbook.Sheets("BOM") ' Create new worksheets for output On Error Resume Next Application.DisplayAlerts = False ThisWorkbook.Sheets("Output").Delete ThisWorkbook.Sheets("Unmatched").Delete Application.DisplayAlerts = True On Error GoTo 0 Set wsOutput = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)) wsOutput.Name = "Output" Set wsUnmatched = ThisWorkbook.Sheets.Add(After:=wsOutput) wsUnmatched.Name = "Unmatched" ' Phase 1: Read BOM data into dictionary lastRowB = wsBOM.Cells(wsBOM.Rows.Count, "A").End(xlUp).Row Dim bomData As Variant bomData = wsBOM.Range("A2:C" & lastRowB).Value For i = 1 To UBound(bomData, 1) keyPart = Trim(bomData(i, 1) & "") material = Trim(bomData(i, 2) & "") ' Safe handling of usage value If IsNumeric(bomData(i, 3)) Then usage = CDbl(bomData(i, 3)) Else usage = 0 End If If keyPart <> "" And material <> "" Then If Not dictBOM.exists(keyPart) Then dictBOM.Add keyPart, New Collection End If dictBOM(keyPart).Add Array(material, usage) End If Next i ' Phase 2: Process Focest data - only process rows with BOM matches lastRowF = wsFocest.Cells(wsFocest.Rows.Count, "A").End(xlUp).Row Dim focestData As Variant focestData = wsFocest.Range("A2:BJ" & lastRowF).Value ' Columns A to BJ (A, B + 56 weeks) ' Pre-calculate output data size Dim outputRowCount As Long outputRowCount = 0 For i = 1 To UBound(focestData, 1) keyPart = Trim(focestData(i, 1) & "") If keyPart <> "" And dictBOM.exists(keyPart) Then outputRowCount = outputRowCount + dictBOM(keyPart).Count End If Next i ' Prepare output array Dim outputData() As Variant ReDim outputData(1 To outputRowCount, 1 To 60) ' 4 fixed columns + 56 week columns lastRowO = 0 For i = 1 To UBound(focestData, 1) keyPart = Trim(focestData(i, 1) & "") If keyPart = "" Then GoTo NextFocestRow ' Only process rows with BOM matches If dictBOM.exists(keyPart) Then focestCol1 = focestData(i, 1) & "" focestCol2 = focestData(i, 2) & "" ' Safe handling of LIC value If IsNumeric(focestData(i, 2)) Then lic = CDbl(focestData(i, 2)) Else lic = 0 End If ' Extract week values with error handling For j = 1 To 56 If IsNumeric(focestData(i, j + 2)) Then weekValues(j) = CDbl(focestData(i, j + 2)) Else weekValues(j) = 0 End If Next j ' Process matching BOM items For k = 1 To dictBOM(keyPart).Count materialData = dictBOM(keyPart)(k) material = materialData(0) usage = materialData(1) lastRowO = lastRowO + 1 outputData(lastRowO, 1) = focestCol1 outputData(lastRowO, 2) = focestCol2 outputData(lastRowO, 3) = material outputData(lastRowO, 4) = usage For col = 1 To 56 outputData(lastRowO, col + 4) = weekValues(col) * lic * usage Next col Next k End If NextFocestRow: Next i ' Phase 3: Separately process Focest rows without BOM matches For i = 1 To UBound(focestData, 1) keyPart = Trim(focestData(i, 1) & "") If keyPart <> "" And Not dictBOM.exists(keyPart) Then If Not dictUnmatched.exists(keyPart) Then dictUnmatched.Add keyPart, True End If End If Next i ' Batch write output data If outputRowCount > 0 Then wsOutput.Range("A2").Resize(outputRowCount, 60).Value = outputData End If ' Generate unmatched sheet wsUnmatched.Cells(1, 1).Value = "Unmatched Key Part Numbers" If dictUnmatched.Count > 0 Then Dim unmatchedData() As Variant ReDim unmatchedData(1 To dictUnmatched.Count, 1 To 1) i = 0 For Each key In dictUnmatched.Keys i = i + 1 unmatchedData(i, 1) = key Next key wsUnmatched.Range("A2").Resize(dictUnmatched.Count, 1).Value = unmatchedData End If ' Set headers wsOutput.Cells(1, 1).Value = "Focest Col1" wsOutput.Cells(1, 2).Value = "Focest Col2" wsOutput.Cells(1, 3).Value = "Material Number" wsOutput.Cells(1, 4).Value = "BOM Usage" For col = 1 To 56 wsOutput.Cells(1, col + 4).Value = "Week" & col Next col ' Auto-fit columns wsOutput.Columns.AutoFit wsUnmatched.Columns.AutoFit Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True MsgBox "Processing completed! " & outputRowCount & " rows generated in Output sheet. " & _ dictUnmatched.Count & " unmatched items found." End Sub ``` --- ## Module3.bas - Q() ```vba Sub Q() ' Define variables Dim wsSource As Worksheet, wsDest As Worksheet Dim pvtCache As PivotCache Dim pvtTable As PivotTable Dim lastRow As Long Dim SourceDataRange As Range Dim i As Long Dim fieldName As String Dim startTime As Double Dim dataField As PivotField ' Start timing execution startTime = Timer ' Disable Excel features for performance optimization OptimizeVBA True On Error GoTo ErrorHandler ' Check if source worksheet exists If Not WorksheetExists("Output") Then MsgBox "Source worksheet 'Output' not found!", vbCritical GoTo CleanUp End If ' Set reference to source worksheet Set wsSource = ThisWorkbook.Worksheets("Output") ' Delete destination worksheet if it already exists If WorksheetExists("Cutout") Then Application.DisplayAlerts = False ThisWorkbook.Worksheets("Cutout").Delete Application.DisplayAlerts = True End If ' Remove any existing pivot table with the same name RemovePivotTable "WeeklySummaryPivot" ' Create new worksheet for the pivot table Set wsDest = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)) wsDest.Name = "Cutout" ' Find the last row with data in source worksheet - MORE ROBUST METHOD lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row If lastRow = 1 And wsSource.Cells(1, 1).Value = "" Then lastRow = 0 ' Verify there is sufficient data If lastRow < 2 Then MsgBox "Insufficient data in source worksheet!", vbExclamation GoTo CleanUp End If ' Define source data range Set SourceDataRange = wsSource.Range("A1:BH" & lastRow) ' Create pivot cache from source data Set pvtCache = ThisWorkbook.PivotCaches.Create( _ SourceType:=xlDatabase, _ SourceData:=SourceDataRange.Address(ReferenceStyle:=xlR1C1, External:=True)) Set pvtTable = pvtCache.CreatePivotTable( _ TableDestination:=wsDest.Range("A3"), _ tableName:="WeeklySummaryPivot") With pvtTable .ManualUpdate = True .RowAxisLayout xlTabularRow ' Add row field - Material Number (Column C) .PivotFields(wsSource.Cells(1, 3).Value).Orientation = xlRowField ' Add data fields (columns E to BH) - WITH PERFORMANCE CHECK For i = 5 To 60 fieldName = wsSource.Cells(1, i).Value ' Only add field if it has a name and is likely numeric (avoid text fields for sum) If fieldName <> "" Then On Error Resume Next Set dataField = .PivotFields(fieldName) If Err.Number = 0 Then With dataField .Orientation = xlDataField .Function = xlSum .NumberFormat = "#,##0" ' Only rename if not already renamed If InStr(1, .Caption, "Sum of", vbTextCompare) = 0 Then .Caption = "Sum of " & fieldName End If End With Else Err.Clear End If On Error GoTo ErrorHandler End If Next i ' Apply formatting .ShowTableStyleRowStripes = True On Error Resume Next .TableStyle2 = "PivotStyleMedium9" If Err.Number <> 0 Then .TableStyle1 = "PivotStyleMedium9" Err.Clear End If On Error GoTo ErrorHandler .ManualUpdate = False End With ' Add title and timestamp With wsDest .Range("A1").Value = "Weekly Summary Report" .Range("A1").Font.Bold = True .Range("A1").Font.Size = 14 .Range("A2").Value = "Generated: " & Now() .Range("A2").Font.Italic = True End With ' Auto-fit columns carefully for large datasets Application.ScreenUpdating = False wsDest.UsedRange.Columns.AutoFit Application.ScreenUpdating = True ' Success message MsgBox "Pivot table created successfully in " & Format(Timer - startTime, "0.00") & _ " seconds! Location: Worksheet " & wsDest.Name, vbInformation CleanUp: OptimizeVBA False Set pvtTable = Nothing Set pvtCache = Nothing Set SourceDataRange = Nothing Set wsSource = Nothing Set wsDest = Nothing Exit Sub ErrorHandler: MsgBox "Error " & Err.Number & ": " & Err.Description & vbCrLf & _ "Please ensure your data in 'Output' sheet is correctly formatted.", vbCritical Resume CleanUp End Sub ' Helper function: Optimize VBA performance Sub OptimizeVBA(Optimize As Boolean) With Application If Optimize Then .ScreenUpdating = False .Calculation = xlCalculationManual .DisplayAlerts = False .EnableEvents = False .StatusBar = "Processing... Please wait" Else .ScreenUpdating = True .Calculation = xlCalculationAutomatic .DisplayAlerts = True .EnableEvents = True .StatusBar = False End If End With End Sub ' Helper function: Check if worksheet exists Function WorksheetExists(sheetName As String) As Boolean On Error Resume Next WorksheetExists = Not ThisWorkbook.Sheets(sheetName) Is Nothing On Error GoTo 0 End Function ' Helper function: Remove pivot table by name (FIXED For Each issue) Sub RemovePivotTable(tableName As String) Dim ws As Worksheet Dim pt As PivotTable On Error Resume Next For Each ws In ThisWorkbook.Worksheets ' CRITICAL FIX: Check if the worksheet has any pivot tables before trying to access one by name If ws.PivotTables.Count > 0 Then Set pt = ws.PivotTables(tableName) If Not pt Is Nothing Then pt.TableRange2.Clear Exit For End If End If Next ws On Error GoTo 0 End Sub ``` --- ## Module20.bas - W() ```vba Sub W() ' ========================================================================= ' USER CONFIGURATION AREA - Modify parameters below ' ========================================================================= ' Data source settings Const SOURCE_SHEET As String = "KCB" ' Source worksheet name Const PIVOT_SHEET_NAME As String = "MaterialSummary" ' Output pivot table sheet name Const HEADER_ROW As Long = 1 ' Header row number ' Custom column settings Dim CUSTOM_COLUMNS As Variant CUSTOM_COLUMNS = Array("B", "C", "D", "E", "F", "G", "H", "I", "J") ' Columns to include ' Pivot table field settings Const ROW_FIELD_COLUMN As String = "B" ' Row field (row labels) column Dim DATA_FIELDS As Variant DATA_FIELDS = Array("C", "D", "E", "F", "G", "H") ' Data field columns to summarize ' Performance optimization settings Const USE_ARRAY_METHOD As Boolean = False ' Disable array method to avoid 1004 errors ' Output settings Const SHOW_PERFORMANCE_STATS As Boolean = True ' Show performance statistics Const AUTO_ADJUST_COLUMNS As Boolean = True ' Auto-adjust column widths ' ========================================================================= ' MAIN PROGRAM - Code below generally doesn't need modification ' ========================================================================= Dim startTime As Double If SHOW_PERFORMANCE_STATS Then startTime = Timer Dim wsData As Worksheet, wsPivot As Worksheet Dim rngData As Range Dim lastRow As Long, lastCol As Long ' Performance optimization settings Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Application.EnableEvents = False Application.StatusBar = "Preparing data..." On Error GoTo ErrorHandler ' Check if source sheet exists If Not WorksheetExists(SOURCE_SHEET) Then MsgBox "Source worksheet '" & SOURCE_SHEET & "' not found!", vbExclamation GoTo CleanUp End If ' Set source worksheet Set wsData = ThisWorkbook.Worksheets(SOURCE_SHEET) ' Get data range With wsData lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row lastCol = .Cells(HEADER_ROW, .Columns.Count).End(xlToLeft).Column If lastRow <= HEADER_ROW Then MsgBox "No data found in worksheet!", vbExclamation GoTo CleanUp End If Application.StatusBar = "Reading data (" & lastRow & " rows)..." ' Build data range Set rngData = BuildSafeRange(wsData, HEADER_ROW, lastRow, CUSTOM_COLUMNS) If rngData Is Nothing Then MsgBox "Failed to create data range. Please check column references.", vbExclamation GoTo CleanUp End If If rngData.Rows.Count <= 1 Then MsgBox "No data rows found after applying column filters.", vbExclamation GoTo CleanUp End If End With ' Delete existing worksheet Application.DisplayAlerts = False On Error Resume Next ThisWorkbook.Worksheets(PIVOT_SHEET_NAME).Delete On Error GoTo ErrorHandler Application.DisplayAlerts = True ' Create new worksheet Application.StatusBar = "Creating pivot table..." Set wsPivot = ThisWorkbook.Worksheets.Add wsPivot.Name = PIVOT_SHEET_NAME ' Create pivot table (now uses DATA_FIELDS setting) CreatePivotTableWithDataFields wsPivot, rngData, ROW_FIELD_COLUMN, DATA_FIELDS, wsData, HEADER_ROW ' Apply formatting Application.StatusBar = "Applying formatting..." With wsPivot .Range("A1").Value = "Material Summary" .Range("A1").Font.Bold = True .Range("A1").Font.Size = 14 If AUTO_ADJUST_COLUMNS Then .Columns.AutoFit End If .Range("A2").Value = "Created: " & Now() .Range("A2").Font.Italic = True .Range("A2").Font.Color = RGB(100, 100, 100) End With ' Show results Application.StatusBar = False If SHOW_PERFORMANCE_STATS Then Dim endTime As Double, elapsedTime As Double endTime = Timer elapsedTime = endTime - startTime MsgBox "Pivot table created successfully!" & vbCrLf & _ "Data rows: " & (lastRow - HEADER_ROW) & vbCrLf & _ "Columns included: " & (UBound(CUSTOM_COLUMNS) - LBound(CUSTOM_COLUMNS) + 1) & vbCrLf & _ "Data fields: " & Join(DATA_FIELDS, ", ") & vbCrLf & _ "Processing time: " & Format(elapsedTime, "0.00") & " seconds", vbInformation Else MsgBox "Pivot table created successfully!", vbInformation End If CleanUp: Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True Application.StatusBar = False Exit Sub ErrorHandler: MsgBox "Error " & Err.Number & ": " & Err.Description & vbCrLf & _ "Please check your configuration settings and data structure.", vbCritical GoTo CleanUp End Sub ' ========================================================================= ' Fixed pivot table creation function - Now correctly uses DATA_FIELDS setting ' ========================================================================= Sub CreatePivotTableWithDataFields(wsPivot As Worksheet, rngData As Range, rowFieldCol As String, dataFields As Variant, wsData As Worksheet, headerRow As Long) ' Purpose: Create pivot table using configured data fields On Error GoTo ErrorHandler Dim pc As PivotCache, pt As PivotTable Dim i As Long, fieldIndex As Long Dim rowFieldTitle As String, dataFieldTitle As String Dim colIndex As Long ' Validate data range If rngData Is Nothing Then MsgBox "Data range is empty. Cannot create pivot table.", vbExclamation Exit Sub End If If rngData.Rows.Count <= 1 Then MsgBox "Not enough data rows for pivot table.", vbExclamation Exit Sub End If ' Create pivot cache Set pc = ThisWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=rngData) ' Create pivot table Set pt = pc.CreatePivotTable(TableDestination:=wsPivot.Range("A3"), tableName:="CustomPivot") With pt ' Add row field (using configured row field column) colIndex = GetColumnIndex(rowFieldCol) If colIndex > 0 Then rowFieldTitle = wsData.Cells(headerRow, colIndex).Value .PivotFields(rowFieldTitle).Orientation = xlRowField Else ' If row field is invalid, use first column as default row field .PivotFields(1).Orientation = xlRowField End If ' Add data fields (using configured data fields) For i = LBound(dataFields) To UBound(dataFields) colIndex = GetColumnIndex(dataFields(i)) If colIndex > 0 Then dataFieldTitle = wsData.Cells(headerRow, colIndex).Value On Error Resume Next ' Skip fields that cannot be added .AddDataField .PivotFields(dataFieldTitle), "Sum of " & dataFieldTitle, xlSum On Error GoTo ErrorHandler End If Next i ' If no data fields were successfully added, add all numeric fields as fallback If .dataFields.Count = 0 Then MsgBox "Configured data fields are invalid. Adding all numeric fields.", vbExclamation For i = 2 To .PivotFields.Count On Error Resume Next .AddDataField .PivotFields(i), "Sum of " & .PivotFields(i).Name, xlSum On Error GoTo ErrorHandler Next i End If ' Apply style On Error Resume Next .TableStyle2 = "PivotStyleLight16" .RowAxisLayout xlTabularRow On Error GoTo ErrorHandler End With Exit Sub ErrorHandler: MsgBox "Error creating pivot table: " & Err.Description, vbExclamation End Sub ' ========================================================================= ' Helper functions ' ========================================================================= Function BuildSafeRange(ws As Worksheet, headerRow As Long, lastRow As Long, customCols As Variant) As Range ' Purpose: Safely build data range On Error GoTo ErrorHandler Dim firstCol As Long, lastCol As Long Dim colIndex As Long, i As Long ' Validate custom column references For i = LBound(customCols) To UBound(customCols) colIndex = GetColumnIndex(customCols(i)) If colIndex < 1 Or colIndex > ws.Columns.Count Then MsgBox "Invalid column reference: " & customCols(i), vbExclamation Set BuildSafeRange = Nothing Exit Function End If Next i firstCol = GetColumnIndex(customCols(LBound(customCols))) lastCol = GetColumnIndex(customCols(UBound(customCols))) If headerRow > lastRow Then MsgBox "Header row is after last data row!", vbExclamation Set BuildSafeRange = Nothing Exit Function End If Set BuildSafeRange = ws.Range(ws.Cells(headerRow, firstCol), ws.Cells(lastRow, lastCol)) If BuildSafeRange Is Nothing Then MsgBox "Failed to create data range.", vbExclamation Exit Function End If Exit Function ErrorHandler: MsgBox "Error in BuildSafeRange: " & Err.Description, vbExclamation Set BuildSafeRange = Nothing End Function Function GetColumnIndex(col As Variant) As Long ' Purpose: Convert column letter to column index On Error GoTo ErrorHandler If VarType(col) = vbString Then GetColumnIndex = Range(col & "1").Column Else GetColumnIndex = col End If Exit Function ErrorHandler: GetColumnIndex = 0 End Function Function WorksheetExists(sheetName As String) As Boolean ' Purpose: Check if worksheet exists On Error Resume Next WorksheetExists = Not ThisWorkbook.Worksheets(sheetName) Is Nothing On Error GoTo 0 End Function ' ========================================================================= ' Diagnostic tools ' ========================================================================= Sub CheckDataFields() ' Purpose: Check if data field configuration is correct Dim wsData As Worksheet Dim dataField As Variant Dim colIndex As Long Dim result As String Set wsData = ThisWorkbook.Worksheets("KCB") result = "Data Fields Check:" & vbCrLf & vbCrLf For Each dataField In Array("C", "E") ' Using configured DATA_FIELDS colIndex = GetColumnIndex(dataField) If colIndex > 0 Then result = result & "Column " & dataField & ": Valid" & vbCrLf & _ " Index: " & colIndex & vbCrLf & _ " Title: '" & wsData.Cells(1, colIndex).Value & "'" & vbCrLf & vbCrLf Else result = result & "Column " & dataField & ": Invalid" & vbCrLf & vbCrLf End If Next dataField MsgBox result, vbInformation, "Data Fields Check" End Sub ' ========================================================================= ' Simple version - Use if above code still has issues ' ========================================================================= Sub SimplePivotTable() ' Very simple version to avoid 1004 errors Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Application.EnableEvents = False On Error GoTo ErrorHandler Dim wsData As Worksheet, wsPivot As Worksheet Dim rngData As Range Dim lastRow As Long ' Configuration - modify as needed Const SOURCE_SHEET As String = "KCB" Const PIVOT_SHEET_NAME As String = "SimpleSummary" ' Check if source exists If Not WorksheetExists(SOURCE_SHEET) Then MsgBox "Worksheet '" & SOURCE_SHEET & "' not found!", vbExclamation GoTo CleanUp End If Set wsData = ThisWorkbook.Worksheets(SOURCE_SHEET) ' Find last row in column B (material column) lastRow = wsData.Cells(wsData.Rows.Count, "B").End(xlUp).Row If lastRow <= 1 Then MsgBox "No data found!", vbExclamation GoTo CleanUp End If ' Use simple range (columns B to I) Set rngData = wsData.Range("B1:I" & lastRow) ' Delete existing sheet Application.DisplayAlerts = False On Error Resume Next ThisWorkbook.Worksheets(PIVOT_SHEET_NAME).Delete On Error GoTo ErrorHandler Application.DisplayAlerts = True ' Create pivot table using simple method Set wsPivot = ThisWorkbook.Worksheets.Add wsPivot.Name = PIVOT_SHEET_NAME ' This method is less likely to cause 1004 errors wsPivot.Activate Set rngData = wsData.Range("B1:I" & lastRow) ' Use PivotTableWizard to create pivot table Set pt = wsPivot.PivotTableWizard(SourceType:=xlDatabase, _ SourceData:=rngData, _ TableDestination:=wsPivot.Range("A3")) ' Simple configuration With pt .PivotFields(wsData.Range("B1").Value).Orientation = xlRowField .PivotFields(wsData.Range("E1").Value).Orientation = xlDataField .PivotFields(wsData.Range("H1").Value).Orientation = xlDataField .PivotFields(wsData.Range("I1").Value).Orientation = xlDataField End With ' Simple formatting wsPivot.Range("A1").Value = "Simple Material Summary" wsPivot.Columns.AutoFit MsgBox "Simple pivot table created successfully!", vbInformation CleanUp: Application.ScreenUpdating = True Application.Calculation = xlCalculationAutomatic Application.EnableEvents = True Exit Sub ErrorHandler: MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical GoTo CleanUp End Sub Sub CheckDataRange() ' Purpose: Check data range to help diagnose issues Dim ws As Worksheet Dim rng As Range Dim lastRow As Long, lastCol As Long Set ws = ThisWorkbook.Worksheets("KCB") lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column MsgBox "Data Check:" & vbCrLf & _ "Last row: " & lastRow & vbCrLf & _ "Last column: " & lastCol & vbCrLf & _ "Header row data: " & ws.Range("A1").Value & "..." & ws.Cells(1, lastCol).Value, _ vbInformation, "Data Diagnostic" ' Show a sample of the data If lastRow > 1 Then Set rng = ws.Range("A1").Resize(2, lastCol) rng.Select End If End Sub ``` --- ## Module21.bas - MKey() ```vba Sub MKey() ' Declare variables Dim wsBOM As Worksheet Dim wsTarget As Worksheet Dim dict As Object Dim lastRowBOM As Long Dim lastRowTarget As Long Dim i As Long Dim primaryKey As String Dim model As String Dim modelKey As String Dim dataArray As Variant Dim resultArray() As String Dim modelArray() As String Dim j As Long Dim isDuplicate As Boolean Dim foundKeys As Object Dim originalColumnWidth As Double ' Save original column B width On Error Resume Next originalColumnWidth = Worksheets("0000").Columns("B").Width On Error GoTo 0 ' Turn off screen updating and calculation for speed Application.ScreenUpdating = False Application.Calculation = xlCalculationManual On Error GoTo ErrorHandler ' Set worksheets On Error Resume Next Set wsBOM = Worksheets("BOM_BUFFER") Set wsTarget = Worksheets("0000") On Error GoTo ErrorHandler If wsBOM Is Nothing Then MsgBox "Worksheet 'BOM' not found!", vbExclamation GoTo CleanUp End If If wsTarget Is Nothing Then MsgBox "Worksheet '0000' not found!", vbExclamation GoTo CleanUp End If ' Create dictionaries for faster lookup Set dict = CreateObject("Scripting.Dictionary") Set foundKeys = CreateObject("Scripting.Dictionary") ' Get data from BOM sheet (A=model, B=primary key) starting from row 3 lastRowBOM = wsBOM.Cells(wsBOM.Rows.Count, "A").End(xlUp).Row If lastRowBOM < 3 Then MsgBox "No data found in BOM sheet (data should start from row 3)!", vbExclamation GoTo CleanUp End If dataArray = wsBOM.Range("A3:B" & lastRowBOM).Value ' Build dictionary from BOM data (group models by primary key) For i = 1 To UBound(dataArray, 1) model = Trim(CStr(dataArray(i, 1))) ' Column A - model data primaryKey = Trim(CStr(dataArray(i, 2))) ' Column B - primary key ' Validate data If primaryKey <> "" And model <> "" Then ' MODIFIED: For models starting with "781" - keep first 9 characters If Left(model, 3) = "781" Then If Len(model) >= 9 Then modelKey = Left(model, 9) ' Keep first 9 characters for 781 starting models Else modelKey = model ' If less than 9 chars, keep original End If Else ' Extract first 7 characters for other models If Len(model) >= 7 Then modelKey = Left(model, 7) Else modelKey = model End If End If ' Process by primary key If dict.exists(primaryKey) Then ' Split existing models and check for duplicates modelArray = Split(dict(primaryKey), ",") isDuplicate = False ' Check if modelKey already exists for this primary key For j = 0 To UBound(modelArray) If Trim(modelArray(j)) = modelKey Then isDuplicate = True Exit For End If Next j ' Add only if not duplicate If Not isDuplicate Then dict(primaryKey) = dict(primaryKey) & "," & modelKey End If Else ' First entry for this primary key dict(primaryKey) = modelKey End If End If Next i ' Get target range from 0000 sheet (column A = primary keys) starting from row 3 lastRowTarget = wsTarget.Cells(wsTarget.Rows.Count, "A").End(xlUp).Row If lastRowTarget < 3 Then MsgBox "No primary keys found in 0000 sheet (data should start from row 3)!", vbExclamation GoTo CleanUp End If ' Prepare result array for column B starting from row 3 ReDim resultArray(1 To lastRowTarget - 2, 1 To 1) ' Match models to primary keys - using direct cell reference instead of range variable For i = 3 To lastRowTarget primaryKey = Trim(CStr(wsTarget.Cells(i, 1).Value)) If primaryKey <> "" Then If dict.exists(primaryKey) Then resultArray(i - 2, 1) = Replace(dict(primaryKey), ",", ", ") foundKeys(primaryKey) = True Else resultArray(i - 2, 1) = "Not Found" End If Else resultArray(i - 2, 1) = "" End If Next i ' Insert results into column B of 0000 sheet starting from row 3 wsTarget.Range("B3:B" & lastRowTarget).Value = resultArray ' Restore original column width instead of auto-fit wsTarget.Columns("B").Width = originalColumnWidth ' Show