【入門編】QueryDefの実行結果を「CSV」として非同期出力する:UIを止めないバックグラウンド処理 – Access VBA解析バイブル

スポンサーリンク

Access VBAで「画面フリーズ」を撲滅せよ!QueryDefと非同期CSV出力の極意

こんにちは。Access開発の現場で、一度は必ずぶつかる壁があります。「数万件のデータを抽出した瞬間、Accessがフリーズして応答なしになる」。

初心者の方が陥りやすいこの「魔の瞬間」を回避し、プロフェッショナルな挙動を実現する「非同期CSV出力」のテクニックを伝授します。単に動くコードを書くのではなく、「OSとアプリケーションの対話」を理解する、一歩先の世界へ行きましょう。

—

なぜ「フリーズ」が起きるのか?

Accessでクエリを実行すると、Accessは「全レコードをメモリ上に読み込み、画面のグリッドに描画する」という重い作業を一気に行います。これがCPUとメモリを占有し、OSが「Accessは死んだ」と誤認してフリーズ状態を誘発するのです。

私たちが目指すのは、「クエリの実行」と「ファイルへの書き出し」を小分けにし、その合間にOSに呼吸(休憩)させる処理です。

—

鍵となる技術:QueryDefとDoEvents

ここで登場するのが`QueryDef`と`DoEvents`です。

  • QueryDef: クエリをオブジェクトとして操作し、パラメータを柔軟に注入します。
  • DoEvents: これが魔法の関数です。実行中のVBAを一時停止させ、OSに「いま入力操作や画面更新のイベントを受け付けていいよ」と許可を与えます。

—

実践コード:非同期CSV出力の設計

以下のコードは、バックグラウンドでクエリを走らせながら、プログレスバーのように状況を更新しつつCSVを書き出す仕組みです。

Public Sub ExportQueryToCsvAsync(queryName As String, filePath As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rs As DAO.Recordset
Dim fileNum As Integer
Dim i As Long

Set db = CurrentDb
Set qdf = db.QueryDefs(queryName)

‘ パラメータがある場合はここで値を設定
‘ qdf.Parameters(“[開始日]”) = #2023/01/01#

‘ スナップショット形式で読み込む(高速化の鉄則)
Set rs = qdf.OpenRecordset(dbOpenSnapshot)

fileNum = FreeFile
Open filePath For Output As #fileNum

‘ レコードが空なら終了
If rs.EOF Then GoTo Cleanup

‘ 処理のループ
Do While Not rs.EOF
‘ 1行ずつCSV形式に変換して書き出し
Print #fileNum, rs!ID & “,” & rs!DataName & “,” & rs!Amount

rs.MoveNext

‘ 【重要】100件ごとに画面の更新権をOSに返却する
‘ これによりフリーズを防ぎます
If rs.AbsolutePosition Mod 100 = 0 Then
DoEvents
Debug.Print “処理中…” & rs.AbsolutePosition
End If
Loop

Cleanup:
Close #fileNum
rs.Close
Set rs = Nothing
Set qdf = Nothing
MsgBox “CSV出力が完了しました!”, vbInformation
End Sub

—

コードのポイント:ここを理解すればマスター!

1. `dbOpenSnapshot` の魔法

`OpenRecordset` を使う際、デフォルトではなくあえて `dbOpenSnapshot` を指定してください。これは「読み取り専用・メモリ内コピー」を意味し、データ編集のオーバーヘッドを省くため、純粋な抽出速度が段違いに速くなります。

2. `DoEvents` の立ち位置

`DoEvents` は強力ですが、多用しすぎると処理速度が落ちます。上記のコードのように `Mod 100 = 0`(100件ごと)といった具合に、適度なインターバルを設けるのが「プロの加減」です。

3. `FreeFile` の重要性

`Open #1` のように番号を決め打ちするのは危険です。他の処理がその番号を使っている可能性があるため、`FreeFile` 関数を使ってOSから空いているファイル番号を借りるのが、堅牢なコードの第一歩です。

—

陥りやすいエラーと対策

  • 「クエリが見つかりません」エラー: `QueryDefs` は保存済みのクエリしか参照できません。動的SQLを生成する場合は、一時的に `CREATE QUERYDEF` で作成するか、SQL文を直接 `db.OpenRecordset` に渡す手法を検討しましょう。
  • メモリ解放の忘れ: `Set rs = Nothing` を省略すると、Accessは「まだ何か作業があるかも?」とメモリを抱え込みます。大規模データほど、この解放処理が命取りになります。

—

最後に:先輩エンジニアからのエール

Access VBAは古いと言われますが、「データとユーザーの橋渡し」をこれほど高速に、かつ柔軟に実装できるツールは他にありません。

今回紹介した「画面を止めない」という工夫は、ユーザーからの「Accessって重いよね」という不満を「これなら使いやすい!」という信頼に変える大きな一歩です。まずはこのコードをコピーして、あなたのプロジェクトの重い処理に組み込んでみてください。

ここをクリアすれば、あなたはもうマクロの記録を卒業した「エンジニア」です。応援していますよ!

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