- VBAでマクロを作ったんだけど、なんだか遅い気がする…
- マクロを少しでも速くしたい
- 簡単にできるなら、マクロを高速化したい
このようなお悩みをお持ちですか?
この記事を読むことで、下記のことがわかります。
- マクロが遅い原因を知れる
- マクロを高速化する方法とVBAコードが学べる
VBAマクロ歴3年の私が、できるだけわかりやすく解説いたします。
※わかりやすさを重視しております。厳密には解釈が異なる場合がありますことをご了承ください。
VBAでのマクロ処理を高速化する方法
VBA処理が遅い原因
VBAの処理が遅くなる原因にはさまざまなものがありますが、最も一般的な原因は以下の3つです。
- セル操作が多い
- 画面の更新が多い
- 再計算が多い
VBAを高速化することは、業務の効率化や作業時間の短縮に直結します。
そのため、少しでも処理時間を短縮するために、適切な高速化テクニックを活用することが重要です。
次項で具体的な方法を紹介いたします。
VBAを高速化する具体的な方法3選
セル操作を最小限にする
セルを1つずつ読み書きするのではなく、一括で値を取得し、一括で書き込むことを心がけましょう。
エクセルのセルを一度に操作する方法として、Range.Valueを使ってセル範囲をまとめて処理することが効果的です。
また、VBAでは、Forループの中でセルの値を繰り返し読み書きすることが一般的ですが、この操作が遅くなる原因となります。
For Eachを使ってループの速度を改善することができます。
下記VBAコードは、A1~1000までのセルの値を2倍した例です。
▼効率の悪い例
For i = 1 To 1000
Cells(i, 1).Value = Cells(i, 1).Value * 2 ' 1つ1つセルを読み書きしている
Next i
'処理速度:約0.031秒
▼改善した例
Dim cell As Range
For Each cell In Range("A1:A1000") ' セルをまとめて指定
cell.Value = cell.Value * 2
Next cell
'処理速度:約0.015秒
For Eachの書き方や使い方は、下記記事で詳しく解説しております。ご参考ください。
さらに、セルを1つずつ操作する代わりに、配列を使ってデータを一括で処理する方法も有効です。
配列を使うことで、VBAはメモリ上での計算を行い、処理が格段に速くなります。
Dim data As Variant
data = Range("A1:A1000").Value
For i = 1 To UBound(data)
data(i, 1) = data(i, 1) * 2
Next i
Range("A1:A1000").Value = data
'処理速度:約0.011秒
画面の更新を一時停止する
VBAで大量のデータを操作する際、画面が頻繁に更新されると処理速度が遅くなる傾向にあります。
これを防ぐための方法を紹介いたします。
Application.ScreenUpdating = False ' 画面の更新を一時停止
' ここに処理を書く
Application.ScreenUpdating = True ' 画面の更新を戻す
' 対策前:約0.30秒(A1~10000の値を2倍にした場合)
' 対策後:約0.25秒(〃)
「Application.ScreenUpdating = False」とすることで、画面の更新を一時停止できます。
処理が終わったら、「True」に戻すことを忘れないようにしましょう。
今回の差はわずかですが、処理が複雑化すると差が大きくなります。
また、イベント処理が有効な状態だと、セルの変更や操作に対してイベントが発生します。
これを無効にすることで、処理中の余計なイベントを防ぎ、速度を向上させることができます。
Application.EnableEvents = False ' イベント処理を一時停止
' ここに処理を書く
Application.EnableEvents = True ' イベント処理を再開
' 対策前:約0.30秒(A1~10000の値を2倍にした場合)
' 対策後:約0.21秒(〃)
再計算を一時停止する
エクセルの計算モードが自動の場合、セルの値が変更されるたびに計算が行われます。
これが処理の遅延を引き起こす原因となります。
対処法ですが、下記VBAコードを見てください。
Application.Calculation = xlCalculationManual ' 計算モードを一時停止
' ここに処理を書く
Application.Calculation = xlCalculationAutomatic ' 計算モードを再開
' 対策前:約0.30秒(A1~10000の値を2倍にした場合)
' 対策後:約0.22秒(〃)
処理中に計算モードを「Manual」に設定することで、計算を一時的に停止させます。
処理が終わったら、「Automatic」に戻すことを忘れないようにしましょう。
その他のコツ
Variant型の使用は避ける
どんなデータでも格納できるVariant型は便利ですが、
多用するとメモリ消費が増えて処理が遅くなる原因となります。
変数の型を適切に指定することで、メモリ使用量を削減し、計算の効率が向上します。
可能な限り適切なデータ型を使用しましょう。
辞書型を活用する
Dictionaryオブジェクト(辞書型)を使うと、重複データの検索や管理が効率的に行えます。
Collection(配列など)よりも高速に動作するため、データ処理が高速化されます。
' 辞書型データの作成
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
' データの追加
dict.Add "key1", "value1"
dict.Add "key2", "value2"
ADOを利用する
ADO(ActiveX Data Objects)を利用することで、Excelのシートから直接データを高速に読み込むことができます。
Dim conn As Object
Set conn = CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Utatane\test.xlsx;Extended Properties=""Excel 12.0 Xml;HDR=YES"""
VBAの速度を測定する方法
VBAのパフォーマンスを改善した後、実際にどれだけ速度が向上したのかを測定することが重要です。
Timer関数を使うと、処理開始から終了までの時間を計測できます。
Dim startTime As Double
startTime = Timer
' ここに処理を書く
Debug.Print "処理時間: " & Timer - startTime & "秒"

最後に
VBAでのマクロ処理を高速化する方法を解説いたしました。
難しい方法もありましたが、できることから少しずつ高速化を行ってみてください。
当ブログでは、VBAマクロやPythonなど、時間を生み出すプログラミング術を公開しております。
この記事がわかりやすいと感じた方は、他の記事も読んでいってください。
最後までお読みいただき、ありがとうございました。がんばってください!