こんにちは! Access VBAの海原へようこそ。
マクロの記録ボタンを押す時代を抜け出し、「自分の手でシステムをコントロールしたい」と一歩を踏み出したあなたへ。今日は、Access開発において避けて通れない、しかしここさえ押さえれば一気にプロの領域に近づける「データ検索エンジン」の極意を伝授します。
「フォームで大量のデータから目的の1件パッと探したいとき、毎回データベースにSQLの重い処理を投げていませんか?」
もしそうなら、ちょっと待ってください。Accessの裏側で動いている「DAO.Recordset」のメモリ上検索を使いこなせば、驚くほど軽快でスマートな検索エンジンが作れるんです。
ここをクリアすれば、Access VBAの基本はバッチリですよ。さあ、一緒に本質を紐解いていきましょう!
—
1. なぜ「SQL」ではなく「DAO.Recordset」なのか?
AccessVBAでデータを扱うとき、私たちはよくSQL文(`SELECT FROM …`)を書きます。もちろんSQLは強力ですが、画面上のフォームと連動して「あ、この顧客コードの人を表示して!」というようなインタラクティブな操作を行う場合、毎回SQLを発行するのは、いわば「本棚から一冊探すために、毎回図書館の外に出て司書に新しく本を取りに行かせる」ようなもの。大げさですね。
ここで登場するのが DAO.Recordset(データアクセスオブジェクト・レコードセット) です。
メモリ上に「データの縮図」を展開する
DAO.Recordsetを使うと、テーブルやクエリのデータをまるごとメモリ上にロードし、その中を自在に駆け巡ることができます。
今回紹介する `FindFirst` メソッドは、メモリ上に展開されたデータ空間を一瞬でスキャンし、条件に一致するレコードの場所を指し示してくれる強力な機能です。
—
2. 検索エンジンの心臓部:`FindFirst` と `NoMatch` の黄金律
メモリ上を高速に検索するとき、VBAエンジニアが必ずセットで使う呪文があります。それが以下の2つです。
1. `FindFirst “検索条件”`
レコードセットの先頭から条件に合うデータを探しに行きます。
2. `.NoMatch` プロパティ
「見つからなかったかどうか?」を教えてくれる判定フラグです。
⚠️ ここで絶対につまづくポイント(初心者必見エラー)
プログラミング初心者が一番やりがちなミスがこれです。
‘ ❌ やりがちなNGコード
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset(“T_顧客”)
rs.FindFirst “顧客ID = 999”
‘ いきなり見つかった前提でデータを触ると、見つからなかった時に「13: 型が一致しません」や「3021: 現在レコードがありません」エラーで爆発します!
MsgBox rs!顧客名
【鉄則】 `FindFirst` を使ったら、必ずその直後で `NoMatch` をチェックする。これがプロの流儀です。
—
3. 実践!高速データ検索エンジンを実装する
それでは、実際の現場でそのままコピペして使える実用コードを見てみましょう。
今回は、フォームに入力された「顧客ID」をキーにして、一瞬で該当レコードを特定し、フォームに表示させるプロシージャを組み立てます。
‘ =====================================================================
‘ プロシージャ名:SearchCustomer
‘ 概要:DAO.RecordsetのFindFirstを使い、メモリ上から高速に顧客を検索する
‘ =====================================================================
Public Sub SearchCustomer(ByVal targetID As Long)
On Error GoTo ErrorHandler
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strCriteria As String
‘ 1. データベースとレコードセットの取得(現在のDBを指す CurrentDb を使用)
Set db = CurrentDb
‘ テーブル「T_顧客」を加工しやすいようにダイナセット型で開く
Set rs = db.OpenRecordset(“T_顧客”, dbOpenDynaset)
‘ 2. 検索条件の文字列を作成(数値型の場合はそのまま、文字列なら ‘ で囲む)
strCriteria = “顧客ID = ” & targetID
‘ 3. メモリ上で高速検索を実行!
rs.FindFirst strCriteria
‘ 4. 【最重要】NoMatchプロパティで成否を判定する
If rs.NoMatch Then
‘ 該当データがなかった場合の処理
MsgBox “指定された顧客ID「 ” & targetID & ” 」は存在しません。”, vbExclamation, “検索結果”
Else
‘ 該当データが見つかった場合の処理
MsgBox “見つかりました! 顧客名: ” & rs!顧客名, vbInformation, “検索成功”
‘ 応用:もしこのコードをフォームのモジュールで書いているなら、
‘ Me.Bookmark = rs.Bookmark とすることで、フォームの表示位置を
‘ 一瞬でそのレコードにジャンプさせることができます!
End If
CleanUp:
‘ 5. 【オブジェクトの解放】メモリリークを防ぐためのプロの作法
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub
コードの解説と「プロの知見」
- `CurrentDb` の正しい寿命管理
`CurrentDb` は呼び出すたびに新しいデータベースオブジェクトを生成します。そのため、変数に一度受け取って使い終わったら確実に `Set db = Nothing` で解放することが、Accessの動作を安定させる秘訣です。
- オブジェクトの解放(CleanUpラベル)
VBAでは、開いたレコードセット(`rs.Close`)やデータベースは自分で片付ける必要があります。これをサボるとAccessファイルが重くなったり、メモリリークの原因になります。どんなエラーが起きても必ず最後に掃除をする「ジャンプ構文(`On Error GoTo` とラベル)」は、実務では必須のテクニックです。
—
4. まとめ:Access VBAの基本は「メモリとオブジェクト」の理解から
いかがでしょうか? `FindFirst` と `NoMatch` を組み合わせた検索エンジンは、SQLを毎回発行するよりもはるかに軽量で、かつコードの構造もシンプルです。
- データをメモリに載せる(`OpenRecordset`)
- 一瞬で探す(`FindFirst`)
- いない場合の備えをする(`NoMatch`)
- 使い終わったら綺麗に片付ける(`Set Nothing`)
この4つのステップをマスターしたあなたなら、もう「マクロの記録」に頼る必要はありません。ご自身のシステムにこのエンジンを組み込んで、サクサク動く快適なAccessアプリケーションを構築してみてくださいね。
ここをクリアしたあなたなら、Access VBAの基本はもうバッチリです!次のステップへ進みましょう。応援しています!
