今日は、ボクがVBAを学習している時は全然きづかず、
実務で困ったことについて記事にする。
VBAの処理の高速化に関する話について。
結論から話すと、セルを参照させる処理はできるだけ
一括で処理しようという話だが、何のことかわからないと思う。。。
そこで具体的にコードをみながら説明していく。
例えば、下記セルのB行~D行までのセルの値合計を
E行に出力するプログラムを組むときをかんがえよう。
最初ぼくがVBAを学習したてのころはこう書いていた。
Sub 非高速化()
Dim lastData As Long
Dim index As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("計算")
' B~D行セルの各値を足して、E行セルに結果を出力
lastData = ws.Cells(Rows.Count, "A").End(xlUp).Row
For index = 2 To lastData
ws.Range("E" & index).Value = ws.Range("B" & index).Value + _
ws.Range("C" & index).Value + ws.Range("D" & index).Value
Next
End Sub
ぼくもこれができた際はやった!という気持ちになった。
ただ実際の実務でVBAを組んでみると、このデータが何十万行になってたり、計算が複雑になって全然うごかなくなった。。。
そこで先輩に教わりながら、高速化させたプログラムがこちら。
Sub 高速化()
Dim lastData As Long
Dim i As Long, j As Long
Dim ws As Worksheet
Dim resultRng As Range
Dim calRng As Range
Dim calVal As Variant
Dim resultVal As Variant
Set ws = ThisWorkbook.Worksheets("計算")
' A列(No列)の最終行取得
lastData = ws.Cells(Rows.Count, "A").End(xlUp).Row
' B~D列(足す列)のセル範囲取得→セル範囲の値をVariantで取得
Set calRng = ws.Range("B2:" & "D" & lastData)
calVal = calRng.Value
' E列(計算結果列)のセル範囲取得→セル範囲の値をVariantで取得
Set resultRng = ws.Range("E2:E" & lastData)
resultVal = resultRng.Value
' resultVal(計算結果配列)に
' calVal(足す対象が入った配列)を足し合わせた結果を格納する。
For i = LBound(calVal, 1) To UBound(calVal, 1)
resultVal(i, 1) = calVal(i, 1) + calVal(i, 2) + calVal(i, 3)
Next
' 計算結果をE列(計算結果列)に出力
resultRng.Value = resultVal
End Sub
上のプログラムは、
①B列セル~D列セル(足す行)を一回でまとめて読み出し
②①で読みだした値を足し算して、計算結果配列に格納
③計算結果をE行にまとめて出力。
というながれ。
セルを参照させる処理(①や③の処理)
一回でまとめて全部取得しているので、処理が早くなる。
上のプログラムだと、For文で1行1行セル参照しているので
計算がややこしくなると時間がかかる。
これを心がけるだけでも、処理がだいぶ早くなると思う。