Страницы: 1 2 След.
RSS
Как заполнить в цикле динамический массив
 
Добрый день!  
Требуется заполнить динамический массив значениями столбца ячеек, содержащих год например 2008, пока значение ячейки в столбце не станет 2009годом.  
Как построить код?  
Спасибо!
 
Объявить массив  
Определить диапазон для поиска  
По диапазону запусить цикл сравнения:  
Для каждого элемента диапазона  
Если элемент диапазона соответствует условию, то  
а.Изменяем размерность массива с сохранением ранее введенных данных  
б.записываем в массив значение проверяемого элемента  
Конец Если  
Следующий элемент диапазона  
 
Как-то так
 
А как изменить размерность массива с солхранением значений?
 
Использовать  
ReDim ... Preserve
 
Цикл, кстати, не обязательно запускать для всех элементов проверяемого диапазона. Чтобы зря не перебирать весь диапазон, можно использовать цикл с условием, типа:  
Пока условие выполняется (в данном случае, пока год = 2008), делать то-то и то-то, т.е. конструкии    
Do while  
...  
...  
...  
Loop
 
Да что у всех такое прям неприятие к Do... Loop ? :О) чем данная конструкция так уж провинилась?  
Я не про данный случай, я вообще... очень часто сталкиваюсь с нежеланием использовать. А почему - не говорят...
 
For Next быстрее выполняется, и если нет необходимости проверять условие на каждой стадии прохода цикла, предпочтительнее использовать его.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Sub MySub()  
Я вот так сделал  
Dim i As Integer  
Dim my_Array() As Variant  
Dim myRange As Range  
i = 2  
Do While Cells(i, 1) = 2008  
ReDim Preserve my_Array(i)  
Set myRange = Cells(i, 1)  
my_Array(i - 1) = Cells(i, 1).Value  
i = i + 1  
Loop  
End Sub
 
при таком коде какое будет значение у элементов массива my_Arr(0), my_Arr(1)?
 
Sub www()  
   Dim r As Range, a  
   Set r = Range([A1], [A1].End(xlDown))
   r.Sort [A1], 1: r.AutoFilter 1, "2008"
   a = r.SpecialCells(12)  
   ActiveSheet.AutoFilterMode = 0  
End Sub  
Или если уж очень хотца циклом:  
Sub MySub()  
   Dim i As Integer, myArr  
   i = 1  
   Do While Cells(i, 1) = 2008  
       If IsEmpty(myArr) Then  
           ReDim myArr(0)  
       Else  
           ReDim Preserve myArr(i - 1)  
       End If  
       myArr(i - 1) = 2008  
       i = i + 1  
   Loop  
End Sub
Я сам - дурнее всякого примера! ...
 
Я ReDim Preserve не использую - даже непомню, когда практически было необходимо.  
Обычно сразу задаю массив по максимуму (в данном случае по размеру исходного массива), потом заполняю, потом выгружаю заполненную верхушку.  
ReDim Preserve не использую потому, что на каждом шаге массив переписывается заново, что на больших объёмах (что обычно бывает на практике) заметно медленнее, чем выше описанный способ.  
Вот что Вы потом с этими отобранными данными делать будете?
 
Без Preserve и побыстрей:  
Sub MySub()  
   Dim i As Integer, myArr  
   i = WorksheetFunction.CountIf(ActiveSheet.UsedRange.Columns(1), "2008")  
   ReDim myArr(i - 1)  
   For i = 0 To UBound(myArr)  
       myArr(i) = 2008  
   Next  
End Sub
Я сам - дурнее всякого примера! ...
 
Спасибо огромное за советы, все способы отличные!
 
{quote}{login=Пытливый}{date=11.09.2011 12:01}{thema=}{post}Да что у всех такое прям неприятие к Do... Loop ? :О) чем данная конструкция так уж провинилась?  
Я не про данный случай, я вообще... очень часто сталкиваюсь с нежеланием использовать. А почему - не говорят...{/post}{/quote}Кто Вам такое сказал? For Next используем, когда известно конечное число итераций. Do... Loop, или While... Wend - когда нужно выйти по условию. И for each... next, когда неизвестно к-во итераций и не нужен условный выход. Вот и все.
Я сам - дурнее всякого примера! ...
 
Не соображу, как изменить размерность двумерного массива.  
Сначала ReDim задавал в цикле и удивлялся, почему на лист выводятся нули и только последнее значение :)  
Позже вывел ReDim с максимумальной размерностью перед циклом.    
 
На лист заносятся все даты с выбранным числом месяца (например, 15.??.??), которые попадают в период между двумя датами. Во второй столбец - единицы (позже будут и двойки, это пока не важно).  
 
Dim ArrM() As Date, nath As Date, kon As Date  
Dim dd As Date, day1 As Byte, i&  
   With Worksheets("Лист3")  
       nath = .Range("F1") ' начальная дата  
       kon = .Range("F2") ' конечная дата  
       day1 = .Range("G2") ' день месяца  
   End With  
