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

VBA Range en Excel — referenciar, leer y escribir celdas (8 ejemplos)

|

VBA Range en Excel — referenciar, leer y escribir celdas (8 ejemplos)

Probado en: Excel 365 v2509 · Excel 2021 · Excel 2019 · última verificación 05/06/2026

En resumenRange es el objeto que apunta a una o varias celdas. Se lee con .Value y se escribe igual. No hace falta .Select:

Sub FundamentosRange()
    ' LEER una sola celda
    Dim cantidad As Long
    cantidad = Range("B2").Value

    ' ESCRIBIR una sola celda
    Range("C2").Value = cantidad * 1.1

    ' ESCRIBIR un bloque entero de una vez (sin bucle)
    Range("A1:C1").Value = Array("Producto", "Cantidad", "Precio")
End Sub

Todo lo demás — Cells, End, CurrentRegion, Resize — es solo otra forma de indicarle a Range las celdas que quieres. Esta guía muestra las ocho que de verdad usarás.

Todos los ejemplos parten de una pequeña tabla en Hoja1: encabezados Producto / Cantidad / Precio en A1:C1, datos desde la fila 2.

Qué es realmente el objeto Range

Range es el objeto más usado de Excel VBA. Representa una celda, un bloque de celdas, una fila o columna entera, o incluso varios bloques separados. Casi todo lo que haces — leer un valor, escribir una fórmula, cambiar un color, copiar, ordenar — es un método o una propiedad que llamas sobre un Range.

Range("A2").Value = "Widget"                ' propiedad de una celda
Range("A2:C2").Interior.Color = vbYellow    ' propiedad de tres celdas
Range("A:A").Columns.AutoFit                ' propiedad de una columna entera

Ejemplo 1 — Range frente a Cells (cuál usar)

Ambos apuntan a celdas. La diferencia está en cómo las direccionas.

Ideal para Sintaxis
Range("A2") Una dirección fija y legible dirección de texto, como el Cuadro de nombres
Cells(2, 1) Una posición calculada a partir de números Cells(fila, columna)fila primero
' Estas dos líneas tocan la MISMA celda (fila 2, columna 1):
Range("A2").Value = "Widget"
Cells(2, 1).Value = "Widget"

Usa Range cuando conozcas la dirección. Usa Cells dentro de bucles, donde la fila o la columna es una variable:

Dim f As Long
For f = 2 To 6
    Cells(f, 3).Value = Cells(f, 2).Value * 1.1   ' Precio = Cantidad * 1.1
Next f

Incluso se combinan: Range(Cells(2, 1), Cells(6, 3)) construye el bloque A2:C6 a partir de dos celdas esquina, perfecto cuando las esquinas se calculan.

Ejemplo 2 — .Value frente a .Value2 frente a .Text frente a .Formula

Esta es la trampa que pilla a todos los principiantes. La misma celda devuelve cuatro cosas distintas:

' La celda B2 muestra "1.250,00 €" con la fórmula =A2*5
Debug.Print Range("B2").Value     ' 1250    (un Variant sensible a Moneda/Fecha)
Debug.Print Range("B2").Value2    ' 1250    (un Double puro — el más rápido)
Debug.Print Range("B2").Text      ' "1.250,00 €"  (lo que VE el usuario, como texto)
Debug.Print Range("B2").Formula   ' "=A2*5"  (el texto de la fórmula)

Reglas prácticas:

  • .Value2 — para leer rangos grandes o hacer cálculos. Omite la conversión Moneda/Fecha, así que es más rápido y nunca te sorprende con un valor de moneda redondeado.
  • .Text — casi de solo lectura, devuelve la cadena mostrada. Cuidado: si la columna es muy estrecha, devuelve "####".
  • .Formula — lee o escribe la fórmula, no el resultado.

Ejemplo 3 — Deja de usar .Select (el antipatrón n.º 1)

La grabadora de macros escribe .Select por todas partes. Las macros de verdad no. Seleccionar es lento, parpadea la pantalla y se rompe en cuanto está activa la hoja equivocada.

' ❌ Estilo grabadora — frágil y lento
Range("A2").Select
Selection.Value = "Widget"

' ✅ Actuar directamente sobre el Range
Range("A2").Value = "Widget"

Cualifica la hoja en lugar de seleccionarla, para que el código funcione sea lo que sea que haya en pantalla:

ThisWorkbook.Worksheets("Hoja1").Range("A2").Value = "Widget"

Ejemplo 4 — Encontrar la última fila (la fórmula canónica)

Codificar a mano A2:A100 se rompe en cuanto crecen los datos. Esta línea encuentra la última fila realmente usada de la columna A:

Dim ultimaFila As Long
ultimaFila = Cells(Rows.Count, 1).End(xlUp).Row    ' saltar hacia arriba desde el fondo
MsgBox "Los datos terminan en la fila " & ultimaFila

End(xlUp) imita pulsar Ctrl + ↑. Es la forma más fiable de ajustar un rango a tus datos.

Ejemplo 5 — Rangos dinámicos con CurrentRegion

CurrentRegion toma todo el bloque contiguo alrededor de una celda — justo lo que selecciona Ctrl + Mayús + flechas. Sin contar filas:

Dim datos As Range
Set datos = Range("A1").CurrentRegion        ' toda la tabla, encabezados incluidos
MsgBox datos.Rows.Count & " filas × " & datos.Columns.Count & " columnas"

' Saltar el encabezado — bajar una fila (Offset), acortar una (Resize):
Dim cuerpo As Range
Set cuerpo = datos.Offset(1, 0).Resize(datos.Rows.Count - 1)

Offset(filas, columnas) desplaza un rango; Resize(filas, columnas) cambia su tamaño. Juntos recortan un encabezado, añaden una columna o agrandan un bloque — sin una sola dirección codificada a mano.

Ejemplo 6 — Recorrer un rango de forma legible

Cuando quieres cada celda, For Each es más limpio que la aritmética de índices:

Dim celda As Range
For Each celda In Range("B2:B6")
    If celda.Value > 100 Then celda.Interior.Color = vbGreen
Next celda

Ejemplo 7 — Leer un rango entero en una matriz (la vía rápida)

Aquí está el secreto de los profesionales: tocar la hoja miles de veces es lento. Lee el rango entero en memoria de una vez, trabaja ahí y reescribe una sola vez. En 10.000 filas es la diferencia entre 8 segundos y 0,1:

Sub RangoRapido()
    Dim arr As Variant
    arr = Range("A2:C10000").Value2          ' UNA lectura -> matriz 2D (base 1)

    Dim i As Long
    For i = 1 To UBound(arr, 1)
        arr(i, 3) = arr(i, 2) * 1.1          ' calcular en memoria, sin tocar celdas
    Next i

    Range("A2:C10000").Value2 = arr          ' UNA escritura
End Sub

El truco arr = UnRango.Value2 es tan importante que tiene su propia guía.

Ejemplo 8 — Rangos no contiguos y rangos con nombre

Un Range puede contener varios bloques separados (una Union), y puedes direccionar un rango con nombre por su nombre:

' Dos bloques separados, coloreados juntos:
Range("A2:A6, C2:C6").Interior.Color = vbCyan

' Un rango llamado "TasaIVA" en el Cuadro de nombres:
Range("TasaIVA").Value = 0.2

Errores frecuentes con Range (y la solución)

Síntoma Causa Solución
Se edita la hoja equivocada Range(...) sin hoja usa la hoja activa Anteponer ThisWorkbook.Worksheets("Hoja1").Range(...)
Cells(1, 2) toca la celda equivocada Cells es (fila, columna), no (columna, fila) El número de fila va primero
Bucle dolorosamente lento Leer/escribir cada celda por separado Cargar en una matriz (Ejemplo 7)
.Text devuelve "####" Columna demasiado estrecha para el valor Leer .Value2 en vez de .Text
El rango se queda corto al crecer los datos A2:A100 codificado a mano Dimensionar con End(xlUp) o CurrentRegion

Deja la fontanería de Range — describe el resultado

Range, Cells, End, Resize — mucha fontanería solo para mover una columna de números. ExcelMaster Agent te deja decirlo en español sencillo — «en Hoja1, multiplica cada Cantidad de la columna B por 1,1 y pon el resultado en la columna C, para tantas filas como haya» — y genera código seguro que ya gestiona la última fila, el encabezado y la trampa de la hoja activa. Pruébalo gratis →

Guías relacionadas

Preguntas frecuentes

¿Cuál es la diferencia entre Range y Cells en VBA? Ambos apuntan a celdas. Range("A2") usa una dirección de texto; Cells(2, 1) usa coordenadas numéricas (fila, columna) — ideal en bucles donde la posición es variable. Range(Cells(2,1), Cells(6,3)) combina ambos para construir un bloque a partir de esquinas calculadas.

¿Debo usar .Value o .Value2 en VBA? Usa .Value2 para leer rangos grandes y hacer cálculos — devuelve un Double puro, omite la conversión Moneda/Fecha y es más rápido. .Value solo cuando necesites explícitamente el tipo Moneda o Fecha.

¿Cómo referencio un rango con fila y columna variables? Con Cells(fila, columna) y variables, o Range(Cells(f1, c1), Cells(f2, c2)) para un bloque. Para la última fila: Cells(Rows.Count, 1).End(xlUp).Row.

¿Cómo referencio una tabla entera sin saber su tamaño? Range("A1").CurrentRegion devuelve todo el bloque contiguo. Para quitar el encabezado: .Offset(1, 0).Resize(.Rows.Count - 1).

¿Por qué debo evitar .Select en VBA? .Select es lento, hace parpadear la pantalla y depende de que esté activa la hoja correcta. Actúa directamente sobre el rango — Range("A2").Value = "x" — y cualifícalo con la hoja.