Страницы: 1
RSS
Объединение множества массивов в один массив
 
Здравствуйте!

Сразу прошу прощения за "стену текста", познаю VBA недавно. Хочется не только получить результат, но и понять логику разработки.

Есть "х" листов с разным количеством заполненных строк и одинаковым количеством заполненных столбцов. Т.е. первая размерность разная, вторая одинаковая.
Необходимо собрать данные со всех листов в один массив

Должно получиться так (на примере двух листов):
+ : arr1 :  : Variant/Variant(1 to 26, 1 to 200) - массив с первого листа
+ : arr2 :  : Variant/Variant(1 to 29, 1 to 200) - массив со второго листа
+ : arr3 :  : Variant/Variant(1 to 55, 1 to 200) - "массив массивов"

Для решения задачи (и подтверждения того, что "массив массивов" подойдет) был использован код с перебором значений (под спойлером).
Работает, но проблема заключается в том, что нужно использовать не 2 листа, а, к примеру, 20 или 50 (количество постоянно меняется).
Скрытый текст

На данном форуме удалось найти единственный, похожий на мою ситуацию, совет-ответ, к большому сожалению, без самого кода:
Цитата
The_Prist написал:
Вообще, для сокращения кол-ва строк кода можно собирать в отдельные массивы данные с книг. Сами массивы помещать в один общий массив(в котором будут эти массивы). Иными словами создать массив массивов. А потом все это выгружать или объединить в один массив.
Как алгоритм:
1. Создаем динамический массив массивов(avMain)
2. Идем циклом по книгам и собираем данные в промежуточные массивы(avBook_1, avBook_2 ... avBook_n). Попутно в отдельную переменную плюсуем размерность каждого массива: lResCnt = lResCnt + Ubound(avBook1,1)
3. Определяем размерность результирующего массива(avRes): ReDim avRes(1 to lResCnt, 1 to lColsCnt)
4. Осталось только пройтись циклом по avMain и по очереди выгрузить циклами данные из этих массивов в avRes.
Решение вроде понятное, но как его преобразовать в макрос не могу сообразить.
1) создать динамический массив массивов - разве его можно создать первым пунктом, без понимания размерности?
2) идем циклом по листам и собираем данные в промежуточные массивы - я понимаю, как задать цикл по листам, но как автоматически задать каждому листу новый-уникальный массив?
3) ...

К сообщению прикрепил файл с примером. Голые данные, без макросов.
Если необходимо  
Изменено: Fylhtqq - 09.10.2021 19:03:00
 
Цитата
Fylhtqq написал:
но проблема заключается в том, что нужно использовать не 2 листа, а, к примеру, 20 или 50
макросу по-барабану сколько листов использовать: 2, 3, 50 или 50 тыс. листов
если все решвется одним алгоритмом количество строк кода не увеличится от количества обрабатываемых листов
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Ігор Гончаренко написал:
макросу по-барабану сколько листов использовать: 2, 3, 50 или 50 тыс. листов
Согласен с вами. Одна из моих проблем заключается в том, что я "руками" присваивал каждому листу свою переменную. если делать это для 50 листов - капец
:
Код
lrow1 = Sheets("1").Cells(Rows.Count, 1).End(xlUp).Row
lrow2 = Sheets("2").Cells(Rows.Count, 1).End(xlUp).Row
 
    arr1 = Sheets("1").Range("A1:GR" & lrow1)
    arr2 = Sheets("2").Range("A1:GR" & lrow2)
а далее уже формировал массив массивов:
Код
ReDim arr3(1 To (UBound(arr1) + UBound(arr2)), 1 To Application.Max(UBound(arr1, 2), UBound(arr2, 2)))

Предполагал, что можно сделать примерно так:
Код
For Sh = 1 To Sheets.Count
Worksheets(Sh).Activate
lrow = Cells(Rows.Count, 1).End(xlUp).Row
arr = Range("A1:GR" & lrow)
но уперся в то, что не понял, как тогда присваивать уникальное название переменной массива листа. Т.е. лист 1 - arr1, лист 2 - arr2 и тп
вероятно, что можно не формировать множество переменных массивов (для каждого листа), а просто чистить массив arr через "Erase". Но тогда опять не понятно, как формировать размерность массива массивов.

Не уверен, что вообще правильно понимаю и объясняю, но ничего лучше пока не придумал.
Изменено: Fylhtqq - 09.10.2021 19:44:07
 
Цитата
Fylhtqq написал:
Одна из моих проблем заключается в том, что я "руками" присваивал каждому листу свою переменную
ваши личные проблемы не имеют НИКАКОГО отношения к вопросу программного обращения к 50 тыс. листов
это решается простым циклом
Код
for Each Sh in worksheets
  ' а вот тут пишете, что вас интересует на конкретном листе Sh 
next
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Ігор Гончаренко написал:
это решается простым циклом
Скорее всего, я не правильно выразился.
Я присваивал переменную массива каждому листу, т.е. arr1 это данные из "Лист1", arr2 - из "Лист2". И уже исходя из этих переменных формировал массив каждого листа.

Если проходить циклом по листам, как задать каждому листу свою переменную массива? и как потом такое кол-во переменных использовать при создании размерности массива массивов
 
Fylhtqq, А что вы дальше собираетесь делать с массивами?
"Все гениальное просто, а все простое гениально!!!"
 
я уже написал, что не ясно?
Код
Dim a, sh, i&
redim a(1 to worksheets.count)
for each sh in worksheets
  i = i+1
  a(i) = sh.usedrange
