【入門編】【上級】Application.CurrentDbをキャッシュすべき理由:DAO.Database変数の再利用によるパフォーマンス最適化 – Access VBA解析バイブル

スポンサーリンク

こんにちは!日々のAccess開発、本当にお疲れ様です。
マクロの記録から一歩踏み出し、「自分でコードを書いてシステムを動かしたい!」という熱意を持ってVBAに向き合っている姿、素晴らしいですね。

今回は、Access VBAの中級者から上級者への登龍門であり、「知っているか知らないかでアプリのスピードが10倍変わる」超重要テーマをお伝えします。

それが、『`Application.CurrentDb`をキャッシュすべき理由:DAO.Database変数の再利用によるパフォーマンス最適化』です。

なんだか難しそうな名前がついていますが、要は「データベースへの連絡通路を何度も無駄に作り直すな!」というお話です。ここをクリアすれば、あなたの書くAccessアプリは見違えるほどキビキビ動くようになりますよ。さあ、一緒に本質を紐解いていきましょう!

1. なぜ `CurrentDb` を何度も呼ぶと遅くなるのか?

Access VBAでデータベースの中身を操作(データの追加、更新、削除など)するとき、私たちはよく次のようなコードを書きます。

‘ よくあるコード例
Sub UpdateData()
CurrentDb.Execute “UPDATE T_顧客 SET 顧客ランク = ‘A’ WHERE 売り上げ > 100000”, dbFailOnError
End Sub

この `CurrentDb` というメソッド、実は裏側でめちゃくちゃ重たい処理をしています。

イメージしてみてください。`CurrentDb` を呼び出すたびに、Accessは以下の一連の儀式を毎回ゼロから行っています。

1. 「データベースを開きたいです!」というリクエストをAccessのエンジンに送る。
2. エンジンがメモリ上にデータベースへの接続(セッション)を新しく構築する。
3. 処理が終わったら、その接続を安全に解体してメモリを掃除する。

もし、これがボタンを1回押しただけで100回ループする処理だったらどうでしょう? 「たった1行の処理のために、100回も家を建て直しては壊している」ようなものです。そりゃあプログラムも重くなりますよね。これが `CurrentDb` のオーバーヘッド(見えない無駄なコスト)の正体です。

2. 解決策:モジュールレベル変数で「キャッシュ」する

この無駄をなくすためのテクニックが 「DAO.Database変数の再利用(キャッシュ)」 です。

あらかじめデータベースへの接続(通路)を1本書ースタンドバイさせておき、それを何度も使い回す。これがプログラミングの世界でいう「キャッシュ」の概念です。

図解するならこういうイメージです。

【悪い例:毎回接続を作る】
[VBAコード] — (接続・切断) —> [CurrentDb]
[VBAコード] — (接続・切断) —> [CurrentDb] ※これを何回も繰り返す(重い)

【良い例:一度繋いだものを保持(キャッシュ)する】
[VBAコード] ———————> [保持された DAO.Database 変数]
(同じ通路を何回もスルスルと往復するだけなので高速!)

実装パターン:標準モジュールでの設計

では、実際に現場で使えるスマートなコードを見てみましょう。標準モジュールに次のように記述します。

Option Compare Database
Option Explicit

‘ 【モジュールレベル変数】
‘ アプリケーションが起動している間、データベースへの接続を保持し続けます
Private m_db As DAO.Database

‘ データベースオブジェクトを取得するプロパティ(なければ作り、あれば使い回す)
Public Function GetDB() As DAO.Database
‘ もし変数 m_db が空(まだ接続していない、または解放されてしまった)なら
If m_db Is Nothing Then
‘ ここで初めてCurrentDbを呼び出し、変数に“保持(キャッシュ)”する
Set m_db = Application.CurrentDb
End If

‘ キャッシュしたデータベースオブジェクトを呼び出し元に返す
Set GetDB = m_db
End Function

‘ アプリ終了時やリセット時に明示的にメモリを解放するプロシージャ
Public Sub ReleaseDB()
If Not m_db Is Nothing Then
Set m_db = Nothing
End If
End Sub

3. 実際の業務コードで使ってみよう

先ほどの `GetDB` 関数を用意しておけば、日々のデータ操作系コードは以下のように書き換えることができます。

Sub ProcessBulkOrders()
Dim db As DAO.Database

‘ 毎回 CurrentDb を書く代わりに、キャッシュ用関数から受け取る
Set db = GetDB()

‘ トランザクション処理や大量のSQL実行も、同じ db 変数でサクサク処理!
db.Execute “UPDATE T_受注 SET ステータス = ‘処理済み’ WHERE 処理フラグ = True”, dbFailOnError
db.Execute “INSERT INTO T_履歴 (…) SELECT …”, dbFailOnError

‘ ※注意:db変数はキャッシュされているため、ここでは Set db = Nothing しないこと!

MsgBox “一括処理が完了しました!”, vbInformation
End Sub

どうでしょう? コードの書き方はほとんど変わらないのに、裏で行われている無駄なエンジン再起動がピタッと止まり、実行速度が劇的に向上します。

4. 陥りやすい罠・注意点(ここが一番大事!)

上級者への階段を登るあなたへ、プログラミングの現場でハマりがちな「罠」を2つ共有しておきます。ここを知っているかどうかがプロの分かれ道です。

罠①:変数が予期せず消える(リセット問題)

VBAで実行時エラーが発生したり、コード内で `End` ステートメントを使用したりすると、モジュールレベルで保持していた `m_db` の中身が強制的に消去(リセット)されます。
そのため、`GetDB()` 関数の中では必ず `If m_db Is Nothing Then` という「消えていたら再取得する」ためのガード節を書いておく必要があります。上記のサンプルコードにその処理が入っているのはそのためです。

罠②:オブジェクトの寿命を意識する

標準モジュールで保持した `m_db` は、Accessを閉じたり、VBAのプロジェクトがリセットされたりするまでメモリ上に残り続けます。基本的にはAccessの終了と同時に自動解放されますが、クリーンなコーディングを心掛けるなら、アプリケーションの終了時やメイン画面の閉じるイベントで `ReleaseDB` を呼んであげるのが美しい設計です。

まとめ:ここをクリアすれば、Access VBAの基本はバッチリ!

今回は `Application.CurrentDb` のオーバーヘッドと、DAO.Database変数をモジュールレベルでキャッシュする設計パターンについて解説しました。

  • `CurrentDb` は呼ぶたびに内部で重たい接続処理を行っている。
  • 一度取得した `DAO.Database` を変数に保持(キャッシュ)して使い回せば、パフォーマンスが劇的に向上する。
  • 「なければ作り、あれば使い回す」というガード節(`Is Nothing` 判定)をセットで実装する。

このテクニックを取り入れるだけで、あなたの作るAccessアプリは「なんだかモッサリするアプリ」から「プロが作ったサクサク動く業務システム」へと生まれ変わります。

ここをクリアしたあなたなら、もうマクロの記録の卒業生ではありません立派なVBAエンジニアです。ぜひ実際の開発現場で試してみてくださいね。あなたのAccess開発ライフを応援しています!

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