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

VBA ReDim en Excel — Redimensionar arrays con ReDim y ReDim Preserve

|

VBA ReDim en Excel — Redimensionar arrays con ReDim y ReDim Preserve

TL;DR — Un array de VBA fija su tamaño en el momento en que lo declaras con Dima menos que dejes los corchetes vacíos—. Dim a() declara un array dinámico que aún no tiene tamaño; ReDim a(1 To 10) le da uno. Un ReDim a secas descarta todos los valores que contenía, así que para ampliar un array sin perder datos usas ReDim Preserve. La trampa: en un array bidimensional, ReDim Preserve solo puede redimensionar la última dimensión. Los arrays de tamaño fijo (Dim a(1 To 10)) no se pueden redimensionar con ReDim nunca.

Sub GrowAnArray()
    Dim a() As Long                 ' dinamico - aun sin tamano
    ReDim a(1 To 3)                 ' ahora contiene 3 Longs
    a(1) = 10: a(2) = 20: a(3) = 30

    ReDim Preserve a(1 To 5)        ' ampliar a 5, CONSERVA 10, 20, 30
    a(4) = 40: a(5) = 50            ' un ReDim a secas aqui habria borrado 10-30
End Sub

ReDim es toda la historia de los arrays dinámicos. Declara el array abierto con Dim a(), dale tamaño con ReDim, pregúntale cómo de grande es con UBound y —para una cuadrícula— recuerda que solo la última dimensión puede crecer (ver VBA 2D Arrays). Equivócate con ReDim y tus datos desaparecen en silencio, así que vale la pena entender cuándo el tamaño es fijo y cuándo no.

Lo que aprenderás

  • La única decisión que gobierna cada array — tamaño fijo en el Dim, o abierto con Dim a()
  • Por qué ReDim da tamaño a un array dinámico, y por qué un ReDim a secas borra todo lo que contenía
  • ReDim Preserve — cómo ampliar un array y conservar los datos
  • La trampa número uno: ReDim Preserve solo puede redimensionar la última dimensión de un array 2D
  • Por qué no puedes hacer ReDim de un array de tamaño fijo, y qué hace Erase en realidad
  • Por qué ampliar un array fila a fila dentro de un bucle es lento, y qué hacer en su lugar

El modelo mental: fijo en el Dim, o abierto con corchetes vacíos

Todo array de VBA es de uno de dos tipos, y eliges cuál en la declaración:

Dim fixed(1 To 10) As Long   ' FIJO - 10 huecos, para siempre; el tamano es parte del tipo
Dim flex() As Long           ' DINAMICO - aun sin tamano; le haras ReDim mas tarde

Un array de tamaño fijo se dimensiona una vez y no cambia nunca —el tamaño vive en la declaración, así que VBA no te dejará hacerle ReDim más tarde (obtienes el error de compilación «Array already dimensioned»)—. Un array dinámico se declara con corchetes vacíos: tiene un tipo pero no un tamaño, y ReDim es como le das uno. Esa única elección —corchetes llenos o vacíos en el Dim— decide todo lo demás de esta página. Si aún no sabes cuántos elementos tendrás, decláralo abierto.

ReDim da tamaño a un array dinámico

ReDim reserva almacenamiento nuevo para un array dinámico. Puedes hacer ReDim del mismo array tantas veces como quieras, y cada ReDim puede incluso cambiar los límites:

Dim a() As String
ReDim a(1 To 3)      ' 3 elementos, indexados 1..3
ReDim a(0 To 99)     ' ahora 100 elementos, indexados 0..99

Hay una cosa que debes tener presente, y es el origen de la mayoría de los fallos de «mis datos han desaparecido»: un ReDim a secas reinicializa el array entero. Cada elemento vuelve a su valor por defecto —0 para los números, "" para las cadenas, Nothing para los objetos— como si lo acabaras de crear:

Dim a() As Long
ReDim a(1 To 3)
a(1) = 10: a(2) = 20: a(3) = 30
ReDim a(1 To 5)      ' a(1..3) ahora vuelven a ser 0 - los valores DESAPARECIERON

