【実務・中級編】Application.VBEオブジェクトで「モジュール内のコード」を検索・置換するリファクタリング支援ツール – Access VBA解析バイブル

スポンサーリンク

【Access VBA極限活用】VBEオブジェクトを完全掌握する:モジュール自動リファクタリングツールの設計と実装

開発プロジェクトが終盤に差し掛かったとき、あるいはレガシーな巨大Accessデータベースの保守を引き継いだとき、こんな絶望感を味わったことはないだろうか。

「共通関数の命名規則を変更したいが、数十個ある標準モジュール、クラスモジュール、フォームのコードビハインドから、該当のメソッド名をすべて手作業で置換して回るのか……?」

Access標準の「置換」機能(Ctrl + F)は、現在のモジュール内か、せいぜい「現在のプロジェクト全体」を対象にするものの、意図しない箇所まで巻き込んで誤爆したり、置換前後のログが残らなかったりと、実務の現場で使うにはあまりにも脆弱だ。

世界最高峰の業務自動化を志すエンジニアであれば、手作業という名の泥臭い労働はコードで駆逐すべきだ。
今回は、Accessの心臓部である `Application.VBE` (Visual Basic for Applications) オブジェクトモデル を直接叩き、安全かつ確実にコードの検索・一括置換を行う「リファクタリング支援ツール」の全貌を伝授する。

1. なぜ「VBEオブジェクト」の操作は敬遠されるのか?

VBEオブジェクトモデル(`VBProject`, `VBComponent`, `CodeModule`)を操作するコードは、ネット上のサンプルコードでも断片的なものが多く、「動かすと突然Accessがクラッシュする」「変数が消えた」「参照設定でエラーになる」といったトラウマを持つ開発者が後を絶たない。

原因は明確だ。彼らは「VBEのライフサイクル」と「メモリ上のコードコンテナの重み」を理解していないからだ。

押さえるべき設計の鉄則

1. 「信頼できる場所」への登録が必須
VBEオブジェクトを操作するコードを実行するには、Accessのセキュリティセンターで「VBA プロジェクト オブジェクト モデルへのアクセスを信頼する」にチェックが入っていなければならない。これを前提としたツール配布の動線設計が必要だ。
2. Undo(元に戻す)は効かない
VBEの `CodeModule` に対する書き換えは、一瞬で物理ファイル(またはデータベース内のバイナリ)に反映される。Ctrl + Zは通用しない。だからこそ、完全なトランザクション的思考(事前のバックアップと厳密なバリデーション)が求められる。
3. 不要なモジュールロードの回避
すべてのフォームやレポートを開いた状態でVBEを操作すると、メモリリークやコンテキストの競合を引き起こす。バックグラウンドで安全にイテレーションを回す設計が不可欠だ。

2. 堅牢なリファクタリングツールのアーキテクチャ

今回作成するツールは、指定したキーワードをプロジェクト全体のすべてのモジュール(標準・クラス・フォーム・レポート)から探し出し、安全に置換を行うエンジンだ。

実装のポイント

  • 対象の全網羅: `VBProject.VBComponents` を走査し、モジュールの種類(`vbext_ct_StdModule`, `vbext_ct_ClassModule`, `vbext_ct_Document` 等)を識別する。
  • 正確な行単位の置換: 単なる文字列置換ではなく、`CodeModule` の行操作(`Lines`, `ReplaceLine`)を使い、構文の整合性を保つ。
  • 安全装置(ログ出力と確認モード): 実際に置換を行う前に「どこがどう変わるのか」をイミディエイトウィンドウ、あるいは専用のログテーブルに出力する。

3. 【プロダクションコード】VBE自動リファクタリング・エンジン

以下のコードを、管理用のAccessファイル(ツール本体)の標準モジュールにそのまま貼り付けてほしい。
※実行前に、VBEのツールメニューから「参照設定」を開き、「Microsoft Visual Basic for Applications Extensibility 5.3」 にチェックを入れておくこと。

Option Compare Database
Option Explicit

‘ =========================================================================
‘ 模範的VBEリファクタリング支援エンジン
‘ Author: Chief Architecture Engineer
‘ Description: Accessプロジェクト内の全モジュールを走査し、キーワードを安全に置換する
‘ =========================================================================

Public Sub ExecuteRefactoringTool()
‘ — 設定エリア —
Const TARGET_KEYWORD As String = “OldFunctionName” ‘ 検索する文字列
Const REPLACE_KEYWORD As String = “NewFunctionName” ‘ 置換後の文字列
Const IS_SIMULATION As Boolean = True ‘ Trueの場合、置換を行わずログ出力のみ(安全装置)
‘ —————-

Dim vbProj As VBIDE.VBProject
Dim vbComp As VBIDE.VBComponent
Dim codeMod As VBIDE.CodeModule

Dim totalReplacedCount As Long
Dim moduleCount As Long

‘ 現在のデータベースのVBProjectを取得
On Error GoTo ErrorHandler
Set vbProj = Application.VBE.ActiveVBProject

If vbProj Is Nothing Then
MsgBox “アクティブなVBProjectを取得できませんでした。”, vbCritical, “致命的エラー”
Exit Sub
End If

totalReplacedCount = 0
moduleCount = 0

