Excel вычисляет формулу с функцией VBA как ошибку, если она не введена повторно - PullRequest
15 голосов
/ 24 июня 2011

У меня есть простой оператор if, настроенный на листе, где условие if является определяемой пользователем функцией VBA:

Function CellIsFormula(ByRef rng)
    CellIsFormula = rng(1).HasFormula
End Function

Эта функция работает нормально:

Evaluate 1 Evaluate 2

Но по какой-то причине, которую я не могу понять, ячейка оценивается как ошибка. Хуже всего то, что при оценке формулы excel связывает ошибку с шагом вычисления, который не приводит к ошибке:

Evaluate 4 Evaluate 5 Evaluate 6

В довершение всего, и что меня действительно поражает, так это то, что если я просто повторно введу формулу или произвожу полный пересчет ( Ctrl + Alt + F9 ) - формулы оценивают без проблем!

Re-Enter Formula Calculation worked

Я пытался сделать формулу изменчивой, добавив Application.Volatile к коду функции, но это ничего не изменило. Другие способы обновления вычислений, такие как установка расчета вручную, а затем обратно в автоматический режим, скрытие «перерасчета листа» или просто использование F9 или Ctrl + F9 не работают, только повторный ввод формулы или Ctrl + Alt + F9 приведет к правильному пересчету функции.

Изменение одной из ячеек, на которые есть ссылка в операторе if, не решит проблему, , но , изменение ячейки, на которую ссылается функция CellIsFormula, решит проблему. Однако каждый раз, когда лист открывается снова, ошибка возвращается.

Ответы [ 3 ]

15 голосов
/ 24 июня 2011

Я обнаружил точную проблему, но я хочу, чтобы вы все проголосовали за то, что пытаетесь помочь мне разобраться в этом, и отдаете должное GSerg, потому что, хотя мне не повезло, он был мёртв с его предложением что

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

Хорошая находка GSerg.

Проблема была с Обработчиками событий . Рабочая книга содержит ряд обработчиков событий, таких как Workbook_Open, Worksheet_Change и т. Д. Время от времени одно из действий, выполняемых этими обработчиками событий, приводит к пересчету некоторых ячеек в рабочей книге. Если во время выполнения макроса Excel запускает пересчет, все ячейки, содержащие этот UDF, приведут к ошибке. Это связано с тем, что по какой-то причине во время инициированного VBA пересчета свойство .HasFormula было недоступно. , как сказал @GSerg: Property Unavailable

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

Именно поэтому при пошаговом выполнении «Формула оценки» все будет работать до самого последнего шага, где он фактически не оценивает последний шаг, он просто показывает значение из электронной таблицы, как было рассчитано последним.

Решение

На самом деле было два возможных решения. Первое решение, которое я нашел, состояло в том, чтобы отключить автоматический расчет в начале обработчиков событий, а затем снова включить его. По какой-то причине, даже если макрос выполняется в то время, когда для вычисления задано значение xlCalculationAutomatic, это приведет к успешной повторной оценке UDF и доступному свойству.

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

Function CellIsFormula(ByRef rng As Range) As Boolean
    CellIsFormula = Left(rng(1).Formula, 1) = "="
End Function

Свойство .Formula никогда не будет недоступно. Так что эта проблема никогда не возникает.

6 голосов
/ 24 июня 2011

Я не смог воспроизвести эту ошибку, но:

  1. Подпись должна быть:

    Public Function CellIsFormula2(ByVal rng As Range) As Boolean
      CellIsFormula2 = rng.Cells(1).HasFormula
    End Function
    
  2. Excel предпочитает, чтобы определенные свойства диапазона были недоступны на определенных этапах расчета. Я много раз видел, как свойство .Text внезапно стало недоступным. Так что если изменение подписи не работает, то вам, вероятно, не повезло.

1 голос
/ 24 июня 2011

Я думаю, что ваши проблемы связаны с тем, что свойство HasFormula возвращает вариант, а не логическое значение.Если диапазон имеет смешанные формулы и значения, HasFormula вернет ноль.Кроме того, вы не определяете rng как объект Range и не указываете тип вывода.Я предлагаю такой подход.Его можно изменить, чтобы довольно легко вернуть логическое значение.

Public Function CellIsFormula(rng As Range) As String

Application.Volatile

    Dim testVal As Variant

    testVal = rng.HasFormula 'HasFormula returns variant type

    'testval is null if cells are mixed formulas and values
    If IsNull(testVal) Then
        testVal = "Mixed"
    End If

    Select Case testVal
        Case True
            CellIsFormula = "All Cells in Range Have formula"
        Case False
            CellIsFormula = "No Cells in Range Have formula"
        Case "Mixed"
            CellIsFormula = "Some Cells in Range Have formula"
        Case Else
            CellIsFormula = "Error"
    End Select
End Function
...