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

VBA Filter dans Excel — extraire un sous-ensemble de tableau en un seul appel, et pourquoi ce n'est pas AutoFilter

|

VBA Filter dans Excel — extraire un sous-ensemble de tableau en un seul appel, et pourquoi ce n'est pas AutoFilter

TL;DRFilter(sourceArray, match) renvoie un nouveau tableau indexé à partir de zéro contenant uniquement les éléments qui contiennent la sous-chaîne match. C'est une recherche dans un tableau en mémoire, pas dans une feuille — rien à voir avec AutoFilter. Trois choses mordent : il correspond à une sous-chaîne (donc "AB" conserve "CAB"), il est sensible à la casse par défaut (passez vbTextCompare pour ignorer la casse), et un résultat sans correspondance est un tableau vide avec UBound = -1, pas une erreur. Le troisième argument facultatif Include l'inverse : Filter(a, "x", False) conserve tout ce qui ne contient pas "x".

Sub FilterDemo()
    Dim names As Variant, hits As Variant
    names = Array("Smith", "Jones", "Smithson", "Adams")

    hits = Filter(names, "Smith")          ' garde les elements contenant "Smith"
    Debug.Print hits(0)                     ' Smith      <- indice 0, toujours a partir de zero
    Debug.Print hits(1)                     ' Smithson   <- correspondance de sous-chaine, pas mot entier
    Debug.Print UBound(hits)                ' 1          <- deux resultats : indices 0 et 1

    hits = Filter(names, "smith")           ' minuscules -> AUCUNE correspondance par defaut
    Debug.Print UBound(hits)                ' -1         <- tableau vide, pas une erreur
End Sub

La signature complète, avec les deux arguments qui font trébucher :

Filter(sourceArray, match, [include], [compare])
'      tableau 1D    texte   True/False  vbTextCompare = ignore la casse

Ce que vous allez apprendre

  • Le modèle mental — Filter cherche dans un tableau et vous rend ceux qui restent
  • Pourquoi Filter n'est pas AutoFilter, et quand vous voulez vraiment l'un ou l'autre
  • Le piège de la sous-chaîne : Filter correspond à l'intérieur des mots, pas aux valeurs entières
  • La sensibilité à la casse, et le correctif vbTextCompare
  • Le piège du résultat vide (UBound = -1) et comment s'en prémunir
  • Include:=False pour inverser le filtre, et l'aller-retour avec Split et Join

Le modèle mental : Filter cherche dans un tableau, pas dans une feuille

Filter est la cousine de InStr côté tableau. Là où InStr demande « ce texte est-il à l'intérieur d'une chaîne, et où ? », Filter demande lesquelles de ces chaînes contiennent ce texte, et vous rend un tableau tout neuf ne contenant que celles qui le font. Vous lui donnez une liste ; il vous donne la liste plus courte.

Ce cadrage vous dit exactement quand y recourir : vous avez déjà un tableau de chaînes unidimensionnel en mémoire — les morceaux d'un Split, les clés d'un Dictionary, une liste de noms de fichiers de Dir — et vous voulez le sous-ensemble qui mentionne quelque chose. C'est le remplacement en une ligne de la boucle que tout le monde écrit :

' La facon longue que tout le monde ecrit d'abord
Dim i As Long, n As Long
ReDim keep(UBound(names)) As String
For i = 0 To UBound(names)
    If InStr(1, names(i), "Smith") > 0 Then
        keep(n) = names(i): n = n + 1
    End If
Next i
ReDim Preserve keep(n - 1)

' La meme chose, en un seul appel
keep = Filter(names, "Smith")

La confusion à dissiper : Filter n'est pas AutoFilter

C'est de loin la première source des questions « pourquoi Filter ne marche pas sur ma feuille », et la réponse est que vous tenez deux outils sans rapport qui se trouvent partager un mot. Ce ne sont pas des variantes l'un de l'autre :

Filter() — la fonction AutoFilter — la méthode
Opère sur un tableau 1D en mémoire une Range de feuille
Renvoie un nouveau tableau, plus petit rien — elle masque des lignes dans l'UI
Touche des cellules ? jamais oui, c'est un état visible de la feuille
Type de correspondance sous-chaîne, sensible à la casse égal / contient / supérieur à, via des critères
À utiliser quand vous avez déjà un tableau vous voulez montrer des lignes filtrées à un utilisateur

Si vos données sont dans des cellules et que vous voulez les restreindre, il vous faut AutoFilter ou, pour des copies multi-critères, le filtre avancé — pas cette fonction. Filter() gagne sa place après que vous avez tiré les données dans un tableau. Un pipeline courant et correct : lire une colonne, l'aplatir en un tableau 1D (un travail pour Transpose), puis appliquer Filter en mémoire sans déranger la feuille le moins du monde.

Piège 1 : Filter correspond à une sous-chaîne, pas à une valeur entière

Filter conserve tout élément où le texte recherché apparaît n'importe où à l'intérieur. C'est un atout pour les recherches « contient » et un piège pour les recherches « égal à » :

Dim codes As Variant, r As Variant
codes = Array("AB", "ABC", "CAB", "XY")
r = Filter(codes, "AB")
' r contient "AB", "ABC" ET "CAB" - chaque element qui CONTIENT "AB"

Si vous vouliez seulement les éléments égaux à "AB", Filter est le mauvais outil — il ne sait pas faire de correspondance exacte. Pour un test d'appartenance à correspondance exacte, tournez-vous vers un Dictionary (dict.Exists(key)) ou Application.Match. Utilisez Filter quand « contient » est vraiment ce que vous voulez dire.

Piège 2 : Filter est sensible à la casse par défaut

