Expressions régulières - Patterns pour RegExp

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re re

En fait, cela dépend du résultat auquel tu veux arriver : là pour l'instant, tu travailles sur un type de format décliné en "dddd d mmm yyyy" et "d mmmm yyyy".
Si ton but est de ne rester que sur ce type en incluant le cas particulier de février afin d'obtenir une date valide, c'est une chose.

Si le but est d'élargir à d'autres types (jj/mm/aaaa, jj/mm/aa, jj mm aa,...), ce que ne te permet pas ton code de "formatage" actuel, il faudra voir comment l'imbriquer si c'est jouable.

Dans ce cas, il te faut reprendre ta partie formatage (ou tester directement sur une plage de cellules avec des chaînes de caractères "formatées" différemment et juste pour tester, tu peux simplement l'inclure tel quel dans le motif existant pour voir si cela fonctionne ou pas sur d'autres formats :

Code:
.Pattern = "(0?[1-9]|[12]\d|3[01])[ /](" & MOIS & ")[ /](\d{2,4})|((0[1-9]|[12]\d|3[01])/(0[13578]|1[02])|(0[1-9]|[12]\d|30)/(0[469]|11))/((16|17|18|19|20|21)\d\d)|(0[1-9]|[1]\d|[2][0-8])/02/((16|17|18|19|20|21)\d\d)|29/02/((17|18|19|21[0])[48]|(17|18|19|20|21)([13579][26]|[2468][048])|(160|200)[048])"

Si c'est OK, on pourra alors chercher à l'abstraire.

A+
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re JM
en attendant tes éclaircissements à mon message précédent, j'ai l'impression que si tu veux traiter spécifiquement de février, tu dois le sortir de tes constantes Mois et créer une autre constante spécifique, à moins que tu ne délaisses l'utilisation des constantes au profit d'un array dans lequel tu pourrais faire référence à l'indice de février pour le sélectionner dans ton motif.
Qu'en pense-tu ?
Maintenant, tu avais peut-être une idée particulière en tête...:eek:
A+
 

Staple1600

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Bonsoir à tous

David84
Le but du jeu c'est de pouvoir extraire un date au sein d'une string quelconque non et de de transformer cette sous-chaine valide, non ?
Alors comme cela me délasses, j'y vais à tâtons et m'amuse avec RegExp.
C'est avant tout un divertissement, je ne poursuis donc aucun but précis.

tu travailles sur un type de format décliné en "dddd d mmm yyyy" et "d mmmm yyyy".
Non , j'ai pris ces formats juste pour tester.
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re JM

Le but du jeu c'est de pouvoir extraire un date au sein d'une string quelconque non et de de transformer cette sous-chaine valide, non ?
Selon moi, le but du jeu est d'extraire une date quelle que soit la chaîne de caractères sous laquelle elle est écrite et d'en vérifier sa validité (ex : le 31 avril 2011 ou le 29 02 2011 ne sont pas valides, contrairement au 25 janvier 2011 ou le 29 février 2012).

Alors comme cela me délasses, j'y vais à tâtons et m'amuse avec RegExp.
C'est avant tout un divertissement, je ne poursuis donc aucun but précis.

OK mais si j'ai bien compris ta demande, tu cherchais comment inclure le traitement de février et des années bissextiles dans le motif, d'où ma réponse.
Avais-je mal compris ton attente ?
A+
 

Staple1600

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re


Je n'ai pas vraiment d'attente ;)
J'ai été impressionné par ta fonction et tes motifs.
Cela a éveillé ma curiosité.

J'ai voulu parcourir d'autres chemins que les tiens (et ceci sans autre but que le plaisir de faire du regexp dans Excel)

sauf que le chemin est plus ardu que je ne m'y attendais.

Mais puisque ta fonction fonctionne telle quelle, je pense que je peux arrêter là pour le moment de me creuser les méninges.
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re JM:)

et bien moi je trouve que ton approche avec les constantes est réellement intéressante et d'ailleurs si tu pouvais m'expliquer un peu plus cette syntaxe et ce qu'elle permet de faire, cela m'intéresserait :

Const MOIS As String = _
"(janv(ier)?|févr(ier)?|mar(s)?|avr(il)?|mai?|juin?|juil(let)?|août?|sept(embre)?|oct(obre)?|nov(embre)?|déc(embre)?)"

