martes, 21 de noviembre de 2017

Trabajo con arrays en VBA para Excel


Un array (arreglo, matriz o composición ordenada) es una variable que puede almacenar y gestionar varios valores colocándolos en la memoria RAM de nuestro equipo en forma de matriz. Los arrays pueden tener una disposición matricial de una dimensión (como una simple lista de elementos), de dos dimensiones (en modo tabla, donde las filas son una de las dimensiones y las columnas la otra), pero también pueden tener una disposición en tres dimensiones (como un cubo) o incluso en n dimensiones.




En Excel, en la mayoría de casos se trabaja con arrays de 1 o de 2 dimensiones, Por ejemplo:




Los arrays se suelen utilizar para procesar grandes cantidades de datos de forma muy rápida. Están indicados en los casos en los que la información que hay en un conjunto de datos (normalmente un rango de Excel) debe ser procesada (reorganizada, calculada, modificada, etc.).

La filosofía de trabajo con un array debe ser clara:
  1. Crear el array
  2. Asignar valores (llenar el array) con la información (normalmente se hace mediante bucles For...Next)
  3. Volcar la información en un rango de Excel o en un objeto
1. Crear un array

OPCIÓN A). Solo declarar el array (y después dimensionarlo)

Por ejemplo:

   Dim miArray() As TipoDato
   ReDim miArray(miVariable, 7)

... o también...
   Dim miArray() As TipoDato
   ReDim miArray(3, Range("A1"))
 
Esta opción se utiliza cuando el número de elementos de cada dimensión no es conocido en el momento de escribir la línea de la declaración. Un ejemplo de esto es cuando ese número de elementos deben ser variables, constantes o referencias a rangos de Excel. Hay que tener en cuenta que, en principio, solo es posible dimensionar un array con un par de números. Es decir, el código siguiente no sería admitido:

   Dim miArray(miVariable,4) As Integer

Así pues, esta Opción A (como hemos visto anteriormente) consistiría en declarar el array con la instrucción Dim y posteriormente, dimensionarla con ReDim... ¡¡Qué SÍ permite variables, constantes y referencias a celdas!!.

 OPCIÓN B). Declarar el array y dimensionarlo al mismo tiempo

Por ejemplo:

   Dim miArray(6,3) As Integer

2. Asignar valores al array (llenarlo)

OPCIÓN A). Posición a posición con líneas de código

Por ejemplo:

   miArray(2,3) = Range("A1")
   miArray(4,3) = 836

OPCIÓN B). Posición a posición mediante un bucle

Por ejemplo:

   Dim miArray(6) As String

   For i = 1 To 6
      miArray(i) = i
   Next i

En esta fase de llenado o asignación de valores al array es cuando se puede procesar la información al mismo tiempo que se produce el llenado. Por ejemplo:

   Dim miArray(6) As String

   For i = 1 To 6
      miArray(i) =Left(Cells(i, 3)) & "-" & Right(Cells(i, 4))
   Next i

Con el código de arriba se llena la única columna de miArray* con los 3 caracteres de la izquierda de los datos que hay en las 6 primeras celdas de columna 3 de Excel, más un guion, más los 3 caracteres de la derecha que hay en las 6 primeras celdas de la columna 4 de Excel.

*Trabajando con arrays de una sola dimensión (una sola columna o fila) no es necesario especificar un par (x, y)

3. Volcar la información

Una vez que el array está lleno con la información procesada (si hubiera sido necesario), lo normal es volcar los datos en un Rango de Excel o en un objeto, como puede ser un combo - box o un cuadro de lista de un UserForm. Un ejemplo del primer caso sería:

Range("A1:A6")  = miArray

¡¡Atención!!, el rango destino debe tener el mismo tamaño (filas x columnas) que el array.
Otra cuestión que podemos apreciar en la última línea de código de ejemplo es que, al hacer referencia al array de forma global (no por posiciones), no es necesario aludir al par (x, y).



Los arrays tienen algunas ventajas frente a las variables - matriz:
  1. Los arrays pueden ser dimensionados para cualquier tipo de dato, no solo el tipo variant.
  2. Los arrays pueden ser llenados de valores uno a uno (posición a posición) desde la primera vez que se les asignan valores. Recordemos que las variables-matriz deben ser llenadas en bloque desde un rango de celdas de Excel.
  3. Los arrays pueden tener más de 2 dimensiones y, además, estas pueden ser variables, referencias a rangos, constantes, etc.

José Manuel Pomares Medrano











