Marui_Work_VBA/vba_modules.md

1008 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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