- Rôle des parenthèses, du "|" et du "?".
- Est-ce la même syntaxe avec la même signification que le Regexp ?
- Est-ce du RegExp ?

Après, à voir si l'on peut traiter février avec ces constantes telles quelles ou si l'on doit créer une constante "févr(ier) spécifique ou bien plutôt passer par un Array comme dans la fonction TestDate.

D'autre part, continuons à nous amuser à faire du RegExp en traitant autre chose que les dates comme tu l'avais proposé.
As-tu un thème sur lequel tu aimerais te triturer les méninges:p ?
A+
 

Staple1600

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re

Le pipe
|L’opérateur de choix (aussi appelé opérateur d’alternation ou d’union d’ensembles) fait correspondre l’expression avant ou après l’opérateur.abc|def correspond à "abc" ou "de

?Ce quantificateur, qui n’est reconnu comme tel qu’en dehors d’une classe de caractères (dans une classe il désigne littéralement le caractère correspondant), fait correspondre zéro ou une seule fois l’élément qui le précède. Contrairement à l’opérateur standard, l’élément qui précède peut être aussi un groupe.ba? correspond à "b" ou "ba".

source

C'est donc du RegExp
Pour ce qui est de l'idée que j'avais émis plus bas dans le fil, je ne sais si finalement il ne vaudrait pas mieux réaliser une sorte compilations des sources sur le web dédiés au RegExp, car ce n'est pas évident de trouver des champs d'applications qui n'ont pas déjà été traité ailleurs.
Mais rien ne nous interdit de les mettre en situation dans Excel.
(De plus, il y a déjà le fil de JNP qui est bien fourni en exemples divers et variés)
A priori, comme je disais plus bas, on risque de refaire ce qui a déjà été fait ailleurs ;)
(ex: validation de mail, extraction éléments d'une adresse, validité numéro sécu, CB, SIRET, extraction patronyme etc...)



 
Dernière édition:

JNP

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re :),
Je continue toujours de suivre avec intérêt ;)
Ton dernier propos Jean-Marie, etaye les risques que j'évoquais avec l'opérateur | :p...
En effet, on aurait pu s'attendre à ce qu'il soit prioritaire sur les autres opérations, donc que logiquement, abc|def accepte abcef ou abdef uniquement :eek:... Alors qu'effectivement, quelques tests prouvent le contraire :

Pattern
Chaine
Résultat
abc|def
abc
abc
abc|def
abcdef
abc,def
abc|def
def
def
ab(c|d)ef
abdef
abdef
ab(c|d)ef
abcef
abcef
(abc)|(def)
abcdef
abc,def
(abc)|(def)
abdef
def

Bonne suite :cool:
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re Jean-Noël,
Ton dernier propos Jean-Marie, etaye les risques que j'évoquais avec l'opérateur | ...
Tu as raison mais ce n'est pas un risque à proprement parler, juste le fait de connaître la syntaxe, et c'est vrai que ce n'est pas toujours évident:confused: :

Cela dépend donc de ce que l'on veut rechercher comme précisé ici :
"fran(ce|co|c)" correspond exclusivement à l'un des trois mots suivants : "franc", "france", "franco"
En revanche "fran[ceo]{1,2}" correspond à "franc, frane", "frano", "france", "franeo", "franco", etc...

Code:
Sub test()
Dim Matches, oRegexp, s
Set oRegexp = CreateObject("VBScript.RegExp")
s = "abcdef"
MsgBox "chaîne à traiter : " & s
With oRegexp
.Global = -1: .IgnoreCase = -1
.Pattern = "ab[cd]{1,2}ef"
Set Matches = .Execute(s)
If Matches.Count > 0 Then MsgBox "chaine correspondant au motif ab[cd]{1,2}ef : " & vbCrLf & Matches.item(0) Else _
MsgBox "chaine correspondant au motif ab[cd]{1,2}ef : " & vbCrLf & "aucun item trouvé"
.Pattern = "ab(c|d)ef"
Set Matches = .Execute(s)
If Matches.Count > 0 Then MsgBox "chaine correspondant au motif ab(c|d)ef : & vbcrlf & " & Matches.item(0) Else _
MsgBox "chaine correspondant au motif ab(c|d)ef : " & vbCrLf & "aucun item trouvé"

