Access VBAを極限まで掌握せよ:`CurrentProject.AllModules`で実現するコード動的解析・保守ツールの全貌
大規模なAccess開発案件に直面したとき、あなたは何に絶望するだろうか。
「どこで誰が定義したか分からないグローバル変数」
「仕様変更のたびに全フォーム・全標準モジュールをしらみつぶしに目視確認する絶望的な作業」
「前任者が残した、誰も全容を把握できないスパゲッティコードの山」
素人はここで手作業という名の泥沼に足を踏み入れる。だが、プロのアーキテクトは違う。「Access自身に自分自身のコードを解析させればいい」のだ。
今回は、`Application.CurrentProject.AllModules`(および標準・クラス・フォーム・レポートに潜むコード群)を網羅的に走査し、特定のキーワードやプロシージャ名を自動抽出する「メタプログラミング型・コード保守ツール」の設計思想と実装を授けよう。
—
1. なぜ「目視での保守」は悪なのか?(アーキテクトの視点)
何百ものモジュールを抱えるAccessデータベースにおいて、テキスト検索機能頼みの保守は破綻する。
なぜなら、Accessのコードベースは単一のテキストファイルではなく、フォームやレポートのイベントプロシージャといった「オブジェクトの内部(COMコンポーネントの構造体)」にカプセル化されているからだ。
ここで手作業による検索を行うことの弊害は以下の通りだ。
- 見落としの発生: フォームのイベントハンドラ内に隠蔽されたロジックを見落とし、改修漏れによるバグを生む。
- 工数の無駄: 影響範囲の特定だけで数日を費やし、本質的な機能実装の時間が削られる。
- 属人化: 「あの人に聞かないとどこを修正すればいいか分からない」という最悪のアーキテクチャが完成する。
これを解決するのが、VBE(Visual Basic for Applications Environment)のCOMコンポーネント、すなわち `VBProject` オブジェクトモデル である。
—
2. 堅牢な解析ツールを支える「VBEオブジェクトモデル」の基礎
Accessでコードを動的解析する場合、`CurrentProject.AllModules` は「標準モジュールとグローバルクラスモジュール」の列挙には最適だが、フォームやレポートの内部に記述されたコード(Document Modules)までは直接走査できないという罠がある。
すべてのコード(標準、クラス、フォーム、レポート)を完全に支配下に置くためには、`Application.VBE.ActiveVBProject.VBComponents` コレクションを叩く必要がある。
ここに、アマチュアの書くコードとプロの書くプロダクションコードの決定的な違いがある。
⚠️ 開発時の必須設定(トラップ回避)
VBEオブジェクトモデルを操作するには、Accessのセキュリティ設定で「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」にチェックが入っている必要がある。これを怠ると、プログラムからコード領域へのアクセスは容赦なく拒絶される。
—
3. 【プロダクションコード】コード動・静的解析&抽出ツール
以下のコードは、データベース内の全モジュール・全コンポーネントを走査し、指定したキーワード(プロシージャ名や変数名など)がどこで定義・使用されているかをイミディエイトウィンドウに出力(あるいは一時テーブルに出力)する実用的なツールである。
標準モジュールに貼り付けて実行してほしい。
Option Compare Database
Option Explicit
‘ ==============================================================================
‘ 処理名: データベース内コード網羅的解析・検索ツール
‘ 概要 : VBEコンポーネントを走査し、指定キーワードが含まれる行を抽出する
‘ 備考 : 事前に「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」をONにすること
‘ ==============================================================================
Public Sub AnalyzeVBAProjectCode(ByVal targetKeyword As String)
Dim vbComp As Object ‘ VBComponent
Dim codeMod As Object ‘ CodeModule
Dim totalLines As Long
Dim i As Long
Dim lineText As String
Dim matchCount As Long
‘ ガード節:キーワードの空チェック
If Trim(targetKeyword) = “” Then
MsgBox “検索キーワードを指定してください。”, vbExclamation, “パラメータエラー”
Exit Sub
End If
matchCount = 0
Debug.Print “========================================================”
Debug.Print ” コード解析開始: キーワード [” & targetKeyword & “]”
Debug.Print ” 実行日時: ” & Now
Debug.Print “========================================================”
‘ VBEのプロジェクトコンポーネントを走査
On Error GoTo ErrorHandler
For Each vbComp In Application.VBE.ActiveVBProject.VBComponents
Set codeMod = vbComp.CodeModule
totalLines = codeMod.CountOfLines
If totalLines > 0 Then
‘ 各モジュールの全行を上から下へ走査
For i = 1 To totalLines
lineText = codeMod.Lines(i, 1)
‘ キーワードが含まれているか判定(大文字小文字を区別しない)
If InStr(1, lineText, targetKeyword, vbTextCompare) > 0 Then
matchCount = matchCount + 1
‘ 出力フォーマット: [種別] モジュール名 (行番号) : コード内容
Debug.Print “[” & GetComponentTypeString(vbComp.Type) & “] ” & _
vbComp.Name & ” (Line ” & i & “) : ” & _
Trim(lineText)
End If
Next i
End If
Next vbComp
Debug.Print “========================================================”
Debug.Print ” 解析完了. ヒット件数: ” & matchCount & ” 件”
Debug.Print “========================================================”
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ ==============================================================================
‘ 補助関数: VBComponentのタイプを人間が読める文字列に変換
‘ ==============================================================================
Private Function GetComponentTypeString(ByVal compType As Long) As String
Select Case compType
Case 1: GetComponentTypeString = “標準モジュール” ‘ vbext_ct_StdModule
Case 2: GetComponentTypeString = “クラスモジュール” ‘ vbext_ct_ClassModule
Case 3: GetComponentTypeString = “フォーム” ‘ vbext_ct_MSForm (Accessでは主にフォーム/レポートの裏側)
Case 100: GetComponentTypeString = “Document(F/R等)” ‘ vbext_ct_Document
Case Else: GetComponentTypeString = “不明(” & compType & “)”
End Select
End Function
—
4. このコードのアーキテクチャ的解説と実務での活用法
ただコードを貼るだけではない。プロのエンジニアとして、このコードがなぜ堅牢であるかを解説しよう。
1. `vbComp.CodeModule` の採用理由
`CurrentProject.AllModules` は確かに便利だが、扱えるのはテキストベースのモジュール限定だ。一方、上記の `Application.VBE.ActiveVBProject.VBComponents` を経由する手法は、Accessのフォームやレポートに紐付くイベントコード(`vbext_ct_Document`)の領域まで完全にスコープに収める。これこそが、網羅的解析を可能にする最大の肝である。
2. インメモリでの高速走査とI/O削減
このスクリプトは、ディスク上のファイルを何度も開け閉めするような低効率な処理を一切行わない。すべてVBEのメモリ上のオブジェクトに対して直接インデックスアクセス(`CodeModule.Lines`)を行っているため、数万行規模のプロジェクトであっても数秒で走査が完了する。
3. 実務への応用:テーブルへの出力とレポート化
上記のサンプルではイミディエイトウィンドウに出力しているが、実務の現場ではこれをローカルの解析用一時テーブルにINSERTしていく形に拡張するとさらに強力だ。
- 検出日時
- モジュール名
- モジュール種別
- 該当行番号
- コード内容
このテーブルを元に「影響範囲チェックシート」を自動生成するレポートを組めば、クライアントや監査法人への提出物としてもそのまま活用できる。
—
5. おわりに:チーフアーキテクトからのメッセージ
Accessは「誰でも簡単に作れる」がゆえに、「誰も保守できない負債の温床」になりやすいデータベースだ。しかし、それはツール自体の罪ではなく、開発者の設計リテラシーの欠如に起因する。
今回紹介したVBEオブジェクトモデルを活用した動的解析手法は、あなたの開発スタイルを「勘と根性の保守」から「ロジカルかつ科学的なエンジニアリング」へとシフトさせる強力な武器となるはずだ。
コードに支配されるな。コードを支配しろ。あなたの手元のAccessデータベースが、真に堅牢なシステムへと生まれ変わることを期待している。
