Код ниже полагается на возможность доступа к объекту Scripting.Dictionary.Я использую позднюю привязку, поэтому вам не нужно добавлять ссылку.
Вы сказали, что Range.Resize
убивает вас.Не совсем уверен, почему это так, но я снова использую его в приведенном ниже коде.Если у вас есть проблемы с производительностью, дайте мне знать.
Option Explicit
Private Sub findFirstMatching()
' Declared two constants because OP had done it that way in their post.
' Depending on use case, could get rid of second and just use the one
' But having two allows you to change one without the other.
Const READ_ROW_COUNT As Long = 10000 ' Used for columns A, B
Const COMPARISON_ROW_COUNT As Long = 10000 ' Used for columns D, E
' Change sheet name below to wherever the data is. I assume Sheet1 '
With ThisWorkbook.Worksheets("Sheet1")
Dim columnA() As Variant
columnA = .Range("A1").Resize(READ_ROW_COUNT, 1).Value2
Dim columnD() As Variant
columnD = .Range("D1").Resize(COMPARISON_ROW_COUNT, 1).Value2
Dim columnE() As Variant
columnE = .Range("E1").Resize(COMPARISON_ROW_COUNT, 1).Value2
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim rowIndex As Long
' Fill dictionary (array values as dictionary's keys, row numbers as dictionary's corresponding values)
' If there are duplicates in column D, the dictionary will only contain/return the row number of the FIRST instance/match
For rowIndex = LBound(columnD, 1) To UBound(columnD, 1)
If Not dict.Exists(columnD(rowIndex, 1)) Then
dict.Add columnD(rowIndex, 1), rowIndex
End If
Next rowIndex
Dim outputArray() As Variant
ReDim outputArray(1 To READ_ROW_COUNT, 1 To 1)
Dim rowIndexOfFirstMatch As Long
' Now loop through column A's values and check if it exists in dict
For rowIndex = LBound(columnA, 1) To UBound(columnA, 1)
If dict.Exists(columnA(rowIndex, 1)) Then
rowIndexOfFirstMatch = dict.Item(columnA(rowIndex, 1))
outputArray(rowIndex, 1) = columnE(rowIndexOfFirstMatch, 1)
Else
outputArray(rowIndex, 1) = "#N/A" ' Change to zero if needed.
End If
Next rowIndex
.Range("B1").Resize(READ_ROW_COUNT, 1) = outputArray
End With
End Sub
Я протестировал код на некоторых фиктивных данных, сгенерированных на моем конце, и мне кажется, что код должен делать то, что вы описали (длякаждое значение в столбце A, столбец B в моих выходных данных содержит либо #N/A
, либо значение в столбце E, если совпадение было найдено).Если этого не произойдет, дайте мне знать, почему / что не так.