Страницы: 1 2 След.
RSS
Ускорение работы макросов
 
Всем добрый вечер.
Вот решила поинтересоваться,как профи справляются с проблемой очень медленной работы макросов?
у меня файл загружен макросами и формулами(это по своей сути автоматизированный калькулятор).Есть макрос очистки полей,который закреплён за кнопкой очистки,есть макрос печати с заданными параметрами,есть макрос,который учитывает условия и в зависимости от этих условий открывает и сковывает строки и столбцы..весит около 320 метров ..при нажатии на кнопку очистки макрос очень медленно очищает каждую ячейку,каждую..а их добрых 50 заполненных штук..


что может помочь?
 
Цитата
весит около 320 метров
Нужно уходить от таких размеров. Excel не любит большого веса, от ожирения у него начинаются всяческие приступы :)

Цитата
очищает каждую ячейку
Запомнить адреса и почистить одним движением.

Общие рекомендации: отключать автопересчет листа, обновление экрана, события листа...  Обращение к ячейкам, листу - медленный процесс. Минимизировать, обрабатывать данные в массивах (в памяти).
 
Вначале работы макросов код:
Код
  'Больше не обновляем страницы после каждого действия
  Application.ScreenUpdating = False
 
  'Расчёты переводим в ручной режим
  Application.Calculation = xlCalculationManual
 
  'Отключаем события
  Application.EnableEvents = False
 
  'Не отображаем границы ячеек
  If Workbooks.Count Then
      ActiveWorkbook.ActiveSheet.DisplayPageBreaks = False
  End If
 
  'Отключаем статусную строку
  Application.DisplayStatusBar = False
 
  'Отключаем сообщения Excel
  Application.DisplayAlerts = False
 
В конце работы макросов код:
Код
'Включаем обновление экрана после каждого события  
  Application.ScreenUpdating = True
 
  'Расчёты формул - снова в автоматическом режиме
  Application.Calculation = xlCalculationAutomatic
 
  'Включаем события
  Application.EnableEvents = True
 
  'Показываем границы ячеек
  If Workbooks.Count Then
      ActiveWorkbook.ActiveSheet.DisplayPageBreaks = True
  End If
 
  'Возвращаем статусную строку
  Application.DisplayStatusBar = True
 
  'Разрешаем сообщения Excel
  Application.DisplayAlerts = True
Изменено: Roman Shaleyko - 19.01.2016 23:17:28
 
