【入門編】Application.Echoを制御する汎用クラスの作成:エラー発生時でも画面描画を確実に復帰させる – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの開発現場で、日夜データベースと格闘お疲れ様です。

大量のデータを処理するループを回すとき、`Application.Echo False` を使って画面の描画をピタッと止めると、処理速度が劇的に跳ね上がりますよね。「よし、これで爆速だ!」と満足してテストを走らせている最中……あろうことか、予期せぬエラーでコードが突如としてストップ!

……気づけば、画面がフリーズしたかのように一切更新されず、Accessを強制終了する羽目になった。そんな冷や汗をかくような恐怖体験、あなたも一度や二度ではないはずです。

今回は、そんな悲劇を「絶対に」防ぐための極意――クラスモジュールのライフサイクルを利用した、安全かつエレガントな画面描画制御の仕組みを伝授します。ここをクリアすれば、あなたの書くAccess VBAの信頼性はプロの領域へと一気に飛躍しますよ。さあ、一緒に扉を開けましょう!

なぜ `Application.Echo` は罠だらけなのか?

Accessは、フォームの再描画やコントロールの更新を行うたびに裏で膨大なリソースを消費しています。そのため、数千件のレコードをゴリゴリ処理するマクロやVBAでは、以下のように画面描画を一度オフにするのが定石です。

‘ 【危険なアンチパターン】
Application.Echo False ‘ 画面描画を停止

‘ — 大量のデータ処理(ここでエラーが起きたら…?) —
Call 危険なデータ処理()

Application.Echo True ‘ 画面描画を復帰

一見、何の問題もないように見えますよね。しかし、プログラミングの鉄則は「エラーはいついかなる時でも発生しうる」ということです。

もし、`危険なデータ処理()` の中で型変換エラーや実行時エラーが発生したらどうなるでしょうか? VBAの実行はそこで中断され、その下にある `Application.Echo True` にたどり着くことは永遠にありません。結果として、Accessの画面は描画が停止したまま凍結(エコーオフのまま)。ユーザーは「バグった!」とパニックになり、タスクマネージャーで強制終了するしかなくなるのです。

救世主はクラスモジュールの「Terminateイベント」

「じゃあ、エラー処理(`On Error GoTo`)を毎回書けばいいじゃないか」と思いますよね。もちろんそれも一つの手ですが、すべてのプロシージャに同じエラー処理を書くのは冗長ですし、何より書き忘れるリスクが残ります。

ここで、オブジェクト指向の隠れた名機能――クラスモジュールの「Terminate(終了)イベント」を使います。

Access VBAのクラスには、インスタンスがメモリから消滅する(スコープから外れる)瞬間、自動的に実行される `Class_Terminate` というイベントが存在します。「このクラスが存在している間だけ画面を止め、クラスが消滅するとき(=プロシージャを抜けるとき)には、エラーの有無に関わらず強制的に画面を復帰させる」。この仕組みを作れば、エラーに怯える必要は一切なくなります。

実装:汎用エコー制御クラスを作ろう!

それでは、実際に現場でそのままコピペして使える「画面描画制御クラス」を実装してみましょう。

手順1:クラスモジュールの作成

VBE(Visual Basic Editor)を開き、メニューの [挿入] > [クラス モジュール] をクリックします。
新しくできたクラスモジュールのプロパティウィンドウで、名前を `clsScreenLock` に変更してください。

そして、以下のコードをそのまま貼り付けます。

‘ =================================================================
‘ クラス名: clsScreenLock
‘ 概要: 画面描画(Echo)とマウスポインタを安全に制御するクラス
‘ =================================================================
Option Explicit

‘ クラスが生成された(インスタンス化された)ときに走るイベント
Private Sub Class_Initialize()
‘ 画面の描画を停止してパフォーマンスを向上させる
Application.Echo False

‘ ついでにカーソルを砂時計(処理中)にしてあげると親切です
DoCmd.Hourglass True
End Sub

‘ クラスが破棄される(メモリから消える)ときに「必ず」走るイベント
Private Sub Class_Terminate()
‘ どんなに無様なエラーで落ちようとも、ここが必ず実行されます
On Error Resume Next
DoCmd.Hourglass False
Application.Echo True
On Error GoTo 0
End Sub

たったこれだけです!たったこれだけのコードが、あなたのAccessアプリを鉄壁の守りへと変えてくれます。

手順2:標準モジュールからの呼び出し方

作ったクラスを実際に標準モジュールやフォームのコードから使ってみましょう。使い方は驚くほどシンプルです。

‘ =================================================================
‘ プロシージャ例:安全なデータ一括処理
‘ =================================================================
Sub RunSafeBatchProcess()

‘ 【重要】クラスのインスタンスを生成した瞬間、Echo Falseが発動します
Dim screenLock As clsScreenLock
Set screenLock = New clsScreenLock

On Error GoTo ErrorHandler

‘ — ここから通常の重い処理を記述 —
Debug.Print “重い処理を開始します…”

‘ わざとエラーを起こしてみるテスト(コメントアウトを外すとエラーが発生します)
‘ Err.Raise 9999, , “予期せぬエラー発生!”

‘ 擬似的な重いループ処理
Dim i As Long
For i = 1 to 1000000
‘ 何らかのデータ処理
Next i

Debug.Print “処理が正常に完了しました。”

NormalExit:
‘ 【ポイント】ここで変数を明示的に破棄、またはプロシージャを抜けることで
‘ clsScreenLockの Class_Terminate が走り、画面が自動で復帰します。
Set screenLock = Nothing
Exit Sub

ErrorHandler:
MsgBox “エラーが発生しましたが、画面は正常に復帰します。” & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “システムエラー”

Resume NormalExit

End Sub

このコードの何が凄いのか?

1. エラーが起きても確実に画面が戻る
`Err.Raise` で強制的にエラーを起こそうが、予期せぬゼロ除算エラーが起きようが、VBAの実行が `ErrorHandler` を経て `NormalExit` に向かう際、あるいはプロシージャのスコープを抜ける際に、`screenLock` 変数が破棄されます。その瞬間、`Class_Terminate` が作動し、確実に `Application.Echo True` が実行されます。
2. コードが美しく、メンテナンス性が高い
プロシージャのあちこちに `Application.Echo True` を書き散らす必要がなくなります。書き忘れによる「画面フリーズ事故」が物理的に起こらなくなるため、デバッグのストレスから完全に解放されます。

レイヤの高いエンジニアほど、「エラーが起きたときの後始末」を美しく設計するもの。「ここをこうしておけば、万が一の時もシステムが崩壊しない」という安心感の積み重ねが、プロ品質のAccessアプリケーションを形作ります。

ぜひ、あなたのプロジェクトにもこの `clsScreenLock` を導入してみてください。Access VBAのコーディングが、一段と楽しく、スマートになりますよ!

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