Accessの「重い連結フォーム」に終止符を。DAO.RecordsetのCloneとBookmarkで構築する超高速検索UI
Access開発の現場で、多くのエンジニアが直面する壁がある。「レコード数が増えるとフォームの動作が極端に重くなる」問題だ。
連結フォームは便利だが、数万件のレコードを抱えた途端、Accessの内部エンジンはI/Oの嵐に翻弄され、軽快さとは無縁の「使い物にならないツール」へと成り下がる。
今日授けるのは、DAO.Recordsetの `Clone` と `Bookmark` を駆使し、非連結フォームで「爆速」を実現する設計手法だ。これは単なる小手先のテクニックではない。Accessのメモリ管理とオブジェクトのライフサイクルを掌握した者だけが辿り着ける、プロダクション品質のアーキテクチャである。
—
1. なぜ「連結フォーム」は限界を迎えるのか
連結フォームは、フォームとテーブルが「直結」している。ユーザーがスクロールするたびに、Accessはカレントレコードの同期、プロパティの更新、そして背後での膨大なバッファ管理を自動で行う。
この「自動化」こそが諸悪の根源だ。
我々が目指すべきは、「データの取得」と「UIの表示」を論理的に分離すること。これには非連結フォームを採用し、背後でDAO.Recordsetを制御するのが最適解となる。
—
2. アーキテクチャの核心:CloneとBookmarkの役割
今回用いるのは以下のコンポーネントだ。
- DAO.Recordset: 検索結果を保持する「マスター」。
- Cloneメソッド: フォーム上の操作とは独立して、自由にレコードを走査するための「分身」。
- Bookmark: 物理的なレコード位置を特定する「魔法のインデックス」。
これらを組み合わせることで、「フォーム上には表示用データだけを流し込み、検索やソートは裏側のメモリ上のレコードセットで完結させる」という、極めて堅牢な非連結設計が可能になる。
—
3. 実装:爆速検索UIのプロダクションコード
以下のコードは、検索条件に基づきレコードセットを生成し、リストボックス(またはサブフォーム)へ流し込むためのテンプレートだ。
‘ フォームモジュール内に実装する検索ロジック
Private Sub ExecuteSearch(strFilter As String)
Dim db As DAO.Database
Dim rsMaster As DAO.Recordset
Dim rsClone As DAO.Recordset
Set db = CurrentDb
‘ 1. 検索実行(SQLで必要な分だけ絞り込む)
Set rsMaster = db.OpenRecordset(“SELECT FROM T_Master WHERE ” & strFilter, dbOpenDynaset)
‘ 2. 存在チェック
If rsMaster.EOF Then
MsgBox “該当するデータはありません。”, vbInformation
Exit Sub
End If
‘ 3. Cloneの生成
‘ これにより、rsMasterを破壊せずに、検索や集計を自由に行える
Set rsClone = rsMaster.Clone
‘ 4. フォームへの表示(リストボックス等へ)
‘ 非連結フォームの場合、ここでRecordsetオブジェクトを直接アタッチする
Set Me.lstSearchResult.Recordset = rsMaster
‘ 5. リソースの適切な管理
‘ フォームを開いている間はrsMasterを保持し、Close時に解放する
Set rsClone = Nothing
Set db = Nothing
End Sub
‘ フォームクローズ時にメモリリークを防ぐ
Private Sub Form_Close()
If Not Me.lstSearchResult.Recordset Is Nothing Then
Me.lstSearchResult.Recordset.Close
Set Me.lstSearchResult.Recordset = Nothing
End If
End Sub
—
4. 堅牢な設計のための「3つの鉄則」
① Recordsetの「型」を意識せよ
`dbOpenDynaset` を適切に選べ。単なる参照なら `dbOpenSnapshot` を使うことで、ロックのオーバーヘッドをゼロにできる。パフォーマンス重視ならSnapshot一択だ。
② Bookmarkは「文字列」ではなく「バイト配列」として扱え
`Bookmark` プロパティは内部的にバイト配列(Byte Array)を保持している。これを文字列変換して保存するような愚行は避け、必要であれば `Variant` 型として保持せよ。これにより、オブジェクトの整合性を完全に維持できる。
③ 物理的な「CurrentDb」の呼び出しを最小化せよ
`CurrentDb` は呼び出すたびに新しいインスタンスを生成する可能性がある(実際はキャッシュされるが、依存関係が複雑になる)。変数を定義して使い回すのがプロの作法だ。
—
結論:Accessは「使い捨て」のツールではない
多くの担当者が「Accessだから遅くて当然」と諦めている。だがそれは、Accessの性能不足ではない。「オブジェクトのライフサイクルを制御できていない設計」のせいだ。
今回紹介した `Clone` と `Bookmark` を活用した非連結フォーム設計は、数万件のレコードであってもミリ秒単位のレスポンスを叩き出す。この設計思想をインストールした時、あなたの作るツールは「ただの帳簿」から「真の業務システム」へと進化するはずだ。
次は、このアーキテクチャをベースに、いかにして「排他制御」を組み込み、マルチユーザー環境で破綻しないシステムに仕上げるか。その極意を深掘りすることにしよう。準備はいいか?