s = "abcef"
MsgBox "chaîne à traiter : " & s
.Pattern = "ab[cd]{1,2}ef"
Set Matches = .Execute(s)
If Matches.Count > 0 Then MsgBox "chaine correspondant au motif ab[cd]{1,2}ef : " & vbCrLf & Matches.item(0) Else _
MsgBox "chaine correspondant au motif ab[cd]{1,2}ef : " & vbCrLf & "aucun item trouvé"
.Pattern = "ab(c|d)ef"
Set Matches = .Execute(s)
If Matches.Count > 0 Then MsgBox "chaine correspondant au motif ab(c|d)ef : " & vbCrLf & Matches.item(0) Else _
MsgBox "chaine correspondant au motif ab(c|d)ef : " & vbCrLf & "aucun item trouvé"

End With
End Sub

A+
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Bonjour,
Ci-joint une nouvelle version de la fonction.

La modification touche le traitement des mois.

Le fait de stocker dans un Array tous les types de "formatages" possibles est tout à fait jouable mais peut devenir encombrant.
Donc, l'idée est d'adapter l'idée des constantes proposée par Jean-Marie:) tout en restant dans un Array.

Cet Array stocke 12 valeurs correspondant aux motifs de chaque mois.

Chaque motif est ensuite confronté à la chaîne de caractère et lorsque le mois est détecté, il est remplacé par l'index formaté de l'Array correspondant à ce mois.

Cette possibilité nous permet donc de ne pas nous retrouver avec un Array important et les formats actuellement non pris en compte devront simplement être rajoutés dans les masques des valeurs de l'Array.

Notre Array actuel comportera donc toujours 12 valeurs (contre 35 dans la version précédente) tout en prenant en compte des formats non prévus dans la version précédente.

Le code peut être simplifié ici ou là, mais je vous livre l'idée pour tester (onglet test_date2, dans l'onglet test_date figure l'ancienne version).

Code:
Function testDate2(Cellule As Range, Rang As Integer) As String
'Application.Volatile
Dim oRexp, Match, Matches, MesMois, i As Integer, MaChaine As String, MonPattern As String, k As Byte
If Cellule = "" Then Exit Function

Set oRexp = CreateObject("vbscript.regexp")
MesMois = Array("janv(\s|\.\-|\.|\-|ier)", "(févr|fevr)(\s|\.\-|\.|\-|ier)", "mars(\s|\.\-|\.|\-)", "avr(\s|\.\-|\.|\-|il)", "mai(\s|\.\-|\.|\-)", "juin(\s|\.\-|\.|\-)", _
"juil(\s|\.\-|\.|\-|et)", "(août|aout)(\s|\.\-|\.|\-)", "sept(\s|\.\-|\.|\-|embre)", "oct(\s|\.\-|\.|\-|obre)", "nov(\s|\.\-|\.|\-|embre)", "(déc|dec)(\s|\.\-|\.|\-|embre)")

MaChaine = LCase(Cellule.Value)

With oRexp
    .Global = True
    .IgnoreCase = True
    
    'traitement du mois
    For i = LBound(MesMois) To UBound(MesMois)
    .Pattern = MesMois(i)
        Set Matches = .Execute(MaChaine)
        If .test(MaChaine) = True Then
         For k = 0 To Matches.Count - 1          
                  MaChaine = Replace(Replace(Replace(MaChaine, Matches.item(k), "/" & Format(i + 1, "00") & "/"), " /", "/"), "/ ", "/")
           Next k
        End If
    Next i
    
    'traitement du jour
    .Pattern = "(?:\s|\b)(\d{1})([ /-]\d{1,2}[ /-])(\d{2,4})(?:\s|\b)"
    Set Matches = .Execute(MaChaine)
    MaChaine = .Replace(MaChaine, " 0$1$2$3 ")
    
    'traitement de l'année
    .Pattern = "(?:\s|\b)(\d{1,2})([ /-]\d{1,2}[ /-])((?:0|1|2){1}[0-9])(?:\s|\b)" 'années 2000 à 2 chiffres
    Set Matches = .Execute(MaChaine)
    MaChaine = .Replace(MaChaine, " $1$220$3 ")
       
    .Pattern = "(?:\s|\b)(\d{1,2})([ /-]\d{1,2}[ /-])((?:3|4|5|6|7|8|9){1}[0-9])(?:\s|\b)" 'années 1900 à 2 chiffres
    Set Matches = .Execute(MaChaine)
    MaChaine = .Replace(MaChaine, " $1$219$3 ")
    .Pattern = "((0[1-9]|[12]\d|3[01])[ /-](0?[13578]|1[02])|(0[1-9]|[12]\d|30)[ /-](0?[469]|11))[ /-]((16|17|18|19|20|21)\d\d)|(0[1-9]|[1]\d|[2][0-8])[ /-]0?2[ /-]((16|17|18|19|20|21)\d\d)|29[ /-]0?2[ /-]((190|210)[48]|(17|18|19|20|21)([13579][26]|[2468][048])|(160|200)[048])"
    If .test(MaChaine) = True Then
        Set Matches = .Execute(MaChaine)
        If Rang - 1 < Matches.Count Then testDate2 = Format(Matches(Rang - 1), "dd/mm/yyyy")
    Else
        If Rang = 1 Then testDate2 = "Aucune date valide"
    End If
