Использование IsNumeric в функции

Я написал функцию, которая генерирует «оценку» (1,0,-1) на основе входной ячейки, которая должна содержать число. Однако иногда поле ввода может быть не числовым, и тогда функция должна возвращать вывод «0».

Function ScoreRoE(RoE_Field As Range, goodval As Range, badval As Range)

    Dim RoE As Double, result As Double

    RoE = RoE_Field.Value

        If IsNumeric(RoE_Field.Value) = False Then
            result = "0"
        Else:
            If RoE >= goodval.Value Then
                result = "1"
            ElseIf RoE <= badval.Value Then
                result = "-1"
            Else:
                result = "0"
            End If
        End If

    ScoreRoE = result

End Function

Когда входная ячейка является числовой, функция работает правильно. Однако, когда это не так, он просто возвращает ошибку «#ЗНАЧ!»

Заранее большое спасибо!


person yannk    schedule 21.06.2019    source источник
comment
сделайте свой числовой тест, прежде чем присвоить ROE его начальное значение. В противном случае вы могли бы назначить строку двойнику, и все выглядит не очень многообещающе.   -  person Forward Ed    schedule 21.06.2019


Ответы (2)


Объявить RoE как вариант:

Function ScoreRoE(RoE_Field As Range, goodval As Range, badval As Range)

    Dim RoE As Variant, result As Double

    RoE = RoE_Field.Value

        If Not IsNumeric(RoE) Then
            result = 0
        Else
            If RoE >= goodval.Value Then
                result = 1
            ElseIf RoE <= badval.Value Then
                result = -1
            Else
                result = 0
            End If
        End If

    ScoreRoE = result

End Function

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


Лично я не вижу необходимости ни в одной из переменных:

Function ScoreRoE(RoE_Field As Range, goodval As Range, badval As Range)

    If Not IsNumeric(RoE_Field.Value) Then
        ScoreRoE = 0
    Else
        If RoE_Field.Value >= goodval.Value Then
            ScoreRoE = 1
        ElseIf RoE_Field.Value <= badval.Value Then
            ScoreRoE = -1
        Else
            ScoreRoE = 0
        End If
    End If

End Function
person Scott Craner    schedule 21.06.2019
comment
@ФорвардЭд ¯\_(ツ)_/¯ - person Scott Craner; 21.06.2019
comment
Есть ли особая причина для использования RoE вместо того, чтобы иметь дело с RoE_Field.Value напрямую, помимо нажатий клавиш? - person Forward Ed; 21.06.2019
comment
@ForwardEd Лично я не вижу необходимости использовать какие-либо переменные, но хотел как можно ближе придерживаться того, что использует OP. - person Scott Craner; 21.06.2019
comment
не то, чтобы это ТРЕБУЕТСЯ, но не следует ли функции назначать тип переменной вместо того, чтобы по умолчанию использовать вариант? - person Forward Ed; 21.06.2019
comment
@ForwardEd Я обычно оставляю его как вариант при выводе на лист, но это личное предпочтение. - person Scott Craner; 21.06.2019
comment
@ForwardEd возможно, если RoE_Field.Value (или любой из входных данных) является значением Error, функция должна возвращать CVErr(xlErrValue) как Variant/Error, а не 0. Это невозможно сделать без возврата Variant. - person Mathieu Guindon; 21.06.2019
comment
Нет, все эти переменные не требуются. Это было большим подспорьем, так код стал намного компактнее. - person yannk; 21.06.2019
comment
@yannk ЕСЛИ вы хотите быть компактнее, определите ScoreROE=0 с самого начала. затем проверьте, является ли RoE_Field.Value числом. И затем, если это так, сделайте две проверки на хорошее значение, а затем на плохое. Все остальное будет равно нулю, так как это было то, что вы инициализировали в начале. - person Forward Ed; 21.06.2019

Это интерпретация намерений кода:

Function ScoreRoe(roeInput As String, goodVal As String, badVal As String) As String

    If Not IsNumeric(roeInput) Or Not IsNumeric(goodVal) Or Not IsNumeric(badVal) Then
        ScoreRoe = "0"
    Else
        Dim goodValNumeric As Double: goodValNumeric = goodVal
        Dim badValNumeric As Double: badValNumeric = badVal
        Dim roeInputNumeric As Double: roeInputNumeric = roeInput

        If roeInputNumeric >= goodValNumeric Then
            ScoreRoe = "1"
        ElseIf roeInputNumeric <= badValNumeric Then
            ScoreRoe = "-1"
        Else
            ScoreRoe = "0"
        End If
    End If

End Function

Основная идея заключается в том, что ввод принимается как String, а затем преобразуется в Double для сравнения. Затем, если ввод не является числовым, возвращаемое значение равно 0, и если это так, мы проходим через If-Else.

В общем, было бы неплохо избегать : в VBA If-Else, чтобы избежать нежелательных проблем, подобных этой - VBA — Как двоеточие `:` работает в коде VBA с условием

person Vityata    schedule 21.06.2019
comment
Интересный взгляд на ситуацию. Не тот маршрут, о котором я, естественно, подумал, но хороший способ подойти к проблеме под другим углом. - person Forward Ed; 21.06.2019
comment
@ForwardEd - ну, я начал с удаления _ из имен переменных, затем удалил :, а потом решил сделать это совершенно по-другому :) - person Vityata; 21.06.2019