🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA 2D Arrays en Excel — Arrays bidimensionales, cuadrículas y Range.Value

|

VBA 2D Arrays en Excel — Arrays bidimensionales, cuadrículas y Range.Value

TL;DR — Un array 2D de VBA es un array con dos subíndices —una cuadrícula de filas y columnas, g(row, column)—, no un array de arrays. Dim g(1 To 3, 1 To 4) es tres filas por cuatro columnas. El dato más útil con diferencia para trabajar en Excel: leer Range("A1:D3").Value te entrega un array Variant bidimensional indexado desde 1 en un solo paso, y escribir un array de vuelta con Range(...).Value = arr lo escribe en un solo paso —por eso el procesamiento con arrays es drásticamente más rápido que iterar celda a celda—.

Sub SheetToArrayAndBack()
    Dim data As Variant
    data = Range("A1:D100").Value          ' un solo acceso a la hoja -> array 2D indexado desde 1

    Dim r As Long
    For r = 1 To UBound(data, 1)           ' filas
        data(r, 4) = data(r, 2) * data(r, 3)   ' col D = col B * col C, en memoria
    Next r

    Range("A1:D100").Value = data          ' un solo acceso de vuelta -> instantaneo
End Sub

Un array 2D es donde se encuentran los arrays y las hojas de cálculo: una hoja es una cuadrícula, y la forma más rápida de trabajar con un bloque de celdas es meterlo en un array 2D, calcular en memoria y escribirlo de vuelta. Se apoya directamente en dimensionar arrays con ReDim y leer su forma con UBound —una cuadrícula simplemente tiene un límite por dimensión—. Lo único que hace tropezar a la gente es que los arrays de Range.Value están indexados desde 1, y que ReDim Preserve no puede añadir filas.

Lo que aprenderás

  • El modelo mental — una cuadrícula con dos subíndices, g(row, column), no arrays anidados
  • Declarar y direccionar un array 2D con Dim g(1 To 3, 1 To 4) y g(r, c)
  • El gordo: Range.Value te da un array Variant 2D indexado desde 1 en un solo paso
  • Escribir un array de vuelta a un rango de una sola vez —y por qué eso es mucho más rápido—
  • Dos casos límite: una sola celda no es un array, y una sola columna es (n, 1)
  • Añadir filas: por qué ReDim Preserve no puede, y qué hacer en su lugar
  • En qué se diferencia un «array de arrays» escalonado de un verdadero array 2D

El modelo mental: un array, dos subíndices

Un array unidimensional es una fila numerada de cajas: a(i). Un array bidimensional es una cuadrícula —direccionas cada caja con dos números, una fila y una columna: g(r, c)—. Y lo fundamental: es un único array que resulta estar direccionado de dos formas, no una lista cuyos elementos son a su vez listas:

Dim g(1 To 3, 1 To 4) As Long   ' 3 filas, 4 columnas = 12 elementos
g(1, 1) = 10                     ' fila 1, columna 1
g(3, 4) = 99                     ' fila 3, columna 4

El primer subíndice es por convención la fila, el segundo la columna —el mismo orden en que lees una referencia de celda—. Mantén ese orden coherente y un array 2D se corresponde limpiamente con un bloque rectangular de celdas.

Declarar y recorrer una cuadrícula

Declara los dos límites, luego itera con un For anidado —el externo sobre las filas, el interno sobre las columnas— usando UBound con un número de dimensión:

Dim g(1 To 3, 1 To 4) As Long
Dim r As Long, c As Long
For r = LBound(g, 1) To UBound(g, 1)       ' filas
    For c = LBound(g, 2) To UBound(g, 2)   ' columnas
        g(r, c) = r * 10 + c
    Next c
Next r

UBound(g, 1) es el recuento de filas, UBound(g, 2) el de columnas. Iterar de LBound a UBound en cada dimensión significa que el mismo código funciona tanto si el array es 1 To n (como te lo da Range.Value) como si está indexado desde cero.

El gordo: Range.Value es un array 2D indexado desde 1

Este es el dato que hace que valga la pena aprender los arrays 2D. Leer el .Value de un rango de varias celdas te da, en un solo paso, un array Variant bidimensional cuyos límites empiezan en 1 —independientemente de dónde esté el rango en la hoja—:

Dim data As Variant
data = Range("C5:E7").Value      ' un bloque de 3 filas y 3 columnas en cualquier parte de la hoja
' data es ahora data(1 To 3, 1 To 3) - SIEMPRE indexado desde 1, fila y luego columna
Debug.Print data(1, 1)          ' el valor de C5
Debug.Print data(3, 3)          ' el valor de E7

Fíjate en dos cosas. Primero, el array está indexado desde 1, no desde 0 —así que data(1, 1) es la celda superior izquierda, y un bucle For i = 0 se saltaría la primera fila y se toparía con el error 9—. Segundo, los índices son relativos al bloque, no a la hoja: data(1, 1) es la celda superior izquierda del rango tanto si el rango es A1 como C5. Declara la variable receptora como Variant (no As Long() etc.) —VBA te rellena un Variant 2D nuevo—.

Escríbelo de vuelta de una sola vez

El mismo truco funciona a la inversa. Asigna un array 2D con la forma correcta al .Value de un rango y Excel escribe el bloque entero de golpe:

Range("C5:E7").Value = data     ' escribe las 9 celdas en una sola operacion

