Excel List-Object VBA Ошибка производительности? - PullRequest
4 голосов
/ 15 января 2012

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

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

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

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

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

    • Ручной = 7,64 с
    • Автоматически = 9,39 с

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

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

    • Ручной = 0,14 с
    • Автоматически = 3,23 с

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

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

    • Активная ячейка - это объект списка, а калькуляция - вручную = 0,17 с
    • Активная ячейка - объект списка, а Calc - автоматический = 0,20 с
    • Активная ячейка пуста, а Calc - вручную = 0,14 с
    • Активная ячейка пуста, а калькулятор автоматический = 0,18 с

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

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

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

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

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

Ответы [ 2 ]

2 голосов
/ 04 февраля 2012

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

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

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

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

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

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

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

0 голосов
/ 07 октября 2014

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

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

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

Мой оригинальный код 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 намного лучше, чем условное форматирование ваших собственных массивов ячеек.

...