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

Excel VBA VBA
スポンサーリンク

フィールド定義を「データベース(Access / SQL Server)」から読み込むバージョン

CSVやExcelシートではなく、AccessやSQL Serverに格納した定義表を直接読み込んで入力チェックを行う仕組みです。
これにより、定義をデータベースで一元管理でき、複数のExcelブックから共通ルールを参照できます。


想定する定義テーブル構造(例:FieldDefinitions)

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

VBAコード例(ADOを利用)

Sub ValidateByDBDefinition()
    Dim wsData As Worksheet, wsReport As Worksheet
    Dim lastRow As Long, r As Long, output As Long
    Dim conn As Object, rs As Object
    Dim sql As String
    Dim defs As Collection
    Dim def As Variant
    
    ' データ本体シート
    Set wsData = ThisWorkbook.Sheets("Sheet1")
    
    ' 出力先シート準備
    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
    
    ' --- データベース接続 ---
    Set conn = CreateObject("ADODB.Connection")
    
    ' ▼Accessの場合(例:同じフォルダにあるAccessファイル)
    ' conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.Path & "\FieldDef.accdb;"
    
    ' ▼SQL Serverの場合(例:ローカルのSQL Express)
    ' conn.Open "Provider=SQLOLEDB;Data Source=localhost\SQLEXPRESS;Initial Catalog=MyDB;Integrated Security=SSPI;"
    
    sql = "SELECT 列番号, 項目名, 必須, 型, 最小値, 最大値, 最大文字数, 正規表現 FROM FieldDefinitions"
    
    Set rs = CreateObject("ADODB.Recordset")
    rs.Open sql, conn
    
    Set defs = New Collection
    Do Until rs.EOF
        defs.Add Array(rs(0).Value, rs(1).Value, rs(2).Value, rs(3).Value, _
                       rs(4).Value, rs(5).Value, rs(6).Value, rs(7).Value)
        rs.MoveNext
    Loop
    rs.Close
    conn.Close
    
    ' --- データを検証 ---
    lastRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row
    
    For r = 2 To lastRow
        For Each def In defs
            Dim colIdx As Long, fieldName As String, required As Boolean
            Dim fieldType As String, minVal As String, maxVal As String
            Dim maxLen As Long, regex As String
            Dim value As Variant, errs As Variant, msg As String
            
            colIdx = CLng(def(0))
            fieldName = def(1)
            required = (def(2) = "○")
            fieldType = def(3)
            minVal = def(4)
            maxVal = def(5)
            If def(6) <> "" Then maxLen = CLng(def(6)) Else maxLen = 0
            regex = def(7)
            
            value = wsData.Cells(r, colIdx).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 = colIdx
                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 def
    Next r
    
    MsgBox "DB定義に基づく検証が完了しました。エラー件数: " & (output - 2), vbInformation
End Sub
VB

ポイント

  • AccessProvider=Microsoft.ACE.OLEDB.12.0;Data Source=...
  • SQL ServerProvider=SQLOLEDB;Data Source=サーバ名;Initial Catalog=DB名;Integrated Security=SSPI;
  • 定義表をDBで集中管理 → 複数のExcelブックが同じルールを参照可能。
  • CollectErrors / CheckRequired / CheckNumber / CheckDate は前回の「汎用チェック関数ライブラリ」を利用。

応用アイデア

  • 定義テーブルに「エラーメッセージ」列を追加して、文言をDB側で管理。
  • 複数の定義セット(顧客用・社員用など)を切り替えられるようにする。
  • SQL Serverならストアドプロシージャで定義を返すようにしても良い。

👉 これで「CSV → DB」へ進化し、ルールをシステム的に一元管理できるようになりました。

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