こんにちは。現場の最前線でAccessと格闘している皆さん、お疲れ様です。
「ボタンを押した瞬間、Accessが『応答なし』になって固まる……」
「数百万件のデータを処理しようとしたら、終わるまで祈るしかない……」
そんな経験はありませんか?もしあるなら、今日でその「祈るだけの開発」とはおさらばしましょう。今日は、QueryDef(クエリ定義)を極め、大規模データをスマートに捌くための「非同期的な分割処理」という奥義を伝授します。
—
1. なぜAccessは「固まる」のか?
Accessがフリーズするのは、「CPUの全リソースを一つのクエリ処理に注ぎ込み、OSからの『生きてるか?』という問いかけに応答できなくなるから」です。
VBAで `DoCmd.RunSQL` や `db.Execute` を投げると、Accessは「処理が終わるまで他のことは一切受け付けない」というストイックすぎるモードに入ります。大規模データなら数分かかることもあり、ユーザーは「壊れた?」と思って強制終了したくなる。これが悲劇の始まりです。
これを防ぐ鍵は、「重い処理を、小さな塊に分割して投げ、間に『休憩(DoEvents)』を挟む」という戦略です。
—
2. 魔法のメソッド:DoEventsと分割処理
「進捗表示」と「フリーズ回避」を同時に実現する、現場で使える最小構成のコードを紹介します。
実践:QueryDefを用いた分割実行のテンプレート
このコードは、大きなデータを「IDの範囲」で区切り、少しずつ処理することで、OSへの応答権を維持しつつ進捗をバーに表示する仕組みです。
Public Sub ProcessLargeData()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim i As Long
Dim totalSteps As Long: totalSteps = 10 ‘ 10分割で処理する例
Dim batchSize As Long: batchSize = 1000 ‘ 1ブロックあたりの件数
Set db = CurrentDb
‘ あらかじめ用意したパラメータークエリ名
Set qdf = db.QueryDefs(“qsel_HeavyProcess”)
‘ フォーム上のプログレスバーを想定
For i = 0 To totalSteps – 1
‘ パラメーターに範囲を指定(ここで動的SQLの制御を行う)
qdf.Parameters(“pStartID”) = i batchSize
qdf.Parameters(“pEndID”) = (i + 1) batchSize
‘ クエリ実行
qdf.Execute dbFailOnError
‘ — ここが重要! —
‘ OSに処理権を返し、フリーズを防ぐ魔法の関数
DoEvents
‘ 進捗表示(フォームのラベルなどを更新)
Forms!frmProgress!lblStatus.Caption = (i + 1) 10 & “% 完了…”
Next i
MsgBox “処理が完了しました!”
End Sub
コードの解説
- `QueryDef` を使う理由: 文字列結合でSQLを組み立てるのではなく、パラメーター付きのQueryDefを使い回すことで、実行計画がキャッシュされ、実行速度が劇的に向上します。
- `DoEvents`: これが伝説の呪文です。これをループ内に入れるだけで、Accessは「おっと、OSさん待たせてごめん」と、入力受付や画面描画を裏で処理してくれるようになります。
- `dbFailOnError`: エラー発生時に即座にトランザクションをロールバックするための必須オプションです。
—
3. 陥りやすい罠:なぜ「動的SQL」を避けるべきか
初心者の頃は、`”SELECT FROM Tbl WHERE ID = ” & i` のように、SQLを文字列として生成しがちです。しかし、大規模データではこれが致命的になります。
1. コンパイルコスト: SQL文字列を組み立てるたびに、Accessはそれが正しい文法かを解析します。数万回繰り返すと無視できないロスになります。
2. セキュリティ: SQLインジェクションのリスクもゼロではありません。
「クエリは定義しておき、値だけを差し替える」。これがプロの流儀です。
—
4. さらなる高みへ:進捗表示のコツ
プログレスバーを表示する際、`Forms!frmProgress!lblStatus.Caption` を直接いじるのも良いですが、さらにリッチにするなら「ラベルの横幅(Width)」を計算して動的に変化させるのがスマートです。
‘ 進捗に応じてバーの長さを変える
Forms!frmProgress!boxBar.Width = (i / totalSteps) 5000 ‘ 5000は最大幅
これだけで、ユーザーは「あ、ちゃんと動いているんだな」と安心感を持って待つことができます。「待たせること」そのものよりも「進捗が見えないこと」がユーザーのストレスの正体なのです。
—
まとめ:Access VBAを使いこなすために
今回お伝えした「QueryDefのパラメーター化」と「DoEventsによる応答性確保」は、Access開発の現場における「生命線」です。
- 重い処理は分割する。
- `DoEvents` を忘れない。
- 文字列結合でのSQL作成は卒業し、`QueryDef` を愛する。
この3つを意識するだけで、あなたの作るツールは「固まるポンコツ」から「現場を支える堅牢なシステム」へと進化します。
「ここをクリアすれば、Access VBAの基本はバッチリですよ」。
次は、エラーハンドリングを完璧にして、より堅牢なプログラムを目指しましょう。何か疑問があれば、いつでも聞いてくださいね。応援しています!
