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

Offset en VBA en Excel — moverte en relación con una celda (Offset frente a Resize y la trampa del desfase por uno)

|

Offset en VBA en Excel — moverte en relación con una celda (Offset frente a Resize y la trampa del desfase por uno)

TL;DRrng.Offset(rowDelta, colDelta) devuelve un rango nuevo desplazado esas filas y columnas respecto de rng. Es un paso, no un lugar: conserva el mismo tamaño, no cambia rng y no selecciona nada. Los dos números son relativos: Offset(1, 0) es una fila hacia abajo, Offset(0, 0) es la propia celda y los negativos van hacia arriba o hacia la izquierda. Offset mueve; Resize cambia el tamaño. Júntalos y obtienes la fórmula de rangos más útil de todo VBA: data.Offset(1).Resize(data.Rows.Count - 1), «todo menos el encabezado».

Offset es la forma en que una macro dice «la celda de al lado de la que acabo de encontrar». Has localizado una coincidencia, un total, un encabezado; ahora quieres leer o escribir la celda una columna a la derecha o una fila más abajo. Ese movimiento relativo es todo el trabajo de Offset, y se vuelve algo natural en cuanto dejas de leer los argumentos como coordenadas y empiezas a leerlos como pasos.

Lo que aprenderás

  • El modelo mental: Offset es un paso relativo, no una dirección absoluta
  • La trampa del desfase por uno: por qué Offset(1, 1) cae en B2, no en A1
  • Offset conserva el tamaño; Resize lo cambia, y por qué casi siempre necesitas los dos
  • La fórmula para saltar el encabezado Offset(1).Resize(n - 1), explicada
  • En qué se diferencia Range.Offset (VBA) de la función de hoja de cálculo OFFSET()

El modelo mental: Offset es un paso, no un lugar

Plántate en una celda. Offset(rowsDown, colsRight) da esos pasos y te entrega la celda (o el bloque) en la que aterrizas: un rango totalmente nuevo. El original queda intacto. Como el movimiento es relativo, el mismo Offset(1, 0) significa «una fila hacia abajo» tanto si partes de A1 como de Z500.

Sub OffsetSteps()
    Debug.Print Range("B2").Offset(1, 0).Address   ' -> $B$3   (una fila hacia abajo)
    Debug.Print Range("B2").Offset(0, 1).Address   ' -> $C$2   (una columna a la derecha)
    Debug.Print Range("B2").Offset(-1, 0).Address  ' -> $B$1   (una fila hacia arriba)
    Debug.Print Range("B2").Offset(0, 0).Address   ' -> $B$2   (sin movimiento)
End Sub

Fíjate en que Offset(0, 0) es la propia celda. Esa es la señal de que son deltas, no posiciones. Si quieres una celda absoluta, no calcules un desplazamiento a partir de A1: usa Cells(row, col). Offset es para «en relación con algo que ya tengo».

La regla que pilla a los principiantes: la trampa del desfase por uno

El error número uno con Offset es leer los argumentos como una coordenada. Offset(1, 1) no significa la celda A1 ni «fila 1, columna 1». Significa una fila hacia abajo y una columna a la derecha desde la celda ancla. Desde A1, eso cae en B2.

Range("A1").Offset(1, 1).Address   ' -> $B$2, NO $A$1
Range("A1").Offset(0, 0).Address   ' -> $A$1

Di los dos argumentos en voz alta como «abajo, derecha» cada vez y el error desaparece. También explica el patrón de bucle clásico: para escribir un resultado junto a cada fila que encuentras, desplazas por el contador del bucle, y la primera fila usa Offset(0, …), no Offset(1, …).

La distinción que hace tropezar a todos: Offset mueve, Resize cambia el tamaño

Offset nunca cambia el tamaño de un rango: desliza la forma entera. Mueve una columna de diez celdas y obtienes una columna de diez celdas en otro sitio:

Range("A1:A10").Offset(0, 1).Address   ' -> $B$1:$B$10   (10 celdas, movidas a la derecha)

Para cambiar el tamaño de un rango necesitas otro método, Resize(rows, cols), que vuelve a dibujar el bloque desde su celda superior izquierda:

Range("A1").Resize(5, 2).Address       ' -> $A$1:$B$5   (5 filas, 2 columnas)

Son las dos mitades de la aritmética de rangos: Offset elige dónde, Resize elige cómo de grande. Echas mano de los dos juntos constantemente, casi siempre para descartar una fila de encabezado.

La fórmula que vale la pena memorizar: saltar el encabezado con Offset + Resize

Tienes una tabla que incluye su encabezado y quieres solo el cuerpo de datos. Desplázate una fila hacia abajo para salir del encabezado, pero Offset por sí solo conserva la misma altura, así que el rango ahora se extiende una fila más allá de los datos. Resize lo encoge de vuelta esa fila:

