こんにちは! Accessでのアプリ開発、日々のメンテナンスお疲れ様です。
マクロの記録から一歩踏み出し、「自分でコードを書いて自由自在にコントロールしたい!」という熱意、本当に素晴らしいですね。
Access VBAの世界へようこそ。ここをクリアすれば、あなたのAccess開発スキルは間違いなく一段上のステージに上がります。ぜひ最後までお付き合いください。
—
現場でよくある「あのイライラ」、実は一発で解決できます
サブフォームの一覧から特定のレコードを選んで、ボタン一つでデータを処理する……よくある要件ですよね。
でも、こんな現象に悩んだことはありませんか?
- 「処理を実行したら、画面が勝手に一番上の行に戻っちゃったんだけど!」
- 「さっきまで見ていた行を探すのに、毎回スクロールし直さなきゃいけない……これじゃユーザーに怒られちゃうよ」
そう、Access VBA初心者が必ずと言っていいほどぶつかる壁が、「処理が終わったあとに、元のフォーカス位置を復元できない問題」です。
レコードを更新したり再クエリ(再読み込み)をかけたりすると、Accessは冷酷にもカーソルを一番上の行に戻してしまいます。これをスマートに解決する魔法の鍵が、今回解説する `Bookmark`(ブックマーク)プロパティ です。
ここをクリアすれば、プロ顔負けの滑らかなUI(ユーザーインターフェース)が作れるようになりますよ。さあ、一緒に本質をマスターしていきましょう!
—
DAO.Recordsetの「Bookmark」ってそもそも何?
難しく考える必要はありません。`Bookmark`とは、一言で言うと「現在地を示す特等席のチケット」です。
Accessのテーブルやクエリの裏側では、DAO.Recordsetというデータ管理のエンジンが動いています。Recordsetはたくさんのレコード(行)の束ですが、その中で「今、自分はどこを指しているのか」を記憶しておくための固有の識別子(バイト配列のデータ)がブックマークです。
ブックマークのライフサイクル(重要!)
プログラミングの世界で「今どこにいるか」を覚えるとき、行番号(1行目、2行目…)を使いたくなりますよね。でも、ちょっと待ってください。
もし処理の途中で他の人がデータを追加したり削除したりしたら、行番号なんてあっという間にズレてしまいます。
その点、`Bookmark`はデータ自体の「身分証明書」のようなもの。たとえ途中で並び替えが行われようとも、そのレコードが存在する限り、正確に「そこ」を指し示し続けてくれます。
—
実践!元の位置へ正確に戻るコードの書き方
百聞は一見に如かず。実際のフォーム上に配置されたサブフォームのデータを操作するコードを見てみましょう。
今回は、「サブフォームで選択されている行の特定のフィールド(例: `Status`)を『完了』に書き換え、処理後もユーザーがその行を見失わないように元の位置へフォーカスを戻す」というシナリオです。
Public Sub UpdateSelectedRecord()
Dim rst As DAO.Recordset
Dim varBookmark As Variant
‘ 1. サブフォームのレコードセットオブジェクトを取得する
‘ ※ “SubFormName” はご自身の環境のサブフォームコントロール名に書き換えてください
Set rst = Me.SubFormName.Form.Recordset
‘ サブフォームにデータがない、またはレコードが選択されていない場合は抜ける
If rst.RecordCount = 0 Then
MsgBox “処理するデータがありません。”, vbExclamation, “確認”
Exit Sub
End If
On Error GoTo ErrorHandler
‘ 2. 処理前の「現在地(ブックマーク)」を変数に記憶する!
‘ これが今回の主役です。現在の位置をしっかりキープします。
varBookmark = rst.Bookmark
‘ 3. 実際のデータ処理(トランザクションや更新処理)
‘ ここでは例として、現在のレコードの編集を開始して値を書き換えます
rst.Edit
rst!Status = “完了”
rst.Update
‘ 4. 画面の表示を最新の状態に更新する(Requery)
‘ ※再クエリすると通常はカーソルが先頭に戻ってしまいます
Me.SubFormName.Form.Requery
‘ 5. 【最重要】記憶していたブックマークを使って、元の位置へ華麗に戻る!
‘ DAOのRecordsetオブジェクトのBookmarkプロパティに先ほどのチケットを渡します
rst.Bookmark = varBookmark
‘ 視覚的にもサブフォームのフォーカス(カレントレコード)を同期させる
Me.SubFormName.Form.Bookmark = varBookmark
MsgBox “選択された行の処理が完了し、元の位置に戻りました!”, vbInformation, “成功”
CleanUp:
‘ オブジェクト変数を解放してメモリをクリーンに(プロのたしなみです)
Set rst = Null
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
—
コードのポイントと、陥りやすい罠(エラー対策)
上のコードには、プロのエンジニアが現場で必ず組み込んでいる「知見」が詰まっています。いくつか重要なポイントを解説しますね。
1. バリアント型(Variant)で受けるのが鉄則
`Bookmark`プロパティに格納される値は、単純な数値や文字列ではなく、Access内部で使われる特殊なバイナリデータ(バイト配列)です。そのため、変数を宣言するときは必ず `Dim varBookmark As Variant` としてください。`String`や`Long`で受けると、型不一致エラー(Error 13)で盛大にコケます。
2. 再クエリ(Requery)とのコンボ技
データを書き換えた後、画面上の表示を最新にするために `Requery` を行うのが一般的です。しかし、`Requery` を実行すると、Recordsetは一度破棄されて再構築されるため、カレント位置の記憶がリセットされてしまいます。
だからこそ、「Requeryする直前にBookmarkを退避させ、Requeryした直後にBookmarkを代入し直す」というこのサンドイッチ構造が絶対的な正解になります。
3. レコードが削除された場合のエラーに注意
もし処理の中で「そのレコード自体を削除(Delete)」してしまった場合は要注意です。この場合、当然ながら「元の場所」はもう存在しないため、`rst.Bookmark = varBookmark` を実行した瞬間にエラーになります。
レコードを削除した場合は、元の位置ではなく「次の行(`MoveNext`)」や「前の行」へ移動するロジックを組むのが優しさというものです。
—
まとめ:ここをクリアすれば、Access VBAの基本はバッチリですよ!
お疲れ様でした! `Bookmark` を使ったグリッド操作のイメージは掴めましたでしょうか?
最初は「なんだか難しそうなプロパティが出てきたな……」と感じたかもしれませんが、やっていることはシンプルです。
- 「行くぞ」と決めたら、現在地をバリアント変数にメモする
- どんなに遠く(再クエリなど)へ旅をしても……
- メモ(Bookmark)さえあれば、元の場所にいつでもピタッと戻ってこられる!
このパターンをマスターすれば、ユーザーから「使いやすい!」と絶賛される滑らかなAccessフォームが作れるようになります。ぜひ、あなたの開発するアプリケーションにも取り入れてみてくださいね。
それでは、次のステップでも一緒に楽しくプログラミングを極めていきましょう!
