Access VBAを掌握する極限の知見:QueryDefの「説明文」を極めよ 〜SQLドキュメント自動生成の極意〜
長年、数多のレガシーシステムと向き合ってきた者なら誰もが知っているジレンマがある。それは、「Accessのクエリが増えすぎて、もはや誰も全容を把握できない」というカオスだ。
「このクエリ、何の目的で誰が作ったんだ?」
「変更したら、どこかの帳票出力が死ぬかもしれない……怖くて触れない」
散らばったExcelの設計書を探し回るなど、プロフェッショナルの仕事ではない。仕様書は、コード(あるいはデータベース定義)と一蓮托生でなければならないのだ。
今回は、Accessの`QueryDef`オブジェクトが持つ秘宝、「説明文(Description)プロパティ」に焦点を当てる。DAOの奥底に眠るこのメタデータを完全掌握し、一気通貫でシステム仕様書を自動出力する極限のテクニックを授けよう。
—
1. なぜ「QueryDef.Properties」なのか?
GUIのナビゲーションウインドウでクエリ名を右クリックし、「プロパティ」を開くと、「説明」という入力欄が存在する。ここに入力された値は、実はDAOの`QueryDef.Properties`コレクションの中に隠されている。
しかし、この「説明」プロパティは、新規作成時には標準では存在しない。初回アクセス時に動的に生成して書き込む必要があるという、Access特有の「ツンデレ仕様」を持っている。
ここを理解していないと、「Property not found(エラー 3270)」の呪縛に囚われることになる。まずは、この不可視のプロパティを安全に読み書きする作法から始めよう。
—
2. 実装:メタデータ駆動型・SQLドキュメント自動生成エンジン
以下のコードは、データベース内の全QueryDefを走査し、説明文プロパティから「作成者」「更新日」「業務目的」「依存関係」等のメタデータを抽出し、Excelへ綺麗に出力する実用モジュールだ。
メモリリークを絶対に起こさない、シニアの作法(オブジェクトの明示的解放とエラーハンドリング)で記述している。
Option Compare Database
Option Explicit
‘ =========================================================================
‘ 模块名: modQueryDocumentGenerator
‘ 概要: QueryDefの説明文プロパティを解析し、システム仕様書を自動生成する
‘ =========================================================================
Public Sub GenerateQuerySpecification()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim xlApp As Object
Dim xlWb As Object
Dim xlWs As Object
Dim rowIdx As Long
Dim descText As String
On Error GoTo ErrorHandler
‘ 現在のデータベース参照を取得(パフォーマンス最適化のためCurrentDbを変数保持)
Set db = CurrentDb()
‘ Excelアプリケーションの起動(レイトバインドでバージョン差異を吸収)
Set xlApp = CreateObject(“Excel.Application”)
xlApp.Visible = True
Set xlWb = xlApp.Workbooks.Add
Set xlWs = xlWb.Sheets(1)
xlWs.Name = “クエリ定義書”
‘ ヘッダーの構築
With xlWs
.Cells(1, 1).Value = “クエリ名”
.Cells(1, 2).Value = “クエリ種別”
.Cells(1, 3).Value = “説明文 / 仕様”
.Cells(1, 4).Value = “SQLテキスト”
‘ ヘッダー装飾
.Range(“A1:D1”).Font.Bold = True
.Range(“A1:D1”).Interior.Color = RGB(220, 220, 220)
End With
rowIdx = 2
‘ QueryDefコレクションの走査
For Each qdf In db.QueryDefs
‘ システムクエリ(~で始まる一時クエリなど)はスキップ
If Not (qdf.Name Like “~”) Then
‘ クエリ名
xlWs.Cells(rowIdx, 1).Value = qdf.Name
‘ クエリ種別の判定(SELECT, INSERT, UPDATE, DELETE等)
xlWs.Cells(rowIdx, 2).Value = GetQueryTypeName(qdf.Type)
‘ 【核心】説明文プロパティの安全な取得
descText = GetQueryDescription(qdf)
xlWs.Cells(rowIdx, 3).Value = descText
‘ SQL文(長文対策としてセルに格納)
xlWs.Cells(rowIdx, 4).Value = qdf.SQL
rowIdx = rowIdx + 1
End If
Next qdf
‘ 仕上げ:レイアウト調整
xlWs.Columns(“A:D”).AutoFit
MsgBox “システム仕様書の自動生成が完了しました。”, vbInformation, “完了”
CleanUp:
‘ 对象的明示的解放(VBAにおけるメモリ管理の鉄則)
Set qdf = Nothing
Set db = Nothing
Set xlWs = Nothing
Set xlWb = Nothing
Set xlApp = Nothing
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
‘ =========================================================================
‘ 補助関数: クエリの説明文プロパティを安全に取得(存在しない場合は空文字)
‘ =========================================================================
Private Function GetQueryDescription(ByRef qdf As DAO.QueryDef) As String
Dim prop As DAO.Property
Dim desc As String
On Error GoTo Catch
desc = qdf.Properties(“Description”)
GetQueryDescription = desc
Exit Function
Catch:
‘ プロパティが存在しない場合はエラー3270が発生するため、空文字を返す
If Err.Number = 3270 Then
GetQueryDescription = “(説明文未設定)”
Else
GetQueryDescription = “(取得エラー)”
End If
End Function
‘ =========================================================================
‘ 補助関数: QueryDefのType定数から文字列を返す
‘ =========================================================================
Private Function GetQueryTypeName(ByVal qType As Long) As String
Select Case qType
Case dbQSelect: GetQueryTypeName = “SELECT”
Case dbQMakeTable: GetQueryTypeName = “テーブル作成”
Case dbQAppend: GetQueryTypeName = “追加”
Case dbQUpdate: GetQueryTypeName = “更新”
Case dbQDelete: GetQueryTypeName = “削除”
Case dbQCrosstab: GetQueryTypeName = “クロス集計”
Case dbQPassThrough:GetQueryTypeName = “パススルー”
Case dbQSQLPassThru:GetQueryTypeName = “SQLパススルー”
Case Else: GetQueryTypeName = “その他 (” & qType & “)”
End Select
End Function
—
3. 実践:プログラム側から「説明文」を書き込む(メタデータの統制)
仕様書を自動生成するだけでなく、クエリ生成・変更スクリプトの実行と同時に説明文をプログラムから自動埋め込みする仕組みを作ってこそ、真の自動化エンジニアと言える。
以下のサブルーチンは、動的にQueryDefを作成・上書きする際に、説明文プロパティを確実に付与(または更新)する手法を示している。
Public Sub UpsertQueryWithDescription(ByVal queryName As String, ByVal sqlText As String, ByVal descriptionText As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb()
On Error Resume Next
‘ 既存のクエリが存在するか確認し、あれば削除、なければ新規作成
db.QueryDefs.Delete queryName
Err.Clear
‘ QueryDefの作成
Set qdf = db.CreateQueryDef(queryName, sqlText)
‘ 説明文プロパティの設定(存在しない場合は追加するロジック)
On Error GoTo SetPropError
qdf.Properties(“Description”) = descriptionText
db.Idle dbRefreshCache
Set qdf = Nothing
Set db = Nothing
Exit Sub
SetPropError:
If Err.Number = 3270 Then
‘ プロパティが未定義の場合は新規追加
Dim prop As DAO.Property
Set prop = qdf.CreateProperty(“Description”, dbText, descriptionText)
qdf.Properties.Append prop
Set prop = Nothing
Resume Next
Else
MsgBox “プロパティ設定エラー: ” & Err.Description, vbCritical
End If
End Sub
—
4. チーフアーキテクトからの提言:レガシーの呪縛を断ち切れ
Accessは、正しく扱えば今なお最強のラピッドプロトタイピング・ツールであり、ローコードの祖先である。しかし、「誰も中身を理解できない巨大クエリの山」と化した瞬間、それは負債製造機へと成り下がる。
今回解説した`QueryDef`の「説明文」プロパティの活用は、データベース自体にドキュメントを内包させる「セルフドキュメンティング・データベース」の思想そのものだ。外部のExcel設計書に頼るのではなく、クエリそのものが語る仕様書を構築せよ。
オブジェクトの解放を怠らず、メモリ空間を美しく保ち、コードでシステムを支配する。この境地に達した時、あなたのAccess開発は、単なる「お絵描き」から、揺るぎない「エンジニアリング」へと昇華されるはずだ。
