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 :

Regex : comment limiter le nombre de matches dans une recherche


Sujet :

Macros et VBA Excel

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 66
    Points : 67
    Points
    67
    Par défaut Regex : comment limiter le nombre de matches dans une recherche
    Bonjour,
    Je ne connais pas grand chose en Regex.
    J'ai cette pattern ((\d{2} ){4})\d{2} qui me permet de récupérer des n° de téléphone formattés dans une chaine et qui fonctionne bien. Potentiellement, elle me retourne 0 à 3 matches; je voudrais ne prendre que les 2 premiers matches. Est-ce possible directement dans la Regex ou dois-je le faire comme actuellement en traitant mon tableau de matches ?
    Merci de votre aide.

  2. #2
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 951
    Points : 9 280
    Points
    9 280
    Par défaut
    Hello,
    peux-tu nous mettre ton code complet avec un exemple de données d'entrée et ce que tu veux en sortie (bien sûr pas avec de vrais numéros de téléphone).
    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  3. #3
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 383
    Points : 659
    Points
    659
    Par défaut
    Bonjour,

    Quand tu travailles avec les Regex, tu as la méthode Execute qui te renvoie une collection avec toutes les occurrences qui vérifient ton Pattern.
    Il te suffit donc de prendre les 2 premiers éléments de la collection.

    Si tu veux un peu de documentation, il existe ce tutoriel de Charles A. qui explique les bases des Regex en VBA, ça devrait t'aider
    Demain, je vais commencer par m'acheter des lunettes. Et après, je verrai bien.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 66
    Points : 67
    Points
    67
    Par défaut
    Merci à tous les deux d'avoir regardé mon problème
    @jurassic-pork
    cas le plus complet, certaines fois je n'ai pas de n° , pas de texte, un seul n° etc.
    chaine ="01 22 33 44 55 (standard)|06 45 45 45 45 (mobile)|01 22 33 44 66 (maintenance)"
    avec la regex "((\d{2} ){4})\d{2}" me ramène bien les 3 n°, ce que je voudrais, c'est limiter le nombre de résultats à 2 maximum (les 2 premiers)
    @mat955
    C'est ce que je fais, dans le tableau vba qui collecte les matches, je ne prends que les 2 premiers et ça marche, je voudrais juste savoir si c'était réalisable directement dans la regex

  5. #5
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 951
    Points : 9 280
    Points
    9 280
    Par défaut
    Comme tu peux avoir de 0 à 3 correspondances ça va être difficile de faire une expression régulière qui s'adapte à tous les cas. Qu'est-ce qui ne te plaît pas de le faire dans le traitement des résultats ? et tu ne nous as toujours pas montré ton code complet
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  6. #6
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2013
    Messages : 383
    Points : 659
    Points
    659
    Par défaut
    Je rejoins jurassic pork, les Regex ne sont faites que pour vérifier qu'une chaîne de caractère vérifie un pattern.
    Le plus simple est ensuite d'utiliser la collection pour ne garder que les 2 premiers résultats.
    Demain, je vais commencer par m'acheter des lunettes. Et après, je verrai bien.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 66
    Points : 67
    Points
    67
    Par défaut
    Merci de vos réponses.
    Rien ne me déplait dans le traitement des résultats pour limiter le nombre de retour à 2, c'est ce que je fais et ça marche bien.
    Comme je ne maitrise pas les regex c'était juste pour savoir si c'était possible.

    modèle code : https://www.ablebits.com/office-addi...strings-excel/
    Ci dessous un extrait du code, modèle ci dessus, modifié, qui reçoit en paramètres
    text : la chaine à scanner
    pattern : le motif
    instance_num : le n° de l'instance à retourner, 0 si toutes
    occur_max : le nombre de matches à utiliser (dans l'exemple, 2)
    concat_string : une chaine de concaténation pour joindre les résultats dans un chaine unique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
        Set matches = regex.Execute(text)
        'si correspondance trouvée
        If matches.count > 0 Then
            'si on retient toutes les instances
            If (instance_num = 0) Then
                'si un nombre maxi d'occurrences est précisé, on prend la valeur minimum
                If occur_max <> 0 Then
                    lLimite = IIf(matches.count < occur_max, matches.count, occur_max)
                'sinon on prend tous les résultats
                Else
                    lLimite = matches.count
                'finsi un nombre maxi d'occurences est précisé
                End If
                'on dimensionne un tableau selon la taille limite 
                ReDim text_matches(lLimite - 1)
                'on remplit le tableau
                For matches_index = 0 To lLimite - 1
                    text_matches(matches_index) = matches.Item(matches_index)
                Next matches_index
                'à la complétion du tableau, on concatène les postes, si nécessaire, on insère un séparateur
                If lLimite > 1 And concat_string <> "" Then
                    RegExpExtract = Join(text_matches, concat_string)
                Else
                    RegExpExtract = text_matches
                End If
            'sinon on retourne l'instance choisie
            Else
                RegExpExtract = matches.Item(instance_num - 1)
            'Finsi on retient toutes les instances
            End If
        'finsi correspondance trouvée
        End If

  8. #8
    Rédacteur
    Avatar de omen999
    Profil pro
    Inscrit en
    Février 2006
    Messages
    1 296
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 1 296
    Points : 3 549
    Points
    3 549
    Par défaut
    bonjour,
    Comme je ne maitrise pas les regex c'était juste pour savoir si c'était possible.
    oui
    démonstration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Dim res(1)
    text="header : 01 22 33 44 55 (standard)|06 45 45 45 45 (mobile)|01 22 33 44 66 (maintenance)"
    Set regex = CreateObject("VBScript.RegExp")
    regex.pattern = "((\d{2} ){4})\d{2}"
    regex.MultiLine = True
    For n = 0 to 1
    	Set matches = regex.Execute(text)
    	res(n) = matches(0)
    	text = Mid(text,matches(0).FirstIndex + matches(0).Length)
    Next
    MsgBox res(0) & " -- " & res(1)
    par défaut, la propriété Global de l'objet RegExp est False, ce qui signifie que la fonction Execute ne renvoie que la première occurrence qui vérifie le pattern.
    donc pour obtenir la deuxième occurrence, il suffit de reboucler en prenant soin d'appliquer la fonction Execute sur le texte raccourci (pour éviter de recapturer la première...)

    ps : en complément du premier article donné en lien, en voici un autre pour approfondir le sujet et t'aider à t'endormir
    nomen omen, nemo non omen - Consultez la FAQ VBScript et les cours et tutoriels VBScript
    le plus terrible lorsqu'une voiture renverse un piéton, c'est que ce sont les freins qui hurlent. (ramón)
    pas de questions techniques par mp

  9. #9
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 951
    Points : 9 280
    Points
    9 280
    Par défaut
    Hello,
    Citation Envoyé par omen999 Voir le message
    oui
    démonstration :
    sauf que la solution proposée ne fonctionne pas si il n'y a pas ou seulement un n° de téléphone dans le texte.
    Voici un code qui devrait fonctionner dans tous les cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Sub NumsTel()
    Dim res(1)
    Dim Text As String, i As Integer, j As Integer
    Dim regex As Object, matches As Object
    Dim Match
    Text = "header : 01 22 33 44 55 (standard)|06 45 45 45 45 (mobile)|01 22 33 44 66 (maintenance)"
    Set regex = CreateObject("VBScript.RegExp")
    regex.Pattern = "((\d{2} ){4})\d{2}"
    regex.Global = True
    Set matches = regex.Execute(Text)
    res(0) = "": res(1) = ""
    If matches.Count > 2 Then j = 1 Else j = matches.Count - 1
    For i = 0 To j
      res(i) = matches(i)
    Next
    Debug.Print res(0), res(1) 'res(0) = N° standard si disponible, res(1) = N° mobile si disponible
    Set matches = Nothing
    Set regex = Nothing
    End Sub
    Ami calmant, J.P
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 66
    Points : 67
    Points
    67
    Par défaut
    Merci à tous.
    Le sujet est résolu en ce qui me concerne.
    Je retiens que les regex ne permettent pas nativement de limiter le nombre maximum de réponses souhaité et qu'il convient de le faire dans le code encapsulant regex.

  11. #11
    Membre expérimenté
    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    667
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 667
    Points : 1 419
    Points
    1 419
    Par défaut
    Bonjour,

    Je dirais que c'est possible en te débrouillant pour que l'expression régulière récupère à la fois le 1er résultat et le 2nd résultat (si ce dernier existe) et en conservant reg.Global à False et reg.Multiline à False aussi (j'ai supposé que tes numéros pouvaient apparaître sur des lignes différentes):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ^[\s\S]*?((?:\d{2} ){4}\d{2})(?:\D[\s\S]*?((?:\d{2} ){4}\d{2}))?
    PS: J'ai modifié un peu tes parenthèses pour qu'elles capturent strictement les numéros de téléphone complet, ce qui me semble plus efficace.
    Chaque SubMatch comprend un numéro de téléphone.

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

Discussions similaires

  1. Comment limiter le nombre de threads dans mysql ?
    Par Bronks59 dans le forum Administration
    Réponses: 2
    Dernier message: 28/04/2017, 13h47
  2. [AC-2007] Comment limiter le nombre d'enregistrements dans une table
    Par arabi91 dans le forum Modélisation
    Réponses: 6
    Dernier message: 24/03/2012, 11h25
  3. [LUCENE] limitation du nombre de caratères dans une recherche
    Par ChristopheH dans le forum Développement Web en Java
    Réponses: 0
    Dernier message: 17/03/2010, 12h21
  4. limite du nombre de caractères dans une requete
    Par pheno82 dans le forum Access
    Réponses: 3
    Dernier message: 01/06/2006, 22h12
  5. [C#] Limité le nombre de lignes dans une DataView ...
    Par maitrebn dans le forum Accès aux données
    Réponses: 5
    Dernier message: 07/11/2005, 23h57

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