Вот другой подход, который довольно быстр:
Sub Lister()
Dim t, i, m, arr, rng, dict As Object, dictDupes As Object, usr, v
Set dict = CreateObject("scripting.dictionary")
Set dictDupes = CreateObject("scripting.dictionary")
Set rng = Range("A1:A500000")
'create some dummy data (0.5M rows)
With rng
.Formula = "=""USER_"" & ROUND(RAND()*5000,0) & ""_"" & ROUND(RAND()*3000,0)"
.Value = .Value
End With
t = Timer
arr = rng.Value
For i = 1 To UBound(arr, 1)
usr = arr(i, 1)
If Not dict.exists(usr) Then
dict.Add usr, i
Else
If Not dictDupes.exists(usr) Then dictDupes.Add usr, dict(usr)
dictDupes(usr) = dictDupes(usr) & "|" & i
End If
Next i
For Each usr In dictDupes
v = dictDupes(usr)
'Debug.Print "----" & usr & "---"
'Debug.Print Join(Split(v, "|"), ", ")
Next usr
Debug.Print dict.Count, dictDupes.Count
Debug.Print "Done in", Timer - t
End Sub
Завершается примерно за 20-25 сек c
Еще одно примечание:
Если вы хотите используйте Match, тогда намного быстрее оставить ваши данные на листе вместо запуска Match для массива.
Sub TestMatch()
Dim t, i, m, arr, rng
Set rng = Range("A1:A50000")
With rng
.Formula = "=ROUND(RAND()*30000,0)"
.Value = .Value
End With
t = Timer
For i = 1 To 10000
m = Application.Match(i, rng, 0)
Next i
Debug.Print "sheet", Timer - t
arr = rng.Value
t = Timer
For i = 1 To 10000
arr = rng.Value
m = Application.Match(i, arr, 0)
Next i
Debug.Print "array", Timer - t
End Sub
Вывод:
sheet 3.644531
array 131.9453
Таким образом, массив равен 35x медленнее .