ExcelVBAで大量のデータを処理すると、次のような状態になりがちです。
- 処理中にExcelが固まったように見える
- 「応答なし」と表示される
- 本当に動いているのか不安になる
- 強制終了してデータを壊してしまった
しかし実は、VBAがフリーズする原因のほとんどは「書き方」です。
正しい設計にすれば、数万行・数十万行の処理でも固まらずに実行できます。
この記事では、初心者でも実践できる 「フリーズしない大量処理の基本ルール」を、理由つきで解説します。
結論:フリーズしないVBAは「3つの設計」で決まる
大量処理でも固まらないマクロには、共通点があります。
- ① Excelの画面更新・計算を制御している
- ② セルを直接いじらず、配列で処理している
- ③ DoEventsでExcelに処理を返している
この3つを押さえるだけで、体感速度と安定性は劇的に変わります。
原因①:セルを1つずつ直接操作している
フリーズの最大原因はこれです。
For i = 1 To 100000
Cells(i, 1).Value = Cells(i, 1).Value * 2
Next i
一見普通ですが、
1行ごとにExcel画面・計算・内部処理が走るため、極端に遅くなります。
対策①:配列に読み込んでから一気に書き戻す
大量処理の基本は 「配列処理」 です。
Sub Sample_ArrayProcess()
Dim v As Variant
Dim i As Long
' 一括で配列に読み込み
v = Range("A1:A100000").Value
' メモリ上で処理
For i = 1 To UBound(v, 1)
v(i, 1) = v(i, 1) * 2
Next i
' 一括で書き戻し
Range("A1:A100000").Value = v
End Sub
これだけで、処理速度は数十倍〜数百倍変わります。
原因②:画面更新・自動計算がONのまま
大量処理中に、Excelは次のことを常に行っています。
- 画面を更新する
- 数式を再計算する
- イベントを発火させる
これらは処理中は不要なので、OFFにします。
対策②:処理前に「高速化3点セット」を入れる
Dim prevCalc As XlCalculation
Dim prevScreen As Boolean
Dim prevEvents As Boolean
' 現在の状態を退避
prevCalc = Application.Calculation
prevScreen = Application.ScreenUpdating
prevEvents = Application.EnableEvents
' 高速化
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
処理後は、必ず元に戻します。
Application.ScreenUpdating = prevScreen
Application.Calculation = prevCalc
Application.EnableEvents = prevEvents
※戻し忘れると「Excelが壊れた」と勘違いされる原因になります。
原因③:Excelに処理を返していない(DoEventsなし)
VBAは処理中、Excelを占有します。
そのため、長いループでは「応答なし」になりがちです。
対策③:定期的にDoEventsを入れる
For i = 1 To 100000
' 処理
v(i, 1) = v(i, 1) * 2
' 1000件ごとにExcelへ制御を返す
If i Mod 1000 = 0 Then
DoEvents
End If
Next i
これで、
- 画面更新が反映される
- キャンセルボタンが効く
- フリーズして見えなくなる問題を防げる
応用①:進捗を表示して「動いている感」を出す
フリーズと誤解されないためには、進捗表示が有効です。
Application.StatusBar = "処理中:" & i & " / " & UBound(v, 1)
処理後は必ず元に戻します。
Application.StatusBar = False
応用②:キャンセル可能な大量処理にする
キャンセルフラグと組み合わせると、実務向けになります。
If gCancel Then
MsgBox "処理を中断しました。", vbExclamation
Exit For
End If
※ gCancel は「キャンセルボタンの記事」で紹介したフラグです。
よくある失敗例
- 配列を使っていない
- 高速化設定を戻していない
- DoEventsを入れすぎて逆に遅くしている
- 進捗表示がなく、不安にさせている
特に DoEventsの入れすぎ は逆効果なので、 「数百〜数千件に1回」が目安です。
安全な大量処理テンプレ(実務向け)
Option Explicit
Sub SafeLargeProcess()
Dim prevCalc As XlCalculation
Dim prevScreen As Boolean
Dim prevEvents As Boolean
Dim v As Variant
Dim i As Long
On Error GoTo Finally
' 状態退避
prevCalc = Application.Calculation
prevScreen = Application.ScreenUpdating
prevEvents = Application.EnableEvents
' 高速化
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
' 配列処理
v = Range("A1:A100000").Value
For i = 1 To UBound(v, 1)
v(i, 1) = v(i, 1) * 2
If i Mod 1000 = 0 Then
DoEvents
End If
Next i
Range("A1:A100000").Value = v
Finally:
' 必ず元に戻す
Application.ScreenUpdating = prevScreen
Application.Calculation = prevCalc
Application.EnableEvents = prevEvents
Application.StatusBar = False
End Sub
まとめ:大量処理は「設計」で決まる
- セルを直接触らず、配列で処理する
- 画面更新・計算・イベントを制御する
- DoEventsでExcelを固まらせない
- 進捗表示で安心感を出す
この設計を身につけると、 「VBAが遅い・固まる」問題の9割は解決します。
ぜひ、実務マクロの基本として取り入れてみてください。


コメント