ReDim ArrM(1 To 20, 1 To 2)  
i = 1  
   While DateSerial(Year(nath), Month(nath) + i - 1, day1) < kon  
       dd = DateSerial(Year(nath), Month(nath) + i - 1, day1)  
'        ReDim ArrM(1 To i, 1 To 2)  
       ArrM(i, 1) = dd  
       ArrM(i, 2) = 1  
       i = i + 1  
   Wend  
'ReDim Preserve ArrM(1 To i, 1 To 2)  
'ReDim Preserve ArrM(i)  
 
   Worksheets("Лист3").Range("A2"). _  
               Resize(UBound(ArrM, 1), UBound(ArrM, 2)).Value = ArrM  
 
 
В таком варианте работает, но на лист выгружается лишнее (строки больше i).  
Как правильно записать ReDim Preserve для двумерного массива?
 
Файл на всякий случай.
 
только хотел написать про файлик ))  
Сейчас посмотрим...
 
Dim ArrM() As Date - это что?
 
{quote}{login=Юрий М}{date=08.01.2012 01:02}{thema=}{post}Dim ArrM() As Date - это что?{/post}{/quote}  
Динамический массив с данными в формате ДАТА.  
По крайней мере, Гарнаев указывает типы данных.
 
Вить, может так?  
 
Worksheets("Лист3").Range("A2").Resize(i - 1, 2).Value = ArrM
 
>>Как правильно записать ReDim Preserve для двумерного массива?  
Когда в а набрали значения:  
redim preserve a(1 to ubound(a),1 to 2)
Я сам - дурнее всякого примера! ...
 
Спасибо, работает. За Resize не подумал.  
 
Для галочки в голове: как записать строку с Preserve? Например, задать в цикле, не задавая максимальной размерности. Даты могут отстоять друг от друга и на месяц, и на 5 лет, а забивать память под даты для 5-7 лет есть разбазаривание и транжирство.
 
Не за что, Вить.  
 
По поводу Preserve я не очень уверен, т.к. на сколько я знаю, через Preserve можно менять размерность только внешней границы,    
 
Preserve (1 to тут_менять_нельзя, 1 to тут_менять_можно)  
 
 
Павел  
 
P.S. Сейчас попытаюсь ещё немного оптимизировать твой код
 
{quote}{login=KukLP}{date=08.01.2012 01:12}{thema=}{post}Когда в а набрали значения: redim preserve a(1 to ubound(a),1 to 2){/post}{/quote}  
 
' ReDim ArrM(1 To 1, 1 To 2)  
ReDim ArrM(1 To 7, 1 To 2)  
   While DateSerial(Year(nath), Month(nath) + i - 1, day1) < kon  
       dd = DateSerial(Year(nath), Month(nath) + i - 1, day1)  
       ArrM(i, 1) = dd  
       ArrM(i, 2) = 1  
       i = i + 1  
       ReDim Preserve ArrM(1 To UBound(ArrM), 1 To 2)  
   Wend  
'    ReDim Preserve ArrM(1 To UBound(ArrM), 1 To 2)  
 
Что я не так понял? UBound не изменяется ни в одном из вариантов. Массиву ведь нужно в цикле указать, что добавить 1 строку.
 
Ну можно Preserve двум параллельным одномерным массивам делать :)  
Только потом перед выгрузкой с ними будет мутотень - вероятно надо будет циклом переложить в созданный под размер двумерный.  
Ну и если данных много - то Preserve имхо будет подтормаживать...
 
{quote}{login=}{date=08.01.2012 01:24}{thema=}{post}...на сколько я знаю, через Preserve можно менять размерность только внешней границы...{/post}{/quote}  
А я-то считал, что внешняя граница - это максимальная строка. Выходит, ошибался?
 
Вить, вот посмотри  
 
Sub Test()  
Dim a() As Byte  
ReDim a(10, 20)  
ReDim Preserve a(10, 30) 'работает  
 
ReDim a(10, 20)  
ReDim Preserve a(30, 30) 'не работает  
End Sub  
 
Я тут 2 дня назад создавал тему по этому поводу  
http://www.planetaexcel.ru/forum.php?thread_id=36160
 
Вроде в Справке написано так: ReDim Preserve может менять верхнюю границу последней размерности многомерных размеров, но не может менять первую размерность.
 
Да, вот эксперимент:  
 
 
Sub tt()  
Dim a(), i&, tm!  
tm = Timer  
For i = 1 To 100000  
ReDim Preserve a(1 To i)  
a(i) = i  
Next  
Debug.Print Timer - tm  
End Sub  
 
Теперь увеличьте число итераций вдвое...
 
Без редимов лучше в словарь складывать.
Я сам - дурнее всякого примера! ...
Страницы: 1 2 След.
Читают тему
Наверх