Cuando trabajas con una hoja de Excel grande y necesitas localizar un dato, abrir el cuadro Buscar con Ctrl+B y pulsar «Buscar siguiente» cada vez se vuelve pesado. Con VBA tienes a tu disposición el método Range.Find, que hace lo mismo pero dentro de una macro: busca un valor en un rango y te devuelve la celda donde está, para que la pintes, la leas o la cambies sin tocar el ratón. Al terminar este tutorial sabrás escribir una macro que resalte todas las filas que contengan un texto, sustituir un valor repetido por otro y evitar los tres errores que más se repiten al empezar.
Range.Find está disponible en todas las versiones de Excel que traen el editor de VBA (desde Excel 2007 hasta Microsoft 365, más Excel para Mac); en Excel para la web no se puede usar porque allí no hay VBA.
Qué hace Range.Find y en qué se parece al cuadro Buscar
Imagina una hoja Ventas con cuatrocientas filas: en la columna A hay productos, en la B ciudades (Madrid, Barcelona, Valencia, Sevilla…) y en la C el importe. Si quieres ver todas las ventas de Madrid, con el cuadro Buscar (Ctrl+B) escribes «Madrid», le das a «Buscar siguiente», miras la fila, y otra vez. Con Range.Find le dices a VBA: «busca Madrid en B2:B400, y cuando lo encuentres, píntame la fila entera de amarillo». La macro hace el trabajo por ti en milisegundos.
La idea es la misma que Ctrl+B: buscar un valor dentro de un rango de celdas. La diferencia es que Range.Find se ejecuta desde código, devuelve la celda encontrada como un objeto Range y se puede combinar con un bucle para recorrer todas las coincidencias o con una asignación para reemplazar el valor.
Ctrl+B te obliga a pulsar; Range.Find trabaja solo. Y como vive dentro de una macro, puedes guardar el libro y volver a usarla mañana sin recordar los pasos.
La sintaxis de Range.Find y sus nueve argumentos
La forma completa es expresión.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat), donde expresión es un Range sobre el que se busca. Solo What es obligatorio; los demás son opcionales, y aquí está el primer punto importante: como guardan el último valor que se les asignó, lo mejor es fijarlos siempre.
| Argumento | Tipo | Obligatorio | Para qué sirve |
|---|---|---|---|
What |
Variant | Sí | El dato que se busca: texto entre comillas, número o variable. |
After |
Range | No | Una sola celda del rango desde la que empieza; la búsqueda sigue después. |
LookIn |
XlFindLookIn | No | Dónde mira: valores, fórmulas o comentarios. |
LookAt |
XlLookAt | No | Coincidencia exacta (xlWhole) o parcial (xlPart). |
SearchOrder |
XlSearchOrder | No | Recorre por filas (xlByRows) o por columnas (xlByColumns). |
SearchDirection |
XlSearchDirection | No | Hacia delante (xlNext) o hacia atrás (xlPrevious). |
MatchCase |
Boolean | No | True distingue mayúsculas y minúsculas. |
MatchByte |
Boolean | No | Doble byte, solo en idiomas como japonés o chino. |
SearchFormat |
Boolean | No | Si debe coincidir el formato definido en FindFormat. |
What: el dato que se busca
What es el único argumento obligatorio. Admite texto entre comillas ("Madrid"), un número (1500) o cualquier variable (c.Value). Si el valor es una fecha, pásalo con CLng(CDate("01/03/2026")) para evitar sorpresas con la configuración regional.
After: desde qué celda empieza la búsqueda
After es una sola celda del rango: la búsqueda empieza justo después de ella. Al llegar al final del rango, da la vuelta al principio (lo que se llama «wraparound»). Si se omite, la búsqueda empieza tras la celda superior izquierda del rango. Pasa una celda, no un rango: After:=Range("B50").
LookIn, LookAt, SearchOrder y SearchDirection
LookIn decide dónde mira: xlValues (el valor visible), xlFormulas (la fórmula escrita) o xlComments (comentarios). LookAt decide si la coincidencia debe ser exacta (xlWhole) o si vale con que contenga el texto buscado (xlPart). SearchOrder indica si se recorre fila a fila (xlByRows) o columna a columna (xlByColumns). SearchDirection indica el sentido: xlNext (adelante) o xlPrevious (atrás). Estos cuatro argumentos guardan el último valor usado: si no los fijas en cada llamada, la macro puede comportarse de forma rara. Ponlos siempre explícitos.
MatchCase, MatchByte y SearchFormat
MatchCase vale True o False: con True «Madrid» y «madrid» son distintos. MatchByte solo se usa en idiomas de doble byte (japonés, chino, coreano) y normalmente se deja False. SearchFormat activa la búsqueda por formato, pero antes hay que definirlo en la propiedad FindFormat del rango.
Abrir el editor y preparar una macro con Find
Empezamos con una macro que busca «Madrid» en la columna B de la hoja Ventas y pinta de amarillo la fila entera donde lo encuentre.
- Abre tu libro y, si aún no tiene macros, guárdalo como libro habilitado para macros: F12 > Tipo: *Libro de Excel habilitado para macros (.xlsm)**.
- Abre el editor de Visual Basic con Alt+F11.
- En la ventana de código que se abre, escribe la macro siguiente y pulsa F5 para ejecutarla.
La macro completa, lista para copiar
Sub ResaltaMadrid()
With Worksheets("Ventas").Range("B2:B200")
Set c = .Find("Madrid", LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not c Is Nothing Then
c.EntireRow.Interior.Color = vbYellow
End If
End With
End Sub
Línea a línea: With Worksheets("Ventas").Range("B2:B200") abre el rango donde se busca. Set c = .Find(...) ejecuta la búsqueda y guarda la celda encontrada en la variable c. If Not c Is Nothing Then comprueba que la búsqueda tuvo éxito. c.EntireRow.Interior.Color = vbYellow pinta toda la fila de amarillo. End With cierra el bloque.
Qué pasa cuando el dato no está
Si «Madrid» no aparece en B2:B200, Find devuelve Nothing y, si intentas usar c.EntireRow sin más, VBA muestra el error 91: «Variable de objeto no establecida». La solución es comprobarlo antes, como hace la macro anterior con If Not c Is Nothing Then. Si quieres avisar al usuario, añade una rama con Else:
If c Is Nothing Then
MsgBox "Madrid no aparece en B2:B200"
End If
Buscar todas las coincidencias con FindNext
Una sola búsqueda se queda corta si el dato aparece varias veces. Para recorrerlas todas existe FindNext: parte de una celda ya encontrada y devuelve la siguiente coincidencia. Si la hoja Productos tiene «Lápiz» en seis filas, Find se queda en la primera; FindNext las recorre todas.
| A | B | C | |
|---|---|---|---|
| 1 | Producto | Categoría | Stock |
| 2 | Lápiz | Papelería | 120 |
| 3 | Cuaderno | Papelería | 80 |
| 4 | Lápiz | Papelería | 45 |
| 5 | Bolígrafo | Papelería | 200 |
| 6 | Lápiz | Papelería | 30 |
| 7 | Goma | Papelería | 150 |
Guardar la primera dirección para detener el bucle
FindNext da la vuelta al rango y vuelve a empezar: sin una condición de salida, el bucle no termina nunca. La forma de detenerlo es guardar la dirección de la primera coincidencia y comparar:
Sub ResaltaLapices()
With Worksheets("Productos").Range("B2:B200")
Set c = .Find("Lápiz", LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not c Is Nothing Then
first = c.Address
Do
c.EntireRow.Interior.Color = vbYellow
Set c = .FindNext(c)
Loop While c.Address <> first
End If
End With
End Sub
first = c.Address guarda la dirección de la primera celda encontrada. El bucle pinta la fila, avanza con FindNext(c) y se detiene cuando la dirección vuelve a coincidir con first.
Sustituir un valor antiguo por uno nuevo
El mismo recorrido sirve para reemplazar: dentro del bucle, en vez de pintar, asigna el valor nuevo a c.Value. Si la empresa cambia «Lápiz» por «Bolígrafo» en toda la columna, la macro queda así:
Sub RenombraLapices()
With Worksheets("Productos").Range("B2:B200")
Set c = .Find("Lápiz", LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not c Is Nothing Then
first = c.Address
Do
c.Value = "Bolígrafo"
Set c = .FindNext(c)
Loop While c.Address <> first
End If
End With
End Sub
Fíjate en que c.Value = "Bolígrafo" solo cambia la celda actual; el siguiente FindNext sigue buscando «Lápiz» en las que aún no se han tocado.
Búsqueda parcial, por filas o por columnas, y con comodines
Range.Find acepta comodines en el argumento What, y eso cambia mucho los resultados. Mira esta hoja:
| A | |
|---|---|
| 1 | Concepto |
| 2 | Transferencia |
| 3 | Transporte |
| 4 | Transacción |
| 5 | Compra |
| 6 | Traspaso |
xlWhole contra xlPart: mismo texto, resultado distinto
Con What:="Trans" y LookAt:=xlPart, Find devuelve «Transferencia» (la primera que contiene «Trans»). Con LookAt:=xlWhole no encuentra nada, porque ninguna celda vale exactamente «Trans».
Set c = .Find("Trans", LookIn:=xlValues, LookAt:=xlPart, MatchCase:=False)
Buscar por filas o por columnas
SearchOrder decide cómo se recorre el rango. Con xlByRows, la búsqueda va fila a fila de izquierda a derecha; con xlByColumns, baja por la primera columna y luego pasa a la segunda. En una hoja como la anterior, con una sola columna, da igual; en un rango A1:D20, marca la diferencia.
Set c = .Find("Madrid", LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)
Set c = .Find("Madrid", LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns)
Comodines * y ? en el argumento What
Range.Find admite los comodines clásicos: * vale por cualquier secuencia de caracteres y ? por uno solo. "Trans*" encuentra «Transferencia», «Transporte», «Transacción» y «Traspaso» (porque empieza por «Trans»). "T?ans" encuentra «Trans» y «T3ans», pero no «Transferencia». El resto, igual que en Ctrl+B.
Errores típicos al usar Range.Find y cómo arreglarlos
El error 91 "Variable de objeto no establecida"
Aparece cuando usas la variable Range antes de comprobar Is Nothing. Si el dato no está, Find devuelve Nothing y cualquier c.EntireRow o c.Value lanza el error 91. Se arregla con la comprobación de la nada antes de tocar c.
Find siempre devuelve la misma celda
Si olvidas fijar LookIn, LookAt o MatchCase, VBA reutiliza los valores de la última búsqueda, y la macro no encuentra lo que tú crees. Se arregla pasando los cuatro argumentos explícitos en cada Find y FindNext.
El bucle no se detiene nunca
Con FindNext el recorrido es circular. Si no guardas la dirección de la primera celda y la comparas al final, el bucle sigue y la hoja se queda parpadeando. Se arregla con first = c.Address y Loop While c.Address <> first.
Lo que Find no hace (y qué usar en su lugar)
Range.Find recorre celdas; no devuelve un rango con todas las coincidencias, solo la primera o la siguiente. Si necesitas todas juntas, el patrón limpio es Find + FindNext con un bucle y la dirección guardada, igual que en la sección anterior.
Tampoco recorre formatos fila a fila a menos que configures FindFormat; para eso suele ser más rápido aplicar el formato con un bucle For Each…Next que mire el valor de cada celda. Y si la búsqueda depende de una condición más rica (por ejemplo, «el importe es mayor que 1.000 y la ciudad empieza por M»), Find se queda corto: mejor recorrer el rango con For Each cell In Range("B2:B200") y usar el operador Like de VBA para comparar.
Range.Find "Madrid", LookIn:=xlValues.Lo que ya sabes hacer con Range.Find y el siguiente paso
Range.Findtiene nueve argumentos; soloWhates obligatorio, pero conviene fijar siempreLookIn,LookAt,MatchCaseySearchOrder.LookAt:=xlWholeexige coincidencia exacta;LookAt:=xlPartadmite que el texto buscado esté dentro de la celda.- Si la búsqueda puede no encontrar nada, comprueba
If Not c Is Nothing Thenantes de usar la variable. - Para varias coincidencias, usa
FindNexty guarda la primera dirección conc.Addresspara detener el bucle. - Guarda el libro como *Libro habilitado para macros (.xlsm)** si la macro va a quedarse en el archivo.
El siguiente paso es abrir el editor con Alt+F11, pegar la macro de la sección "Buscar todas las coincidencias" sobre tu propia hoja y ver cómo se pintan las filas. Para profundizar, la página oficial está en learn.microsoft.com/es-es/office/vba/api/excel.range.find.
Dudas al usar Range.Find en VBA
1. ¿Cómo buscar un texto dentro de una cadena de texto con VBA?
La forma más cómoda es usar InStr: InStr("Informe anual 2026","anual") devuelve 1, porque la palabra empieza en la primera posición. Si el texto no está, devuelve 0, así que basta con If InStr(…) > 0 Then para detectarlo sin importar el método Find.
2. ¿Cómo buscar en un rango con varios criterios a la vez con VBA?
El método Find de Excel solo acepta un criterio por búsqueda, así que para combinar varios lo habitual es recorrer el rango con un bucle For Each y validar cada celda con If: por ejemplo, If celda.Value = "Madrid" And celda.Offset(0,1).Value > 1000 Then. Así puedes apilar condiciones todas las que necesites.
3. ¿Cómo buscar un texto en un rango y obtener la dirección de la celda donde está?
Usa Range.Find con el parámetro LookAt:=xlWhole si quieres la coincidencia exacta. Cuando lo encuentra, devuelve un objeto Range y obtienes la dirección con .Address: Set c = Range("A:A").Find("Sevilla") y luego MsgBox c.Address te mostrará algo como $A$15.
4. ¿Cómo buscar una fecha dentro de un rango con VBA?
Las fechas en Excel son números seriales, así que la búsqueda funciona igual que con números: Range.Find(CLng(DateValue("15/03/2026"))). Si te falla, revisa el formato de la celda y usa LookIn:=xlValues para que compare el valor, no el formato visual.
5. ¿Cómo hacer que Find devuelva solo coincidencias exactas?
Añade LookAt:=xlWhole en los parámetros de Find; con eso Excel distingue "Madrid" de "Madrid Centro". Si vas a hacer varias búsquedas seguidas, recuerda fijar MatchCase:=False si no quieres que diferencie mayúsculas, ya que xlWhole por sí solo no lo hace.
6. ¿Qué diferencia hay entre Cells.Find y Range.Find en VBA?
Los dos llaman al mismo método Find, lo único que cambia es cómo escribes el rango: Cells.Find mira en toda la hoja activa, mientras que Range("A1:D500").Find restringe la búsqueda a ese bloque. Si solo necesitas una celda concreta, Cells(Fila, Columna).Find es más rápido y claro.
7. ¿Cómo localizar la fila que contiene un texto concreto con VBA?
Después de un Range.Find correcto, la fila la tienes en .Row: Set c = Range("B:B").Find("Pendiente") y con MsgBox c.Row obtienes el número, por ejemplo 42. Para recorrer todas las apariciones, usa un bucle Do While Not c Is Nothing, avanzando con c.FindNext(c).
Fuentes
- MicrosoftVBA: Find value "Year" and select cell on Activecell.Rowconsultado el 05/10/2026
- MicrosoftEl editor de VBA y la primera macro — documentación oficialconsultado el 05/10/2026
- MicrosoftLAMBDA — documentación oficialconsultado el 05/10/2026
- MicrosoftRange.Formula, FormulaLocal, FormulaR1C1 y FormulaR1C1Local — documentación oficialconsultado el 05/10/2026
- MicrosoftAtajos que funcionan igual en cualquier idioma — documentación oficialconsultado el 05/10/2026