こんにちは!Access VBAの世界へようこそ。
日々、フォームのデータ検索や一覧表示を作っていて、「検索ボタンを押すたびに画面がチラつく…」「検索結果がパッと表示されなくて、なんだかもたつく…」なんてストレスを感じていませんか?
マクロの記録から一歩踏み出し、自力でVBAを書けるようになってくると、避けて通れないのがこの「パフォーマンスとユーザー体験(UX)」の壁です。
今回は、その壁を鮮やかにブチ破る、Access VBAの隠れた超重要機能「RecordsetClone(レコードセットクローン)」を使った高速検索のテクニックを伝授します。
ここをクリアすれば、あなたの作るAccessアプリは「もたつく古いシステム」から「サクサク動くモダンなシステム」へと生まれ変わります。一緒に本質をマスターしていきましょう!
—
1. なぜ「画面のチラつき」や「もたつき」が起きるのか?
まずは敵を知ることから始めましょう。
多くの初心者がやりがちな検索処理は、次のようなアプローチです。
- 「検索条件に合うように、フォームの `RecordSource`(データソース)のSQL文を書き換えて再読み込みする」
これ、一見すると正しく動きそうですよね。しかし、裏側のメカニズムを考えてみてください。
Accessは、SQLを書き換えられるたびに、データベースサーバー(またはローカルのエンジン)に問い合せを行い、画面(フォーム)のレイアウトをゴッソリ再描画します。
人間で例えるなら、本棚から目的の1冊を探すために、「本棚ごと一度部屋の外に運び出して、並べ替えてから部屋に戻す」ようなものです。そりゃあ疲れるし、動きも遅くなりますよね。
救世主「RecordsetClone」とは?
ここで登場するのが `RecordsetClone` です。
これは、現在フォームが開いているレコードセットの「そっくりさん(分身)」をメモリ上にこっそり作成する機能です。
イメージ図で表すとこうなります:
[ Access フォーム画面 ] (ユーザーに見えている場所 / 描画はそのまま!)
│
├─ (連動) ── 裏でこっそり作業
▼
[ RecordsetClone ] (メモリ上の分身 / ここで高速に検索・移動する)
メモリ上の分身(Clone)を動かして「あ、目的のデータはこの行だね」と見つけたら、フォーム本体に「おーい、今すぐその行を表示してくれよ!」とカレントレコード(現在の選択位置)だけをテレポートさせるのです。
これなら画面の再描画が起きないため、圧倒的に高速で、チラつきが一切ない検索が実現できます。
—
2. 実践!高速検索コードの書き方
百聞は一見にしかず。実際のコードを見てみましょう。
「顧客ID」を入力して、ボタン一発でその顧客のレコードへジャンプするフォームのモジュールを想定してください。
以下のコードを、検索ボタンのクリックイベントなどにそのままコピペして使えます。
Private Sub 検索ボタン_Click()
Dim rs As DAO.Recordset
Dim searchID As Long
‘ 1. 検索ボックスから値を取得(未入力チェック付き)
If IsNull(Me.txt検索ID.Value) Then
MsgBox “検索する顧客IDを入力してください。”, vbExclamation, “入力エラー”
Exit Sub
End If
searchID = Me.txt検索ID.Value
‘ 2. フォームのRecordsetCloneをオブジェクト変数に代入
Set rs = Me.RecordsetClone
‘ 3. 分身(RecordsetClone)側でデータを検索する(FindFirstメソッド)
‘ ※IDフィールドの型に合わせて、数値ならそのまま、文字列なら “ID = ‘” & searchID & “‘” のように囲む
rs.FindFirst “顧客ID = ” & searchID
‘ 4. データが見つかったかどうかの判定
If rs.NoMatch Then
MsgBox “お探しの顧客IDは存在しません。”, vbInformation, “検索結果”
Else
‘ 5. 見つかった場合、フォームのブックマーク(現在位置)を分身に同期させる!
Me.Bookmark = rs.Bookmark
‘ 6. ユーザーに分かりやすいよう、テキストボックスにフォーカスを戻すなど
Me.txt顧客名.SetFocus
End If
‘ 7. オブジェクト変数を解放してメモリをキレイに掃除する(超重要!)
Set rs = Nothing
End Sub
コードの重要ポイント解説
- `Set rs = Me.RecordsetClone`
フォームが持つレコードセットのクローンを、VBAのDAOオブジェクト変数 `rs` に取得しています。これでメモリ上で自由に動き回れるようになります。
- `rs.FindFirst “顧客ID = ” & searchID`
DAOレコードセット特有の強力なメソッドです。条件に一致する最初のレコードを秒速で探し出します。
- `Me.Bookmark = rs.Bookmark`
ここが魔法の瞬間です。メモリ上の分身(`rs`)が「ここにあったよ!」と指し示した場所(Bookmark)を、フォーム本体(`Me`)に教えてあげることで、画面が一瞬でその行へジャンプします。
- `Set rs = Nothing`
プログラミングの基本であり鉄則です。使い終わったメモリ上のオブジェクトは必ず解放しましょう。これをサボるとメモリリーク(動作不良の原因)につながります。
—
3. 陥りやすい罠とエラー回避の知見
実務でこのコードを書き始めると、いくつかの「罠」にハマることがあります。伝説のエンジニアとして、先回りしてその回避策を伝授しておきますね。
罠その1:文字列の検索で型ミスマッチエラーが起きる
SQLやRecordsetの検索条件では、文字列を扱うときにシングルクォーテーション (`’`) で囲む必要があります。
- 数値型の場合: `rs.FindFirst “顧客ID = ” & searchID` (OK)
- 文字列型(テキスト型)の場合: `rs.FindFirst “顧客名 = ‘” & searchName & “‘” ` (これが正解!)
ここを忘れると、「型が一致しません」というエラーが出て悶絶することになります。文字列のときはシングルクォーテーションの挟み込みに注意してください。
罠その2:該当データがないのに Bookmark を代入してエラー
`FindFirst` でデータが見つからなかった場合(`rs.NoMatch = True` のとき)、そのまま `Me.Bookmark = rs.Bookmark` を実行すると、「実行時エラー ‘3021’: 現在レコードマンはありません」というエラーで容赦なくプログラムが落ちます。
必ず、先ほどのサンプルコードのように `If rs.NoMatch Then … Else … End If` で条件分岐を挟む防衛的プログラミング(ディフェンシブ・プログラミング)を徹底しましょう。
—
まとめ:ここをクリアすれば、Access VBAの基本はバッチリ!
いかがでしょうか?
`RecordsetClone` を使った非連結風の高速検索テクニック。
1. フォームの再読み込みは遅いしチラつくので避ける
2. メモリ上の分身(RecordsetClone)に探させる
3. 見つかったら `Bookmark` で画面を同期させる
この3ステップを理解できれば、あなたのAccess開発スキルは初級者を完全に卒業し、中級者・プロの領域へと足を踏み入れています。
複雑なUIフレームワークを使わなくても、Access標準の機能をここまで深く理解して使いこなせば、驚くほど軽快で実用的なシステムが作れます。ぜひ今日の業務から試してみてくださいね。あなたのAccessライフがもっと快適になりますように!
