Вот в этой теме столкнулся с проблемой "ридимопресервания" 2х массива
Процесс: 1. ищу совпадения (строки "r", может быть несколько) по заданному столбцу 2. Если совпадение есть, то забираю значения ячеек нескольких "N" столбцов по этой строке 3. Продолжаю поиск
Первое, что приходит в голову, это собирать двумерный массив arr(1 To r, 1 To N). Но для этого нужно объявить его с запасом, то есть Redim arr (1 To ROWS, 1 To N), где ROWS - все проверяемые строки. Проблема возникает, при попытке после отбора сделать Redim Preserve arr(1 To r, 1 To N), т.к. редимить можно только последнюю размерность. В той теме я обошёл это, собирая всё в 1х массив, редимя его и, потом, в цикле, восстанавливая структуру по блокам. Как сделать быстрее, проще и правильнее в этом случае?
Планирую собрать в этой теме примеры с разными размерностями и нюансами их использования
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
1) Если исходный массив больше не будет использоваться можно его перезаписывать с применением дополнительной переменной счетчиком, которая увеличивается при выполнении определенного условия. 2) Либо объявить массив размером с исходником, заполнять так же как и в первом случае с использованием переменной (счетчик), далее переносить на лист указывая размерность по вертикали равную переменной счетчику. 3) можно и ReDim пресервить перевернув массив а потом просто транспонировать циклом, транспонирование больших массивов займет время, но не думаю что это критично.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Sub test1()
' ----------------------------
Dim arr(), dic As Object
Dim i&, j&, x&
' ----------------------------
Set dic = CreateObject("Scripting.Dictionary")
' заполняем словарь данными для проверки
arr = ActiveSheet.UsedRange.Value
For i = 1 To UBound(arr)
If dic.exists(CStr(arr(i, 1))) Then
x = x + 1
For j = 1 To UBound(arr, 2)
arr(x, j) = arr(i, j)
Next j
End If
Next i
Worksheets(1).[a1].Resize(x, UBound(arr, 2)).Value = arr
End Sub
Код
Sub test2()
' ----------------------------
Dim arr(), dic As Object
Dim i&, j&, x&
' ----------------------------
Set dic = CreateObject("Scripting.Dictionary")
' заполняем словарь данными для проверки
arr = ActiveSheet.UsedRange.Value
ReDim iarr(1 To UBound(arr), 1 To UBound(arr, 2))
For i = 1 To UBound(arr)
If dic.exists(CStr(arr(i, 1))) Then
x = x + 1
For j = 1 To UBound(arr, 2)
iarr(x, j) = arr(i, j)
Next j
End If
Next i
Worksheets(1).[a1].Resize(x, UBound(arr, 2)).Value = iarr
End Sub
Код
Sub test3()
' ----------------------------
Dim arr(), dic As Object
Dim i&, j&, x&, iarr(), larr()
' ----------------------------
Set dic = CreateObject("Scripting.Dictionary")
arr = ActiveSheet.UsedRange.Value
' заполняем словарь данными для проверки
For i = 1 To UBound(arr)
If dic.exists(CStr(arr(i, 1))) Then
x = x + 1
ReDim Preserve iarr(1 To UBound(arr, 2), 1 To x)
For j = 1 To UBound(arr, 2)
iarr(j, x) = arr(i, j)
Next j
End If
Next i
ReDim larr(1 To UBound(iarr, 2), 1 To UBound(iarr))
For i = 1 To UBound(iarr)
For j = 1 To UBound(iarr, 2)
larr(j, i) = iarr(i, j)
Next j, i
Worksheets(2).[a20].Resize(UBound(larr), UBound(larr, 2)).Value = larr
End Sub
Nordheim, реализация через словарь - буду пробовать. Спасибо!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Все зависит от количества обращений к листу. Если их очень много, то скорость обработки вырастает в разы. У меня был макрос обрабатывающий (сверяющий 2 листа) хитрым образом выводя в отчет еще 3 листа. Написан был с обращением к листу так там время обработки было от 2 до 6 мин. Запихнул обработку в массив время обработки сократилось от 6 до 21 сек. Как то так
Еще вариант: 1. Собираем в словарь номера строк, удовлетворяющих условию. (в примере - это непустые значения 1-го столбца). 2. Определяем уже известную размерность итогового массива 3. Собираем итоговый массив из выбранных строк исходного массива. Т. е примерно так:
Код
Sub qq()
Dim i As Long, j As Long, a(), b(), z, q
Set z = CreateObject("Scripting.Dictionary")
a = [A1:C20].Value 'Пусть это исходный массив
For i = 1 To UBound(a, 1)
If a(i, 1) <> "" Then z(i) = ""
Next
ReDim b(1 To z.Count, 1 To UBound(a, 2)): i = 0
For Each q In z.Keys
i = i + 1
For j = 1 To UBound(a, 2): b(i, j) = a(q, j): Next
Next
End Sub
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
тупо - согласен)) просто я мысленно словари на массивы заменил))) Типа, собираем строки, а потом комплектуем массив известной размерности. Чуть более понятно, но с 2мя (отдельными не вложенными) циклами, что, наверное, проиграет в скорости. Решения всякие нужны, решения всякие важны!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Nordheim написал: Все зависит от количества обращений к листу
Все верно, просто часто в массив загоняют и малоразмерные области, типа по привычке, потом вах надо изменить размерность и начинается танец с бубном, а там разница по скорости будет совсем скромная. Для каждой задачи свое решение.
Jack Famous написал: с 2мя (отдельными не вложенными) циклами
Если объемы большие то это не вариант. Если не привычны словари, то можно коллекции использовать там принцип вроде тот же, только уникальность обрабатывается через
Код
On Error Resume Next
, а в условии прописывается
Код
If Err.Number = 0 then
'Цикл переноса
Err.Clear
End If
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Sub uuu()
Dim i As Long, j As Long, a(), b(), z&(), q&, s&
a = [A1:C20].Value 'Пусть это исходный массив
ReDim z(1 To UBound(a, 1)) ' массив номеров строк (размер с запасом) '
For i = 1 To UBound(a, 1)
If a(i, 1) <> "" Then q = q + 1: z(q) = i
''''If a(i, 1) = Что_ищем Then q = q + 1: z(q) = i
Next
ReDim b(1 To q, 1 To UBound(a, 2))
For i = 1 To q
s = s + 1
For j = 1 To UBound(b, 2): b(s, j) = a(z(i), j): Next
Next
[F1].Resize(q, UBound(b, 2)).Value = b
End Sub
Jack Famous написал #1: Процесс:1. ищу совпадения (строки "r", может быть несколько) по заданному столбцу2. Если совпадение есть, то забираю значения ячеек нескольких "N" столбцов по этой строке3. Продолжаю поиск
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Вариант с использованием коллекции. Чуть проще, т. к. выбор элементов коллекции осуществляется по указателю цикла. Как быстрее - не проверял.
Код
Sub qq()
Dim i As Long, j As Long, a(), b(), z As New Collection
a = [A1:C20].Value 'Пусть это исходный массив
For i = 1 To UBound(a, 1)
If a(i, 1) <> "" Then z.Add i
Next
ReDim b(1 To z.Count, 1 To UBound(a, 2))
For i = 1 To z.Count
For j = 1 To UBound(a, 2): b(i, j) = a(z(i), j): Next
Next
End Sub
согласен — стараюсь использовать For i=…To… только когда нужен этот i внутри цикла
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
А почему нет? В Словарях только этот цикл и использую, а если делать с помощью For ...Next (в словарях), так там прям танцы с бубнами, в одних скобках запутаешься.
"Все гениальное просто, а все простое гениально!!!"
Nordheim, век живи - век учись)) про выгоду For Each слышал не раз, а то что её можно всегда использовать таким образом - не допёр Спасибо вам большое!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