Si querías conservar los datos, para eso está exactamente Preserve.

ReDim Preserve: ampliar sin perder datos

ReDim Preserve copia los valores existentes en el array redimensionado antes de devolvértelo:

Dim a() As Long
ReDim a(1 To 3)
a(1) = 10: a(2) = 20: a(3) = 30
ReDim Preserve a(1 To 5)   ' a(1..3) aun contienen 10, 20, 30; a(4), a(5) son 0

Recurre a Preserve siempre que estés extendiendo un array que ya has rellenado. Funciona cuando amplías y cuando reduces —al reducir simplemente se descartan los elementos que quedan más allá del nuevo límite superior—. La única regla que debes respetar es sobre las dimensiones, y es donde casi todo el mundo cae.

La trampa número uno: Preserve solo redimensiona la última dimensión

En un array unidimensional, ReDim Preserve es libre de cambiar el límite. En un array bidimensional, ReDim Preserve solo puede cambiar la última dimensión. Intenta cambiar la primera y VBA lanza el error de ejecución 9, «Subscript out of range»:

Dim g() As Long
ReDim g(1 To 3, 1 To 2)          ' 3 filas, 2 columnas
ReDim Preserve g(1 To 5, 1 To 2) ' error 9 - no se puede redimensionar la PRIMERA dimension
ReDim Preserve g(1 To 3, 1 To 4) ' OK - la ULTIMA dimension (columna) puede crecer

Esto no es un fallo que puedas sortear con un ReDim más ingenioso; es cómo VBA almacena los arrays en memoria. Además choca con la intuición, porque una hoja es filas × columnas, así que el «crecer» que normalmente quieres —añadir filas— es la primera dimensión, la que no tienes permitido tocar. Dos salidas: declara la cuadrícula como columnas × filas para que la dimensión que amplías sea la última o, más habitualmente, dimensiona el array una sola vez a su recuento final de filas antes del bucle y prescinde de Preserve por completo. Si de verdad tienes que añadir filas a un array 2D existente, lo reconstruyes (o transpones, redimensionas la última dimensión y vuelves a transponer). Hay más sobre esto en VBA 2D Arrays.

No puedes hacer ReDim de un array de tamaño fijo

ReDim es solo para arrays declarados con corchetes vacíos. Si dimensionaste el array en su Dim, el tamaño queda grabado en la declaración y ReDim es un error de compilación:

Dim a(1 To 10) As Long
ReDim a(1 To 20)      ' error de compilacion - "Array already dimensioned"

Si te encuentras con ganas de redimensionar un array, esa es la señal de que debería haberse declarado dinámico (Dim a()) desde el principio. Un array dinámico al que haces ReDim una sola vez, justo después de conocer el recuento, te da lo mejor de ambos mundos: un tamaño de trabajo fijo y limpio, elegido en tiempo de ejecución.

Erase: reiniciar o liberar

Erase hace dos cosas distintas según el tipo de array. En un array de tamaño fijo reinicia cada elemento a su valor por defecto pero mantiene el array del mismo tamaño. En un array dinámico va más allá —libera la memoria y devuelve el array a su estado sin tamaño, como si solo hubieras escrito Dim a()—:

Dim fixed(1 To 3) As Long
Erase fixed            ' los tres elementos vuelven a ser 0; sigue con tamano 3

Dim flex() As Long
ReDim flex(1 To 3)
Erase flex             ' memoria liberada; flex vuelve a no tener tamano - haz ReDim antes de reusar

Después de hacer Erase de un array dinámico, llamar a UBound sobre él lanza el error 9 hasta que le vuelvas a hacer ReDim —el array genuinamente no tiene límites que reportar—.

Dimensiona una vez, no amplíes de uno en uno

