Остановитесь VBA Оценивают от вызывания целевой функции дважды

Я испытываю затруднения при получении VBA's, Оценивают () функцию, чтобы только выполниться однажды; это, кажется, всегда работает дважды. Например, рассмотрите тривиальный пример ниже. Если мы выполним RunEval () подпрограмма, то он назовет EvalTest () функцией дважды. Это видно двум различным случайным числам, которые печатаются в непосредственном окне. Поведение было бы тем же, если бы мы звонили, другая подпрограмма с Оценивают вместо функции. Кто-то может объяснить, как я могу добраться, Оценивают для выполнения целевой функции однажды вместо дважды?Спасибо.

Sub RunEval()
    Evaluate "EvalTest()"
End Sub

Public Function EvalTest()
    Debug.Print Rnd()
End Function
8
задан Abiel 10 April 2010 в 01:55
поделиться

3 ответа

Кажется, эта ошибка возникает только с UDF, а не со встроенными функциями. {{1 }} Вы можете обойти это, добавив выражение:

Sub RunEval()
    ActiveSheet.Evaluate "0+EvalTest()"
End Sub

Но есть также ряд других ограничений с Evaluate, задокументированных здесь http://www.decisionmodels.com /calcsecretsh.htm

8
ответ дан 5 December 2019 в 17:35
поделиться

Я провел быстрый поиск и обнаружил, что другие сообщали о подобном поведении и других странных ошибках с Application.Evaluate (см. KB823604 и this ). Это, вероятно, не входит в список исправлений Microsoft, так как это было замечено, по крайней мере, с Excel 2002. Эта статья базы знаний предлагает обходной путь, который может работать и в вашем случае - поместите выражение для оценки в рабочий лист, а затем получите значение из это примерно так:

Sub RunEval()
    Dim d As Double

    Range("A1").Formula = "=EvalTest()"
    d = Range("A1").Value
    Range("A1").Clear
    Debug.Print d
End Sub

Public Function EvalTest() As Double
    Dim d As Double
    d = Rnd()
    Debug.Print d
    EvalTest = d + 1
End Function

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

1
ответ дан 5 December 2019 в 17:35
поделиться

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

(ПРАВКА: У Чарльза Уильямса на самом деле есть ответ на ваш конкретный вопрос. Мой ответ все еще может быть полезен, когда вы не знаете, какой тип данных вы можете вернуть, или когда вы ожидаете получить что-то вроде массива или диапазона.)

Если вы используете свойство Application.Caller в процедуре, вызываемой в результате вызова Application.Evaluate, вы увидите, что один из вызовов, по-видимому, исходит из верхней левой ячейки фактического диапазона, из которого выполнен вызов Evaluate, а другой из ячейки $A$1 листа, на который включен этот диапазон.Если вы вызовете Application.Evaluate из окна интерпретации, как и в примере Sub, один вызов будет отображаться из верхней левой ячейки выбранного диапазона, а один из ячейки $A$1 текущего листа. Я почти уверен, что это первый звонок, который в обоих случаях составляет $A 1 доллар. (Я бы проверил это, если это имеет значение.)

Однако из Application.Evaluate будет возвращено только одно значение. Я почти уверен, что это тот, что из второго эваля. (Я бы тоже проверил это.)

Очевидно, что это не будет работать с вызовами, сделанными с фактического сотового $A 1 доллар.

(Что касается меня, я хотел бы знать , почему происходит двойная оценка. Я также хотел бы знать, почему оценщик вообще подвергается воздействию. Кто-нибудь?)

EDIT: Я спросил на StackOverflow здесь: Почему метод Excel 'Evaluate' является общим оценщиком выражений?

Я надеюсь, что это поможет, хотя это не отвечает прямо на ваш вопрос.

1
ответ дан 5 December 2019 в 17:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: