Sie sind auf Seite 1von 5

Pasar argumentos por valor (ByVal) o por referencia (byRef) en

VBA para Excel


Puede descargar el archivo ReferenciaValor.xlsm

En el lenguaje de programación VBA para Excel podemos elegir entre pasar


parámetros o argumentos a las funciones o subprocedimientos por valor (ByVal) o por
referencia (ByRef). Veremos las diferencias de ambos métodos y pondremos varios
ejemplos.

 ByVal. Cuando se pasa un parámetro por valor lo que se hace es enviar un


número si la variable es numérica o un string si la variable es una cadena, o del tipo
que sea. No son la misma variable la interna al subprocedimiento o función que la del
procedimiento principal, por lo que al terminar el subprocedimiento y retornar el flujo
del programa al procedimiento principal la variable no retorna con el valor con el que
hubiera acabado el subprocedimiento. Al retornar al procedimiento principal la variable
continúa valiendo lo mismo que valía cuando se envió como parámetro. Por ejemplo,
si la variable i se envía como parámetro con el valor 5, y al terminar el
subprocedimiento o función finaliza con el valor 10, al retornar al procedimiento
principal la variable i continuará con el valor 5.
 ByRef. Cuando se pasa un parámetro por referencia lo que hacemos es enviar
una variable con un cierto valor, el que tenga en el momento del envío. Al retornar al
procedimiento principal la variable viene con el valor con el que hubiera terminado en
el subprocedimiento o función. Por ejemplo, si la variable ise envía como parámetro
con el valor 5, y al terminar el subprocedimiento o función finaliza con el valor 10, al
retornar al procedimiento principal la variable ivendrá con el valor 10.

Por defecto los parámetros en VBA se pasan ByRef

Caso 1
Disponemos de un procedimiento principal que contiene un bucle for que se repite
cuatro veces. Dentro del bucle únicamente tenemos una línea de código que llama al
subprocedimiento Saluda y le pasa el valor de i como parámetro.
El subprocedimiento Saluda recoge el parámetro i como valor (ByVal). Mediante
un MsgBox mostrará en una pequeña ventana emergente un saludo
diciendo Hola junto al valor de i, que será un número de 1 al 4. Luego, y dentro del
subprocedimiento, se asigna a i el valor 100.

 ByVal. Si pasamos el valor de i por valor, al lanzar el procedimiento principal


la macro nos saludará cuatro veces y al final ejecutará la última línea del
procedimiento principal y nos dirá que i es igual a 5.
 ByRef. Si pasamos el valor de i por referencia, al lanzar el procedimiento
principal únicamente nos saludará una vez diciendo Hola1, pero no seguirá con los
siguientes ciclos del bucle for ya que la variable i vuelve con el valor 100. Como 100
es superior al límite dado en el bucle for que es cuatro, se considera que el bucle ha
finalizado y por tanto se ejecutará la última línea del procedimiento principal que hace
que se muestre en pantalla el valor 101.
Sub Principal_1()
For i = 1 To 4
Call Saluda(i)
Next i
MsgBox (i)
End Sub
Sub Saluda(ByVal i)
MsgBox ("Hola" & i)
i = 100
End Sub

Caso 2
En el procedimiento principal asignamos a las variables x, y, z el valor 5. Imprimiremos
su valor empleando para la variable x la columna A, para la variable y la columna B y
para la variable z la columna C. Llamamos al subprocedimiento Dobla y le pasamos
como parámetros los valores x, y, z.
El subprocedimiento Dobla recibe el parámetro x por referencia (ByRef), el
parámetro y por valor (ByVal) y el parámetro z lo recibe sin indicar nada para ver
cómo trata VBA por defecto los parámetros que se pasan a un subprocedimiento o
función. Se dobla el valor de x, y, z. Se imprime nuevamente el valor de x, y, z en la
fila dos de las columnas A, B, C respectivamente. Veremos que los valores impresos
son 10, 10, 10, esto es así ya que estamos imprimiendo el valor de la variable interna
del subprocedimiento y en los tres casos esta variable es el doble de cinco.
Finalizado el subprocedimiento se vuelve al procedimiento principal y en la fila tres se
imprimen nuevamente los valores de x, y, z. Pero ahora vemos que lo que se imprime
es 10, 5, 10. Veamos el motivo de esta diferencia.

 ByRef. El parámetro x se pasó por referencia. Continúa siendo la misma


