こんにちは!Access VBAの世界へようこそ。
マクロの記録から一歩踏み出し、「自分の手で意のままにシステムをコントロールしたい」と願うあなたへ。今日、とてもエキサイティングで実務に直結するテクニックを伝授します。
ここをクリアすれば、Access VBAの基本はバッチリですよ!
今回取り上げるのは、「DAO.RecordsetのCloneとBookmarkを使った、非連結フォームでの高速検索UI」です。
「フォームを開くたびに検索条件でクエリを書き換えていたら、画面がチラついて動きがもっさりする…」そんなストレスを感じたことはありませんか?
プロの現場では、レコードソースをガチャガチャいじらず、メモリ上でスマートに目的のレコードを捉えるのが常道です。その秘密兵器が `RecordsetClone` と `Bookmark` です。
それでは、Accessの奥深いオブジェクトモデルの世界へ、一緒に出発しましょう!
—
1. なぜ「レコードソースの直接書き換え」は悪手なのか?
Accessで検索機能を作るとき、初学者がやりがちなのがコレです。
‘ 【アンチパターン】検索のたびにSQLを書き換える
Me.RecordSource = “SELECT FROM T_顧客 WHERE 顧客名 LIKE ‘” & Me.txt検索 & “‘”
Me.Requery
一見、動くので問題ないように見えますが、実務のデータ量(数万件〜)になると致命的な問題が発生します。
1. ネットワークやディスクへの負荷: 検索のたびにデータベースエンジンにクエリの再コンパイルと実行が走ります。
2. 画面のチラつき(フリッカ): フォーム全体の再描画が走るため、ユーザーの目が疲れます。
3. カレントレコードの喪失: 再クエリ(Requery)によって、フォーカスが先頭行に戻ってしまい、ユーザーが「今どこを見ているのか」を見失います。
プロが使う「Clone」という名の影武者
Accessのフォームには、裏側でデータを保持している「RecordsetClone(レコードセットクローン)」という強力なオブジェクトが存在します。
これは、「フォームが持っているデータセットのコピー(影武者)」をメモリ上に展開したものです。
影武者側で「何番目のデータがどこにあるか」を素早く探し出し、本番のフォームに「おい、ここにジャンプしろよ!」と指示(Bookmark)を出す。
この仕組みを使えば、データベースへの無駄なアクセスを極限まで減らし、驚異的なスピードと滑らかな操作感を持つUIが完成します。
—
2. 全体像をイメージしよう(仕組みの図解)
[ Access フォーム画面 (UI) ]
(ユーザーがテキストボックスに文字を入力)
│
▼
[ VBAコードの実行 ]
1. Me.RecordsetClone でメモリ上の「影武者」を取得
2. 影武者の中で高速検索 (.FindFirst)
3. 該当レコードの「住所(Bookmark)」を特定
│
▼
[ フォームへ即座に反映 ]
Me.Bookmark = 影武者.Bookmark (★一瞬でジャンプ!)
このシンプルな連携プレーをコードで表現していきます。
—
3. 実装コード:これだけで劇的に速くなる!
それでは、実際のフォームに配置するコードを見てみましょう。
今回は、「社員検索テキストボックス(`txtKeyword`)」に文字を入力し、ボタンを押すかEnterキーを押したときに、該当する社員の行へ一瞬でジャンプする機能を実装します。
Option Compare Database
Option Explicit
Private Sub btn検索_Click()
‘ =====================================================================
‘ 目的:RecordsetCloneとBookmarkを使い、画面を再読み込みせずに高速検索する
‘ =====================================================================
Dim rs As DAO.Recordset
Dim strKeyword As String
On Error GoTo ErrorHandler
‘ 1. 検索キーワードの取得(未入力なら処理を抜ける)
If Trim(Me.txtKeyword.Value & “”) = “” Then
MsgBox “検索キーワードを入力してください。”, vbExclamation, “入力エラー”
Me.txtKeyword.SetFocus
Exit Sub
End If
strKeyword = Me.txtKeyword.Value
‘ 2. フォームの「影武者(RecordsetClone)」をオブジェクト変数に取得
‘ ※ここでポイントなのは、フォーム自体のレコードソースは一切いじらないこと!
Set rs = Me.RecordsetClone
‘ 3. 影武者の中で条件に一致するレコードを高速検索
‘ ※今回は「氏名」フィールド部分一致検索の例です
rs.FindFirst “氏名 LIKE ‘” & strKeyword & “‘”
‘ 4. 該当データが見つかったかどうかの判定
If rs.NoMatch Then
MsgBox “該当するデータが見つかりませんでした。”, vbInformation, “検索結果”
‘ 見つからなかった場合の処理(必要に応じて影武者の解放)
rs.Close
Set rs = Nothing
Exit Sub
End If
‘ 5. 【最重要】影武者の現在地(Bookmark)を、本番フォームに同期させる!
‘ これにより、画面全体の再読み込みなしで、一瞬で該当行にフォーカスが移動します。
Me.Bookmark = rs.Bookmark
‘ 後片付け(メモリリーク防止の作法)
rs.Close
Set rs = Nothing
Exit Sub
ErrorHandler:
‘ 予期せぬエラーの捕捉
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “システムエラー”
If Not rs Is Nothing Then
rs.Close
Set rs = Nothing
End If
End Sub
—
4. コードの深掘りポイント(エンジニアの知見)
初心者のうちは、「動けばいいや」となりがちですが、プロのコードには「オブジェクトのライフサイクル管理」という美学があります。
① `Me.RecordsetClone` は「新規生成」されることに注意
このプロパティを呼び出すたびに、Accessは内部で新しいRecordsetオブジェクトへの参照を返します。つまり、使い終わったら必ず `rs.Close` と `Set rs = Nothing` でメモリから解放してあげなければなりません。これをサボると、見えないところでメモリを食いつぶし(メモリリーク)、Access全体のパフォーマンス低下を招きます。
② `Bookmark` 型の正体
`Bookmark` は、データベースエンジン内部におけるレコードの「一意な住所(バイト配列)」です。
人間でいう「東京都港区…の何番地」といった番地のようなもので、これをフォームの `Bookmark` プロパティに代入するだけで、Accessは迷うことなくそのレコードへ一瞬でジャンプできます。
—
5. 陥りやすいエラーと回避のテクニック
現場でこの実装を行う際、初心者が必ずハマる「罠」がいくつかあります。あらかじめ知っておきましょう。
- 罠1:そもそもフォームにレコードが存在しない(空っぽ)
- 現象: データが1件もない状態で検索をかけると、`RecordsetClone` が空っぽのため、`FindFirst` でエラーになることがあります。
- 対策: 検索の前に `If Me.Recordset.RecordCount = 0` などのチェックを入れると鉄壁です。
- 罠2:データ型によるクエリの構文エラー
- 現象: 検索対象が「数値型」や「日付型」であるにもかかわらず、上記のコード(`LIKE ‘…’` は文字列専用)をそのまま使うと、型不一致エラーになります。
- 対策: 数値型を検索する場合は `rs.FindFirst “社員ID = ” & strKeyword` のように、シングルクォーテーションを外す配慮が必要です。
—
おわりに:ここをクリアすれば、あなたはもう初心者ではない!
いかがでしたでしょうか?
`RecordsetClone` と `Bookmark`。名前は少し難しそうに見えますが、やっていることは「裏でこっそり調べて、ピンポイントでジャンプする」という非常にシンプルでエレガントな手法です。
この仕組みを理解し、使いこなせるようになると、あなたが作るAccessアプリの動作速度とユーザビリティは、見違えるように洗練されたものになります。
「マクロの貼り付け」から卒業し、オブジェクトのライフサイクルを意識した真のVBAエンジニアへの第一歩。ぜひ、あなたの開発環境でも試してみてくださいね。
それでは、次回の極限の知見でお会いしましょう!
