Ошибка производительности Excel List-Object VBA?

У меня проблема с производительностью в приложении Excel, которое использует объекты списка (также известные как таблицы Excel). Я подозреваю, что это может быть ошибка, но, несмотря на мой поиск в Google, я не смог найти никаких упоминаний об этом. Я уже разработал обходной путь для своего приложения, но меня интересует, может ли кто-нибудь объяснить, почему это происходит.

Примечание. Я использую Excel 2007 в Windows Vista. Настройка выглядит следующим образом: у меня есть электронная таблица, содержащая данные в объекте списка, с кодом VBA, который можно запустить с помощью командной кнопки; этот код может вносить несколько изменений в любое количество ячеек на листе, поэтому перед любыми изменениями для режима расчета Excel устанавливается значение «Вручную».

Проблема, с которой я столкнулся, заключается в том, что если текущая активная ячейка находится внутри объекта списка, то установка режима расчета на ручной, похоже, не имеет никакого эффекта. Поэтому, если у пользователя в том же экземпляре открыта тяжелая рабочая книга для вычислений, тогда код VBA работает очень медленно. Мне практически пришлось разобрать свое приложение, чтобы обнаружить, что это было вызвано активной ячейкой; и я создал новую книгу с простой версией этого сценария, чтобы убедиться, что в моем приложении не было каких-либо повреждений.

Я провел несколько тестов с этим, и ниже приведены результаты того, что я нашел:

  1. Хотя это, как правило, связано с расчетом, все же существует разница во времени, когда режим расчета переключается между ручным и автоматическим...

    • Manual = 7.64 secs
    • Автоматически = 9,39 с

    Ручной режим чуть менее чем на 20% быстрее, чем автоматический. Но я ожидал, что они будут более или менее одинаковыми, учитывая, что проблема, похоже, заключается в том, что расчет начинается даже в ручном режиме.

  2. Сравните это с тем, когда активная ячейка не находится в объекте списка, и результаты сильно отличаются...

    • Manual = 0.14 secs
    • Автоматически = 3,23 с

    Теперь ручной запуск выполняется в 50 раз быстрее, а автоматический запуск показывает, что расчет не должен был занимать более 3,2 секунды! Итак, теперь первый тест выглядит так, как будто он мог выполнить расчет дважды в ручном режиме и почти 3 раза в автоматическом режиме.

  3. Повторяем этот тест еще раз, на этот раз в экземпляре без формулы расчета ни в одной ячейке, и внезапно он кажется не таким уж плохим,

    • Active cell is List Object & Calc is Manual = 0.17 secs
    • Активной ячейкой является объект списка, а расчет выполняется автоматически = 0,20 с.
    • Активная ячейка пуста, а расчет ведется вручную = 0,14 с.
    • Активная ячейка пуста, а расчет выполняется автоматически = 0,18 с.

    Он по-прежнему медленнее, но уже только на 10-20%, что делает его незаметным. Но это показывает, что проблема должна быть каким-то образом связана с расчетом, иначе он занял бы столько же времени, сколько и первый тест.

Если кто-то хочет создать эти тесты, чтобы убедиться в этом, настройка выглядит следующим образом:

  • Новая рабочая книга с добавленным объектом списка (не должна быть связана с какими-либо данными)
  • Добавьте формулу, вычисление которой займет некоторое время (я только что повторил «=1*1» 30 000 раз)
  • Напишите быстрый код VBA, который будет; (i) выполнить простое редактирование ячейки несколько сотен раз, (ii) и записать время, затраченное на это
  • Затем просто запустите код, изменив активную ячейку между объектом списка и пустой ячейкой.

Мне было бы очень интересно услышать, может ли кто-нибудь объяснить, почему Excel ведет себя таким образом, и если это ошибка или какая-то функция, связанная с объектами списка, которая действительно имеет какое-то реальное применение?

Спасибо, Стюарт.


person Skytunnel    schedule 14.01.2012    source источник
comment
Я не могу дублировать ваши результаты. Нестабильная формула не пересчитывается при редактировании данных в объекте-списке в режиме ручного расчета. Если Screenupdating включено, то повторное редактирование ячейки в listobject с активной ячейкой в ​​listobject происходит медленно, как и ожидалось, но при отключенном screenupdating я не вижу существенной разницы. Можете ли вы опубликовать ссылку на файл примера?   -  person Charles Williams    schedule 15.01.2012
comment
@CharlesWilliams Спасибо за ваш ответ. Возможно, я не полностью объяснил свою настройку, ссылка для скачивания здесь У меня было отключено обновление экрана во время всех моих тестов. Я не совсем понимаю, когда именно excel запустит расчет, но сегодня я добавил счетчик в событие worksheet_calculation, чтобы увидеть, как это будет выглядеть, и верно для формы, когда режим расчета ручной, счетчик был 0. Так что, может быть, я лаю не на то дерево?   -  person Skytunnel    schedule 15.01.2012
comment
Спасибо за ссылку. Чтобы получить замедление, вам, кажется, нужны 3 условия: 1. активная ячейка должна быть внутри объекта List (таблица). 2. Обновляемые ячейки должны находиться на том же рабочем листе, что и объект списка. 3. Затраченное время зависит от количества формул (но формулы не пересчитываются). На данный момент я не могу понять, почему это происходит.   -  person Charles Williams    schedule 16.01.2012


Ответы (2)


Это не относится к найденной вами "ошибке", что весьма интересно и интригующе.

Я просто хочу поделиться, что есть отличный способ избежать задержек вычислений. У меня были фантастические результаты с этим, и теперь я использую его все время.

Проще говоря, Excel занимает много времени, копируя данные туда и обратно между «миром VBA» и «миром электронных таблиц».

Если вы выполняете все «чтения» сразу, обрабатываете, а затем выполняете все «записи» одновременно, вы получаете потрясающую производительность. Это делается с использованием массивов вариантов, как описано здесь:

http://msdn.microsoft.com/en-us/library/ff726673.aspx#xlFasterVBA

в разделе с пометкой: Чтение и запись больших блоков данных за одну операцию

Я смог провести рефакторинг некоторого кода, который занимал у меня 5 минут, и сократить его до 1,5 минут. Рефакторинг занял у меня 10 минут, что удивительно, потому что это был довольно сложный код.

person pgr    schedule 04.02.2012

Что касается производительности таблицы (и производительности в целом):

Я знаю, что это старый вопрос, но я хочу, чтобы это было задокументировано.

Одна вещь, которая изменилась между более старыми версиями Excel и версиями после 2007 года, заключается в том, что Excel теперь активирует целевой лист любой операции PasteSpecial. Вы не можете переопределить его, отключив обновление экрана и выполнив расчеты вручную. Такая активация сделает лист видимым и вызовет неконтролируемое мерцание.

Мой первоначальный код VBA работал очень быстро на старой однопроцессорной машине XP с Excel 2000. Переход на Excel 2013 на современной машине был ошеломляющим из-за ужасной медлительности выполнения кода. Три области, которые убивают производительность, — это PasteSpecial с одного листа на другой, любой другой код, требующий активации листов (уровень масштабирования, расширенный фильтр, имена диапазонов на уровне листа и т. д.), и автоматическая защита/снятие защиты листа.

Это очень плохо, потому что PasteSpecial помогает «очистить» копируемые данные (прямое использование .Copy для цели иногда вызывает ошибку).

Поэтому вам нужно просмотреть свой код и убедиться, что вы используете прямое присвоение нужному свойству для нужного вам типа данных (например, из числа Value, Value2, Text и Formula) вместо PasteSpecial.

например .Range("MYRANGE").Value = .Cells(5, 7).Value2

Вы также должны скрупулезно воздерживаться от использования Select и Activate во всем коде.

Как упоминалось выше, многие комментарии, которые вы найдете на форумах Excel по этому последнему пункту, будут содержать заявления о том, что вам «никогда» не нужно использовать активацию, что явно не соответствует действительности, поскольку некоторые вещи в Excel применяются только к активным листам или требуют их. Понимание случаев, когда активация выполняется автоматически с помощью определенного метода или использования объекта, также поможет в написании кода. К сожалению, вы не увидите много документации по этому поводу.

Обновлять:

Что касается условного форматирования, вы найдете много жалоб на различные форумы о медлительности Excel при обнаружении большого количества ячеек с условным форматированием. Я подозревал, что это повлияет на таблицы Excel, поскольку у них есть много вариантов формата таблиц. Чтобы проверить это, я взял большую рабочую книгу, которую мы используем, которая в настоящее время отформатирована как несколько рабочих листов с одинаковым стилем таблицы Excel.

После преобразования таблиц в обычный диапазон я не заметил никакой разницы в скорости выполнения кода. Казалось бы, это указывает на то, что использование форматов таблиц Excel намного превосходит условное форматирование ваших собственных массивов ячеек.

person K Rhodes    schedule 07.10.2014