Matrices

En esta sección veremos cómo manipular muchos datos mediante una sola variable. Las matrices pueden ser de mucha utilidad o convertirse en un verdadero galimatías si no se manejan correctamente. Es importante que aprendas a utilizarlas pues muchas estructuras de LibreOffice Basic vienen implementadas en matrices.

La sintaxis más sencilla para una matriz es la siguiente:

Dim Nombre_Matriz( Tamaño As Integer ) As Tipo

Aquí también la variable debe cumplir las mismas condiciones que las mencionadas para nombrar las macros y las variables vistas anteriormente.

Entre sus características aparece el tamaño, que se refiere al número de elementos que contendrá la matriz, y el tipo de variable. En cuanto al tipo, he hecho la prueba con valores más grande que un Integer (Entero), pero no me imagino una macro que use tantos elementos, y si lo hay tal vez quiera decir que es hora de pasar a usar bases de datos.

No he encontrado documentación al respecto del límite de este valor. Estoy casi seguro que está condicionado más por el límite de la memoria Ram del equipo donde se ejecute que por otra causa. Te dejo a tu criterio, experiencia y pruebas el límite de elementos que quieras usar.

Hay matrices sencillas como una simple lista de valores, o complejas como aquellas formadas por una tabla de filas y columnas. Por ejemplo, podemos crear una matriz con una simple lista que enumere los días de la semana.

Y observa que con un simple bucle, podemos acceder a toda la matriz.

Nota que la matriz empieza en 0, que es la forma predeterminada. Podemos forzar a que las matrices empiecen en 1 usando la palabra clave Option Base de la siguiente manera. Al pulsar en Aceptar la ventana nos dirá el día de la semana siguiente desde el contador For co1 = 1 To 7.

Option Base no puede ir dentro de una macro, debe de ir al inicio de un módulo en el área de declaración de variables. La mayoría de las estructuras de LibreOffice Basic inician en 0, así que usaremos este valor de inicio como predeterminado en todo el libro. Si te es necesario un inicio o un fin diferente puedes usar la siguiente variante para la declaración de matrices.

Dim Nombre_Matriz( Inicio As Tipo To Fin As Tipo ) As Tipo

En donde Inicio puede ser incluso un valor negativo como en los ejemplos siguientes.

Observa que en los dos casos las matrices tienen diez elementos. En una lista guardamos números y en la otra texto, pero muy bien podemos combinar datos si declaramos la matriz como Variant, como en el siguiente ejemplo.

Notarás que en los casos vistos hasta ahora, para recorrer una matriz con un bucle habíamos establecido los valores superior e inferior de la matriz declarada previamente. En muchas ocasiones no conocerás los valores de inicio y fin de una matriz. LibreOffice Basic cuenta con dos funciones muy útiles para conocer estos valores.

En este ejemplo aprendemos cuatro nuevas funciones de LibreOffice Basic: Array, que nos permite crear una matriz introduciendo directamente los valores de que se compone (cada uno separado por una coma), LBound que nos devuelve el límite inferior de una matriz, UBound que nos devuelve el límite superior, y por último la función Str que convierte en cadena de texto (String) el argumento que le hayamos pasado. Usando LBound y UBound ni siquiera necesitamos conocer los límites de una matriz.

Puedes declarar una matriz de un determinado tamaño y usar Array para llenar la matriz con un número de elementos distinto al declarado. Veamos qué ocurre al ejecutar la macro.

Al observar los valores inferior y superior que nos devuelve cada matriz notamos que la matriz se redimensiona con el número de elementos que realmente contiene la función Array, no importándole el valor con el que hayamos declarado la matriz.

Cambiar de tamaño o de cantidad de elementos que puede contener una matriz de forma dinámica durante la ejecución de una macro es una tarea habitual de programación, por ello existen varias alternativas para lograr este propósito. LibreOffice Basic cuenta con una instrucción especifica para lograr esto, se llama ReDim y se usa de la siguiente manera.

Efectivamente, en el segundo bucle, solo nos muestra los valores de los índices 3 y 4. Esto se debe a que al redimensionar la matriz con ReDim se borran los valores que hayamos introducido previamente en la matriz. En ocasiones desearemos mantener los valores que existan, esto se logra agregando otra palabra clave (Preserve).

Pero ReDim no solo sirve para aumentar elementos, también sirve para disminuirlos. Sin embargo tiene el inconveniente de que ni aun usando Preserve se mantienen los valores previos, como lo demuestra el siguiente ejemplo.

Una solución es la propuesta siguiente.

Seguro que se te ocurre alguna otra solución. Como es una tarea habitual (el disminuir de tamaño una matriz y desear mantener los valores restantes), es una tarea idónea para convertirla en una subrutina o si lo deseas en una función como veremos más adelante en  Funciones y subrutinas. Aquí las dos formas y tú decides cuál usar:

Como una subrutina, en donde le pasamos la matriz a redimensionar y el nuevo tamaño que tendrá. Si es mayor solo redimensiona, si es menor copia los valores a mantener y redimensiona, si es igual la deja tal cual.

Como una función, que hace exactamente lo mismo, excepto que devuelve el valor en vez de manipular el parámetro pasado.

Ahora mostramos unas macros que invocan las macros anteriores, primero la subrutina y luego la función.

