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.

     Sub example()
     
     'Idéntico a:
     Public Sub example()
    

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

    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:

    Private Sub warning()
        MsgBox "Caution !!!"
    End Sub
    
    Sub macro_test()
        If Range("A1") = "" Then
            warning '=> ejecutar procedimiento "warning"
        End If
        'etc...
    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).

    Private Sub warning(var_text As String)
        MsgBox "Caution : " & var_text & " !"
    End Sub
    
    Sub macro_test()
        If Range("A1") = "" Then
            warning "celda vacia"
        ElseIf Not IsNumeric(Range("A1")) Then
            warning "valor no numérico"
        End If
    End Sub
    

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

    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:

    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:

    Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
    

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

     'Ejemplo 1: mostrar el apellido:
     dialog_boxes last_name1
       
     'Ejemplo 2: mostramos el apellido y el nombre:
     dialog_boxes last_name1, first_name1
       
     'Ejemplo 3: mostrar el apellido y la edad:
     dialog_boxes last_name1, , age1
       
     'Ejemplo 4: mostrar apellido, nombre y edad:
     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:

    Sub macro_test()
    
        Dim last_name1 As String, first_name1 As String, age1 As Integer
       
        last_name1 = Range("A1")
        first_name1 = Range("B1")
        age1 = Range("C1")
    
        'Ejemplo 1: mostrar el apellido:
        dialog_boxes last_name1
       
        'Ejemplo 2: mostramos el apellido y el nombre:
        dialog_boxes last_name1, first_name1
       
        'Ejemplo 3: mostrar el apellido y la edad:
        dialog_boxes last_name1, , age1
       
        'Ejemplo 4: mostrar apellido, nombre y edad:
        dialog_boxes last_name1, first_name1, age1
    
    End Sub
    
    Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
       
        If IsMissing(age) Then 'Si falta la variable edad...
           
            If IsMissing(first_name) Then 'Si falta la variable first_name, entonces
            							  'solo se mostrará el apellido
               MsgBox last_name
            Else 'De lo contrario, se mostrarán el apellido y el nombre.
               MsgBox last_name & " " & first_name
            End If
           
        Else 'Si la variable edad está presente...
    
            If IsMissing(first_name) Then 'Si falta la variable first_name, entonces
                                          'se mostrará el apellido y la edad
               MsgBox last_name & ", " & age & "años"
            Else 'De lo contrario, se mostrarán el apellido, el nombre y la edad.
               MsgBox last_name & " " & first_name & ", " & age & "años"
            End If
       
        End If
           
    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:

    Sub macro_test()
        Dim var_number As Integer
        
        var_number = 30
        calcul_square var_number
       
        MsgBox var_number
    End Sub
    
    Private Sub calcul_square(ByRef var_value As Integer) 'ByRef es opcional
                                                          '(es el valor predeterminado)
        var_value = var_value * var_value
    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:

     var_number = 30
     'El valor inicial de la variable "var_number" es 30
    
     calcul_square var_number
     'El subprocedimiento se ejecuta con "var_number" como argumento
    
     Private Sub calcul_square(ByRef var_value As Integer)
     'La variable "var_value" sirve hasta cierto punto para un acceso rápido a la variable "var_number",
     'lo que significa que si se cambia la variable "var_value", la variable "var_number" también cambiará
     '(y no tienen que tener el mismo nombre)
     var_value = var_value * var_value
     'Se cambia el valor de la variable "var_value" (y por lo tanto "var_number" también se cambia al mismo tiempo)
    
     End Sub
     'Fin del subprocedimiento
    
     MsgBox var_number
     '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:

     var_number = 30
     'El valor inicial de la variable "var_number" es 30
    
     calcul_square var_number
     'El subprocedimiento se ejecuta con "var_number" como argumento
    
     Private Sub calcul_square(ByVal var_value As Integer)
     'La variable "var_value" copia el valor de la variable "var_number" (las segundas variables no están relacionadas)
    
     var_value = var_value * var_value
     'Se ha cambiado el valor de la variable "var_value"
    
     End Sub
     'Fin del subprocedimiento (en este ejemplo, el subprocedimiento no tiene ningún efecto sobre nada)
    
     MsgBox var_number
     '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:

    Function square(var_number)
        square = var_number ^ 2 'La función "cuadrado" devuelve el valor de "raíz cuadrada"
    End Function
    
    Sub macro_test()
        Dim result As Double
        result = square(9.876) 'A la variable resultado se le asigna el valor que fue calculado por la función
        MsgBox result 'Se muestra el resultado (en este caso el cuadrado de 9.876)
    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: