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.
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()
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
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.
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):
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.
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: