Access VBAの「脱・クエリ再生成」:RecordsetCloneとFilterを極め、UIを爆速化する
Access開発の現場で、検索機能を作るたびに「SQL文を文字列結合してクエリを書き換える」という原始的な手法をとっていないだろうか?
その設計は、ネットワークトラフィックの無駄な増大を招き、データベースエンジンを疲弊させ、何より「ユーザー体験」を著しく損なう。プロフェッショナルは、メモリ上のレコードセットを操る。
今回は、DAO.Recordsetの`Filter`プロパティと`RecordsetClone`を組み合わせ、Accessフォームを「高速検索エンジン」へと変貌させるための極限の技法を伝授する。
—
なぜ「SQLの都度生成」は悪手なのか
フォームの検索機能で `Me.RecordSource = “SELECT FROM … WHERE …”` を繰り返すと、毎回Jet/ACEエンジンがクエリを解析・最適化するオーバーヘッドが発生する。大規模なデータになればなるほど、この遅延は顕著になる。
我々が目指すべきは、「一度開いたデータセットをメモリ上に保持し、その上で絞り込みを行う」というアプローチだ。
核心技術:RecordsetClone と Filter の連携
`RecordsetClone`は、現在のフォームが参照しているデータソースの「分身」をDAO.Recordsetとして取得するプロパティだ。この分身に対して`Filter`を適用し、フォームの`Bookmark`を同期させる。これだけで、クエリ再実行なしに表示を瞬時に更新できる。
実装のプロダクションコード
保守性を担保するため、以下のコードは検索条件を引数で受け取る単一のサブプロシージャとして設計している。フォームの検索ボタンから呼び出すことを想定してほしい。
‘ 検索を実行する汎用プロシージャ
‘ @param strFilter 検索条件文字列 (WHERE句の条件部分)
Public Sub ApplySearchFilter(ByVal strFilter As String)
Dim rs As DAO.Recordset
‘ エラーハンドリングは堅牢な開発の基本
On Error GoTo ErrorHandler
‘ 1. 現在のフォームのレコードセットを複製
Set rs = Me.RecordsetClone
‘ 2. フィルタの適用
‘ Filterを空にすると全件表示になるよう設計
rs.Filter = strFilter
‘ 3. フィルタ後のレコードセットをセット
‘ RecordsetCloneに対してFilterを適用した結果を開き直す
Set rs = rs.OpenRecordset()
‘ 4. フィルタ結果が0件の場合のハンドリング
If rs.EOF Then
MsgBox “該当するデータは見つかりませんでした。”, vbInformation
rs.Close
Exit Sub
End If
‘ 5. フォームのブックマークを同期
‘ これにより、画面表示が検索結果へ瞬時に切り替わる
Set Me.Recordset = rs
‘ メモリ解放の作法
rs.Close
Set rs = Nothing
Exit Sub
ErrorHandler:
MsgBox “エラー番号: ” & Err.Number & vbCrLf & “内容: ” & Err.Description, vbCritical
If Not rs Is Nothing Then Set rs = Nothing
End Sub
—
現場で生き残るための設計原則
この手法を採用する上で、必ず守るべき「3つの鉄則」がある。
1. フィルタ文字列のクレンジング
ユーザーが入力した値をそのまま `Filter` に渡してはならない。シングルクォーテーションのエスケープ処理(`Replace(str, “‘”, “””)`)を怠ると、悪意のある入力や記号によるSQLインジェクション的挙動、あるいは単純な構文エラーでシステムが停止する。
2. インデックスの有効活用
`Filter`プロパティはDAOの機能だが、対象となるテーブルのフィールドにインデックスが貼られていなければ、検索速度は劇的に低下する。特に検索対象となるフィールドには、あらかじめインデックスを設計しておくのがデータベースアーキテクトの最低限の義務だ。
3. Recordsetの破棄を忘れない
`RecordsetClone`や`OpenRecordset`で生成したオブジェクトは、VBAのガベージコレクションに頼ってはいけない。`Set rs = Nothing` を呼び出すまでメモリを占有し続ける。「開いたら閉じる」のスコープを関数内に閉じ込めることで、メモリリークを根絶せよ。
まとめ:次の一歩
この手法を導入すれば、フォームの検索処理は「クエリの再評価」という重い作業から解放され、メモリ上の操作による「ミリ秒単位の応答」へと進化する。
次にあなたが取り組むべきは、検索条件が複雑化した場合の「動的フィルタ生成クラス」の作成だ。`Filter`文字列を泥臭い文字列結合で作るのではなく、Dictionaryオブジェクトを用いてスマートに構築する設計へ移行すれば、あなたのツールはプロのプロダクションコードとして確固たる地位を築くだろう。
コードは嘘をつかない。論理的な設計こそが、Accessの限界を超える唯一の道だ。
