IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Simplifier une Expression Rationnelle [XL-2010]


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut Simplifier une Expression Rationnelle
    Bonjour à tous,

    Comme l'indique l'intitulé de la discussion, je cherche à simplifier une RegExp.

    Tout d'abord j'ai suivi le très bon tutoriel : Les Expressions Rationnelles appliquées en VBA Access

    Ma problématique vient de l'utilisation du quantificateur {x} pour répéter des motifs

    Avec :
    • la chaine "0.1.2.3.4.5.6.7.8.9"
    • le pattern (\d)\.(\d)\.(\d)\.(\d)\.(\d)\.(\d)\.(\d)\.(\d)\.(\d)\.(\d)

    => le test est True avec les 10 motifs "0", "1", "2", ... "8" et "9"


    J'aimerais simplifier l'écriture car dans mon cas réel il ne s'agit pas de simple digits séparé d'un "." mais de motif comme ceci : [A-Z]{3}\d\d[A-Z]{2} (ABC12DE) séparé d'un "."
    De plus il n'y en a pas 10 mais 32.

    Le pattern va donc être :
    ([A-Z]{3}\d\d[A-Z]{2})\.([A-Z]{3}\d\d[A-Z]{2})\. ...................... \.([A-Z]{3}\d\d[A-Z]{2}) (32 fois)
    En terme de maintenance on devine déjà que ça ne va pas être pratique.

    Comment simplifier l'expression en faisant probablement intervenir {31} pour avoir mes 32 motifs ?


    PS :
    • Dans le tutoriel ci-dessus, il y a l'exemple d'une adresse IP qui est constitué de 4 nombres <= 255 séparés d'un "." mais malheureusement le pattern du tutoriel ne renvoie pas les 4 motifs. (J'ai bien testé je vous le promets)
    • Je sais qu'un split pourrait être utilisé ici mais la méthode .Join sur un tableau est beaucoup moins puissante qu'un RegExp.Replace en terme de possibilité et de maintenance.

  2. #2
    Inactif  
    Homme Profil pro
    Analyste-Programmeur / Intégrateur ERP
    Inscrit en
    Mai 2013
    Messages
    2 511
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste-Programmeur / Intégrateur ERP
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 511
    Par défaut
    Bonjour,

    Si je suis le tutoriel, je dirais quelque chose comme ceci :

    reg.Pattern = "^(([A-Z]{3}\d\d[A-Z]{2})\.){31}([A-Z]{3}\d\d[A-Z]{2})$"
    Il me semble que cela correspond à ce que tu cherches à faire, cela me retourne bien true pour une chaine de 32 éléments séparés par un "." si le pattern est respecté et false sinon.

  3. #3
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut
    Merci Zirak pour ta réponse mais malheureusement ça ne fonctionne pas.
    Cette partie du tutoriel ne fonctionne pas sur les motifs. Le Test est juste encore que je ne suis pas si sur.

    J'avais testé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Sub test()
        AllRegExp "POI42AB.PIO40AC.POI42DG", "^(([A-Z]{3}\d\d[A-Z]{2})\.){2}([A-Z]{3}\d\d[A-Z]{2})$", ""
    End Sub
    Avec la fonction fourni dans le tuto :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Function AllRegExp(ByVal strSource As String, _
                       ByVal strPattern As String, _
                       ByVal strReplace As String)

    J'ai ça comme rendu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ==================================
          Travaux liés à .Execute
    ==================================
    source >>     POI42AB.PIO40AC.POI42DG
    [$1]          PIO40AC.
    [$2]          PIO40AC
    [$3]          POI42DG
    ==================================
            Travaux liés à .Test
    ==================================
    Vrai
    .Test est bien à VRAI mais les motifs sont faux et il y a un "." qui traine.

  4. #4
    Inactif  
    Homme Profil pro
    Analyste-Programmeur / Intégrateur ERP
    Inscrit en
    Mai 2013
    Messages
    2 511
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste-Programmeur / Intégrateur ERP
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 511
    Par défaut
    Je t'avoue que je n'ai pas testé au niveau du retour de chaque partie de la chaine (je ne me sers jamais de cette fonction, donc il y a surement des subtilités que je ne connais pas).

    Mais juste sur le test pour voir si la chaine correspond bien au pattern, j'ai essayé sur plusieurs chaines, c'est tombé juste à chaque fois, donc le pattern en lui-même est bon.


    Maintenant, si je suis le tuto, il s'agit de vérifier la présence d'un pattern au sein d'une chaine, puis d'afficher les différents éléments, alors que dans ton cas, le pattern correspond à la chaine entière, ce qui entraine peut-être ce dysfonctionnement ?

    Car si je test ceci en simplifiant le pattern (pour vérifier la présence d'une ou plusieurs sous-chaines de type ABD12AB dans ta chaine de 32 éléments), cela me retourne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Call AllRegExp(CStr(Range("B2")), "([A-Z]{3}\d\d[A-Z]{2})", "")

    ==================================
    Travaux liés à .Execute
    ==================================
    source >> ABC01AB
    [$1] ABC01AB
    source >> ABC02AB
    [$1] ABC02AB
    source >> ABC03AB
    [$1] ABC03AB
    source >> ABC04AB
    [$1] ABC04AB
    source >> ABC05AB
    [$1] ABC05AB
    source >> ABC06AB
    [$1] ABC06AB
    source >> ABC07AB
    [$1] ABC07AB
    source >> ABC08AB
    [$1] ABC08AB
    source >> ABC09AB
    [$1] ABC09AB
    source >> ABC10AB
    [$1] ABC10AB
    source >> ABC11AB
    [$1] ABC11AB
    source >> ABC12AB
    [$1] ABC12AB
    source >> ABC13AB
    [$1] ABC13AB
    source >> ABC14AB
    [$1] ABC14AB
    source >> ABC15AB
    [$1] ABC15AB
    source >> ABC16AB
    [$1] ABC16AB
    source >> ABC17AB
    [$1] ABC17AB
    source >> ABC18AB
    [$1] ABC18AB
    source >> ABC19AB
    [$1] ABC19AB
    source >> ABC20AB
    [$1] ABC20AB
    source >> ABC21AB
    [$1] ABC21AB
    source >> ABC22AB
    [$1] ABC22AB
    source >> ABC23AB
    [$1] ABC23AB
    source >> ABC24AB
    [$1] ABC24AB
    source >> ABC25AB
    [$1] ABC25AB
    source >> ABC26AB
    [$1] ABC26AB
    source >> ABC27AB
    [$1] ABC27AB
    source >> ABC28AB
    [$1] ABC28AB
    source >> ABC29AB
    [$1] ABC29AB
    source >> ABC30AB
    [$1] ABC30AB
    source >> ABC31AB
    [$1] ABC31AB
    source >> ABC32AB
    [$1] ABC32AB
    ==================================
    Travaux liés à .Test
    ==================================
    Vrai
    ==================================
    Travaux liés à .Replace
    ==================================
    ...............................



    Je retrouve bien mes 32 éléments.


    Au final, tu veux juste vérifier si le pattern de ta chaine est juste, ou tu as besoin de récupérer les différents éléments de ta chaine pour travailler dessus (et faire quoi dessus ?) ?


    EDIT:

    Citation Envoyé par antonysansh Voir le message
    .Test est bien à VRAI mais les motifs sont faux et il y a un "." qui traine.
    Alors le "." qui traine oui, mais attention, les motifs ne sont pas faux, la chaine que tu lui passe en argument, correspond bien au pattern passé lui aussi en argument, donc c'est normal que cela te retourne "vrai".

    ' Utilisation de .Test
    ' pour savoir si le motif a été trouvé sur la chaîne source
    Pour moi ce n'est pas fait pour t'indiquer si chaque sous-chaine a le bon motif.

  5. #5
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut
    Dans ton exemple c'est la propriété .Global a True qui renvoi toutes les sous-chaines qui match.

    Ce que je veux faire c'est récupérer mes 32 motifs pour les réorganiser selon les cas. Dans mes cas je ne vais pas toujours retourner les 32 motifs et pas toujours avec le même séparateur entre eux.

    Dans un cas par exemple je vais renvoyer $1.$2.$3 => $4
    dans d'autre $10-$20+$30 = $14

    D'où le fait de passer par une RegExp car un Split / Join ne me permets pas la réorganisation des la chaines.

  6. #6
    Inactif  
    Homme Profil pro
    Analyste-Programmeur / Intégrateur ERP
    Inscrit en
    Mai 2013
    Messages
    2 511
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste-Programmeur / Intégrateur ERP
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 511
    Par défaut
    Citation Envoyé par antonysansh Voir le message
    Dans ton exemple c'est la propriété .Global a True qui renvoi toutes les sous-chaines qui match.
    Non.

    La propriété .Global permet de définir si l'on traite seulement la 1ère occurrence, ou toutes, ensuite c'est la boucle qui retourne les résultats correspondants :

    que la variable soit à true ou false si ton motif n'est pas trouvé dans ta chaine => 0 retour
    que la variable soit à true ou false si ton motif n'est présent qu'une fois dans ta chaine => 1 retour

    Il n'y a que dans le cas où ton motif est présent plusieurs fois, qu'en fonction de ta variable, tu auras 1 ou plusieurs retours.


    Citation Envoyé par antonysansh Voir le message
    Ce que je veux faire c'est récupérer mes 32 motifs pour les réorganiser selon les cas. Dans mes cas je ne vais pas toujours retourner les 32 motifs et pas toujours avec le même séparateur entre eux.

    Dans un cas par exemple je vais renvoyer $1.$2.$3 => $4
    dans d'autre $10-$20+$30 = $14

    D'où le fait de passer par une RegExp car un Split / Join ne me permets pas la réorganisation des la chaines.

    1ère question :

    Au final, tes traitements avec tes motifs, pour les faire, as-tu besoin que la chaine complète respecte le schéma ABC12DE x32 avec le point comme séparateur ?


    2ème question :

    Si une ou plusieurs des sous-chaines n'a/ont pas le bon motif au sein de ta chaine, tu dois récupérer les sous-chaines concernées seulement ?
    Tu peux en récupérer des "avec", et des "sans" le bon motif dans le même traitement ?


    3ème question :

    Au final, quelles sont tes règles pour faire tes différents traitements ?

    Car tu dis que selon les cas, tu vas faire tel ou tel traitement, donc tu ne vas pas pouvoir tout gérer avec une seule regex, tu vas bien être obligé d'intercaler du VBA pour tester "je ne sais quoi", pour orienter ton traitement d'un côté ou de l'autre non ?

  7. #7
    Membre Expert Avatar de antonysansh
    Homme Profil pro
    Chargé d'études RH
    Inscrit en
    Mai 2014
    Messages
    1 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'études RH
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 1 115
    Par défaut
    Citation Envoyé par Zirak Voir le message
    Pour moi ce n'est pas fait pour t'indiquer si chaque sous-chaine a le bon motif.
    Je ne suis pas entièrement d'accord.

    Car le pattern "^\d{10}$" va être vrai uniquement si mon entrée est un nombre de 10 chiffres. "0123456789" est VRAI mais pas de motifs renvoyé

    Par contre "^(\d{5})(\d{5})$" va être vrai uniquement si mon entrée commence par un nombre de 5 chiffres et fini par un nombre de 5 chiffres avec rien entre les deux (donc un nombre de 10 chiffres).
    "0123456789" va être VRAI avec comme motifs $1 = "01234" et $2 = "56789"

  8. #8
    Inactif  
    Homme Profil pro
    Analyste-Programmeur / Intégrateur ERP
    Inscrit en
    Mai 2013
    Messages
    2 511
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste-Programmeur / Intégrateur ERP
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mai 2013
    Messages : 2 511
    Par défaut
    Citation Envoyé par antonysansh Voir le message
    Je ne suis pas entièrement d'accord.

    Car le pattern "^\d{10}$" va être vrai uniquement si mon entrée est un nombre de 10 chiffres. "0123456789" est VRAI mais pas de motifs renvoyé

    Par contre "^(\d{5})(\d{5})$" va être vrai uniquement si mon entrée commence par un nombre de 5 chiffres et fini par un nombre de 5 chiffres avec rien entre les deux (donc un nombre de 10 chiffres).
    "0123456789" va être VRAI avec comme motifs $1 = "01234" et $2 = "56789"
    Je pense que les parenthèses jouent beaucoup, je m'explique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Call AllRegExp(CStr(Range("B4")), "^\d{10}$", "")
    me renvoi effectivement (sans retour) :

    ==================================
    Travaux liés à .Execute
    ==================================
    source >> 2123456789
    ==================================
    Travaux liés à .Test
    ==================================
    Vrai
    ==================================
    Travaux liés à .Replace
    ==================================

    Alors que,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Call AllRegExp(CStr(Range("B4")), "^(\d{10})$", "")
    me renvoi la même chose (mais avec le retour) :

    ==================================
    Travaux liés à .Execute
    ==================================
    source >> 2123456789
    [$1] 2123456789
    ==================================
    Travaux liés à .Test
    ==================================
    Vrai
    ==================================
    Travaux liés à .Replace
    ==================================


    Les sous-motifs capturés entre parenthèses sont mis dans des variables de type Perl $1, $2 ... $n
    Si tu ne mets pas de parenthèses, c'est normal que tu n'ais pas de retour de ce que j'en comprends.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2007] [RegExp]Mettre une negation dans une Expression Rationnelle
    Par EvaristeGaloisBis dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 08/08/2013, 18h34
  2. Recherche avec une expression rationnelle
    Par romanegr dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 26/01/2008, 20h01
  3. Vérifier une expression rationnelle
    Par senacle dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 25/01/2008, 16h35
  4. Problème avec une expression rationnelle.
    Par Pragmateek dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 11/06/2006, 20h34
  5. simplifier une expression math ?
    Par kanzarih dans le forum Delphi
    Réponses: 7
    Dernier message: 23/05/2006, 23h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo