【Access VBAを掌握する極限の知見】CurrentDb.Properties極限活用:起動時設定の動的制御による堅牢な環境スイッチング
開発プロジェクトの現場で、こんな不毛な作業に時間を奪われていないだろうか。
「開発環境ではテスト用フォームを起動させ、本番環境ではメインメニューを立ち上げる。そのために、毎回Accessのオプション画面を開いて『起動時のフォーム』を手動でポチポチ切り替えている」
「クライアントに配布するMDB/ACCDBファイルごとに、配布先に応じたカスタムリボンやメニューバーの制御を自動化したい」
素人はこれを手作業で行う。あるいは、環境ごとに別々のアプリケーションファイルを用意して管理という名の爆弾を抱え込む。
しかし、プロのアーキテクトは違う。我々は「コードでデータベースのプロパティを支配する」。
今回は、`CurrentDb.Properties`を駆使し、アプリケーションの起動時設定を動的にコントロールする極限のテクニックを伝授する。オブジェクトのライフサイクルとAccessの内部構造を理解していれば、環境の切り替えなど一瞬で、かつ完全にバグフリーで実現できるのだ。
—
1. なぜ「手動設定」と「安易なCurrentDb」は地雷なのか
まず、Accessのプロパティ構造の闇を理解しておこう。
Accessのデータベースプロパティ(`StartupForm`や`StartupShowStatusBar`など)は、最初からすべてのプロパティが存在しているわけではない。
開発者が一度もGUIから設定を変更していないプロパティは、システム内部のコレクションに存在すらしない。
ここに素人が書いたダメなコードの例がある。
‘ 【アンチパターン】存在しないプロパティに直接アクセスして爆死する例
Sub SetStartupForm_Bad(formName As String)
‘ プロパティが未作成の場合、ここで実行時エラー 3270「プロパティが見つかりません」が発生する
CurrentDb.Properties(“StartupForm”) = formName
End Sub
エラーハンドリングで逃げるか、GUIであらかじめ空設定を入れておく……?
プロの開発者として、そんな泥臭いアプローチは言語道断だ。正解は、「プロパティが存在しなければ、その場で動的に生成し、存在すれば値を書き換える」という防御的設計(Defensive Design)を徹底することである。
さらに、`CurrentDb`関数の挙動の重みを知る者であれば、ループ内で何度も`CurrentDb`を呼び出す愚行は犯さない。`CurrentDb`は呼び出すたびに新しいDAOのデータベースオブジェクトを生成する。参照を適切に変数に保持し、ライフサイクルを管理するのがプロの作法だ。
—
2. 堅牢性極まるプロダクションコード:動的プロパティ・マネージャー
以下のコードは、実務の現場でそのまま使える、堅牢性と保守性を極限まで高めたプロパティ操作のユーティリティモジュールだ。
エラーハンドリング、プロパティの有無の判定と自動生成(`CreateProperty`)、そして変更の即時反映まで完璧に網羅している。
Option Compare Database
Option Explicit
‘ =========================================================================
‘ モジュール名: modStartupManager
‘ 概要 : データベースの起動時プロパティを動的に制御するクラス/モジュール
‘ 著作権表記: © 202X Enterprise Architecture Lab.
‘ =========================================================================
‘ DAOプロパティのデータ型定数(Type Enumのローカル定義)
Private Const DB_TEXT As Long = 10
Private Const DB_BOOLEAN As Long = 1
Private Const DB_INTEGER As Long = 3
/
- 指定したデータベースプロパティを設定(存在しない場合は自動生成)
- @param propName 設定するプロパティ名 (例: “StartupForm”)
- @param propType DAOのデータ型 (DB_TEXT, DB_BOOLEAN 等)
- @param propValue 設定する値
/
Public Sub SetDatabaseProperty(ByVal propName As String, ByVal propType As Long, ByVal propValue As Variant)
Dim dbs As DAO.Database
Dim prp As DAO.Property
Dim isPropertyExists As Boolean
On Error GoTo ErrorHandler
‘ CurrentDbは毎回生成されるため、必ず変数に格納してオーバーヘッドを防ぐ
Set dbs = CurrentDb
isPropertyExists = False
‘ プロパティの存在確認
For Each prp In dbs.Properties
If prp.Name = propName Then
isPropertyExists = True
Exit For
End If
Next prp
If isPropertyExists Then
‘ 存在する場合は値を更新
dbs.Properties(propName).Value = propValue
Else
‘ 存在しない場合は新規作成して追加
Set prp = dbs.CreateProperty(propName, propType, propValue)
dbs.Properties.Append prp
End If
Debug.Print “[Success] プロパティ ‘” & propName & “‘ を ‘” & propValue & “‘ に設定しました。”
GoTo Finally
ErrorHandler:
MsgBox “プロパティの設定中に予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “システムエラー”
Finally:
‘ オブジェクトの明示的な解放(メモリリーク防止)
Set prp = Nothing
Set dbs = Nothing
End Sub
/
- 実行環境(開発/本番)に応じて起動時設定を自動スイッチングする例
- ※Autoexecマクロやスプラッシュフォームから呼び出すことを想定
/
Public Sub SwitchEnvironmentSettings(ByVal isProduction As Boolean)
On Error GoTo ErrorHandler
If isProduction = True then
‘ — 本番環境向け設定 —
Call SetDatabaseProperty(“StartupForm”, DB_TEXT, “frmMainDashboard”) ; メインメニュー
Call SetDatabaseProperty(“StartupShowDBWindow”, DB_BOOLEAN, False) ; ナビゲーションウィンドウ非表示
Call SetDatabaseProperty(“StartupShowStatusBar”, DB_BOOLEAN, True) ; ステータスバー表示
Call SetDatabaseProperty(“AllowBuiltinToolbars”, DB_BOOLEAN, True) ; 組み込みツールバー制限(必要に応じてFalse)
Call SetDatabaseProperty(“AllowFullMenus”, DB_BOOLEAN, False) ; フルメニュー禁止
Call SetDatabaseProperty(“AllowShortcutMenus”, DB_BOOLEAN, True) ; ショートカットメニュー
Else
‘ — 開発・デバッグ環境向け設定 —
Call SetDatabaseProperty(“StartupForm”, DB_TEXT, “frmDevControlPanel”) ; 開発用コンソール
Call SetDatabaseProperty(“StartupShowDBWindow”, DB_BOOLEAN, True) ; ナビゲーションウィンドウ表示
Call SetDatabaseProperty(“StartupShowStatusBar”, DB_BOOLEAN, True) ; ステータスバー表示
Call SetDatabaseProperty(“AllowBuiltinToolbars”, DB_BOOLEAN, True)
Call SetDatabaseProperty(“AllowFullMenus”, DB_BOOLEAN, True) ; フルメニュー許可
Call SetDatabaseProperty(“AllowShortcutMenus”, DB_BOOLEAN, True)
End If
MsgBox “環境設定の切り替えが完了しました。” & vbCrLf & _
“変更を完全に適用するためには、データベースの再起動が必要です。”, vbInformation, “環境スイッチング完了”
Exit Sub
ErrorHandler:
MsgBox “環境設定の切り替えに失敗しました: ” & Err.Description, vbCritical
End Sub
—
3. 実務で活きるアーキテクチャの要点
このコードとアプローチを導入するにあたり、シニアエンジニアとして押さえておくべき設計思想を解説する。
① 変更の即時反映と「再起動の罠」
Accessの多くの起動時プロパティ(特に `StartupForm` や `StartupShowDBWindow` など)は、データベース起動時に一度だけ評価され、メモリ上にロードされる。
したがって、VBAの実行中にこれらのプロパティを書き換えても、現在稼働中のセッション上では即座にUIが変化しないケースが多い。そのため、上記のコード例のように対話メッセージを挟み、ユーザーに「一度アプリケーションを再起動させる」オペレーションを強制するのが最も確実な設計となる。
② フロントエンドとバックエンドの分離原則(FE/BE分離)
マルチユーザー環境において、この動的プロパティ変更を実行するのは「フロントエンド(ACCDE/ACCDB)」側でなければならない。
テーブルを格納した「バックエンド」側に対して起動時プロパティを設定しても何の意味もない。配布用のフロントエンド生成スクリプト(外部のVBScriptやMaster管理ツール)から、今回紹介したロジックを叩いてビルド自動化パイプラインに組み込むのが、モダンなAccess開発の極みである。
③ DAOライブラリの明示的な参照
Access VBAでは初期状態でDAO(Data Access Objects)が参照設定されていることがほとんどだが、大規模開発や他モジュールとの競合を避けるため、厳密には `Dim dbs As DAO.Database` のように明示的な型宣言(DAOプレフィックス)を付与すべきである。ADOとの混同を防ぎ、コンパイルの安定性を高める。
—
4. 総括
Accessは「おもちゃのデータベース」ではない。設計思想さえ誤らなければ、エンタープライズの現場でも十分に通用する高速なラピッド開発プラットフォームになり得る。
今回紹介した `CurrentDb.Properties` を用いた動的設定制御をマスターすれば、環境ごとの手動設定ミスという無駄なヒューマンエラーを根絶し、デプロイメントの自動化への扉が開かれる。
「なぜ手動でやっているのか?」
――その疑問を持てるかどうかが、プロのエンジニアと、単なるマクロ屋の分かれ道だ。あなたのコードベースを、今日からより堅牢に、よりエレガントにアップデートしてほしい。
