Sub TEST1()
Dim A, B
A = Range("A2:A10") '値を配列に入力
ReDim B(1 To UBound(A, 1), 1 To 1) '空の配列を作成する(重複しないリスト用)
Dim Flag
'値をループする
For i = 1 To UBound(A, 1)
Flag = 0
'重複しないリストの配列をループ
For j = 1 To UBound(B, 1)
'空白の場合ループ終了
If IsEmpty(B(j, 1)) Then Exit For
'値が一致した場合
If A(i, 1) = B(j, 1) Then
Flag = 1 'フラグを立てる
Exit For 'ループを終了
End If
Next
'フラグがオフの場合
If Flag = 0 Then
m = m + 1 'カウントアップ
B(m, 1) = A(i, 1) '重複しないリストに登録
End If
Next
'配列をセルに入力
Range("C2").Resize(UBound(B, 1)) = B
End Sub
手順としては、
商品を配列に入力
商品をループする
商品が登録されているかを確認
登録されていなければ新しくリストに登録
配列をセルに入力
という感じです。
「商品が登録されているか」の確認に結構時間がかかってしまいます。
重複したリストを用意しておきます。
重複したリストを用意
VBAコードの手順をみてみます。
重複しないリストに登録されているかを確認します。
登録されているかを確認する
商品をループして登録されていない場合は登録していきます。
登録されていない場合は登録する
すべての商品をループして、重複しないリストが作成されます。
重複しないリストをセルに入力します。
配列をセルに入力
これで、重複しないリストを作成できます。
重複しないリストを作成できた
重複しないリストを作成できました。
大量のデータで実行してみる
大量のデータで実行してみます。
Sub TEST2()
t = Timer
Dim A, B
A = Range("A2:A50001") '値を配列に入力
ReDim B(1 To UBound(A, 1), 1 To 1) '空の配列を作成する(重複しないリスト用)
Dim Flag
'値をループする
For i = 1 To UBound(A, 1)
Flag = 0
'重複しないリストの配列をループ
For j = 1 To UBound(B, 1)
'空白の場合ループ終了
If IsEmpty(B(j, 1)) Then Exit For
'値が一致した場合
If A(i, 1) = B(j, 1) Then
Flag = 1 'フラグを立てる
Exit For 'ループを終了
End If
Next
'フラグがオフの場合
If Flag = 0 Then
m = m + 1 'カウントアップ
B(m, 1) = A(i, 1) '重複しないリストに登録
End If
Next
'配列をセルに入力
Range("C2").Resize(UBound(B, 1)) = B
Debug.Print Timer - t & " 秒"
End Sub
「50,001」行のデータを用意しました。
「50,001」行のデータを用意
では、VBAコードを実行してみます。
重複しないリストを作成できた
重複しないリストを作成できました。
かかった時間
かかった時間は、「81.23438 秒」です。
まぁ時間がかかりますね。
重複しないリストを力技でやろうとすると、時間がかかってしまいます。
Dictionaryを使って重複しないリストを作成する
「Dictionary」を使って重複しないリストを作成してみます。
重複しないリストを作成する
「Dictionary」を使って重複しないリストを作成するVBAコードです。
手順は、
値を配列に入力
商品をループする
商品が登録されていなければ登録
「キー」をセルに入力
という感じです。
Sub TEST3()
Dim A
'辞書を作成
Set A = CreateObject("Scripting.Dictionary")
Dim B
'値を配列に入力
B = Range("A2:A10")
'値をループ
For i = 1 To UBound(B, 1)
'登録されていない場合
If A.exists(B(i, 1)) = False Then
A.Add B(i, 1), 0 '辞書に登録する
End If
Next
'セルに値を入力
Range("C2").Resize(A.Count) = WorksheetFunction.Transpose(A.keys)
End Sub
登録されているかの確認を「A.Exists(キー)」でできるのがポイントです。
まずは、簡単なデータで動きを確認してみます。
重複するリストを用意しておきます。
重複するリストを用意
では、順を追って実行結果をみてみます。
商品をループして、辞書に登録されていない場合は登録していきます。
商品をループして辞書に登録されていない場合は登録
登録の確認が「A.Exists(キー)」で簡単にできるので、便利です。
すべての商品をループしたら、セルに「キー」だけを入力します。
辞書のキーをセルに入力
これで、重複しないリストが完成できます。
重複しないリストを作成できた
重複しないリストを作成できました。
VBAコードもシンプルになっていますね。
大量のデータで実行してみる
では、大量のデータで「Dictionary」を使って実行してみます。
Sub TEST4()
t = Timer
Dim A
'辞書を作成
Set A = CreateObject("Scripting.Dictionary")
Dim B
'値を配列に入力
B = Range("A2:A50001")
'値をループ
For i = 1 To UBound(B, 1)
'登録されていない場合
If A.exists(B(i, 1)) = False Then
A.Add B(i, 1), 0 '辞書に登録する
End If
Next
'セルに値を入力
Range("C2").Resize(A.Count) = WorksheetFunction.Transpose(A.keys)
Debug.Print Timer - t & " 秒"
End Sub
「50,001」行のデータを用意しておきます。
「50,001」行のデータを用意
では、VBAコードを実行してみます。
重複しないリストを作成できた
重複しないリストを作成できました。
かかった時間
かかった時間は、「0.125 秒」です。
これなら実務でも使えるレベルですね。
何回も実行するようなVBAコードだと、なおさら速いに越したことはないです。
Dictionaryを使って複数列で重複しないリストを作成する
Dictionaryを使って「複数列」で重複しないリストを作成することもできます。
うまく「Dictionary」を使えば、自由自在に重複しないリストが作成できます。
複数列で重複しないリストを作成
「複数列」で重複しないリストを作成してみます。
ポイントは、複数列の値を「区切り文字」で結合して登録する、というところです。
区切り文字は、データの中で使わない文字を使います。
手順としては、
値を配列に入力
配列をループ
「商品」+「/」+「支店」で登録されているかを確認
登録されていなければ、「商品」+「/」+「支店」を登録
配列にも「商品」と「支店」を入力
「商品」と「支店」の配列をセルに入力
という感じです。
Sub TEST5()
Dim A
'辞書を作成
Set A = CreateObject("Scripting.Dictionary")
Dim B, C
'値を配列に入力
B = Range("A2:B10")
'空配列を作成
ReDim C(1 To UBound(B, 1), 1 To 2)
k = 0
'配列をループする
For i = 1 To UBound(B, 1)
'登録されていない場合
If A.exists(B(i, 1) & "/" & B(i, 2)) = False Then
A.Add B(i, 1) & "/" & B(i, 2), 0 '辞書に登録
k = k + 1
C(k, 1) = B(i, 1) '商品
C(k, 2) = B(i, 2) '支店
End If
Next
'配列をセルに入力
Range("D2").Resize(A.Count, 2) = C
End Sub
ポイントは、辞書とは別に「配列」を作成して、重複しない「商品」と「支店」を入力する点になります。
まずは、簡単なデータで試してみます。
重複するリストを用意
では、順を追って実行結果をみてみます。
「商品+支店」のデータで、登録されていない場合は、登録していきます。
商品+支店で、登録されていない場合は登録
辞書に登録する際に、配列にも「商品」と「支店」を入力していきます。
商品と支店の値を、配列にも値を入力
元データを最後までループすると、複数列で重複しない値を、「配列」に格納することができます。
最後までループして、辞書と配列に値を登録
最後に配列をセルに入力したら完了です。
配列をセルに入力
これで、複数列で重複しないリストを作成できます。
複数列で重複しないリストを作成できた
「複数列」で重複しないリストを作成できました。
大量のデータで実行してみる
複数列の場合で大量のデータを使って実行してみます。
複数列の場合でも「Dictionary」を使えば、高速で実行することができます。
Sub TEST6()
t = Timer
Dim A
'辞書を作成
Set A = CreateObject("Scripting.Dictionary")
Dim B, C
'値を配列に入力
B = Range("A2:B50001")
'空配列を作成
ReDim C(1 To UBound(B, 1), 1 To 2)
k = 0
'配列をループする
For i = 1 To UBound(B, 1)
'登録されていない場合
If A.exists(B(i, 1) & "/" & B(i, 2)) = False Then
A.Add B(i, 1) & "/" & B(i, 2), 0 '辞書に登録
k = k + 1
C(k, 1) = B(i, 1) '商品
C(k, 2) = B(i, 2) '型番
End If
Next
'配列をセルに入力
Range("D2").Resize(A.Count, 2) = C
Debug.Print Timer - t & " 秒"
End Sub