Cómo devolver un resultado de una función VBA

Respuestas:

430

Para los tipos de retorno sin objeto, debe asignar el valor al nombre de su función, de esta manera:

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

Ejemplo de uso:

Dim i As Integer
i = test()

Si la función devuelve un tipo de objeto, debe usar la Setpalabra clave de esta manera:

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

Ejemplo de uso:

Dim r As Range
Set r = testRange()

Tenga en cuenta que asignar un valor de retorno al nombre de la función no termina la ejecución de su función. Si desea salir de la función, debe decir explícitamenteExit Function . Por ejemplo:

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

Documentación: http://msdn.microsoft.com/en-us/library/office/gg264233%28v=office.14%29.aspx

Dan
fuente
32
Para completar, debe tenerse en cuenta que cuando devuelve un objeto (como un Rangepor ejemplo), debe usarlo Setcomo lo haría si configura una variable de objeto en un método regular. Entonces, si, por ejemplo, "prueba" fuera una función que devolviera un Rango, la declaración de retorno se vería así set test = Range("A1").
Jay Carr
¿Por qué es ese @ JayCarr?
PsychoData
44
@PsychoData: simplemente porque así es como configura una variable de objeto en general, y hacerlo sin setproblemas puede generar problemas. He tenido problemas para hacerlo sin, pero si lo uso setno lo hago :).
Jay Carr
1
Creo que también vale la pena mencionar que el comportamiento de la función difiere cuando se llama desde una hoja de cálculo, en comparación con llamar desde otra función VBA o Sub.
Doug Jenkins
2
Cuando se llama dentro de VBA, la función devolverá un objeto de rango, pero cuando se llama desde una hoja de trabajo, devolverá solo el valor, por lo que set test = Range("A1")es exactamente equivalente a test = Range("A1").Value, donde "prueba" se define como una Variante, en lugar de un Rango.
Doug Jenkins
86

Las funciones de VBA tratan el nombre de la función como una especie de variable. Entonces, en lugar de usar una returndeclaración " ", simplemente diría:

test = 1

Tenga en cuenta, sin embargo, que esto no se escapa de la función. Cualquier código después de esta declaración también se ejecutará. Por lo tanto, puede tener muchas instrucciones de asignación que asignen valores diferentes test, y cualquiera que sea el valor cuando llegue al final de la función será el valor devuelto.

froadie
fuente
En realidad, respondiste la pregunta más claramente con información adicional (lo que podría conducir potencialmente a otra pregunta para un chico nuevo en VBA). Sigan con el buen trabajo
Adarsha
Lo siento, parecía que acababas de responder lo mismo que mi respuesta, que tenía primero, pero solo añadía el hecho de que no se salía de la función. Es una buena adición, solo pensé que sería más apropiado como comentario. No estoy seguro de cuál es la etiqueta adecuada, supongo que fue un poco grosero rechazarlo por eso, porque es una buena respuesta, pero no me deja deshacerlo.
Dan
41

Simplemente establecer el valor de retorno para el nombre de la función todavía no es exactamente lo mismo que la returninstrucción Java (u otra) , porque en Java, returnsale de la función, así:

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

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

En VB, el equivalente exacto toma dos líneas si no está configurando el valor de retorno al final de su función . Entonces, en VB, el corolario exacto se vería así:

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 

Como este es el caso, también es bueno saber que puede usar la variable de retorno como cualquier otra variable en el método. Me gusta esto:

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 

O bien, la extrema ejemplo de cómo las variables de retorno obras (pero no necesariamente un buen ejemplo de cómo en realidad se debe código) -la que le mantendrá en la noche:

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
LimaNocheHawk
fuente
2
"también es bueno saber que puede usar la variable de retorno como cualquier otra variable en el método" es mayormente cierto, pero, por ejemplo, si el tipo de retorno es Varianty su objetivo es devolver una matriz, algo como ReDim test(1 to 100)esto provocará un error. Además, aunque es posible tratar un tipo básico Integerscomo ese, se considera algo unidiomático. Hace que el código sea más difícil de leer. Los programadores de VBA buscan líneas que se asignan al nombre de la función para comprender qué hace una función. Usar el nombre de la función como una variable regular oscurece innecesariamente esto.
John Coleman
@JohnColeman, totalmente de acuerdo en ambos puntos. De ninguna manera el último ejemplo debe ser uno de metodología recomendada. Pero, la pregunta del tema es con respecto a cómo devolver una variable, por lo que esto es solo un intento de una explicación completa del resultado de retorno de VB y, por extensión, cómo funcionan. Ciertamente, el último caso no es una recomendación. (Ciertamente no codificaría eso como más que un ejemplo). Entonces, sus puntos están bien tomados y son buenas adiciones. Gracias.
LimaNightHawk
Que es útil para funciones más bien pequeñas, y es algo que cualquier programador VBA debe conocer, así que tuve ningún problema con que mencionarlo. Solo pensé que debería incluirse una advertencia.
John Coleman
Gracias explicando cómo se Exit Functionrelaciona conreturn
Austin D
@JohnColeman, ¡Obviamente, no puede hacerlo ReDim test(1 to 100)sin activar un error simplemente porque 'test' no se declara como una matriz! ¡y por ninguna otra razón! No puede declarar una función como una matriz. Declare como a Variant, luego simplemente construya su matriz de salida (puede ser Dinámica o Estática) dentro de esta función testy luego asigne ("=") esta matriz testcomo un valor de retorno. Para manipular aún más, como ReDimsi fuera necesario, debe asignar el valor devuelto a una variable, por ejemplo, Dim x as Varianty llamar x = test, ¡después de lo cual xes lo que hizo testque sea!
Gene
-6

El siguiente código almacena el valor de retorno en la variable retValy luego MsgBoxse puede usar para mostrar el valor:

Dim retVal As Integer
retVal = test()
Msgbox retVal
Biju John
fuente