【VBA】ADOによるAccess連携:「パラメータ化クエリ」で安全にデータを絞り込み・取得する(テストコード付き)
これまでに構築した共通のコネクションパーツ(OpenDatabaseConnection / CloseDatabaseConnection)をそのまま活かし、今回は新たに「ADODB.Commandオブジェクトを活用したパラメータ化クエリ(プリペアードステートメント)」による安全なデータ抽出処理を実装しました。
実際の実行結果とともに、モジュール全体をお届けします。
1. 実装:パラメータ化クエリによる安全なデータ抽出モジュール
' [機能名] Accessデータベースへの接続確立
' ==============================================================================
Public Function OpenDatabaseConnection(ByVal dbFileName As String) As Object
Set OpenDatabaseConnection = Nothing
On Error GoTo ErrorHandler
Dim dbPath As String
dbPath = ThisWorkbook.Path & "\" & dbFileName
If Dir(dbPath) = "" Then
Debug.Print "[WARNING] OpenDatabaseConnection: ファイルが見つかりません。 Path: " & dbPath
Exit Function
End If
Dim conn As Object
Set conn = CreateObject("ADODB.Connection")
Dim connStr As String
connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath & "; "
conn.Open connStr
Debug.Print "[INFO] Database Connected: " & dbFileName
Set OpenDatabaseConnection = conn
Exit Function
ErrorHandler:
Debug.Print "[WARNING] OpenDatabaseConnection: 接続エラー (Err:" & Err.Number & " - " & Err.Description & ")"
Set OpenDatabaseConnection = Nothing
End Function
' ==============================================================================
' [機能名] パラメータ化クエリを用いた条件付きデータ取得と出力
'
' [処理内容]
' ・ADODB.CommandとCreateParameterを使用して、SQLインジェクションを防止しながら
' 指定した条件(部署・年齢など)に一致するレコードを安全に抽出・出力します。
'
' [引数]
' @param {Object} conn : 必須 : 接続済みの ADODB.Connection オブジェクト
' @param {String} tableName : 必須 : 対象のテーブル名(例: "社員マスタ")
' @param {String} targetDep : 必須 : 抽出する部署名条件
' @param {Long} targetAge : 必須 : 抽出する年齢の下限条件
' ==============================================================================
Public Function PrintTableDataParameterized(ByVal conn As Object, ByVal tableName As String, ByVal targetDep As String, ByVal targetAge As Long) As Boolean
PrintTableDataParameterized = False
If conn Is Nothing Or Trim(tableName) = "" Then
Debug.Print "[WARNING] PrintTableDataParameterized: 引数が無効です。"
Exit Function
End If
Dim cmd As Object
Dim rs As Object
On Error GoTo ErrorHandler
' Commandオブジェクトの生成
Set cmd = CreateObject("ADODB.Command")
With cmd
Set .ActiveConnection = conn
.CommandType = 1 ' adCmdText = 1
' プレースホルダーとして ? を使用(AccessのOLEDBでは位置ベース)
.CommandText = "SELECT * FROM [" & tableName & "] WHERE [部署] = ? AND [年齢] >= ?"
' パラメータの追加(adVarChar = 200, adInteger = 3, adParamInput = 1)
.Parameters.Append .CreateParameter("pDep", 200, 1, 50, targetDep)
.Parameters.Append .CreateParameter("pAge", 3, 1, , targetAge)
' 実行してレコードセットを取得
Set rs = .Execute
End With
Debug.Print "=================================================="
Debug.Print " [Parameterized Query Data] " & tableName & " (部署: " & targetDep & " / 年齢以上: " & targetAge & ")"
Debug.Print "=================================================="
' フィールド名のヘッダー行を作成
Dim headerStr As String
Dim i As Long
headerStr = ""
For i = 0 To rs.Fields.Count - 1
headerStr = headerStr & Left(rs.Fields(i).Name & Space(15), 15) & " | "
Next i
Debug.Print headerStr
Debug.Print String(Len(headerStr), "-")
' レコードのループ出力
Do While Not rs.EOF
Dim rowStr As String
rowStr = ""
For i = 0 To rs.Fields.Count - 1
Dim valStr As String
valStr = CStr(Nz(rs.Fields(i).Value, ""))
rowStr = rowStr & Left(valStr & Space(15), 15) & " | "
Next i
Debug.Print rowStr
rs.MoveNext
Loop
Debug.Print "=================================================="
rs.Close
Set rs = Nothing
Set cmd = Nothing
PrintTableDataParameterized = True
Exit Function
ErrorHandler:
Debug.Print "[WARNING] PrintTableDataParameterized: パラメータクエリ実行エラー (Err:" & Err.Number & " - " & Err.Description & ")"
On Error Resume Next
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set cmd = Nothing
On Error GoTo 0
PrintTableDataParameterized = False
End Function
' ==============================================================================
' [機能名] データベース接続の安全な切断・解放
' ==============================================================================
Public Sub CloseDatabaseConnection(ByRef conn As Object)
On Error Resume Next
If Not conn Is Nothing Then
If conn.State = 1 Then
conn.Close
Debug.Print "[INFO] Database Disconnected."
End If
Set conn = Nothing
End If
On Error GoTo 0
End Sub
' Null安全対策ヘルパー
Private Function Nz(ByVal varValue As Variant, ByVal valueIfNull As Variant) As Variant
If IsNull(varValue) Then Nz = valueIfNull Else Nz = varValue
End Function
2. 単体テスト用コード(パラメータ化クエリの実行テスト)
' [機能名] パラメータ化クエリによるデータ取得テスト
' ==============================================================================
Public Sub Test_GetParameterizedEmployeeData()
Dim startTime As Double
startTime = Timer
Debug.Print "[START] Test_GetParameterizedEmployeeData (" & Format(Now, "yyyy/mm/dd hh:nn:ss") & ")"
Debug.Print "=================================================="
Debug.Print " パラメータ化クエリ データ取得テスト開始"
Debug.Print "=================================================="
Dim targetDbName As String
targetDbName = "SampleDB.accdb"
' 1. 接続 (Connect) - 共通関数を使用
Dim conn As Object
Set conn = OpenDatabaseConnection(targetDbName)
If conn Is Nothing Then
Debug.Print "[FAIL] 接続テスト: DB接続に失敗しました。"
GoTo Test_End
Else
Debug.Print "[PASS] 接続テスト: DB接続成功"
End If
' 2. パラメータ化クエリによるデータ取得 (部署 = '営業部', 年齢 >= 30)
Dim targetTable As String
targetTable = "社員マスタ"
Dim isSuccess As Boolean
isSuccess = PrintTableDataParameterized(conn, targetTable, "営業部", 30)
If isSuccess Then
Debug.Print "[PASS] パラメータクエリテスト: データの安全な抽出 OK"
Else
Debug.Print "[FAIL] パラメータクエリテスト: データの取得に失敗しました。"
End If
Test_End:
' 3. 切断 (Disconnect) - 共通Subを使用
CloseDatabaseConnection conn
If conn Is Nothing Then
Debug.Print "[PASS] 切断テスト: コネクションの安全な破棄 OK"
Else
Debug.Print "[FAIL] 切断テスト: コネクションの解放漏れ"
End If
Debug.Print "=================================================="
Dim elapsed As Double
elapsed = Timer - startTime
If elapsed < 0 Then elapsed = elapsed + 86400
Debug.Print "[END] Test_GetParameterizedEmployeeData (Elapsed: " & Format(elapsed, "0.000") & " sec)"
End Sub
3. 実行結果(イミディエイトウィンドウの出力)
==================================================
パラメータ化クエリ データ取得テスト開始
==================================================
[INFO] Database Connected: SampleDB.accdb
[PASS] 接続テスト: DB接続成功
==================================================
[Parameterized Query Data] 社員マスタ (部署: 営業部 / 年齢以上: 30)
==================================================
ID | 氏名 | 部署 | 年齢 |
------------------------------------------------------------------------
2 | 山田太郎 | 営業部 | 30 |
==================================================
[PASS] パラメータクエリテスト: データの安全な抽出 OK
[INFO] Database Disconnected.
[PASS] 切断テスト: コネクションの安全な破棄 OK
==================================================
[END] Test_GetParameterizedEmployeeData (Elapsed: 0.438 sec)