' ============================================================ ' Module Name: Master_Kukan ' Module Desc: M1 Kukan master data management (import/export/validate) ' Module Methods: ' - CreateEnumDropdown ' - Worksheet_Change ' - Validate ' ============================================================ Private Sub Worksheet_Change(ByVal Target As Range) Dim HasHeaderEdit As Boolean: HasHeaderEdit = CheckHeaderEdit(Me, Target) If HasHeaderEdit = True Then Exit Sub ' === Column C changes: Create L column dropdown === If Target.Column = 3 And Target.Row >= 7 Then Dim cell As Range For Each cell In Target If Trim(cell.Value) = "" Then Me.Cells(cell.Row, 12).Validation.Delete Call ClearDataRow(Me, START_COL + 1, END_COL, cell.Row, ERROR_COL) Else Call BuildTokubetuDropdown(Me, "L", cell.Row) Call BuildRenrakuDropdown(Me, "K", cell.Row) End If Next End If ' === Column D changes: Fill E column === If Target.Column = 4 And Target.Row >= 7 Then Dim z1Cache As Object: Set z1Cache = GetCache("Z1") Dim cellD As Range For Each cellD In Target Dim dVal As String: dVal = Trim(cellD.Value) If dVal = "" Then Me.Cells(cellD.Row, 5).ClearContents Else If Not z1Cache Is Nothing And z1Cache.Exists(dVal) Then Dim valsD As Variant: valsD = z1Cache(dVal) Me.Cells(cellD.Row, 5).Value = valsD(0) Else Me.Cells(cellD.Row, 5).ClearContents End If End If Next End If End Sub Private Sub Validate(ws As Worksheet, ByVal rowNum As Long, ByVal lastDataRow As Long) On Error GoTo ErrHandler Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig() Dim sheetConf As Object: Set sheetConf = sheetConfDict(ws.CodeName) Dim startCol As String: startCol = sheetConf("StartCol") Dim endCol As String: endCol = sheetConf("EndCol") Dim errorCol As String: errorCol = sheetConf("ErrorCol") Dim clearRange As Range: Set clearRange = ws.Range(ws.Cells(rowNum, startCol), ws.Cells(rowNum, endCol)) clearRange.Interior.Color = vbWhite ' Check column required Dim colLetter As Variant For Each colLetter In Array("C", "D", "E", "F", "G", "I", "L") If Trim(ws.Range(colLetter & rowNum).Value) = "" Then ws.Cells(rowNum, errorCol).Value = GetErrorMsg("E002", colLetter & rowNum) ws.Range(colLetter & rowNum).Interior.Color = RGB(255, 0, 0) Exit Sub End If Next colLetter ' Check column numeric For Each colLetter In Array("H", "I", "J", "N") Dim val As String: val = Trim(ws.Range(colLetter & rowNum).Value) If val <> "" And Not IsNumeric(val) Then ws.Cells(rowNum, errorCol).Value = GetErrorMsg("E011", colLetter & rowNum) ws.Range(colLetter & rowNum).Interior.Color = RGB(255, 0, 0) Exit Sub End If Next colLetter ' Check C column repeat Dim cValue As String: cValue = Trim(ws.Range("C" & rowNum).Value) Dim foundCell As Range Set foundCell = ws.Range("C7:C" & lastDataRow).Find(What:=cValue, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext) If Not foundCell Is Nothing Then If foundCell.Row <> rowNum Then ws.Cells(rowNum, errorCol).Value = "C column value is duplicated" ws.Range("C" & rowNum).Interior.Color = RGB(255, 0, 0) Exit Sub End If End If ' Check D and E column in the cache Dim z1Cache As Object: Set z1Cache = GetCache("Z1") Dim dValue As String: dValue = Trim(ws.Range("D" & rowNum).Value) Dim eValue As String: eValue = Trim(ws.Range("E" & rowNum).Value) If Not z1Cache.Exists(dValue) Then ws.Cells(rowNum, errorCol).Value = GetErrorMsg("E004", "D" & rowNum) ws.Range("D" & rowNum).Interior.Color = RGB(255, 0, 0) Exit Sub Else Dim valueArray As Variant valueArray = z1Cache(dValue) If Not IsArray(valueArray) Or UBound(valueArray) < 0 Then ws.Cells(rowNum, errorCol).Value = "Invalid reference data for D column." Exit Sub End If Dim expectedEValue As String expectedEValue = Trim(CStr(valueArray(0))) If eValue <> expectedEValue Then ws.Cells(rowNum, errorCol).Value = "E column does not match reference data." ws.Range("E" & rowNum).Interior.Color = RGB(255, 0, 0) Exit Sub End If End If ' Check L column in the tokubetuList Dim tokubetuList As Object: Set tokubetuList = GetCache("tokubetuList") Dim lValue As String: lValue = Trim(ws.Range("L" & rowNum).Value) If Not tokubetuList.Exists(lValue) Then ws.Cells(rowNum, errorCol).Value = "L column does not exist." ws.Range("L" & rowNum).Interior.Color = RGB(255, 0, 0) Exit Sub End If ' Validation passed - clear error ws.Cells(rowNum, errorCol).ClearContents Exit Sub ErrHandler: lastErrorMsg = Err.Description End Sub ' obtain z1 master data, and update column E Private Sub Refresh(ws As Worksheet, ByVal startRow As Long, ByVal lastDataRow As Long) Dim z1Cache As Object: Set z1Cache = GetCache("Z1") Application.EnableEvents = False On Error GoTo ErrorHandler Dim r As Long For r = startRow To lastDataRow Dim dVal As String: dVal = Trim(ws.Cells(r, 4).Value) ' Column D If dVal <> "" And z1Cache.Exists(dVal) Then Dim valsD As Variant: valsD = z1Cache(dVal) ws.Cells(r, 5).Value = valsD(0) ' Column E End If Next r Exit Sub ErrorHandler: Application.EnableEvents = True Err.Raise ERR_CACHE_NOT_FOUND, "M1.Refresh", "Failed to refresh M1: " & Err.Description End Sub Private Sub ValidateWarn(ws As Worksheet, ByVal lastDataRow As Long) On Error GoTo ErrorHandler Dim exitMsg As String ' Get M2 sheet kukan code list directly Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig() Dim m2SheetConf As Object: Set m2SheetConf = sheetConfDict("M2") Dim m2StartRow As Long: m2StartRow = m2SheetConf("StartRow") Dim wsM2 As Worksheet: Set wsM2 = ThisWorkbook.Worksheets("M2") Dim lastRowM2 As Long: lastRowM2 = GetLastDataRowInRange(wsM2) If lastRowM2 < m2StartRow Then exitMsg = "M2 sheet has no data" GoTo ErrorHandler End If ' Build kukan code list from M2 sheet Dim kukanList As Object: Set kukanList = CreateObject("Scripting.Dictionary") Dim r As Long For r = m2StartRow To lastRowM2 Dim kukanCode As String: kukanCode = Trim(wsM2.Cells(r, 3).Value) If kukanCode <> "" And Not kukanList.Exists(kukanCode) Then kukanList.Add kukanCode, True End If Next r Dim sheetConf As Object: Set sheetConf = sheetConfDict("M1") Dim startRow As Long: startRow = sheetConf("StartRow") Dim errorCol As String: errorCol = sheetConf("ErrorCol") ' Check all rows in M1 sheet If lastDataRow < startRow Then exitMsg = "M1 sheet has no data" GoTo ErrorHandler End If Dim rowNum As Long For rowNum = startRow To lastDataRow Dim cValue As String: cValue = Trim(ws.Range("C" & rowNum).Value) If Not kukanList.Exists(cValue) Then ws.Cells(rowNum, errorCol).Value = GetErrorMsg("W001", cValue) ws.Range("C" & rowNum).Interior.Color = RGB(255, 128, 0) End If NextRow: Next rowNum Exit Sub ErrorHandler: If exitMsg <> "" Then MsgBox "ValidateWarn: " & exitMsg, vbExclamation Else MsgBox "ValidateWarn: " & Err.Description, vbExclamation End If End Sub