Debug.Print “=== リファクタリング・セッション開始 ===”
Debug.Print “対象キーワード: ” & TARGET_KEYWORD
Debug.Print “置換キーワード: ” & REPLACE_KEYWORD
Debug.Print “シミュレーションモード: ” & IIf(IS_SIMULATION, “ON (書き換えません)”, “OFF (実実行)”)
Debug.Print “————————————————–”

‘ プロジェクト内の全コンポーネントを走査
For Each vbComp In vbProj.VBComponents
Set codeMod = vbComp.CodeModule

If codeMod.CountOfLines > 0 Then
moduleCount = moduleCount + 1
Dim replacedInThisModule As Long

‘ 各モジュール内の置換処理を実行
replacedInThisModule = ProcessModule(codeMod, vbComp.Name, TARGET_KEYWORD, REPLACE_KEYWORD, IS_SIMULATION)
totalReplacedCount = totalReplacedCount + replacedInThisModule
End If
Next vbComp

Debug.Print “————————————————–”
Debug.Print “=== セッション終了 ===”
Debug.Print “走査モジュール数: ” & moduleCount
Debug.Print “総置換箇所数: ” & totalReplacedCount & IIf(IS_SIMULATION, ” (シミュレーション)”, ” (適用済み)”)

If IS_SIMULATION Then
MsgBox “シミュレーションが完了しました。イミディエイトウィンドウを確認してください。”, vbInformation, “完了”
Else
MsgBox “リファクタリングが正常に完了しました!総置換数: ” & totalReplacedCount, vbInformation, “完了”
End If

Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub

‘ =========================================================================
‘ 個別モジュールのコード解析と置換処理
‘ =========================================================================
Private Function ProcessModule(ByRef codeMod As VBIDE.CodeModule, _
ByVal moduleName As String, _
ByVal target As String, _
ByVal rep As String, _
ByVal isSim As Boolean) As Long

Dim i As Long
Dim lineText As String
Dim count As Long
Dim firstLine As Long, numLines As Long

count = 0

‘ 1行目から最終行までループ
For i = 1 To codeMod.CountOfLines
lineText = codeMod.Lines(i, 1)

‘ 大文字小文字を区別せず、かつ完全一致に近い形で検索(必要に応じてInStrなどを調整)
If InStr(1, lineText, target, vbTextCompare) > 0 Then

‘ 変更前のログ
Debug.Print “[” & moduleName & “] Line ” & i & ” 検出:”
Debug.Print ” 旧: ” & lineText

‘ 文字列置換の実行(VBA.Replaceを使用)
‘ ※ 単語境界を厳密に判定したい場合は正規表現(RegExp)をここに組み込む
Dim newLineText As String
newLineText = Replace(lineText, target, rep, 1, -1, vbTextCompare)

Debug.Print ” 新: ” & newLineText

If Not isSim Then
‘ 実際にコードを書き換える
codeMod.ReplaceLine i, newLineText
End If

count = count + 1
End If
Next i

ProcessModule = count
End Function

4. チーフアーキテクトが教える、現場で失敗しないための「極意」

上記のコードをそのまま現場に投入するにあたり、プロの視点からさらに堅牢性を高めるためのアドバイスを授けよう。

1. 「単語境界」を考慮した正規表現への拡張

上記のコードは `Replace` 関数による単純な部分一致置換を行っている。もし `GetUser()` という関数を `User()` に置換したい場合、変数名である `pOldUser` まで `pOldUser()` に変わってしまう「誤爆事故」が起きうる。
本番運用では、VBScriptの正規表現オブジェクト (`VBScript.RegExp`) を併用し、単語境界(`\b`)を指定した置換ロジックへアップグレードすることを強く推奨する。

2. バックアップの自動化をコードに組み込む

VBEを操作するツールの冒頭には、必ず以下のバックアップ処理を走らせるべきだ。

‘ 実行前にカレントDBのコピーを自動生成するスニペット
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim srcPath As String, backupPath As String
srcPath = CurrentDb.Name
backupPath = Left(srcPath, InStrRev(srcPath, “.”) – 1) & “_backup_” & Format(Now, “yyyymmddHHMMSS”) & “.accdb”
fso.CopyFile srcPath, backupPath, True

この3行を仕込んでおくだけで、万が一のロジックミスによるデータ破損から完全に身を守ることができる。これがプロとアマの決定的な違いだ。

3. フォームのイベントプロシージャに潜む罠

Accessのフォームやレポート(ドキュメントモジュール)のコードビハインドは、UIの設計変更と密結合している。
モジュール内のメソッド名を置換したあと、フォーム上のコントロール(ボタンのクリック時イベントなど)のプロパティに記述されている関数名がそのままだと、イベントがロストする。
リファクタリングを行う際は、「コード側の置換」だけでなく「コントロールのイベントプロパティ名」の整合性も同時に検証する仕組みを視野に入れる必要がある。

総括

Access VBAにおけるVBEオブジェクトの操作は、諸刃の剣である。
しかし、その仕組みを正しく理解し、安全装置(シミュレーションモードや自動バックアップ)を設けた上でアーキテクチャに組み込めば、手作業によるヒューマンエラーをゼロにし、開発・保守工数を劇的に圧縮する最強の武器となる。

「面倒な作業は、すべてコードに踊らせる」。
この思想をあなたの開発プロジェクトにもインストールし、真のエンジニアリングの効率化を体感してほしい。

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