variable la que se definió inicialmente en el procedimiento principal, la que luego se
usa en el subprocedimiento y la que finalmente retorna al procedimiento principal. Al
retornar, vuelve con el valor 10.
 ByVal. El parámetro y se pasó por valor y por tanto lo que se hace es pasarlo
como si fuera un número sin que quede vinculación con la variable inicialmente
definida en el procedimiento principal. En el subprocedimiento se dobla el valor ypara
de 5 a 10, pero al retornar al procedimiento principal no se retorna ningún valor, y la
variable y en el procedimiento principal sigue valiendo 5 que es tal y como se definió
en un principio.
 Por defecto. El parámetro z se pasó sin indicar nada y al final se ha
comportado como la variable x. Esto indica que si no ponemos nada, por defecto VBA
pasa los parámetros por referencia (ByRef).

Sub Principal_2()
x = 5: y = 5: z = 5
Cells(1, "A") = x: Cells(1, "B") = y: Cells(1, "C") = z
Call Dobla(x, y, z)
Cells(3, "A") = x: Cells(3, "B") = y: Cells(3, "C") = z
End Sub
Sub Dobla(ByRef x, ByVal y, z)
x = 2 * x: y = 2 * y: z = 2 * z
Cells(2, "A") = x: Cells(2, "B") = y:: Cells(2, "C") = z
End Sub

Caso 3
Queremos listar los números del 10 al 20. Disponemos de un procedimiento principal
que llama a un subprocedimiento que se denomina Listado, al que se pasan dos
parámetros ay b. El parámetro b se puede pasar por valor o por referencia. Si se pasa
por valor la lista impresa se genera en vertical y si se pasa por referencia la lista
impresa se muestra en diagonal.

En el procedimiento principal inicializamos la variable


b haciendo que su valor se igual a uno. Nos metemos en un bucle for donde la
variable a varía entre 10 y 20. Dentro del bucle se llama al subprocedimiento Listado
pasándole los parámetros a y b.
El subprocedimiento Listado escribe el valor de a en la fila a y columna b. Finalmente
tiene una línea de código que incrementa el valor de b en una unidad.

 ByRef. Si pasamos el parámetro b por referencia el incremento de la variable b


en una unidad que se hace en la última línea de código se recordará en el
procedimiento principal y por tanto la variable b en el primer ciclo del bucle for valdrá 1,
pero en el segundo ciclo ya valdrá 2, en el tercero 3, y así sucesivamente. Esto hace
que al ejecutar reiteradamente el subprocedimiento y escribir con cells cada vez se
haga en una fila más a la derecha, lo que provoca que el resultado se vea en diagonal.
 ByVal. Si pasamos el parámetro b por valor la última línea de código que hace
que b se incremente en una unidad no se recordará al llegar la procedimiento principal
y por tanto b continuará valiendo 1 que es el valor con el que se inicializó. Esto
provoca que al ser b siempre igual a uno, no nos movamos de la columna uno, y por
tanto la serie de números se imprima en vertical todos ellos en la columna uno.

Sub Principal_3()
b = 1
For a = 10 To 20
Call Listado(a, b)
Next a
End Sub
Sub Listado(a, ByRef b)
Cells(a, b) = a
b = b + 1
End Sub

Caso 4
Vamos a calcular el montante final al que se llega aplicando la ley de capitalización
compuesta con los siguientes datos.
Capital inicial C = 1.000 €
tipo de interés i = 0,15
tiempo años t = 3

Disponemos de un procedimiento principal que llama dos veces a la función Montante.


En la función existe una última línea de código que hace que el valor del tipo de interés
i se reduzca en un 5%.

 ByRef. Si pasamos el parámetro i por referencia la primera vez el tipo de


interés valdrá 15% y la segunda vez valdrá 10% ya que se ha reducido el valor del tipo
de interés y el procedimiento principal toma ese valor ya que no olvida el último valor
con el que quedó la variable. Esto provoca que los dos montantes sean diferentes, el
primero calculado al 15% y el segundo al 10%.
 ByVal. Si pasamos el parámetro i por valor la última línea del
subprocedimiento no se recordará al llegar al procedimiento principal y por tanto el
valor del tipo de interés no se reducirá y continuará siendo del 15%. Esto provoca que
los dos montantes sean iguales, ambos calculados al 10%.

Sub Principal_4()
i = 0.15
t = 3
C = 1000
Cells(1, "H") = Montante(i, t, C)
Cells(2, "H") = Montante(i, t, C)
End Sub
Function Montante(ByVal i, t, C)
Montante = C * (1 + i) ^ t
i = i - 0.05
End Function

Das könnte Ihnen auch gefallen