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

VBA VLookup dans Excel — le plantage « introuvable » et quand un Dictionary gagne

|

VBA VLookup dans Excel — le plantage « introuvable » et quand un Dictionary gagne

Testé sur : Excel 365 v2509 · Excel 2021 · Excel 2019 · dernière vérification le 12/06/2026

En bref — Il existe deux façons d'appeler VLOOKUP (RECHERCHEV dans l'Excel français) depuis VBA, et la différence décide si une valeur absente fait planter votre macro. Application.WorksheetFunction.VLookup déclenche une erreur d'exécution quand la valeur n'est pas trouvée ; Application.VLookup (sans WorksheetFunction) renvoie une valeur d'erreur que vous testez avec IsError. Et dès que vous bouclez sur des milliers de lignes, la bonne réponse n'est généralement ni l'une ni l'autre — c'est un Dictionary.

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

    ' (1) WorksheetFunction — PLANTE (erreur 1004) si "Acme" est absent
    Debug.Print Application.WorksheetFunction.VLookup("Acme", tbl, 2, False)

    ' (2) Application — renvoie une VALEUR D'ERREUR si introuvable, sans planter
    Dim r As Variant
    r = Application.VLookup("Ghost", tbl, 2, False)
    If IsError(r) Then Debug.Print "introuvable" Else Debug.Print r
End Sub

Le modèle mental : VLOOKUP est une fonction de feuille en visite dans VBA

VLOOKUP a été conçu pour vivre dans une cellule. En l'appelant depuis VBA, vous empruntez une fonction de feuille — et ce prêt a deux conditions dont aucune formule de cellule ne vous avertit : son comportement quand la valeur est absente, et sa mauvaise montée en charge quand vous l'appelez dans une boucle. Gardez cette image, et les deux pièges de cet article cessent d'être des surprises.

La première question n'est donc pas « comment écrire VLOOKUP en VBA ? » — c'est la partie facile, une ligne. La vraie question est quel VLOOKUP, car VBA en expose deux au comportement d'erreur opposé, puis si vous devriez l'appeler tout court dès qu'une boucle entre en jeu.

La seule règle : WorksheetFunction.VLookup plante, Application.VLookup renvoie une erreur

C'est la distinction derrière le problème VBA VLOOKUP le plus signalé — la redoutable erreur d'exécution 1004 « Impossible de lire la propriété VLookup » :

Appelé via WorksheetFunction, une valeur absente déclenche une erreur d'exécution qui stoppe net votre macro. Appelé directement via Application, une valeur absente revient comme une valeur d'erreur (du type Erreur 2042) que vous testez avec IsError — sans plantage.

Aucun n'est « correct » ; ce sont des outils pour deux situations. Utilisez WorksheetFunction quand une valeur absente est vraiment un bug et que vous voulez que la macro s'arrête (ou que vous l'avez enveloppée dans On Error). Utilisez Application.VLookup quand « introuvable » est un résultat normal et attendu que vous voulez gérer proprement.

' (A) WorksheetFunction + On Error — arrêter ou bifurquer sur une vraie erreur
Dim price As Double
On Error Resume Next
price = Application.WorksheetFunction.VLookup(code, tbl, 2, False)
If Err.Number <> 0 Then
    price = 0                       ' valeur par défaut, et on continue
    Err.Clear
End If
On Error GoTo 0

' (B) Application.VLookup + IsError — le motif plus propre pour "peut être absent"
Dim res As Variant
res = Application.VLookup(code, tbl, 2, False)
If IsError(res) Then price = 0 Else price = res

Le motif (B) se lit mieux et ne détourne pas la gestion d'erreur pour un flux de contrôle ordinaire — privilégiez Application.VLookup chaque fois qu'un échec est attendu. (Voir VBA On Error pour comprendre pourquoi un On Error Resume Next dispersé est un fardeau.)

Le piège qui coûte vraiment : VLOOKUP dans une boucle est en O(n²)

Voici celui que les tutoriels sautent. Un seul VLOOKUP parcourt la colonne de recherche jusqu'à trouver une correspondance. Placez cet appel dans une boucle sur vos lignes, et vous reparcourez toute la colonne à chaque itération :

' ⚠ LENT — 10 000 lignes, chacune cherchant dans une table de 10 000 lignes.
' Jusqu'à 100 000 000 de comparaisons, et il relit la feuille à chaque passage.
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

C'est un travail quadratique, et sur de vraies données cela transforme « pourquoi ma macro est figée ? » en pause-café de plusieurs minutes. Le nombre de comparaisons croît avec le carré du nombre de lignes — doublez les lignes, quadruplez l'attente.

La solution est d'arrêter de chercher en boucle. Lisez la table de recherche une fois dans un Dictionary — c'est une table de hachage, donc chaque accès est en O(1) au lieu de O(n) — et tout le travail devient linéaire :

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

    ' Lire les deux colonnes en mémoire en UN coup — voir VBA Array, pourquoi ça compte
    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)        ' clé = colonne A, valeur = colonne B
    Next i

    ' Lire les clés, résoudre en mémoire, réécrire en UN coup
    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/a"
    Next i
    Sheet1.Range("C2").Resize(n, 1).Value = out      ' une écriture, pas 10 000
End Sub

Même résultat, mais il lit la feuille deux fois au lieu de 20 000, et la correspondance est par hachage. Sur 10 000 lignes, c'est la différence entre « instantané » et « va chercher un café ». (L'autre moitié du gain — lire et écrire des tableaux en un coup plutôt que cellule par cellule — est une habitude à part qui en vaut la peine.)