Плюс избавляемся от использования метода .Select и, по мере возможности, от прямых манипуляций с диапазонами (вместо этого работаем с данными в памяти через массивы или словарь) :)  При отключении перерисовки экрана и пересчета формул (см #4), очистка 50.000 ячеек даже по одной должна быть практически молниеносной :)
Изменено: KL - 19.01.2016 23:27:03
KL
 
о, друзья... Я сейчас перепишу код и попробую, сообщу,как прошло!!!спасибо большое!
 
урааааа!все так быстро работает!!
всем спасибо!и добрых снов!
 
Цитата
Roman Shaleyko написал:
'Не отображаем границы ячеек  
If Workbooks.Count Then
     ActiveWorkbook.ActiveSheet.DisplayPageBreaks = False
Поправка: данный код отключает показ разбиения листа на печатные страницы. Но не границы ячеек.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Мои 5 оптимизационных копеек

Оптимизация
1) Избегать формул массивов (по возможности)
2) Избегать волатильных формул (по возможности) (условное форматирование, как пример волатильности)
3) Использовать структурированные таблицы и именнованные диапазоны
4) заменять неиспользуемые формулы значениеями
5) Хранить все данные для расчета на одном листе (по возможности)
6) Избегать в формулах ссылки на целые столбцы
7) использовать =IFERROR вместо IF + ISERR/ISERROR
8) использовать MAX(A1;0) вместо IF(A1>0;A1;0)
9) использовать INDEX+MATCH вместо VLOOKUP
10) использовать -- для конвертации лог.значение в 0/1
11) использовать A1*0.1 чем A1/10
VBA
12) Используй оператор if else, вместо IIF
13) Используй Long т.е. Long лучше Вуte, Integer, конечно, variant
14) Применяй if else, чем switsh; shoose
15) Лучше проверяй строку так len(s)=0, чем s = “”
16) Лучше инициализируй строку так s =vbnullstring, чем s =""
17) Если возможно пиши так s = "АВ", чем s ="А" & "В"
18) Вставляй строку в текст так Мid$(а,3,4)="like". чем s = left$(8,2) & "like" & mid(з,7)
19) Сравнивай строки так if strcomp(s1,s2,vbtextcompare) =0, чем if ucase(s1)=ucase(s2)
20) Лучше используй $-функцию, т.е. left$ лучше left.
21) Цикл for …next. работает быстрее do...lоор
22) Точнее объявляй объекты: as commandbutton лучше as control, еще лучше as object
23) Цикл for Еасh..next лучше, чем цикл for…next семейств объектов
24) Цикл for ...next лучше, чем цикл fог Еасh...next: для массивов.
25) Использовать оператор With при обращении к элементам сходной иерархической модели
Для общих (расшаренных) книг
26) Удалить пользовательские представления Вид-Представления-Удалить
27) Снять пометки с Параметров печати и Фильтров , так Рецензировани-Доступ к книге-Параметры печати и Фильтры
28) Периодически отключать общий доступ, сохранять книгу, сключать общий доступ и снова сохранять
29) Удостовериться, что книга открывается в режиме просмотра Вид-Обычный (для того, чтобы избежать обращения к сетевому принтеру с соответствующими временными последствиями)
Для уменьшения размера книги MSE (актуально для книг в которых часто пишется и удаляется инфа)
30) Перелить одну книгу в другую путем копирования не листа, а содержимого в новую внигу со вставкой сначала значения, потом формулы, потом форматы и макросы через испорт экспорт перенести в новую книгу
31 ) удалить избыточное форматирование
 
Цитата
e_artem написал:
использовать INDEX+MATCH вместо VLOOKUP
можно поподробнее? Чем же ВПР отличается от ПОИСКПОЗ так, что ПОИСКПОЗ по-Вашему работает оптимальнее? Насколько знаю, принцип работы у них одинаковый. Вопрос может быть только в размере ссылок на массив данных. Но этот вопрос одинаково справедлив для обеих функций.
Цитата
e_artem написал:
использовать -- для конвертации лог.значение в 0/1
тоже не всегда справедливо. Все зависит от конкретной формулы и ситуации, это обсуждалось. Нельзя с уверенностью сказать для всех формул, что бинарное отрицание будет быстрее мат.операций с данными.
Цитата
e_artem написал:
as commandbutton лучше as control, еще лучше as object
8-0  Когда это глобальный тип object стал работать быстрее, чем прямой указатель на тип? Ведь в этом случае VBA должен будет на ходу определять тип, исходя из строки присвоения, что приводит к дополнительной трате времени. Скорее тут просто неверно написано и должно быть так: объявлять as commandbutton лучше чем as control и тем более лучше, чем as object.
Цитата
e_artem написал:
Используй Long т.е. Long лучше Вуte
Спорный момент. Long лучше, чем Integer для 32-битных систем. Но тут надо учитывать еще и кол-во памяти на ПК. Т.к. доступ к Long происходит хоть и быстрее - памяти на этот тип выделяется больше. Поэтому если есть подозрения на слабую машину - надо все же исходить не только из понятий более быстрой инициализации.
P.S. Хотя сам в большинстве случаев Long использую :)

От себя добавлю, что еще можно ускорить код, объявляя массивы явно:
Dim arr()
вместо
Dim arr
Еще лучше будет
Dim arr() as string, arr2() as long
но это только если есть уверенность в том, что в массив будут заноситься строго указанные типы данных.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
as commandbutton лучше as control, еще лучше as object
имелось в виду лучше использовать commandbutton, чем более глобальные объекты...коряво написал...
 
Это ссылки касаемо
Цитата
можно поподробнее? Чем же ВПР отличается от ПОИСКПОЗ так, что ПОИСКПОЗ по-Вашему работает оптимальнее?
http://trumpexcel.com/2014/11/vlookup-vs-index-match-debate-ends/
http://exceluser.com/blog/727/excels-fastest-lookup-methods-the-tested-results.html