Sub DataBodyOnly()
    Dim tbl As Range, body As Range
    Set tbl = Range("A1").CurrentRegion          ' encabezado + datos
    Set body = tbl.Offset(1).Resize(tbl.Rows.Count - 1)
    body.Select                                  ' solo filas de datos, sin encabezado
End Sub

Offset(1) (el delta de columna vale 0 por defecto) desliza el bloque entero una fila hacia abajo; Resize(tbl.Rows.Count - 1) recorta la fila inferior que ahora sobresale. El resultado es el cuerpo de datos con el encabezado eliminado: el rango exacto que quieres ordenar, copiar o limpiar. Esta única línea sustituye un montón de A2:A armado a mano. Para encontrar tbl sin codificarlo a mano, mira cómo encontrar la última fila y CurrentRegion.

La trampa del borde de la hoja

Como Offset es relativo, dar un paso más allá del borde de la hoja es un error, no un recorte silencioso:

Range("A1").Offset(-1, 0)   ' error en tiempo de ejecución 1004 — no se puede subir de la fila 1

Si una macro sube o va hacia la izquierda cerca de la esquina superior izquierda (algo habitual al buscar encabezados), protege el movimiento o comprueba rng.Row > 1 antes de desplazarte hacia arriba.

Offset, el método, frente a OFFSET, la función de hoja de cálculo

Comparten nombre y la misma idea, pero no son la misma herramienta. La función de hoja de cálculo OFFSET() vive en una celda, es volátil (se recalcula con cada cambio, lo que puede ralentizar un libro) y devuelve un valor o una referencia para una fórmula. Range.Offset es un método de VBA: devuelve un objeto Range, no es volátil y solo se ejecuta cuando se ejecuta tu código. Si estás escribiendo una macro, usa el método; recurre a la función de hoja de cálculo solo cuando necesites una referencia viva y autoactualizable dentro de una fórmula.

Cómo ayuda ExcelMaster

El código cargado de Offset suele construir una sola cosa: un resultado colocado en relación con algo que encontraste —una marca junto a cada coincidencia, un acumulado una columna más allá, un valor copiado de la fila que hay debajo de una etiqueta—. ExcelMaster toma esa intención en lenguaje natural —«junto a cada factura vencida, escribe los días de retraso»— y genera la lógica de referencias relativas, para que no tengas que contar deltas a mano ni depurar un desfase por uno.

Seguirás escribiendo Offset dentro de un bucle de macro ajustado. Pero para la tarea cotidiana de «pon un resultado al lado de cada fila», describir la ubicación es más rápido y más difícil de equivocar que razonar sobre (1, 0) frente a (0, 1).

Preguntas frecuentes

¿Qué hace Offset en VBA?

rng.Offset(rowDelta, colDelta) devuelve un rango nuevo desplazado esas filas y columnas respecto de rng, conservando el mismo tamaño. Es un movimiento relativo: Offset(1, 0) es una fila hacia abajo, Offset(0, 1) es una columna a la derecha y los números negativos mueven hacia arriba o hacia la izquierda. No cambia ni selecciona el rango original.

¿Por qué Offset(1, 1) no devuelve la celda A1?

Porque los argumentos son deltas, no coordenadas. Offset(1, 1) significa una fila hacia abajo y una columna a la derecha desde la celda ancla, así que Range("A1").Offset(1, 1) es B2. Usa Cells(row, col) cuando quieras una celda absoluta en lugar de un paso relativo.

¿Cuál es la diferencia entre Offset y Resize?

Offset mueve un rango sin cambiar su tamaño; Resize(rows, cols) cambia el tamaño desde la celda superior izquierda sin moverlo. A menudo los combinas: rng.Offset(1).Resize(rng.Rows.Count - 1) salta una fila de encabezado bajando una fila y encogiendo una.

¿Cómo salto la fila de encabezado con Offset?

Usa table.Offset(1).Resize(table.Rows.Count - 1). Offset(1) mueve el bloque hacia abajo más allá del encabezado; Resize recorta la fila que ahora sobresale por abajo, dejando solo el cuerpo de datos.

¿Es lo mismo Range.Offset de VBA que la función OFFSET de hoja de cálculo?

No. Range.Offset es un método de VBA que devuelve un objeto Range y no es volátil. La función de hoja de cálculo OFFSET() vive en una celda, es volátil (se recalcula constantemente) y devuelve un valor o una referencia para fórmulas. Usa el método en macros; usa la función solo para referencias vivas en fórmulas.

Probado en

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

Guías relacionadas: VBA Última fila · VBA UsedRange frente a CurrentRegion · VBA Range · Función OFFSET de hoja de cálculo