【入門編】【初心者】DAO.Recordsetの「EOF」と「BOF」:空レコードセットによる実行時エラーを撲滅する – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。
マクロの記録から一歩踏み出し、自分の手でコードを書いてシステムを動かそうとしているあなたへ、今日はとても大切な、そして絶対に避けて通れない「データ操作の基本と防衛策」をお伝えします。

ここをクリアするかどうかで、あなたの書くVBAの信頼性が劇的に変わります。心してかかると身構える必要はありませんよ。優しく、本質からしっかり解説していきますね。

1. なぜ、Recordsetはいきなり牙をむくのか?

Access VBAでデータベースの中身を操作するとき、私たちはDAO(Data Access Objects)という仕組みを使います。その主役が `Recordset`(レコードセット)です。

例えば、「顧客テーブルから特定の顧客を探し出して処理する」というコードを書いたとします。

Dim db As DAO.Database
Dim rs As DAO.Recordset

Set db = CurrentDb
Set rs = db.OpenRecordset(“T_顧客”)

‘ 見つかった最初の顧客の名前を表示する
MsgBox rs!顧客名

rs.Close
Set rs = Nothing
Set db = Nothing

このコード、一見すると完璧に見えますよね?
しかし、もし 「T_顧客」テーブルが空っぽ(データが1件もない状態) だったとしたらどうなるでしょうか?

正解は……実行時エラー(「No current record.」など)が発生し、容赦なくプログラムが強制終了します。

初心者の方が最初に直面する「なぜか動いたり止まったりする謎のエラー」の多くは、これが原因です。データベースには「データが1件もない」という状況が日常茶飯事に起こり得ます。その現実を無視して、いきなり「中身をくれ!」と要求するから、VBAがパニックを起こしてしまうのです。

2. 「EOF」と「BOF」という2つの境界線を知る

データがない状態や、データの端っこにいる状態をVBAに伝えるための仕組みが、`EOF``BOF` です。

これらは変数ではなく、Recordsetオブジェクトが持つ「状態(フラグ)」です。それぞれ英語の略称で、以下のような意味を持っています。

  • EOF (End Of File): データの「最後尾」よりも後ろにいる状態
  • BOF (Begin Of File): データの「最先端」よりも前にいる状態

図解:Recordsetの迷宮とポインタ

Recordsetを開いたとき、VBAの「現在地を示すポインタ(目印)」は、データの先頭に立っています。

【データが3件あるとき】
[BOF = False] (先頭よりは後ろにいる)

[ 1件目:田中さん ] <-- 最初はここにポインタがある (Current Record) [ 2件目:鈴木さん ] [ 3件目:佐藤さん ] ↓ [EOF = False] (まだ最後尾には到達していない) もし、データが1件もない(空っぽの)場合、世界はどうなるでしょうか?

【データが0件(空)のとき】
[BOF = True] \
> ポインタを置く場所がない!
[EOF = True] / 最初から最後までが行き止まり

データが1件もないとき、Recordsetを開いた瞬間から `BOF` も `EOF` も両方とも `True` になります。「ここには何もありません」というサインです。

3. 実践!エラーを撲滅する防御的プログラミング

この性質を利用すれば、「データがあるかどうか」を事前にチェックし、エラーを完全防御することができます。

ここからが、プロのエンジニアも必ず書く「鉄壁のコードパターン」です。しっかり覚えていってくださいね。

パターンA:データが存在するかチェックしてから処理する

「そもそもデータが0件なら、何もしない(あるいはメッセージを出す)」という最も安全なアプローチです。

Sub CheckDataExists()
Dim db As DAO.Database
Dim rs As DAO.Recordset

Set db = CurrentDb
Set rs = db.OpenRecordset(“T_顧客”, dbOpenDynaset)

‘ 【防御策】EOFとBOFの両方がTrueなら、データは1件もない!
If rs.EOF And rs.BOF Then
MsgBox “対象となるデータが1件も存在しません。”, vbExclamation, “通知”
GoTo Cleanup ‘ 後処理へジャンプ
End If

‘ — ここから下に書くコードは、絶対にデータが存在することが保証されている安全地帯 —
Do Until rs.EOF
Debug.Print rs!顧客名
rs.MoveNext ‘ 次のレコードへ移動
Loop

Cleanup:
‘ 忘れずにオブジェクトを解放する(メモリリーク防止の極意)
If Not rs Is Nothing Then rs.Close
Set rs = Nothing
Set db = Nothing

MsgBox “処理が完了しました。”, vbInformation
End Sub

コードの解説と優しさのポイント

1. `If rs.EOF And rs.BOF Then`
これが今回の最重要ポイントです。DAOの仕様上、「Recordsetが空のときは `EOF` も `BOF` も `True` になる」という鉄則があります。この条件で最初にガードしておけば、後続の処理でエラーが出ることはまずありません。
2. `Do Until rs.EOF`
データがあることが保証された世界でのループ処理です。「EOF(最後尾を過ぎる)に到達するまで繰り返せ」という意味になります。
3. クリーンアップの習慣
処理が終わったら必ず `Close` し、`Nothing` を代入してメモリを解放します。これをサボらないのが、ワンランク上のエンジニアへの第一歩です。

4. ここをクリアすれば、Access VBAの基本はバッチリですよ

今回は、Recordsetの最大の罠である「空のレコードセット」と、それを防ぐ `EOF` / `BOF` の使い方について解説しました。

  • データがないテーブルをいきなり触ると、VBAは泣き出してしまう(エラーになる)。
  • 開いた直後に `If rs.EOF And rs.BOF Then` で空っぽかどうかを必ず確認する。
  • この防壁を作っておけば、予期せぬエラーでユーザーを困らせることがなくなる。

この「もしデータがなかったら?」という視点(防御的プログラミング)を持てるようになったあなたは、もう「マクロの記録をなんとなく直している初心者」ではありません立派なVBAプログラマーです。

日々の開発でテーブルを操作するときは、ぜひこの「EOFとBOFのチェック」を思い出してくださいね。あなたのAccess開発ライフを、これからも応援しています!

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