Нынче время дороже стоимости оперативной памяти...
Цитата
Спорный момент. Long лучше, чем Integer для 32-битных систем. Но тут надо учитывать еще и кол-во памяти на ПК. Т.к. доступ к Long происходит хоть и быстрее - памяти на этот тип выделяется больше
Это мои заметки, и я не применяю их влоб как написано, все зависит от ситуации. аналогичное можно применять ко многим пунктам оптимизации
Цитата
тоже не всегда справедливо. Все зависит от конкретной формулы и ситуации, это обсуждалось.
 
e_artem, если позволите, в вашем разделе Оптимизация есть весьма сомнительные/спорные обобщения :)

1) избегать формул массива потому, что некоторые могут подвесить расчеты от непонимания того, как они действуют, - все равно, что избегать VBA потому, что можно по незнанию попасть в бесконечный цикл. Вопреки поверьям, формулы массива не медленнее, чем отдельные формулы их составляющие если сумма операций одна и та же. Формулы массива менее эффективны лишь тогда, когда алгоритм не оптимален: а. повторные расчеты, которых можно избежать, вынеся на лист как отдельные формулы, б. как частный случай, бинарные условные расчеты типа СУММПРОИЗВ(...), где нет возможности прекратить расчеты после нахождения искомого или где не был ограничен использованный диапазон. Точно также не все формулы массива длинные и непонятные :)

2) волатильность - не абсолютное зло, ее следует избегать в специфическом случае, когда сумма времен пересчета всех зависимых от нее формул достигает уровня создающего неудобства в работе с файлом, например 1 секунда и более (но последнее субъективно). Отказ от волатильных функций в других случаях может означать ненужные ограничения. Для примера, волатильны все функции времени и случайных чисел, а также СМЕЩ, ДВССЫЛ, ЯЧЕЙКА, ИНФОРМ и некоторые частные случаи неволатильных функций.

3) совсем непонятно избегание имен :) единственный недостаток я могу себе представить - это пересчет каждого упоминания имени в случае если зависимая формула пересчитывается, но это может быть проблемой лишь в случае "тяжелых" расчетов (например точного поиска или поиска по условиям) хранимых в имени. В этом смысле это то же, что и мой подпункт а. в пункте 1) этого списка.

6) злоупотреблять конечно не стоит, но на всякий случай, использование целых столбцов в функциях точного поиска и функции ИНДЕКС абсолютно не влияет на эффективность формулы. В случае функций неточного поиска, влияние нематериально даже при множестве повторов ввиду бинарного алгоритма. Реально известная проблема с этим - опять таки бинарные условные формулы типа СУММПРОИЗВ(...)
Изменено: KL - 20.01.2016 14:20:39
KL
 
Цитата
e_artem, если позволите, в вашем разделе Оптимизация есть весьма сомнительные/спорные обобщения  
Я ничуть не против, пожалуйста сомневайтесь, опровергайте, предлагайте свои варианты, вообще думаю, что в направлении оптимизации любой момент может быть спортным, все зависит от ситуации
 
По формулам массива еще момент: например, ТРАНСП, которая вводится разом во все ячейки будет пересчитываться быстрее, чем то же транспонирование через ИНДЕКС, т.к. рассчитывается один раз, а ИНДЕКС столько раз, сколько ячеек задействовано.
И во многих случаях формулы массива, введенные разом в диапазон ячеек быстрее будут работать, чем ввод формулы массива в одну ячейку и "тиражирование" её на множество ячеек.
Но опять же: все всегда зависит от конкретной ситуации и порой там, где одно быстрее - другое будет медленнее.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
В конечном счете получается, что вышеописанное это не инструкции к действию на случай проблем производительности, а моменты на которые стоит обратить внимание (прощупать) в конкретном файле и посмотреть быстрее или медленее или вообще всю структуру файла переделать прийдется...
 
