VBA - Initiation aux expressions rationnelles

Septembre 2016



Introduction

Ce tutoriel est loin de vous expliquer toutes les subtilités liées aux expressions rationnelles. Nous n'allons aborder ici que le préambule à leur utilisation. Il existe d'autres tutoriels bien plus documentés sur Internet.

Le but ici est d'apprendre à parcourir des chaînes (String), d'y trouver des sous-chaînes grâce à un motif. Ce motif sera indiqué par un schéma, une notation particulière : l'expression rationnelle.

Nous allons donc découvrir les Expressions Rationnelles (plus communément appelées RegExp) par l'exemple.

Référence à cocher

Dans votre éditeur VBA, dans le menu outils, allez dans références.
Parcourez les différentes références et cochez : "Microsoft vbscript regular expression 5.5"

Syntaxe et déclaration

Dans ces exemples, les seuls termes dont nous aurons besoin sont :

La déclaration

Deux possibilités s'offrent à nous :

As Object

Probablement la plus simple à retenir...
Le code :

Dim reg As Object
Set reg = CreateObject("vbscript.regexp")

VBScript_RegExp_55.regexp

Cette notation est probablement plus conventionnelle.

Dim reg As VBScript_RegExp_55.regexp
Set reg = New VBScript_RegExp_55.regexp

Les propriétés à connaitre pour ce tutoriel

Peu importe comment vous avez déclaré votre RegExp, les propriétés auront la même syntaxe.

Pattern

Le Pattern représente le motif que doit respecter la sous-chaîne. Il est ce que nous allons chercher à trouver dans la chaîne. Sa notation revêt un caractère de simplification lorsque l'on utilise les expressions régulières.
Le code correspondant :

reg.Pattern = "IciLeMotif"

Test

Comme son nom l'indique, va tester la chaîne et, si le Pattern (motif) y figure, va revoyer True. Il s'agit d'un Boolean.
Le code correspondant :

reg.Test(expression_à_tester)


Ceci étant vu, nous pouvons commencer nos exemples.

La chaîne commence par "A" Majuscule

Le Pattern serait donc :
  • en début de chaîne,
  • il y a un A

La notation de ce motif est : ^A, tout simplement, que l'on placera entre guillemets.

