Разделение таблицы в разные книги - можно ли оптимизировать?
25.01.2021 23:17:58
|
|
|
|
25.01.2021 23:40:15
охохо.. попробую написать заново :-) Делал в рамках одной рабочей задачи такую штуку:
Дано: длинная таблица (100-200 тысяч строк) с некоторым количеством колонок и хедером. Чтобы было проще представить - пусть это будет отчет о продажах, где в колонке А расположены уникальные названия магазинов (штук 120), а во всех остальных колонках параметры относящиеся к продаже - номер заказа, дата и так далее. Задача: разделить эту большую и длинную таблицу на отдельные Excel файлы для каждого магазина. Включая перенос хедера и небольшие косметические операции с каждым файлом - ну типа вставить 4 пустые строки и значение в ячейку дополнительно. Как сделано:
Работает вполне ок, все разделяет, все копирует, нема проблема. Вопрос: можно ли этот процесс ускорить? Сейчас обработка 1-го файла занимает 1-2 секунд, что в принципе не составляет никаких проблем, интерес чисто академический. Вдруг кто-то сталкивался. Пример в приложенном файле - там три макроса, один из них чистит документ, второй наполняет его рендомными данными (в колонке А будет 120 уникальных значений), третий собственно делит таблицу на отдельные файлы.
Изменено: |
|||
|
|
26.01.2021 02:34:09
у меня вопрос - на листе много формул? Если да, то вот эта строка в начале макроса (в блоке 'Speed up macro execution)
Application.Calculation = xlAutomatic должна выглядеть вот так Application.Calculation =xlCalculationManual Объясню. Допустим у вас на листе куча формул. Вы в начале макроса ставите режим Автоматический пересчёт формул (xlAutomatic) - в этот момент включается пересчёт всех формул в книге (1 раз!). А так же когда вы ставите фильтр и когда вы снимаете фильтр (а это 120 раз поставили и 120 раз сняли, то есть 240 РАЗ!) - все формулы на всех листах пересчитываются - будет задержка времени. Всегда при работе с большим объёмом данных в начале макроса отключают Автоматический пересчёт на ручной, а в конце макроса ставят Автоматический - на этой строке сразу происходит пересчёт всех формул в книге. P.S. Если формул на листе нет, то можно всё это организовать на массивах - все данные с листа берёте в двумерный массив, а дальше бегаете циклами по нему (как у вас реализовано вот это For Itm = 1 To UBound(MyArr), и сравниваете если значение в столбце 1 общего массива равно MyArr(i), тогда перекладываете все 7 столбцов в новый массив, который будете выгружать на лист в новый файл. P.P.S. Вот в этой строке вы всегда копируете 200.000 строк ws.Range("A1:H" & LR).Copy, но т.к. массив отфильтрован, то строк тут будет всегда меньше, возможно надо в цикле For Itm = 1 To UBound(MyArr) находить последнюю строку (как у вас LR = ws.Cells(ws.Rows.Count, vCol).End(xlUp).Row) и использовать новую переменную с последней заполненной строкой для копирования данных PPP.S Вот эти строки Rows(1).Insert Shift:=xlShiftDown Rows(1).Insert Shift:=xlShiftDown Rows(1).Insert Shift:=xlShiftDown Rows(1).Insert Shift:=xlShiftDown думаю можно заменить одной строкой Rows("1:4").Insert Shift:=xlShiftDown - если у вас включен Автоматический пересчёт формул и формул много - после каждого добавления строки будет идти пересчёт всех формул, т.е. к вышеуказанным 1+240 разам добавятся ещё +4 раза пересчёт формул PPPP.S. - эту строку Cells.Columns.AutoFit - лучше написать Columns("A:G").AutoFit, чтобы не было обращения ко всем столбцам на листе - снятие автофильтра ws.Range(vTitles).AutoFilter Field:=vCol можно (и так более правильнее) написать так ws.ShowAllData PPPPP.S. - вот эту строку в конце макроса (в блоке 'Cleanup) Application.ScreenUpdating = True - лучше писать самой последней (по крайней мере обязательно ПОСЛЕ включения пересчёта Автоматического пересчёта формул)
Изменено: |
|
|
|
26.01.2021 02:42:47
Ух, какое лютое шаманство. действительно 41 секунда приблизительно. Учиться, учиться и учиться, как завещали..
Буду изучать. Огромное спасибо за науку. |
|
|
|
26.01.2021 02:44:48
я там ещё добавил внизу PPPP.S.в моём сообщение выше и добавьте строку ActiveSheet.DisplayPageBreaks = False в блок 'Speed up macro execution. Включать её в True в конце макроса не стоит
Изменено: |
|
|
|
26.01.2021 15:26:20
Всем большое спасибо за советы, это было действительно интересно, подчерпнул для себя новое - так что профит есть 100%
Изначально не планировал ничего менять, просто интерес был, но посмотрев примеры, понял насколько у меня убогий код и переписал его согласно вашим рекоммендациям на продакшен документе. Пользователю наверное без разницы, 30 секунд или минута, они вообще это руками делали днями Но мне лично - приятно. PS. артефакты в коде которые под вопросом остались, типа MyCount - это я просто основной функционал выдрал, где-то мог забыть что-то. В оригинале документ посимпатичнее, с кнопками всякими, обеспечивает импорт данных выгружаемых из сервиса, его приведение в надлежащий вид, разделение на файлы, отправку по почте каждого файла и так далее - короче автоматизирует в 4 нажатия все то, что пользователь делал вручную. |
||||
|
|
|||