Excel VBA | フィールド定義表から自動でチェックを組み立てる仕組み(メタデータ駆動)

Excel VBA VBA
スポンサーリンク

毎回コードに「必須」「数値」「日付」などのチェックを書き込むのは大変です。
そこで 「フィールド定義表」=各列のルールを表にまとめておき、マクロはその定義を読み取って自動的にチェックを実行する 仕組みを作ると、柔軟でメンテしやすくなります。

フィールド定義表の例(別シート「定義」)

列番号項目名必須最小値最大値最大文字数正規表現
1氏名文字列50
2年齢整数0120
3入社日日付1990/1/1TODAY
4メール文字列100^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$

マクロコード例

Sub ValidateByDefinition()
    Dim wsData As Worksheet, wsDef As Worksheet, wsReport As Worksheet
    Dim lastRow As Long, lastDef As Long
    Dim r As Long, c As Long, output As Long
    Dim fieldName As String, fieldType As String
    Dim required As Boolean, minVal As String, maxVal As String
    Dim maxLen As Long, regex As String
    Dim value As Variant, errs As Variant, msg As String
    
    Set wsData = ThisWorkbook.Sheets("Sheet1")   ' データ本体
    Set wsDef = ThisWorkbook.Sheets("定義")      ' フィールド定義表
    
    ' 出力先シート準備
    On Error Resume Next
    Set wsReport = ThisWorkbook.Sheets("検証結果")
    On Error GoTo 0
    If wsReport Is Nothing Then
        Set wsReport = ThisWorkbook.Sheets.Add
        wsReport.Name = "検証結果"
    Else
        wsReport.Cells.Clear
    End If
    
    wsReport.Range("A1:E1").Value = Array("行番号", "列番号", "項目名", "値", "エラー内容")
    output = 2
    
    lastRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row
    lastDef = wsDef.Cells(wsDef.Rows.Count, "A").End(xlUp).Row
    
    ' データ行ごとに検証
    For r = 2 To lastRow
        For c = 1 To lastDef
            fieldName = wsDef.Cells(c, "B").Value
            required = (wsDef.Cells(c, "C").Value = "○")
            fieldType = wsDef.Cells(c, "D").Value
            minVal = wsDef.Cells(c, "E").Value
            maxVal = wsDef.Cells(c, "F").Value
            maxLen = wsDef.Cells(c, "G").Value
            regex = wsDef.Cells(c, "H").Value
            
            value = wsData.Cells(r, wsDef.Cells(c, "A").Value).Value
            
            ' エラー収集
            errs = CollectErrors( _
                IIf(required, CheckRequired(value, fieldName), ""), _
                IIf(maxLen > 0, CheckMaxLength(value, fieldName, maxLen), ""), _
                IIf(fieldType = "整数", CheckInteger(value, fieldName), _
                   IIf(fieldType = "数値", CheckNumber(value, fieldName), _
                   IIf(fieldType = "日付", CheckDate(value, fieldName), ""))), _
                IIf(fieldType = "整数" Or fieldType = "数値", CheckNumberRange(value, fieldName, minVal, maxVal), ""), _
                IIf(fieldType = "日付", CheckDateRange(value, fieldName, minVal, IIf(maxVal = "TODAY", Date, maxVal)), ""), _
                IIf(regex <> "", CheckRegex(value, fieldName, regex, ""), "") _
            )
            
            msg = JoinErrors(errs)
            If msg <> "" Then
                wsReport.Cells(output, "A").Value = r
                wsReport.Cells(output, "B").Value = wsDef.Cells(c, "A").Value
                wsReport.Cells(output, "C").Value = fieldName
                wsReport.Cells(output, "D").Value = value
                wsReport.Cells(output, "E").Value = msg
                wsReport.Cells(output, "E").WrapText = True
                output = output + 1
            End If
        Next c
    Next r
    
    MsgBox "検証完了。エラー件数: " & (output - 2), vbInformation
End Sub
VB

CollectErrors, CheckRequired, CheckNumber, CheckDate などは前回作った「汎用チェック関数ライブラリ」を利用します。


ポイント

  • 定義表を編集するだけでルール変更可能(コード修正不要)。
  • TODAY など特殊値を解釈して「今日まで」などの条件に対応。
  • 正規表現を使えばメールや電話番号の形式チェックも可能。

応用アイデア

  • 定義表に「エラーメッセージ」を直接書いておき、カスタム文言を返す。
  • 定義表をCSVやDBから読み込んで、複数シートに共通適用。
  • エラーがなければ「全件正常」とサマリーを出す。

👉 この仕組みを使えば、「定義表を更新するだけでチェックルールを変えられる」ので、現場での運用がとても楽になります。

タイトルとURLをコピーしました