【入門編】QueryDefのSQLプロパティを「外部JSONファイル」で管理する:ソースコードとクエリの完全分離 – Access VBA解析バイブル

スポンサーリンク

こんにちは! Access VBAの「マクロの記録」や、VBAのコードの中に長〜いSQL文を直接ベタ書きするスタイルから、そろそろ卒業したいと思っていませんか?

「VBAの中にSQLを書きすぎて、どこを直したらいいか分からない…」
「SQLの構文エラーが出るたびにVBAのコードを修正するのが面倒…」

そんな悩みを抱えるあなたへ。今回は、プロの現場でも使われる「SQL文を外部のJSONファイルで管理し、それをAccessのQueryDef(クエリ定義)に読み込ませて実行する」という、極上のテクニックを伝授します。

ここをクリアすれば、あなたのAccess開発のスキルは間違いなく一段階上のステージに上がります。一緒に優しく、深く、学んでいきましょう!

—

1. なぜ「ソースコードとSQLの分離」が必要なのか?

まずは、なぜVBAの中にSQLを直接書くべきではないのか、その本質からお話ししますね。

よくある初心者のコードはこうです:

‘ ありがちなベタ書きの例
Dim strSQL As String
strSQL = “SELECT 顧客ID, 顧客名, 住所 FROM T_顧客 ” & _
“WHERE 登録日 >= #2023-01-01# ” & _
“ORDER BY 顧客ID;”
CurrentDb.QueryDefs(“Q_抽出”).SQL = strSQL

一見動くので問題なさそうに見えますが、SQLが長くなればなるほど、ダブルクォーテーション(”)や改行の連結地獄にハマりますよね。

これを外部のJSONファイル(例:`query_config.json`)に追い出します。

{
“Q_抽出”: “SELECT 顧客ID, 顧客名, 住所 FROM T_顧客 WHERE 登録日 >= #2023-01-01# ORDER BY 顧客ID;”
}

こうすることで、以下の圧倒的なメリットが手に入ります。

  • メンテナンス性の向上: VBAのコンパイルを直さず、SQLだけをテキストエディタでサクッと修正できる。
  • 役割の分離: 「プログラムの処理」と「データの抽出条件(SQL)」を完全に切り離すことで、コードがスッキリ美しくなる。

—

2. 全体像の把握:どうやって動かすのか?

今回の仕組みは、以下のステップで流れます。

1. JSONファイルの配置: Accessのデータベースファイルと同じフォルダに、SQLをまとめたJSONファイルを置きます。
2. VBAからの読み込み: VBAでJSONファイルをテキストとして読み込みます(今回は外部ライブラリに頼らず、標準機能やVBAのテキスト操作でスマートに処理します)。
3. QueryDefへのセット: 読み込んだSQLを、Accessのクエリ定義(QueryDef)に流し込みます。

それでは、具体的なコードを見ていきましょう!

—

3. 実装コード:魔法のVBAプロシージャ

開発環境の標準モジュールに、以下のコードをコピー&ペーストしてください。コピペしてそのまま現場で使える実用コードです。

準備:JSONファイルの作成

まず、Accessファイルと同じ階層に `settings.json` という名前のファイルをメモ帳などで作成し、中身を以下のように記述してください。

{
“Q_MonthlySales”: “SELECT 担当者ID, SUM(売上金額) AS 合計売上 FROM T_売上 GROUP BY 担当者ID;”
}

VBAコード(標準モジュール)

Option Explicit

‘ =====================================================================
‘ 外部JSONからSQLを読み込み、QueryDefに動的設定するメインプロシージャ
‘ =====================================================================
Public Sub ApplySQLFromJSON()
On Error GoTo ErrorHandler

Dim jsonFilePath As String
Dim jsonContent As String
Dim queryName As String
Dim sqlText As String

‘ 1. JSONファイルのパスを取得(Accessファイルと同じフォルダを想定)
jsonFilePath = CurrentProject.Path & “\settings.json”

‘ ファイルが存在するかチェック
If Dir(jsonFilePath) = “” Then
MsgBox “JSONファイルが見つかりません: ” & jsonFilePath, vbCritical, “エラー”
Exit Sub
End If

‘ 2. JSONファイルをテキストとして丸ごと読み込む
jsonContent = ReadTextFile(jsonFilePath)

‘ 3. 【超重要】簡易JSONパーサー(今回は “クエリ名”: “SQL文” のペアを抽出)
‘ ※実務では正規表現や専用パーサーを使うとより堅牢になります
queryName = “Q_MonthlySales”
sqlText = ExtractJsonValue(jsonContent, queryName)