Podemos copiar una matriz en otra sencillamente con:

MatrizDestino() = MatrizOrigen()

También, observa el uso de la palabra clave Erase para borrar de la memoria las matrices dinámicas que ya no usemos. Si bien ahora la mayoría de las computadoras disponen de muchos megas de RAM, procura mantener el control de la cantidad de memoria que uses en tus macros.

Al copiar matrices de este modo, tienes que saber que estas quedan vinculadas, como se demuestra con la siguiente macro de ejemplo.

Puede que esto sea una característica o un error, pero tienes que considerarlo, pues en algunos algoritmos, los valores de las matrices se usan varias veces (sobre todo en ciclos) por lo que puedes llegar a obtener resultados erróneos si no consideras esta forma de trabajar las matrices por parte de LibreOffice Basic.

Hasta ahora hemos visto la declaración y el uso de matrices de una sola dimensión, es posible declarar y usar matrices de más de una dimensión. Veamos cómo se hace. La sintaxis para declarar matrices multidimensionales es la siguiente:

Dim Nombre_Matriz( Tamaño As Integer, Tamaño As Integer) As Tipo

Observa que ahora le indicamos dos tamaños separados por una coma, un ejemplo es más ilustrativo.

Piensa en las matrices de dos dimensiones como en una hoja de cálculo formada por filas y columnas. La matriz anterior quedaría así:

Por supuesto puedes declarar y usar matrices de más de dos dimensiones. Cuántas dimensiones, parece ser que el límite está determinado una vez más por la cantidad de memoria RAM de que disponga la computadora donde se ejecute la macro.

Otro ejemplo divertido, llenamos una matriz de 10 x 10 elementos y la llenamos con valores aleatorios de entre 1 y 100.

Como puedes observar la función Rnd() nos devuelve un número aleatorio entre 0 y 1, que al ser multiplicado por el valor superior que nos interesa y sumarle el valor inferior que nos interesa, nos da dicho número aleatorio comprendido entre estos dos. Así tenemos ahora el algoritmo que devuelve un número aleatorio entre dos valores dados.

Con las matrices de dos dimensiones podemos simular el uso de una pequeña base de datos o el uso de una hoja de cálculo donde guardamos una serie de datos en columnas que se denominan “campos” y filas que se denominan “registros”. Veamos un sencillo ejemplo.

Pero lo interesante y divertido es darle la oportunidad al usuario de ir capturando estos datos e ir creciendo la matriz según las necesidades de este, veamos cómo.

Observa atentamente que hacemos un poco de trampa al ir guardando los valores introducidos por el usuario en un variable temporal (sTmp), con lo cual no estamos muy seguros de que efectivamente los datos estén siendo guardados dentro de la matriz. Para corroborarlo, de tarea tienes que modificar la macro para que:

  • Te muestre tu directorio completo, llenando la variable sTmp después de salir del bucle. Para resolver esto tienes que hacer uso de la función UBound vista más arriba, pero con una pequeña variante: le tienes que indicar de qué dimensión quieres saber su límite superior, como en el ejemplo siguiente: MsgBox UBound( mDirectorio, 1 ) En donde nos mostrará el índice superior de la primera dimensión y así sucesivamente, si le estableces un número superior al de dimensiones que tiene la matriz te dará un error.
  • Obliga al usuario a introducir un nombre y teléfono, es decir, que no estén vacíos estos campos.
  • Por último, ingéniatelas para poder darle la oportunidad al usuario de borrar un registro. Es decir, tienes que encontrar la manera de preguntarle al usuario si quiere borrar un registro, y por supuesto, borrarlo efectivamente.

Reconozco que este último punto es  fácil implementarlo cuando uno va empezando, pero está dentro de lo posible y tus capacidades de investigación. Así que a trabajar.

Otra variante del uso de las matrices es tener matrices de matrices, es decir, tener dentro de una matriz otra matriz. Algunos autores a estas les llaman matrices escalares, veamos su uso.

Observa el uso de una variable temporal (mTmp) para asignar la matriz interna y así poder acceder a sus valores. Algunas funciones y estructuras de LibreOffice Basic que veremos más adelante, están implementadas de esta forma, es decir, como una matriz dentro de otra; de ahí la importancia de que las conozcas. Su uso es muy sencillo, veamos un ejemplo divertido de los que me gustan.

Analízala y verás que no es tan complejo como parece.

Tarea: modifica la macro de modo que le pregunte al usuario de cuántos caracteres quiere su contraseña. Ponle un rango mínimo y máximo que pueda escoger, digamos entre 5 y 50 caracteres.

Una segunda forma de acceder a los valores de una matriz de matrices es usando un doble índice como nos muestra el siguiente ejemplo.

Es muy importante que siempre valides los rangos de las matrices (UBound y LBound) cuando accedes por medio de sus índices, si el índice no existe te dará un error en tiempo de ejecución. También es importante que notes la diferencia entre una matriz multidimensional y una matriz de matrices.

A estas alturas ya te habrás dado cuenta de la cantidad de variantes que se pueden crear con unas cuantas instrucciones de LibreOffice Basic. Ahora queda a tu curiosidad e imaginación buscarle sus aplicaciones prácticas y las no tan prácticas ( que a veces son las más divertidas). Disfruta programando.