【上級】DAO.Database.CreatePropertyを用いたカスタムデータベースプロパティの保存と取得
こんにちは!日々の業務自動化やシステム開発、本当にお疲れ様です。
Access VBAの世界へようこそ。マクロの自動記録から一歩踏み出し、VBAのコードを使ってAccessを思い通りに制御できるようになってくると、「設定値やバージョン情報をどこに保存すべきか?」という壁に必ずぶつかります。
「設定保存用の専用テーブルを作るべき?」「レジストリ?」「テキストファイル?」……実は、Accessファイル(.accdb)そのものにオリジナルの隠しプロパティを埋め込む最高にスマートな方法が存在します。それが、今回解説する`DAO.Database.CreateProperty` を用いたカスタムプロパティ管理です。
一見すると上級者向けに見えますが、仕組みさえ理解すれば非常にシンプルです。ここをクリアすれば、Access VBAの基本とオブジェクトモデルの理解はバッチリですよ!一緒に本質を学んでいきましょう。
—
1. カスタムデータベースプロパティとは?(図解的アプローチ)
Accessファイルには、標準で「ファイル名」や「作成日時」などのプロパティが存在します。しかし、DAO(Data Access Objects)を利用すると、開発者が独自のプロパティ(名前と値のペア)を追加できます。
イメージとしては、「Accessファイルというノートの裏表紙の内側に、自分専用の秘密のメモ書き欄を作る」ようなものです。
【Accessファイル (.accdb)】
├── テーブル
├── フォーム
├── モジュール
└── データベースプロパティ (Properties)
├── 標準プロパティ(Title, Author など)
└── ★カスタムプロパティ(あなたが自由に追加!)
├── “AppVersion” = “1.2.0”
├── “IsDebugMode” = True
└── “LastSyncDate” = “2023/10/25”
なぜ設定テーブルや外部ファイルより優れているのか?
1. 外部ファイル不要: 設定用の`.ini`ファイルや`.json`ファイルを別途配付する必要がありません。
2. テーブルを汚さない: ユーザーが誤って削除してしまうリスクのある「設定テーブル」を作らずに済みます。
3. ファイルと一体管理: データベースファイルをコピーすれば、設定値もそのまま一緒に移動します。
—
2. 押さえておきたいDAOオブジェクトモデルの基本構造
コードを書く前に、背景にある「オブジェクトの仕組み」を頭に入れておきましょう。
Access VBAでデータベースそのものを操作するとき、核となるのが `DAO.Database` オブジェクトです。
- `CurrentDb()` : 現在開いているデータベースを参照する関数。
- `Properties` コレクション : データベースが保持しているプロパティのリスト。
- `CreateProperty` メソッド : 新しいプロパティオブジェクト(`DAO.Property`)をメモリ上に生成する命令。
ここで多くの開発者が躓くポイントが一つあります。それは、「生成しただけでは保存されない」という点です。
1. CreateProperty でプロパティを作る(メモリ上に浮いている状態)
2. Properties.Append でデータベースにガチャンと結合する(これで永続保存!)
この「作ってから追加する(Append)」という2段階のプロセスが、DAO操作の美しくも重要なルールです。
—
3. 実践!カスタムプロパティを安全に読み書きする汎用モジュール
それでは、現場でそのまま使える信頼性の高いVBAコードを作成しましょう。
プロパティ操作で最も頻出するトラブルは、「まだ存在しないプロパティを読み込もうとしてエラーになる(エラーコード 3265: アイテムが見つかりません)」ことです。
このエラーを華麗に交わし、存在しなければ自動生成し、存在すれば更新する堅牢な汎用関数を定義します。
標準モジュールを作成し、以下のコードを貼り付けてみてください。
Option Explicit
‘ ==============================================================================
‘ モジュール名: mod_DbProperties
‘ 概要: データベース自体にカスタムプロパティを安全に読み書きするモジュール
‘ ==============================================================================
”’
”’ 存在しない場合は新規作成し、存在する場合は値を更新します。
”’
”’ プロパティ名
”’ 設定する値
”’ データ型(省略時は文字列型: dbText)
Public Sub SetDbProperty(ByVal PropName As String, _
ByVal PropValue As Variant, _
Optional ByVal PropType As DAO.DataTypeEnum = dbText)
Dim db As DAO.Database
Dim prp As DAO.Property
‘ CurrentDbオブジェクトの参照を取得
‘ ※CurrentDbを直接何度も呼ぶと毎回インスタンスが生成されるため、変数に保持するのがプロの鉄則です
Set db = CurrentDb()
On Error Resume Next
‘ まずは既存のプロパティを取得してみる
Set prp = db.Properties(PropName)
On Error GoTo 0
If prp Is Nothing Then
‘ ———————————————————————-
‘ 【存在しない場合】新規作成して追加する
‘ ———————————————————————-
‘ 1. プロパティオブジェクトを生成
Set prp = db.CreateProperty(PropName, PropType, PropValue)
‘ 2. データベースのPropertiesコレクションに追加(これで永続化)
db.Properties.Append prp
Else
‘ ———————————————————————-
‘ 【存在する場合】既存のプロパティの値を更新する
‘ ———————————————————————-
prp.Value = PropValue
End If
‘ メモリの明示的解放(オブジェクトのライフサイクルを意識する)
Set prp = Nothing
Set db = Nothing
End Sub
”’
”’ プロパティが存在しない場合は、指定された初期値(DefaultValue)を返します。
”’
”’ プロパティ名
”’ プロパティが存在しない場合の戻り値
”’
Public Function GetDbProperty(ByVal PropName As String, _
Optional ByVal DefaultValue As Variant = Null) As Variant
Dim db As DAO.Database
Dim prp As DAO.Property
Dim result As Variant
Set db = CurrentDb()
On Error Resume Next
‘ プロパティの取得を試みる(存在しない場合はエラー3265が発生するがResume Nextで回避)
Set prp = db.Properties(PropName)
On Error GoTo 0
If prp Is Nothing Then
‘ 存在しない場合はデフォルト値を返す
result = DefaultValue
Else
‘ 存在する場合はその値を返す
result = prp.Value
End If
GetDbProperty = result
‘ メモリの明示的解放
Set prp = Nothing
Set db = Nothing
End Function
—
4. 実際の使い方と動作確認
上記のモジュールを実装したら、イミディエイトウィンドウやテスト用プロシージャで動かしてみましょう!
実行コード例
Public Sub Test_CustomProperties()
‘ 1. アプリケーションのバージョン情報を保存(文字列型)
Call SetDbProperty(“AppVersion”, “2.1.0”, dbText)
‘ 2. メンテナンスモードフラグを保存(ブール型)
Call SetDbProperty(“IsMaintenanceMode”, True, dbBoolean)
‘ 3. 最終更新日時を保存(日付型)
Call SetDbProperty(“LastUpdate”, Now(), dbDate)
‘ — 取得してデバッグ表示してみる —
Debug.Print “=== 保存されたプロパティの確認 ===”
Debug.Print “バージョン: ” & GetDbProperty(“AppVersion”)
Debug.Print “メンテモード: ” & GetDbProperty(“IsMaintenanceMode”)
Debug.Print “最終更新日: ” & GetDbProperty(“LastUpdate”)
‘ 存在しないプロパティを取得しようとした場合(デフォルト値が返る)
Debug.Print “未定義設定: ” & GetDbProperty(“NonExistingKey”, “設定なし”)
End Sub
出力結果(イミディエイトウィンドウ)
=== 保存されたプロパティの確認 ===
バージョン: 2.1.0
メンテモード: True
最終更新日: 2023/10/25 14:30:00
未定義設定: 設定なし
外部ファイルを使わずに、Accessファイル自体にデータがピッタリ保存されましたね!
—
5. 初心者がハマりがちな3つの罠と「チーフアーキテクトの知恵」
実務で活用するにあたり、落とし穴になりやすいポイントを先輩エンジニアとしてアドバイスしておきます。
罠①:エラー `3265`(アイテムが見つかりません)でプログラムが止まる
DAOの `Properties` コレクションは、存在しないプロパティ名を指定すると即座にランタイムエラーを起こします。
今回紹介したコードのように、`On Error Resume Next` を局所的に使い、取得できたかどうか(`If prp Is Nothing`)をチェックするガード節を入れるのが鉄則です。
罠②:`CurrentDb` の無駄遣いによるパフォーマンス低下
VBAの初心者がよくやってしまうのが、以下のような書き方です。
‘ ✕ 悪い例:CurrentDbを毎回呼び出している
CurrentDb.CreateProperty(…)
CurrentDb.Properties.Append …
`CurrentDb` を呼び出すたびに、Access内部ではデータベース構造の新しいインスタンス(複製)が作成され、大きなコストがかかります。必ず `Dim db As DAO.Database : Set db = CurrentDb()` と変数に一度受けてから操作しましょう。
罠③:データ型(`DataTypeEnum`)の指定ミス
`CreateProperty` の第2引数には、適切な型(`dbText`, `dbInteger`, `dbBoolean`, `dbDate` など)を指定してください。一度作成したプロパティのデータ型は後から変更できません。型を変更したい場合は、一度 `db.Properties.Delete(“プロパティ名”)` で削除してから再作成する必要があります。
—
6. まとめ:一歩先を行くAccessエンジニアへ
お疲れ様でした!今回の内容を振り返ってみましょう。
1. カスタムプロパティを使えば、Accessファイルの中に直接設定値を保持できる。
2. 作成には `CreateProperty` で生成し、`Properties.Append` で追加 する2ステップが必要。
3. エラー `3265` に備え、安全な読み書き用の共通関数(カプセル化) を通して操作するのがベストプラクティス。
テーブルを増やさず、ファイル単体で美しく設定を完結させるこの手法は、社内ツールのバージョン管理(「新しいフロントエンドファイルに更新してください」という通知判定など)に絶大な効果を発揮します。
これが理解できれば、Access VBAのオブジェクトモデル(`Application` ➔ `Database` ➔ `Properties`)の階層構造がしっかり身についた証拠です。基本はバッチリですよ!
自信を持って、あなたのプロジェクトに組み込んでみてくださいね。応援しています!