If sqlText = “” Then
MsgBox “指定されたクエリ定義がJSON内に見つかりません。”, vbExclamation, “警告”
Exit Sub
End If

‘ 4. QueryDefオブジェクトを取得(または新規作成)してSQLをセット
UpdateQueryDef queryName, sqlText

MsgBox “QueryDef [” & queryName & “] のSQL更新が完了しました!”, vbInformation, “成功”
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “システムエラー”
End Sub

‘ =====================================================================
‘ テキストファイルをUTF-8(またはANSI)で読み込む関数
‘ =====================================================================
Private Function ReadTextFile(ByVal filePath As String) As String
Dim fso As Object
Dim ts As Object

Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 第3引数 -1 はUnicode(UTF-8等)での読み込みを示す
Set ts = fso.OpenTextFile(filePath, 1, False, -1)

ReadTextFile = ts.ReadAll
ts.Close

Set ts = Nothing
Set fso = Nothing
End Function

‘ =====================================================================
‘ 簡易的なJSONの値抽出ロジック(”key”: “value” を探す)
‘ =====================================================================
Private Function ExtractJsonValue(ByVal json As String, ByVal key As String) As String
Dim targetKey As String
Dim posKey As Long
Dim posStart As Long
Dim posEnd As Long

targetKey = “””” & key & “”””
posKey = InStr(json, targetKey)

If posKey = 0 Then
ExtractJsonValue = “”
Exit Function
End If

‘ キーの後のコロンとダブルクォーテーションを探す
posStart = InStr(posKey + Len(targetKey), json, “”””)
If posStart = 0 Then
ExtractJsonValue = “”
Exit Function
End If

‘ 値の終わりのダブルクォーテーションを探す(エスケープ文字の考慮は簡易化)
posEnd = InStr(posStart + 1, json, “”””)
If posEnd = 0 Then
ExtractJsonValue = “”
Exit Function
End If

‘ 値を切り出す
ExtractJsonValue = Mid(json, posStart + 1, posEnd – posStart – 1)
End Function

‘ =====================================================================
‘ QueryDefのSQLを安全に更新するプロシージャ
‘ =====================================================================
Private Sub UpdateQueryDef(ByVal qryName As String, ByVal sql As String)
Int_SafeDeleteQuery qryName

Dim qdf As DAO.QueryDef
‘ クエリを新規作成してSQLを代入
Set qdf = CurrentDb.CreateQueryDef(qryName, sql)

Set qdf = Nothing
End Sub

‘ =====================================================================
‘ 既存のクエリが存在する場合に安全に削除するヘルパー
‘ =====================================================================
Private Sub Int_SafeDeleteQuery(ByVal qryName As String)
Dim qdf As DAO.QueryDef
On Error Resume Next
Set qdf = CurrentDb.QueryDefs(qryName)
If Err.Number = 0 Then
CurrentDb.QueryDefs.Delete qryName
End If
On Error GoTo 0
Set qdf = Nothing
End Sub

—

4. 陥りやすいエラーと回避の極意

この手法を実装する際、現場でよくぶつかる壁と、そのスマートな回避方法をシェアしておきますね。

① 漢字や特殊文字化け問題

  • 現象: JSONファイルを保存した際、VBA側で読み込むと文字化けしてSQLがSyntaxError(構文エラー)になる。
  • 極意: テキストファイル(JSON)の文字コードは UTF-8(できればBOM付き、またはVBA側で適切に制御) で保存してください。上記のコードでは `FileSystemObject` の `-1`(Unicode指定)を使用しているため、比較的文字化けを防ぎやすくなっています。

② ダブルクォーテーション(”)の衝突

  • 現象: SQL文の中に条件値としてダブルクォーテーションを入れたい場合、JSONの構造とぶつかってエラーになる。
  • 極意: SQL内の文字列リテラルには、Access(Jet/ACEエンジン)が許容している シングルクォーテーション(’) を使うのが鉄則です。
  • NG: `WHERE 氏名 = “山田”`
  • OK: `WHERE 氏名 = ‘山田’`

—

最後に:ここをクリアすれば、あなたはもう初心者ではない!

お疲れ様でした!
今回紹介した「ソースコードとSQLの完全分離(JSON管理)」は、小規模なAccessアプリであっても、将来的なメンテナンス性を劇的に引き上げてくれるプロの知恵です。

「VBAは画面の制御や処理の流れだけに集中させ、データの抽出定義は外に出す」

この設計思想が頭に入っていれば、Access VBAだけでなく、将来的にC#やPythonなどのモダンな開発言語にステップアップしたときにも、必ずあなたの強力な武器になります。

ここをクリアしたあなたなら、もうAccessの基本はバッチリです!ぜひ明日の開発から取り入れてみてくださいね。

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