こんにちは!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開発ライフを、これからも応援しています!
