Dominar el dilema de Byref y Byval en la programación de VBA
Byref (por referencia) y BYVAL (por valor) son dos métodos de aprobación de argumentos (comúnmente conocidos como ‘mecanismos de paso’) a los procedimientos en Visual Basic y VBA, cada uno con comportamientos e implicaciones distintas de cómo se manejan las variables dentro de las funciones o subrutas.
Tomemos un momento para examinarlos para comprender mejor sus propósitos y dificultades.
Byref (por referencia)
En primer lugar, debe tenerse en cuenta que Byref es el argumento predeterminado «mecanismo de aprobación», por lo que si no se especifica nada en las declaraciones de argumentos de un procedimiento, entonces VBA considera que es Byref.
Cuando se pasa un argumento ByRef, se pasa un puntero a la ubicación de la memoria de ese argumento al procedimiento. Esto significa que cualquier cambio realizado en el argumento dentro del procedimiento afectará la variable original en el código de llamadas.
En inglés sencillo, un argumento de Byref se pasa básicamente como él mismo, por lo que cualquier cambio que ocurra en el procedimiento llamado se devolverá al procedimiento de llamadas.
Ejemplo 1 (Byref):
Sub ModifyValueByRef(ByRef iSomeNumber As Integer) iSomeNumber = iSomeNumber * 2 End Sub Sub MainByRef() Dim iNumber As Integer iNumber = 5 Debug.Print iNumber ' Output: 5 ModifyValueByRef iNumber Debug.Print iNumber ' Output: 10 -> reflects the x * 2 from ModifyValueByRef() ModifyValueByRef (iNumber) Debug.Print iNumber ' Output: 10 (not 20!) -> We'll discuss why later, spoiler it's because of the () End Sub
En este ejemplo, el valor original del inundador se modifica porque se pasa por Byref al ModifyValueByRef () y se multiplica dentro de él, por lo tanto, ese cambio se refleja en el procedimiento de llamadas.
Byval (por valor)
Cuando se aprueba un argumento, solo el valor del argumento se envía al procedimiento. La variable original permanece sin cambios, incluso si el parámetro se modifica dentro del procedimiento.
Ejemplo 2 (BYVAL):
Sub ModifyValueByVal(ByVal iSomeNumber As Integer) iSomeNumber = iSomeNumber * 2 End Sub Sub MainByVal() Dim iNumber As Integer iNumber = 5 Debug.Print iNumber ' Output: 5 ModifyValueByVal iNumber Debug.Print iNumber ' Output: 5 ModifyValueByVal (iNumber) Debug.Print iNumber ' Output: 5 End Sub
Aquí, el valor original de inundador permanece sin cambios independientemente de lo que ocurra dentro de los procedimientos llamados.
Diferencias clave
- Mutabilidad / protección variable
Byref permite que el procedimiento modifique la variable original, mientras que ByVal la protege de los cambios.
- Actuación
Byref generalmente ofrece un mejor rendimiento, especialmente con grandes estructuras de datos, ya que evita copiar datos. Sin embargo, con el poder informático actual, la diferencia suele ser insignificante.
- Parámetros de salida
Byref permite que un procedimiento devuelva realmente múltiples valores en lugar de uno solo como se ve típicamente con funciones.
Ejemplo 3 (combinación Byref & Byval):
Sub ModifyDateByVal(ByVal d As Date) d = DateSerial(2025, 1, 1) ' This doesn't affect the original End Sub Sub ModifyDateByRef(ByRef d As Date) d = DateSerial(2025, 2, 2) ' This also doesn't affect the original End Sub Sub Main_ModifyDate() Dim myDate As Date myDate = #3/5/2025# Debug.Print myDate ' Output: 3/5/2025 ModifyDateByVal myDate Debug.Print myDate ' Output: 3/5/2025, because it is ByVal ModifyDateByRef myDate Debug.Print myDate ' Output: 2/2/2025, because it is ByRef End Sub
Casos especiales
El argumento de la matriz debe ser byref (
El tipo definido por el usuario no se puede pasar byval (
Puede haber más.
Forzar el comportamiento del Byval, incluso en los casos de Byref definidos
Puede forzar el comportamiento de Byval incluso cuando un procedimiento espera Byref mediante el uso de paréntesis:
Sub SetNewString(ByRef inString As String) inString = "New value" End Sub Sub Main() Dim str As String str = "Original" Debug.Print str SetNewString (str) ' Passed as ByVal because of () -> forces ByVal, str remains "Original" Debug.Print str SetNewString str ' Passed ByRef, str becomes "New value" Debug.Print str End Sub
Esta técnica le permite anular el mecanismo de aprobación de Byref predeterminado y protege la variable original de las modificaciones no deseadas.
Mejores prácticas
Aquí hay algunos consejos cuando se trata de usar Byref vs. Byval en su código VBA:
- Siempre debe hacer un esfuerzo para declarar explícitamente Byref o Byval para mayor claridad.
- Use Byref para un mejor rendimiento, especialmente con grandes estructuras de datos o cuando necesita modificar la variable original.
Pero, tenga cuidado con Byref para evitar efectos secundarios no deseados en su código. - Use ByVal cuando no tenga la intención de modificar la variable original.
En resumen
BYVAL hace una copia de la variable original, por lo que cualquier manipulación nunca se refleja. El valor original permanece intacto.
Byref manipula la variable real y, por lo tanto, permite la alteración de los valores a través de procedimientos llamados.
Byref es como darle a su amigo su papel de término original. Pueden marcarlo, y cuando lo devuelven, ves todos los cambios directamente en tu artículo original.
Byval es como darle a tu amigo una fotocopia de tu término papel. Pueden hacer cambios en la copia, pero cuando la devuelven, su artículo original permanece sin cambios. Debería transferir manualmente cualquier cambio de la copia a su original.
Comprender las diferencias entre Byref y BYVAL es crucial para escribir código eficiente y libre de errores en VBA y Visual Basic. Elija el método apropiado en función de sus necesidades específicas y siempre considere las implicaciones para el alcance variable y la mutabilidad en sus procedimientos.
Más lecturas (s) sobre el tema
Historial de la página
Fecha | Resumen de cambios |
---|---|
2025-03-24 | Lanzamiento inicial |