Excel VBAの「フリーズ」を制御せよ:DoEventsの正しい流儀
こんにちは。日々の自動化業務、お疲れ様です。
マクロを実行した瞬間、「応答なし」という冷酷な文字がExcelのタイトルバーに浮かび上がり、心臓が止まりそうになった経験はありませんか?
「重い処理だから仕方ない」と諦めるのはまだ早いです。今日は、VBAにおける「DoEvents(ドゥ・イベント)」という魔法の杖について、その本質と、絶対に守るべき「引き際」を伝授しましょう。
—
1. なぜExcelは「フリーズ」するのか?
まず、敵を知りましょう。
ExcelのVBAは、基本的に「シングルスレッド」で動作します。つまり、コードが実行されている間、Excelは「計算」や「ループ処理」に全力を注いでおり、画面の更新やユーザーからの操作(クリックやスクロール)を受け付ける余裕を失ってしまうのです。
これが、いわゆる「フリーズ」の正体です。
—
2. DoEvents:Excelに「休息」を与える魔法
`DoEvents`は、VBAに「今溜まっているOSのメッセージ(クリックなどの操作)を処理していいぞ」と命令する関数です。
これをループの中に差し込むことで、Excelは処理の合間に「おっと、ユーザーが何か言っているな」と耳を傾ける余裕を持つようになります。
基本的な書き方
Sub DoEventsの基本()
Dim i As Long
For i = 1 To 100000
‘ 重い処理の代わり
Cells(i, 1).Value = i
‘ 100回に1回、Excelにメッセージを処理させる
If i Mod 100 = 0 Then
DoEvents
End If
Next i
MsgBox “完了しました”
End Sub
—
3. なぜ「多用」してはいけないのか?(プロの視点)
ここからが本題です。多くの初心者は「とにかくフリーズを防ごう」と、ループの毎行に`DoEvents`を書き込みます。
これは「禁じ手」です。
理由はシンプル。パフォーマンスが劇的に低下するからです。
`DoEvents`を呼ぶたびに、Excelは「操作の確認」というオーバーヘッド(余計な処理)を発生させます。1万回のループで毎回確認すれば、処理速度は目に見えて遅くなります。
賢い配置の鉄則:間隔を空ける
プロは「処理の重さ」に合わせて、`DoEvents`を呼ぶ頻度を調整します。
- 処理が非常に軽いなら:1,000回に1回
- 処理がそこそこ重いなら:100回に1回
- 処理が極めて重いなら:1回ごと
この「バランス感覚」こそが、自動化エンジニアとしての腕の見せ所です。
—
4. 現場で使える「プロ仕様」の制御術
さらに一歩進んで、「キャンセルボタン」を実装する高度なテクニックを紹介します。これがあれば、長時間処理中でもユーザーが任意に中断できます。
‘ 標準モジュールに記述
Public isCancelled As Boolean
Sub 処理中断可能なループ()
isCancelled = False
Dim i As Long
For i = 1 To 50000
‘ ここで重い処理を行う
Cells(i, 1).Value = Rnd()
‘ 50回に1回だけチェックする
If i Mod 50 = 0 Then
DoEvents ‘ メッセージ処理を許可
If isCancelled Then
MsgBox “中断されました”
Exit Sub
End If
End If
Next i
End Sub
‘ ユーザーフォームのボタン等に割り当てるコード
Sub キャンセルボタン_Click()
isCancelled = True
End Sub
—
5. まとめ:今日から使えるエンジニアの心得
`DoEvents`は、正しく使えばExcelを「快適に操作できるツール」に変貌させますが、無闇に使えば「遅いマクロ」の原因になります。
- DoEventsは「休憩時間」を与えるためのもの。
- 毎行書くのはNG。バッファを持たせよ。
- 「操作を受け付ける」だけでなく「処理を中断させる」ためのトリガーとして活用せよ。
ここをクリアすれば、あなたのVBAは単なるスクリプトから、ユーザーに寄り添った「アプリケーション」へと進化します。
さあ、恐れずにコードを書いてみてください。もし詰まったら、いつでも戻ってきてくださいね。あなたの自動化の旅を、これからも応援しています。
