LoginSignup
4

More than 1 year has passed since last update.

VBAでApplication.ScreenUpdatingは本当に必要?

Last updated at Posted at 2021-12-13

Application.ScreenUpdatingとは

Application.ScreenUpdatingはVBAでのマクロ実行時に描画を停止・開始する機能である。

VBAが高速になる?

様々な書籍・サイトにて

Application.ScreenUpdating
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パターンのコードをそれぞれ以下に記載します。
※計測結果をセルに追記する部分は省略しています。

パターン1
'セルの指定に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
パターン2
'セルの指定に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
パターン3
'セルの指定に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
パターン4
'セルの指定に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
パターン5
'配列に値を格納してからセルに書き出す
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
パターン6
'配列に値を格納してからセルに書き出す+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初投稿となるので、至らない点が多々あるかと思いますが、ご容赦ください。
この記事に不備、ご意見等ありましたらコメント欄にて頂ければと思います。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4