Probado en: Excel 365 v2509 · Excel 2021 · Excel 2019 · última verificación 05/06/2026
En resumen — Range 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
- VBA Array en Excel — leer un rango 100× más rápido
- VBA Dictionary en Excel — búsquedas, eliminar duplicados y agrupar
- VBA For en Excel — 8 ejemplos reales
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.
