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

VBA VLookup en Excel — el fallo de "no encontrado" y cuándo gana un Dictionary

|

VBA VLookup en Excel — el fallo de "no encontrado" y cuándo gana un Dictionary

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

En resumen — Hay dos formas de llamar a VLOOKUP (BUSCARV en el Excel en español) desde VBA, y la diferencia decide si un valor ausente hace fallar tu macro. Application.WorksheetFunction.VLookup lanza un error de ejecución cuando no encuentra el valor; Application.VLookup (sin WorksheetFunction) devuelve un valor de error que compruebas con IsError. Y en cuanto recorres miles de filas, la respuesta correcta no suele ser ninguna de las dos — es un Dictionary.

Sub VLookupTwoWays()
    Dim tbl As Range
    Set tbl = Sheet1.Range("A:B")

    ' (1) WorksheetFunction — FALLA (error 1004) si "Acme" no está
    Debug.Print Application.WorksheetFunction.VLookup("Acme", tbl, 2, False)

    ' (2) Application — devuelve un VALOR DE ERROR si no lo encuentra, sin fallar
    Dim r As Variant
    r = Application.VLookup("Ghost", tbl, 2, False)
    If IsError(r) Then Debug.Print "no encontrado" Else Debug.Print r
End Sub

El modelo mental: VLOOKUP es una función de hoja de visita en VBA

VLOOKUP se diseñó para vivir en una celda. Al llamarlo desde VBA tomas prestada una función de hoja — y ese préstamo trae dos condiciones de las que ninguna fórmula de celda te avisa: cómo se comporta cuando el valor falta, y lo mal que escala cuando lo llamas en un bucle. Mantén esa imagen y las dos trampas de este artículo dejan de ser sorpresas.

Así que la primera pregunta no es «¿cómo escribo VLOOKUP en VBA?» — esa es la parte fácil, una línea. La pregunta real es cuál VLOOKUP, porque VBA expone dos con comportamiento de error opuesto, y luego si deberías llamarlo siquiera en cuanto entra un bucle.

La única regla: WorksheetFunction.VLookup falla, Application.VLookup devuelve un error

Esta es la distinción tras el problema de VBA VLOOKUP más reportado — el temido error de ejecución 1004 «No se puede obtener la propiedad VLookup»:

Llamado por WorksheetFunction, un valor ausente lanza un error de ejecución que detiene en seco tu macro. Llamado directamente por Application, un valor ausente vuelve como un valor de error (como Error 2042) que compruebas con IsError — sin fallo.

Ninguno es «el correcto»; son herramientas para dos situaciones. Usa WorksheetFunction cuando un valor ausente sea de verdad un bug y quieras que la macro pare (o lo hayas envuelto en On Error). Usa Application.VLookup cuando «no encontrado» sea un resultado normal y esperado que quieres tratar con elegancia.

' (A) WorksheetFunction + On Error — parar o bifurcar ante un error real
Dim price As Double
On Error Resume Next
price = Application.WorksheetFunction.VLookup(code, tbl, 2, False)
If Err.Number <> 0 Then
    price = 0                       ' valor por defecto, y seguimos
    Err.Clear
End If
On Error GoTo 0

' (B) Application.VLookup + IsError — el patrón más limpio para "puede faltar"
Dim res As Variant
res = Application.VLookup(code, tbl, 2, False)
If IsError(res) Then price = 0 Else price = res

El patrón (B) se lee mejor y no secuestra el manejo de errores para el flujo normal — recurre a Application.VLookup siempre que un fallo sea esperado. (Mira VBA On Error sobre por qué un On Error Resume Next disperso es un lastre.)

La trampa que de verdad cuesta: VLOOKUP dentro de un bucle es O(n²)

Aquí está la que los tutoriales se saltan. Un solo VLOOKUP recorre la columna de búsqueda hasta hallar una coincidencia. Mete esa llamada en un bucle sobre tus filas y vuelves a recorrer toda la columna en cada iteración:

' ⚠ LENTO — 10.000 filas, cada una buscando en una tabla de 10.000 filas.
' Hasta 100.000.000 de comparaciones, y relee la hoja en cada pasada.
Dim i As Long
For i = 2 To 10000
    Cells(i, "C").Value = Application.WorksheetFunction.VLookup( _
        Cells(i, "A").Value, Sheet2.Range("A:B"), 2, False)
Next i

Es trabajo cuadrático, y con datos reales convierte «¿por qué está colgada mi macro?» en una pausa para el café de varios minutos. El número de comparaciones crece con el cuadrado del número de filas — el doble de filas, el cuádruple de espera.

La solución es dejar de buscar una y otra vez. Lee la tabla de búsqueda una vez en un Dictionary — es una tabla hash, así que cada acceso es O(1) en vez de O(n) — y todo el trabajo se vuelve lineal:

Sub LookupConDictionary()
    Dim dict As Object
    Set dict = CreateObject("Scripting.Dictionary")

    ' Leer ambas columnas a memoria de UNA vez — mira VBA Array, por qué importa
    Dim lookup As Variant
    lookup = Sheet2.Range("A2:B10000").Value
    Dim i As Long
    For i = 1 To UBound(lookup, 1)
        dict(lookup(i, 1)) = lookup(i, 2)        ' clave = columna A, valor = columna B
    Next i

    ' Leer las claves, resolver en memoria, reescribir de UNA vez
    Dim keys As Variant, out() As Variant, n As Long
    keys = Sheet1.Range("A2:A10000").Value
    n = UBound(keys, 1)
    ReDim out(1 To n, 1 To 1)
    For i = 1 To n
        If dict.Exists(keys(i, 1)) Then out(i, 1) = dict(keys(i, 1)) Else out(i, 1) = "n/d"
    Next i
    Sheet1.Range("C2").Resize(n, 1).Value = out      ' una escritura, no 10.000
