Las matrices (arrays)
Las matrices, también conocidas por su nombre en inglés arrays, o como vectores o campos de datos se podrían definir como un conjunto de datos del mismo tipo que se almacenan juntos en la memoria, identificados por el mismo nombre, y a los que se pueden distinguir y acceder de forma concreta por un índice numérico.
Veamos un ejemplo: Supongamos que debemos almacenar en variables los resultados de ventas de un año, mes a mes. Podríamos crear un código como el siguiente:
Encontrarás en los códigos de ejemplo una o más series de puntos suspensivos. No es código BASIC; sólo tratan de representar que "aquí habría más código" |
Sub LeeVentasMes Dim vMes01 As Single, vMes02 As Single, vMes03 As Single, vMes04 As Single, _ vMes05 As Single, vMes06 As Single, vMes07 As Single, vMes08 As Single, _ vMes09 As Single, vMes10 As Single, vMes11 As Single, vMes12 As Single vMes01 = 1000 vMes02 = 1500 vMes03 = 2000 ... vMes12 = 1900 End Sub
Este código se puede simplificar con el uso de matrices:
Sub LeeVentasMes Dim vMes(12) As Single vMes(1) = 1000.75 vMes(2) = 1500.50 vMes(3) = 2000.00 ... vMes(12) = 1900.30 End Sub
A la hora de nombrar una matriz se siguen las mismas reglas que para nombrar variables, pues una matriz es una variable.
Sub LeeVentasMes Dim [Mes del año](12) As Single [Mes del año](01) = 1000.75 [Mes del año](02) = 1500.50 [Mes del año](03) = 2000.00 ... [Mes del año](12) = 1900.30 End Sub
También podemos tipificar las matrices, como se ve en el ejemplo (As Single) del mismo modo que se hace para las variables, pues una matriz es una variable.
Declarar una matriz
Se declaran del mismo modo que las variables, utilizando la instrucción Dim, pues una matriz es una variable.
A diferencia del resto de variables, que pueden ser declaradas de forma implícita, las matrices obligatoriamente deben ser declaradas de forma explícita, independientemente de la directiva del compilador Option Explicit.
Las matrices también se diferencian del resto de variables es en que están compartimentadas, y cada compartimento contiene un valor. En el momento de su declaración podemos indicar el número de compartimentos (elementos) que la conforman, usando la siguiente sintaxis:
Dim <nombre>([<número_de_elementos>]) [As <tipo>]
Pero no es absolutamente necesario, pues podemos añadir nuevos elementos a la matriz, o eliminar elementos en cualquier momento. Para ello se utiliza la instrucción ReDim, que cambia el número de elementos de una matriz.
ReDim <nombre>(<nuevo_número_de_elementos>)
Como Dim y ReDim son formas abreviadas de las palabras inglesas que se traducen como Dimensionar y Redimensionar, se confunde habitualmente el número de elementos de una matriz con las dimensiones de una matriz, pero no es lo mismo. Más adelante trataremos el tema de las dimensiones de una matriz |
Así, si hemos declarado una matriz de 5 elementos, y queremos redimensionarla a 10 elementos, utilizaremos un código como el que mostramos a continuación:
Dim MiMatriz(4) ... ... Redim MiMatriz(9) ... ... Redim MiMatriz(6) ... ...
¿Para declarar una matriz de 5 elementos escribo Dim MiMatriz(4)? Sí, pues por defecto, las matrices se crean numerando a sus elementos desde el número 0. Al declarar la matriz con un 4 entre paréntesis, hemos definido que tendrá desde el elemento 0 al 4. Tendrá el elemento 0, el 1, el 2, el 3 y el 4. 0,1,2,3,4. En total, ¡¡¡ 5 elementos !!!
Este comportamiento puede modificarse utilizando la directiva del compilador Option Base, que permite empezar la numeración desde el elemento 1. En ese caso, al utilizar la orden Dim MiMatriz(4) obtendremos también una matriz de 5 elementos, pero numerados desde el 1 al 5 (1,2,3,4,5, en total, 5 elementos).
De hecho, en nuestro primer ejemplo, al declarar la matriz vMes(12) hemos declarado una matriz de 13 elementos con Option Base puesto a cero; no hemos querido utilizar el primero de sus elementos, vMes(0) por que nos ha parecido más sencillo identificar el elemento vMes(1) con el dato correspondiente al mes de Enero, y así, sucesivamente para el resto de meses. Cuestión de gustos.
En el código hemos aumentado el número de elementos de 5 a 10 con la instrucción ReDim MiMatriz(9), y posteriormente lo hemos reducido a 7 con la instrucción ReDim MiMatriz(7)
Instrucción ReDim Preserve
Al utilizar la instrucción ReDim para cambiar el número de elementos de una matriz se pierde todo su contenido. Por decirlo de otra forma, obtendremos una matriz con el nuevo número de elementos, pero todos los compartimentos estarán vacíos.
Para cambiar el número de elementos de una matriz y mantener el contenido de los antiguos compartimentos hay que utilizar la instrucción Redim Preserve. Si ampliamos el número de elementos de 4 a 6, los dos nuevos elementos estarán vacíos, pero los "primeros" 4 mantendrán sus valores.
Dim MiMatriz(4) ... ... Redim Preserve MiMatriz(9) ... ... Redim Preserve MiMatriz(6) ... ...
Si utilizamos ReDim Preserve para reducir el número de elementos de la matriz de 10 a 7, los últimos 3 elementos serán eliminados, por lo que perdemos su contenido, pero se mantendrán los valores contenidos en los 7 primeros elementos de la matriz.
Acceder al contenido de un elemento de la matriz
Como ya habrás podido deducir por el código mostrado, para acceder al contenido de un elemento, o para establecer el contenido de un elemento, lo haremos nombrando la matriz y entre paréntesis, el número índice del elemento.
Para asignar al elemento 12 de la matriz vMes de nuestro primer ejemplo el valor 5500, escribimos el siguiente código:
vMes(12) = 5500
Para acceder al elemento 12 de la matriz vMes de nuestro primer ejemplo y leer el valor que contiene, escribimos el siguiente código:
MsgBox "Las ventas del mes de diciembre fueron de " & vMes(12) & " millones de Euros"
Definir los índices mínimo y máximo de una matriz
Hemos visto cómo utilizando la directiva del compilador Option Base se define que el primer elemento de una matriz es el elemento numerado como 0 o como 1.
Se pueden establecer los índices mínimo y máximo de una matriz, independientemente del valor que se haya dado a la directiva Option Base, utilizando la siguiente sintaxis:
Dim <nombre>(<índice_menor> TO <índice_mayor>) [As <tipo>]
Así, si deseamos definir una matriz cuyo primer elemento sea el número 5 y el último el número 14 (una matriz de 10 elementos), podemos escribir un código como el siguiente:
Dim aDistritos( 5 to 14 ) aDistritos(5) = "46100" ' primer elemento de la matriz ... aDistritos(14) = "46900" ' último elemento de la matriz
Se pueden utilizar valores negativos para los índices. Según la documentación consultada, El índice más pequeño admitido es -32768. El mayor posible es el 32767. El número máximo de elementos (dentro de una dimensión) es de 16.368. Nosotros hemos comprobado que funciona con rangos mayores que estos (aburridos de probar, nos detuvimos en el rango desde -250000 hasta +250000, lo que indica un total de 500.001 elementos), pero hay que tener cuidado, pues matrices de miles de elementos pueden agotar la memoria disponible del ordenador en que se ejecuta el código.
Dim aDistritos( -14 to -5 ) aDistritos(-14) = "46100" ' primer elemento de la matriz ... aDistritos(-5) = "46900" ' último elemento de la matriz
Primer y último elemento de una matriz
Las funciones LBound() y UBound() nos indican, respectivamente, el número índice del primer y del último elemento de una matriz.
Option Base 0 Sub Main Dim a(5), b(3 to 8) MsgBox "Matriz a: Primer elemento es " & LBound(a) MsgBox "Matriz a: Último elemento es " & UBound(a) MsgBox "Matriz b: Primer elemento es " & LBound(b) MsgBox "Matriz b: Último elemento es " & UBound(b) End Sub
Comprueba los resultados del mismo código, pero con Option Base puesto a 1.
Matrices multidimensionales
Se pueden declarar matrices de varias dimensiones. Para especificar el número de dimensiones, se indicarán el número de elementos de cada dimensión separados por comas, según la siguiente sintaxis:
Dim <nombre>([<ned_1>[,<ned_2>,...,<ned_n>]]) [As <tipo>]
donde ned_1 significa número de elementos de la dimensión 1, ..., ned_n significa número de elementos de la dimensión n
Por ejemplo, el siguiente código declara una matriz de dos dimensiones, de 3x12 = 36 elementos:
Dim aVentasTrienio(2,11)
Para asignar o leer valores de estas matrices multidimensionales se indicará el nombre de la matriz, seguida por un par de paréntesis que contendrán, separados por comas, el índice de cada dimensión, siendo obligatorio indicar un índice por cada dimensión.
Dim aVentasTrienio(2,11) aVentasTrienio(0,0) = 1000 ' Ventas año 1 mes 1 ... aVentasTrienio(1,8) = 3000 ' Ventas año 2 mes 9 ... aVentasTrienio(2,11) = 2800 ' Ventas año 3 mes 12 ... MsgBox "Las ventas del mes de agosto del segundo año fueron " & aVentasTrienio(1,7)
Se pueden definir matrices con cientos de dimensiones, pero en la práctica, la memoria disponible limita el número de dimensiones que se pueden tener en una matriz. Una matriz de 100 elementos por dimensión, y 3 dimensiones, contiene un total de 100x100x100 = 1.000.000 elementos.
Dim aMD(99,99,99) ' matriz de tres dimensiones, en total 1.000.000 de elementos
Matrices que contienen matrices
Una matriz puede contener uno o más elementos que a su vez sean una matriz. Por ejemplo:
Dim Matriz(2), subMatriz_1(11), subMatriz_2(4), subMatriz_3(5 to 8) Matriz(0) = subMatriz_1 Matriz(1) = subMatriz_2 Matriz(2) = subMatriz_3
Al asignar o leer un valor de uno de los elementos, se asigna o lee el valor del elemento de la submatriz contenida en el elemento de la matriz. La sintaxis a seguir es la siguiente: nombre de la matriz principal, seguido de un par de paréntesis conteniendo el número de elemento de la matriz principal, seguido por un par de paréntesis conteniendo el número de elemento de la submatriz.
Dim Matriz(4), subMatriz_C(11), subMatriz_X(4), subMatriz_J(5 to 8) Matriz(0) = "Datos de ventas" Matriz(1) = subMatriz_C Matriz(2) = subMatriz_X Matriz(3) = subMatriz_J Matriz(1)(0) = "Enero" ' elemento 0 de la SubMatriz_C ... Matriz(1)(11) = "Diciembre" ' elemento 11 de la SubMatriz_C ... Matriz(2)(3) = "Valencia" ' elemento 3 de la SubMatriz_X ... Matriz(3)(5) = 3000 ' elemento 0 de la SubMatriz_J ... Matriz(4) = "23/08/2012"