Files
vba/src/sh/tuk/module/Common_Button.bas
2026-05-30 16:47:51 +09:00

422 lines
14 KiB
QBasic

Attribute VB_Name = "Common_Button"
Option Explicit
' --- Private Variables ---
Private m_LastErrorMsg As String
' ============================================================
' Get/Set last error message
' ============================================================
Public Sub SetLastErrorMsg(msg As String)
m_LastErrorMsg = msg
End Sub
Public Function GetLastErrorMsg() As String
GetLastErrorMsg = m_LastErrorMsg
End Function
Public Sub ClearLastErrorMsg()
m_LastErrorMsg = ""
End Sub
' ============================================================
' Module Name: Common_Button
' Module Desc: Common button handlers with centralized error handling
' Public Methods:
' - CSV_Import_Button (CSV import entry, binds to sheet button)
' - Validation_Button (validation entry, binds to sheet button)
' - CSV_Export_Button (CSV export entry, binds to sheet button)
' - Sort_Button (sort entry, binds to sheet button)
' - Filter_Button (filter entry, binds to sheet button)
' - Fit_Button (autofit column width, binds to sheet button)
' - RefreshCache_Button (refresh master cache)
' - RunValidationSilent (validate sheet, returns row count or -1)
' - HandleError (centralized error handler)
' Private Methods:
' - ValidateKukanCache
' - UpdateByMaster
' - Fit_Button
' ============================================================
Sub RefreshCache_Button()
On Error GoTo ErrorHandler
Dim activeSheetName As String: activeSheetName = ActiveSheet.CodeName
Debug.Print "1. Validate Z1~Z4, T1~T3, O1~O3 master data"
Dim cacheSheets As Variant: cacheSheets = Array(CACHE_Z1, CACHE_Z2, CACHE_Z3, CACHE_Z4, CACHE_T1, CACHE_T2, CACHE_T3, CACHE_O1, CACHE_O2, CACHE_O3)
Dim sheetName As Variant
Dim ws As Worksheet
For Each sheetName In cacheSheets
Set ws = ThisWorkbook.Worksheets(CStr(sheetName))
Dim result As Long: result = RunValidationSilent(ws)
If result = 0 Then
Err.Raise ERR_CACHE_EMPTY, "RefreshCache_Button", sheetName & " sheet has no data."
End If
If result < 0 Then
Err.Raise ERR_CACHE_EMPTY, "RefreshCache_Button", "Can't refresh " & sheetName & " cache. Validation error occurs."
End If
Next sheetName
Debug.Print "2. refresh master data"
Call RefreshMasterCache()
Debug.Print "3. Determine which cache sheets to refresh based on ActiveSheet"
If activeSheetName = "C1" Then
' first is M1
Call ValidateKukanCache("M1")
Call RefreshKukanCache("M1")
Call UpdateByMaster("M1")
' second is M2
Call ValidateKukanCache("M2")
Call RefreshKukanCache("M2")
Call UpdateByMaster("M2")
ElseIf activeSheetName = "M2" Then
Call ValidateKukanCache("M1")
Call RefreshKukanCache("M1")
Call UpdateByMaster("M1")
End If
Debug.Print "4. update content by other master data"
Call UpdateByMaster(activeSheetName)
Exit Sub
ErrorHandler:
Debug.Print "sheetName = " & sheetName
HandleError "RefreshCache_Button"
End Sub
Private Sub ValidateKukanCache(ByVal sheetName As String)
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(CStr(sheetName))
Dim result As Long: result = RunValidationSilent(ws)
If result = 0 Then
Err.Raise ERR_CACHE_EMPTY, "ValidateKukanCache", sheetName & " sheet has no data."
End If
If result = -1 Then
Err.Raise ERR_VALIDATION_FAILED, "ValidateKukanCache", "Validation error in " & sheetName & " sheet."
End If
End Sub
Private Sub UpdateByMaster(ByVal sheetName As String)
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(CStr(sheetName))
Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig()
Dim sheetConf As Object: Set sheetConf = sheetConfDict(sheetName)
Dim startRow As Long: startRow = sheetConf("StartRow")
Dim lastDataRow As Long: lastDataRow = GetLastDataRowInRange(ws)
Application.Run sheetName & ".Refresh", ws, startRow, lastDataRow
End Sub
' ============================================================
' CSV Import entry point (binds to sheet button)
' ============================================================
Public Sub CSV_Import_Button()
Dim ws As Worksheet: Set ws = ActiveSheet
On Error GoTo ErrorHandler
' Step 1: get csv encoding
Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig()
Dim cfg As Object: Set cfg = sheetConfDict(ws.CodeName)
Dim expectedColumnCount As Long: expectedColumnCount = cfg("ExpectedColumnCount")
' Step 2: Select CSV file
Dim filePath As String: filePath = SelectCSVFile()
If filePath = "" Then Exit Sub
' Step 3: Read CSV and return 2D array
Dim csvData As Variant: csvData = ReadCSVAs2DArrayStrict(filePath, expectedColumnCount, cfg("CSV_Encoding"), cfg("HasHeader"))
If Not IsArray(csvData) Or UBound(csvData, 1) < 1 Then
Err.Raise ERR_FILE_EMPTY, "DO_CSV_Import", "No data in CSV."
End If
' === Step 4: Clear all data rows before import ===
Application.ScreenUpdating = False
Application.EnableEvents = False
Call ClearDataRows(ws)
' === Step 5: Write CSV data to worksheet ===
Dim colLetters As Variant: colLetters = cfg("HeaderColumns")
Dim writeRow As Long: writeRow = cfg("StartRow")
Dim i As Long
For i = LBound(csvData, 1) To UBound(csvData, 1)
Dim j As Long
For j = 0 To expectedColumnCount - 1
ws.Cells(writeRow, ws.Range(colLetters(j) & "1").Column).Value = CleanCSVField(CStr(csvData(i, j + 1)))
Next j
If cfg.Exists("DisplayCol") Then
Call BuildDisplayDropdown(ws, writeRow)
End If
writeRow = writeRow + 1
Next i
MsgBox writeRow - cfg("StartRow") & " rows imported.", vbInformation
GoTo FinallyExit
ErrorHandler:
HandleError "DO_CSV_Import"
GoTo FinallyExit
FinallyExit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
' ============================================================
' Do_Validation entry point (binds to sheet button)
' ============================================================
Public Sub Validation_Button()
Dim ws As Worksheet: Set ws = ActiveSheet
On Error GoTo ErrorHandler
Application.EnableEvents = False
Dim result As Long: result = RunValidationSilent(ws)
If result = -1 Then
Err.Raise ERR_VALIDATION_FAILED, "Do_Validation", "Validation has errors."
End If
If result = 0 Then
Err.Raise ERR_CACHE_EMPTY, "Do_Validation", "No data to validate."
End If
If ws.CodeName <> "C1" Then
RefreshCache(ws.CodeName)
WriteCachesSheet(ws.CodeName)
End If
MsgBox "Validation complete. Success: " & result, vbInformation
' step2. ValidateWarn for M1 sheet
If ws.CodeName = "M1" Then
Dim lastDataRow As Long: lastDataRow = GetLastDataRowInRange(ws)
Application.Run "M1.ValidateWarn", ws, lastDataRow
End If
Do_Fit_Internal ws
Application.EnableEvents = True
Exit Sub
ErrorHandler:
Application.EnableEvents = True
HandleError "Do_Validation"
Do_Fit_Internal ws
End Sub
' ============================================================
' CSV Export entry point (binds to sheet button)
' ============================================================
Public Sub CSV_Export_Button()
Dim ws As Worksheet: Set ws = ActiveSheet
On Error GoTo ErrorHandler
' === Step 1: Validate all rows before export ===
Dim result As Long: result = RunValidationSilent(ws)
If result = 0 Then
Err.Raise ERR_CACHE_EMPTY, "DO_CSV_Export", "No data rows to output."
End If
If result < 0 Then
Err.Raise ERR_VALIDATION_FAILED, "DO_CSV_Export", "Validation failed. Export aborted."
End If
' === Step 2: Select save path ===
Dim savePath As String: savePath = GetSaveCSVPath()
If savePath = "" Then Exit Sub
Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig()
Dim sheetConf As Object: Set sheetConf = sheetConfDict(ws.CodeName)
' === Step 3: Count data rows ===
Dim lastDataRow As Long: lastDataRow = GetLastDataRowInRange(ws)
Dim startRow As Long: startRow = sheetConf("StartRow")
Dim rowCount As Long: rowCount = lastDataRow - startRow + 1
' === Step 4: Count data columns ===
Dim expectedColumnCount As Long: expectedColumnCount = sheetConf("ExpectedColumnCount")
' === Step 5: check export csv has header ===
Dim hasHeader As Boolean: hasHeader = sheetConf("HasHeader")
Dim dataRow As Long: dataRow = 1
Dim outputArr As Variant
If hasHeader Then
ReDim outputArr(1 To rowCount + 1, 1 To expectedColumnCount)
Else
ReDim outputArr(1 To rowCount, 1 To expectedColumnCount)
End If
' === Step 6: Build array with header and data ===
If hasHeader Then
Dim headerArr As Variant
headerArr = GetCSVHeader(ws)
Dim colIdx As Long
For colIdx = 0 To expectedColumnCount - 1
outputArr(1, colIdx + 1) = headerArr(1, colIdx + 1)
Next colIdx
dataRow = dataRow + 1
End If
Dim colLetters As Variant: colLetters = sheetConf("HeaderColumns")
Dim r As Long
Dim colIndex As Long
For r = startRow To lastDataRow
For colIdx = 0 To expectedColumnCount - 1
colIndex = Columns(colLetters(colIdx)).Column
outputArr(dataRow, colIdx + 1) = CleanCSVField(ws.Cells(r, colIndex).Value)
Next colIdx
dataRow = dataRow + 1
Next r
Call WriteCSVFromArray(savePath, outputArr, sheetConf("CSV_Encoding"), sheetConf("AlwaysQuote"))
MsgBox "CSV export completed. Total data rows: " & rowCount, vbInformation
Exit Sub
ErrorHandler:
HandleError "DO_CSV_Export"
End Sub
' ============================================================
' Do_Sort entry point (binds to sheet button)
' ============================================================
Public Sub Sort_Button()
Dim ws As Worksheet: Set ws = ActiveSheet
On Error GoTo ErrorHandler
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 startRow As Long: startRow = sheetConf("StartRow")
Dim lastDataRow As Long: lastDataRow = GetLastDataRowInRange(ws)
If lastDataRow < startRow Then
Err.Raise ERR_CACHE_EMPTY, "Do_Sort", "No data to sort."
End If
Dim sortRange As Range: Set sortRange = ws.Range(ws.Cells(startRow, ws.Range(startCol & "1").Column), ws.Cells(lastDataRow, ws.Range(endCol & "1").Column))
Application.Goto sortRange
Application.Dialogs(xlDialogSort).Show
Exit Sub
ErrorHandler:
HandleError "Do_Sort"
End Sub
' ============================================================
' Do_Filter entry point (binds to sheet button)
' ============================================================
Public Sub Filter_Button()
Dim ws As Worksheet: Set ws = ActiveSheet
On Error GoTo ErrorHandler
Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig()
Dim sheetConf As Object: Set sheetConf = sheetConfDict(ws.CodeName)
' Check if auto filter is already on
If ws.AutoFilterMode Then
ws.AutoFilterMode = False
Exit Sub
End If
Dim startCol As Long: startCol = ws.Range(sheetConf("ErrorCol") & "1").Column
Dim endCol As Long: endCol = ws.Range(sheetConf("EndCol") & "1").Column
Dim filterRow As Long: filterRow = sheetConf("FilterRow")
Dim filterRange As Range: Set filterRange = ws.Range(ws.Cells(filterRow, startCol), ws.Cells(filterRow, endCol))
filterRange.AutoFilter
Exit Sub
ErrorHandler:
HandleError "Do_Filter"
End Sub
Public Sub Fit_Button()
Do_Fit_Internal ActiveSheet
End Sub
' ============================================================
' Do_Fit internal implementation
' ============================================================
Private Sub Do_Fit_Internal(ws As Excel.Worksheet)
On Error GoTo ErrorHandler
Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig()
Dim sheetConf As Object: Set sheetConf = sheetConfDict(ws.CodeName)
' adjust width function contains error column
Dim startCol As String: startCol = sheetConf("ErrorCol")
Dim endCol As String: endCol = sheetConf("EndCol")
ws.Columns(startCol & ":" & endCol).AutoFit
Exit Sub
ErrorHandler:
HandleError "Do_Fit"
End Sub
' ============================================================
' RunValidationSilent
' Returns:
' - Positive number = success (number of rows validated)
' - 0 = no data
' - -1 = has errors
' ============================================================
Public Function RunValidationSilent(ws As Worksheet) As Long
Dim sheetConfDict As Object: Set sheetConfDict = GetSheetConfig()
Dim sheetConf As Object: Set sheetConf = sheetConfDict(ws.CodeName)
Dim validate As String: validate = ws.CodeName & ".Validate"
Dim lastDataRow As Long: lastDataRow = GetLastDataRowInRange(ws)
Dim startRow As Long: startRow = sheetConf("StartRow")
Dim errorCol As Long: errorCol = ws.Range(sheetConf("ErrorCol") & "1").Column
If lastDataRow < startRow Then
RunValidationSilent = 0
Exit Function
End If
Dim r As Long
Dim hasError As Boolean: hasError = False
For r = startRow To lastDataRow
SetLastErrorMsg ""
Application.Run validate, ws, r, lastDataRow
If GetLastErrorMsg() <> "" Then
Err.Raise ERR_VALIDATION_FAILED, "RunValidationSilent", GetLastErrorMsg()
End If
Dim errorMessage As String: errorMessage = Trim(ws.Cells(r, errorCol).Value)
Dim errorCode As String: errorCode = GetCode(errorMessage)
If errorCode <> "W001" And errorCode <> "" Then
hasError = True
End If
Next r
If hasError = True Then
RunValidationSilent = -1
Exit Function
End If
RunValidationSilent = lastDataRow - startRow + 1
Exit Function
End Function
' ============================================================
' Error Handlers
' ============================================================
' Main error handler - centralized error processing
Public Sub HandleError(Optional ByVal sourceProcedure As String = "")
Dim shortCode As String: shortCode = Right("0000" & CStr(Err.Number - vbObjectError), 4)
MsgBox "[ERROR] " & shortCode & " : " & Err.Description, vbExclamation
End Sub