End With
End Function
A+
 
Dernière édition:

Dull

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Salut les fadas du cervelet à datepéremptoirenondéfinie :)

Z'êtes de grands malades les gars... Surtout David:)... JNP :)... est en haut de la liste...Tant qu'a l'agrafe:D... il décroche le pompon Bref... des cerveaux qui nous rendent, nous pauvres Excielliens, Envieux et admiratifs :D

Merci pour vos décarcassages de neurones j'ai beau m'accrocher mais ...

Les dates sont souvent sources de problèmes et je suis admiratif devant vos tests :)

je ne peux que vous encourager à poursuivre vos efforts

@David
si, dans ton dernier fichier, en B1 on écrit
Code:
je suis né le lundi 13 juillet 1964 à 15 heures
en C1 j'ai
Code:
Aucune date valide
...commentça...aucunedatevalide???...:mad:... je te signal que je poste...Donc je suis... :p alors que si j'écris
Code:
13/07/64
en lieu et place de
Code:
lundi 13 juillet 1964
cela fonctionne bien:confused:

De plus, en B8 si j’inscris
Code:
je suis né le lundi 13 juillet 1964 à 15 heures et je me suis marié le 11 septembre 1992 à Saint-pierre
en C1 je n'ai que la date de mon mariage alors que la date (1ère dans la phrase) au format "dd/mm/aaaa" fonctionne nickel

Bref...y'aencoreduboulot :) mais j'ai foi en vous mes amis:)

Encore merci de nous faire partager cela :)
Excellente Journée mes amis
...et moi je vais vais prendre 2 Dolicranes ;)
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re Dull:),
Bravo pour ce test.
C'est simplement parce que le 2ème l (lettre L) de juillet avait été oublié dans le motif
"juil(\s|\.\-|\.|\-|et)"
qu'il faut remplacer par
"juil(\s|\.\-|\.|\-|let)"

Le code réactualisé donne donc :

Code:
Function testDate2(Cellule As Range, Rang As Integer) As String
'Application.Volatile
Dim oRexp, Match, Matches, MesMois, i As Integer, MaChaine As String, MonPattern As String, k As Byte
If Cellule = "" Then Exit Function

Set oRexp = CreateObject("vbscript.regexp")
MesMois = Array("janv(\s|\.\-|\.|\-|ier)", "(févr|fevr)(\s|\.\-|\.|\-|ier)", "mars(\s|\.\-|\.|\-)", "avr(\s|\.\-|\.|\-|il)", "mai(\s|\.\-|\.|\-)", "juin(\s|\.\-|\.|\-)", _
"juil(\s|\.\-|\.|\-|let)", "(août|aout)(\s|\.\-|\.|\-)", "sept(\s|\.\-|\.|\-|embre)", "oct(\s|\.\-|\.|\-|obre)", "nov(\s|\.\-|\.|\-|embre)", "(déc|dec)(\s|\.\-|\.|\-|embre)")

MaChaine = LCase(Cellule.Value)