Function Prem_Lettre_A(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'Le Pattern est le motif que l'on recherche
'début de chaîne : ^
'doit être : A
reg.Pattern = "^A"
'le test renvoie un Boolean (parfait pour notre fonction Booléenne!!!)
Prem_Lettre_A = reg.test(expression)
End Function


La procédure d'appel pour tester :

Sub Test_A()
'Nous allons chercher si un String commence par "A" Majuscule
MsgBox Prem_Lettre_A("alors?")
MsgBox Prem_Lettre_A("Ahhh")
MsgBox Prem_Lettre_A("Pas mal non?")
End Sub

Commence par a ou A

Ici, nous allons simplement identifier la première lettre, sans respecter de casse.
La notation pour la lettre a sans tenir compte de la casse est : [aA]

Sub Test_a_ou_A()
'Nous allons chercher si un String commence par "a" ou "A"
MsgBox Prem_Lettre_a_ou_A("alors?")
MsgBox Prem_Lettre_a_ou_A("Ahhh")
MsgBox Prem_Lettre_a_ou_A("Pas mal non?")
End Sub

Function Prem_Lettre_a_ou_A(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'ici la première lettre : ^
'doit être : a ou A => [aA]
reg.Pattern = "^[aA]"
Prem_Lettre_a_ou_A = reg.test(expression)
End Function

Commence par une lettre Majuscule

Peu importe la lettre, tant que celle-ci est en majuscule. La simplicité des RegExp, et surtout de sa notation nous donne : [A-Z]

Sub Commence_par_Majuscule()
MsgBox "alors? commence par une majuscule : " & Prem_Lettre_Majuscule("alors?")
MsgBox "Ahhh commence par une majuscule : " & Prem_Lettre_Majuscule("Ahhh")
MsgBox "Pas mal non?  commence par une majuscule : " & Prem_Lettre_Majuscule("Pas mal non?")
End Sub

Function Prem_Lettre_Majuscule(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'ici la première lettre : ^
'doit être une lettre Majuscule : [A-Z]
reg.Pattern = "^[A-Z]"
Prem_Lettre_Majuscule = reg.test(expression)
End Function

Se termine par

Jusqu'alors nous avions vu "commence par", soit ^. La chaîne se termine par se note : $, tout simplement.

Sub Fini_Par()
MsgBox "La phrase : Les RegExp c'est super! se termine par super : " & Fin_De_Phrase("Les RegExp c'est super!")
MsgBox "La phrase : C'est super les RegExp! se termine par super : " & Fin_De_Phrase("C'est super les RegExp!")
End Sub

Function Fin_De_Phrase(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'La fin de la chaine doit être : super!
'notation de fin de chaîne : $
reg.Pattern = "super!$"
'note le $ se place à la fin...
Fin_De_Phrase = reg.test(expression)
End Function

Contient un chiffre

La notation de "un chiffre" coule de source. [0-9].
Si nous avions souhaité trouver un chiffre entre 3 et 7 nous aurions pu écrire : [3-7]

Sub Contient_un_chiffre()
MsgBox "aze1rty contient un chiffre : " & A_Un_Chiffre("aze1rty")
MsgBox "azerty contient un chiffre : " & A_Un_Chiffre("azerty")
End Sub

Function A_Un_Chiffre(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'doit comporter un chiffre de 0 à 9 n'importe ou (début, milieu, fin de chaine...)
reg.Pattern = "[0-9]"
'remarque [0-9] s'écrit également : \d
    'reg.Pattern = "\d"
A_Un_Chiffre = reg.test(expression)
End Function

Contient un nombre à 3 chiffres

Nous allons maintenant "quantifier" dans notre RegExp. Pour écrire au code qu'il faut trouver 3 occurrences, il convient d'utiliser les accolades : {}.

Sub Contient_Un_Nombre_A_trois_Chiffres()
MsgBox "aze1rty contient 3 chiffres : " & Nb_A_Trois_Chiffre("aze1rty")
MsgBox "a1ze2rty3 contient 3 chiffres : " & Nb_A_Trois_Chiffre("a1ze2rty3")
MsgBox "azer123ty contient 3 chiffres : " & Nb_A_Trois_Chiffre("azer123ty")
End Sub

Function Nb_A_Trois_Chiffre(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'doit comporter 3 chiffres de 0 à 9 qui se suivent
'le nombre d'occurrence se note {}
reg.Pattern = "\d{3}" 'équivalant de : reg.Pattern = "[0-9]{3}"
Nb_A_Trois_Chiffre = reg.test(expression)
End Function

Contient 3 chiifres séparés

Code

Sub Contient_trois_Chiffres()
MsgBox "aze1rty contient 3 chiffres séparés : " & Trois_Chiffre("aze1rty")
MsgBox "a1ze2rty3 contient 3 chiffres séparés : " & Trois_Chiffre("a1ze2rty3")
MsgBox "azer123ty contient 3 chiffres séparés : " & Trois_Chiffre("azer123ty")
End Sub

Function Trois_Chiffre(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'doit comporter 3 chiffres de 0 à 9 qui ne se suivent pas
'le nombre d'occurrence se note {}
'le point (.) indique n'importe quel caractère sauf le saut de ligne
'le + indique que ce qui le précède (ici le point) doit être représenté une ou une infinité de fois
reg.Pattern = "(.)+(\d{1})(.)+(\d{1})(.)+(\d{1})"
Trois_Chiffre = reg.test(expression)
End Function

Variante

Sub Contient_trois_Chiffres_Variante()
MsgBox "aze1rty contient 3 chiffres séparés : " & Trois_Chiffre_Simplifiee("aze1rty")
MsgBox "a1ze2rty3 contient 3 chiffres séparés : " & Trois_Chiffre_Simplifiee("a1ze2rty3")
MsgBox "azer123ty contient 3 chiffres séparés : " & Trois_Chiffre_Simplifiee("azer123ty")
End Sub

Function Trois_Chiffre_Simplifiee(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'Comme le même motif : (.)+(\d{1}) se répète trois fois :
reg.Pattern = "(.+\d{1}){3}"
Trois_Chiffre_Simplifiee = reg.test(expression)
End Function

Exemple concret

Ici le but sera de définir si la chaine est un enchainement précis de :
  • 1 : Le mot Vis au début de la chaine,
  • 2 : suivi d'un espace,
  • 3 : suivi de 1 à 3 lettres,
  • 4 : suivi d'un espace,
  • 5 : suivi de la lettre M,
  • 6 : suivie de 1 à 2 lettres,
  • 7 : suivie d'un tiret,
  • 8 : suivi de 1 à 3 lettres,
  • 9 : suivi du mot classe entouré d'espace ET en minuscules,
  • 10 : suivi d'1 à 2 lettres,
  • 11 : suivi d'un point,
  • 12 : suivi d'une lettre.

A savoir :
Chaque bloc du motif est entouré de parenthèses.

Notation :
1- => (^Vis) ^ représente le début de la chaine et Vis respecte la casse (Majusc, minusc)
2- => ( )
3- => ([a-zA-Z]{1,3})
4- => ( ) --- Note : on aurait pu l'insérer avec le M qui suit... Mis pour l'exemple
5- => (M)
6- => ([a-zA-Z]{1,2})
7- => ( -)
8- => ([a-zA-Z]{1,3})
9- => ( classe )
10- => ([a-zA-Z]{1,2})
11- => (\.)
12- => ([a-zA-Z]{1})

Ce qui nous donne le motif suivant :
"(^Vis)( )([a-zA-Z]{1,3})( )(M)([a-zA-Z]{1,2})(-)([a-zA-Z]{1,3})( classe )([a-zA-Z]{1,2})(.)([a-zA-Z]{1})"

Le code :

Sub Main()
If VerifieMaChaine("Vis xx Mxx-x classe xx.x") Then
    MsgBox "good"
Else
    MsgBox "pas glop"
End If
'manque l'espace avant le M :
If VerifieMaChaine("Vis xxMxx-x classe xx.x") Then
    MsgBox "good"
Else
    MsgBox "pas glop"
End If
End Sub

Function VerifieMaChaine(expression As String) As Boolean
Dim reg As Object

Set reg = CreateObject("vbscript.regexp")
'Il y a forcément plus simple, mais c'est juste un exemple pour être le plus clair possible
reg.Pattern = "(^Vis)( )([a-zA-Z]{1,3})( )(M)([a-zA-Z]{1,2})(-)([a-zA-Z]{1,3})( classe )([a-zA-Z]{1,2})(.)([a-zA-Z]{1})"
VerifieMaChaine = reg.test(expression)
End Function
End Sub

Conclusion & téléchargement

Les codes donnés dans ce tutoriel sont tous réunis dans ce classeur exemple.

Vous pouvez maintenant tester des chaînes sans avoir d'exactitude sur la sous-chaine à y trouver.

Je vous invite à aller voir d'autres tutoriels à ce sujet, notamment, pour continuer l'apprentissage, celui de caféine.

A voir également :

Ce document intitulé «  VBA - Initiation aux expressions rationnelles  » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.