Цитата
e_artem написал:
http://trumpexcel.com/2014/11/vlookup-vs-index-match-debate-ends/
http://exceluser.com/blog/727/excels-fastest-lookup-methods-the-tested-results.html
Разница в скорости между ИНДЕКС/ПОИСКПОЗ и ВПР нематериальна даже на очень больших диапазонах. Тем не менее гибкость - главное и важное преимущество ИНДЕКС/ПОИСКПОЗ.

Серьезная оптимизация скорости возникает при замене точного поиска на неточный по совету Чарльза Уильямса (если данные можно отсортировать) или при выносе ПОИСКПОЗ в доп. столбец (если нужно получить результат из множества столбцов базы). Но даже в последнем случае у ВПР есть ответ - использование массива в 3-ем параметре.
Изменено: KL - 20.01.2016 15:01:18
KL
 
Цитата
e_artem написал:
Нынче время дороже стоимости оперативной памяти
позвольте засомневаться...Ведь опять все зависит от ситуации и каждый совет не может быть истиной в последней инстанции, здесь мы солидарны, я полагаю :) На 32-битных системах нельзя использовать более 4Гб. Докупай, не докупай...А Excel-ю отводится и того в два раза меньше. И если файл большой - то он может приличный объем доступной памяти скушать, что оставит для VBA значительно меньший кусок от пирога памяти. А еще же и другие приложения в ОС могут быть открыты.  
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Серьезная оптимизация скорости возникает при замене точного поиска на неточный по совету Чарльза Уильямса (если данные можно отсортировать)
Интересная информация. Т.е. отсортировав список и применив ПОИСКПОЗ с неточным поиском, получим ускорение вычислений?
 
гигантское :)

http://www.decisionmodels.com/optspeede.htm
Изменено: KL - 20.01.2016 15:11:06
KL
 
Вить, так это же логично. ПОИСКПОЗ просматривает отсортированный массив и в зависимости от типа соответствия может реально и точно сравнить данные раньше и позже с текущим и понять - имеет ли смысл идти дальше или уже достигнут предел максимально точного соответствия.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
The_Prist, солидарны ... Ладно, со списком куда смотреть/что щупать/где крутить примерно определились...Вопрос теперь, в какой последовательности подкручивать.
Вот например ситуация. Приходит пользователь к MSE гуру с вопросом: у меня тормозит MSE файл, помоги плз и гуру по доброте душевной/трудовому договору/... начинает ковырять файл, но времени/желания/... у гуру и/или пользователя для глубокого анализа нет. В какой последовательности начинать заточку MSE файла, как определить наиболее узкие горлышки файла?
 
Цитата
...может реально и точно сравнить данные раньше и позже с текущим и понять...
В чем разница? И при точном, и при неточном соответствии нашли значение (в сортированном массиве) - остановились. Тут, наверное, разница в логике поиска?
 
Цитата
e_artem написал:
В какой последовательности начинать заточку MSE файла, как определить наиболее узкие горлышки файла?
Незаменимая вещь: http://www.decisionmodels.com/FastExcelV3Profiler.htm
KL
 
Цитата
vikttur написал: Тут, наверное, разница в логике поиска?
Да, неточный - бинарный, точный - поячеечно. Бинарный значит максимум 19 проверок в миллионе строк.
KL
 
Thanks
 
И от меня спасибо.
Писал же не раз о бинарном, а я ушами прохлопал.
 
Очень полезная статья!!!! Спасибо!
 
Немного дополнил макрос Roman Shaleyko, из ответа № 3, добавив функционал из темы Макрос отключения/изменения характеристик вкладки Вид (Обычный режим просмотра книги, Сетка, Строка формул, Заголовки) (спасибо форумчанам МатросНаЗебре, Конь)
Итак, сами макросы
Код
Sub БыстродействиеВКЛ()
'Больше не обновляем страницы после каждого действия
  Application.ScreenUpdating = False
    'Расчёты переводим в ручной режим
  Application.Calculation = xlCalculationManual
    'Отключение отображения строки формул
    Application.DisplayFormulaBar = False
     'Отключаем события
  Application.EnableEvents = False
    'Не отображаем границы ячеек
  If Workbooks.Count Then
      ActiveWorkbook.ActiveSheet.DisplayPageBreaks = False
  End If
    'Отключаем статусную строку
  Application.DisplayStatusBar = False
    'Отключаем сообщения Excel
  Application.DisplayAlerts = False
 'Отключение отображения сетки
       Dim iList As Worksheet
    For Each iList In Worksheets
    If iList.Visible = True Then
    iList.Select Replace:=False
    End If
    Next
    ActiveWindow.DisplayGridlines = False
    'Отключение отображения заголовков
    ActiveWindow.DisplayHeadings = False
  'Отображение обычного режима просмотра книги
  ActiveWindow.View = xlNormalView
