こんにちは! Access VBAの開発現場で、日々フォームやクエリと格闘していませんか?
「検索窓を作ったはいいものの、検索のたびにフォームのデータソース(レコードソース)を書き換えていたら、画面がチラついたり、思わぬところでエラーが出たりする……」
そんな壁にぶつかったことはありませんか?
実は、プロの現場では、フォームのデータソースを直接汚さずに、スマートに検索結果を同期させる「RecordsetClone(レコードセットクローン)」と「Bookmark(ブックマーク)」という強力な武器を使います。
ここをクリアすれば、あなたもマクロの記録から完全に脱却し、ワンランク上のAccessエンジニアの仲間入りです。さあ、一緒に本質をマスターしていきましょう!
—
1. なぜ「データソースの直接書き換え」は危険なのか?
検索機能を実装するとき、多くの初心者がやってしまいがちなのが、以下のようなコードです。
‘ 駄目な例:検索のたびにフォームのデータソースを書き換えている
Me.RecordSource = “SELECT FROM T_顧客 WHERE 顧客名 Like ‘” & Me.txt検索 & “‘”
Me.Requery
一見すると動くように思えますが、これには大きなデメリットがあります。
- フォームの「現在の状態」がリセットされる(カレントレコードが先頭に戻ってしまう)。
- マルチユーザー環境においてロックやパフォーマンスの面で不利になる。
- フォームが持っている本来の「入力・編集用」という役割と、「検索・表示用」という役割が混ざってしまい、コードがスパゲッティ化する。
これを解決するのが、「フォームの表示はそのままに、裏で持っているコピー(クローン)を操作し、その位置を本体に教え込ませる」というテクニックです。
—
2. 核心に迫る!「RecordsetClone」と「Bookmark」の正体
このテクニックの仕組みを、図解的にイメージしてみましょう。
[ Accessフォーム (画面) ]
│
├─ 表示されているデータ (そのまま維持!)
│
▼ 同期! (Bookmarkの受け渡し)
│
[ RecordsetClone (メモリ上のコピー) ]
│
└─ ここで「検索・絞り込み」を行う
1. RecordsetCloneとは?
フォームが現在開いているレコードセットの「双子の兄弟(コピー)」をメモリ上に呼び出すプロパティです。このクローンを操作しても、画面上のフォームの表示はビクともしません。
2. Bookmarkとは?
レコードセット内の「特定の1行(レコード)」をピンポイントで指し示す、いわば「しおり(ブックマーク)」です。
この2つを組み合わせると、「裏側のクローンで検索して目的のレコードを探し、その『しおり』をフォーム本体に渡すことで、画面の表示位置をピタッと合わせる」という神業が可能になります。
—
3. 実践!検索結果をスマートに同期させるコード例
それでは、実際のフォームに実装するコードを見ていきましょう。
ここでは、「T_顧客」テーブルから「顧客名」の部分一致検索を行い、該当するレコードにフォームをジャンプさせるシナリオを想定しています。
フォームに配置するコントロール:
- 検索キーワードを入力するテキストボックス:`txt検索`
- 検索を実行するボタン:`btn検索`
Private Sub btn検索_Click()
Dim rs As DAO.Recordset
On Error GoTo ErrorHandler
‘ 1. フォームのクローン(双子の兄弟)をオブジェクト変数に取得する
Set rs = Me.RecordsetClone
‘ 2. クローン側で、入力されたキーワードをもとにレコードを検索する
‘ ※ここではDAOのFindFirstメソッドを使用します
Dim 検索条件 As String
If Trim(Me.txt検索.Value) = “” & “” Then
‘ 検索ワードが空の場合は何もしないか、全件表示に戻す等の処理
MsgBox “検索ワードを入力してください。”, vbExclamation, “入力チェック”
Exit Sub
End If
検索条件 = “顧客名 Like ‘” & Me.txt検索.Value & “‘”
rs.FindFirst 検索条件
‘ 3. 該当するデータが見つかったか判定する
If rs.NoMatch Then
MsgBox “該当するデータは見つかりませんでした。”, vbInformation, “検索結果”
Else
‘ 4. ★ここが最重要!★
‘ クローンの「しおり(Bookmark)」を、フォーム本体の「しおり」に代入する
Me.Bookmark = rs.Bookmark
‘ ※これによって、画面上のフォームが「一瞬で」該当レコードにジャンプします!
End If
CleanUp:
‘ 5. オブジェクト変数を解放し、メモリリークを防ぐ(プロの必須作法)
Set rs = Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub
—
4. コードの深掘りポイントとプロの知見
上記のコードで、特に意識してほしいポイントを解説します。
① `Me.Bookmark = rs.Bookmark` の魔法
フォームの `Bookmark` プロパティに、クローン側(`rs`)の `Bookmark` を代入した瞬間、Accessは自動的に画面上の表示をその行へスクロールさせ、カレントレコードを移動させます。
ループを使って1行ずつ `MoveNext` するような野暮ったいコードを書く必要は一切ありません。一瞬で処理が完了します。
② メモリの解放(`Set rs = Nothing`)を怠らない
Access VBAにおいて、`DAO.Recordset` などのオブジェクト変数を生成したら、処理の最後で必ず `Nothing` を代入してメモリを解放するのが鉄則です。これをサボると、長期間アプリを稼働させた際にメモリリーク(メモリの無駄遣い)を引き起こし、Access全体の動作が重くなる原因になります。
—
まとめ:ここをクリアすれば、Access VBAの基本はバッチリです!
今回は、フォームの「RecordsetClone」と「Bookmark」を同期させ、データソースを汚さずに検索結果を反映させるテクニックをご紹介しました。
- フォームのデータソースを直接書き換えない
- 検索はメモリ上の `RecordsetClone` で行う
- 見つけた位置を `Bookmark` でフォーム本体に教え込む
この3つの原則さえ押さえておけば、どれだけデータ量が増えても軽快に動作する、プロフェッショナルな画面設計ができるようになります。
「マクロの記録」や「力技のコード」から卒業し、Accessのオブジェクトモデルを自在に操る楽しさを、ぜひあなたの開発現場でも体感してください。応援しています!