With oRexp
    .Global = True
    .IgnoreCase = True
    
    'traitement du mois
    
    For i = LBound(MesMois) To UBound(MesMois)
    .Pattern = MesMois(i)
        Set Matches = .Execute(MaChaine)
        If .test(MaChaine) = True Then
         For k = 0 To Matches.Count - 1
                  MaChaine = Replace(Replace(Replace(MaChaine, Matches.item(k), "/" & Format(i + 1, "00") & "/"), " /", "/"), "/ ", "/")
           Next k
        End If
    Next i
    
    'traitement du jour
    .Pattern = "(?:\s|\b)(\d{1})([ /-]\d{1,2}[ /-])(\d{2,4})(?:\s|\b)"
    Set Matches = .Execute(MaChaine)
    MaChaine = .Replace(MaChaine, " 0$1$2$3 ")
    
    'traitement de l'année
    .Pattern = "(?:\s|\b)(\d{1,2})([ /-]\d{1,2}[ /-])((?:0|1|2){1}[0-9])(?:\s|\b)" 'années 2000 à 2 chiffres
    Set Matches = .Execute(MaChaine)
    MaChaine = .Replace(MaChaine, " $1$220$3 ")
       
    .Pattern = "(?:\s|\b)(\d{1,2})([ /-]\d{1,2}[ /-])((?:3|4|5|6|7|8|9){1}[0-9])(?:\s|\b)" 'années 1900 à 2 chiffres
    Set Matches = .Execute(MaChaine)
    MaChaine = .Replace(MaChaine, " $1$219$3 ")
    .Pattern = "((0[1-9]|[12]\d|3[01])[ /-](0?[13578]|1[02])|(0[1-9]|[12]\d|30)[ /-](0?[469]|11))[ /-]((16|17|18|19|20|21)\d\d)|(0[1-9]|[1]\d|[2][0-8])[ /-]0?2[ /-]((16|17|18|19|20|21)\d\d)|29[ /-]0?2[ /-]((190|210)[48]|(17|18|19|20|21)([13579][26]|[2468][048])|(160|200)[048])"
    If .test(MaChaine) = True Then
        Set Matches = .Execute(MaChaine)
        If Rang - 1 < Matches.Count Then testDate2 = Format(Matches(Rang - 1), "dd/mm/yyyy")
    Else
        If Rang = 1 Then testDate2 = "Aucune date valide"
    End If
End With
End Function

Fichier réactualisé et dans lequel figurent tes 2 exemples.
Merci et si tu vois d'autres choses, n'hésite pas.
A+
 

Pièces jointes

  • Test_date_format_14_01.xls
    110 KB · Affichages: 46
Dernière édition:

Dull

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re Dull:),
Bravo pour ce test.
C'est simplement parce que le 2ème l (lettre L) de juillet avait été oublié dans le motif qu'il faut remplacer par
...

de rien mon ami David :) quelques minutes pour trouver la réponse: Chapeau... tu maitrise vraiment les RegExp :) j'ai presque compris...:p dieumercirienn'estperdu:eek: je poursuis mes tests et tacherais de te coller une nouvelle fois :D

"juil(\s|\.\-|\.|\-|et)"
"juil(\s|\.\-|\.|\-|let)"

Bonne Journée
 

david84

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Re
je poursuis mes tests et tacherais de te coller une nouvelle fois
Mais c'est le but des tests:rolleyes: !
Pense à tester non seulement différentes dates (entre le 01/01/1600 et le 31/12/2199), mais attention, sous forme de texte de
...01/01/1654............2 janv 1889.............3 3 65.......4 6-09...
, mais également les différents formats de chaîne de caractères avec le jour et l'année en chiffres (pour le jour 1 ou 2 chiffres et pour l'année 2 ou 4 chiffres).

D'ailleurs il suffit à chacun de ceux qui passent de tester ne serait-ce que 10 chaînes de caractères comportant 1 ou plusieurs dates pour faire avancer la mise au point de cette fonction.
Il suffit ensuite de placer ces tests sur ce fil et je les incorporerai dans le fichier.
A+
 
Dernière édition:

Tibo

XLDnaute Barbatruc
Re : Expressions régulières - Patterns pour RegExp

Salut David,

J'ai régulièrement suivi ce fil sans intervenir (car j'en étais bien incapable), mais en étant sincèrement très admiratif (voire davantage) de la puissance de ton analyse du problème.

Je tiens simplement à te dire BRAVO DAVID pour cette œuvre et j'ai une pensée pour le paquet de neurones que tu as dû griller :p

J'ai bien entendu testé ton application, et bien entendu, ne suis pas parvenu à la prendre en défaut.

Merci à toi de mettre à disposition sur le Forum de si belles œuvres, de si beaux bijoux.

Au plaisir de te recroiser.

@+
 

Statistiques des forums

Discussions
312 428
Messages
2 088 338
Membres
103 821
dernier inscrit
Lorient56