【入門編】Application.VBEオブジェクトを用いた、モジュール内のプロシージャ名一括取得とドキュメント化 – Access VBA解析バイブル

スポンサーリンク

こんにちは! Access VBAの奥深い世界へようこそ。チーフアーキテクトの私です。

これまでマクロの記録ボタンを押すだけだったり、ネットで見つけたコードをなんとなくコピペして動かしたりしていませんか?「動くには動くけれど、裏側で何が起きているのか分からない……」そんなモヤモヤを抱えているあなたへ。

今回は、Access VBAの真骨頂である「VBE(Visual Basic Editor)の裏側をプログラムから直接のぞき見する」という、ちょっと魔法のようなテクニックを伝授します。

ここをクリアすれば、あなたは単なる「Accessの利用者」から、システムを意のままに操る「エンジニア」へと一歩踏み出せますよ。さあ、一緒に扉を開けましょう!

1. なぜ「モジュール内のプロシージャ名」を自動取得するのか?

皆さんは、こんな経験はありませんか?

  • 「このAccessファイル、作った人は別の人だけど、中にどんな関数(SubやFunction)が入っているのか一覧が欲しい……」
  • 「社内の引き継ぎ用に、機能仕様書を作れって言われたけれど、コードを1行ずつ読んで手作業でリストアップするなんて気が遠くなる……」

数百行、数千行のコードを人間が目で追ってまとめるのは、まさに苦行です。
しかし、考えてみてください。「VBAのコードを書くためのVBE自体も、実はAccessのオブジェクト(部品)の一つ」なのです。

ということは、「Access VBAを使って、自分自身のコード(VBE)を読みに行けばいい」のですね。これをマスターすれば、ボタンを1回ポチッと押すだけで、モジュールの中にあるプロシージャ(SubやFunction)の名前を自動で全自動収集し、テーブルに出力するドキュメント自動化ツールが作れます。

2. 魔法の鍵:`Application.VBE` との出会い

まずは、Accessの根幹を支える `Application` オブジェクトと、VBEの世界を繋ぐ扉について知る必要があります。

通常、私たちが触るフォームやクエリは `CurrentDb` 経由で操作しますが、「VBAのコードそのもの」や「モジュール」を操作したいときは、`Application.VBE`(Visual Basic for Applications Environment)を使います。

ただし、ここで一つだけ最大の関門(初心者が必ずつまずくトラップ)があります。
デフォルトのままでは、Accessはセキュリティの観点から「プログラムが自分自身のコードを勝手に見たり書き換えたりすること」を禁止しています。

⚠️ 避けて通れない!最初に行うべき重要設定

このコードを動かす前に、必ず以下の設定を行ってください。これをしていないと、「オブジェクトはサポートされていません」というエラーで撃墜されます。

1. AccessのVBE画面([Alt] + [F11])を開く。
2. メニューの [ツール] > [オプション] をクリック。
3. [信頼性] タブ(または [セキュリティ] タブ)を開く。
4. 「Visual Basic プロジェクトへのアクセスを信頼する」 にチェックを入れる。

※ここをクリアすれば、準備はバッチリです!

3. 実装:プロシージャ名一括取得の全コード

お待たせしました。ここからが本番です。
以下のコードを、標準モジュールにそのまま貼り付けてみてください。

このコードは、現在開いているAccessファイル(`CurrentProject`)の中にあるすべての標準モジュールを巡回し、中にある `Sub` や `Function` の名前を根こそぎ拾い上げてイミディエイトウィンドウに出力する、精鋭のプログラムです。

Option Compare Database
Option Explicit

‘ =========================================================================
‘ 処理名 : 既存モジュールからプロシージャ名を自動列挙する
‘ 概要 : Application.VBE を用いて、VBAプロジェクト内の全プロシージャを解析する
‘ =========================================================================
sub GetProcedureListFromVBE()

‘ 1. 変数の宣言(VBE関連のオブジェクトを網羅)
Dim vbProj As Object ‘ VBProject (VBAプロジェクト全体)
Dim vbComp As Object ‘ VBComponent (標準モジュールやフォームなど個別の部品)
Dim codeMod As Object ‘ CodeModule (モジュール内のコード実体)

Dim i As Long ‘ 行カウンタ
Dim lineText As String ‘ 読み込んだ1行のコード
Dim firstProcLine As Long ‘ プロシージャの開始行
Dim procName As String ‘ 抽出したプロシージャ名

‘ 2. 現在のAccessプロジェクトのVBE情報を取得
‘ ※注意: 事前に「Visual Basic プロジェクトへのアクセスを信頼する」にチェックが必要です
Set vbProj = Application.VBE.ActiveVBProject

Debug.Print “=== [解析開始] プロシージャ名一覧の抽出 ===”

‘ 3. プロジェクト内の全コンポーネント(モジュール等)をループ処理
For Each vbComp In vbProj.VBComponents