next
ВСЕ!!!
в массиве а у вас массивы данных с листов (ели только размер а не вывалится за пределы возможностей адресного пространства операционной ссистемы или не превысит максимально допустимый разиер) т.е. вопрос как это сделать решен, но совершенно отрыт вопрос "а на кой это нужно"? (зачем они все вместе вам нужны?????)
Изменено: Ігор Гончаренко - 09.10.2021 20:40:52
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Nordheim написал:
Fylhtqq , А что вы дальше собираетесь делать с массивами?
Мне необходимо получить данные со всех листов в одном массиве.
Для этого предполагалось, что с каждого листа будет "получен" отдельный массив и потом все массивы будут объединены в один. На сколько это удачный путь, не могу сказать, но выглядит логично.
 
сделайте коллекцию/словарь и записывайте в нее массивы
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Fylhtqq написал:
но выглядит логично.
только с вашей точки зрения
с моей точки зрения - это абсурдно, а с учетом необходимости проверки не вылезло-ли все за пределы возможностей - вообще как бы это по-мягче сказать, о! - это не рационально! (просились другие слова, но "не рационально" - это корректное выражение для этой ситуации)
если понимать чего вы добиваетесь - можно подсказать как этого достичь, а пока можно только недоумевать: "зачем все это нужно???"
Изменено: Ігор Гончаренко - 09.10.2021 20:47:39
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Если нужно
Цитата
Fylhtqq: получить данные со всех листов в одном массиве
, то совершенно незачем копить эти массивы
Алгоритм простой: берём массив с каждого листа и переписываем в основной массив без накопления
вариант переполнения памяти из-за огромного количества данных, в примере никак не обходится.
    В СВОИХ макросах я выгружаю данные каждого листа сразу на ЛИСТ (и считаю количество строк, т.к. на лист тоже можно только немногим больше миллиона записать). И даже в этом случае, при 200стах столбцах на очередном листе можно переполнить память сразу при попытке получить массив из рабочей области. Особенно на версии Excel x32 (не путать с Win x32 - версия офиса может отличаться от винды) с ограничением используемой оперативной памяти
Изменено: Jack Famous - 11.10.2021 09:49:05
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Бежим по листам, определяем количество строк на каждом. При этом контролируем общее количество (если перевалило через миллион - пора тормозить). Эти значения можно сохранить в массив (какой-нибудь aRowsCount) для дальнейшего использования.
По сумме определяем размерность массива aData для загрузки данных.
Далее опять бежим по листам, но уже забирая данные и дополняя массив.

Этот вариант и вариант, предложенный выше, обратно противоположны. Этот быстрее, но "жрет" память по максимуму, Джек предложил вариант медленнее, но  меньше забивающий оперативную память.
 
vikttur, вариант, но, если можно обойтись без 2ух циклов, то стараюсь делать это  :)
Если уж и делать второй цикл, то тогда я бы уже и массив массивов собирал, чтобы по листам второй раз не бегать  :D

Fylhtqq, "массив массивов" это не такой же массив, но с большим количеством строк, как вы считаете, а массив, ЭЛЕМЕНТАМИ которого являются другие массивы. Для примера это был бы массив aSh(1 To ActiveWorkbook.WorkSheets.Count)
Изменено: Jack Famous - 11.10.2021 10:46:49
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал: если можно обойтись без 2ух циклов, то стараюсь делать это
И это пишет адепт суперскоростей? :):):)
 
Цитата
vikttur: Этот вариант и вариант, предложенный выше, обратно противоположны. Этот быстрее, но "жрет" память по максимуму, Джек предложил вариант медленнее, но  меньше забивающий оперативную память
наоборот — вариант "с запасом" (если ты про КОД) всегда оттяпывает много памяти и может выдать ошибку, где твой метод скальпеля её не выдаст. Плюс, 2 цикла не сильно медленнее будут, зато позволят сформировать итоговый массив точно и без запасов

Но, если ты про "мой" метод выгрузки на лист каждого массива, то всё верно - он заметно медленнее, но и самый надёжный - позволит забить лист "под завязку"  :D

Цитата
vikttur: И это пишет адепт суперскоростей?
адепт  :D
так а сокращение кода не всегда его замедляет  :) Ну а если ты всё также про выгрузку на лист, то надёжность/стабильность/качество результат для меня на 1ом месте, а скорость уже на 2ом  :D

P.S.: вот ты меняешь текст без отметок о редактировании, а мои ответы потом глупо выглядят  :D
Хоть цитируй всё подряд  :D
Изменено: Jack Famous - 11.10.2021 10:54:34
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал: вариант "с запасом" (если ты про КОД) всегда оттяпывает много памяти
Так я же не писал по запас. пробежали, посмотрели количество и только после этого задали размерность
 
Цитата
vikttur: я же не писал
столько наредактировал, что поясню как понял  :D

Цитата
vikttur: Бежим … определяем количество строк … Этот вариант и вариант, предложенный выше, обратно противоположны
этот вариант быстрый, незаметно медленнее 1го цикла, зато лишён минуса оттяпывания памяти в сравнении с вариантом "с запасом"
"Вариант выше" это вариант, который я предложил автору - вариант с 1 циклом и массивом "с запасом". Плох для больших объёмов, зато короче.
Как следует из "сравнения методов" от vikttur, он "вариантом выше" называет "мой" метод "надёжного сбора" - с выгрузкой данных каждого листа на лист-сборник. Этот метод медленее всех, но и надёжный. По надёжности метод vikttur не хуже, однако он будет сложнее в управлении, если данные будем собирать из разных файлов (смежная задача).
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Страницы: 1
Наверх