Страницы: 1
RSS
Упростить сбор данных с нескольких листов
 
Как всегда, хочется улучшений :)  
 
Работает: из 6-7 листов собирается информация в сводный лист.  
1. выбрали лист  
2. посмотрели, есть ли данные  
3. если да, загнали диапазон в массив  
3. записали нужные строки в массив (перезаписали массив) (может быть на каждом листе до 1500)  
4. выгрузили найденное на сводный лист  
5. выбрали следующий лист...  
При таком варианте обращаемся к сводному листу (выгрузка) несколько раз.    
 
Хотелка: последовательно записать в массив данные со всех листов и один раз выгрузить на сводный (так быстрее?).  
Проблема известна: нельзя изменять первую размерность массива.  
Обход проблемы: создать два массива и записывать данные то в один, то в другой (данные предыдущего массива плюс данные просматриваемого листа).  
 
Есть ли вариант лучше? Словари и прочие страшные слова пока не предлагать. Не дорос, а хочется понятного :)  
 
Ниже пример действующего кода.  
 
For Each shts In Rng.Value ' перебор листов  
   ------------------  
       With Worksheets(shts)    
           lRws = .Cells(Rows.Count, "K").End(xlUp).Row ' последняя строка  
           Set Rng = .Range("C5:R" & lRws) ' присвоить переменной Rng ссылку на диапазон  
       End With  
   ------------------          
       If lRws > 4 Then ' если записи есть  
               i = 0  
               ArrTmp = Rng.Value ' значения диапазона листа в переменную  
               For k = 1 To UBound(ArrTmp, 1)     ' скопировать нужные строки  
                   If условие_выполняется Then        
                       i = i + 1  
                       ArrTmp(i, 2) = ArrTmp(k, 2)  
                       ArrTmp(i, 3) = ArrTmp(k, 3)  
     ..................................  
                   End If  
               Next k  
   ------------------              
           ' выгрузка массива на  сводный лист  
           With Worksheets("свод")  
               lRws = .Cells(Rows.Count, "K").End(xlUp).Row + 1 ' первая пустая строка  
               .Cells(lRws, 3).Resize(i, UBound(ArrTmp, 2)).Value = ArrTmp ' массив на лист  
           End With  
       End If  
   Next shts
 
Я думаю, что выгрузить один раз всё, или 7 раз частями - разница будет менее секунды.  
Попробуй задать сразу результирующий массив на 14000 строк (чтоб хватило), заполнить и выгрузить - и посмотри разницу в скорости.
 
Я как-то раз сделал следующим способом: создавал временный лист, на него циклом копировал диапазоны целиком (это быстро), забирал сборный диапазон в массив. Размерность уже известна. Затем в параллельный массив перекладывал по условию нужное, и уже этот второй массив выгружал на лист.
 
Не экспериментировал с объемами, которые предполагаются, но если действительно разница небольшая, то для данной задачи сойдет и так.  
О массиве "с запасом" тоже думал, но это же память кушать...  
 
Юра, а диапазоны целиком на временный лист - это же та же головомойка с последовательной выгрузкой...
 
Специально для этого делал фукцию соединения двумерных массивов:   
http://excelvba.ru/code/CombineArrays
 
Спасибо, Игорь, это такой же вариант:  
{quote}{login=vikttur}{date=02.07.2012 01:15}{post}...создать два массива и записывать данные то в один, то в другой (данные предыдущего массива плюс данные просматриваемого листа){/post}{/quote}
 
ничего не понял. Где файл с примером? )
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Зачем?  
Часть показанного кода - для визуализации описанного алгоритма.  
Делать не нужно, прошу общее направление мысли:  
можно ли применить другой алгоритм? Более эффективный, более быстрый?  
Hugo отметил, что, может, зря "улучшать нормальное"? Разница во времени совсем небольшая...
 
Специально для Саши файл (всю ночь делал)  :-)  
На первом листе желаемый результат.
 
Можно вероятно так (не делал) - перебором листов создаём словарь листов, каждому в item массив с его диапазона, попутно считаем сколько нужно будет строк для сводного массива.  
Создаём пустой сводный массив максимально нужного размера.  
Затем перебираем уже эти массивы из словаря, отбирая нужное в сводный.  
Расход памяти конечно будет больше, чем если перебирать и выгружать данные по одному листу - ведь тут нужно держать в памяти весь файл, затем повторно все данные (в словаре), плюс ещё массив этого же размера, куда отбираем, и периодически дополнительно массив с данными текущего анализируемого листа (правда по ходу дела обработанное можно удалять - но не знаю, насколько эффективно будет освобождаться память...)  
Если памяти много, то должно сработать. Но кажется, что ускорение если и будет, то небольшое.  
К томуже тут используется страшное слово :)
 
Игорь, то чё? Просил же человек:  
{quote}{login=vikttur}{date=02.07.2012 01:15}{thema=Упростить сбор данных с нескольких листов}{post} Словари и прочие страшные слова пока не предлагать. Не дорос, а хочется понятного :){/post}{/quote}  
:-)
 
Вот-вот. В одной теме успокаивают ребенка, в другой пугают... Злые...
 
ReDim Preserve avArr(lCnt)  
avArr(lCnt) = ArrTmp  
 
Не понял, как работает.  
Изменяем размерность avArr() с сохранением данных? Как же потом в одномерный помещается двумерный?...  
С этим связан цикл выгрузки...  
Можно комментарии?
 
[Юрий М]>Специально для Саши файл (всю ночь делал) :-)
Раз уж Вы старались, я тоже постарался (за завтраком) )  
 
 
Рекомендую посмотреть ВСЕМ. Об установке размера массива можно забыть.
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
>[Юрий М]>Специально для Саши файл (всю ночь делал) :-)
По рабоче-крестьянски:
 
Ой, буква "A" не нужна - осталась после тестирования.
 
Спасибо всем. буду читать.    
Коллекции меня все меньше пугают :)  
 
На будущее: пример-таки нужно прикладывать. Даже если не нужно (казалось бы).
Страницы: 1
Читают тему
Наверх
Loading...