#arrays #excel #vba
#массивы #excel #vba
Вопрос:
Я хочу проверить, существует ли каждое конкретное значение (текст и числа) из диапазона 1 в диапазоне 2. Если нет, это значение должно быть добавлено к диапазону 2.
Для каждого цикла требуется слишком много времени. Я хочу попробовать с массивами:
-
создайте массив со всеми значениями из диапазона 1
-
создайте массив со всеми значениями из диапазона 2
-
проверьте, не является ли элемент массива 1 пустым
3.1 если нет, проверьте, существует ли элемент в массиве 2
3.1.1 если да, перейдите к следующему элементу массива 1
3.1.2 если нет:
3.1.2.1 добавить элемент в массив 2
3.1.2.1 добавить элемент в диапазон 2 (в рабочей книге)
3.2 если да,перейдите к следующему элементу массива 1 -
перейдите к следующему элементу массива 1 и повторите третий шаг
Public Sub Table_And_Layout() Dim wsRoadmap As Worksheet Dim wsBacklog As Worksheet Dim bList As Range Dim Arr() As Variant Dim rListLastCol As Long Dim TempRng As Variant Dim element As Variant 'Range Set wsBacklog = Sheets("Backlog") Set wsRoadmap = Sheets("Roadmap") Set bList = wsBacklog.Range("C7", wsBacklog.Cells(bListLast, 3)) bListLast = wsBacklog.Cells(wsBacklog.Rows.Count, "C").End(xlUp).Row Arr = wsRoadmap.Range("C6", wsRoadmap.Cells(rListLastRow, rListLastCol)) For Each element In Arr If Not IsEmpty(element) Then Set TempRng = bList.Find(element.Value) If TempRng Is Nothing Then wsBacklog.Cells(bListLast 1, 3).Value = wsRoadmap.Cells(element.Row, element.Column).Value bListLast = wsBacklog.Cells(wsBacklog.Rows.Count, "C").End(xlUp).Row End If End If Next element End Sub
Комментарии:
1. В чем проблема с вашим кодом?
2. «Установить TempRng = bList.Find(элемент. Значение)» —> выдает ошибку: требуется объект
3. Почему вы не используете dictionnary?
4.
Arr
является массивом, а элементы массива не имеютValue
свойства.
Ответ №1:
ВАРИАНТ 2 является самым быстрым:
Public Sub Table_And_Layout()
Dim wsRoadmap As Worksheet
Dim wsBacklog As Worksheet
Dim bList As Range
Dim bListLast As Long
Dim rList As Range
Dim rListLastCol As Long
Dim TempRng As Variant
Dim element As Variant
'****************************
Dim StartTime As Double
Dim SecondsElapsed As Double
StartTime = Timer
'****************************
'Remember time when macro starts
StartTime = Timer
Set wsBacklog = Sheets("Backlog")
Set wsRoadmap = Sheets("Roadmap")
' unlock sheet
wsBacklog.Unprotect
bListLast = wsBacklog.Cells(wsBacklog.Rows.Count, "C").End(xlUp).Row
Set bList = wsBacklog.Range("C7", wsBacklog.Cells(bListLast, 3))
Set rList = wsRoadmap.Range("C6:BB100")
' find last not empty column
rListLastCol = wsRoadmap.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'MsgBox "Last Col: " amp; rListLastCol
' find last not empty row
rListLastRow = wsRoadmap.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'MsgBox "Last Row: " amp; rListLastRow
Set rList = wsRoadmap.Range("C6", wsRoadmap.Cells(rListLastRow, rListLastCol))
'MsgBox rList.Address
'OPTION 1 (works but very slow)
' ' filling backlog
' For Each element In rList
' If Not element Is Nothing Then
' Set TempRng = bList.Find(element.Value)
' If TempRng Is Nothing Then
' wsBacklog.Cells(bListLast 1, 3).Value = wsRoadmap.Cells(element.Row, element.Column).Value
' bListLast = wsBacklog.Cells(wsBacklog.Rows.Count, "C").End(xlUp).Row
' End If
' End If
' Next element
'OPTION 2 (works fast)
' declare array for roadmap
Dim Arr() As Variant ' declare an unallocated array.
Arr = wsRoadmap.Range("C6", wsRoadmap.Cells(rListLastRow, rListLastCol)) ' Arr is now an allocated array
' Dim NumRows As Long
' Dim NumCols As Long
' MsgBox NumRows = UBound(Arr, 1) - LBound(Arr, 1) 1
' MsgBox NumCols = UBound(Arr, 2) - LBound(Arr, 2) 1
' declare array for backlog
Dim ArrB() As Variant
ArrB = wsBacklog.Range("C6", wsBacklog.Cells(bListLast, 3))
'filling backloga
For Each element In Arr
If Not IsEmpty(element) Then
Set TempRng = bList.Find(element)
If TempRng Is Nothing Then
wsBacklog.Cells(bListLast 1, 3).Value = element
bListLast = wsBacklog.Cells(wsBacklog.Rows.Count, "C").End(xlUp).Row
End If
End If
Next element
'OPTION 3 (does not work)
' For i = LBound(Arr) To UBound(Arr)
' For j = LBound(ArrB) To UBound(ArrB)
' If Not IsEmpty(i) Then
' If Arr(i) = ArrB(j) Then
' wsBacklog.Cells(bListLast 1, 3).Value = Arr(i)
' End If
' End If
' Next
' Next
'*************************************************************************************
'Determine how many seconds code took to run
SecondsElapsed = Round(Timer - StartTime, 2)
'Notify user in seconds
MsgBox "This code ran successfully in " amp; SecondsElapsed amp; " seconds", vbInformation
'*************************************************************************************
End Sub
PS. Спасибо, SJR!