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

  1. #1
    Membre régulier
    Homme Profil pro
    Automaticien
    Inscrit en
    décembre 2015
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Automaticien

    Informations forums :
    Inscription : décembre 2015
    Messages : 84
    Points : 107
    Points
    107
    Par défaut [Outil-E] Récupérer le nom des membres d'une énumération
    Bonjour,

    Ayant eu besoin de retrouver le nom d'un membre d'une énumération par rapport à sa valeur en Long, j'ai créé une fonction qui permet de retrouver la liste des membres sous forme d'un Dictionnary.
    Le dictionnaire renvoie dans key, la valeur Long de l'énumération.
    Et dans item, un string contenant le nom de l'énumération.

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    'A pour but de récupérer un dictionnaire comportant la liste des membres d'une énumération
    'Où Key = Valeur / Item = eMembreEnumeration
        '@Param strEnumName : Nom de l'énumération à rechercher
        '@Param strModuleName : Module qui contient l'énumération (si inconnu, celui-ci cherchera dans tous les modules)
        '@Param strProjectName : Nom du Projet (si inconnu, celui-ci cherchera dans tous les projets)
        'Resultat : Retourne un objet Dictionnary qui contient la liste des noms de l'énumération passé en paramètre
    'Necessite les références :
        'Microsoft Visual Basic for Applications Extensibility 5.3
        'Microsoft Scripting Runtime
    Public Function EnumNoms(ByVal strEnumName As String, Optional ByVal strModuleName As String, Optional ByVal strProjectName As String) As Scripting.Dictionary
        Dim objVBProject As VBProject
        Dim objVBComponent As VBComponent
        Dim objCodeModule As CodeModule
        Dim objDictionnary As Scripting.Dictionary
     
        Dim strVBProjectFileName As String
        Dim strLine As String
        Dim strEnumMemberName As String
        Dim strErrorMessage As String
     
        Dim lngEnumMemberValue As Long
        Dim i As Long
        Dim lngCharPosition(2) As Long
     
        Dim blnFinEnum As Boolean
     
        Dim vntSplitResult As Variant
        Dim vntSplittedProjectName As Variant
     
        If strProjectName <> vbNullString Then
            vntSplittedProjectName = Split(strProjectName, ".")
            strProjectName = vntSplittedProjectName(0)
        End If
     
        For Each objVBProject In Application.VBE.VBProjects
            If strProjectName <> vbNullString Then
                vntSplittedProjectName = Split(objVBProject.Filename, "\")    'Découpe le chemin d'accès du FileName avec le séparateur "\"
                vntSplittedProjectName = Split(vntSplittedProjectName(UBound(vntSplittedProjectName)), ".") 'Récupère le nom de fichier en retirant l'extension
                strVBProjectFileName = vntSplittedProjectName(0)  'Ecrit le nom de fichier dans la variable pour comparaison avec celui demandé
            End If
            If strVBProjectFileName = strProjectName Or strProjectName = vbNullString Then    'Si le projet demandé est le même que celui scruté ou si aucun projet n'est spécifié en paramètre
                For Each objVBComponent In objVBProject.VBComponents 'Boucle pour chaque Composant du projet VB (Sheets, ThisWorkbook, Userforms, Modules, Modules de classe)
                    If objVBComponent.Name = strModuleName Or strModuleName = "" Then   'Si le nom de fichier correspond à celui demandé en paramètre ou si rien n'est spécifié en paramètre
                        Set objCodeModule = objVBComponent.CodeModule 'Permet d'accéder au code contenu dans le composant du projet VB
                        With objCodeModule
                            If .Find("Public Enum " & strEnumName, 1, 1, .CountOfLines, 1024) Then  'Si la déclaration de l'énumération demandée est trouvée dans le module
                                For i = 1 To .CountOfLines
                                    strLine = .Lines(i, 1)
                                    lngCharPosition(0) = InStr(1, strLine, "Public Enum " & strEnumName, vbTextCompare)
                                    If lngCharPosition(0) > 0 Then  'Si la ligne est celle de la déclaration de l'énumération
                                        lngCharPosition(1) = InStr(1, Left(strLine, lngCharPosition(0)), "'", vbBinaryCompare)
                                        If lngCharPosition(1) = 0 Then  'Vérifie que la ligne de déclaration n'est pas en commentaire
                                            Set objDictionnary = New Scripting.Dictionary
                                            Do Until blnFinEnum Or (i + 1 = .CountOfLines)    'Boucle jusqu'à la fin de l'énumération
                                                i = i + 1
                                                strLine = .Lines(i, 1)
                                                strLine = Replace(strLine, " ", vbNullString)
                                                vntSplitResult = Split(strLine, "'")
                                                vntSplitResult = Split(vntSplitResult(0), "=")
                                                If UBound(vntSplitResult) = 1 Then              'Si le caractère '=' a pu être isolé
                                                    strEnumMemberName = vntSplitResult(0)       'Récupère le nom du membre
                                                    vntSplitResult(1) = Replace(vntSplitResult(1), """", vbNullString)  'Retire les guillemets à la valeur (Quand une déclaration au format hexa est utilisé Exemple :"&H0F1")
                                                    lngEnumMemberValue = vntSplitResult(1)      'Récupère la valeur (Long) du membre
                                                    If Not objDictionnary.Exists(lngEnumMemberValue) Then   'Si la valeur pour énumération n'existe pas déjà, l'ajoute au dictionnaire sinon elle est ignorée.
                                                        objDictionnary.Add lngEnumMemberValue, strEnumMemberName
                                                    End If
                                                End If
                                                strLine = .Lines(i + 1, 1)
                                                vntSplitResult = Split(strLine, "'")
                                                If UBound(vntSplitResult) = 0 Then                      'Vérifie que la ligne suivante n'est pas en commentaire
                                                    blnFinEnum = .Find("End Enum", i, 1, i + 1, 1024)   'Si la fin de l'énumération est trouvée, met à True blnFinEnum pour sortir
                                                End If
                                            Loop
                                            GoTo Fin    'Sort des boucles
                                        End If
                                    End If
                                Next
                            End If
                        End With
                    End If
                Next objVBComponent
            End If
        Next objVBProject
    Fin:
        If objDictionnary Is Nothing Then
            strErrorMessage = "L'enumération passée en paramètre ''strEnumName'' (" & strEnumName & ") n'a pas été trouvé dans "
            If strModuleName <> vbNullString Then
                strErrorMessage = strErrorMessage & "le module ''" & strModuleName & "''"
            Else
                strErrorMessage = strErrorMessage & "les modules"
            End If
            If strProjectName <> vbNullString Then
                strErrorMessage = strErrorMessage & " du projet ''" & strProjectName & "''"
            Else
                strErrorMessage = strErrorMessage & " des projets ouverts."
            End If
            Err.Raise 515, , strErrorMessage
        End If
        Set EnumNoms = objDictionnary
    End Function
    Il faut activer des références (Dans Outils --> Références.) :
    - Microsoft Scripting Runtime (pour jouer avec l'objet Dictionnary)
    - Microsoft Visual Basic for Applications Extensibility. (pour pouvoir se balader dans le code du module et en récupérer des lignes)

    Ensuite il faut cocher une case dans :
    Options Excel --> Trust Center --> Macro Settings --> Developer Macro Settings
    Vous devriez aussi cocher la case "Trust access to the VBA project object model"

    Ou dans la version Française
    Options Excel --> Centre de gestion de la confidentialité --> Paramètres du Centre de gestion de la confidentialité --> Paramètres des macros --> Paramètres de macros pour les développeurs.
    Cocher Accès approuvé au modèle d'objet du projet VBA.


    Limitations : Au vu du fonctionnement d'un dictionnary (à savoir qu'une key doit être unique), si plusieurs membres de l'énumération possèdent la même valeur (Long) mon bout de code n'ajoute que le premier membre de l'énumération vu.

    PS : Cette fonction est assez spécifique, je vous l'accorde il faut chercher avant de lui trouver une utilité
    Je l'ai créée pour construire un message d'erreur personnalisé.
    C'était entre autre pour m'éviter un Select Case à rallonge qui ne faisait que renvoyer un string avec le nom du membre de l'énumération.
    Et c'était aussi parce que je sais que mon énumération va grossir au fur et à mesure du temps et que mon code se retrouverais incomplet si j'oubliais de rajouter des 'Case' à chaque nouveau membre de l'enum.
    Il y a 10 types de personnes dans le monde : ceux qui comptent en binaire et les autres.

  2. #2
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Salut

    J'ai joué avec les expressions régulières il y a peu et ça me semblerait adapté

    Et pour le dico, pourquoi ne pas inverser key et value, le nom dans l'enum est unique comme la key et la value peut être identique à l'un ou l'autre des enum (et des key).
    [Edit]Peut-être tout simplement parce que ça ne fonctionne pas ^^... c'est pas la 1ère fois que je me fais avoir avec les Dico...[/Edit]


    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  3. #3
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Salut

    Je me permet... bon j'en ai sué gouttes et eaux... c'est chouette les reg Exp... mais ça se mérite
    Bon après ça ne simplifie pas tant le code que je l'aurais pensé au départ, par contre je pense qu'avec les reg Exp le code est plus polyvalent.
    En parcourant ton code, je viens de voir que je n'avais pas pensé aux valeurs Hexadécimales... c'est corrigé!
    Le code prend également en compte l'absence de valeur affectée en prenant la valeur suivante de l'entrée précédente.

    Bon un peu déçu pour le Dico, ça n'est pas la 1ère fois que je me fait avoir en passant qu'il fonctionne dans les deux sens Key>Item Item>Key, ce qui n'existe pas ailleurs que dans ma tête :par
    Pour palier à ce petit goût de manque j'ai mis un pis aller en lui faisant écrire dans Item toutes les valeurs ayant la même key... ça s'enlève facilement hein...

    Bref!

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    Option Explicit
     
    'A pour but de récupérer un dictionnaire comportant la liste des membres d'une énumération par exemple Private/Public/__ Enum sont pris en compte.
    'Où Key = Valeur / Item = eMembreEnumeration
        '@Param strEnumName : Nom de l'énumération à rechercher
        '@Param strModuleName : Module qui contient l'énumération (si inconnu, celui-ci cherchera dans tous les modules)
        '@Param strProjectName : Nom du Projet (si inconnu, celui-ci cherchera dans tous les projets)
        'Resultat : Retourne un objet Dictionnary qui contient la liste des noms de l'énumération passé en paramètre
    'Necessite les références :
        'Microsoft Visual Basic for Applications Extensibility 5.3
        'Microsoft Scripting Runtime
     
    Sub testEnum()
    Dim a As Dictionary
     
        Set a = EnumNoms("eMatrix_Operation", "Module1", "Functions VBA Matrice.xlsm")
     
        MsgBox "Teste l'Enum de value 3 est " & a.Item(16)
    End Sub
     
     
     
     
     
     
    Public Function EnumNoms(ByVal strEnumName As String, Optional ByVal strModuleName As String, Optional ByVal strProjectName As String) As Scripting.Dictionary
        Dim objVBProject As VBProject
        Dim objVBComponent As VBComponent
        Dim objCodeModule As CodeModule
        Dim objDictionnary As Scripting.Dictionary
     
        Dim strVBProjectFileName As String
        Dim strErrorMessage As String
     
        Dim lngEnumMemberValue As Long
     
        Dim vntSplittedProjectName As Variant
     
        Dim strCodeModule As String
        Dim regEnum As RegExp
        Dim matchesEnum As MatchCollection
        Dim strListEnum As String, vntLigneEnum As Variant, vntCoupleKV As Variant
     
        'Initialisation
        lngEnumMemberValue = -1
     
        If strProjectName <> vbNullString Then
            vntSplittedProjectName = Split(strProjectName, ".")
            strProjectName = vntSplittedProjectName(0)
        End If
     
        For Each objVBProject In Application.VBE.VBProjects
            If strProjectName <> vbNullString Then
                vntSplittedProjectName = Split(objVBProject.Filename, "\")    'Découpe le chemin d'accès du FileName avec le séparateur "\"
                vntSplittedProjectName = Split(vntSplittedProjectName(UBound(vntSplittedProjectName)), ".") 'Récupère le nom de fichier en retirant l'extension
                strVBProjectFileName = vntSplittedProjectName(0)  'Ecrit le nom de fichier dans la variable pour comparaison avec celui demandé
            End If
            If strVBProjectFileName = strProjectName Or strProjectName = vbNullString Then    'Si le projet demandé est le même que celui scruté ou si aucun projet n'est spécifié en paramètre
                For Each objVBComponent In objVBProject.VBComponents 'Boucle pour chaque Composant du projet VB (Sheets, ThisWorkbook, Userforms, Modules, Modules de classe)
                    If objVBComponent.Name = strModuleName Or strModuleName = "" Then   'Si le nom de fichier correspond à celui demandé en paramètre ou si rien n'est spécifié en paramètre
                        Set objCodeModule = objVBComponent.CodeModule 'Permet d'accéder au code contenu dans le composant du projet VB
                        With objCodeModule
     
                            'On instancie la RegExp
                            Set regEnum = New RegExp
                            'On parametre
                            regEnum.Global = True
                            regEnum.MultiLine = False
                            regEnum.IgnoreCase = True
                            '
                            'On récupère le code du module
                            strCodeModule = .Lines(1, .CountOfLines)
     
                            'On supprime les commentaires
                            'On teste et on execute la regexp
                            'Ici la regExp ne cherche pas si ' est dans une zone de chaine
                            If TestRunRegExp(regEnum, strCodeModule, "((\t| )*REM|')(\s*(.*)(\n(\t| )*?.*( _\n\s*.*))?)", matchesEnum) Then
                                'On supprime les zones de com
                                strCodeModule = regEnum.Replace(strCodeModule, vbNullString)
                            End If
     
                            'On recherche notre Enum
                            If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum eMatrix_Operation((.|\n)*)(End Enum)+?", matchesEnum) Then
                                'Logiquement un seul ou pas de résultat
                                'On prend en compte la liste des enum
                                'On supprime les tabulations, espaces,chr(10) éventuel(les)
                                strListEnum = Replace(Replace(Replace(matchesEnum(0).SubMatches(2), Chr(9), vbNullString), " ", vbNullString), Chr(10), "")
                                'On instancie le dico
                                Set objDictionnary = New Scripting.Dictionary
                                'On boucle sur chaque ligne
                                For Each vntLigneEnum In Split(strListEnum, Chr(13))
                                    If vntLigneEnum <> "" Then
                                        'On découpe pour trouver le couple key / valeur
                                        vntCoupleKV = Split(vntLigneEnum, "=")
     
                                        If UBound(vntCoupleKV) > 0 Then
                                            'On mémorise la valeur attribuée par le programmeur
                                            vntCoupleKV(1) = Replace(vntCoupleKV(1), """", vbNullString)
                                            lngEnumMemberValue = CLng(vntCoupleKV(1))
                                        Else
                                            'On détermine la valeur attribuée par VB
                                            lngEnumMemberValue = lngEnumMemberValue + 1
                                        End If
                                        'On note le couple dans le dico
                                        If objDictionnary.Exists(lngEnumMemberValue) Then
                                            objDictionnary.Item(lngEnumMemberValue) = Replace(objDictionnary.Item(lngEnumMemberValue), " ou", ",") & " ou " & vntCoupleKV(0)
                                        Else
                                            objDictionnary.Add lngEnumMemberValue, vntCoupleKV(0)
                                        End If
                                    End If
                                Next
                            End If
                            'On sort des boucles
                            GoTo Fin:
                        End With
                    End If
                Next
            End If
        Next
    Fin:
        If objDictionnary Is Nothing Then
            strErrorMessage = "L'enumération passée en paramètre ''strEnumName'' (" & strEnumName & ") n'a pas été trouvé dans "
            If strModuleName <> vbNullString Then
                strErrorMessage = strErrorMessage & "le module ''" & strModuleName & "''"
            Else
                strErrorMessage = strErrorMessage & "les modules"
            End If
            If strProjectName <> vbNullString Then
                strErrorMessage = strErrorMessage & " du projet ''" & strProjectName & "''"
            Else
                strErrorMessage = strErrorMessage & " des projets ouverts."
            End If
            Err.Raise 515, , strErrorMessage
        End If
        Set EnumNoms = objDictionnary
    End Function
     
    Function TestRunRegExp(aRegExp As RegExp, Text As String, aPattern As String, Matches As MatchCollection) As Boolean
        aRegExp.Pattern = aPattern
        If aRegExp.Test(Text) Then
            'On lance la requête
            Set Matches = aRegExp.Execute(Text)
            TestRunRegExp = Not Matches Is Nothing
        End If
    End Function
     
    Sub TestExpReg(texte As String, aRegExp As RegExp, Optional ByRef SupTexte As String)
    Dim Match As VBScript_RegExp_55.Match
    Dim Matches As VBScript_RegExp_55.MatchCollection
    Dim i As Integer
     
        If aRegExp.Test(texte) Then
            Set Matches = aRegExp.Execute(texte)
     
            If Matches.Count = 0 Then
                Debug.Print "Aucune occurence trouvée"
            ElseIf Matches.Count > 500 Then
                Debug.Print "Plus de 500 occurences..."
            Else
                Debug.Print Matches.Count & " occurence(s) trouvée(s) pour ExpReg: " & aRegExp.Pattern
                For Each Match In Matches
                    Debug.Print "source >>", Match.Value
                    For i = 0 To Match.SubMatches.Count - 1
                        Debug.Print "[$" & i + 1 & "]", Match.SubMatches(i)
                    Next i
                    If SupTexte <> "" Then SupTexte = Replace(SupTexte, Match.Value, "")
                Next Match
                Debug.Print Matches.Count & " occurence(s) trouvée(s) pour ExpReg: " & aRegExp.Pattern & vbCrLf
            End If
        Else
            Debug.Print "Pattern introuvable dans la chaine"
        End If
    End Sub
    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  4. #4
    Membre régulier
    Homme Profil pro
    Automaticien
    Inscrit en
    décembre 2015
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Automaticien

    Informations forums :
    Inscription : décembre 2015
    Messages : 84
    Points : 107
    Points
    107
    Par défaut
    Bonjour Qwazerty,

    Merci de ta contribution, tu me fais au passage découvrir les expressions régulières (je ne connaissais pas).

    Je vais aller m'y intéresser de plus près parce que ça a l'air très puissant !

    Si je peux me permettre, j'ai une petite modification à apporter à ton code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum eMatrix_Operation((.|\n)*)(End Enum)+?", matchesEnum) Then
    Je remplacerais cette ligne par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?" & strEnumName & "((.|\n)*)(End Enum)+?", matchesEnum) Then

    Tu avais écrit le nom de ton énumération en dur, donc ça marchait moins bien avec les miennes

    Par contre après plusieurs essais, tu as quelques cas de figures qui te génèrent des problèmes...

    Quand tu as plusieurs énumérations dans le module et que celle que tu recherches est la première de la liste (ton code récupère aussi les énumérations suivantes).

    C'est provoqué dû à la présence de plusieurs lignes de "End Enum", il prend tout simplement la dernière ligne.
    Il y a 10 types de personnes dans le monde : ceux qui comptent en binaire et les autres.

  5. #5
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Salut
    Je vais aller m'y intéresser de plus près parce que ça a l'air très puissant !
    Oui ça me le semble aussi, la seule limite semble être l'imagination

    Au passage, je te conseille ce site, il permet de tester les Reg Exp en direct... super pratique. Des fois le site crash, dû à une écriture qui ne lui plait pas (ou peut-être au texte à traité qui ne lui plait pas voir en dessous les soucis de chr(10)).

    Si je peux me permettre, j'ai une petite modification à apporter à ton code :
    Avec plaisir, n'hésite pas, il n'est pas figé dans le marbre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum eMatrix_Operation((.|\n)*)(End Enum)+?", matchesEnum) Then
    Je remplacerais cette ligne par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?" & strEnumName & "((.|\n)*)(End Enum)+?", matchesEnum) Then
    Oui c'est un oubli dû a d’innombrables essais ^^, j'ai eu des petit soucis à cause du contenu de strCodeModule une fois les commentaires retirés, certains caractères chr(10 et 13) venaient se placer a quelques endroits dans le corps du texte. J'ai contourné le problème mais ne l'ai pas vraiment résolu... Au début j'avais aussi codé le reconnaissance des différente lignes entre Enum et End Enum mais vu que ça n'avais pas de plus-value j'ai simplifié l'écriture.
    Par contre attention, il faut garder le Enum
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum " & strEnumName & "((.|\n)*)(End Enum)+?", matchesEnum) Then
    [Edit]
    J'ai compris mon erreur, c'est la partie (.|\n) qui doit se répéter le mon de fois possible... pas End Enum, il faut donc écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum " & strEnumName & "((.|\n)*?)End Enum", matchesEnum) Then
    [/Edit]

    C'est provoqué dû à la présence de plusieurs lignes de "End Enum", il prend tout simplement la dernière ligne.
    Ca aussi, j'ai testé à un moment donné ça fonctionné mais j'ai du "tuer" le truc en simplifiant mon écriture, je vais regardé D'autant que logiquement (End Enum)+? devrait retourner le End Enum le plus proche du texte reconnu par le pattern, étrange.

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  6. #6
    Membre régulier
    Homme Profil pro
    Automaticien
    Inscrit en
    décembre 2015
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Automaticien

    Informations forums :
    Inscription : décembre 2015
    Messages : 84
    Points : 107
    Points
    107
    Par défaut
    Citation Envoyé par Qwazerty Voir le message
    Au passage, je te conseille ce site, il permet de tester les Reg Exp en direct... super pratique. Des fois le site crash, dû à une écriture qui ne lui plait pas (ou peut-être au texte à traité qui ne lui plait pas voir en dessous les soucis de chr(10)).
    Merci beaucoup ! Je lis cet article (qui au passage est très bien réalisé, bravo cafeine pour le boulot !) :
    https://cafeine.developpez.com/access/tutoriel/regexp/
    En aurais-tu d'autres (afin d'avoir plus d'exemples, des infos complémentaires, etc)?

    Citation Envoyé par Qwazerty Voir le message
    Oui c'est un oubli dû a d’innombrables essais ^^
    T'inquiètes pas je connais ça... Un programme qui marche en entier et du premier coup j'ai jamais vu... Ou c'est que le code est super simple ! Sinon c'est que la personne est surhumaine Hahaha !

    Citation Envoyé par Qwazerty Voir le message
    Par contre attention, il faut garder le Enum
    J'ai testé ton code, j'ai vu qu'il ne marchait pas dû à la variable écrite en dur, je l'ai remplacée et après en relisant ton code je me suis fait la réflexion "tiens c'est bizarre pourquoi n'as t'il pas mis le 'Public Enum' ou 'Private Enum' ?!"
    Et j'ai même pas vu que c'était moi qui l'avait retiré ! Hahahaha, je suis un vrai boulet...


    Citation Envoyé par Qwazerty Voir le message
    Ça aussi, j'ai testé à un moment donné ça fonctionné mais j'ai du "tuer" le truc en simplifiant mon écriture, je vais regardé D'autant que logiquement (End Enum)+? devrait retourner le End Enum le plus proche du texte reconnu par le pattern, étrange.
    J'ai ajouté une condition qui fait sortir prématurément de la boucle quand la ligne = "EndEnum" (il n'y a pas d'espace parce qu'un peu plus haut tu les retires). Ligne 78 ci-dessous

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    'A pour but de récupérer un dictionnaire comportant la liste des membres d'une énumération par exemple Private/Public/__ Enum sont pris en compte.
    'Où Key = Valeur / Item = eMembreEnumeration
        '@Param strEnumName : Nom de l'énumération à rechercher
        '@Param strModuleName : Module qui contient l'énumération (si inconnu, celui-ci cherchera dans tous les modules)
        '@Param strProjectName : Nom du Projet (si inconnu, celui-ci cherchera dans tous les projets)
        'Resultat : Retourne un objet Dictionnary qui contient la liste des noms de l'énumération passé en paramètre
    'Necessite les références :
        'Microsoft Visual Basic for Applications Extensibility 5.3
        'Microsoft Scripting Runtime
    Public Function EnumNoms(ByVal strEnumName As String, Optional ByVal strModuleName As String, Optional ByVal strProjectName As String) As Scripting.Dictionary
        Dim objVBProject As VBProject
        Dim objVBComponent As VBComponent
        Dim objCodeModule As CodeModule
        Dim objDictionnary As Scripting.Dictionary
     
        Dim strVBProjectFileName As String
        Dim strErrorMessage As String
     
        Dim lngEnumMemberValue As Long
     
        Dim vntSplittedProjectName As Variant
     
        Dim strCodeModule As String
        Dim regEnum As RegExp
        Dim matchesEnum As MatchCollection
        Dim strListEnum As String, vntLigneEnum As Variant, vntCoupleKV As Variant
     
        'Initialisation
        lngEnumMemberValue = -1
     
        If strProjectName <> vbNullString Then
            vntSplittedProjectName = Split(strProjectName, ".")
            strProjectName = vntSplittedProjectName(0)
        End If
     
        For Each objVBProject In Application.VBE.VBProjects
            If strProjectName <> vbNullString Then
                vntSplittedProjectName = Split(objVBProject.Filename, "\")    'Découpe le chemin d'accès du FileName avec le séparateur "\"
                vntSplittedProjectName = Split(vntSplittedProjectName(UBound(vntSplittedProjectName)), ".") 'Récupère le nom de fichier en retirant l'extension
                strVBProjectFileName = vntSplittedProjectName(0)  'Ecrit le nom de fichier dans la variable pour comparaison avec celui demandé
            End If
            If strVBProjectFileName = strProjectName Or strProjectName = vbNullString Then    'Si le projet demandé est le même que celui scruté ou si aucun projet n'est spécifié en paramètre
                For Each objVBComponent In objVBProject.VBComponents 'Boucle pour chaque Composant du projet VB (Sheets, ThisWorkbook, Userforms, Modules, Modules de classe)
                    If objVBComponent.Name = strModuleName Or strModuleName = "" Then   'Si le nom de fichier correspond à celui demandé en paramètre ou si rien n'est spécifié en paramètre
                        Set objCodeModule = objVBComponent.CodeModule 'Permet d'accéder au code contenu dans le composant du projet VB
                        With objCodeModule
     
                            'On instancie la RegExp
                            Set regEnum = New RegExp
                            'On parametre
                            regEnum.Global = True
                            regEnum.MultiLine = False
                            regEnum.IgnoreCase = True
                            '
                            'On récupère le code du module
                            strCodeModule = .Lines(1, .CountOfLines)
     
                            'On supprime les commentaires
                            'On teste et on execute la regexp
                            'Ici la regExp ne cherche pas si ' est dans une zone de chaine
                            If TestRunRegExp(regEnum, strCodeModule, "((\t| )*REM|')(\s*(.*)(\n(\t| )*?.*( _\n\s*.*))?)", matchesEnum) Then
                                'On supprime les zones de com
                                strCodeModule = regEnum.Replace(strCodeModule, vbNullString)
                            End If
     
                            'On recherche notre Enum
                            If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum " & strEnumName & "((.|\n)*)(End Enum)?", matchesEnum) Then
                                'Logiquement un seul ou pas de résultat
                                'On prend en compte la liste des enum
                                'On supprime les tabulations, espaces,chr(10) éventuel(les)
                                strListEnum = Replace(Replace(Replace(matchesEnum(0).SubMatches(2), Chr(9), vbNullString), " ", vbNullString), Chr(10), "")
                                'On instancie le dico
                                Set objDictionnary = New Scripting.Dictionary
                                'On boucle sur chaque ligne
                                For Each vntLigneEnum In Split(strListEnum, Chr(13))
                                    Select Case vntLigneEnum
                                        'Si c'est la fin de l'énumération, sort de la boucle
                                        Case "EndEnum"
                                            Exit For
     
                                        Case Is <> ""
                                           'On découpe pour trouver le couple key / valeur
                                           vntCoupleKV = Split(vntLigneEnum, "=")
     
                                           If UBound(vntCoupleKV) > 0 Then
                                               'On mémorise la valeur attribuée par le programmeur
                                               vntCoupleKV(1) = Replace(vntCoupleKV(1), """", vbNullString)
                                               lngEnumMemberValue = CLng(vntCoupleKV(1))
                                           Else
                                               'On détermine la valeur attribuée par VB
                                               lngEnumMemberValue = lngEnumMemberValue + 1
                                           End If
                                           'On note le couple dans le dico
                                           If objDictionnary.Exists(lngEnumMemberValue) Then
                                               objDictionnary.Item(lngEnumMemberValue) = Replace(objDictionnary.Item(lngEnumMemberValue), " ou", ",") & " ou " & vntCoupleKV(0)
                                           Else
                                               objDictionnary.Add lngEnumMemberValue, vntCoupleKV(0)
                                           End If
     
                                    End Select
                                Next
                            End If
                            'On sort des boucles
                            GoTo Fin:
                        End With
                    End If
                Next
            End If
        Next
    Fin:
        If objDictionnary Is Nothing Then
            strErrorMessage = "L'enumération passée en paramètre ''strEnumName'' (" & strEnumName & ") n'a pas été trouvé dans "
            If strModuleName <> vbNullString Then
                strErrorMessage = strErrorMessage & "le module ''" & strModuleName & "''"
            Else
                strErrorMessage = strErrorMessage & "les modules"
            End If
            If strProjectName <> vbNullString Then
                strErrorMessage = strErrorMessage & " du projet ''" & strProjectName & "''"
            Else
                strErrorMessage = strErrorMessage & " des projets ouverts."
            End If
            Err.Raise 515, , strErrorMessage
        End If
        Set EnumNoms = objDictionnary
    End Function
     
    Function TestRunRegExp(aRegExp As RegExp, Text As String, aPattern As String, Matches As MatchCollection) As Boolean
        aRegExp.Pattern = aPattern
        If aRegExp.test(Text) Then
            'On lance la requête
            Set Matches = aRegExp.Execute(Text)
            TestRunRegExp = Not Matches Is Nothing
        End If
    End Function
     
    Sub TestExpReg(texte As String, aRegExp As RegExp, Optional ByRef SupTexte As String)
        Dim Match As VBScript_RegExp_55.Match
        Dim Matches As VBScript_RegExp_55.MatchCollection
        Dim i As Integer
     
        If aRegExp.test(texte) Then
            Set Matches = aRegExp.Execute(texte)
     
            If Matches.Count = 0 Then
                Debug.Print "Aucune occurence trouvée"
            ElseIf Matches.Count > 500 Then
                Debug.Print "Plus de 500 occurences..."
            Else
                Debug.Print Matches.Count & " occurence(s) trouvée(s) pour ExpReg: " & aRegExp.Pattern
                For Each Match In Matches
                    Debug.Print "source >>", Match.Value
                    For i = 0 To Match.SubMatches.Count - 1
                        Debug.Print "[$" & i + 1 & "]", Match.SubMatches(i)
                    Next i
                    If SupTexte <> "" Then SupTexte = Replace(SupTexte, Match.Value, "")
                Next Match
                Debug.Print Matches.Count & " occurence(s) trouvée(s) pour ExpReg: " & aRegExp.Pattern & vbCrLf
            End If
        Else
            Debug.Print "Pattern introuvable dans la chaine"
        End If
    End Sub
    Cette solution fonctionne mais me plaît à moitié, il doit y avoir un moyen de l'éviter dans le Pattern directement... Je dois continuer à m'exercer et à apprendre sur RegEx.


    [Edit 14/08/18 à 14h30] : Je viens de voir ta modification, du coup j'ai barré ce que je venais d'ajouter (je vais de ce pas m'entrainer sur les pattern pour mieux appréhender la syntaxe), voici le code

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    'A pour but de récupérer un dictionnaire comportant la liste des membres d'une énumération par exemple Private/Public/__ Enum sont pris en compte.
    'Où Key = Valeur / Item = eMembreEnumeration
        '@Param strEnumName : Nom de l'énumération à rechercher
        '@Param strModuleName : Module qui contient l'énumération (si inconnu, celui-ci cherchera dans tous les modules)
        '@Param strProjectName : Nom du Projet (si inconnu, celui-ci cherchera dans tous les projets)
        'Resultat : Retourne un objet Dictionnary qui contient la liste des noms de l'énumération passé en paramètre
    'Necessite les références :
        'Microsoft Visual Basic for Applications Extensibility 5.3
        'Microsoft Scripting Runtime
        'Microsoft VBScript Regular Expressions
    Public Function EnumNoms(ByVal strEnumName As String, Optional ByVal strModuleName As String, Optional ByVal strProjectName As String) As Scripting.Dictionary
        Dim objVBProject As VBProject
        Dim objVBComponent As VBComponent
        Dim objCodeModule As CodeModule
        Dim objDictionnary As Scripting.Dictionary
     
        Dim strVBProjectFileName As String
        Dim strErrorMessage As String
     
        Dim lngEnumMemberValue As Long
     
        Dim vntSplittedProjectName As Variant
     
        Dim strCodeModule As String
        Dim regEnum As RegExp
        Dim matchesEnum As MatchCollection
        Dim strListEnum As String, vntLigneEnum As Variant, vntCoupleKV As Variant
     
        'Initialisation
        lngEnumMemberValue = -1
     
        If strProjectName <> vbNullString Then
            vntSplittedProjectName = Split(strProjectName, ".")
            strProjectName = vntSplittedProjectName(0)
        End If
     
        For Each objVBProject In Application.VBE.VBProjects
            If strProjectName <> vbNullString Then
                vntSplittedProjectName = Split(objVBProject.Filename, "\")    'Découpe le chemin d'accès du FileName avec le séparateur "\"
                vntSplittedProjectName = Split(vntSplittedProjectName(UBound(vntSplittedProjectName)), ".") 'Récupère le nom de fichier en retirant l'extension
                strVBProjectFileName = vntSplittedProjectName(0)  'Ecrit le nom de fichier dans la variable pour comparaison avec celui demandé
            End If
            If strVBProjectFileName = strProjectName Or strProjectName = vbNullString Then    'Si le projet demandé est le même que celui scruté ou si aucun projet n'est spécifié en paramètre
                For Each objVBComponent In objVBProject.VBComponents 'Boucle pour chaque Composant du projet VB (Sheets, ThisWorkbook, Userforms, Modules, Modules de classe)
                    If objVBComponent.Name = strModuleName Or strModuleName = "" Then   'Si le nom de fichier correspond à celui demandé en paramètre ou si rien n'est spécifié en paramètre
                        Set objCodeModule = objVBComponent.CodeModule 'Permet d'accéder au code contenu dans le composant du projet VB
                        With objCodeModule
     
                            'On instancie la RegExp
                            Set regEnum = New RegExp
                            'On parametre
                            regEnum.Global = True
                            regEnum.MultiLine = False
                            regEnum.IgnoreCase = True
     
                            'On récupère le code du module
                            strCodeModule = .Lines(1, .CountOfLines)
     
                            'On supprime les commentaires
                            'On teste et on execute la regexp
                            'Ici la regExp ne cherche pas si ' est dans une zone de chaine
                            If TestRunRegExp(regEnum, strCodeModule, "((\t| )*REM|')(\s*(.*)(\n(\t| )*?.*( _\n\s*.*))?)", matchesEnum) Then
                                'On supprime les zones de com
                                strCodeModule = regEnum.Replace(strCodeModule, vbNullString)
                            End If
     
                            'On recherche notre Enum
                            If TestRunRegExp(regEnum, strCodeModule, "( |\t)*(Public |Private )?Enum " & strEnumName & "((.|\n)*?)End Enum", matchesEnum) Then
                                'Logiquement un seul ou pas de résultat
                                'On prend en compte la liste des enum
                                'On supprime les tabulations, espaces,chr(10) éventuel(les)
                                strListEnum = Replace(Replace(Replace(matchesEnum(0).SubMatches(2), Chr(9), vbNullString), " ", vbNullString), Chr(10), "")
                                'On instancie le dico
                                Set objDictionnary = New Scripting.Dictionary
                                'On boucle sur chaque ligne
                                For Each vntLigneEnum In Split(strListEnum, Chr(13))
                                    If vntLigneEnum <> "" Then
                                           'On découpe pour trouver le couple key / valeur
                                           vntCoupleKV = Split(vntLigneEnum, "=")
     
                                           If UBound(vntCoupleKV) > 0 Then
                                               'On mémorise la valeur attribuée par le programmeur
                                               vntCoupleKV(1) = Replace(vntCoupleKV(1), """", vbNullString)
                                               lngEnumMemberValue = CLng(vntCoupleKV(1))
                                           Else
                                               'On détermine la valeur attribuée par VB
                                               lngEnumMemberValue = lngEnumMemberValue + 1
                                           End If
                                           'On note le couple dans le dico
                                           If objDictionnary.Exists(lngEnumMemberValue) Then
                                               objDictionnary.Item(lngEnumMemberValue) = Replace(objDictionnary.Item(lngEnumMemberValue), " ou", ",") & " ou " & vntCoupleKV(0)
                                           Else
                                               objDictionnary.Add lngEnumMemberValue, vntCoupleKV(0)
                                           End If
     
                                    End If
                                Next
                            End If
                            'On sort des boucles
                            GoTo Fin:
                        End With
                    End If
                Next
            End If
        Next
    Fin:
        If objDictionnary Is Nothing Then
            strErrorMessage = "L'enumération passée en paramètre ''strEnumName'' (" & strEnumName & ") n'a pas été trouvé dans "
            If strModuleName <> vbNullString Then
                strErrorMessage = strErrorMessage & "le module ''" & strModuleName & "''"
            Else
                strErrorMessage = strErrorMessage & "les modules"
            End If
            If strProjectName <> vbNullString Then
                strErrorMessage = strErrorMessage & " du projet ''" & strProjectName & "''"
            Else
                strErrorMessage = strErrorMessage & " des projets ouverts."
            End If
            Err.Raise 515, , strErrorMessage
        End If
        Set EnumNoms = objDictionnary
    End Function
     
    Function TestRunRegExp(aRegExp As RegExp, Text As String, aPattern As String, Matches As MatchCollection) As Boolean
        aRegExp.Pattern = aPattern
        If aRegExp.test(Text) Then
            'On lance la requête
            Set Matches = aRegExp.Execute(Text)
            TestRunRegExp = Not Matches Is Nothing
        End If
    End Function
    Merci de ton amélioration, merci de m'avoir appris l’existence de RegEx, et au passage tu m'as appris qu'un commentaire pouvait aussi se faire via le mot clef 'Rem' (je ne le savais pas, bon après j'avoue que je trouve ça moins lisible que l'apostrophe mais c'est bien de savoir que ça existe ).


    Note : J'ai intégré le bout de code à un module de classe qui était instancié plusieurs milliers de fois (ça a exécuté 3278 fois la fonction )...

    Ma conclusion est que si le but est la rapidité d'exécution, la méthode sans RegExp (juste en manipulant les string) sera plus rapide mais moins lisible (0.78 sec / 3278 exécutions)...
    Si vous souhaitez une bonne lisibilité et une plus grande puissance de traitement RegExp sera meilleur (22 sec et des broutilles / 3278 exécutions).

    Évidemment il n'y a pas besoin d'exécuter ce genre de fonction des milliers de fois, une fois est amplement suffisant... Si le besoin est de l'utiliser à plusieurs endroits il vaut mieux déclarer le Dictionnary retourné en Public et d'exécuter la fonction une fois à l'ouverture...
    Mais du coup, si jamais à l'avenir vous savez que vous avez besoin d'une grande rapidité d'exécution, l'objet RegExp n'est pas forcément le plus rapide comparé à des opérations "normales" sur du texte (après ça dépend aussi peut-être du nombre de lignes à analyser).
    Il y a 10 types de personnes dans le monde : ceux qui comptent en binaire et les autres.

  7. #7
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Citation Envoyé par Nono02P Voir le message
    Merci beaucoup ! Je lis cet article (qui au passage est très bien réalisé, bravo cafeine pour le boulot !) :
    https://cafeine.developpez.com/access/tutoriel/regexp/
    En aurais-tu d'autres (afin d'avoir plus d'exemples, des infos complémentaires, etc)?
    J'ai bien sûr utilisé le tuto de cafeïne!
    Il y a beaucoup de source sur internet mais j'ai trouvé que celui-ci offret un spectre assez large, par contre certaine écriture ne semblent pas pouvoir être utiliser en VB (du moins, je n'ai pas su les utiliser).

    Citation Envoyé par Nono02P Voir le message
    ... et au passage tu m'as appris qu'un commentaire pouvait aussi se faire via le mot clef 'Rem' (je ne le savais pas, bon après j'avoue que je trouve ça moins lisible que l'apostrophe mais c'est bien de savoir que ça existe ).
    C'est un vieux reliquat de Basic, je pense qu'il est conservé pour la compatibilité descendante. Mais bon, autant en tenir compte.

    Citation Envoyé par Nono02P Voir le message
    Note : J'ai intégré le bout de code à un module de classe qui était instancié plusieurs milliers de fois (ça a exécuté 3278 fois la fonction )...

    Ma conclusion est que si le but est la rapidité d'exécution, la méthode sans RegExp (juste en manipulant les string) sera plus rapide mais moins lisible (0.78 sec / 3278 exécutions)...
    Si vous souhaitez une bonne lisibilité et une plus grande puissance de traitement RegExp sera meilleur (22 sec et des broutilles / 3278 exécutions).

    Évidemment il n'y a pas besoin d'exécuter ce genre de fonction des milliers de fois, une fois est amplement suffisant... Si le besoin est de l'utiliser à plusieurs endroits il vaut mieux déclarer le Dictionnary retourné en Public et d'exécuter la fonction une fois à l'ouverture...
    Mais du coup, si jamais à l'avenir vous savez que vous avez besoin d'une grande rapidité d'exécution, l'objet RegExp n'est pas forcément le plus rapide comparé à des opérations "normales" sur du texte (après ça dépend aussi peut-être du nombre de lignes à analyser).
    OK. Après les expressions que j'ai écrite ne sont peut-être pas efficiente et effectivement, je pense que le gain se fait sur la masse à traiter. Mais ça fait quand même un sacré écart... Je me demande si cette écart est proportionnel au nombre d'essais.


    J'ai vu que tu avait fait une version "Implement", il serait sans doute intéressant avec une seul fonction de créer la liste de tous les Enum, Implement, Function, ... en fonction d'un paramètre qui précise ce que l'on souhaite, seule la reg exp serait différente (Select Case par exemple).

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  8. #8
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Concernant le site de test, il y a aussi beaucoup d'information sur la partie droit, des exemples (qui m'ont montré ? mais aussi des fonctionnalités (Cheat Sheet). Je n'avais pas suffisamment regardé son contenu, je viens d'y voir des choses intéressantes et qui ne figuent pas (du moins je ne les ai pas vu) sur les tutoriels que j'ai compulsé.
    Par exemple ?: qui permet de ne pas faire apparaitre la partie en tant que souschaine, ?= et ?! semblent également intéressants.

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  9. #9
    Membre régulier
    Homme Profil pro
    Automaticien
    Inscrit en
    décembre 2015
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Automaticien

    Informations forums :
    Inscription : décembre 2015
    Messages : 84
    Points : 107
    Points
    107
    Par défaut
    Citation Envoyé par Qwazerty Voir le message
    Concernant le site de test, il y a aussi beaucoup d'information sur la partie droit, des exemples (qui m'ont montré ? mais aussi des fonctionnalités (Cheat Sheet). Je n'avais pas suffisamment regardé son contenu, je viens d'y voir des choses intéressantes et qui ne figuent pas (du moins je ne les ai pas vu) sur les tutoriels que j'ai compulsé.
    Par exemple ?: qui permet de ne pas faire apparaitre la partie en tant que souschaine, ?= et ?! semblent également intéressants.

    ++
    Qwaz


    Voilà la fonction qui intègre les énumérations et les implémentations !
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    'A pour but d'analyser le code et de retourner un dictionnaire qui contient
    'le contenu du code à analyser (en fonction des paramètres de recherche)
        '@Param lngRegExpParameter : permet de sélectionner le type d'analyse à faire
        '@Param blnOnlyDeclarationLines : Mettre à True pour analyser uniquement les lignes de code en déclaration seules
        '@Param strProjectName : Nom du Projet (si inconnu, celui-ci cherchera dans tous les projets)
        'Resultat : Retourne un objet Dictionnary qui contient :
            '- eImplements : Pour chaque Modules, contient la liste des interfaces implémentées par le module
            '- eEnumMembers : Pour chaque énumération, contient la liste des membres de l'énumération
    Public Function AnalyserCode(lngRegExpParameter As gv_enumRegExp, Optional ByVal blnOnlyDeclarationLines As Boolean, Optional ByVal strProjectName As String) As Scripting.Dictionary
        Dim objVBProject As VBProject
        Dim objVBComponent As VBComponent
        Dim objCodeModule As CodeModule
        Dim dicResultat As Scripting.Dictionary
        Dim objRegExpEnum As RegExp
        Dim objColMatches As MatchCollection
        Dim objMatch As Match
        Dim strMatchExtraction As String
        Dim strVBProjectFileName As String
        Dim strCodeModule As String
        Dim vntSplittedProjectName As Variant
     
        Dim dicEnumerations As Scripting.Dictionary
        Dim dicEnumMembers As Scripting.Dictionary
        Dim objMatchesEnumMembers As MatchCollection
        Dim strListEnumMembers As String
        Dim lngEnumMemberValue As Long
        Dim vntLigneEnum As Variant
        Dim vntCoupleKV As Variant
     
        Dim dicModuleImplements As Scripting.Dictionary
        Dim dicInterface As Scripting.Dictionary
     
        Select Case lngRegExpParameter
            Case eEnumMembers
                Set dicEnumerations = New Scripting.Dictionary
                Set dicResultat = dicEnumerations
     
            Case eImplements
                Set dicModuleImplements = New Scripting.Dictionary
                Set dicResultat = dicModuleImplements
     
        End Select
     
        Set objRegExpEnum = New RegExp  'On instancie la RegExp
        With objRegExpEnum              'On parametre RegExp
            .Global = True
            .MultiLine = False
            .IgnoreCase = True
        End With
     
        If strProjectName <> vbNullString Then
            vntSplittedProjectName = Split(strProjectName, ".")
            strProjectName = vntSplittedProjectName(0)
        End If
     
        For Each objVBProject In Application.VBE.VBProjects
            If strProjectName <> vbNullString Then
                vntSplittedProjectName = Split(objVBProject.Filename, "\")    'Découpe le chemin d'accès du FileName avec le séparateur "\"
                vntSplittedProjectName = Split(vntSplittedProjectName(UBound(vntSplittedProjectName)), ".") 'Récupère le nom de fichier en retirant l'extension
                strVBProjectFileName = vntSplittedProjectName(0)  'Ecrit le nom de fichier dans la variable pour comparaison avec celui demandé
            End If
            If strVBProjectFileName = strProjectName Or strProjectName = vbNullString Then    'Si le projet demandé est le même que celui scruté ou si aucun projet n'est spécifié en paramètre
                For Each objVBComponent In objVBProject.VBComponents 'Boucle pour chaque Composant du projet VB (Sheets, ThisWorkbook, Userforms, Modules, Modules de classe)
                    Set objCodeModule = objVBComponent.CodeModule 'Permet d'accéder au code contenu dans le composant du projet VB
                    With objCodeModule
                        If blnOnlyDeclarationLines Then 'Limite le code du module à examiner aux lignes de déclaration ou à la totalité
                            strCodeModule = .Lines(1, .CountOfDeclarationLines)
                        Else
                            strCodeModule = .Lines(1, .CountOfLines)
                        End If
                        'On supprime les commentaires si ils sont trouvés
                        If RegExpExecute(objRegExpEnum, strCodeModule, "((\t| )*REM|')(\s*(.*)(\n(\t| )*?.*( _\n\s*.*))?)", objColMatches) Then
                            strCodeModule = objRegExpEnum.Replace(strCodeModule, Chr(13))
                        End If
     
                        Select Case lngRegExpParameter
                            Case eEnumMembers
                                'On recherche et exécute RegExp pour retrouver notre Enum
                                If RegExpExecute(objRegExpEnum, strCodeModule, "(\t| )*(Public |Private ).?Enum ((\w)*)", objColMatches) Then
                                    'On prend en compte la liste des enum
                                    For Each objMatch In objColMatches
                                        strMatchExtraction = objMatch.SubMatches(2)
                                        If RegExpExecute(objRegExpEnum, strCodeModule, "(\t| )*(Public |Private )?Enum " & strMatchExtraction & "((.|\n)*?)End Enum", objMatchesEnumMembers) Then
                                            'Logiquement un seul ou pas de résultat
                                            'On prend en compte la liste des enum
                                            'On supprime les tabulations, espaces, chr(10) éventuel(les)
                                            strListEnumMembers = Replace(Replace(Replace(objMatchesEnumMembers(0).SubMatches(2), Chr(9), vbNullString), " ", vbNullString), Chr(10), "")
                                            'Initialisation
                                            lngEnumMemberValue = -1
                                            Set dicEnumMembers = New Scripting.Dictionary
                                            'On boucle sur chaque ligne (membre d'énumération)
                                            For Each vntLigneEnum In Split(strListEnumMembers, Chr(13))
                                                If vntLigneEnum <> "" Then
                                                   'On découpe pour trouver le couple key / valeur
                                                   vntCoupleKV = Split(vntLigneEnum, "=")
     
                                                   If UBound(vntCoupleKV) > 0 Then
                                                       'On retire les " et converti en Long (en cas de valeur Hexadécimale)
                                                       vntCoupleKV(1) = Replace(vntCoupleKV(1), """", vbNullString)
                                                       lngEnumMemberValue = CLng(vntCoupleKV(1))
                                                   Else
                                                       'On détermine la valeur attribuée par VB
                                                       lngEnumMemberValue = lngEnumMemberValue + 1
                                                   End If
                                                   'On note le couple dans le dico
                                                   If dicEnumMembers.Exists(lngEnumMemberValue) Then
                                                       dicEnumMembers.Item(lngEnumMemberValue) = dicEnumMembers.Item(lngEnumMemberValue) & "," & vntCoupleKV(0) 'Replace(dicEnumMembers.Item(lngEnumMemberValue), " ou", ",") & " ou " & vntCoupleKV(0)
                                                   Else
                                                       dicEnumMembers.Add lngEnumMemberValue, vntCoupleKV(0)
                                                   End If
                                                End If
                                            Next
                                            dicEnumerations.Add strMatchExtraction, dicEnumMembers
                                        End If
                                    Next
                                End If
     
                            Case eImplements
                                'On recherche et exécute RegExp pour retrouver nos Implements
                                If RegExpExecute(objRegExpEnum, strCodeModule, "(\s)(Implements).((\w)*)", objColMatches) Then
                                    Set dicInterface = New Scripting.Dictionary
                                    'On prend en compte la liste des Implementations
                                    For Each objMatch In objColMatches
                                        strMatchExtraction = objMatch.SubMatches(2)
                                        dicInterface.Add strMatchExtraction, strMatchExtraction
                                    Next
                                    dicModuleImplements.Add objVBComponent.Name, dicInterface
                                End If
     
                        End Select
                    End With
                Next
            End If
        Next
     
        Set AnalyserCode = dicResultat
    End Function
     
     
    'Permet de tester et exécuter un RegExp (Expression Régulière)
        '@Param objRegExp : Instance de RegExp à exécuter
        '@Param strText : Texte à tester
        '@Param strPattern : Pattern à utiliser
        '@Param objMatches : MatchsCollection (résultats de la requête RegExp)
    Public Function RegExpExecute(ByRef objRegExp As RegExp, ByVal strText As String, ByVal strPattern As String, ByRef objMatches As MatchCollection) As Boolean
        With objRegExp
            .Pattern = strPattern
            If .test(strText) Then
                Set objMatches = .Execute(strText)    'On lance la requête
                RegExpExecute = Not objMatches Is Nothing
            End If
        End With
    End Function
    Dans le module qui sert à déclarer les variables globales :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Public Enum gv_enumRegExp
        eImplements = 1
        eEnumMembers = 2
    End Enum
    J'ai modifié le tout afin d'avoir un Dictionnary renvoyant une liste de dictionnary qui eux contiennent les données.

    ça permet entre autre de récupérer toutes les énumérations et pour chaque énumération récupérer les membres.
    ça permet aussi de récupérer tous les modules de classe implémentant une interface et pour chacun d'entre eux les interfaces qu'ils implémentent.
    Il y a 10 types de personnes dans le monde : ceux qui comptent en binaire et les autres.

  10. #10
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Salut

    Super, sitôt dit sitôt fait

    Y'a plus qu'à faire un parseur de module complète qui extrait la totalité des informations!
    J'utilise la version gratuite de Mz-Tool, il y a une fonction qui permet de faire ça, ça te liste dans une arborescence tous les projets, tous leurs modules, toutes les fonctions des module, toutes les variables non utilisées dans chaque module. Très pratique pour faire du nettoyage après un développement.


    Pour le Pattern des Implements, j'aurais plutôt utilisé ça

    (?: |\t)*Implements (\w+)

    • "(?: |\t)*" : aucun ou plusieurs espaces ou tabulations. ?: permet de ne pas renvoyer le résultat dans une souschaine(mais dans ce cas je pense que c'est inutile, c'était pour le fun ).
      Le \S quand à lui prend aussi les sauts de ligne et du coup ça prend les lignes vides qui se trouvent avant le terme recherché, ce qui n'est pas souhaitable.
    • "Implements " : Le mot clef avec l'espace en fin
    • "(\w+)" : un caractère ou plus pour constituer un mot qui est retourné comme sous-chaine de résultat.



    J'en profite aussi pour te remercier parce que je ne connaissais pas Implements et ça va peut-être me servir

    [Edit]
    Les dicos de dicos me chagrine par contre. Les dicos dicEnumMembers tout particulièrement.
    Ils sont instanciés dans le corps de de la function AnalyserCode, puis empaqueté dans dicEnumerations qui est ensuite transmis au demandeur. Du coup, à la charge du demandeur de détruire l'instance de dicEnumerations, ça ok mais aussi toutes les instances dicEnumMembers qu'il contient et je trouve pas ça très charmant
    La solution serait sans doute d'utiliser des collections au sein d'un module de classe afin d'automatiser la destruction des sous collections lors de la destruction de la collection "conteneur". Je reconnais que ça commence à faire beaucoup de taff

    Comment utilises-tu (notamment leur destruction) les dicos retournés?
    [/Edit]

    [Edit2]
    Tout autre chose, un conseil pour ne pas perdre inutilement plusieurs heures de boulot...
    Lors des phases de teste des regexp, fait en sorte de sauvegarder ton classeur avant chaque teste d'un nouveau pattern. Certain pattern font carrément planter RegExp et il est impossible de stopper le code puisque l'erreur (boucle infini je pense) est en cours à l'extérieur d'excel qui n'arrive plus à reprendre la main... Heureusement que j'ai l’enregistrement auto des xslm... sinon j'aurais pleuré.
    [/Edit2]

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  11. #11
    Membre régulier
    Homme Profil pro
    Automaticien
    Inscrit en
    décembre 2015
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Automaticien

    Informations forums :
    Inscription : décembre 2015
    Messages : 84
    Points : 107
    Points
    107
    Par défaut
    Salut !

    Citation Envoyé par Qwazerty Voir le message
    J'utilise la version gratuite de Mz-Tool, il y a une fonction qui permet de faire ça, ça te liste dans une arborescence tous les projets, tous leurs modules, toutes les fonctions des module, toutes les variables non utilisées dans chaque module. Très pratique pour faire du nettoyage après un développement.
    Je l'ai déjà vu sur le net (une fois je cherchais un outil pour aider au développement) mais je n'ai jamais testé.
    J'utilise Rubberduck (open source) qui permet d'analyser le code, te conseiller sur certaines syntaxe plutôt que d'autres, permet de renommer intelligemment des variables, des modules, etc...
    Il te permet de créer une sorte d'arborescence en rangeant tes modules sous forme de dossiers, etc...
    Il te permet à partir d'une variable dans un module de classe de l'encapsuler, il permet d'extraire une interface, etc...

    J'en oubli forcément, je ne connais pas encore l'étendu de toutes les fonctionnalités et je n'ai pas tout en tête. Bref depuis que je l'ai essayé, je l'ai adopté et j'avoue que je ne sais pas si je saurais m'en passer

    Citation Envoyé par Qwazerty Voir le message
    Pour le Pattern des Implements, j'aurais plutôt utilisé ça

    (?: |\t)*Implements (\w+)
    Oui et non, en fait en pratique je l'ai essayé et il attrape aussi d'autres éléments du code...
    Plus précisément cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Private m_dicImplements As Scripting.Dictionary
    Bon une fois que j'aurais fait mon module de classe cette ligne n'aura plus de raison d'être mais bon... Si un jour je rajoute quelque chose du même genre ailleurs, ça aura un impact négatif sur le résultat de mon code sans que je puisse le voir tout de suite !

    La seule manière que j'avais trouvé était d'utiliser \s ou \n mais comme tu le dis ce sont les sauts de ligne...

    Citation Envoyé par Qwazerty Voir le message
    J'en profite aussi pour te remercier parce que je ne connaissais pas Implements et ça va peut-être me servir
    J'en suis content, un jour on m'a dit :
    Si je te donne 1 €, et toi tu me donnes 1 €... On aura 1€ chacun !
    Mais si je te donne une idée et que tu m'en donne une aussi... On aura deux idées chacun !
    J'ai galéré un peu au début pour trouver des infos sur implements !
    Voici ce que j'ai pu trouver (désolé aux éventuelles personnes de developpez qui ont fait un article la dessus, je n'ai rien trouvé )
    https://www.developpez.net/forums/d6...mplementation/
    https://code.i-harness.com/fr/q/1279c19
    Et si t'es pas Anglophobe :
    https://stackoverflow.com/questions/...s-in-excel-vba

    Citation Envoyé par Qwazerty Voir le message
    Les dicos de dicos me chagrine par contre. Les dicos dicEnumMembers tout particulièrement.
    Ils sont instanciés dans le corps de de la function AnalyserCode, puis empaqueté dans dicEnumerations qui est ensuite transmis au demandeur. Du coup, à la charge du demandeur de détruire l'instance de dicEnumerations, ça ok mais aussi toutes les instances dicEnumMembers qu'il contient et je trouve pas ça très charmant
    La solution serait sans doute d'utiliser des collections au sein d'un module de classe afin d'automatiser la destruction des sous collections lors de la destruction de la collection "conteneur". Je reconnais que ça commence à faire beaucoup de taff

    Comment utilises-tu (notamment leur destruction) les dicos retournés?
    Je suis d'accord avec toi, en écrivant la destruction de l'objet ça me chagrinait aussi... Je me suis dis "Je vais quand même pas faire un module de classe?" lol
    En voyant que je ne suis pas le seul à m'être dis ça, je vais le faire effectivement ça sera plus propre...



    Citation Envoyé par Qwazerty Voir le message
    Tout autre chose, un conseil pour ne pas perdre inutilement plusieurs heures de boulot...
    Lors des phases de teste des regexp, fait en sorte de sauvegarder ton classeur avant chaque teste d'un nouveau pattern. Certain pattern font carrément planter RegExp et il est impossible de stopper le code puisque l'erreur (boucle infini je pense) est en cours à l'extérieur d'excel qui n'arrive plus à reprendre la main... Heureusement que j'ai l’enregistrement auto des xslm... sinon j'aurais pleuré.
    C'est ma hantise dans ma vie de tous les jours... Une fois c'est mon disque dur qui a crashé, j'ai cru perdre 3 mois de boulot (j'avais pas fait de backup de mon disque dur depuis 3 mois par manque de temps).
    Ça devient un toc, je sauvegarde je ne sais pas combien de fois en une journée...
    Il y a 10 types de personnes dans le monde : ceux qui comptent en binaire et les autres.

  12. #12
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    J'utilise Rubberduck (open source) qui permet d'analyser le code, te conseiller sur certaines syntaxe plutôt que d'autres, permet de renommer intelligemment des variables, des modules, etc...
    Je viens de le télécharger je regarde ça dès que j'ai un moment!


    Oui et non, en fait en pratique je l'ai essayé et il attrape aussi d'autres éléments du code...
    Plus précisément cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Private m_dicImplements As Scripting.Dictionary
    Ah oui bien vu
    Alors au moins ça "(\s)Implements (\w*)", il n'est pas utile d'affecter le mot Implements à une sous-chaine. Préciser l'espace après Implements évite d'attraper Private ImplementsA As Scripting.Dictionary le . remplaçant n'importe quel caractère, il faut être prudent

    J'en suis content, un jour on m'a dit :
    Si je te donne 1 €, et toi tu me donnes 1 €... On aura 1€ chacun !
    Mais si je te donne une idée et que tu m'en donne une aussi... On aura deux idées chacun !
    C'est un mantra intéressant. Dès fois je me dis tiens j'ai une belle idée, je me la garde ou je la partage... baa autant la partager, j'en trouverai bien une autre Et souvent en la partageant, on s'apperçoit, soit qu'elle n'était pas si terrible, soit qu'on pouvait faire mieux... rien que le fait d'expliquer une idée permet parfois de la développer, même si l'autre en face ne pipe rien


    J'ai galéré un peu au début pour trouver des infos sur implements !
    Voici ce que j'ai pu trouver (désolé aux éventuelles personnes de developpez qui ont fait un article la dessus, je n'ai rien trouvé )
    https://www.developpez.net/forums/d6...mplementation/
    https://code.i-harness.com/fr/q/1279c19
    Et si t'es pas Anglophobe :
    https://stackoverflow.com/questions/...s-in-excel-vba
    J'ai lu le dernier en entier et j'ai lu en diagonale serrée le 1er juste avant de partir ce matin avant de partir. Mais il est vrai que les information sont maigres, si tu maitrises le truc, tu ne voudrais pas nous faire un tutoriel?

    Je suis d'accord avec toi, en écrivant la destruction de l'objet ça me chagrinait aussi... Je me suis dis "Je vais quand même pas faire un module de classe?" lol
    En voyant que je ne suis pas le seul à m'être dis ça, je vais le faire effectivement ça sera plus propre...
    Si deux idées se recoupent...


    C'est ma hantise dans ma vie de tous les jours... Une fois c'est mon disque dur qui a crashé, j'ai cru perdre 3 mois de boulot (j'avais pas fait de backup de mon disque dur depuis 3 mois par manque de temps).
    Ça devient un toc, je sauvegarde je ne sais pas combien de fois en une journée...
    Je limite les risque avec un NAS, j'ai un RAID sur 3 DD, Si un seul disque rend l'âme (et j'en ai déjà passer au moins 3 en 5/6ans[Peut-être un peu plus... le temps passe si vite!]), l'intégrité des données est assurée. Bon après il y a toujours les risque d'incendie... ou que deux DD rendent l'âme... Je me dit souvent qu'au cours de ma vie je perdrai forcement toutes mes données un jour, toute mes photos (à l'origine c'est pour ça que j'ai pris un NAS)... C'est paradoxale quand je regarde des clichés sur diapo/photo papier qui ont traversé les époques malgré qu'elles aient été prises avec la technologie des années 50, je me dis que toutes les photos que j'ai prise avec une technologie bien plus avancée ne survivront probablement pas aussi longtemps...

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  13. #13
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Salut

    bon j'ai regardé Ruuber vite fait avant de regarder le code source , je ferais une découverte plus approfondi du logiciel mais j'ai retrouvé quelques fonctions de Mz-tool.

    Le code source utilise les interfaces (implements), c'est codé en R#, je ne connais pas la structure de ce langage, ça ressemble à du Java un peu, j'en avais entendu parlé notamment par des amis qui font de la recherche et où R semble utilisé pour faire du traitement de données, bref.

    J'ai regardé le code pour voir si et le cas échéant comment il parse le texte de code... il va falloir que je m'y reprenne plusieurs fois pour comprendre... mais le code utilise bien les RegExp.

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  14. #14
    Membre régulier
    Homme Profil pro
    Automaticien
    Inscrit en
    décembre 2015
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Automaticien

    Informations forums :
    Inscription : décembre 2015
    Messages : 84
    Points : 107
    Points
    107
    Par défaut
    Salut !

    Citation Envoyé par Qwazerty Voir le message
    J'ai regardé le code pour voir si et le cas échéant comment il parse le texte de code... il va falloir que je m'y reprenne plusieurs fois pour comprendre... mais le code utilise bien les RegExp.
    C'est bizarre comme ça m'étonne pas la fonction est tellement puissante, quand tu cherches quelque chose de compliqué t'as juste à te battre pour trouver le bon pattern et la suite c'est du velour...


    Bon voici une première esquisse... Donnes moi ton avis

    Dans un module nommé "blsCollectionClassCommonCode"
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    Attribute VB_Name = "blsCollectionClassCommonCode"
    Option Explicit
     
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'Code commun à tous les objets faisant partie d'une collection d'objets
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     
     
    'Permet de connaitre la position d'un objet dans la collection de son Parent
        '@Param objAppelant: Envoi de l'objet qui veut connaitre sa position dans l'objet Parent
        'Resultat :Renvoi la position de l'élément dans la collection Parent.
    Public Function RetourneIndex(ByVal objAppelant As Object) As Long
        Dim objRecherche As Object
        Dim i As Long
     
        For Each objRecherche In objAppelant.Parent
            i = i + 1
            If objRecherche Is objAppelant Then Exit For
        Next objRecherche
        RetourneIndex = i
    End Function
     
     
    'Permet de retirer tous les éléments de la collection
        '@Param colAVider: Collection qui doit être vidée
        '@Param blnExecuteClearOnChild : Permet d'exécuter la fonction Clear sur chaque objet de la collection
            'A utiliser si l'objet contient lui même une collection. ATTENTION l'objet Child doit avoir une Sub 'Clear'
    Public Sub CollectionClear(ByRef colAVider As Collection, Optional ByVal blnExecuteClearOnChild As Boolean)
        Dim objEnfant As Object
        Dim strTypeParent As String
        Dim strTypeEnfant As String
     
        For Each objEnfant In colAVider
            strTypeParent = TypeName(objEnfant.Parent)
            strTypeEnfant = TypeName(objEnfant)
            If blnExecuteClearOnChild Then
                objEnfant.Clear
            End If
            Set objEnfant.Parent = Nothing              'Brise les liens ascendants
        Next
        Debug.Print "Clear collection of " & strTypeEnfant & " in " & strTypeParent
        Set colAVider = New Collection               'Brise les liens descendants
    End Sub
    Dans un module de classe nommé "clsCodeAnalyseur"
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
    END
    Attribute VB_Name = "clsCodeAnalyseur"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    '@Folder("Analyseur de code")
    Option Explicit
     
    Private m_colEnumerations As Collection
    Private m_colInterfaces As Collection
     
     
    Private Sub Class_Initialize()
        Set m_colEnumerations = New Collection
        Set m_colInterfaces = New Collection
    End Sub
     
     
    Private Sub Class_Terminate()
        Clear
        Debug.Print "Class_Terminate : " & TypeName(Me)
        'Print #221, "Class_Terminate : " & TypeName(Me)
        Set m_colEnumerations = Nothing
        Set m_colInterfaces = Nothing
    End Sub
     
     
    Public Sub AnalyzeCode()
        Dim objVBProject As VBProject
        Dim objVBComponent As VBComponent
        Dim objCodeModule As CodeModule
        Dim objRegExp As RegExp
        Dim objColMatches As MatchCollection
        Dim objMatch As Match
        Dim strVBProjectFileName As String
        Dim strCodeModule As String
        Dim vntSplittedProjectName As Variant
        Dim lngVariableScope As gv_enumVariableScope
     
        Set objRegExp = New RegExp  'On instancie la RegExp
        With objRegExp              'On parametre RegExp
            .Global = True
            .MultiLine = False
            .IgnoreCase = True
        End With
     
        For Each objVBProject In Application.VBE.VBProjects
            vntSplittedProjectName = Split(objVBProject.Filename, "\")    'Découpe le chemin d'accès du FileName avec le séparateur "\"
            vntSplittedProjectName = Split(vntSplittedProjectName(UBound(vntSplittedProjectName)), ".") 'Récupère le Name de fichier en retirant l'extension
            strVBProjectFileName = vntSplittedProjectName(0)
            For Each objVBComponent In objVBProject.VBComponents 'Boucle pour chaque Composant du projet VB (Sheets, ThisWorkbook, Userforms, Modules, Modules de classe)
                Set objCodeModule = objVBComponent.CodeModule 'Permet d'accéder au code contenu dans le composant du projet VB
                With objCodeModule
                    If .CountOfLines > 0 And .CountOfDeclarationLines > 0 Then
                        strCodeModule = .Lines(1, .CountOfLines)
                        'On supprime les Comments si ils sont trouvés
                        If RegExpExecute(objRegExp, strCodeModule, "((\t| )*REM|')(\s*(.*)(\n(\t| )*?.*( _\n\s*.*))?)", objColMatches) Then
                            strCodeModule = objRegExp.Replace(strCodeModule, Chr(13))
                        End If
     
                        If RegExpExecute(objRegExp, strCodeModule, "(?:\s)+(Public |Private )?Enum ((?:\w)*)((?:.|\n)*?)End Enum", objColMatches) Then
                            'On prend en compte la liste des enum
                            For Each objMatch In objColMatches
                                Select Case objMatch.SubMatches(0)
                                    Case "Public "
                                        lngVariableScope = ePublic
                                    Case "Private "
                                        lngVariableScope = ePrivate
                                End Select
                                AddEnumerations strListEnumMembers:=objMatch.SubMatches(2), _
                                    lngVariableScope:=lngVariableScope, _
                                    strNameEnum:=objMatch.SubMatches(1), _
                                    strModuleName:=objVBComponent.Name, _
                                    strProjectName:=strVBProjectFileName
                            Next
                        End If
     
                        If RegExpExecute(objRegExp, strCodeModule, "(?:\s)Implements (\w*)", objColMatches) Then
                            AddInterfaces objColMatches, objVBComponent.Name
                        End If
                    End If
                End With
            Next
        Next
    End Sub
     
     
    Private Sub AddEnumerations(strListEnumMembers As String, lngVariableScope As gv_enumVariableScope, strNameEnum As String, strModuleName As String, strProjectName As String)
        Dim objClsEnum As clsCodeEnum
        Dim lngEnumMemberValue As Long
        Dim vntLigneEnum As Variant
        Dim vntCoupleKV As Variant
     
        Set objClsEnum = New clsCodeEnum
        With objClsEnum
            .Name = strNameEnum
            .ModuleName = strModuleName
            .ProjectName = strProjectName
            .VariableScope = lngVariableScope
            Set .Parent = Me
     
            strListEnumMembers = Replace(Replace(Replace(strListEnumMembers, Chr(9), vbNullString), " ", vbNullString), Chr(10), "")
            'Initialisation
            lngEnumMemberValue = -1
     
            'On boucle sur chaque ligne (membre d'énumération)
            For Each vntLigneEnum In Split(strListEnumMembers, Chr(13))
                If vntLigneEnum <> "" Then
                    'On découpe pour trouver le couple key / Value
                    vntCoupleKV = Split(vntLigneEnum, "=")
     
                    If UBound(vntCoupleKV) > 0 Then
                        'On retire les " et converti en Long (en cas de Value Hexadécimale)
                        vntCoupleKV(1) = Replace(vntCoupleKV(1), """", vbNullString)
                        lngEnumMemberValue = CLng(vntCoupleKV(1))
                    Else
                        'On détermine la Value attribuée par VB
                        lngEnumMemberValue = lngEnumMemberValue + 1
                    End If
                    .AddMember CStr(vntCoupleKV(0)), lngEnumMemberValue
                End If
            Next
        End With
        Select Case lngVariableScope
            Case ePrivate
                m_colEnumerations.Add objClsEnum, CStr(strProjectName & "|" & strModuleName & "|" & strNameEnum)
            Case ePublic
                m_colEnumerations.Add objClsEnum, strNameEnum
        End Select
    End Sub
     
     
    Private Sub AddInterfaces(objColMatches As MatchCollection, strModuleName As String)
        Dim objClsInterfaces As clsCodeInterfaces
        Dim objMatch As Match
     
        Set objClsInterfaces = New clsCodeInterfaces
        With objClsInterfaces
            .ModuleName = strModuleName
            Set .Parent = Me
     
            For Each objMatch In objColMatches
                .AddInterface objMatch.SubMatches(0)
            Next
        End With
        m_colInterfaces.Add objClsInterfaces, strModuleName
    End Sub
     
     
    Public Sub Clear()
        blsCollectionClassCommonCode.CollectionClear m_colEnumerations, True
        blsCollectionClassCommonCode.CollectionClear m_colInterfaces
    End Sub
     
    Public Function ItemEnumeration(Index As Variant) As clsCodeEnum
        Set ItemEnumeration = m_colEnumerations.Item(Index)
    End Function
     
    Public Function ItemInterface(Index As Variant) As clsCodeInterfaces
        Set ItemInterface = m_colInterfaces.Item(Index)
    End Function
     
    Public Function CountEnumerations() As Long
        CountEnumerations = m_colEnumerations.Count
    End Function
     
    Public Function CountInterfaces() As Long
        CountInterfaces = m_colInterfaces.Count
    End Function
     
    Public Sub RemoveEnumeration(ByVal Index As Variant)
        ItemEnumeration(Index).Clear
        Set ItemEnumeration(Index).Parent = Nothing
        m_colEnumerations.Remove Index
    End Sub
     
    Public Sub RemoveInterface(ByVal Index As Variant)
        Set ItemInterface(Index).Parent = Nothing
        m_colInterfaces.Remove Index
    End Sub
    Dans un module de classe nommé "clsCodeEnum"
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
    END
    Attribute VB_Name = "clsCodeEnum"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    '@Folder("Analyseur de code.Enumerations")
    Option Explicit
     
    Private m_clsParent As clsCodeAnalyseur
    Private m_colMembers As Collection 'Scripting.Dictionary
    Private m_lngVariableScope As gv_enumVariableScope
    Private m_strName As String
    Private m_strModuleName As String
    Private m_strProjectName As String
     
    Public Property Get ProjectName() As String
        ProjectName = m_strProjectName
    End Property
     
     
    Public Property Let ProjectName(ByVal strProjectName As String)
        m_strProjectName = strProjectName
    End Property
     
     
     
     
     
    Public Property Get ModuleName() As String
        ModuleName = m_strModuleName
    End Property
     
     
    Public Property Let ModuleName(ByVal strModuleName As String)
        m_strModuleName = strModuleName
    End Property
     
     
     
     
    Public Property Get Name() As String
        Name = m_strName
    End Property
     
     
    Public Property Let Name(ByVal strName As String)
        m_strName = strName
    End Property
     
     
     
     
    Public Property Get Parent() As clsCodeAnalyseur
        Set Parent = m_clsParent
    End Property
     
     
    Public Property Set Parent(ByVal clsParent As clsCodeAnalyseur)
        Set m_clsParent = clsParent
    End Property
     
     
     
     
    Public Property Get VariableScope() As gv_enumVariableScope
        VariableScope = m_lngVariableScope
    End Property
     
     
    Public Property Let VariableScope(ByVal lngVariableScope As gv_enumVariableScope)
        m_lngVariableScope = lngVariableScope
    End Property
     
     
     
     
    Public Function Item(Index As Variant) As clsCodeEnumMember
        Set Item = m_colMembers.Item(Index)
    End Function
     
     
     
     
    Public Sub Clear()
        blsCollectionClassCommonCode.CollectionClear m_colMembers
    End Sub
     
     
    Public Function AddMember(strName As String, lngValue As Long, Optional strComment As String) As clsCodeEnumMember
        Dim objEnumMember As clsCodeEnumMember
     
        Set objEnumMember = New clsCodeEnumMember
        With objEnumMember
            .Name = strName
            .Value = lngValue
            .Comment = strComment
            Set .Parent = Me
        End With
        m_colMembers.Add objEnumMember, strName
    End Function
     
    Public Sub RemoveMember(Index As Variant)
        Set Item(Index).Parent = Nothing
        m_colMembers.Remove Index
    End Sub
     
     
    Public Function CountMembers() As Long
        CountMembers = m_colMembers.Count
    End Function
     
    Private Sub Class_Initialize()
        Set m_colMembers = New Collection
    End Sub
     
    Private Sub Class_Terminate()
        Debug.Print "Class_Terminate : " & TypeName(Me)
        'Print #221, "Class_Terminate : " & TypeName(Me) & " (" & Me.Name & ")"
        'Set m_clsParent = Nothing
        Set m_colMembers = Nothing
    End Sub
    Dans un module de classe nommé "clsCodeEnumMember"
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
    END
    Attribute VB_Name = "clsCodeEnumMember"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    '@Folder("Analyseur de code.Enumerations.Members")
    Option Explicit
     
    Private m_clsParent As clsCodeEnum
    Private m_strName As String
    Private m_lngValue As Long
    Private m_strComment As String
     
     
    Public Property Get Name() As String
        Name = m_strName
    End Property
     
     
    Public Property Let Name(ByVal strName As String)
        m_strName = strName
    End Property
     
     
     
     
    Public Property Get Value() As Long
        Value = m_lngValue
    End Property
     
     
    Public Property Let Value(ByVal lngValue As Long)
        m_lngValue = lngValue
    End Property
     
     
     
     
    Public Property Get Comment() As String
        Comment = m_strComment
    End Property
     
     
    Public Property Let Comment(ByVal strComment As String)
        m_strComment = strComment
    End Property
     
     
     
     
    Public Property Get Parent() As clsCodeEnum
        Set Parent = m_clsParent
    End Property
     
     
    Public Property Set Parent(ByVal clsParent As clsCodeEnum)
        Set m_clsParent = clsParent
    End Property
     
     
     
     
     
    Private Sub Class_Terminate()
        Debug.Print "Class_Terminate : " & TypeName(Me)
        'Print #221, "Class_Terminate : " & TypeName(Me) & " (" & Me.Name & ")"
        'Set m_clsParent = Nothing
    End Sub
    Dans un module de classe nommé "clsCodeInterfaces"
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    VERSION 1.0 CLASS
    BEGIN
      MultiUse = -1  'True
    END
    Attribute VB_Name = "clsCodeInterfaces"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    '@Folder("Analyseur de code.Implémentations")
    Option Explicit
     
    Private m_clsParent As clsCodeAnalyseur
    Private m_strModuleName As String
    Private m_dicInterfaces As Scripting.Dictionary 'Collection
     
    Public Property Get ModuleName() As String
        ModuleName = m_strModuleName
    End Property
     
     
    Public Property Let ModuleName(ByVal strModuleName As String)
        m_strModuleName = strModuleName
    End Property
     
     
     
     
    Public Property Get Parent() As clsCodeAnalyseur
        Set Parent = m_clsParent
    End Property
     
     
    Public Property Set Parent(ByVal clsParent As clsCodeAnalyseur)
        Set m_clsParent = clsParent
    End Property
     
     
     
     
     
    Public Sub AddInterface(strNameInterface As String)
        m_dicInterfaces.Add strNameInterface, strNameInterface ', strNameInterface
    End Sub
     
    Public Function Exists(strKey As String) As Boolean
        Exists = m_dicInterfaces.Exists(strKey)
    End Function
     
     
    Private Sub Class_Initialize()
        Set m_dicInterfaces = New Scripting.Dictionary 'Collection
    End Sub
     
    Private Sub Class_Terminate()
        Debug.Print "Class_Terminate : " & TypeName(Me)
        'Print #221, "Class_Terminate : " & TypeName(Me)
        'Set m_clsParent = Nothing
        Set m_dicInterfaces = Nothing
    End Sub
    Ce n'est pas fini, je dois regarder pour gérer les doublons et pour ajouter les commentaires sur les membres de l'énumération...
    Mais bon une bonne partie est faite normalement


    [Edit]: Par fatigue peut-être, j'ai oublié d'intégrer Count et Remove... Je corrige le tir ! C'est ajouté, j'ai aussi modifié le tout pour éviter le Franglais...
    Il y a 10 types de personnes dans le monde : ceux qui comptent en binaire et les autres.

  15. #15
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    avril 2002
    Messages
    3 622
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : avril 2002
    Messages : 3 622
    Points : 8 087
    Points
    8 087
    Par défaut
    Salut

    Je suis en plein préparatifs de départ en vacance et plutôt que de faire une réponse à la va vite, je me réserve l'étude de ton code à mon retour dans 1 semaine.

    Par contre je n'ai pas pu m'empêcher de penser aux implements et je me demande si ça ne serait pas intéressant dans le cas qui nous occupe, j’essaie de gratter ça avant de partir en vacance! (J'ai déjà couché quelques lignes)

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

Discussions similaires

  1. [C#] Récupérer le nom des colonnes d'une datatable
    Par dai.kaioh dans le forum Accès aux données
    Réponses: 6
    Dernier message: 28/09/2006, 17h35
  2. récupérer le nom des attributs d'une classe
    Par danyboy85 dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 22/06/2006, 11h42
  3. Réponses: 11
    Dernier message: 12/05/2006, 17h18
  4. Réponses: 2
    Dernier message: 23/06/2005, 17h56
  5. récupérer le nom des champs d'une table d'une BDD-page web
    Par mathieu_r dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 09/06/2005, 14h02

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