Quantcast
Channel: いつも隣にITのお仕事
Viewing all articles
Browse latest Browse all 2111

【エクセルVBA】重複排除処理が速いのはどっち?Dictionaryオブジェクト vs 複数ループ

$
0
0

dictionaryVSLoop,eyecatch

皆様こんにちは、ノグチです。

前回までは、Dictionaryオブジェクトを使って、複数ループで書かれた重複排除の処理を

置き換えていく方法をご紹介してきました。

今回は、置き換え前の複数ループ文で書かれたコードと、Dictionaryに置き換えられたコード、どちらが処理速度が速いのか?を試してみたいと思います!

前回記事は、下記リンクをご覧ください。

【エクセルVBA】Dictionaryオブジェクトを使ったリストの重複排除プログラム
複数のループ文で書かれた重複排除処理のコードを、これまで複数回にわけでご紹介してきた、Dictionaryオブジェクトと各メソッド、プロパティを使ったコードに置き換えていきます。これなら複数ループでネストが深くなってしまったり、ゴチャゴチャしてしまうコードともオサラバ!...かも?

処理時間比較用のリストとコード

検証用のリストデータ

まず、速度の検証に使うデータはこちらです。vba,dictionary,検証用データ

このリストは前回までの記事で何度か登場してきましたが、今回はこの左側リストのレコード件数を30,000件に増やして、各コードの処理時間を計測してみたいと思います!

複数ループを使った重複排除処理のコード

まず、ループを複数使って書かれた重複排除処理のコードがこちら。

先にお見せしたリストの、左側のリストにある品目の値が右側の出力リストにあるかどうかをループで探し、対象の品目が右側のリストにあった場合は在庫数を加算する、という動作のコードです。

Sub TestList()
Dim i As Long
Dim j As Long
Dim flgFind As Long
Dim maxRow  As Long
Dim Start as Variant
Dim Finish as Variant

Start = time

With ActiveSheet
    maxRow = .Cells(Rows.Count, 2).End(xlUp).Row
    For i = 2 To maxRow
        flgFind = 0
        For j = 2 To .Cells(Rows.Count, 6).End(xlUp).Row
            If .Cells(i, 2).Value = .Cells(j, 6).Value Then
                .Cells(j, 7).Value = .Cells(j, 7).Value + .Cells(i, 3).Value
                flgFind = 1
                Exit For
            End If
        Next j
        
        If flgFind = 0 Then
            .Cells(j, 6).Value = .Cells(i, 2).Value
            .Cells(j, 7).Value = .Cells(i, 3).Value
        End If
    Next i
    
End With

Finish = time

MsgBox "処理時間は" & Finish - Start & "秒です"

End Sub

コードは前回の記事のものと全く同じですが、今回は処理時間の計測ということで、処理完了時にメッセージボックスで処理時間を表示するようにしました。

処理時間を計測する方法については、下記記事をご覧くださいね。

遅い…重い…そんなエクセルVBAプログラムの処理速度を劇的に改善する方法
エクセルVBAの実行速度が遅い・重いって時ありませんか?そんな時にエクセルVBAのプログラムの処理速度を速くするテクニックを紹介します。プログラムの実行時間を測定する方法も合わせてお伝えします。

Dictionaryを使った重複排除処理のコード

そして、Dictionaryオブジェクトを使った重複排除のコードです。

こちらも、前回出てきたコードに処理時間を計測して、メッセージボックスで表示するコードを追加してあります。

Sub ListWithDictionary()
Dim i As Long
Dim j As Long
Dim maxRow As Long
Dim dic As Dictionary
Dim Start As Variant
Dim Finish As Variant

Start = Time

Set dic = New Dictionary

j = 2 'リスト書き出し開始行

With ActiveSheet

    maxRow = .Cells(Rows.Count, 2).End(xlUp).Row

    For i = 2 To maxRow
        If dic.Exists(.Cells(i, 2).Value) Then
            .Cells(dic.Item(.Cells(i, 2).Value), 7).Value = .Cells(dic.Item(.Cells(i, 2).Value), 7).Value + .Cells(i, 3).Value
        Else
            dic.Add (.Cells(i, 2).Value), j
            .Cells(j, 6).Value = .Cells(i, 2).Value
            .Cells(j, 7).Value = .Cells(i, 3).Value
            j = j + 1
        End If
    Next i

End With

Finish = Time

MsgBox "処理時間は" & Format(Finish - Start, "nn分ss秒") & "です"

End Sub

計測方法

前述2種類のコードを、冒頭にお見せした3000件のデータを使って実行時間を計測してみましょう。

計測時間の比較は、単純に各コードを3回ずつ実行して、平均した値で行っていきます。

実行結果

では早速、複数ループのコードから実行してみましょう!
1回目
vba,dictionary,計測時間,loop,1回目
2回目
vba,dictionary,計測時間,loop,2回目
3回目
vba,dictionary,計測時間,loop,3回目

3回の平均は33秒でした。

やはりループが複数あると処理時間は長くなりやすいですね。

お次はDictionaryオブジェクトのコードを実行してみます。

1回目
vba,dictionary,計測時間,1回目
2回目
vba,dictionary,計測時間,2回目
3回目
vba,dictionary,計測時間,3回目
3回の平均は4.7秒

平均を出すまでもなく結果が見えている気がしますが、先のコードの実行時間と比較すると相当なスピードアップです。

各コードの処理時間を表にまとめてみました。

処理時間(秒) 複数ループ Dictionary
1回目 35 4
2回目 34 5
3回目 30 5

結果は、表のとおりDictionaryオブジェクトのコードが複数ループ文におよそ7倍ほどの差をつけて圧勝でした。

今回は処理対象の項目が2項目のみと少ないのでこの結果になっていますが、項目や処理の種類が増えるほど処理時間の差が開きそうですね。

最後に

今回は、Dictionaryオブジェクトを使って書かれたコードと、複数ループを使って書かれたコードの処理時間を比較してみました。

結果で見られた通り、Dictionaryオブジェクトを使ったコードならばかなり高速化できそうですね。

もし皆様のお手元にあるVBAコードの処理時間が長い、と悩んでおられるなら、Dictionaryオブジェクトでコードを書き換えてみてはいかがでしょうか。

それでは、最後までお読みいただきありがとうございました!

連載目次:エクセルVBAのDictionaryオブジェクトでリストの重複を排除する

エクセルVBAでリストの重複を排除する方法として、Dictionaryオブジェクトを使った重複排除の方法をご紹介しています。

  1. 【エクセルVBA】リスト処理に便利!Dictionaryオブジェクトをコードで使うための準備
  2. 【エクセルVBA】AddメソッドでDictionaryオブジェクトにキーと要素を追加する方法
  3. 【エクセルVBA】DictionaryオブジェクトのExistsメソッドで重複があるかを確認する方法
  4. 【エクセルVBA】Dictionaryオブジェクトを使ったリストの重複排除プログラム

Viewing all articles
Browse latest Browse all 2111

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>