Por eso el enfoque con arrays es rápido. Tocar las celdas de una en una cruza la frontera entre VBA y Excel en cada lectura y escritura —miles de idas y vueltas para un rango grande—. Leer en un array, calcular en memoria y escribir de vuelta significa solo dos cruces en total. Para cualquier cosa que pase de unos cientos de celdas, esta es la diferencia entre una macro que se siente instantánea y otra que ves avanzar a duras penas. El rango escrito debe coincidir con la forma del array (filas × columnas), así que dimensiona el rango de destino a UBound(arr, 1) filas por UBound(arr, 2) columnas.

Dos casos límite que muerden

Una sola celda no es un array. Range("A1").Value devuelve un escalar corriente, no un array 1 To 1, 1 To 1 —así que el código que da por hecho un array fallará en un rango de una sola celda—. Si el rango pudiera ser una sola celda, compruébalo con IsArray() antes de indexarlo.

Una sola fila o columna sigue siendo 2D. Range("A1:A10").Value es data(1 To 10, 1 To 1) —diez filas, una columna— así que sigues direccionándolo como data(i, 1), no data(i). Lo mismo vale para una sola fila: data(1, j). Es fácil olvidar el segundo subíndice en una porción «unidimensional» de una hoja.

Añadir filas: ReDim Preserve no puede

Como ReDim Preserve solo redimensiona la última dimensión, no puedes ampliar el recuento de filas (la primera dimensión) de un array 2D conservando los datos. Tres opciones prácticas:

  • Dimensiona una vez. Si conoces el recuento de filas de antemano (una última fila, un recuento de registros), haz ReDim de la cuadrícula a su tamaño final antes del bucle y nunca uses Preserve.
  • Amplía las columnas en su lugar. Declara el array como columnas × filas para que la dimensión que extiendes sea la última, luego transpón a la salida con Application.Transpose.
  • Reconstruye. Para un crecimiento de verdad desconocido, recopila en una Collection o una estructura escalonada y construye el array 2D una sola vez al final.

Para el trabajo con hojas casi siempre aplica la primera opción, porque el recuento de filas es algo barato de averiguar antes de empezar.

Los arrays escalonados son otra cosa

Un verdadero array 2D es rectangular —cada fila tiene el mismo número de columnas—. Un array escalonado es un array unidimensional cuyos elementos son a su vez arrays, así que cada «fila» puede tener una longitud distinta. Lo direccionas con dos pares de corchetes, no con dos subíndices:

Dim jagged(1 To 2) As Variant
jagged(1) = Array(1, 2, 3)      ' una fila de 3 elementos
jagged(2) = Array(9, 8)         ' una fila de 2 elementos
Debug.Print jagged(1)(3)        ' 3   <- dos pares de corchetes, no (1, 3)

Los arrays escalonados son útiles para datos irregulares, pero no interoperan con Range.Value, que siempre es rectangular. Cuando los datos son un rectángulo —que es lo que siempre es un bloque de hoja— recurre a un verdadero array 2D.

Cómo te ayuda ExcelMaster

Trabajar con un bloque de celdas de forma eficiente es un solo patrón —leer Range.Value en un array 2D indexado desde 1, calcular en memoria, escribirlo de vuelta de una sola vez— y las trampas están todas en los detalles: el índice desde 1, el escalar de una sola celda, la fila que no puedes ampliar con Preserve.

ExcelMaster te deja describir la tarea —«para cada fila del rango usado, pon cantidad por precio en la columna E»— y lee el bloque en un array 2D, itera de 1 a UBound(arr, 1), escribe el resultado de vuelta en una sola asignación, y gestiona los casos de una sola celda y una sola columna, así que la macro es a la vez correcta y rápida. Tú conservas el libro y el código.

Preguntas frecuentes

¿Cómo declaro un array 2D en VBA?

Da dos límites separados por una coma: Dim g(1 To 3, 1 To 4) As Long crea una cuadrícula de tres filas y cuatro columnas. Direcciona un elemento con dos subíndices, g(row, column), por ejemplo g(2, 3). Para un array 2D dinámico, decláralo abierto con Dim g() y dimensiónalo más tarde con ReDim g(1 To 3, 1 To 4).

¿Cómo leo un rango en un array 2D en VBA?

Asigna el .Value del rango a un Variant: Dim data As Variant: data = Range("A1:D100").Value. VBA rellena un array bidimensional indexado desde 1, data(1 To rows, 1 To columns), en un solo paso. Direcciona las celdas como data(row, column), donde los índices son relativos a la esquina superior izquierda del rango. Esta es la forma más rápida de procesar muchas celdas.

¿Por qué mi array de Range.Value está indexado desde 1 en lugar de desde 0?

Porque así es como lo devuelve Excel —un array de Range.Value siempre empieza en el índice 1 en ambas dimensiones, sin importar dónde esté el rango en la hoja—. Itera de LBound(data, 1) a UBound(data, 1) (o simplemente 1 To UBound) para no saltarte la primera fila ni salirte del final con un bucle indexado desde 0.

¿Cómo escribo un array 2D de vuelta a un rango?

Asígnalo al .Value del rango: Range("A1:D100").Value = data. El rango debe tener la misma forma que el array —el mismo número de filas y columnas— así que dimensiona el destino con UBound(data, 1) filas y UBound(data, 2) columnas. Esto escribe el bloque entero en una sola operación, mucho más rápido que celda a celda.

¿Puedo añadir una fila a un array 2D en VBA?

No con ReDim Preserve —solo puede redimensionar la última dimensión (la de columnas), así que ampliar el recuento de filas lanza el error 9—. O bien dimensionas el array a su recuento final de filas antes del bucle, lo declaras como columnas × filas y transpones, o lo construyes a partir de una Collection y creas el array 2D una sola vez al final.

Probado en

Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 24/09/2026.

Guías relacionadas: VBA ReDim · VBA UBound · VBA Array · VBA For Loop · VBA Range