TOP

VBA-Lección 9. Procedimientos y funciones

En cualquier lenguaje de programación existen conceptos tales como procedimientos y funciones. También se incluyeron en el lenguaje de programación incorporado VBA para Excel.

  • Una función es una rutina que devuelve un resultado. Una llamada de función es una expresión y se puede usar en otras expresiones o en el lado derecho de una instrucción de asignación (indicada en VBA como "Función");
  • Un procedimiento es cualquier rutina que no es una función. Marcado en VBA como "Sub" (de la palabra "subrutina").

  • Procedimientos (Public - Private)

    En este punto, todos los procedimientos que hemos creado son del tipo Public, lo que significa que son accesibles desde cualquier módulo.

    1. Sub example()  
    2.   
    3. 'Idéntico a:  
    4. Public Sub example()  

    Para que el procedimiento esté disponible solo en un determinado módulo, se utiliza la palabra clave Private:

    1. Private Sub example()  

    Ejecutar un procedimiento desde la mitad de otro procedimiento

    Para ejecutar un procedimiento desde dentro de otro procedimiento, simplemente ingrese su nombre.

    Aquí hay un ejemplo muy simple de esto:

    1. Private Sub warning()  
    2.     MsgBox "Caution !!!"  
    3. End Sub  
    4.   
    5. Sub macro_test()  
    6.     If Range("A1") = "" Then  
    7.         warning '=> ejecutar procedimiento "warning"  
    8.     End If  
    9.     'etc...  
    10. End Sub  

    Argumentos

    Los argumentos permiten utilizar valores de un procedimiento en un subprocedimiento (recuerde que, por defecto, las variables solo están disponibles desde el procedimiento en el que fueron declaradas).

    1. Private Sub warning(var_text As String)  
    2.     MsgBox "Caution : " & var_text & " !"  
    3. End Sub  
    4.   
    5. Sub macro_test()  
    6.     If Range("A1") = "" Then  
    7.         warning "celda vacia"  
    8.     ElseIf Not IsNumeric(Range("A1")) Then  
    9.         warning "valor no numérico"  
    10.     End If  
    11. End Sub  

    Se ha agregado un argumento al procedimiento "warning", en este caso es una variable "var_text" de tipo "String" (cinta):

    1. Private Sub warning(var_text As String)  

    Esta rutina toma un argumento, por lo que debemos poner un valor después de "warning" para ejecutarla:

    1. warning "celda vacia"  

    Cuando queremos escribir varios argumentos, entonces deben estar separados por comas.

    Argumentos opcionales

    De forma predeterminada, si el procedimiento tiene argumentos, se deben proporcionar y, si no se proporcionan, el procedimiento no se ejecutará.

    Se puede agregar un argumento opcional después de uno obligatorio, usando la palabra clave Optional. Ejemplo:

    1. Private Sub dialog_boxes(last_name As StringOptional first_name, Optional age)  

    Este procedimiento ahora se puede ejecutar con o sin un argumento opcional, como aquí:

    1. 'Ejemplo 1: mostrar el apellido:  
    2. dialog_boxes last_name1  
    3.     
    4. 'Ejemplo 2: mostramos el apellido y el nombre:  
    5. dialog_boxes last_name1, first_name1  
    6.     
    7. 'Ejemplo 3: mostrar el apellido y la edad:  
    8. dialog_boxes last_name1, , age1  
    9.     
    10. 'Ejemplo 4: mostrar apellido, nombre y edad:  
    11. dialog_boxes last_name1, first_name1, age1  

    Los argumentos deben introducirse en el orden correcto.

    Para probar si un argumento opcional está presente en un procedimiento, usamos la función IsMissing. Esta función solo es compatible con algunos tipos de funciones (del tipo Variant) y esto es fundamental porque no se declaró el tipo de los argumentos opcionales (tipo no declarado = Variant).

    Aquí hay un ejemplo que usa los dos fragmentos de código discutidos anteriormente:

    1. Sub macro_test()  
    2.   
    3.     Dim last_name1 As String, first_name1 As String, age1 As Integer  
    4.      
    5.     last_name1 = Range("A1")  
    6.     first_name1 = Range("B1")  
    7.     age1 = Range("C1")  
    8.   
    9.     'Ejemplo 1: mostrar el apellido:  
    10.     dialog_boxes last_name1  
    11.      
    12.     'Ejemplo 2: mostramos el apellido y el nombre:  
    13.     dialog_boxes last_name1, first_name1  
    14.      
    15.     'Ejemplo 3: mostrar el apellido y la edad:  
    16.     dialog_boxes last_name1, , age1  
    17.      
    18.     'Ejemplo 4: mostrar apellido, nombre y edad:  
    19.     dialog_boxes last_name1, first_name1, age1  
    20.   
    21. End Sub  
    22.   
    23. Private Sub dialog_boxes(last_name As StringOptional first_name, Optional age)  
    24.      
    25.     If IsMissing(age) Then 'Si falta la variable edad...  
    26.          
    27.         If IsMissing(first_name) Then 'Si falta la variable first_name, entonces  
    28.                                       'solo se mostrará el apellido  
    29.            MsgBox last_name  
    30.         Else 'De lo contrario, se mostrarán el apellido y el nombre.  
    31.            MsgBox last_name & " " & first_name  
    32.         End If  
    33.          
    34.     Else 'Si la variable edad está presente...  
    35.   
    36.         If IsMissing(first_name) Then 'Si falta la variable first_name, entonces  
    37.                                       'se mostrará el apellido y la edad  
    38.            MsgBox last_name & ", " & age & "años"  
    39.         Else 'De lo contrario, se mostrarán el apellido, el nombre y la edad.  
    40.            MsgBox last_name & " " & first_name & ", " & age & "años"  
    41.         End If  
    42.      
    43.     End If  
    44.          
    45. End Sub  

    Ver imagen de abajo (ejemplo 1):

    ByRef - ByVal

    De forma predeterminada, los argumentos son del tipo ByRef, lo que significa que si se pasa una variable como argumento, también se pasará una referencia a ella. En otras palabras, si otro subprocedimiento ha cambiado una variable, también se cambiará en el procedimiento externo que llama a ese subprocedimiento.

    Ejemplo:

    1. Sub macro_test()  
    2.     Dim var_number As Integer  
    3.       
    4.     var_number = 30  
    5.     calcul_square var_number  
    6.      
    7.     MsgBox var_number  
    8. End Sub  
    9.   
    10. Private Sub calcul_square(ByRef var_value As Integer'ByRef es opcional  
    11.                                                       '(es el valor predeterminado)  
    12.     var_value = var_value * var_value  
    13. End Sub  

    Para que quede claro, a continuación se muestra un ejemplo de lo que sucederá si se inicia la ejecución de la macro:

    1. var_number = 30  
    2. 'El valor inicial de la variable "var_number" es 30  
    3.   
    4. calcul_square var_number  
    5. 'El subprocedimiento se ejecuta con "var_number" como argumento  
    6.   
    7. Private Sub calcul_square(ByRef var_value As Integer)  
    8. 'La variable "var_value" sirve hasta cierto punto para un acceso rápido a la variable "var_number",  
    9. 'lo que significa que si se cambia la variable "var_value", la variable "var_number" también cambiará  
    10. '(y no tienen que tener el mismo nombre)  
    11. var_value = var_value * var_value  
    12. 'Se cambia el valor de la variable "var_value" (y por lo tanto "var_number" también se cambia al mismo tiempo)  
    13.   
    14. End Sub  
    15. 'Fin del subprocedimiento  
    16.   
    17. MsgBox var_number  
    18. 'La variable "var_number" se ha cambiado, por lo que ahora se mostrará 900 en el cuadro de diálogo.  

    El segundo método es usar ByVal.

    A diferencia de ByRef, que pasa una referencia (etiqueta), ByVal pasa un valor, lo que significa que el valor pasado como argumento no ha sido modificado.

    A continuación puedes ver cómo funciona el código anterior y ByVal:

    1. var_number = 30  
    2. 'El valor inicial de la variable "var_number" es 30  
    3.   
    4. calcul_square var_number  
    5. 'El subprocedimiento se ejecuta con "var_number" como argumento  
    6.   
    7. Private Sub calcul_square(ByVal var_value As Integer)  
    8. 'La variable "var_value" copia el valor de la variable "var_number" (las segundas variables no están relacionadas)  
    9.   
    10. var_value = var_value * var_value  
    11. 'Se ha cambiado el valor de la variable "var_value"  
    12.   
    13. End Sub  
    14. 'Fin del subprocedimiento (en este ejemplo, el subprocedimiento no tiene ningún efecto sobre nada)  
    15.   
    16. MsgBox var_number  
    17. 'La variable "var_number" no se ha cambiado, por lo que se mostrará 30 en el cuadro de diálogo  

    Lo que debe recordar: use ByVal cuando no se deba cambiar la variable.

    Funciones

    La principal diferencia entre un procedimiento y una función es que una función devuelve un valor.

    Aquí hay un ejemplo simple:

    1. Function square(var_number)  
    2.     square = var_number ^ 2 'La función "cuadrado" devuelve el valor de "raíz cuadrada"  
    3. End Function  
    4.   
    5. Sub macro_test()  
    6.     Dim result As Double  
    7.     result = square(9.876) 'A la variable resultado se le asigna el valor que fue calculado por la función  
    8.     MsgBox result 'Se muestra el resultado (en este caso el cuadrado de 9.876)  
    9. End Sub  

    La función se puede usar en una hoja de trabajo como cualquier otra función en Excel.

    Por ejemplo, para obtener el cuadrado del valor ingresado en la celda A1: