こんにちは!Access VBAの開発現場で、日夜データと格闘お疲れ様です。
先輩エンジニアの私です。
マクロの記録から一歩踏み出し、自らVBAを書き始めると、こんな壁にぶつかりませんか?
「大量のデータを処理しているとき、画面がバババッと激しく点滅して、なんだか動作も遅い気がする…」
そう、Accessは処理のたびに画面(フォームやクエリの実行結果など)を一生懸命再描画しようとするため、画面がちらつき(フリッカー)、パフォーマンスも低下します。これをピタッと止めてくれるのが、魔法の呪文`Application.Echo False`です。
「画面を描画しないで処理だけしてね!」とAccessにお願いするこのメソッド、処理速度が劇的に上がり、見た目もスマートになります。
しかし!ここにAccess VBA開発者が必ず一度はハマる「魔の罠」があります。
今回は、初心者の方が絶対に知っておくべき「Echoの恐怖」と、それを美しく、そして絶対に安全に回避する「汎用クラスモジュール」の設計思想を、優しく、かつ本質的に伝授します。ここをクリアすれば、あなたのVBAスキルはワンランク上のステージに到達しますよ!
—
1. 画面描画を止める `Application.Echo` の光と闇
まずは基本のおさらいです。
Accessで大量のレコードを更新したり、複数のクエリを連続して実行したりするとき、以下のようにコードを書きますよね。
Sub Sample_WithoutEcho()
‘ 画面の描画を停止!
Application.Echo False
‘ — ここに重い処理を書く —
‘ 例: 大量のデータ更新クエリの実行など
DoCmd.SetWarnings False
DoCmd.OpenQuery “qAppend_MonthlyData”
DoCmd.SetWarnings True
‘ —————————-
‘ 画面の描画を復帰!
Application.Echo True
MsgBox “処理が完了しました!”, vbInformation
End Sub
素晴らしい!これを使えば、画面のチラつきが消え、処理スピードも向上します。
……が、プログラミングの神様はそんなに甘くありません。
初心者が陥る「画面が二度と戻らない」ホラー現象
もし、上記の「重い処理」の最中に、予期せぬエラー(例えば、参照先データがない、主キーが重複した、など)が発生したらどうなるでしょうか?
VBAはエラーで強制停止します。その瞬間、コードの実行はストップするため、`Application.Echo True`(画面を戻すコード)が一生実行されません。
結果どうなるか?
- Accessの画面が真っ白、あるいは最後の画面でフリーズしたようになる。
- マウスを動かしても反応が鈍い(実際は裏で動いているか、操作を受け付けなくなっている)。
- 最悪の場合、Accessを強制終了するしかない。
現場でこれやると、ユーザーから「なんかAccessが壊れました!」と青ざめた顔で駆け寄られることになります。これが、`Application.Echo` の恐ろしい「闇」です。
—
2. エラーが起きても絶対に復帰させる!「クラス」という防波堤
「じゃあ、エラー処理(`On Error GoTo`)を毎回書けばいいんでしょ?」
そう思ったあなた、鋭いですね。確かに各プロシージャの最後にエラー処理を書く手もありますが、何十個もあるプロシージャに毎回同じボイラープレート(お決まりのコード)を書くのは、エンジニアとしてスマートではありません。
ここで登場するのが、「クラスモジュール」です!
「クラスって何?難しそう……」と思った方、大丈夫です。
今回は、『生まれた瞬間にEchoを止め、消滅する瞬間に自動的にEchoを戻してくれる頼もしい用心棒』という役割を持つクラスを作ります。
VBAのオブジェクトには「ライフサイクル(生成されてから消滅するまでの寿命)」という概念があります。これを利用すると、「エラーが起きようが、途中でマクロが強制終了しようが、メモリから消える時に必ず後片付けをしてくれる」という強固な仕組みが作れるのです。
—
3. 実装:汎用Echo制御クラス(`clsScreenLock`)の作成
百聞は一見にしかず。実際にコードを書いてみましょう。
手順1:クラスモジュールの追加
1. VBAエディタ(VBE)を開きます。
2. メニューの [挿入] > [クラス モジュール] をクリックします。
3. プロパティウィンドウで、このモジュールの名前を `clsScreenLock` に変更します。
手順2:コードの記述
以下のコードを、新しくできた `clsScreenLock` の中に丸ごとコピー&ペーストしてください。
Option Explicit
‘ =================================================================
‘ クラス名: clsScreenLock
‘ 概要: 画面描画(Echo)を制御し、エラーや終了時に確実に復帰させる汎用クラス
‘ =================================================================
‘ クラスが初期化された(生まれた)時に実行されるイベント
Private Sub Class_Initialize()
On Error GoTo ErrorHandler
‘ 画面の描画を停止し、ステータスバーにメッセージを表示
Application.Echo False, “処理を実行中です。しばらくお待ちください…”
Exit Sub
ErrorHandler:
‘ 万が一初期化時にエラーが出た場合は描画を強制復帰
Application.Echo True
MsgBox “画面制御の初期化に失敗しました: ” & Err.Description, vbCritical
End Sub
‘ クラスが破棄された(消滅する)時に実行されるイベント
Private Sub Class_Terminate()
On Error Resume Next
‘ 【超重要】どんな状況であれ、このクラスがメモリから解放される瞬間、
‘ 必ず画面描画を元の状態(True)に戻す!
Application.Echo True
‘ ステータスバーをクリア
SysCmd acSysCmdClearStatus
On Error GoTo 0
End Sub
たったこれだけです!
このクラスのミソは `Class_Terminate` という特別なイベント。VBAでは、このモジュールの変数が役割を終えて消える時、エラーの有無に関わらず100%このコードが実行されます。 つまり、消滅の瞬間に必ず画面が復帰する仕組みというわけです。
—
4. 現場での使い方:驚くほどシンプルで安全なコード
では、先ほど作った用心棒クラスを、実際の業務ロジックでどのように使うのかを見てみましょう。標準モジュールに以下のように書きます。
Sub ExecuteHeavyProcess()
‘ 1. 用心棒クラスの変数を宣言する
Dim screenLock As clsScreenLock
‘ 2. クラスの実体を生成する(ここで自動的に Echo False になる!)
Set screenLock = New clsScreenLock
‘ — ここからメインの処理(エラーが起きても怖くない!) —
‘ わざとエラーが起きそうな処理や、時間のかかる処理を書く
DoCmd.SetWarnings False
‘ 例としてクエリを実行
DoCmd.OpenQuery “qUpdate_CustomerStatus”
‘ もしここで何らかのエラーが発生して処理が止まっても……
‘ このプロシージャを抜ける瞬間に screenLock 変数メメモリから消えるため、
‘ 自動的に clsScreenLock の Terminate が発動し、画面は必ず元に戻ります!
DoCmd.SetWarnings True
‘ ——————————————————–
‘ 3. 正常終了時のメッセージ
MsgBox “すべての処理が正常に完了しました!”, vbInformation
‘ (※変数 screenLock はプロシージャ終了時に自動破棄されます)
End Sub
この書き方の何がスゴいのか?
1. `Application.Echo True` を書き忘れることが物理的に不可能になる
コードの途中で `Exit Sub` で抜けようが、予期せぬエラーで止まろうが、変数 `screenLock` の寿命が尽きた瞬間に安全装置が作動します。
2. コードの見通しが圧倒的に良くなる
「画面を止める」「戻す」という定型作業をクラスに丸投げできるため、肝心のビジネスロジック(データの処理)だけに集中できます。
—
5. 先輩エンジニアからのメッセージ
今回は、Access VBAにおける `Application.Echo` のリスクと、それをオブジェクト指向的なアプローチ(クラスモジュール)でエレガントに解決する方法を解説しました。
「マクロの記録」から抜け出した初学者の壁は、「エラーが起きたときの後始末(例外処理とリソースの解放)」をいかにスマートに記述できるかにあります。
ここをクリアできたあなたは、単なる「VBAのコードを繋ぎ合わせた人」から、「堅牢なシステムを設計できるエンジニア」へと確実にステップアップしています。
ぜひ、あなたの開発するAccessデータベースにこの `clsScreenLock` を組み込んで、快適で安全な自動化ライフを手に入れてくださいね。それでは、次の開発現場でお会いしましょう!