‘ 標準モジュール(vbext_ct_StdModule = 1)だけに絞り込む
‘ ※フォームやレポートのモジュールを除外する場合のフィルター
If vbComp.Type = 1 Then

Set codeMod = vbComp.CodeModule
Debug.Print vbCrLf & “【モジュール名: ” & vbComp.Name & “】”

i = 1
‘ 4. モジュールの1行目から最終行までをスキャン
Do While i <= codeMod.CountOfLines ' 5. プロシージャの先頭行かどうかを判定する魔法のメソッド ' ProcOfLine は、指定した行がどのプロシージャに属しているか、 ' またそのプロシージャが何行目から始まるかを教えてくれます。 procName = codeMod.ProcOfLine(i, 0) ' 0 = vbext_pk_Proc (プロシージャ全体) ' プロシージャ名が存在し、かつ、それが「ちょうどそのプロシージャの開始行」である場合 If procName <> “” Then
firstProcLine = codeMod.ProcStartLine(procName, 0)

‘ 同じプロシージャ名で何度も出力されないよう、開始行が一致した瞬間だけキャッチする
If i = firstProcLine Then
‘ プロシージャの種類(Sub なのか Function なのか)を判定して出力
Debug.Print ” └ プロシージャ名: ” & procName & ” (開始行: ” & firstProcLine & “行目)”
End If
End If

‘ 次のプロシージャの開始位置へ一気にジャンプ(無駄なループをスキップして高速化)
If procName <> “” Then
i = codeMod.ProcStartLine(procName, 0) + codeMod.ProcCountLines(procName, 0)
Else
i = i + 1
End If

Loop

End If

Next vbComp

Debug.Print vbCrLf & “=== [解析終了] すべての処理が完了しました ===”

‘ 7. オブジェクトの解放(メモリ管理の基本)
Set codeMod = Nothing
Set vbComp = Nothing
Set vbProj = Nothing

End Sub

4. コードの解説:ここがエンジニアの急所!

初心者の方には少し見慣れないメソッドが出てきたので、重要なポイントを噛み砕いて解説します。

① `vbComp.Type = 1` の意味

AccessのVBAプロジェクトの中には、標準モジュールだけでなく、フォームの裏にあるコードや、レポート、クラスモジュールなど、様々な「箱」が混ざっています。
今回は「純粋なプログラムの関数一覧」が欲しいので、`Type = 1`(標準モジュールを表す定数 `vbext_ct_StdModule`)だけにターゲットを絞っています。

② `codeMod.ProcOfLine` と `ProcStartLine` の連携プレイ

これが今回の最も美しいアルゴリズムです。

  • `ProcOfLine(i, 0)` は、「今、何行目を読んでる? そこに含まれるプロシージャの名前は何?」を答えてくれます。
  • しかし、これだけだと同じプロシージャ内の行をループしている間中、何度も同じ名前がヒットしてしまいます。
  • そこで `ProcStartLine` を使い、「このプロシージャが本当に始まる最初の行」と、現在の行(`i`)が一致した瞬間だけを捉えることで、重複のない美しいリスト化を実現しています。

さらに、プロシージャを検出した後は、そのプロシージャの終わりまで一気に `i` のカウンターを進めています(`i = codeMod.ProcStartLine(…) + codeMod.ProcCountLines(…)`)。
これにより、コードが何万行あっても一瞬で処理が終わる、極限まで無駄を削ぎ落とした高速化を実現しています。これぞプロの技です。

5. 現場でありがちな「ハマりポイント」と対策

最後に、このコードやVBE操作を実務で使うときによくあるトラブルシューティングをご紹介します。

  • Q. 「コンパイルエラー: ユーザー定義型は定義されていません」と言われる
  • A. コードの最初で `As Object` を使っているので基本は起きませんが、もし `VBProject` などを直接型指定している場合は、VBEのツール > 参照設定 から「Microsoft Visual Basic for Applications Extensibility 5.3」にチェックが入っているか確認してください。`As Object`(後期バインディング)にしておけば、この参照設定すら不要になり、環境を選ばないのでオススメです。
  • Q. 実行しても何も出力されない
  • A. 解析対象のAccessファイルの中に「標準モジュール」が1つも作成されていない可能性があります。まずは標準モジュールを1つ追加し、適当な `Sub Test()` を書いてから実行してみてください。

おわりに

お疲れ様でした!
今回は、Access VBAの裏側にある `Application.VBE` を使って、モジュール内のプロシージャを自動列挙する高度な手法を解説しました。

「VBAでVBAのコードを読み解く」という感覚、少しワクワクしませんか?
この技術を応用すれば、自分が書いたコードの行数を自動集計したり、特定のキーワードが含まれるプロシージャを自動で探す「社内用コードチェッカー」なども作れるようになります。

ここをクリアしたあなたなら、もうAccess VBAの基礎はバッチリです。ぜひ自分の環境で試して、黒いイミディエイトウィンドウに美しく並ぶプロシージャ名を確認してみてくださいね。それでは、次のステップでお会いしましょう!

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