【入門編】DAOのFindFirstとADOのFilter:検索速度を比較し最適なメソッドを選択する – Access VBA解析バイブル

スポンサーリンク
スポンサーリンク

Access VBAの深淵へようこそ:DAOのFindFirstとADOのFilter、どちらを選ぶべきか?

こんにちは。今日までマクロの記録や、断片的なコードの書き写しで頑張ってきたあなた。その努力は素晴らしいものです。しかし、もしあなたが「プログラムがなぜか遅い」「もっとスマートに書きたい」と感じ始めているなら、それはあなたが「エンジニア」への入り口に立っている証拠です。

今日は、Access VBAにおける二大勢力、DAO(Data Access Objects)とADO(ActiveX Data Objects)のアーキテクチャの違い、そして検索処理における「決定的な使い分け」についてお話ししましょう。

単なる「書き方の違い」ではありません。これは「データの動き(ライフサイクル)」を支配するための知恵です。ここをクリアすれば、あなたのAccessアプリケーションは別次元のスピードと安定性を手に入れることができますよ。

1. そもそも、DAOとADOは何が違うのか?

「どちらもデータを扱うものじゃないか」と思うかもしれません。しかし、その立ち位置は全く異なります。

DAO:Accessエンジンの「直通電話」

DAOは、Accessの心臓部である「Jet/ACEエンジン」のために設計された、いわば純正の通信手段です。Accessのテーブル構造やインデックス(索引)を最も深く理解しており、エンジンに対して「このインデックスを使って、この値を直接見つけて!」と、最短距離で命令を伝えることができます。

ADO:外部世界への「万能な翻訳機」

一方、ADOは、SQL ServerやOracleといった外部のデータベースとも対話できるように作られた、汎用的な通信手段です。非常に洗練されたインターフェースを持っていますが、Access内部で使う場合、一度「翻訳」の工程が入るため、DAOに比べるとわずかにオーバーヘッド(余計な負荷)が生じることがあります。

2. 検索メソッドの正体:FindFirst vs Filter

さて、本題の検索メソッドについて掘り下げましょう。ここがパフォーマンスの分岐点です。

DAOの `FindFirst`:インデックスを駆使する「一撃の狙撃手」

`FindFirst`は、レコードセットの中を先頭から順番に、あるいはインデックス(索引)を使って、条件に一致する最初の1件を探し出すメソッドです。

  • 動作の仕組み: もし検索対象のフィールドに「インデックス」が貼られていれば、エンジンは全データを走査することなく、インデックスを辿って一瞬で目的の場所にジャンプします。
  • 得意なこと: 「特定のIDを持つレコードを1件だけ見つけたい」という、ピンポイントな検索。

ADOの `Filter`:条件で切り取る「魔法のフィルター」

`Filter`プロパティは、レコードセット全体の中から、条件に一致するものだけを抽出した「新しいサブセット(部分集合)」をメモリ上に作り出す操作です。

  • 動作の仕組み: 条件に合うレコードをすべて抽出し、それだけが見える「窓」を新しく作り直すイメージです。
  • 得意なこと: 「『売上高が10万以上』のレコードだけを一覧表示したい」という、条件に合うグループの抽出。

3. 実践コード:使い分けの極意

では、実際にどのようにコードを書くべきか、比較してみましょう。

【パターンA】DAOで高速に1件を特定する

大量のデータ(例:10万件の顧客マスタ)から、特定の社員番号を探す場合は、迷わずDAOの`FindFirst`を選んでください。

Sub SearchWithDAO()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim targetID As String
    
    targetID = "E12345" ' 探したいID
    
    Set db = CurrentDb
    ' テーブルを開く(インデックスが効くようにする)
    Set rs = db.OpenRecordset("T_Employee", dbOpenDynaset)
    
    ' 【ここがポイント】FindFirstを使用
    ' インデックスが貼られていれば、爆速で完了します
    rs.FindFirst "EmployeeID = '" & targetID & "'"
    
    If Not rs.NoMatch Then
        Debug.Print "発見! 氏名: " & rs![EmployeeName]
    Else
        Debug.Print "見つかりませんでした。"
    End If
    
    ' 後始末はエンジニアのたしなみ
    rs.Close
    Set rs = Nothing
    Set db = Nothing
End Sub

【パターンB】ADOで条件に合うリストを抽出する

「特定の部署に所属するメンバー全員」を抽出して、何らかの処理を行いたい場合は、ADOの`Filter`が直感的で使いやすい場面があります。

Sub FilterWithADO()
    Dim cn As ADO.Connection
    Dim rs As ADO.Recordset
    Dim filterStr As String
    
    filterStr = "Department = 'Sales'" ' 部署がSalesの人
    
    Set cn = CurrentProject.Connection
    Set rs = New ADO.Recordset
    
    ' レコードセットを開く
    rs.Open "T_Employee", cn, adOpenStatic, adLockReadOnly
    
    ' 【ここがポイント】Filterを使用して、条件に合うものだけに絞り込む
    ' 抽出された「新しい集合」に対して操作を行うイメージです
    rs.Filter = filterStr
    
    If rs.EOF Then
        Debug.Print "該当者なし"
    Else
        Do Until rs.EOF
            Debug.Print "氏名: " & rs!EmployeeName
            rs.MoveNext
        Loop
    End If
    
    ' 後始末
    rs.Close
    Set rs = Nothing
    Set cn = Nothing
End Sub

4. 結論:どちらを選ぶべきか?(判断基準チャート)

迷ったときは、以下の基準を思い出してください。

状況 推奨メソッド 理由
大量のデータから1件だけ探したい DAO `FindFirst` インデックスを活用でき、メモリ消費も最小限で済むため。
条件に合う「グループ」を扱いたい ADO `Filter` 抽出後の集合に対して、そのままループ処理などが容易に行えるため。
Access内のローカルテーブルを扱う DAO エンジン直結の圧倒的なパフォーマンスを享受できるため。
SQL Serverなどの外部DBを扱う ADO 外部接続の標準的な作法であり、汎用性が高いため。

⚠️ 初学者が陥りやすい「落とし穴」

「ループの中で `Filter` を何度も呼び出さないこと」

これが最も重要なアドバイスです。
例えば、「1,000件のデータに対して、1件ごとに `Filter` をかけて新しいサブセットを作る」という処理を書いてしまうと、そのたびにメモリ上に新しい集合が構築され、動作は劇的に重くなります。

このような場合は、「最初からSQL(SELECT文)で条件を絞り込んでからレコードセットを開く」のが、プロのアーキテクトのやり方です。

最後に

DAOとADOの違いを理解することは、単に「動くコード」を書く段階から、「効率的なシステム」を設計する段階へステップアップすることを意味します。

「なぜこのメソッドを使うのか?」
その理由を、データの動き(インデックスなのか、新しい集合なのか)の観点から説明できるようになれば、あなたはもう立派なエンジニアです。

一歩ずつ、確実に。コードの裏側にある「理(ことわり)」を楽しんでくださいね。応援していますよ!

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