End Sub

Код
Sub БыстродействиеВЫКЛ()
'Включаем обновление экрана после каждого события
  Application.ScreenUpdating = True
    'Расчёты формул - снова в автоматическом режиме
  Application.Calculation = xlCalculationAutomatic
   'Влючение отображения строки формул
    Application.DisplayFormulaBar = True
     'Включаем события
  Application.EnableEvents = True
    'Показываем границы ячеек
  If Workbooks.Count Then
      ActiveWorkbook.ActiveSheet.DisplayPageBreaks = True
  End If
    'Возвращаем статусную строку
  Application.DisplayStatusBar = True
    'Разрешаем сообщения Excel
  Application.DisplayAlerts = True
  'Включение отображения сетки
       Dim iList As Worksheet
    For Each iList In Worksheets
    If iList.Visible = True Then
    iList.Select Replace:=False
    End If
    Next
    ActiveWindow.DisplayGridlines = True
    'Включение отображения заголовков
    ActiveWindow.DisplayHeadings = True
    'Отображение страничного режима просмотра книги
    ActiveWindow.View = xlPageBreakPreview
End Sub

Может быть кому-то пригодится.
П.С. данный сборник не является какой-либо панацеей и не является готовым решением всех проблем. В данном сборнике, собраны всякие разные настройки в один код - включает и выключает. Особо подчеркну: не все на быстродействие влияют, но вдруг кому надо будет - все в одном месте. Используя данный сборник, пользователь принимает на себя все риски связанные с его использованием и результат работы сборника не всегда может соответствовать ожиданиям пользователя к процессу/результату его работы.
Изменено: Maximich - 06.04.2022 11:16:48
Кто ясно мыслит, тот ясно излагает.
 
Maximich, тут очень много, чего можно оспорить, но главное - понять, что нет и не бывает никакого волшебного макроса быстродействия. Скорость и оптимальность кода - в голове у разработчика, понимающего, что он делает.
30% "фишек" вообще по моему опыту никакого влияния на скорость выполнения не оказывают, ещё 30% нужны очень редко, оставшиеся 40% нужно запоминать и восстанавливать, а не включать, а ActiveWindow.View = xlPageBreakPreview вообще нахрена включать, если вы не мазохист
Ерунда с претензией на полезную сборку всегда гораздо хуже обычной ерунды…
А вот пример процедуры с запоминанием и восстановлением параметров (не панацея)
Изменено: Jack Famous - 06.04.2022 10:03:02
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Jack Famous написал:
Maximich , тут очень много, чего можно оспорить, но главное - понять, что нет и не бывает никакого волшебного макроса быстродействия. Скорость и оптимальность кода - в голове у разработчика, понимающего, что он делает.
- об этом я догадываюсь.
Цитата
Jack Famous написал:
30% "фишек" вообще по моему опыту никакого влияния на скорость выполнения не оказывают, ещё 30% нужны очень редко, оставшиеся 40% нужно запоминать и восстанавливать, а не включать, а ActiveWindow.View = xlPageBreakPreview вообще нахрена включать, если вы не мазохист
Вам виднее, я в данной области не специалист.
Цитата
Jack Famous написал:
Ерунда с претензией на полезную сборку всегда гораздо хуже обычной ерунды…
- поэтому я и написал
Цитата
Maximich написал:
Может быть кому-то пригодится.
Кто ясно мыслит, тот ясно излагает.
Страницы: 1 2 След.
Читают тему
Наверх