Accessの「Open」と「Load」を掌握せよ:メモリとイベントのライフサイクルを制御する極限の作法
Access開発において、多くのエンジニアが「なんとなく」で使い分けているのが `Form_Open` と `Form_Load` だ。しかし、この二つのイベントの境界線を正しく理解せず、安易な初期化処理を記述することは、メモリリークや予期せぬ実行時エラー、そして何よりパフォーマンスの低下を招く「罪」である。
本稿では、レガシーシステムを延命させつつ、モダンなアーキテクチャへと昇華させるための、Accessイベントモデルの真髄を解き明かす。
—
1. ライフサイクルの本質:OpenとLoadの「非対称性」
まず、心に刻んでおくべきは「フォームの初期化プロセスは、データソースのバインドと密接に関わっている」という事実だ。
- OnOpen: フォームそのものがメモリ上にロードされ、データソース(RecordSource)が初期化される直前に発生する。この時点で、コントロールのValueプロパティにはまだアクセスできない。
- OnLoad: レコードセットが確定し、コントロールにデータがバインドされた後に発生する。
なぜこれが重要なのか?
初心者は `OnOpen` で「コントロールの値を操作しよう」とする。これは無駄なエラーを誘発するだけでなく、Access内部のクエリ実行エンジンに対して非効率な負荷を強いることになる。
結論:
- Open: 「フォームの挙動制御(Cancel可)」と「動的なSQLの構築」。
- Load: 「コントロールの初期値設定」と「UIの動的装飾」。
—
2. 実践的パターン:安全な初期化処理の設計
以下に、不確実性を排除した初期化処理のテンプレートを示す。
‘ フォームモジュール内でのベストプラクティス
Option Compare Database
Option Explicit
Private Sub Form_Open(Cancel As Integer)
‘ 1. データソースの動的変更はここで行う
‘ Loadイベントでは遅すぎる。ここでRecordSourceを差し替えることで
‘ 無駄な初期クエリの実行を防ぐ。
Dim strSQL As String
strSQL = “SELECT FROM T_Master WHERE CategoryID = ” & Me.OpenArgs
‘ 不正なOpenArgsに対する安全装置
If IsNull(Me.OpenArgs) Then
MsgBox “パラメータが不正です。”, vbCritical
Cancel = True ‘ フォームの起動そのものを中止
Exit Sub
End If
Me.RecordSource = strSQL
End Sub
Private Sub Form_Load()
‘ 2. コントロールの操作はここで行う
‘ ここでは既にRecordSourceが評価済みであるため、
‘ コントロールのValueへのアクセスが保証されている。
Me.txtStatus.Value = “データロード完了”
Call ApplyDynamicUI(Me)
End Sub
—
3. シニアエンジニアのためのメモリ最適化とAPI連携
Accessのフォームを大量に開閉するようなツールを構築する場合、メモリ管理を放置してはならない。特に `CurrentDb` の使い方は、パフォーマンスを左右する最大の分岐点だ。
CurrentDbのキャッシュ戦略
`CurrentDb` をループ内で何度も呼び出すのは、毎回新しいインスタンスを生成するようなものだ。シニアエンジニアは、DBオブジェクトを保持し、再利用する。
‘ モジュールレベルで保持し、明示的に解放する
Private m_db As DAO.Database
Private Sub Form_Open(Cancel As Integer)
Set m_db = CurrentDb
End Sub
Private Sub Form_Close()
‘ オブジェクトのライフサイクルを制御する
‘ Accessの自動解放を待つのではなく、自ら始末をつける
Set m_db = Nothing
End Sub
Windows APIによる制御の深淵
もし、「特定のフォームを常に最前面に置く」「タスクバーから消す」といった要件がある場合、`OnLoad` イベントでAPIを叩くのが定石だ。
‘ Windows APIの宣言
Private Declare PtrSafe Function SetWindowPos Lib “user32” ( _
ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, _
ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Private Sub Form_Load()
‘ フォームを最前面に固定する例
Const HWND_TOPMOST = -1
Call SetWindowPos(Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, &H3)
End Sub
—
4. チーフアーキテクトからの提言:レガシーとの共存
Access開発において、イベントの順序を厳密に制御することは、単なるコードの整理ではない。それは、「ブラックボックス化しやすいAccessの振る舞い」を、我々の制御下に置くという意思表明である。
1. Cancelプロパティを信じろ: `OnOpen` で例外をキャッチし、`Cancel = True` でフォームを開かせない設計こそが、システムの堅牢性を担保する最後の砦だ。
2. UIとデータソースを分離せよ: `OnLoad` でコントロールに複雑なロジックを詰め込んではいけない。ロジックは必ず標準モジュール等の別クラスへ追い出し、フォームを「ただの表示デバイス」として極限まで薄く保て。
Accessは、正しく扱えば強力なRADツールだが、適当に扱えば技術的負債の塊と化す。コードを書く前に、今一度「その処理は、どのライフサイクルで実行されるべきか」を自問自答してほしい。
これこそが、Accessを掌握する者の責務である。
