Как вернуть результат из функции VBA

277

Как вернуть результат из функции?

Например:

Public Function test() As Integer
    return 1
End Function

Это дает ошибку компиляции.

Как сделать так, чтобы эта функция возвращала целое число?

Майк
источник
10
Документация: msdn.microsoft.com/en-us/library/office/...
Жан-Франсуа Corbett

Ответы:

430

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

Public Function test() As Integer
    test = 1
End Function

Пример использования:

Dim i As Integer
i = test()

Если функция возвращает тип объекта, то вы должны использовать Setключевое слово, подобное этому:

Public Function testRange() As Range
    Set testRange = Range("A1")
End Function

Пример использования:

Dim r As Range
Set r = testRange()

Обратите внимание, что присвоение возвращаемого значения имени функции не прекращает выполнение вашей функции. Если вы хотите выйти из функции, то вам нужно явно сказать Exit Function. Например:

Function test(ByVal justReturnOne As Boolean) As Integer
    If justReturnOne Then
        test = 1
        Exit Function
    End If
    'more code...
    test = 2
End Function

Документация: http://msdn.microsoft.com/en-us/library/office/gg264233%28v=office.14%29.aspx

Дэн
источник
32
Для полноты следует отметить, что когда вы возвращаете объект (например, a Range), вы должны использовать его так Setже, как если бы вы устанавливали переменную объекта в обычном методе. Поэтому, если, например, «test» - это функция, возвращающая Range, оператор return будет выглядеть следующим образом set test = Range("A1").
Джей Карр
Почему это @JayCarr?
PsychoData
4
@PsychoData - просто потому, что именно так вы устанавливаете переменную объекта в целом, и выполнение этого без него setможет привести к проблемам. У меня были проблемы без этого, но если я использую, setя не делаю :).
Джей Карр
1
Я думаю, что также стоит упомянуть, что поведение функции отличается, когда вы вызываете ее из электронной таблицы, по сравнению с вызовом ее из другой функции VBA или Sub.
Дуг Дженкинс
2
При вызове из VBA функция возвращает объект диапазона, но при вызове из рабочего листа она возвращает только значение, что set test = Range("A1")в точности эквивалентно тому test = Range("A1").Value, где «тест» определен как вариант, а не как диапазон.
Дуг Дженкинс
86

Функции VBA обрабатывают само имя функции как своего рода переменную. Таким образом, вместо использования returnвыражения " ", вы бы просто сказали:

test = 1

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

froadie
источник
На самом деле вы ответили на вопрос более четко с дополнительной информацией (что может привести к другому вопросу от новичка в VBA парень). Продолжайте в том же
духе
Извините, мне показалось, что вы просто ответили так же, как и мой ответ, который я получил первым, но просто добавили тот факт, что он не выходит из функции. Это хорошее дополнение, я просто подумал, что это будет более уместным в качестве комментария. Я не уверен, каков правильный этикет, я думаю, было бы немного грубо понижать голос за это, потому что это хороший ответ, но он не позволит мне отменить его.
Дан
41

Просто установка возвращаемого значения для имени функции по-прежнему не совпадает с returnинструкцией Java (или другой) , потому что в Java, returnвыход из функции, например, так:

public int test(int x) {
    if (x == 1) {
        return 1; // exits immediately
    }

    // still here? return 0 as default.
    return 0;
}

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

Public Function test(ByVal x As Integer) As Integer
    If x = 1 Then
        test = 1 ' does not exit immediately. You must manually terminate...
        Exit Function ' to exit
    End If

    ' Still here? return 0 as default.
    test = 0
    ' no need for an Exit Function because we're about to exit anyway.
End Function 

Так как это так, также приятно знать, что вы можете использовать возвращаемую переменную, как и любую другую переменную в методе. Как это:

Public Function test(ByVal x As Integer) As Integer

    test = x ' <-- set the return value

    If test <> 1 Then ' Test the currently set return value
        test = 0 ' Reset the return value to a *new* value
    End If

End Function 

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

Public Function test(ByVal x As Integer) As Integer

    test = x ' <-- set the return value

    If test > 0 Then

        ' RECURSIVE CALL...WITH THE RETURN VALUE AS AN ARGUMENT,
        ' AND THE RESULT RESETTING THE RETURN VALUE.
        test = test(test - 1)

    End If

End Function
LimaNightHawk
источник
2
«также приятно знать, что вы можете использовать возвращаемую переменную, как и любую другую переменную в методе», в основном это правда, но, например, если тип возвращаемого значения Variantи ваша цель - вернуть массив, то что-то подобное ReDim test(1 to 100)вызовет ошибку. Кроме того, несмотря на то, что такой базовый тип можно трактовать так Integers, он считается несколько недиоматичным. Это делает код сложнее для чтения. Программисты VBA сканируют строки, которые присваивают имени функции, чтобы понять, что делает функция. Использование имени функции в качестве регулярной переменной излишне затеняет это.
Джон Колман
@JohnColeman, полностью согласен в обоих пунктах. Ни в коем случае не следует использовать последний пример рекомендуемой методологии. Но основной вопрос касается того, как вернуть переменную, и поэтому это всего лишь попытка полного объяснения возвращаемого результата VB и, как следствие, как они работают. Конечно, последний случай не является рекомендацией. (Я, конечно, не буду кодировать это как пример.) Итак, ваши очки хорошо взяты, и хорошие дополнения. Спасибо.
LimaNightHawk
Это является полезным для низковата функций, и это то , что любой VBA программист должен знать о, так что я не имел никаких проблем с вами упоминание о нем. Я просто подумал, что предупреждение должно быть включено.
Джон Колман
Спасибо, объясняя, как Exit Functionотносится кreturn
Остин D
@JohnColeman, очевидно, вы не можете ReDim test(1 to 100)без вызова ошибки просто потому, что 'test' не объявлен как массив! и ни по какой другой причине вообще! Вы не можете объявить функцию как массив. Объявите его как a Variant, затем просто создайте свой выходной массив (он может быть динамическим или статическим) внутри этой функции, testа затем присвойте ("=") этот массив testв качестве возвращаемого значения. Для дальнейшей манипуляции, например ReDim, вам нужно присвоить возвращаемое значение переменной, например, Dim x as Variantи вызвать x = test, после чего xвы сделали то, testчто нужно!
Джин,
-6

Приведенный ниже код сохраняет возвращаемое значение в переменной retValи затем MsgBoxможет использоваться для отображения значения:

Dim retVal As Integer
retVal = test()
Msgbox retVal
Бижу Джон
источник