こんにちは!Access VBAでの開発、日々の業務お疲れ様です。
マクロのボタンを押したはいいものの、画面が真っ白になってフリーズしたかのように固まり、「これ、ちゃんと動いてる……?」と不安になった経験はありませんか? 処理が終わるまでユーザーに画面を見つめて待ってもらうのは、モダンなシステム開発において少しストレスフルですよね。
今回は、そんな長時間処理のUX(ユーザー体験)を劇的に改善する「DAO.RecordsetのAbsolutePositionプロパティを活用した、滑らかな進捗バーの動的更新」について解説します。
ここをクリアすれば、Access VBAの基本だけでなく、プロ仕様の「魅せるUI設計」の感覚まで一気に身につきますよ。一緒にマスターしていきましょう!
—
なぜ「進捗バー」と「AbsolutePosition」なのか?
数万件規模のレコードをループ処理する際、VBAは既定で画面の描画を停止するため、Access全体が固まったようになります。ここで活躍するのが進捗バー(ProgressBar)ですが、「今、全体の何%が終わっているのか」を正確に知るには、レコードセットの現在地を把握する必要があります。
そこで登場するのが、今回主役に据える `AbsolutePosition`(アソリュート・ポジション) プロパティです。
AbsolutePositionとは?
DAOレコードセットオブジェクトが持つ、「現在ポインタが置かれているレコードのインデックス(何番目か)」を返すプロパティです。
※注意点として、このインデックスは `0` から始まります。つまり、最初のレコードは `0`、2番目は `1` となります。
—
実装の全体像とアーキテクチャ
今回は、以下のステップでスマートな進捗表示を実現します。
1. レコード件数の取得(総数の把握)
`RecordCount` プロパティを使う前に、必ず `.MoveLast` を実行してレコードセットを完全にポップュレート(実体化)させます。これ、DAOの鉄則です。
2. ループ処理とAbsolutePositionの監視
`Do Until` ループの中で、現在の `AbsolutePosition` を取得し、総件数に対する割合(パーセンテージ)を計算します。
3. 画面の滑らかな更新(DoEvents)
VBAにOSへ制御を一時返却させる `DoEvents` を挟むことで、進捗バーや画面がフリーズせずにスルスルと動くようになります。
—
実践!進捗バー連動のVBAコード
それでは、実際の開発現場でそのままコピペして使えるサンプルコードを見ていきましょう。
今回は、フォーム上に配置した「プログレスバー(Microsoft ProgressBar Control)」と「ラベル(進捗率表示)」を連動させる想定で記述しています。
‘ ==============================================================================
‘ メソッド名: UpdateDataWithProgress
‘ 概要 : 大量レコードの処理を行いつつ、AbsolutePositionで進捗バーを更新する
‘ ==============================================================================
Public Sub UpdateDataWithProgress()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim lngTotalCount As Long
Dim lngCurrentPos As Long
Dim dblPercent As Double
On Error GoTo ErrorHandler
‘ 1. データベースとレコードセットの初期化
Set db = CurrentDb
‘ ※ここでは例として「T_顧客マスタ」を対象にします
Set rs = db.OpenRecordset(“T_顧客マスタ”, dbOpenDynaset)
‘ レコードが1件もない場合のガード節
If rs.EOF Then
MsgBox “処理対象のデータが存在しません。”, vbInformation, “通知”
GoTo Cleanup
End If
‘ 2. 正確なレコード総数を取得するため、一旦末尾に移動する
rs.MoveLast
lngTotalCount = rs.RecordCount
rs.MoveFirst ‘ 先頭に戻して処理スタート
‘ フォーム側の進捗コントロール初期化(フォーム名: F_Progressを想定)
DoCmd.OpenForm “F_Progress”
Forms!F_Progress!ProgressBar.Min = 0
Forms!F_Progress!ProgressBar.Max = lngTotalCount
Forms!F_Progress!ProgressBar.Value = 0
Forms!F_Progress!LblStatus.Caption = “処理を開始します…”
‘ 3. メインのループ処理
Do Until rs.EOF
‘ — ここに実際のデータ更新処理を書きます(例:フラグを立てる) —
rs.Edit
rs!ProcessedFlag = True
rs.Update
————————————————————-
‘ 4. 現在位置(AbsolutePosition)の取得
‘ ※AbsolutePositionは0から始まるため、人間が見るために「+1」します
lngCurrentPos = rs.AbsolutePosition + 1
‘ 進捗率の計算
dblPercent = (lngCurrentPos / lngTotalCount) 100
‘ 5. フォームのプログレスバーとラベルを動的更新
Forms!F_Progress!ProgressBar.Value = lngCurrentPos
Forms!F_Progress!LblStatus.Caption = lngCurrentPos & ” / ” & lngTotalCount & ” 件処理中 (” & Format(dblPercent, “0.0”) & “%)”
‘ ★超重要:Windowsに画面描画の権利を戻す(これがないとバーが固まります)
DoEvents
‘ 次のレコードへ
rs.MoveNext
Loop
‘ 終了処理
Forms!F_Progress!LblStatus.Caption = “処理が完了しました!”
MsgBox “すべての処理が正常に完了しました。”, vbInformation, “完了”
Cleanup:
‘ 6. オブジェクトの開放(メモリリーク防止の極意)
If Not rs Is Nothing Then
rs.Close
Set rs = Nothing
End If
Set db = Nothing
‘ 進捗フォームを閉じる
If CurrentProject.AllForms(“F_Progress”).IsLoaded Then
DoCmd.Close acForm, “F_Progress”
End If
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”
Resume Cleanup
End Sub
—
押さえておきたい!プロエンジニアの知見と注意点
上記のコードには、現場で生き残るための「Accessの流儀」がいくつも詰まっています。いくつか重要なポイントを深掘りしておきましょう。
1. `rs.MoveLast` を忘れない
DAOの仕様上、レコードセットを開いた直後の段階では、正確な `RecordCount` が取得できない(あるいは最初の1件しかカウントされない)場合があります。「 `RecordCount` を使う前には必ず `.MoveLast` を呼ぶ」。これはAccess VBAにおける呪文のようなものだと覚えておいてください。
2. `DoEvents` の魔力とトレードオフ
コード内の `DoEvents` は、VBAの処理を一時中断してOSにイベント(画面の再描画やユーザーのマウス操作など)を処理させる命令です。
これがあるおかげで進捗バーが滑らかに動くのですが、あまりに毎回 `DoEvents` を挟むと、逆に全体の処理速度が低下するというジレンマがあります。
もし処理件数が数十万件に及ぶ場合は、`If lngCurrentPos Mod 100 = 0 Then` のように、100件に1回だけ画面を更新する間引き処理を入れると、パフォーマンスとUXのバランスが劇的に向上します。
3. オブジェクトのクリーンアップ(メモリ管理)
コードの最後にある `Cleanup` ラベル。エラーが起きようが正常終了しようが、必ず `rs.Close` と `Set rs = Nothing` を通るように設計しています。これをサボるとAccessのメモリが徐々に圧迫され、や挙句の果てにファイルが破損する原因になります。プログラミングの美しさは、後始末の徹底さに宿ります。
—
まとめ
今回は `DAO.Recordset.AbsolutePosition` を軸にした、滑らかな進捗バーの実装方法を解説しました。
- `AbsolutePosition` で今の進捗(何番目か)を正確にキャッチする。
- `MoveLast` で総件数を確実に把握する。
- `DoEvents` でユーザーを待たせない優しい画面を作る。
この3つを抑えるだけで、あなたが書くAccessアプリケーションのクオリティは、プロのエンジニアが作ったそれと同等レベルに跳ね上がります。ぜひ、日々の業務システムやツール開発に取り入れてみてくださいね。
「ここをもっと詳しく知りたい!」というリクエストがあれば、いつでも先輩エンジニアにお声がけください。あなたのAccess VBAライフを応援しています!