10 comentarios:

  1. Hola buen post, tengo un problema con el que me tope.
    estoy tratando de escribir un arreglo a un rango, el problema es que mi arreglo es de 250000 elementos, y al pasar al rango (ya lo intente de varias formas) siempre me pasa valores desde el elemento 1 hasta el 53392, a partir del 53393 me pone #N/A y asi hasta el ultimo. Sabes a que se debe?

    ResponderEliminar
    Respuestas
    1. Habría que conocer otras cosas, pero el motivo no es una limitación de los arrays. Por ejemplo, el siguiente código funciona:

      Sub pruebaArray()
      Dim MIArray() As Double
      ReDim MIArray(99999999, 1)
      MIArray(9999999, 1) = 1
      End Sub

      Saludos

      Eliminar
    2. Hola, es bastante abierta la interpretación que podría darse, pero empieza por el tipo de variable que definiste. El tipo Variant ayuda mucho, pero ocupa bastante memoria. Saludos.

      Eliminar
  2. necesito encontrar una sentencia para filtrar un valor con coincidencia exacta en "array".
    Gracias de manera anticipada.

    ResponderEliminar
    Respuestas
    1. Hola, probaste con el Método WorksheetFunction.Match?? Puedes investigar en soporte Microsoft, donde lo encontré. No sé si se podrá publicar el link, pero acá va:

      https://docs.microsoft.com/en-us/office/vba/api/excel.worksheetfunction.match

      o bien, compartirte un ejemplo que hallé:

      https://stackoverflow.com/questions/26457432/compare-2-arrays

      Suerte y saludos ;)

      Eliminar
  3. saludes desde Nicaragua. Quiero generar aleatoriamente nombres en un codigo, cual es el procedimiento, por favor. gracias

    ResponderEliminar
    Respuestas
    1. Sub NombreElegido()

      'la lista puede tomarse de un rango
      Dim N(12) As String

      N(1) = "Jorge": Range("A1").Value = N(1)
      N(2) = "Ana": Range("A2").Value = N(2)
      N(3) = "Juan": Range("A3").Value = N(3)
      N(4) = "Nicolas": Range("A4").Value = N(4)
      N(5) = "Patricia": Range("A5").Value = N(5)
      N(6) = "Alex": Range("A6").Value = N(6)
      N(7) = "Pablo": Range("A7").Value = N(7)

      For i = 8 To 10
      N(i) = InputBox("Inserte un nuevo nombre" & " (" & i - 7 & ")")
      Cells(i, 1).Value = N(i)
      Next

      primero = 1
      ultimo = 10
      Azar = WorksheetFunction.RandBetween(primero, ultimo)

      MsgBox ("El nombre elegido es: " & N(Azar))
      End Sub

      Te escribí ese... espero sirva...

      Eliminar
  4. Hola, si entendí bien, te sugiero que hagas una lista de nombres en una columna excel (por ejemplo un listado de nombres de una rifa), luego en la columna siguiente, con una función =ALEATORIO.ENTRE(1,100) desde el primer nombre hasta el último, paso siguiente copia los valores de esos resultados en una tercera columna (debido a que cambian con cada cáculo), y ordénalos de menor a mayor. Finalmente escoge los primeros 3 lugares u otro orden. De manera simple, respecto al código basta con el uso de la función WorksheetFunction.RandBetween(primero, ultimo).
    Espero haya ayudado. Suerte.

    ResponderEliminar
  5. Hola, estoy intentando realizar una macro genérica que de un fichero excel con múltiples columnas me coja algunas y me las ordena según un orden que yo quiero, que no tiene porque ser el mismo siempre, por eso lo de genérica. La idea más simple y sencilla cuando se trata de ficheros pequeños simplemente copiando y pegando se puede realizar pero los problemas vienen para ficheros con miles y miles de datos y que además valga para cualquier fichero. Se me ocurre entonces que sabiendo el orden que busco, si meto en un array la fila de los encabezados de las columnas que quiero en el orden que quiero. Posteriormente en la hoja que tengamos la tabla a ordenar voy recorriendo cada columna de esos datos hasta dar con la que tiene el mismo nombre, entonces la corta y la pega en la misma posición que toque y repetir este proceso con cada una. ¿Alguien sabe como podría realizar esto en código o se os ocurre otra forma de conseguir lo que busco? Muchisimas gracias por adelantado

    ResponderEliminar
  6. Quiero empezar este año con buen pie y pensé en hacer un curso de empleado de oficina en esta web https://cursos2023.com/c-cursos-de-empleado-de-oficina-2023 y me gustaría saber: ¿Si creen que hay buenas salidas para trabajar si lo curso?

    ResponderEliminar