End Sub

Mismo resultado, pero lee la hoja dos veces en lugar de 20.000, y el cotejo es por hash. En 10.000 filas es la diferencia entre «al instante» y «ve a por un café». (La otra mitad de la mejora — leer y escribir arrays de una vez en lugar de celda por celda — es un hábito aparte que merece la pena.)

Cuándo usar cuál

Tu situación Usa Por qué
Búsqueda única, el valor siempre debería existir WorksheetFunction.VLookup Un fallo es un bug — deja que se lance
Búsqueda única, el valor puede faltar Application.VLookup + IsError Tratar «no encontrado» sin On Error
Buscar muchas filas contra una tabla Un Dictionary construido una vez O(1) en vez de O(n) por búsqueda
Quieres la posición de fila, no un valor Application.Match VLOOKUP no devuelve una dirección
La columna de búsqueda está a la izquierda del resultado Index/Match o un Dictionary VLOOKUP solo mira a la derecha

La opinión: si llamas a VLOOKUP en un bucle, en realidad quieres un Dictionary

La línea que defiendo: VLOOKUP pertenece a las celdas, no a los bucles. Llamar una función de hoja una vez desde VBA para coger un solo valor está perfectamente bien. En cuanto está dentro de un bucle For sobre tus datos, has pedido a una operación diseñada para una búsqueda que recorra una columna miles de veces — y lo notarás.

El reflejo de «usa VLOOKUP sin más, ya lo conozco» es justo lo que mantiene lentas las macros. La jugada profesional es reconocer la forma del problema: muchas búsquedas contra una tabla es para lo que existe un Dictionary. Construye la tabla en memoria una vez, resuelve cada fila contra ella, reescribe las respuestas de una vez. Tu macro pasa de cuadrática a lineal, y el código para hacerlo es más corto que el manejo de errores que envolverías si no alrededor de un VLOOKUP en bucle.

Errores comunes de VBA VLOOKUP (y la solución)

Síntoma Causa Solución
Error 1004 «No se puede obtener la propiedad VLookup» WorksheetFunction.VLookup no halló el valor Application.VLookup + IsError, o envolver en On Error
La macro se cuelga con muchos datos VLOOKUP llamado en un bucle de filas (O(n²)) Construir un Dictionary una vez, resolver en memoria
Devuelve el valor equivocado 4.º argumento omitido → coincidencia aproximada por defecto Pasar siempre False para coincidencia exacta
#N/D aunque el valor está ahí La columna de búsqueda tiene espacios / Chr(160) al final Limpiar la clave primero — mira VBA Trim
No puede buscar hacia la izquierda VLOOKUP solo busca en la primera columna, hacia la derecha Index/Match o un Dictionary
Discrepancia de tipos al guardar el resultado El resultado puede ser un valor de error Guardar en un Variant, comprobar IsError antes de usar

Cuando las búsquedas se acumulan — describe el cruce en su lugar

No querías un debate sobre WorksheetFunction contra Application. Querías «cruza el export de este mes con mi lista de precios y marca los códigos que no existen». Para cuando has elegido el VLOOKUP correcto, protegido los fallos y reescrito el bucle como Dictionary para que termine esta década, la fontanería es la macro. ExcelMaster Agent te deja describir el cruce en español sencillo — «busca cada código de la columna A en la hoja de precios, pon el precio en C y lista los que no tengan coincidencia» — y escribe Python que lo hace todo en una pasada, haciendo antes una copia de seguridad de tu libro. Pruébalo gratis →

Guías relacionadas

FAQ

¿Cómo se usa VLOOKUP en VBA? Llámalo por el objeto application: Application.WorksheetFunction.VLookup(valorBuscado, rangoTabla, índiceColumna, False). Pasa siempre False como cuarto argumento para una coincidencia exacta. Si el valor puede faltar, usa Application.VLookup (sin WorksheetFunction) y comprueba el resultado con IsError, para que un fallo devuelva un valor de error en vez de hacer fallar la macro.

¿Por qué VBA VLOOKUP da el error de ejecución 1004? Porque lo llamaste por WorksheetFunction y el valor no se encontró — esa vía lanza un error en vez de devolver #N/D. O envuelves la llamada en On Error Resume Next y compruebas Err.Number, o usas Application.VLookup, que devuelve un valor de error comprobable que tratas con If IsError(resultado).

¿Cuál es la diferencia entre Application.VLookup y WorksheetFunction.VLookup? Hacen la misma búsqueda pero fallan distinto. WorksheetFunction.VLookup lanza un error de ejecución si nada coincide; Application.VLookup devuelve un valor de error (como Error 2042) que compruebas con IsError. Usa WorksheetFunction cuando un fallo sea un bug real, y Application cuando «no encontrado» sea esperado.

¿Es VLOOKUP lento en VBA? Una sola llamada está bien. Llamarlo en un bucle sobre muchas filas es lento porque cada llamada vuelve a recorrer la columna de búsqueda, y el trabajo crece con el cuadrado del número de filas. Para muchas búsquedas, carga la tabla en un Scripting.Dictionary una vez y resuelve cada fila en O(1) — mucho más rápido con muchos datos.

¿Puede VBA VLOOKUP buscar un valor en otra hoja? Sí — cualifica el rango de la tabla con la hoja: Application.WorksheetFunction.VLookup(clave, Worksheets("Precios").Range("A:B"), 2, False). Usa una referencia plenamente cualificada Worksheets("nombre").Range(...) para que la búsqueda no lea por accidente la hoja activa.