TL;DR — Il n'existe pas de mot-clé
Regexen VBA. Vous créez l'objet VBScript RegExp, soit en liaison tardive avecCreateObject("VBScript.RegExp"), soit en liaison précoce via une référence. Il ne fait rien tant que vous n'avez pas réglé ses propriétés :.Pattern, et les deux qui prennent par défaut la valeur peu utile —.Global = False(seulement la première correspondance) et.IgnoreCase = False(sensible à la casse). Choisissez ensuite le bon verbe :.Testrenvoie un Boolean,.Replacerenvoie une chaîne (les références arrière sont$1, pas\1), et.Executerenvoie une collection de correspondances dont les groupes capturés vivent dans.SubMatches— pas dans.Value.
Sub RegexBasics()
Dim re As Object
Set re = CreateObject("VBScript.RegExp") ' liaison tardive - aucune reference requise
re.Pattern = "PO-(\d+)" ' un groupe capture les chiffres
re.Global = True ' trouve TOUTES les correspondances, pas juste la premiere
re.IgnoreCase = True ' insensible a la casse
Dim m As Object
For Each m In re.Execute("po-17 and PO-9004")
Debug.Print m.Value ' PO-17 puis PO-9004 (la correspondance entiere)
Debug.Print m.SubMatches(0) ' 17 puis 9004 (le groupe capture)
Next m
End Sub
Ce que vous allez apprendre
- Le modèle mental — regex est un objet que vous créez, pas un mot-clé
- La liaison tardive contre l'ajout de la référence, et l'erreur de compilation qui s'ensuit
- Pourquoi
Global = Falsesignifie que vous n'obtenez jamais que la première correspondance - Ce que renvoient
Test,ReplaceetExecute - Pourquoi extraire une valeur suppose d'aller au-delà de
Match.Valuejusqu'àSubMatches - Ce que la saveur de motif VBScript prend en charge, et ce qu'elle ne prend pas
Le modèle mental : regex est un objet que vous créez, pas un mot-clé
En venant de presque tout autre langage, vous attendez un opérateur ou une fonction regex. VBA n'a ni
l'un ni l'autre. Ce qu'il a, c'est un composant COM — la bibliothèque VBScript Regular Expressions —
que vous instanciez, câblez avec des propriétés, puis appelez. Le modèle mental n'est donc pas « appeler
une fonction » mais « configurer un objet, puis lui poser une question ». Toute frustration ci-dessous
est en réalité « j'ai oublié de régler une propriété avant de demander ».
Cela vous dit aussi quand cela vaut la peine d'y recourir. RegExp est le poids lourd au sommet de
l'échelle, au-dessus de l'opérateur Like et du simple
InStr. Vous payez un coût de configuration — le
créer, régler le motif, basculer les interrupteurs — et en retour vous obtenez des comptes de
répétition, l'alternance, et la seule chose que les autres ne savent pas faire : extraire les morceaux
capturés de la correspondance.
La mise en place : liaison tardive contre référence
Deux façons d'obtenir l'objet, et le choix a de vraies conséquences :
' Liaison tardive - portable, sans reference, resolue a l'execution
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
' Liaison precoce - ajoutez d'abord la reference, puis ceci compile
' Tools -> References -> "Microsoft VBScript Regular Expressions 5.5"
Dim re As New RegExp
La liaison précoce vous donne l'IntelliSense et des appels un peu plus rapides, mais elle ne compile que
si la référence est cochée — et si vous envoyez le classeur à quelqu'un dont la référence manque, il
obtient une erreur de compilation Type défini par l'utilisateur non défini sur la ligne
As New RegExp avant qu'une seule instruction ne s'exécute. La liaison tardive (As Object +
CreateObject) n'a rien de cette fragilité : elle se résout à l'exécution et voyage sans référence. Pour
tout ce que vous distribuez, préférez la liaison tardive — la portabilité vaut la perte de l'IntelliSense.
Piège 1 : Global est désactivé, donc vous n'obtenez que la première correspondance
.Global vaut False par défaut, et ce seul défaut cause les deux rapports « regex est cassé » les plus
fréquents :
re.Pattern = "\d+"
re.Global = False ' le defaut
Debug.Print re.Replace("a1 b2 c3", "#") ' "a# b2 c3" <- seule la PREMIERE suite remplacee
Debug.Print re.Execute("a1 b2 c3").Count ' 1 <- seule la PREMIERE correspondance trouvee
re.Global = True
Debug.Print re.Replace("a1 b2 c3", "#") ' "a# b# c#" <- toutes maintenant
Debug.Print re.Execute("a1 b2 c3").Count ' 3
Si un remplacement n'a touché que la première occurrence, ou si une recherche a trouvé une correspondance
quand vous en voyez trois, c'est presque toujours la cause. Réglez .Global = True chaque fois que vous
voulez dire « partout ». Sa voisine .IgnoreCase vaut False de la même manière, donc un motif qui
devrait clairement correspondre à du texte de casse différente et n'y parvient pas est le plus souvent un
re.IgnoreCase = True oublié.
Piège 2 : Test, Replace et Execute renvoient trois choses différentes
L'objet expose trois verbes, et confondre leurs types de retour est le deuxième grand faux pas :
re.Test(s)renvoie un Boolean — le motif correspond-il quelque part ? Utilisez-le comme validateur, la cousine deLikedopée à la regex.re.Replace(s, replacement)renvoie une String — l'entrée avec chaque correspondance (siGlobal) remplacée. Les références arrière dans le remplacement utilisent un signe dollar :$1est le premier groupe capturé. Écrire\1insère un littéral antislash-un, un bug fréquent pour qui arrive d'autres langages.re.Execute(s)renvoie une MatchCollection — une collection d'objetsMatchque vous parcourez pour inspecter ou extraire.
re.Pattern = "(\d{4})-(\d{2})"
Debug.Print re.Test("2026-09") ' True
Debug.Print re.Replace("2026-09", "$2/$1") ' "09/2026" - $1, $2 sont les groupes
Choisissez le verbe selon la réponse voulue : un oui/non, c'est Test ; une chaîne transformée, c'est
Replace ; et tout ce où vous voulez le texte correspondant ou ses morceaux, c'est Execute.
Piège 3 : pour extraire, allez au-delà de Value jusqu'à SubMatches
C'est celui qui fait tourner les gens en rond. Chaque Match issu de .Execute a un .Value — le texte
correspondant entier — et une collection .SubMatches contenant les groupes capturés, les
parties que vous avez entourées de parenthèses :
re.Pattern = "Invoice #(\d+) dated (\d{4}-\d{2}-\d{2})"
re.Global = True
Dim m As Object
For Each m In re.Execute("Invoice #4471 dated 2026-09-04")
Debug.Print m.Value ' Invoice #4471 dated 2026-09-04 (la correspondance entiere)
Debug.Print m.SubMatches(0) ' 4471 (premier groupe)
Debug.Print m.SubMatches(1) ' 2026-09-04 (deuxieme groupe)
Debug.Print m.FirstIndex ' 0 (position de depart, base 0, dans l'entree)
Next m
Si vous voulez le nombre, vous voulez m.SubMatches(0), pas m.Value — lire .Value et se demander
pourquoi il contient encore le texte environnant est le bug d'extraction numéro un. SubMatches est en
base zéro, et un groupe qui n'a pas participé à la correspondance revient sous forme de chaîne vide,
alors protégez-vous sur re.Test(s) (ou le .Count de la collection) avant d'y indexer.
La saveur VBScript : ce que le langage de motifs prend en charge et ce qu'il ignore
La regex de VBA est la saveur VBScript (RegExp 5.5), pas PCRE, et les manques piègent quiconque a de
l'expérience regex ailleurs. Elle prend en charge la boîte à outils du quotidien : \d \w \s et leurs
négations, les quantificateurs * + ? {n} {n,m}, l'alternance a|b, les groupes ( ), les classes de
caractères [ ], et les ancres ^ $ (avec .MultiLine décidant si elles visent la ligne ou la chaîne
entière). Elle ne prend pas en charge le lookbehind, les groupes de capture nommés, ni les groupes
atomiques ou possessifs — les motifs qui s'appuient dessus ne compileront tout simplement pas comme vous
l'attendez.
Un soulagement propre à VBA : parce que l'antislash n'est pas un caractère d'échappement dans les
littéraux de chaîne VBA, vous écrivez les motifs directement — "\d{4}", pas "\\d{4}". Aucun double
échappement, contrairement à C#, Java ou JSON. Le seul doublement nécessaire est celui d'un guillemet
littéral, qui est le "" propre à VBA.
L'avis : la regex ne vaut la cérémonie que pour une vraie structure
RegExp est l'outil texte le plus puissant de VBA et celui vers lequel on se précipite le plus souvent
trop tôt. Créer l'objet, régler le motif, et se souvenir de Global et IgnoreCase est une vraie
cérémonie, et pour une forme fixe ou un simple oui/non, c'est une cérémonie dont vous n'avez pas besoin —
Like tient en une ligne lisible et
InStr est plus rapide pour « contient ce littéral ».
La ligne à tracer, c'est la structure que vous devez démonter. Quand le motif a une répétition
variable, une vraie alternance, ou — le point décisif — un groupe que vous devez extraire, la regex
est le seul outil de la boîte qui le fait, et elle gagne son salaire : un numéro de commande tiré d'une
ligne d'objet, les morceaux d'un horodatage brouillon, chaque e-mail dans un bloc de texte. Recourez-y là,
préférez la liaison tardive pour qu'elle voyage, réglez Global et IgnoreCase à dessein, et lisez
SubMatches pour les morceaux. Partout en deçà, redescendez l'échelle.
Quand l'analyse est tout l'enjeu — décrivez le travail plutôt
Même quand la regex est le bon outil, le motif est rarement le but — « sors chaque numéro de facture et
sa date de cette colonne et répartis-les en deux champs » l'est. Et un motif VBScript avec des groupes de
capture, plus la boucle sur Execute, plus la comptabilité des SubMatches, plus les cas limites où une
ligne ne correspond pas du tout, cela fait beaucoup de machinerie fragile autour d'une seule intention.
ExcelMaster vous laisse décrire le
résultat en langage courant — « extrais le numéro de facture et la date de la colonne B vers les colonnes
C et D, signale les lignes sans correspondance » — et génère du Python qui fait l'extraction avec un vrai
moteur de regex, sauvegarde d'abord votre fichier, et signale les lignes qu'il n'a pas pu analyser. Vous
décrivez ce qu'il faut extraire ; il gère le motif, les groupes et les ratés.
Foire aux questions
Comment utiliser regex en VBA ?
Créez l'objet VBScript RegExp, réglez ses propriétés, puis appelez une méthode. La voie portable est la
liaison tardive : Set re = CreateObject("VBScript.RegExp"), puis re.Pattern = "\d+",
re.Global = True, re.IgnoreCase = True, et enfin re.Test(s), re.Replace(s, repl) ou
re.Execute(s) selon que vous voulez un Boolean, une nouvelle chaîne ou les correspondances.
Pourquoi ma regex VBA ne remplace-t-elle que la première correspondance ?
Parce que .Global vaut False par défaut. Avec Global désactivé, .Replace et .Execute s'arrêtent
tous deux après la première correspondance. Réglez re.Global = True avant de les appeler pour agir sur
chaque correspondance de la chaîne.
Comment extraire un groupe capturé en regex VBA ?
Parcourez re.Execute(s) et lisez Match.SubMatches. SubMatches(0) est le premier groupe entre
parenthèses, SubMatches(1) le deuxième, et ainsi de suite (base zéro). Match.Value est le texte
correspondant entier, pas le groupe — lire .Value alors qu'on voulait un groupe est l'erreur
d'extraction la plus courante.
Faut-il ajouter une référence pour utiliser regex en VBA ?
Seulement pour la liaison précoce. Dim re As New RegExp exige la référence « Microsoft VBScript Regular
Expressions 5.5 » sous Tools -> References, et échoue à compiler avec Type défini par l'utilisateur non
défini si elle manque. La liaison tardive — Dim re As Object avec CreateObject("VBScript.RegExp") —
ne demande aucune référence et est le meilleur choix pour les classeurs que vous partagez.
Quelle saveur de regex VBA utilise-t-il, et prend-il en charge le lookbehind ?
VBA utilise la saveur VBScript (RegExp 5.5). Elle prend en charge \d \w \s, les quantificateurs,
l'alternance, les groupes, les classes de caractères et les ancres ^ $, et les références arrière de
remplacement avec $1. Elle ne prend pas en charge le lookbehind ni les groupes de capture nommés.
Aussi, parce que l'antislash n'est pas spécial dans les littéraux de chaîne VBA, vous écrivez "\d{4}"
directement sans double échappement.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 04/09/2026.
Guides associés : VBA Like · VBA IsNumeric · VBA InStr · VBA Replace · VBA Split
