【入門編】フォームの「RecordSource」をVBAで動的に書き換える検索画面の構築 – Access VBA解析バイブル

スポンサーリンク

こんにちは!チーフアーキテクトの私です。
マクロの記録から一歩抜け出し、「自分の手で自由自在にシステムを操りたい」と願うあなたへ。今日はいよいよ、Access開発の現場で最も使用頻度が高く、かつエンジニアとしての実力が試される「フォームのRecordSource動的書き換えによる検索画面の構築」について解説します。

ここをクリアすれば、Access VBAの基本はバッチリですよ。
データベースの心臓部をVBAで直接コントロールする、その爽快感を一緒に味わっていきましょう!

なぜ「RecordSourceの書き換え」が必要なのか?

Accessで検索画面を作るとき、よくある間違いが「全てのレコードを表示したクエリを基に、フィルター(Filterプロパティ)をカチカチと切り替える」というアプローチです。

件数が数百件程度ならこれでも動きますが、数万件を優に超える業務データになると、「最初に全部のデータを読み込もうとして画面がフリーズする」という致命的なパフォーマンス劣化を引き起こします。

プロのアーキテクトが選ぶアプローチは違います。
「検索条件に合致した最小限のSQLだけを組み立て、フォームのデータソース(RecordSource)そのものをスワップ(差し替え)する」のです。これなら、何百万件のデータがあろうが一瞬で画面が表示されます。

現場で使う検索フォームの全体像

イメージしてください。
あなたが今作っているのは「顧客管理システム」です。画面には以下のコントロールが配置されています。

  • テキストボックス(検索キーワード): `txtKeyword`
  • コンボボックス(顧客ランク): `cmbRank`
  • コマンドボタン(検索実行): `btnSearch`
  • データ表示用フォーム(連続フォーム): `fsub_CustomerList`

ユーザーが条件を入力して「検索」ボタンを押した瞬間、背後で何が起きているのか。そのメカニズムをコードで覗いてみましょう。

実践!動的SQL生成とRecordSourceの書き換えコード

検索ボタンの「クリック時」イベントに記述する、実戦形式のVBAコードがこちらです。そのままコピペして現場で使えるよう、細かくコメントを入れています。

Private Sub btnSearch_Click()
On Error GoTo ErrorHandler

Dim strSQL As String
Dim strWhere As String
Dim db As DAO.Database

‘ 1. 基本となるSQLのベース(SELECT句とFROM句)を定義する
strSQL = “SELECT CustomerID, CustomerName, Rank, Phone, UpdatedDate ” & _
“FROM M_Customer ”

‘ 2. 検索条件(WHERE句)の動的構築をスタート
strWhere = “WHERE 1=1 ” ‘ どんな条件が来てもANDで繋げられる魔法の定石

‘ 【条件A】キーワードが入力されている場合(部分一致検索)
If Not IsNull(Me.txtKeyword) And Me.txtKeyword <> “” Then
‘ SQLインジェクション対策としてシングルクォーテーションのエスケープに注意
strWhere = strWhere & “AND (CustomerName Like ‘” & Replace(Me.txtKeyword, “‘”, “””) & “‘ ” & _
“OR Phone Like ‘” & Replace(Me.txtKeyword, “‘”, “””) & ‘%’) ”
End If

‘ 【条件B】顧客ランクが選択されている場合(完全一致検索)
If Not IsNull(Me.cmbRank) And Me.cmbRank <> “” Then
strWhere = strWhere & “AND Rank = ‘” & Me.cmbRank & “‘ ”
End If

‘ 3. ベースSQLと動的WHERE句を結合し、オーダー(並び順)を付与
strSQL = strSQL & strWhere & “ORDER BY CustomerID DESC;”

‘ 4. デバッグ用:イミディエイトウインドウに完成したSQLを出力(プロの必須テクニック)
Debug.Print strSQL

‘ 5. サブフォームのRecordSourceに流し込み、データを再クエリする
‘ ※メインフォーム内に配置されたサブフォームコントロール名を “fsub” と仮定
Me.fsub_CustomerList.Form.RecordSource = strSQL
Me.fsub_CustomerList.Form.Requery

Exit Sub

ErrorHandler:
MsgBox “検索処理中に予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”
End Sub

コードの核心を読み解く 3つの重要ポイント

初学者のあなたが「おっ」と躓きやすいポイントを、エンジニアの視点で解説しておきますね。

① 魔法の構文 `WHERE 1=1` の正体

SQLを動的に組み立てるとき、「最初の条件には `WHERE` をつけ、2つ目以降の条件には `AND` をつける」という分岐を書くのは非常にコードが汚くなります。
最初から `WHERE 1=1`(常に真となる条件)を置いておけば、その後に続く条件をすべて `AND …` で機械的に連結できるため、コードが劇的にシンプルになります。これは現場の常識テクニックです。

② デバッグの神様 `Debug.Print`

VBAでSQL文を組み立てると、「あれ?スペースが抜けて構文エラーになる」「シングルクォーテーションの閉じ忘れで怒られる」ということが必ず起きます。
そんなときは、コード実行後に[Ctrl] + [G]を押して「イミディエイトウインドウ」を開いてください。そこに表示されたSQLをそのままAccessのクエリデザイナに貼り付ければ、一発でエラーの原因が特定できます。

③ サブフォームへのアプローチ経路

メインフォームからサブフォームのプロパティ(RecordSourceなど)を書き換えるときは、オブジェクトの階層構造を正確に指定する必要があります。
`Me.サブフォームコントロール名.Form.RecordSource` というドットつなぎの作法を体に覚え込ませましょう。

陥りやすい罠:「検索結果が0件のとき」の恐怖

動的SQLを使った検索画面で最も多いトラブルが、「条件に合うデータが1件もなかったとき、フォームのテキストボックスがエラー表示(#Deletedなど)になる」という現象です。

これを防ぐためには、RecordSourceを書き換える前に、レコードが存在するかどうかを`DCount`などで事前にチェックするか、あるいはエラートラップ(`On Error GoTo`)を必ず仕込んでおくことがプロとしてのたしなみです。

‘ 事前に件数チェックを入れるアプローチの例
Dim lngCount As Long
lngCount = Nz(DCount(“CustomerID”, “M_Customer”, Mid(strWhere, 7)), 0) ‘ WHEREを取り除いた条件を渡す

If lngCount = 0 Then
MsgBox “該当するデータは見つかりませんでした。”, vbInformation, “検索結果”
‘ あえて空のレコードソースを割り当てて画面をクリアする
Me.fsub_CustomerList.Form.RecordSource = “SELECT FROM M_Customer WHERE 1=0;”
Exit Sub
End If

※`WHERE 1=0` は、データ構造(列定義)だけを残してレコードを1件も返さない、ビュークリアの定石技です。

最後に:エンジニアリングを楽しもう

フォームのRecordSourceをVBAで書き換える技術は、単なる「検索画面の作り方」にとどまりません。ユーザーの操作(UI)とデータベース(Data)をVBAという言語で自由自在に接着する、Access開発の最もエキサイティングな瞬間です。

最初は覚えることが多くてクラクラするかもしれませんが、一度この構造をマスターすれば、どんなに複雑な業務システムであっても怖くなくなります。

手を動かし、コードを書き、イミディエイトウインドウでSQLを睨みながら、自分だけのシステムを組み上げる喜びをぜひ噛み締めてください。
あなたのAccess開発ライフが、より一層素晴らしいものになることを応援しています!

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