🔝To translate this blog post to your language, select it in the top left Google box.
Mientras diseño un mapa del mundo me he encontrado con la tarea de calcular la localización de cada país en el mapa mundial.
Cada vez que cambia el zoom o el scroll del mapa tengo que recalcular la posición de los países, por lo que el algoritmo de cálculo debe ser eficiente y con un rendimiento máximo para que ese cálculo no interfiera en el manejo del mapa.
Explicaré por qué utilizar una matriz para recopilar datos de las formas de lo países y escribir en la matriz en lugar de escribir directamente en un rango de celdas de la hoja de trabajo.
En estos artículos encontrarás más información de las matrices (array) y de las formas (shapes):
Este consejo de optimización del código VBA permite mejorar el rendimiento, reduciendo el tiempo de ejecución entre 10 y 100 veces.
Este artículo en inglés es muy relevante:
Chip Pearson comenta que:
La transferencia de datos entre celdas de la hoja de cálculo y variables de VBA es una operación costosa en tiempo de ejecución, por lo que debe reducirse lo más posible. Puede aumentar considerablemente el rendimiento de su aplicación Excel pasando matrices de datos a la hoja de cálculo, y viceversa, en una sola operación en lugar de una celda cada vez. Si necesita realizar cálculos extensos sobre datos en VBA, debe transferir todos los valores de la hoja de trabajo a una matriz, hacer los cálculos en la matriz y luego escribir la matriz nuevamente en la hoja de trabajo. Esto mantiene al mínimo la cantidad de veces que se transfieren datos entre la hoja de trabajo y VBA. Es mucho más eficaz transferir en una única instrucción una matriz de 100 valores a la hoja de cálculo que transferir cada uno de los 100 elementos separadamente en una celda diferente.
Con esta técnica de cargar la matriz y escribirla en las celdas una sola vez, he conseguido tiempos de ejecución de menos de medio segundo, cuando un bucle para escribir separadamente en las celdas no baja de 60 segundos.
Como se aprende practicando, os dejo un ejemplo con las dos macros, la lenta y la rápida.
El problema es que en la hoja 'Mapa' hay formas (shapes) de 240 países que hay que guardar en una tabla de la hoja 'Fronteras', para lo que hace falta una macro que escriba en la tabla algunas de las propiedades de las 240 formas, lo que se hace con un bucle de dos maneras diferentes.
Las propiedades de las formas se guardan en la tabla "TablaFronteras" en las 5 primeras columnas, el resto de columnas se calculan con fórmulas que hay que mantener.
Normalmente se programa la macro lenta si no se conoce la técnica de la macro rápida, que mejora el rendimiento al usar matrices (arrays). A continuación explicaré la diferencia principal entre estas dos macros.
Se escribe cada celda dentro de un bucle a la vez que se leen las propiedades de cada una de las formas (shapes) de cada país del mapa. Este método es ineficiente pues consume mucho tiempo escribir celdas individualmente, pues las macros VBA y Excel son dos mundos separados y el interfaz de conexión entre ellos no está optimizado internamente.
Con un bucle se escriben las propiedades de cada forma (shape) de los países en una matriz (array) bidimensional, que se copia en el rango de celdas de la tabla con una única instrucción, lo que mejora su rendimiento pues es el método más eficiente.
La única instrucción que copia la matriz en el rango está optimizada internamente para pasar valores entre VBA y la hoja de cálculo.
En este vídeo explico cómo usar las dos macros y calcular su rendimiento.
Descarga la versión 2.0 desde uno de estos enlaces:
- Microsoft OneDrive: Rendimiento de las macros - PW2.xlsm
- Sites Google Drive: Rendimiento de las macros - PW2.xlsm
Las macros del archivo descargado están bloqueadas por defecto. Para desbloquear las macros debes modificar las Propiedades del archivo siguiendo estas instrucciones:
Las macros de Internet están bloqueadas de forma predeterminada en Office - Deploy Office | Microsoft Learn
Abre el archivo y presiona el botón: Habilitar edición cuando aparezca el aviso de VISTA PROTEGIDA.
Presiona el botón: Habilitar contenido cuando aparezca la ADVERTENCIA DE SEGURIDAD Las macros se han deshabilitado o se deshabilitó parte del contenido activo.
Las hojas no están protegidas, y no está protegido el proyecto VBA, por lo que puedes estudiar y analizar el código de las macros.
ATENCIÓN: Se puede modificar este libro de Excel respetando esta licencia:
Creative Commons — Atribución-NoComercial-CompartirIgual 3.0 No portada — CC BY-NC-SA 3.0
Con el archivo descargado los tiempos de ejecución son mucho más rápidos que en el vídeo pues es un ejemplo reducido.
- Macro lenta: >0,6 segundos
- Macro rápida: <0,05 segundos
El rendimiento es de más de 1 a 10 con matrices.
Los tiempos en el vídeo son con el archivo que estoy diseñando ¡es el caso real!:
- Macro lenta: >60 segundos
- Macro rápida: <0,5 segundos
El rendimiento es de más de 1 a 100 con matrices.
La macro lenta se ejecuta en 0,6 segundos en un archivo reducido, pero ese tiempo es de 60 segundos en el archivo real del vídeo. El escalado empeora el tiempo en un factor de 100.
La macro rápida se ejecuta en 0,05 segundos en un archivo reducido, y en 0,5 segundos en el archivo real del vídeo. El escalado solo empeora el tiempo en un factor de 10, siendo razonables los 0,5 segundos que es mejor tiempo para la macro rápida que el mejor tiempo de la macro lenta en un archivo reducido.
A veces no tenemos en cuenta que el rendimiento de los algoritmos no optimizados empeora con el escalado de las aplicaciones.
Una macro que parece rápida y eficaz se vuelve lenta y torpe cuando las hojas de cálculo crecen, pues no están optimizadas para el escalado y el rendimiento óptimo, que hay que tener en cuenta desde la primera versión del algoritmo si no queremos encontrarnos sorpresas desagradables cuando el proyecto crezca.
Para la aplicación que estoy desarrollando de un Mapa del mundo es importante que funcione en todo tipo de máquinas, también en las lentas con versiones antiguas de Excel.
Los tiempos de la macro rápida en mi viejo portátil con Excel 2010 corriendo en Windows 7 son similares a los de mi nuevo portátil con Excel para Microsoft 365 en Windows 11. La macro lenta tiene un rendimiento un 100% inferior en el viejo portátil.
En la versión 2.0 he incluido varias macros más de este hilo:
Me ayudaron desinteresadamente los grandes maestros Héctor Miguel y Macro Antonio a mejorar el rendimiento de las macros:
- GuardarFronterasLento en el MóduloFronteras por Pedro Wave.
- Mejor tiempo: 0,53 segundos.
- En un bucle recorre cada forma (shape) y guarda sus propiedades en la tabla.
- getShapesListInWorksheet en el MóduloHM por Héctor Miguel Orozco Díaz.
- Mejor tiempo: 0,21 segundos.
- La UDF getShapePropertie se copia en la tabla y se pegan sus valores.
- No usa bucles, ya que son sustituidos por: With Worksheets("Fronteras").[A2].Resize(n)
- GuardarFronterasMA en el MóduloMA por Macro Antonio.
- Mejor tiempo: 0,24 segundos.
- Guarda en una matriz (array) las propiedades de las formas (shapes).
- Redimensiona la matriz con todas las columnas de la tabla, incluidas las que tienen fórmulas.
- Cambia el tamaño de la tabla y copia las fórmulas en las 4 columnas de la derecha.
- Es lenta porque tiene que desproteger la hoja 'Fronteras' y volver a protegerla.
- GuardarFronterasRápido en el MóduloFronteras por Pedro Wave.
- Mejor tiempo: 0,03 segundos.
- Guarda en una matriz (array) las propiedades de las formas (shapes).
- Copia la matriz en la tabla con una sola instrucción.
- GuardarFronteras en el MóduloFronteras por Macro Antonio.
- Mejor tiempo: 0,01 segundos.
- Guarda en una matriz (array) las propiedades de las formas (shapes).
- Copia la matriz en la tabla con una sola instrucción.
- La macro está muy optimizada para reducir al máximo el tiempo de ejecución.
Todas las adaptaciones y cambios de macros son de mi responsabilidad si, por alguna circunstancia que se me escapa, empeoraron su rendimiento.
Esta última macro es óptima pues mejora el rendimiento hasta 1.000 veces en el prototipo real de un mapa mundial que publicaré próximamente.
Pronto publicaré un mapa completo del mundo con todas las funciones y características que voy publicando estas últimas semanas aquí: