Application.ScreenUpdatingとは
Application.ScreenUpdatingはVBAでのマクロ実行時に描画を停止・開始する機能である。
VBAが高速になる?
様々な書籍・サイトにて
Application.ScreenUpdating = False
'処理
Application.ScreenUpdating = True
を記載すると高速化できるとの記載があります。
VBA初心者の方であればおまじないとして書いていることもあるくらい
世の中に浸透していますが、
Office TANAKAの
によればコードの書き方の問題であり、
書き方を工夫すれば
Application.ScreenUpdatingを使おうが使うまいが
あまり変わらないとの記載が。
今回もう少し詳細に調べてみて実際どうなのかを検証していきます。
検証内容
今回は10000個のセルに対し、
値を1、背景色を赤
に変更するマクロにて検証を行います。
以下の6パターンについてそれぞれ10回実行し、
1回ごとの時間、平均値を求めていきます。
パターン1:セルの指定にSelectを使う
パターン2:セルの指定にSelectを使う+Application.ScreenUpdating
パターン3:セルの指定にSelectを使わない
パターン4:セルの指定にSelectを使わない+Application.ScreenUpdating
パターン5:配列に値を格納してからセルに書き出す
パターン6:配列に値を格納してからセルに書き出す+Application.ScreenUpdating
今回使用したコード
上記6パターンのコードをそれぞれ以下に記載します。
※計測結果をセルに追記する部分は省略しています。
'セルの指定にSelectを使う
Sub write_test()
Dim i As Long
Dim start_time As Double, end_time As Double, process_time As Double
Dim count As Long
Const N As Long = 10000
For count = 1 To 10
start_time = Timer
For i = 1 To N
ThisWorkbook.Worksheets(1).Select
ThisWorkbook.Worksheets(1).Cells(i, 1).Select
With Selection
.Value = 1
.Interior.Color = rgbRed
End With
Next i
end_time = Timer
process_time = end_time - start_time
ThisWorkbook.Worksheets(1).Cells(1, 1).CurrentRegion.Delete
Next count
End Sub
'セルの指定にSelectを使う+Application.ScreenUpdating
Sub write_test()
Dim i As Long
Dim start_time As Double, end_time As Double, process_time As Double
Dim count As Long
Const N As Long = 10000
Application.ScreenUpdating = False
For count = 1 To 10
start_time = Timer
For i = 1 To N
ThisWorkbook.Worksheets(1).Select
ThisWorkbook.Worksheets(1).Cells(i, 1).Select
With Selection
.Value = 1
.Interior.Color = rgbRed
End With
Next i
end_time = Timer
process_time = end_time - start_time
ThisWorkbook.Worksheets(1).Cells(1, 1).CurrentRegion.Delete
Next count
Application.ScreenUpdating = True
End Sub
'セルの指定にSelectを使わない
Sub write_test()
Dim i As Long
Dim start_time As Double, end_time As Double, process_time As Double
Dim count As Long
Const N As Long = 10000
For count = 1 To 10
start_time = Timer
For i = 1 To N
With ThisWorkbook.Worksheets(1).Cells(i, 1)
.Value = 1
.Interior.Color = rgbRed
End With
Next i
end_time = Timer
process_time = end_time - start_time
ThisWorkbook.Worksheets(1).Cells(1, 1).CurrentRegion.Delete
Next count
End Sub
'セルの指定にSelectを使わない+Application.ScreenUpdating
Sub write_test()
Dim i As Long, j As Long
Dim start_time As Double, end_time As Double, process_time As Double
Dim count As Long
Const N As Long = 10000
Application.ScreenUpdating = False
For count = 1 To 10
start_time = Timer
For i = 1 To N
With ThisWorkbook.Worksheets(1).Cells(i, 1)
.Value = 1
.Interior.Color = rgbRed
End With
Next i
end_time = Timer
process_time = end_time - start_time
ThisWorkbook.Worksheets(1).Cells(1, 1).CurrentRegion.Delete
Next count
Application.ScreenUpdating = True
End Sub
'配列に値を格納してからセルに書き出す
Sub write_test()
Dim i As Long, j As Long
Dim start_time As Double, end_time As Double, process_time As Double
Dim count As Long
Const N As Long = 10000
Dim arr(N) As Long
For count = 1 To 10
start_time = Timer
For i = 1 To N
arr(i - 1) = 1
Next i
With ThisWorkbook.Worksheets(1)
With .Range(.Cells(1, 1), .Cells(N, 1))
.Value = arr
.Interior.Color = rgbRed
End With
End With
end_time = Timer
ThisWorkbook.Worksheets(1).Cells(1, 1).CurrentRegion.Delete
Next count
End Sub
'配列に値を格納してからセルに書き出す+Application.ScreenUpdating
Sub write_test()
Dim i As Long, j As Long
Dim start_time As Double, end_time As Double, process_time As Double
Dim count As Long
Const N As Long = 10000
Dim arr(N) As Long
Application.ScreenUpdating = False
For count = 1 To 10
start_time = Timer
For i = 1 To N
arr(i - 1) = 1
Next i
With ThisWorkbook.Worksheets(1)
With .Range(.Cells(1, 1), .Cells(N, 1))
.Value = arr
.Interior.Color = rgbRed
End With
End With
end_time = Timer
ThisWorkbook.Worksheets(1).Cells(1, 1).CurrentRegion.Delete
Next count
Application.ScreenUpdating = True
End Sub
結果
以下に6パターンの結果を示します。
パターン1:セルの指定にSelectを使う | |
---|---|
回数 | 時間(秒) |
1 | 32.26171875 |
2 | 23.203125 |
3 | 45.3671875 |
4 | 32.8828125 |
5 | 33.328125 |
6 | 33.7421875 |
7 | 33.234375 |
8 | 33.34375 |
9 | 33.34375 |
10 | 33.48828125 |
平均 | 33.41953125 |
セルの指定にSelectを使う+Application.ScreenUpdating | |
---|---|
回数 | 時間(秒) |
1 | 2.890625 |
2 | 2.875 |
3 | 2.96875 |
4 | 3.05859375 |
5 | 2.92578125 |
6 | 2.9375 |
7 | 2.921875 |
8 | 3.0625 |
9 | 2.9375 |
10 | 2.9453125 |
平均 | 2.95234375 |
パターン3:セルの指定にSelectを使わない | |
---|---|
回数 | 時間(秒) |
1 | 2.25 |
2 | 2.25 |
3 | 1.4375 |
4 | 1.375 |
5 | 1.375 |
6 | 1.359375 |
7 | 1.34375 |
8 | 1.359375 |
9 | 1.375 |
10 | 1.359375 |
平均 | 1.5484375 |
パターン4:セルの指定にSelectを使わない+Application.ScreenUpdating | |
---|---|
回数 | 時間(秒) |
1 | 1.34375 |
2 | 1.3125 |
3 | 1.328125 |
4 | 1.328125 |
5 | 1.3125 |
6 | 1.328125 |
7 | 1.3125 |
8 | 1.3125 |
9 | 1.328125 |
10 | 1.328125 |
平均 | 1.3234375 |
パターン5:配列に値を格納してからセルに書き出す | |
---|---|
回数 | 時間(秒) |
1 | 0 |
2 | 0 |
3 | 0.015625 |
4 | 0.015625 |
5 | 0.015625 |
6 | 0.015625 |
7 | 0.015625 |
8 | 0.015625 |
9 | 0.015625 |
10 | 0.015625 |
平均 | 0.0125 |
パターン6:配列に値を格納してからセルに書き出す+Application.ScreenUpdating | |
---|---|
回数 | 時間(秒) |
1 | 0.015625 |
2 | 0.015625 |
3 | 0.015625 |
4 | 0 |
5 | 0.015625 |
6 | 0.015625 |
7 | 0.015625 |
8 | 0.015625 |
9 | 0.015625 |
10 | 0 |
平均 | 0.0125 |
結論
コードの書き方によってはApplication.ScreenUpdatingを使わなくても実行時間に変わりがないことが確認できました。
※パターン3と4では約0.2秒だけ速くなる、パターン5と6では速度が一緒
※パターン1と2では約30秒速くなる
Selectなどの選択の動作をするコードを使った場合は一応速くはなりますが、
エラーの元になったりするのでなるべく使わないコードで書いた方がいいかと思います。
なお、Application.ScreenUpdatingで高速化できると記載のある書籍・サイトには
Selectを使ったコードを例にしているものもあり、
確かにその書き方であれば早くなりますが、
Selectを使わないで書く書き方を教えるべきだと思います。
なお、Application.ScreenUpdatingを使わないとわずかに画面のちらつきが見られることがあるので、
ちらつきが嫌だという場合は見た目上の問題で使うのはありかと思います。
おわりに
今回がQiita初投稿となるので、至らない点が多々あるかと思いますが、ご容赦ください。
この記事に不備、ご意見等ありましたらコメント欄にて頂ければと思います。