Par défaut, Filter utilise une comparaison binaire"smith" ne correspond pas à "Smith". C'est l'inverse de l'attente mentale de la plupart des gens, et cela renvoie silencieusement un tableau vide. Le quatrième argument corrige ça :

r = Filter(names, "smith")                        ' binaire -> rate "Smith"
r = Filter(names, "smith", True, vbTextCompare)   ' texte -> correspond a "Smith", "SMITH", "smith"

À noter : vous devez fournir le troisième argument (Include, ici True) pour atteindre le quatrième. En alternative, Option Compare Text en tête de module rend insensible à la casse chaque comparaison de chaînes de ce module, Filter compris — pratique, mais cela change le comportement à l'échelle du module, alors passez vbTextCompare appel par appel quand vous voulez l'effet en local.

Piège 3 : aucune correspondance renvoie un tableau vide, et Include inverse

Un Filter qui ne correspond à rien ne déclenche pas d'erreur — il renvoie un tableau valide de longueur zéro, dont l'UBound vaut -1. Une boucle For i = 0 To UBound(r) dessus ne fait rien sans danger, mais accéder à r(0) explose avec « L'indice n'appartient pas à la sélection ». Prémunissez-vous sur UBound avant d'indexer :

r = Filter(names, "Zzz")
If UBound(r) < 0 Then
    MsgBox "No matches."
Else
    MsgBox (UBound(r) + 1) & " match(es) found."   ' decompte = UBound + 1
End If

Et l'argument que presque personne ne retient : Include. Il vaut True par défaut (garder les correspondances). Passez False et Filter inverse — il conserve tout élément qui ne contient pas le motif recherché. C'est ainsi qu'on retire des éléments d'une liste en une ligne :

' Retire tout chemin qui mentionne "temp"
clean = Filter(paths, "temp", False)

L'avis : Filter est pour les tableaux que vous détenez déjà — et la ligne Split-Filter-Join

Filter est une colle superbe et un moteur médiocre. Il brille sur des données déjà en tableau de chaînes 1D et là où « contient » est la vraie question — élaguer un listing de dossier, restreindre des jetons issus d'un Split, garder les lignes d'erreur hors d'un tableau de log. C'est la mauvaise réponse dès que vous voulez des correspondances exactes (utilisez un Dictionary), dès que vos données sont encore dans des cellules (utilisez AutoFilter), ou dès que les éléments ne sont pas des chaînes (Filter convertit en chaîne et compare du texte, ce qui trompe en silence sur les nombres).

Son meilleur tour, c'est d'être le milieu d'un pipeline de trois fonctions. Split analyse, Filter conserve, Join réassemble — une seule expression qui remplace une boucle de quinze lignes :

' D'une ligne CSV, ne garder que les champs mentionnant "2026", puis les rejoindre
result = Join(Filter(Split(line, ","), "2026"), ", ")

Cette ligne, c'est tout le trio en miniature : Split transforme la chaîne en tableau, Filter en extrait un sous-ensemble, Join le recolle — sans boucle, sans arithmétique d'indices, sans erreur de décalage.

Comment ExcelMaster vous aide

Filtrer est rarement le but. Le but, c'est « sors les factures en retard de cet export, laisse tomber les lignes de test, et donne-moi les codes clients ». Le temps de lire la colonne dans un tableau, de l'aplatir, de vous prémunir contre la sensibilité à la casse, de gérer le résultat vide et de recoller les survivants, la plomberie écrase la seule réponse que vous vouliez. ExcelMaster vous laisse énoncer ce but en langage courant — « liste les codes clients de chaque facture en retard hors test » — et génère du Python qui lit les données, applique la vraie logique de correspondance et sauvegarde d'abord votre fichier — vous décrivez le résultat voulu, et il gère la sensibilité à la casse, les cas vides et les cas limites.

Foire aux questions

Que fait la fonction Filter en VBA ?

Filter(sourceArray, match) renvoie un nouveau tableau ne contenant que les éléments de sourceArray qui contiennent la sous-chaîne match. La source doit être un tableau unidimensionnel, et le résultat est toujours indexé à partir de zéro. Il cherche dans un tableau en mémoire et renvoie un tableau plus petit — il ne modifie aucune cellule.

VBA Filter est-il la même chose qu'AutoFilter ?

Non. Filter() est une fonction qui extrait un sous-ensemble d'un tableau unidimensionnel en mémoire et renvoie un nouveau tableau. AutoFilter est une méthode de feuille qui masque des lignes dans la feuille visible selon des critères. Ils partagent un nom et rien d'autre — si vos données sont dans des cellules, il vous faut AutoFilter ; si c'est déjà un tableau, il vous faut Filter().

Pourquoi VBA Filter ne renvoie-t-il rien alors que le texte correspond clairement ?

Presque toujours la sensibilité à la casse. Filter utilise une comparaison binaire par défaut, donc "smith" ne correspond pas à "Smith". Passez vbTextCompare en quatrième argument — Filter(a, "smith", True, vbTextCompare) — ou placez Option Compare Text en tête de module.

Comment exclure des éléments avec VBA Filter ?

Passez False comme troisième argument, Include. Filter(paths, "temp", False) renvoie tout élément qui ne contient pas "temp". Avec Include omis ou à True, Filter conserve les correspondances ; avec False, il conserve les non-correspondances.

Comment vérifier si VBA Filter a trouvé des correspondances ?

Testez l'UBound du résultat. Un Filter sans correspondance renvoie un tableau vide dont l'UBound vaut -1, pas une erreur, donc If UBound(result) < 0 Then signifie que rien n'a correspondu. Le nombre de correspondances est UBound(result) + 1, puisque le tableau est indexé à partir de zéro.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 03/09/2026.

Guides associés : VBA Join · VBA Transpose · VBA Split · VBA AutoFilter · VBA Dictionary