Quand utiliser quoi

Votre situation Utilisez Pourquoi
Recherche unique, la valeur doit toujours exister WorksheetFunction.VLookup Un échec est un bug — laissez-le se déclencher
Recherche unique, la valeur peut manquer Application.VLookup + IsError Gérer « introuvable » sans On Error
Rechercher beaucoup de lignes dans une table Un Dictionary construit une fois O(1) au lieu de O(n) par recherche
Vous voulez la position de ligne, pas une valeur Application.Match VLOOKUP ne renvoie pas d'adresse
La colonne de recherche est à gauche du résultat Index/Match ou un Dictionary VLOOKUP ne regarde qu'à droite

L'opinion : si vous appelez VLOOKUP dans une boucle, vous voulez en fait un Dictionary

La ligne que je défends : VLOOKUP appartient aux cellules, pas aux boucles. Appeler une fonction de feuille une fois depuis VBA pour récupérer une seule valeur est tout à fait bien. Dès qu'elle est dans une boucle For sur vos données, vous avez demandé à une opération conçue pour une recherche de reparcourir une colonne des milliers de fois — et vous le sentirez.

Le réflexe « prends juste VLOOKUP, je connais » est exactement ce qui garde les macros lentes. Le geste professionnel est de reconnaître la forme du problème : beaucoup de recherches dans une table, c'est à cela que sert un Dictionary. Construisez la table en mémoire une fois, résolvez chaque ligne contre elle, réécrivez les réponses d'un coup. Votre macro passe de quadratique à linéaire, et le code pour le faire est plus court que la gestion d'erreur que vous enrouleriez sinon autour d'un VLOOKUP en boucle.

Erreurs courantes de VBA VLOOKUP (et la solution)

Symptôme Cause Solution
Erreur 1004 « Impossible de lire la propriété VLookup » WorksheetFunction.VLookup n'a pas trouvé la valeur Application.VLookup + IsError, ou envelopper dans On Error
La macro se fige sur de grandes données VLOOKUP appelé dans une boucle de lignes (O(n²)) Construire un Dictionary une fois, résoudre en mémoire
Renvoie la mauvaise valeur 4ᵉ argument omis → correspondance approximative par défaut Toujours passer False pour une correspondance exacte
#N/A alors que la valeur est là La colonne de recherche a des espaces / Chr(160) en fin Nettoyer la clé d'abord — voir VBA Trim
Impossible de chercher vers la gauche VLOOKUP ne cherche que dans la première colonne, vers la droite Index/Match ou un Dictionary
Incompatibilité de type au stockage Le résultat peut être une valeur d'erreur Stocker dans un Variant, tester IsError avant usage

Quand les recherches s'accumulent — décrivez plutôt le rapprochement

Vous ne vouliez pas d'un débat WorksheetFunction contre Application. Vous vouliez « rapprocher l'export de ce mois de ma liste de prix et signaler les codes qui n'existent pas ». Le temps de choisir le bon VLOOKUP, de protéger les échecs et de réécrire la boucle en Dictionary pour qu'elle finisse avant la fin de la décennie, la plomberie est la macro. ExcelMaster Agent vous laisse décrire le rapprochement en français clair — « cherche chaque code de la colonne A dans la feuille de prix, mets le prix en C et liste ceux sans correspondance » — et écrit du Python qui fait tout en une passe, en sauvegardant d'abord votre classeur. Essayer gratuitement →

Guides associés

FAQ

Comment utiliser VLOOKUP en VBA ? Appelez-le via l'objet application : Application.WorksheetFunction.VLookup(valeurCherchée, plageTable, indiceColonne, False). Passez toujours False comme quatrième argument pour une correspondance exacte. Si la valeur peut manquer, utilisez plutôt Application.VLookup (sans WorksheetFunction) et testez le résultat avec IsError, pour qu'un échec renvoie une valeur d'erreur au lieu de faire planter la macro.

Pourquoi VBA VLOOKUP donne l'erreur d'exécution 1004 ? Parce que vous l'avez appelé via WorksheetFunction et que la valeur n'a pas été trouvée — cette voie déclenche une erreur au lieu de renvoyer #N/A. Soit enveloppez l'appel dans On Error Resume Next et vérifiez Err.Number, soit utilisez Application.VLookup, qui renvoie une valeur d'erreur testable que vous gérez avec If IsError(résultat).

Quelle est la différence entre Application.VLookup et WorksheetFunction.VLookup ? Ils font la même recherche mais échouent différemment. WorksheetFunction.VLookup déclenche une erreur d'exécution si rien ne correspond ; Application.VLookup renvoie une valeur d'erreur (comme Erreur 2042) que vous testez avec IsError. Utilisez WorksheetFunction quand un échec est un vrai bug, et Application quand « introuvable » est attendu.

VLOOKUP est-il lent en VBA ? Un seul appel est correct. L'appeler dans une boucle sur de nombreuses lignes est lent car chaque appel reparcourt la colonne de recherche, et le travail croît avec le carré du nombre de lignes. Pour de nombreuses recherches, chargez la table dans un Scripting.Dictionary une fois et résolvez chaque ligne en O(1) — bien plus rapide sur de grandes données.

VBA VLOOKUP peut-il chercher une valeur dans une autre feuille ? Oui — qualifiez la plage de la table avec la feuille : Application.WorksheetFunction.VLookup(clé, Worksheets("Prix").Range("A:B"), 2, False). Utilisez une référence pleinement qualifiée Worksheets("nom").Range(...) pour que la recherche ne lise pas par accident la feuille active.