Accessで「画面が固まる」とおさらばする。Timerイベントによる擬似マルチスレッドの極意
こんにちは。Accessの深淵へようこそ。
多くの開発者がAccessで重い処理(大量データの計算や外部APIとの通信など)を走らせた瞬間、画面が白くなり「応答なし」という地獄を見たことがあるはずです。Accessは基本的にシングルスレッド。一つの処理が終わるまで、操作を一切受け付けない「独裁者」のような挙動をします。
しかし、伝説的なアーキテクトは知っています。「フォームのTimerイベント」を巧妙に操れば、シングルスレッドの制約をすり抜け、あたかもバックグラウンドで処理が動いているような体験を作れるということを。
今日は、あなたのAccessを「フリーズさせない賢いアプリケーション」へと進化させる技術を伝授します。
—
なぜ「Timerイベント」が魔法の鍵なのか?
Accessの`TimerInterval`プロパティは、指定したミリ秒ごとに`OnTimer`イベントを発生させます。通常は時計を表示したりするのに使われますが、ここに「処理を小分けにする」という概念を持ち込むと、景色が変わります。
重い処理を一度にやるのではなく、「少しだけやってはイベントを抜ける」を繰り返す。これこそが、擬似マルチスレッドの正体です。
処理のイメージ図
1. 開始: フォームのタイマーを開始。
2. Step1: 全体の1/10だけ処理して終了。
3. 制御権を解放: VBAが終了し、Accessが画面描画や操作受付を行う隙間ができる。
4. Step2: タイマーが発火し、次の1/10を実行。
5. 完了: 全工程が終わったらタイマーを停止。
これなら、ユーザーは処理中もボタンを押せますし、進捗バーを動かすことも可能です。
—
実践:重い処理を「分割」して実行するコード
以下のコードを、適当なフォーム(例えば `frmBackgroundProcess`)のモジュールに貼り付けてください。
Option Compare Database
Option Explicit
‘ 処理の状態を保持する変数
Private m_CurrentStep As Long
Private Const MAX_STEPS As Long = 100 ‘ 全体を100ステップに分ける
Private Sub btnStart_Click()
‘ 処理を開始し、タイマーを100ミリ秒ごとに設定
m_CurrentStep = 0
Me.TimerInterval = 100
End Sub
Private Sub Form_Timer()
‘ タイマーイベントで呼び出される「小分けの処理」
‘ 1. 進捗の更新
m_CurrentStep = m_CurrentStep + 1
‘ 2. 実際の重い処理をここに書く(例:複雑な計算やループの一部)
Call DoHeavyTask(m_CurrentStep)
‘ 3. 進捗バーの更新(フォームにtxtProgressがある前提)
Me.txtProgress.Value = (m_CurrentStep / MAX_STEPS) 100
‘ 4. 終了判定
If m_CurrentStep >= MAX_STEPS Then
Me.TimerInterval = 0 ‘ タイマーを停止
MsgBox “処理が完了しました!”
End If
End Sub
Private Sub DoHeavyTask(step As Long)
‘ ここで数ミリ秒〜数十ミリ秒程度の処理を行う
‘ あまりに重すぎると結局フリーズするので注意!
Debug.Print “Step ” & step & ” 実行中…”
End Sub
—
ここをクリアすればプロの仲間入り:注意点と極意
この手法をマスターする上で、いくつか「現場の壁」があります。
1. 「DoEvents」との使い分け
「`DoEvents`関数を使えばいいのでは?」と思うかもしれません。確かに`DoEvents`はループ内で制御を解放しますが、連発するとAccessの内部処理が追いつかず、逆に不安定になることがあります。`Timer`を使う利点は、「一定の間隔で確実に制御をOSに返せる」というリズムの安定性にあります。
2. 変数の寿命(スコープ)
`m_CurrentStep`は必ず`Option Explicit`の下、モジュールレベルで宣言してください。プロシージャ内で宣言すると、タイマーが動くたびに値がリセットされてしまいます。「状態を保持し続けること」が、分割処理の魂です。
3. エラーハンドリングは必須
バックグラウンドで動いているように見えても、VBAは一つです。タイマー内でエラーが発生すると、そのままフォーム全体が沈黙します。必ず `On Error GoTo` を入れ、異常時はタイマーを止め、エラーログを出力する堅牢な設計にしてください。
—
最後に:エンジニアとして一歩先へ
今回学んだのは「イベント駆動型プログラミング」の真髄です。Accessに「待機」を強いるのではなく、「隙間」を縫って仕事をさせる。この考え方は、他のプログラミング言語(JavaScriptの非同期処理など)にも通じる普遍的なスキルです。
最初は難しく感じるかもしれませんが、まずは「100回のループを1回ずつタイマーで回してみる」という小さな実験から始めてみてください。
あなたのAccess開発が、ユーザーにとって「ストレスのない、軽快な道具」になることを願っています。応援していますよ!
