こんにちは!Accessでのフォーム開発、日々お疲れ様です。
「フォームのデータを検索したい」「特定のレコードにジャンプしたい」と思ったとき、あなたならどうやってコードを書きますか?
まさか、検索のたびに `Me.RecordSource = “SELECT FROM … WHERE …”` なんて書き換えていませんよね……?
もしそれに心当たりがあるなら、ここから先の話はあなたのAccess開発の常識を根底からひっくり返すかもしれません。今回は、Accessのパフォーマンスと安全性を極限まで高める秘儀「RecordsetClone(レコードセットクローン)」の世界へご案内します。
ここをクリアすれば、あなたも「マクロの記録」や「力技のコード」を卒業した、ワンランク上のエンジニアの仲間入りです。一緒に優しく、深く、マスターしていきましょう!
—
1. なぜ「直接フォームをいじるな」と言われるのか?
Accessのフォームには、テーブルやクエリといった「データソース」が紐付いていますよね。
画面にデータを表示している本丸(フォーム自身)を直接操作して検索や絞り込みを行おうとすると、以下のような問題が発生します。
- 画面のチラつきと描画負荷: フォームのデータソースを頻繁に書き換えると、その都度Accessは画面の再描画(UIの更新)を行い、動作が重くなります。
- カレントレコードの迷子: 検索処理の途中で予期せぬレコード移動が起き、ユーザーが今どこを見ているのか分からなくなる現象が起きます。
- コードの複雑化: エラーが起きたときのロールバックや状態の復元が非常に面倒になります。
そこで登場するのが、「RecordsetClone」です。
💡 RecordsetCloneの本質とは?
一言で言うと、「フォームの裏側で動いているデータ(レコードセット)の『分身(クローン)』をメモリ上にこっそり呼び出す機能」です。
- 分身だから安全: 分身をどれだけいじり倒しても、大元のフォーム画面(本物)には直接影響しません。
- 高速: 画面の描画を伴わないメモリ内での処理なので、圧倒的に高速です。
- 同期している: 分身の位置(カレントレコード)を動かすと、なんと一瞬で本物のフォーム側もそのレコードに追従してジャンプしてくれます。
この「分身を操作して、本体をスマートに操る」というアーキテクチャこそ、プロのAccess開発者が好む王道の手法なのです。
—
2. 【実践】RecordsetCloneを使った超高速「レコード検索」
それでは、実際の現場で即戦力となるコードを見ていきましょう。
「顧客ID」を入力して、ボタンを押したら一発でその人のレコードにジャンプする機能を実装します。
以下のコードを、フォームに配置したコマンドボタンの「クリック時」イベントに記述してみてください。
Private Sub btnSearch_Click()
‘ 1. 変数の宣言(DAOのレコードセットを扱います)
Dim rs As DAO.Recordset
Dim searchID As Long
‘ 2. 検索ボックスから値を取得(未入力チェック付き)
If IsNull(Me.txtSearchID.Value) Then
MsgBox “検索する顧客IDを入力してください。”, vbExclamation, “入力エラー”
Exit Sub
End If
searchID = Me.txtSearchID.Value
‘ 3. フォームのRecordsetCloneをオブジェクト変数に代入
‘ ※ここで「New」を使ってはいけません!すでにある分身を「Set」で取得します。
Set rs = Me.RecordsetClone
‘ 4. 分身の中でデータを検索する(FindFirstメソッド)
‘ 「ID」というフィールドから searchID を探します
rs.FindFirst “ID = ” & searchID
‘ 5. 見つかったかどうかの判定
If rs.NoMatch Then
‘ 見つからなかった場合
MsgBox “該当する顧客IDが見つかりませんでした。”, vbInformation, “検索結果”
Else
‘ 見つかった場合:
‘ ★ここが魔法の瞬間!分身のブックマークをフォーム本体に教え込む
Me.Bookmark = rs.Bookmark
‘ ついでにフォーカスをそのテキストボックスに移すなど
Me.txtCustomerName.SetFocus
End If
‘ 6. 对象的解放(メモリリークを防ぐプロの作法)
Set rs = Nothing
‘ 「ここをクリアすればバッチリ!」ですね。
End Sub
コードの重要ポイント解説
1. `Set rs = Me.RecordsetClone`
フォームが持っているデータセットの分身を取得しています。新しくクエリを発行するわけではないので、データベースに負荷をかけません。
2. `rs.FindFirst “条件式”`
DAOの真骨頂である高速検索メソッドです。上から順に条件に合うレコードを探します。(※文字列を探す場合は `FindFirst “氏名 = ‘” & searchName & “‘”` のようにシングルクォーテーションで囲むのを忘れないように!)
3. `Me.Bookmark = rs.Bookmark`
ここが最大のキモです!分身(`rs`)で見つけた「位置(ブックマーク)」を、フォーム本体(`Me`)のブックマークに代入することで、一瞬でフォームの表示位置がそのレコードにジャンプします。
—
3. 陥りやすい罠とエラー回避の知見
プロの現場でよくある失敗パターンと、その対策もあわせて押さえておきましょう。
⚠️ 注意点1: 新規追加行(入力中の行)でのエラー
フォームが「新規レコード入力待ち(一番下の新しい行)」の状態にあるとき、`RecordsetClone`に対して検索を行うと、エラーが発生することがあります。
- 対策: 検索を行う前に、もしフォームが新規入力中なら `Me.Dirty = False` (変更を保存)するか、一度既存のレコードにフォーカスを移してから実行するガード節を入れましょう。
⚠️ 注意点2: オブジェクトの解放(`Set rs = Nothing`)をサボらない
VBAの初心者がやりがちなのが、`Set rs = …` と取得したオブジェクトをそのまま放置することです。
Access(VBA)の裏側では、明示的に `Nothing` を代入してメモリを解放しないと、小さなメモリリークが蓄積し、長時間の稼働でAccessが不安定になる原因を作ります。プロフェッショナルは「使ったら必ず捨てる(解放する)」を徹底します。
—
まとめ
いかがでしょうか?
`RecordsetClone` と `Bookmark` を組み合わせたこの手法をマスターすると、あなたの作るAccessアプリは見違えるほど軽快で、プロフェッショナルな挙動に生まれ変わります。
- 画面を直接いじらず、「分身(Clone)」を操作する。
- 見つけたら `Bookmark` で本体をジャンプさせる。
- 使い終わったら `Nothing` で綺麗に片付ける。
この3つさえ心に留めておけば、もうフォーム操作で迷うことはありません。
明日からのAccess開発に、ぜひこの知見をフル活用してみてくださいね。あなたのVBAライフを心から応援しています!
