VBAの勉強を始めてみた

色々試しています。

ループ処理を極力軽くする方法の模索~混乱編~(Tips-7)

VBAの勉強を始めて、これまでに学んだことや、思いついたアレやコレをメモっておきます。

 

今回は、ループ処理を使わなければならない場合に、ループの中に含まれる処理を極力軽くする方法について、模索してみようと思います。

下のように、1~9の数値がランダムに入った、A1:A10000のセル範囲に対して、数値が偶数だった場合に行を非表示にする処理を、いくつかのコードで試して、速さの違いを比較してみましょう。

f:id:kouten0430:20180624151654j:plain


test1として、セルを上から順に比較していき、偶数だった場合にその都度、行を非表示にします。
(Modは、左側の数値を右側の数値で割って、余りを求める演算子です。なので、2で割った時に0であった場合が偶数ということになります)
※時間計測のために必要なコードは省略して記載します。

Sub test1()
    Dim i As Integer
    
    For i = 1 To 10000
        If Cells(i, 1).Value Mod 2 = 0 Then
            Rows(i & ":" & i).Hidden = True
        End If
    Next i
    
End Sub

 

 上記のコードでかかった時間は、

f:id:kouten0430:20180624150823j:plain

7秒

 

次に、test2として、セルを上から順に比較していき、偶数だった場合にその都度、行をUnionメソッドで取り込み、最後にまとめて非表示にします。

Sub test2()
    Dim i As Integer
    Dim myRange As Range
    
    For i = 1 To 10000
        If Cells(i, 1).Value Mod 2 = 0 Then
            If myRange Is Nothing Then
                Set myRange = Range(i & ":" & i)
            Else
                Set myRange = Union(myRange, Range(i & ":" & i))
            End If
        End If
    Next i

    myRange.EntireRow.Hidden = True

End Sub

 

上記のコードでかかった時間は、

f:id:kouten0430:20180624150909j:plain

56秒

あれ?

 

最後にまとめて、非表示にするほうが速いと思っていたんですが・・・・・・。

 

と、とりあえず、次に、test3として、A1:A10000の範囲を配列に取り込んでから比較し、偶数だった場合にその都度、行をUnionメソッドで取り込んで、最後にまとめて非表示にします。

Sub test3()
    Dim i As Integer
    Dim myRange As Range
    
    Tdim = Range("A1:A10000")
    
    For i = 1 To 10000
        If Tdim(i, 1) Mod 2 = 0 Then
            If myRange Is Nothing Then
                Set myRange = Range(i & ":" & i)
            Else
                Set myRange = Union(myRange, Range(i & ":" & i))
            End If
        End If
    Next i

    myRange.EntireRow.Hidden = True
    
End Sub

 

上記のコードでかかった時間は、

f:id:kouten0430:20180624151057j:plain

56秒

変わらない・・・・・・。

 

最後に、test4として、A1:A10000の範囲を配列に取り込んでから比較し、偶数だった場合にその都度、行を非表示にします。

Sub test4()
    Dim i As Integer
    Dim myRange As Range
    
    Tdim = Range("A1:A10000")
    
    For i = 1 To 10000
        If Tdim(i, 1) Mod 2 = 0 Then
            Rows(i & ":" & i).Hidden = True
        End If
    Next i

End Sub

 

上記のコードでかかった時間は、

f:id:kouten0430:20180624151130j:plain

7秒
test1と変わらないね(@_@;)

 

test1~4をまとめると、下表のようになりました。

方法 時間
1セルごとに比較し、1行ずつ非表示にする 7秒
1セルごとに比較し、Unionメソッドで取り込んだ行を最後にまとめて非表示にする 56秒
配列の中で比較し、Unionメソッドで取り込んだ行を最後にまとめて非表示にする 56秒
配列の中で比較し、1行ずつ非表示にする 7秒

 

えーっと。
自分の予想では、速い順に、test3 < test2 < test4 << test1 だったのですが。
すべて予想と違い、若干混乱しております(@_@;)

Unionメソッドってもしかして、時間のかかる処理なのかな?

セル比較と配列比較で時間が変わらなかったのは、サンプルデータが少なかったからでしょうか。それとも何か、見落としていることがある?

 

というか、今日は何を模索するんだっけ?あれ??