DEJE QUE EXCEL HAGA EL TRABAJO SUCIO

Notación abreviada para referirse a un rango versus Range

La llamada notación abreviada es una forma de referirse a un rango (o a algún otro objecto en Excel, como una hoja) haciendo uso del método Evaluate. El método Evaluate es quizás uno de los más poderosas en VBA y tiene múltiples usos. Sin embargo, en este caso hablaremos exclusivamente de su uso para referirse a un rango.

Leyendo la ayuda sobre Evaluate en el editor de VB encontramos esto:

Convierte un nombre de Microsoft Excel en un objeto o un valor.

Esto quiere decir que si tenemos un nombre de un objeto de Excel (por ejemplo, "A1" que es el nombre de la celda A1, podemos convertir ese nombre en el objecto al que hace referencia por medio de Evaluate: Evaluate("A1"). Si tenemos una hoja llamada "Hoja1", podemos convertir ese nombre en un objeto pasándoselo al método Evaluate: Evaluate("Hoja1"), etc.

Ciertamente, aún no hemos hecho uso de la notación abreviada. La notación abreviada es una forma 'abreviada' de utilizar el método Evaluate y quizás usted ya la haya visto en alguna ocasión: [A1].

En este caso [A1] equivale a Evaluate("A1"), que será convertido por el método Evaluate a Range("A1").

Así, resulta muy conveniente usar la notación abreviada: [A1].select, [A1] = "Prueba", etc.

Lo que se debe tener en cuenta es que [A1] no equivale a Range("A1"), equivale a Evaluate("A1") y lo que hará Evaluate("A1") será convertir el texto entre paréntesis en el objecto correspondiente: Range("A1").

Esto quiere decir que el uso de [A1] necesariamente implica un paso de más a usar directamente Range("A1"), pues antes se deberá convertir "A1" al objeto Range correspondiente por medio Evaluate.

Por supuesto, esto implicará un pequeña desventaja en cuanto a rendimiento al usar [A1] versus Range("A1"). Se pueden hacer algunas pruebas para comparar los desempeños de Evaluate versus Range. A continuación copio dos funciones que he escrito con este fin y que devuelven el tiempo que tomó en ejecutarse cada una:

Haciendo uso de la notación abreviada para referirse a A1
Private Function Tiempo_Evaluate(ByVal iteraciones As Long) As Single

    Dim inicio As Single
    Dim x As Long
    Dim y As Long
    
    inicio = Timer
    
    For x = 1 To iteraciones
    
        [a1].Select
        [a1].value = iteraciones
        y = [a1].value
        
    Next x
    
    Tiempo_Evaluate = Timer - inicio
    
End Function

Haciendo uso de Range para referirse a A1
Private Function Tiempo_Range(ByVal iteraciones As Long) As Single
    
    Dim inicio As Single
    Dim x As Long
    Dim y As Long
    
    inicio = Timer
    
    For x = 1 To iteraciones
    
        Range("a1").Select
        Range("a1").value = iteraciones
        y = Range("a1").value
        
    Next x
    
    Tiempo_Range = Timer - inicio
    
End Function

Como se ve, cada función se refiere tres veces al rango "A1": Una para seleccionarlo, otra para escribir en él un valor y otra para leer de él un valor. La única diferencia es que en la función Tiempo_Evaluate se usa la notación abreviada de Evaluate para referirse al rango "A1", mientras que en la función Tiempo_Range se usa Range("A1") para referirse al mismo rango.

Ahora podemos llamar a las dos funciones y comparar sus tiempos de ejecución, indicando cuatas veces queresmo repetir el bucle en las funciones:

Public Sub Comparar()

    Dim prueba As Byte

    Const iteraciones As Long = 1000
    
    For prueba = 1 To 3
    
        Debug.Print "Evaluate:", Tiempo_Evaluate(iteraciones); "segundos"
        Debug.Print "Range:", Tiempo_Range(iteraciones); "segundos"
        Debug.Print VBA.String$(32, "=")
        
    Next prueba
        
    
End Sub

He llevado a cabo tres pruebas con esta macro (y las dos funciones correspondientes): Una con 1.000 iteraciones, otra con 10.000 y otra con 50.000 (Const iteraciones as long). En todos los casos la macro repite tres veces la llamada a las funciones, obteniendo tres resultados para cada número de iteraciones especificado. En los tres casos: 1.000, 10.000 y 50.000 (de tres ensayos cada uno) fue más rápido el uso de Range y como se ve (de acuerdo con los resultados obtenidos en mi equipo), la diferencia puede llegar a ser importante:

Const iteraciones As Long = 1000
Evaluate:      1,632813 segundos
Range:         1,277344 segundos
================================
Evaluate:      1,457031 segundos
Range:         1,121094 segundos
================================
Evaluate:      1,5625 segundos
Range:         1,042969 segundos
================================

Const iteraciones As Long = 10000
Evaluate:      18,17578 segundos
Range:         14,00391 segundos
================================
Evaluate:      18,90625 segundos
Range:         13,73438 segundos
================================
Evaluate:      18,87109 segundos
Range:         13,55469 segundos
================================

Const iteraciones As Long = 50000
Evaluate:      70,47266 segundos
Range:         50,14063 segundos
================================
Evaluate:      71,40625 segundos
Range:         51,66406 segundos
================================
Evaluate:      73,28516 segundos
Range:         52,70313 segundos
================================

Tenga en cuenta que acá se está discutiendo el uso de la notación abreviada de Evaluate para referirse a un objeto tipo Range. El uso de Evaluate va mucho más allá de esto y puede ser realmente poderoso cuando se usa para evaluar una fórmula, permitiendo en muchos casos evitar bucles y ahorrando ahí sí, mucho tiempo en la ejecución de una macro.

Sin embargo, en el caso específico que nos ocupa, esto es, el uso de la notación abreviada de Evaluate para referirse a un rango, pues vemos que aunque nos puede ahorrar algunas teclas al momento de escribir el código, al momento de ejecutarlo pude enlentecer la macro en la que se use... claro, la diferencia no va a ser significativa si se usa una vez, pero en definitiva, si se quisiera ganar hasta la última mílesima de segundo en rendimiento, quizás convenga evitar siempre la notación abreviada para referirse a un rango.

Sería interesante que usted mismo hiciera unas pruebas y ver si sus resultados respaldan lo expuesto... así que lo animo a que haga las pruebas correspondientes y comparta sus resultados.

3 comentarios:

  1. Mauricio siempre con tus grandes aportes, gracias!

    ResponderSuprimir
  2. Hola Gerson,

    Gracias a ti por tu comentario y por visitar el Blog. Me alegra tenerte por acá.

    ResponderSuprimir