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

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

# VBAが高速になる?
様々な書籍・サイトにて

```vb:Application.ScreenUpdating
Application.ScreenUpdating = False
'処理
Application.ScreenUpdating = True
```
を記載すると高速化できるとの記載があります。
VBA初心者の方であればおまじないとして書いていることもあるくらい
世の中に浸透していますが、
Office TANAKAの

http://officetanaka.net/excel/vba/speed/

によればコードの書き方の問題であり、
書き方を工夫すれば
Application.ScreenUpdatingを使おうが使うまいが
あまり変わらないとの記載が。
今回もう少し詳細に調べてみて実際どうなのかを検証していきます。

# 検証内容
今回は10000個のセルに対し、
値を1、背景色を赤
に変更するマクロにて検証を行います。

以下の6パターンについてそれぞれ10回実行し、
1回ごとの時間、平均値を求めていきます。

パターン1：セルの指定にSelectを使う
パターン2：セルの指定にSelectを使う+Application.ScreenUpdating
パターン3：セルの指定にSelectを使わない
パターン4：セルの指定にSelectを使わない+Application.ScreenUpdating
パターン5：配列に値を格納してからセルに書き出す
パターン6：配列に値を格納してからセルに書き出す+Application.ScreenUpdating

# 今回使用したコード
上記6パターンのコードをそれぞれ以下に記載します。
※計測結果をセルに追記する部分は省略しています。

```vb:パターン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
```


```vb:パターン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
```


```vb:パターン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
```


```vb:パターン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
```


```vb:パターン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
```


