Функция возвращает по-разному при вызове из sub vs excel

#excel #vba #excel-formula #error-handling

#excel #vba #excel-формула #обработка ошибок

Вопрос:

Здесь у меня есть простая функция, которая выполняет вычисления для диапазона значений. Диапазон всегда будет иметь 5 значений. Диапазон также должен быть одномерным. В попытке охватить случай, когда он выходит за пределы диапазона, я попытался добавить обработку ошибок, которая будет запрашивать пользователя об ограничении функций.

Когда я проверяю диапазон со значением x> 1 из подпрограммы, я получаю сообщение об ошибке только один раз, как и предполагалось. Однако, когда я пытаюсь использовать тот же диапазон ячеек с рабочего листа, я получаю сообщение об ошибке много раз.

Я не понимаю, почему я получаю разные результаты от рабочего листа и подпрограммы.

Любая помощь приветствуется.

 Public Function RIAJ_SCORE_RANGE(Range_FROM_million_TO_gold As Range) As Double

On Error GoTo eh

Dim millionTOgold As Variant

millionTOgold = Range_FROM_million_TO_gold.Value

Dim i As Long
Dim x As Integer

x = 1

If x <> 1 Then GoTo er1

For i = LBound(millionTOgold) To UBound(millionTOgold)
If i = 1 Then
RIAJ_SCORE_RANGE = millionTOgold(i, 1) * 10
ElseIf i = 2 Then RIAJ_SCORE_RANGE = RIAJ_SCORE_RANGE   millionTOgold(i, x) * 7.5
ElseIf i = 3 Then RIAJ_SCORE_RANGE = RIAJ_SCORE_RANGE   millionTOgold(i, x) * 5
ElseIf i = 4 Then RIAJ_SCORE_RANGE = RIAJ_SCORE_RANGE   millionTOgold(i, x) * 2.5
ElseIf i = 5 Then RIAJ_SCORE_RANGE = RIAJ_SCORE_RANGE   millionTOgold(i, x)
Else: GoTo eh

End If
Next i

er1:
    x = 1
    MsgBox ("Function requires range from a single column")
    GoTo eh
    
eh:
    Exit Function

End Function
  

Этот sub выполняется по назначению, возвращая сообщение об ошибке и завершая работу функции. Из Excel передача одного и того же диапазона выдает сообщение об ошибке 32 раза.

 Sub testRange()

RIAJ_SCORE_RANGE (ActiveSheet.Range("E86:F91"))

End Sub
  

Ответ №1:

 RIAJ_SCORE_RANGE (ActiveSheet.Range("E86:F91"))
  

Отбросьте круглые скобки, они позволяют вводить ваше Range значение с помощью неявного вызова элемента по умолчанию ( Range.[_Default] скрытого элемента, который «переходит» к другим элементам в зависимости от того, как он параметризован), который в конечном итоге Пытается передать 2D- Variant массив (т. Е. Именно То, Что вы получите ActiveSheet.Range("E86:F91").Value ) процедуре, котораяхочет работать с Range объектом, отсюда и ошибка несоответствия типов.

Это означало бы передачу Range объекта без преобразования его в массив:

 RIAJ_SCORE_RANGE ActiveSheet.Range("E86:F91")
  

Тем не менее, вызов функции без захвата ее возвращаемого значения (должен быть) бесполезен, потому что функция (особенно та, которая предназначена для запуска из ячейки рабочего листа) не должна иметь никаких побочных эффектов: она принимает входные данные, вычисляет результат на основе этих входных данных и выводит результат. Похоже, это именно то, что у вас здесь, так что .. хорошая работа!

Вам нужны круглые скобки, когда вы фиксируете возвращаемое значение функции:

 MsgBox RIAJ_SCORE_RANGE(ActiveSheet.Range("E86:F91"))
  

Обратите внимание на пропущенный пробел между именем функции и ( символом: это VBE сообщает вам, что (...) круглые скобки ограничивают список аргументов. Когда есть пробел (VBE принудительно заполняет этот пробел, вы не можете с этим бороться), скобки разрешаются — принудительное использование первого аргумента в списке аргументов — MsgBox это тоже функция, и мы здесь не фиксируем его возвращаемое значение, поэтому круглые скобки не нужны.

Для этого нам пришлось бы добавить круглые скобки:

 Debug.Print MsgBox(RIAJ_SCORE_RANGE(ActiveSheet.Range("E86:F91")), vbInformation)
  

И это было бы незаконно:

 MsgBox (RIAJ_SCORE_RANGE(ActiveSheet.Range("E86:F91")), vbInformation)
  

…потому (RIAJ_SCORE_RANGE(ActiveSheet.Range("E86:F91")), vbInformation) что не имеет смысла как выражение значения!

Комментарии:

1. Я знаю, что я не должен говорить спасибо, но это вдумчивое объяснение невероятно полезно. Большое вам спасибо!

2. Выглядит как полезный инструмент. Я буду использовать это в будущем!