2015-09-22 6 views
1

Как правило, функция Evaluate Excel VBA - это удобный способ получить результат формулы рабочей таблицы в VBA без необходимости вводить формулу в ячейку рабочего листа. Тем не менее, я нахожу, что если формула, подлежащая оценке, является функцией MATCH, работающей через несколько столбцов, она удивительно медленная - МНОГО медленнее, чем вычисление той же формулы в ячейке рабочего листа. Например:Вычислить функцию медленно с помощью функции листа со списком ссылок, ссылающихся на несколько столбцов

MatchingRow = EVALUATE(MATCH(Sheet1!G6&Sheet1!H6&Sheet1!I6,Sheet2!B:B&Sheet2!C:C&Sheet2!D:D,0)) 

Любая идея, почему это было бы намного медленнее, чем это, в ячейке рабочего листа?

=MATCH(Sheet1!G6&Sheet1!H6&Sheet1!I6,Sheet2!B:B&Sheet2!C:C&Sheet2!D:D,0) 

Я уверен, что я могу услышать кого-то уже набирает ответ говорят, что это все из-за накладные расходы вызова функции рабочего листа из среды VBA. Но если это так, мой следующий вопрос: Почему не ОЦЕНКА медленная для других функций тоже?

+1

Если бы я должен был догадаться, это потому, что EVALUATE обрабатывает вашу формулу так, как будто это формула массива. Целые столбцы (например, Sheet2! B: B & Sheet2! C: C & 'Sheet2! D: D) замедляют его. В качестве теста попробуйте установить, чтобы ссылки на все столбцы были ближе к фактическим диапазонам, которые необходимо оценить, и посмотрите, улучшаете ли вы производительность. – sous2817

+1

Взгляните на [это] (https://fastexcel.wordpress.com/2011/11/02/evaluate-functions-and-formulas-fun-how-to-make-excels-evaluate-method-twice-as -fast /) Чарльз Уильямс. Среди других интересных наблюдений он поддерживает, что «Application.Evaluate» вызывается дважды (это ошибка) по сравнению с «Worksheetfunction.Evaluate». – Ioannis

+0

sous2817: спасибо, что улучшена производительность примерно в 10 000 раз. –

ответ

2

Несколько вещей.

Сфера применения важна при использовании метода Evaluate(). Вызов метода на листе примерно в два раза быстрее, чем просто использование Evaluate(), что является сокращением для Application.Evaluate().

Конкатенация известна медленно, и эта неэффективность умножается при вызове барьера между VBA и Excel.

Этой переделка формулы с использованием булевой логики в качестве альтернативного механизма, чтобы прибыть в том же результате формулы, выполняет быстрее и гораздо ближе во время к листу-размещены формулам:

MatchingRow = = Sheet1.[MATCH(1,(Sheet1!G6=Sheet2!B:B)*(Sheet1!H6=Sheet2!C:C)*(Sheet1!I6=Sheet2!D:D),0)] 

UPDATE

Для полноты вы также должны решительно рассмотреть возможность ограничения глубины ваших диапазонов поиска. Это значительно ускорит оценку формулы на листе или VBA. Вот та же самая формула, что и выше, но с диапазонами поиска, ограничивающимися только 100 строками. При необходимости отрегулируйте:

Sheet1.[MATCH(1,(Sheet1!G6=Sheet2!B1:B100)*(Sheet1!H6=Sheet2!C1:C100)*(Sheet1!I6=Sheet2!D1:D100),0)] 
+0

Спасибо, используя метод Evaluate для листа, был почти в два раза быстрее, чем метод Evaluate приложения, и умножая отдельные логические результаты каждого столбца на более высокую производительность в 3 раза. Также это интересный способ использования MATCH. Я должен сказать, однако, что предложение sous2817 ограничить диапазоны действительными диапазонами, которые необходимы вместо ссылок на целые столбцы, улучшило производительность примерно в 10 000. Поэтому я должен был бы рассмотреть этот ответ или, по крайней мере, необходимую часть ответа. –

+0

Ну, компонент ограничения всегда применяется во всех ситуациях формулы (за исключением очень немногих высоко оптимизированных функций, таких как SUMIFS). Мой ответ был посвящен вашей конкретной ситуации. –

+0

Я обновил ответ. –