```vb:パターン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パターンの結果を示します。


<table>
	<thead>
		<tr>
			<th colspan="2">
				パターン1：セルの指定にSelectを使う
			</th>
		</tr>
		<tr>
			<th>
				回数
			</th>
			<th>
				時間(秒)
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				32.26171875
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				23.203125
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				45.3671875
			</td>
		</tr>
		<tr>
			<td>
				4
			</td>
			<td>
				32.8828125
			</td>
		</tr>
		<tr>
			<td>
				5
			</td>
			<td>
				33.328125
			</td>
		</tr>
		<tr>
			<td>
				6
			</td>
			<td>
				33.7421875
			</td>
		</tr>
		<tr>
			<td>
				7
			</td>
			<td>
				33.234375
			</td>
		</tr>
		<tr>
			<td>
				8
			</td>
			<td>
				33.34375
			</td>
		</tr>
		<tr>
			<td>
				9
			</td>
			<td>
				33.34375
			</td>
		</tr>
		<tr>
			<td>
				10
			</td>
			<td>
				33.48828125
			</td>
		</tr>
		<tr>
			<td>
				平均
			</td>
			<td>
				33.41953125
			</td>
		</tr>
	</tbody>
</table>

<table>
	<thead>
		<tr>
			<th colspan="2">
				セルの指定にSelectを使う+Application.ScreenUpdating
			</th>
		</tr>
		<tr>
			<th>
				回数
			</th>
			<th>
				時間(秒)
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				2.890625
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				2.875
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				2.96875
			</td>
		</tr>
		<tr>
			<td>
				4
			</td>
			<td>
				3.05859375
			</td>
		</tr>
		<tr>
			<td>
				5
			</td>
			<td>
				2.92578125
			</td>
		</tr>
		<tr>
			<td>
				6
			</td>
			<td>
				2.9375
			</td>
		</tr>
		<tr>
			<td>
				7
			</td>
			<td>
				2.921875
			</td>
		</tr>
		<tr>
			<td>
				8
			</td>
			<td>
				3.0625
			</td>
		</tr>
		<tr>
			<td>
				9
			</td>
			<td>
				2.9375
			</td>
		</tr>
		<tr>
			<td>
				10
			</td>
			<td>
				2.9453125
			</td>
		</tr>
		<tr>
			<td>
				平均
			</td>
			<td>
				2.95234375
			</td>
		</tr>
	</tbody>
</table>

<table>
	<thead>
		<tr>
			<th colspan="2">
				パターン3：セルの指定にSelectを使わない
			</th>
		</tr>
		<tr>
			<th>
				回数
			</th>
			<th>
				時間(秒)
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				2.25
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				2.25
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				1.4375
			</td>
		</tr>
		<tr>
			<td>
				4
			</td>
			<td>
				1.375
			</td>
		</tr>
		<tr>
			<td>
				5
			</td>
			<td>
				1.375
			</td>
		</tr>
		<tr>
			<td>
				6
			</td>
			<td>
				1.359375
			</td>
		</tr>
		<tr>
			<td>
				7
			</td>
			<td>
				1.34375
			</td>
		</tr>
		<tr>
			<td>
				8
			</td>
			<td>
				1.359375
			</td>
		</tr>
		<tr>
			<td>
				9
			</td>
			<td>
				1.375
			</td>
		</tr>
		<tr>
			<td>
				10
			</td>
			<td>
				1.359375
			</td>
		</tr>
		<tr>
			<td>
				平均
			</td>
			<td>
				1.5484375
			</td>
		</tr>
	</tbody>
</table>


<table>
	<thead>
		<tr>
			<th colspan="2">
				パターン4：セルの指定にSelectを使わない+Application.ScreenUpdating
			</th>
		</tr>
		<tr>
			<th>
				回数
			</th>
			<th>
				時間(秒)
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				1.34375
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				1.3125
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				1.328125
			</td>
		</tr>
		<tr>
			<td>
				4
			</td>
			<td>
				1.328125
			</td>
		</tr>
		<tr>
			<td>
				5
			</td>
			<td>
				1.3125
			</td>
		</tr>
		<tr>
			<td>
				6
			</td>
			<td>
				1.328125
			</td>
		</tr>
		<tr>
			<td>
				7
			</td>
			<td>
				1.3125
			</td>
		</tr>
		<tr>
			<td>
				8
			</td>
			<td>
				1.3125
			</td>
		</tr>
		<tr>
			<td>
				9
			</td>
			<td>
				1.328125
			</td>
		</tr>
		<tr>
			<td>
				10
			</td>
			<td>
				1.328125
			</td>
		</tr>
		<tr>
			<td>
				平均
			</td>
			<td>
				1.3234375
			</td>
		</tr>
	</tbody>
</table>

<table>
	<thead>
		<tr>
			<th colspan="2">
				パターン5：配列に値を格納してからセルに書き出す
			</th>
		</tr>
		<tr>
			<th>
				回数
			</th>
			<th>
				時間(秒)
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				0
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				0
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				4
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				5
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				6
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				7
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				8
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				9
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				10
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				平均
			</td>
			<td>
				0.0125
			</td>
		</tr>
	</tbody>
</table>

<table>
	<thead>
		<tr>
			<th colspan="2">
				パターン6：配列に値を格納してからセルに書き出す+Application.ScreenUpdating
			</th>
		</tr>
		<tr>
			<th>
				回数
			</th>
			<th>
				時間(秒)
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				4
			</td>
			<td>
				0
			</td>
		</tr>
		<tr>
			<td>
				5
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				6
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				7
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				8
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				9
			</td>
			<td>
				0.015625
			</td>
		</tr>
		<tr>
			<td>
				10
			</td>
			<td>
				0
			</td>
		</tr>
		<tr>
			<td>
				平均
			</td>
			<td>
				0.0125
			</td>
		</tr>
	</tbody>
</table>


# 結論
コードの書き方によってはApplication.ScreenUpdatingを使わなくても実行時間に変わりがないことが確認できました。
※パターン3と4では約0.2秒だけ速くなる、パターン5と6では速度が一緒
※パターン1と2では約30秒速くなる
Selectなどの選択の動作をするコードを使った場合は一応速くはなりますが、
エラーの元になったりするのでなるべく使わないコードで書いた方がいいかと思います。
なお、Application.ScreenUpdatingで高速化できると記載のある書籍・サイトには
Selectを使ったコードを例にしているものもあり、
確かにその書き方であれば早くなりますが、
Selectを使わないで書く書き方を教えるべきだと思います。
なお、Application.ScreenUpdatingを使わないとわずかに画面のちらつきが見られることがあるので、
ちらつきが嫌だという場合は見た目上の問題で使うのはありかと思います。

# おわりに
今回がQiita初投稿となるので、至らない点が多々あるかと思いますが、ご容赦ください。
この記事に不備、ご意見等ありましたらコメント欄にて頂ければと思います。