【入門編】DAO.RecordsetのFindFirstメソッドとNoMatch判定による、高速なデータ検索エンジンの構築 – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。チーフアーキテクトの私です。

マクロの記録から一歩抜け出して、「自分の手で自由自在にシステムを操りたい!」そう思った時が、あなたのエンジニアとしての本当のスタートラインです。

今回は、Accessでの開発において避けて通れない「データの高速検索」について、魂を込めて解説します。

「フォームで大量のデータから特定の1件を探したい時、毎回クエリを実行していませんか?」
もしそうなら、今回の記事はあなたの開発ライフを劇的に変えるキッカケになります。ここをクリアすれば、Access VBAの基本とパフォーマンスの概念はバッチリですよ!一緒に本質をマスターしていきましょう。

1. なぜ「クエリの再発行」は遅いのか?

Accessで検索機能を実装する時、初学者がやりがちなのが「検索条件を変えるたびに、SQL(クエリ)を書き換えてフォームのデータソースに再設定する」という方法です。

‘ 【アンチパターン】やりがちな遅い検索処理
Me.RecordSource = “SELECT FROM T_顧客 WHERE 顧客名 LIKE ‘%” & Me.txtKeyword.Text & “%'”

これ、データが数万件程度ならまだ動きますが、ネットワーク越しの共有ファイル(バックエンドが別PC)だったり、データが数十万件に膨れ上がると、「画面が固まる(フリーズ)」現象を引き起こします。なぜなら、その都度データベースエンジンに重たい問い合わせ(I/O処理)が発生しているからです。

解決策:メモリ上に乗せた「DAO.Recordset」を叩け!

プロのエンジニアは、最初にデータをメモリ上(RAM)に読み込んでおき、その中を高速で駆け巡る「DAO.Recordset(レコードセット)」というオブジェクトを使います。メモリ上の検索であれば、体感できるほどのスピード差(圧倒的な高速化)を生み出すことができます。

2. 秘密兵器「FindFirstメソッド」と「NoMatchプロパティ」

メモリ上のRecordsetから目的のデータを一瞬で見つけ出すために用意されているのが、`FindFirst`メソッドです。

そして、検索した結果「見つかったのか、見つからなかったのか」を判定するのが`NoMatch`プロパティです。

この2つコンビの動きをイメージ図で見てみましょう。

[ DAO.Recordset(メモリ上のデータテーブル) ]
├── 1行目: ID=1, 顧客名=佐藤
├── 2行目: ID=2, 顧客名=鈴木 <-- FindFirst "顧客名 = '鈴木'" を実行! └── 3行目: ID=3, 顧客名=高橋 判定:NoMatch = False (見つかった!ポインタが2行目を指す) もし条件に合致するデータがなければ、`NoMatch` は `True` になります。このシンプルな真偽値判定を組み合わせるだけで、堅牢で高速な検索エンジンが作れるのです。 ---

3. 実践!高速データ検索エンジンの実装コード

それでは、実際の開発現場でそのままコピー&ペーストして使える、実用的なコードをご紹介します。

今回は、「社員ID」を入力して、フォームの表示位置(カレントレコード)をその社員に一瞬でジャンプさせる検索機能を実装してみましょう。

Option Compare Database
Option Explicit

‘ =====================================================================
‘ @Title: 社員マスター高速検索エンジン
‘ @Description: メモリ上のRecordsetを使い、クエリを発行せずに高速ジャンプする
‘ =====================================================================
Private Sub btnSearch_Click()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim searchID As Long

‘ 1. 入力値のバリデーション(空チェックなど)
If IsNull(Me.txtSearchID) Then
MsgBox “検索する社員IDを入力してください。”, vbExclamation, “入力エラー”
Me.txtSearchID.SetFocus
Exit Sub
End If

searchID = Me.txtSearchID.Value

‘ 2. 現在のデータベースへの参照を取得
Set db = CurrentDb

‘ 3. フォームが現在持っているレコードソースを、メモリ上のRecordsetとしてクローン取得
‘ ※ Me.RecordsetCloneを使うことで、フォームの表示速度を落とさずに裏で高速操作できます
Set rs = Me.RecordsetClone

‘ 4. FindFirstメソッドで条件に一致するデータを高速検索
‘ ※ 検索条件の書き方はSQLのWHERE句と同じです(数値はそのまま、文字列はシングルクォーテーションで囲む)
rs.FindFirst “社員ID = ” & searchID

‘ 5. NoMatchプロパティで結果を判定
If rs.NoMatch Then
‘ — 見つからなかった場合の処理 —
MsgBox “該当する社員IDが見つかりませんでした。”, vbInformation, “検索結果”
rs.Close
Set rs = Nothing
Set db = Nothing
Exit Sub
End If

‘ 6. 見つかった場合:フォームのブックマークを同期させて、画面をその行にジャンプさせる!
Me.Bookmark = rs.Bookmark

‘ 7. オブジェクトの解放(メモリリークを防ぐためのエンジニアの作法)
rs.Close
Set rs = Nothing
Set db = Nothing

MsgBox “データを検出しました。”, vbInformation, “完了”
End Sub

4. コードの深掘りとエンジニアの心得

ここで、コードの肝となる部分をいくつか補足します。初学者がハマりがちなポイントを先回りして潰しておきましょう。

① `Me.RecordsetClone` の魔法

コード内で `Set rs = Me.RecordsetClone` という記述をしています。
これは、今ユーザーが画面で見ているフォームのデータ構造を、そのままメモリ上に「複製(クローン)」する神機能です。ゼロからSQLを発行してデータを引っ張ってくる必要がないため、データベースに負荷をかけません。

② `Me.Bookmark = rs.Bookmark` による画面連動

`FindFirst` で見つかった位置(`rs.Bookmark`)を、フォームのブックマーク(`Me.Bookmark`)に代入しています。これにより、「メモリ上で見つけた位置」と「画面で表示している位置」が完全に同期し、フォームの表示がシュッとその行に移動します。

③ オブジェクトの解放(クリーンアップ)

VBAを書いていて絶対に忘れてはいけないのが、処理の最後にある以下の解放処理です。

rs.Close
Set rs = Nothing
Set db = Nothing

メモリ上に確保したリソース(DAOオブジェクト)をそのまま放置すると、メモリリーク(メモリの無駄遣い)を引き起こし、Access全体の動作が不安定になります。「開いたものは必ず閉じる。変数の中身は空にする(Nothing)」。これはプログラミングの世界の美徳であり、一流のエンジニアの絶対条件です。

まとめ

今回は、`DAO.Recordset`の`FindFirst`メソッドと`NoMatch`判定を用いた、高速なデータ検索エンジンの構築方法について解説しました。

  • クエリを何度も発行する古いやり方から脱却する
  • メモリ上の `RecordsetClone` を活用する
  • `FindFirst` と `NoMatch` でスマートに条件分岐する
  • 使い終わったオブジェクトは必ず解放する

この基本パターンを身につければ、あなたの作るAccessアプリケーションは見違えるほど軽快で、プロフェッショナルな動きをするようになります。

ここをクリアしたあなたなら、もうAccess VBAの基礎はバッチリです!
ぜひ今日の開発現場から取り入れて、その圧倒的なスピードの違いを体感してみてください。それでは、また次の極限知見でお会いしましょう!

タイトルとURLをコピーしました