Añadir un elemento al final de la matriz
Bien para aumentar un elemento, bien para completar el contenido de una matriz declarada inicialmente como matriz vacía, es necesario disponer de una función que nos permita añadir elementos a la matriz. OOo Basic no dispone de una función integrada que realice esta tarea, pero podemos crearla.
La comunidad [Open Office] ha publicado una función con este objetivo: aumentar el contenido de una matriz, añadiendo un elemento al final de la misma (1). Te la muestro y explico a continuación:
Function aAdd(ByRef a(), ByVal xValor)Dim u As Integeru = UBound(a()) + 1ReDim Preserve a(u)a(u) = xValoraAdd = a ()End Function
Aparentemente su funcionamiento es muy sencillo: aAdd() recibe dos parámetros obligatorios: el primero la matriz original (ByRef a()) y el segundo (ByVal xValor) el dato a añadir. Además cuenta con una variable privada (u) cuyo cometido es facilitar el cálculo de la nueva dimensión de la matriz, la cual se calcula haciendo uso de la función UBound() sobre la matriz-parámetro, valor al que se añade una unidad (u = UBound(a()) + 1).
Posteriormente se recalcula el tamaño de la matriz-parámetro mediante instrucciones (ReDim Preserve a(u)), haciendo uso del valor de u. Precisamente sobre el índice u se ejecuta la asignación del nuevo dato o contenido a la matriz redimensionada (a(u) = xValor) recurriendo, ahora, al segundo parámetro de la función, la cual finaliza con el return correspondiente (aAdd = a ())
En principio, la lógica de esta función es clara y correcta, pero, por desgracia el comportamiento de las instrucciones ReDim Preserve no es el esperado, produciéndose el vaciado de contenido de la matriz (2): el resultado es que, al aplicar la función obtenemos una matriz redimensionada, pero vacía.
Para superar esta muy seria limitación, he desarrollado una función alternativa (aFin()) que tiene el mismo objetivo, pero que elude el uso de la instrucción Preserve y modifica la lógica de la función "original". Si sintaxis es la siguiente:
Function aFin (ByRef mP(), ByVal fVal)Dim mS () As StringDim i As IntegerDim u As Integeru = uBound(mP()) + 1ReDim mS(u)For i = LBound(mP()) To UBound(mP())mS(i) = mP(i)NextmS(u) = fValaFin = mS()End Function
En cuanto a los parámetros, aFin() no se diferencia de aAdd(), como se puede ver (3), pero sí en lo relativo a las variables privadas: en aFin() se declaran una función auxiliar (mS()) y dos variables Integer, una (u) con idéntica función (y denominación) que en aAdd(), y otra (i) con función de contador para la implementación de un bucle For.
La primera acción que se desarrolla es el mismo proceso que en aAdd(), obtener sobre u la dimensión de la matriz, en base al valor que devuelve UBound() de la matriz-parámetro (u = uBound(mP()) + 1), como valor para redimensionar una matriz; pero con dos modificaciones de interés:
- La que se redimensiona es la matriz auxiliar (mS(u)), la matriz-parámetro, por lo que se evita que ésta pierda su contenido.
- Y sólo se usa la instrucción ReDim, ya que estamos hablando de una matriz vacía de contenido (ReDim mS(u))
Finalmente el return se realiza sobre esa matriz (aFin = mS())
Ahora te toca a ti idear un script que te permita comprobar el funcionamiento efectivo de ambas funciones, en las que, si lo deseas, puedes introducir modificaciones que las hagan más eficientes.
NOTAS
(1) Entre otras cosas, esto corrobora que efectivamente OOo Basic no dispone de una función Built-In que cumpla este objetivo. Siendo algo tan básico y necesario, no deja de ser ésta una carencia significativa.
(2) Esta "inconsistencia" ha sido detectada por diferentes autores, incluyendo a los mismos [creadores de esta función]. Por mi parte he comprobado que en ocasiones funcionan correctamente (redimensionan y mantienen el contenido original. [Ver aquí]), pero no en otras, como es el caso de la función aAdd(). Lo que no he encontrado en la literatura es una explicación del motivo, tan sólo la constatación un tanto sorprendida del fallo en el funcionamiento, que siempre es el no mantenimiento del contenido previo, lo que implica que la que no funciona como debiera es la instrucción Preserve, ya que ReDim sí lo hace según lo esperado.
(3) Sí modifico su denominación (Function aFin (ByRef mP(), ByVal fVal)), pero esto es secundario.
(4) Inicialmente intenté pasar los valores directamente (mS() = mP()), pero mS() perdía la dimensión dada mediante ReDim, por lo que no resultó viable. Al usar un bucle ajustado a la dimensión de mP(), el paso de datos se resuelve correctamente.