Como cada ReDim Preserve reserva un bloque nuevo y copia el contenido antiguo en él, ampliar un array de uno en uno en cada pasada de un bucle convierte un trabajo O(n) en uno O(n²) —bien para 50 elementos, doloroso para 50.000—. La solución idiomática es dimensionar el array una sola vez, de antemano, usando un recuento que ya tienes (una última fila, el tamaño de una colección), y recortar solo al final si hace falta:

Dim a() As Long, n As Long, i As Long
n = Cells(Rows.Count, 1).End(xlUp).Row   ' cuantas filas de datos hay
ReDim a(1 To n)                          ' una sola reserva
For i = 1 To n
    a(i) = Cells(i, 1).Value
Next i

Cuando de verdad no puedes conocer el recuento de antemano, un patrón habitual es hacer ReDim en bloques generosos (por ejemplo, duplicar el tamaño cuando te quedas sin espacio) y ReDim Preserve hasta el recuento exacto una sola vez al final —muchísimas menos copias que ampliar de uno en uno cada vez—.

Cómo te ayuda ExcelMaster

Toda la historia de ReDim es una decisión —¿este array es de tamaño fijo, o crece?— y los dos errores clásicos son un ReDim a secas que borra tus datos en silencio y un ReDim Preserve que se topa con el error 9 en la dimensión equivocada.

ExcelMaster te deja describir la tarea —«lee la columna A en un array, conserva los valores no vacíos, escríbelos en la columna C»— y declara el array dinámico, lo dimensiona una sola vez a partir del recuento real de filas, usa ReDim Preserve solo donde la dimensión lo permite, y lee el rango de una sola vez en lugar de celda a celda. Tú conservas el libro y el código.

Preguntas frecuentes

¿Qué hace ReDim en VBA?

ReDim establece o cambia el tamaño de un array dinámico —uno declarado con corchetes vacíos, como Dim a() As Long—. ReDim a(1 To 10) da al array diez elementos. Puedes hacer ReDim del mismo array repetidamente, y cada ReDim puede cambiar los límites. Un ReDim a secas también reinicializa cada elemento a su valor por defecto, así que usa ReDim Preserve cuando necesites conservar los datos existentes.

¿Cuál es la diferencia entre ReDim y ReDim Preserve?

Un ReDim a secas reserva el nuevo tamaño y borra cada elemento devolviéndolo a su valor por defecto, descartando lo que fuera que contuviera el array. ReDim Preserve copia primero los valores existentes en el array redimensionado, así que los datos sobreviven. Usa el ReDim a secas para el primer dimensionado, y ReDim Preserve siempre que estés extendiendo un array que ya has rellenado.

¿Por qué ReDim Preserve da el error 9 en un array 2D?

Porque ReDim Preserve solo puede redimensionar la última dimensión de un array multidimensional. Cambiar la primera dimensión lanza el error de ejecución 9, «Subscript out of range». Para añadir «filas» a una cuadrícula, o bien la declaras como columnas × filas para que la dimensión que crece sea la última, la dimensionas a su recuento final de filas antes del bucle, o reconstruyes el array.

¿Puedo hacer ReDim de un array de tamaño fijo?

No. Si declaraste el array con un tamaño, como Dim a(1 To 10), ese tamaño es parte del tipo y ReDim es un error de compilación, «Array already dimensioned». Solo los arrays declarados con corchetes vacíos (Dim a()) se pueden dimensionar y redimensionar con ReDim.

¿Cómo añado un elemento a un array de VBA?

Lleva tú mismo la cuenta y usa ReDim Preserve para hacer sitio: ReDim Preserve a(1 To n + 1): a(n + 1) = value: n = n + 1. Esto funciona, pero redimensionar en cada elemento es lento porque cada ReDim Preserve copia el array entero. Para bucles grandes, dimensiona el array una sola vez a partir de un recuento conocido, o amplíalo en bloques y recorta una vez al final. Una Collection suele ser más sencilla cuando el recuento es de verdad desconocido.

Probado en

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

Guías relacionadas: VBA UBound · VBA 2D Arrays · VBA Array · VBA Dim · VBA For Loop