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

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

Macros et VBA Excel Discussion :

Tri et filtrage VBA avec tableaux structurés


Sujet :

Macros et VBA Excel

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut Tri et filtrage VBA avec tableaux structurés
    Bonjour à tous,

    Je devrai élaborer plusieurs fichiers Excel, avec lesquels effectuer, en VBA, des opérations de base (filtrage et tri notamment). Or, depuis l'un de mes derniers messages, j'ai suivi le conseil de Philippe Tulliez, qui évoquait l'intérêt de passer par des tableaux structurés... ce que je ne connaissais pas. C'est effectivement très pratique, plus besoin de passer par des formules pour gérer la taille du tableau! Mais j'ai tout de même quelques difficultés à élaborer mon fichier. Il est d'autant plus important qu'il servira de structure pour les fichiers à venir.

    En gros, j'aimerais, pour chaque tableau structuré nommé, respecter certaines règles:
    1) Utilisation des macros événementielles
    2) Feuilles protégées sans mot de passe

    et là où je bute:

    3) Certaines colonnes seront filtrables (le doubleclic dans une cellule filtre les données OU les réaffiche toutes si un filtrage était déjà en cours dans la colonne)
    4) Certaines colonnes seront triables (par doubleclic sur l'entête; un doubleclic trie de A à Z, un nouveau doubleclic sur l'entête trie dans l'autre sens. Un doubleclic sur une cellule effectue un filtrage)
    5) Certaines colonnes seront filtrables et triables (lorsqu'un deuxième filtre s'applique, il ne doit pas effacer le premier, il s'ajoute au premier et s'applique seulement aux lignes affichées)
    6) D'autres colonnes ne seront ni l'un ni l'autre

    J'ai passé par ChatGPT, qui m'a proposé des solutions très proches de ce que je cherche... mais jamais tout à fait fiables, ou jamais tout à fait à 100%. Je cherchais quelque chose qui soit le plus simple possible. La possibilité d'indiquer, dans la macro et pour chaque fichier, les colonnes où interviendra le tri, le filtrage (ou les deux) m'intéresse beaucoup, car elle offre une structure de base où il ne me sera pas nécessaire de devoir tout réinventer à chaque fois. Voici, à titre d'exemple, les codes que l'IA m'a proposés:

    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
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    Private Sub Workbook_Open()
        Dim ws As Worksheet
        Dim tbl As ListObject
     
        ' Désactiver les événements et le rafraîchissement d'écran
        Application.EnableEvents = False
        Application.ScreenUpdating = False
     
        ' Déprotéger la feuille, désactiver les icônes de filtrage, puis reprotéger la feuille
        For Each ws In ThisWorkbook.Worksheets
            ws.Unprotect Password:=""
            For Each tbl In ws.ListObjects
                tbl.ShowAutoFilter = False
            Next tbl
            ws.Protect Password:="", UserInterfaceOnly:=True
        Next ws
     
        ' Réactiver les événements et le rafraîchissement d'écran
        'Application.ScreenUpdating = True
        Application.EnableEvents = True
    End Sub
     
     
     
     
     
     
    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        Dim tbl As ListObject
        Dim triableCols As Collection
        Dim filterableCols As Collection
        Dim col As Variant
     
        On Error GoTo EnableEvents
     
        Set triableCols = New Collection
        Set filterableCols = New Collection
     
        triableCols.Add 2 ' Colonne 2 dans le tableau structuré (B)
        triableCols.Add 11 ' Colonne 11 dans le tableau structuré (K)
     
        filterableCols.Add 2 ' Colonne 2 dans le tableau structuré (D)
        filterableCols.Add 3 ' Colonne 3 dans le tableau structuré (E)
        filterableCols.Add 4 ' Colonne 4 dans le tableau structuré (F)
        filterableCols.Add 5 ' Colonne 5 dans le tableau structuré (G)
     
        ' Définir le tableau structuré
        Set tbl = ActiveSheet.ListObjects("Rapports_médicaux")
        ' MsgBox "Début de Worksheet_BeforeDoubleClick"
     
        ' Désactiver les événements pour éviter les déclenchements récursifs
        Application.EnableEvents = False
     
        ' MsgBox "Avant de vérifier la cellule"
     
        ' Vérifier si le double-clic est sur une cellule pour filtrer
        If Not Intersect(Target, tbl.DataBodyRange) Is Nothing Then
            ' MsgBox "Double-clic sur une cellule dans la plage de données"
            For Each col In filterableCols
                ' MsgBox "Vérification de la colonne " & col & " contre la colonne cible " & (Target.Column - tbl.Range.Column + 1)
                If (Target.Column - tbl.Range.Column + 1) = col Then
                    ' MsgBox "La cellule est dans les colonnes filtrables"
                    ' Vérifier si la colonne est déjà filtrée
                    If Not tbl.AutoFilter Is Nothing Then
                        If tbl.AutoFilter.Filters.Count >= col And tbl.AutoFilter.Filters(col).On Then
                            ' MsgBox "Réinitialisation du filtrage pour la colonne"
                            RéinitialiserFiltrageColonne CInt(col)
                        Else
                            ' MsgBox "Application du filtrage exact"
                            ' Appliquer le filtre exact
                            FiltreExact CInt(col), Target.Value, True
                        End If
                    Else
                        ' MsgBox "Application du filtrage exact"
                        ' Appliquer le filtre exact
                        FiltreExact CInt(col), Target.Value, True
                    End If
     
                    Cancel = True
                    GoTo EnableEvents
                End If
            Next col
            ' MsgBox "Colonne non trouvée dans les colonnes filtrables"
            GoTo EnableEvents
        End If
     
        ' MsgBox "Avant de vérifier l'en-tête"
     
        ' Vérifier si le double-clic est sur l'en-tête pour trier ou réinitialiser
        If Not Intersect(Target, tbl.HeaderRowRange) Is Nothing Then
            For Each col In triableCols
                ' MsgBox "Vérification de la colonne triable " & col & " contre la colonne cible " & (Target.Column - tbl.Range.Column + 1)
                If (Target.Column - tbl.Range.Column + 1) = col Then
                    ' MsgBox "L'en-tête est dans les colonnes triables"
                    TriColonne CInt(col)
                    Cancel = True
                    GoTo EnableEvents
                End If
            Next col
     
            For Each col In filterableCols
                ' MsgBox "Vérification de la colonne filtrable " & col & " contre la colonne cible " & (Target.Column - tbl.Range.Column + 1)
                If (Target.Column - tbl.Range.Column + 1) = col Then
                    ' MsgBox "L'en-tête est dans les colonnes filtrables"
                    RéinitialiserFiltrage
                    Cancel = True
                    GoTo EnableEvents
                End If
            Next col
            ' MsgBox "Aucune colonne correspondante trouvée dans les en-têtes"
            GoTo EnableEvents
        End If
     
        ' MsgBox "Après vérification de l'en-tête"
     
    EnableEvents:
        ' Réactiver les événements
        Application.EnableEvents = True
    End Sub
     
     
     
     
     
     
    Sub RéinitialiserFiltrage()
        Dim tbl As ListObject
        Dim cell As Range
     
        ' Définir le tableau structuré
        Set tbl = ActiveSheet.ListObjects("Rapports_médicaux")
        ' MsgBox "Début de la réinitialisation du filtrage"
     
        ' Afficher toutes les lignes du tableau
        Application.ScreenUpdating = False
        For Each cell In tbl.ListColumns(1).DataBodyRange
            cell.EntireRow.Hidden = False
        Next cell
        Application.ScreenUpdating = True
        ' MsgBox "Filtrage réinitialisé"
    End Sub
     
    Sub RéinitialiserFiltrageColonne(colIndex As Integer)
        Dim tbl As ListObject
        Dim cell As Range
        Dim otherFilters As Collection
        Dim col As Variant
     
        ' Définir le tableau structuré
        Set tbl = ActiveSheet.ListObjects("Rapports_médicaux")
        Set otherFilters = New Collection
     
        ' MsgBox "Début de la réinitialisation du filtrage pour la colonne " & colIndex
     
        ' Trouver les autres colonnes qui sont filtrées
        For col = 1 To tbl.ListColumns.Count
            If col <> colIndex Then
                If tbl.AutoFilter.Filters(col).On Then
                    otherFilters.Add col
                End If
            End If
        Next col
     
        ' Afficher toutes les lignes du tableau pour la colonne spécifiée
        Application.ScreenUpdating = False
        tbl.Range.AutoFilter Field:=colIndex
        For Each cell In tbl.ListColumns(colIndex).DataBodyRange
            cell.EntireRow.Hidden = False
        Next cell
     
        ' Réappliquer les filtres des autres colonnes
        For Each col In otherFilters
            tbl.Range.AutoFilter Field:=col, Criteria1:=tbl.AutoFilter.Filters(col).Criteria1
        Next col
     
        Application.ScreenUpdating = True
        ' MsgBox "Filtrage de la colonne réinitialisé"
    End Sub
     
    Sub FiltreExact(colIndex As Integer, filtreValeur As String, Optional filtreVisibleSeulement As Boolean = False)
        Dim tbl As ListObject
        Dim cell As Range
        Dim found As Boolean
        Dim cellValue As String
     
        ' Définir le tableau structuré
        Set tbl = ActiveSheet.ListObjects("Rapports_médicaux")
        ' MsgBox "Début du filtrage exact sur la colonne " & colIndex
     
        ' Appliquer le filtrage exact
        Application.ScreenUpdating = False
        found = False
        For Each cell In tbl.ListColumns(colIndex).DataBodyRange
            If Not filtreVisibleSeulement Or cell.EntireRow.Hidden = False Then
                cellValue = cell.Value
                ' MsgBox "Comparaison de la valeur de la cellule: " & cellValue & " avec la valeur du filtre: " & filtreValeur
                If cellValue = filtreValeur Then
                    cell.EntireRow.Hidden = False
                    found = True
                Else
                    cell.EntireRow.Hidden = True
                End If
            End If
        Next cell
        Application.ScreenUpdating = True
        If found Then
            ' MsgBox "Filtrage appliqué"
        Else
            ' MsgBox "Aucune correspondance trouvée"
        End If
    End Sub
     
    Sub TriColonne(colIndex As Integer)
        Dim tbl As ListObject
        Dim currentOrder As XlSortOrder
     
        ' Définir le tableau structuré
        Set tbl = ActiveSheet.ListObjects("Rapports_finaux")
        ' MsgBox "Début du tri sur la colonne " & colIndex
     
        ' Déterminer l'ordre de tri actuel
        If tbl.Sort.SortFields.Count > 0 Then
            If tbl.Sort.SortFields(1).Order = xlAscending Then
                currentOrder = xlDescending
            Else
                currentOrder = xlAscending
            End If
        Else
            currentOrder = xlAscending
        End If
     
        ' Effectuer le tri sur la colonne spécifiée
        tbl.Sort.SortFields.Clear
        tbl.Sort.SortFields.Add Key:=tbl.ListColumns(colIndex).Range, _
                                SortOn:=xlSortOnValues, Order:=currentOrder, DataOption:=xlSortNormal
     
        With tbl.Sort
            .Header = xlOui
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With
        ' MsgBox "Tri effectué"
    End Sub
    Sur cette macro, Excel affiche une erreur 91 à la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If tbl.AutoFilter.Filters.Count >= col And tbl.AutoFilter.Filters(col).On Then
    Tous les msgbox (désactivés) m'ont servi à identifier où se situaient les problèmes.

    Merci d'avance pour toute aide que vous pourriez m'apporter!

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Je vois que j'ai fait une erreur: le tableau s'appelle Rapports_finaux (C8:M123, la ligne 7 étant réservée aux en-têtes)

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Excusez-moi, dernière précision: un doubleclic en colonne E, par exemple, effectue un filtrage (Excel n'affiche que les lignes avec la valeur sur laquelle l'utilisateur a doublecliqué, ou réaffiche tout si un filtrage était en cours). Un doubleclic en colonne F effectue un nouveau filtrage, parmi les lignes affichées.

    Mais, et c'est ce que n'arrive pas à faire ChatGPT, si je doubleclique sur une cellule en colonne E, Excel doit enlever tout filtre pour cette colonne-là, et cette colonne-là seulement! Désolé pour la longueur, mais je voulais être le plus clair possible

  4. #4
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    975
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 975
    Points : 4 096
    Points
    4 096
    Par défaut
    Bonjour,
    Pour répondre à certains de vos besoins je vous propose l'approche ci-dessous expliquée avec cette image :

    Nom : Capture d’écran.jpg
Affichages : 121
Taille : 83,0 Ko

    De "A" à "H" le tableau structuré nommé [TS_Eleves], où je veux classer par ordre croissant ou décroissant les noms de famille et prénoms et ôter le filtre des notes en cliquant sur les en-têtes respectifs.
    J'ai créé en "J:L" un second tableau [Tableau_Tri], que vous masquerez par la suite, qui reprend en "J1" la cellule "Nom Famille". Cette cellule est nommée "Nom_Famille" via le menu "Formules \ gestionnaire des noms". Idem pour le prénom en "K1" nommé "Prénom" et la note en "L1" nommée "Note".
    Puis en "A1" j'ai inséré un lien : clic droit / liens / Emplacement dans ce document / Noms définis = Nom_Famille. (Astuce : modifiez l'info bulle par "Trier" pour ne pas voir afficher un vilain texte quand la souris pointe la cellule).
    A quoi ça sert ?
    Lorsque vous cliquez sur la cellule "A1"le lien vous redirige vers "J1" qui est sélectionnée. Il ne reste plus qu'a faire un événement "Sur changement de sélection". Si "J1" est sélectionné alors on trie les noms de famille soit par ordre croissant si J2=-1 ou décroissant dans le cas contraire. Et l'on renseigne "J2" du nouveau tri.
    Si "K1" est sélectionné, même principe sur la colonne des prénoms.
    Si "L1" est sélectionné on supprime le filtre de la colonne des notes.

    Ci-dessous le code de l'événement. Les fonctions utilisées sont expliquées dans cette documentation : Fonctions pour gérer les Tableaux Structurés

    Code VBA : 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
    '------------------------------------------------------------------------------------------------------
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    '------------------------------------------------------------------------------------------------------
     
    If Target.Address = Range("Nom_Famille").Address Then
        If TS_InfoCellule([Tableau_Tri], "Nom Famille", 1) = -1 Then
            Call TS_TrierUneColonne([TS_Eleves], "Nom Famille", xlSortOnValues, xlAscending)
            Call TS_ModifCellule([Tableau_Tri], "Nom Famille", 1, 1)
        Else
            Call TS_TrierUneColonne([TS_Eleves], "Nom Famille", xlSortOnValues, xlDescending)
            Call TS_ModifCellule([Tableau_Tri], "Nom Famille", 1, -1)
        End If
        [TS_Eleves].ListObject.HeaderRowRange([TS_Eleves].ListObject.ListColumns("Nom Famille").Index).Select
    End If
     
    If Target.Address = Range("Prénom").Address Then
        If TS_InfoCellule([Tableau_Tri], "Prénom", 1) = -1 Then
            Call TS_TrierUneColonne([TS_Eleves], "Prénom", xlSortOnValues, xlAscending)
            Call TS_ModifCellule([Tableau_Tri], "Prénom", 1, 1)
        Else
            Call TS_TrierUneColonne([TS_Eleves], "Prénom", xlSortOnValues, xlDescending)
            Call TS_ModifCellule([Tableau_Tri], "Prénom", 1, -1)
        End If
        [TS_Eleves].ListObject.HeaderRowRange([TS_Eleves].ListObject.ListColumns("Prénom").Index).Select
    End If
     
    If Target.Address = Range("Note").Address Then
        Call TS_Filtres_Effacer([TS_Eleves], "Note")
        [TS_Eleves].ListObject.HeaderRowRange([TS_Eleves].ListObject.ListColumns("Note").Index).Select
    End If
     
    End Sub
    '------------------------------------------------------------------------------------------------------

    Bonne continuation.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Merci laurent_ott, mais c'est trop compliqué pour moi...
    Je me rends compte que, finalement, ce que j'aimerais est assez simple à expliquer, mais beaucoup moins à réaliser. Sur les colonnes où le doubleclic doit s'appliquer, lors d'un doubleclic sur une cellule, Excel doit évaluer si des filtres sont déjà actifs POUR CETTE COLONNE-LA SEULEMENT. S'il n'y en a pas, il récupère la valeur de la cellule doublecliquée et n'affiche que les lignes contenant cette valeur. Si un filtre est déjà actif, Excel l'enlève.

    Si je passe à une colonne adjacente, Excel doit fonctionner pareil. S'il filtre des données, il doit le faire uniquement sur les cellules affichées (et pas sur celles qui ont été masquées avec un premier filtre). C'est là que l'IA bute: soit elle annule tous les les filtres, soit ils ne fonctionnent pas

  6. #6
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    975
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 975
    Points : 4 096
    Points
    4 096
    Par défaut
    Ca pourrait ressembler à cela :

    Code VBA : 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
    '------------------------------------------------------------------------------------------------------
    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    '------------------------------------------------------------------------------------------------------
    Dim r As Range, Colonne As Long, Ligne As Long
    Set r = TS_CelluleActive(Range("TS_Eleves"), Colonne, Ligne)
    If Not r Is Nothing Then
     
        If TS_Filtres_Existe([TS_Eleves], Colonne) = True Then
            Call TS_Filtres_Effacer([TS_Eleves], Colonne)
        Else
            Call TS_Filtres_Poser([TS_Eleves], Colonne, Target.Value)
        End If
     
        Cancel = True
     
    End If
     
    End Sub
    '------------------------------------------------------------------------------------------------------

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Je ne vois pas bien comment adapter ta macro à mon problème.

    Comme indiqué dans le colonne, les colonnes du tableau "Rapports_finaux" sur lesquels j'aimerais pouvoir appliquer des filtrages par doubleclic sont les colonnes 2, 3, 4, 11, et celles où j'aimerais pouvoir trier les données, par doubleclic également, sont les colonnes 2, 5.

    Le doubleclic dans les colonnes indiquées doit faire faire une évaluation à Excel: s'il y a déjà un filtre DANS CETTE COLONNE, l'enlever (plus de filtre); s'il n'y a pas de filtre, récupérer la valeur doublecliquée et n'afficher que les lignes qui ont cette valeur.

    Comme indiqué aussi, chaque ligne est indépendante des autres: lorsqu'un filtrage est effectué, les données ne sont pas, au préalable, réaffichées: le filtrage se fait uniquement sur les lignes affichées.

    Quant au tri, il doit se faire par doubleclic en D7 ou en G7.

    S'il t'était possible de m'indiquer comment adapter ta macro à ces contraintes, je serais très satisfait et soulagé!!

    Merci

  8. #8
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 936
    Points : 28 932
    Points
    28 932
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    Personnellement, si le but est de faire fonctionner le filtre comme le tri pour n'importe quel tableau structuré du classeur lors d'un double click, je privilégierais la procédure événementielle

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
      Dim oList As ListObject
      Dim c As Integer
      Set oList = Target.ListObject
      If Not oList Is Nothing Then
         ' Ici le code pour invoquer les procédures qui traiteront soit le tri (si le double clic a été effectué dans la ligne des titresà soit le filtre (si le double clic a eu lieu dans la zone des données)
         Cancel = True
      End If
    End Sub
    Pour savoir si une colonne est filtrée, voici un exemple d'une procédure nommée IsFilteredColumn qui renvoie True si elle est filtrée et False dans le cas contraire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Function IsFilteredColumn(oList As ListObject, Column As Variant)
     ' Arguments
     '   oList       Table a tester
     '   Column   soit le nom de la colonne, soit son numéro
     '
      With oList
       If VarType(Column) = vbString Then Column = .ListColumns(Column).Index
       IsFilteredColumn = .AutoFilter.Filters.Item(Column).On
      End With
    End Function
    Exemple pour l"invoquer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Sub Test_IsFilteredColumn()
      Debug.Print IsFilteredColumn(Range("t_Data_1").ListObject, "Ville")
    End Sub
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Bonjour Philippe,

    Merci pour votre message! Mais je ne suis pas sûr de voir comment l'adapter aux contraintes que j'ai décrites. Où apparaîtrait le nom du tableau structuré, "Rapports_finaux"? A quoi correspondraient "t_data_1" et "Ville" dans mon exemple? Si vous pouviez m'éclairer un peu, ce serait avec grand plaisir!

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    J'ajoute encore les derniers codes proposés par l'IA, qui, comme je l'ai dit, fonctionnent, mais avec une certaine instabilité... Cela vous permettra peut-être de mieux comprendre et de me suggérer ce qui sera utile dans ma situation. Merci!

    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
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    Private Sub Workbook_Open()
        RéinitialiserTousLesFiltres
    End Sub
     
     
     
    Module standard
     
    Sub RéinitialiserTousLesFiltres()
        Dim ws As Worksheet
        Dim tbl As ListObject
        Dim headerCell As Range
     
        Application.ScreenUpdating = False
        Application.EnableEvents = False
     
        For Each ws In ThisWorkbook.Worksheets
            On Error Resume Next
            Set tbl = ws.ListObjects("Rapports_finaux")
            If Not tbl Is Nothing Then
                tbl.Range.AutoFilter
                For Each headerCell In tbl.HeaderRowRange
                    headerCell.Value = Trim(headerCell.Value)
                Next headerCell
            End If
            On Error GoTo 0
        Next ws
     
        Application.EnableEvents = True
        Application.ScreenUpdating = True
    End Sub
     
    Sub RéinitialiserFiltrageColonne(tbl As ListObject, colIndex As Integer)
        Application.ScreenUpdating = False
     
        ' Réinitialiser uniquement le filtre de la colonne spécifiée
        tbl.Range.AutoFilter Field:=colIndex
     
        ' Faire défiler la feuille de calcul vers le haut pour afficher les en-têtes
        ActiveWindow.ScrollRow = 1
     
        ' Masquer les icônes de filtrage
        On Error Resume Next
        If tbl.ShowAutoFilter Then
            ActiveSheet.Unprotect
            tbl.ShowAutoFilter = False
            ActiveSheet.Protect
        End If
        On Error GoTo 0
     
        Application.ScreenUpdating = True
    End Sub
     
    Sub FiltreExact(tbl As ListObject, colIndex As Integer, filtreValeur As String)
        Application.ScreenUpdating = False
     
        ' Debug message
        MsgBox "Application du filtrage exact sur la colonne " & colIndex & " avec la valeur " & filtreValeur
     
        ' Appliquer le filtrage sur la colonne spécifiée
        tbl.Range.AutoFilter Field:=colIndex, Criteria1:=filtreValeur
     
        ' Faire défiler la feuille de calcul vers le haut pour afficher les en-têtes
        ActiveWindow.ScrollRow = 1
     
        ' Masquer les icônes de filtrage
        On Error Resume Next
        If tbl.ShowAutoFilter Then
            ActiveSheet.Unprotect
            tbl.ShowAutoFilter = False
            ActiveSheet.Protect
        End If
        On Error GoTo 0
     
        Application.ScreenUpdating = True
    End Sub
     
     
     
     
    Module de feuille de calcul 
     
    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        Dim tbl As ListObject
        Dim colIndex As Integer
     
        ' Désactiver les événements pour éviter les déclenchements récursifs
        Application.EnableEvents = False
     
        ' Définir le tableau structuré
        Set tbl = ActiveSheet.ListObjects("Rapports_finaux")
     
        ' Debug messages
        MsgBox "Début de Worksheet_BeforeDoubleClick"
     
        ' Vérifier si le double-clic est sur une cellule pour filtrer
        If Not Intersect(Target, tbl.DataBodyRange) Is Nothing Then
            colIndex = Target.Column - tbl.Range.Column + 1
     
            ' Debug messages
            MsgBox "Double-clic sur une cellule dans la colonne " & colIndex
     
            ' Vérifier l'état du filtrage
            If GetFilterState(tbl, colIndex) = "Filtrage activé" Then
                MsgBox "Filtrage déjà activé, réinitialisation..."
                RéinitialiserFiltrageColonne tbl, colIndex
                SetFilterState tbl, colIndex, "Filtrage désactivé"
            Else
                MsgBox "Aucun filtrage actif, application du filtrage..."
                FiltreExact tbl, colIndex, Target.Value
                SetFilterState tbl, colIndex, "Filtrage activé"
            End If
     
            ' Masquer les icônes de filtrage
            On Error Resume Next
            ActiveSheet.Unprotect
            tbl.ShowAutoFilter = False
            ActiveSheet.Protect
            On Error GoTo 0
     
            Cancel = True
            GoTo EnableEvents
        End If
     
        ' Vérifier si le double-clic est sur l'en-tête pour trier ou réinitialiser
        If Not Intersect(Target, tbl.HeaderRowRange.Cells(1, 2)) Is Nothing Then
            MsgBox "Double-clic sur l'en-tête de la colonne Clients pour tri"
            TriColonneD tbl
     
            ' Masquer les icônes de filtrage
            On Error Resume Next
            ActiveSheet.Unprotect
            tbl.ShowAutoFilter = False
            ActiveSheet.Protect
            On Error GoTo 0
     
            Cancel = True
            GoTo EnableEvents
        End If
     
    EnableEvents:
        ' Réactiver les événements
        Application.EnableEvents = True
        MsgBox "Fin de Worksheet_BeforeDoubleClick"
    End Sub
     
    ' Fonction pour obtenir l'état du filtrage
    Function GetFilterState(tbl As ListObject, colIndex As Integer) As String
        Dim headerCell As Range
        Set headerCell = tbl.HeaderRowRange.Cells(1, colIndex)
        If Right(headerCell.Value, 1) = " " Then
            GetFilterState = "Filtrage activé"
        Else
            GetFilterState = "Filtrage désactivé"
        End If
    End Function
     
    ' Sub pour définir l'état du filtrage
    Sub SetFilterState(tbl As ListObject, colIndex As Integer, state As String)
        Dim headerCell As Range
        Set headerCell = tbl.HeaderRowRange.Cells(1, colIndex)
     
        Application.EnableEvents = False
        If state = "Filtrage activé" Then
            headerCell.Value = Trim(headerCell.Value) & " "
            headerCell.Interior.Color = RGB(105, 105, 105) ' Gris foncé
        Else
            headerCell.Value = Trim(headerCell.Value)
            headerCell.Interior.Color = RGB(172, 185, 202) ' Couleur d'origine
        End If
        Application.EnableEvents = True
    End Sub
     
    ' Sub pour trier la colonne D et mettre à jour l'en-tête
    Sub TriColonneD(tbl As ListObject)
        Dim headerCell As Range
        Dim currentOrder As XlSortOrder
        Dim arrowColor As Long
     
        arrowColor = RGB(255, 0, 0) ' Couleur de la flèche (rouge, pour l'exemple)
     
        Set headerCell = tbl.HeaderRowRange.Cells(1, 2) ' Colonne D
     
        ' Debug messages
        MsgBox "Début du tri de la colonne D"
     
        ' Déterminer l'ordre de tri actuel
        If InStr(headerCell.Value, "▲") > 0 Then
            currentOrder = xlDescending
            headerCell.Value = "Clients ▼"
        ElseIf InStr(headerCell.Value, "▼") > 0 Then
            currentOrder = xlAscending
            headerCell.Value = "Clients ▲"
        Else
            ' Si aucun tri n'est défini, commencer par l'ordre ascendant
            currentOrder = xlAscending
            headerCell.Value = "Clients ▲"
        End If
     
        ' Debug messages
        MsgBox "Ordre de tri déterminé : " & IIf(currentOrder = xlAscending, "Ascendant", "Descendant")
     
        ' Effectuer le tri sur la colonne D
        tbl.Sort.SortFields.Clear
        tbl.Sort.SortFields.Add Key:=tbl.ListColumns(2).Range, _
                                SortOn:=xlSortOnValues, Order:=currentOrder, DataOption:=xlSortNormal
     
        With tbl.Sort
            .Header = xlYes
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With
     
        ' Debug messages
        MsgBox "Tri appliqué"
     
        ' Ajouter un espace pour indiquer que le tri est activé
        headerCell.Value = headerCell.Value & " "
        headerCell.Interior.Color = RGB(105, 105, 105) ' Gris foncé
     
        ' Colorer la flèche
        If InStr(headerCell.Value, "▲") > 0 Then
            headerCell.Characters(Start:=Len("Patients") + 10, Length:=1).Font.Color = arrowColor
        ElseIf InStr(headerCell.Value, "▼") > 0 Then
            headerCell.Characters(Start:=Len("Patients") + 10, Length:=1).Font.Color = arrowColor
        End If
     
        ' Debug messages
        MsgBox "Flèche colorée"
     
        ' Faire défiler la feuille de calcul vers le haut pour afficher les en-têtes
        ActiveWindow.ScrollRow = 1
     
        ' Debug messages
        MsgBox "Fin du tri de la colonne D"
    End Sub

  11. #11
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 936
    Points : 28 932
    Points
    28 932
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    Où apparaîtrait le nom du tableau structuré, "Rapports_finaux"? A quoi correspondraient "t_data_1" et "Ville" dans mon exemple?
    A partir du moment où nous avons une variable objet oList dans la procédure événementielle. Connaître le nom est simple, c'est la propriété Name mais ce n'était qu'un exemple puisque l'argument de la fonction IsFilteredColumn est de type ListObject on peut directement utiliser cette variable)
    Dans mon exemple t_data_1 est le nom du tableau et "Ville", l'étiquette de colonne
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  12. #12
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Merci pour les précisions... mais j'avoue que je suis un peu perdu. J'utilise assez souvent les macros événementielles, mais dans ce cas de figure, je ne sais pas comment élaborer la macro qui sera rattachée au DoubleClick, ni les macros qu'il faudrait placer dans un module standard. Je ne voudrais pas abuser de votre temps, mais si vous pouviez me mettre un peu sur la voie, cela m'aiderait beaucoup! D'autant que ce fichier me servira de modèle pour d'autres tableaux structurés, avec la même idée d'utiliser le double clic (sur un en-tête pour trier la colonne, ou sur une valeur pour n'afficher que ces valeurs dans la colonne).

    Je compte sur vous, ayant renoncé à l'IA (qui fournit beaucoup de pistes, mais c'est toujours de l'à peu près)...

  13. #13
    Rédacteur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2013
    Messages
    975
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Août 2013
    Messages : 975
    Points : 4 096
    Points
    4 096
    Par défaut
    Bonjour,
    Depuis la feuille où se trouve votre tableau structuré, clic droit sur l'onglet puis "Visualiser le code". Placez le code suivant dans l'éditeur :

    Code VBA : 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
    '------------------------------------------------------------------------------------------------------
    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    '------------------------------------------------------------------------------------------------------
    Static T(0 To 999)
    Dim Tableau As Range
    Dim Colonne As Long, Ligne As Long
     
    ' Remplacez TS_Eleves par le nom du tableau à gérer:
    Set Tableau = Range("TS_Eleves")
     
    ' Si double clic sur le tableau:
    If Tableau.ListObject.Active = True Then
     
        ' Récupérer la ligne et la colonne active:
        Ligne = ActiveCell.Row - Tableau.Row + 1
        Colonne = ActiveCell.Column - Tableau.Column + 1
     
        ' Si c'est un titre:
        If Ligne = 0 Then
     
            ' Si la colonne est triée dans l'ordre décroissant la trier en ordre croissant et inversement:
            If T(Colonne) = 0 Then
                Call TS_TrierUneColonne(Tableau, Colonne, xlSortOnValues, xlAscending)
            Else
                Call TS_TrierUneColonne(Tableau, Colonne, xlSortOnValues, xlDescending)
            End If
            ' Mémoriser l'ordre:
            T(Colonne) = 1 - T(Colonne)
     
        Else
     
            ' Si la colonne est filtrée alors effacer le filtre:
            If TS_Filtres_Existe(Tableau, Colonne) = True Then
                Call TS_Filtres_Effacer(Tableau, Colonne)
            ' Sinon poser un filtre sur la valeur active:
            Else
                If IsNumeric(Target.Value) = False Then
                    Call TS_Filtres_Poser(Tableau, Colonne, Target.Value)
                End If
                If IsNumeric(Target.Value) = True Then
                    Call TS_Filtres_Poser(Tableau, Colonne, Target.Text)
                End If
                If IsDate(Target.Value) = True Then
                    Call TS_Filtres_Poser(Tableau, Colonne, Target.Text)
                End If
            End If
     
        End If
     
        Cancel = True
     
    End If
     
    End Sub
    '------------------------------------------------------------------------------------------------------

    Y remplacez TS_Eleves par le nom de votre tableau à gérer (en ligne 9 : Set Tableau = Range("TS_Eleves")).
    Lancez la documentation : Fonctions pour gérer les Tableaux Structurés
    Chargez le fichier joint à cette documentation pour y récupérer le module TS que vous copierez dans votre projet VBA. Ce module contient le code des fonctions TS que j'utilise ici, ainsi que 80 autres qui vous seront peut-être utiles.
    Activez les références demandées.

    Bonne continuation.

  14. #14
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 936
    Points : 28 932
    Points
    28 932
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    J'utilise assez souvent les macros événementielles, mais dans ce cas de figure, je ne sais pas comment élaborer la macro qui sera rattachée au DoubleClick
    Si l'on doit intercepter un événement qui se déroule dans une feuille, on utiliserai les procédures événementielles de la feuille, si l'on souhaite intercepter un événement qui peut se produire dans plusieurs feuilles on privilégiera les événements du classeur
    Dans cet événement, je ne fais qu'une seule chose, c'est de vérifier si le double-clic a eu lieu dans la cellule d'un tableau structurer. Si c'est le cas, j'invoque une procédure qui se trouve dans un module standard, nommée ici SortFilter en lui passant comme argument Target soit la cellule où a eu lieu le double clic
    La procédure événementielle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
      Dim oList As ListObject
      Dim c As Integer
      Set oList = Target.ListObject
      If Not oList Is Nothing Then
        SortFilter Target
        Cancel = True
      End If
      Set oList = Nothing
    End Sub
    La procédure SortFilter vérifie si la cellule où a eu lieu le double clic est dans la ligne des titres (HeaderRowRange) ou dans la zone des données (DataBodyRange) ce qui permet donc de faire trier ou filtrer la colonne (variable c) où a eu lieu l'événement
    Voici je l'espère ce qui permet de vous donner des idées

    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
    Sub SortFilter(Target As Range)
      Dim oList As ListObject
      Dim c As Integer
      Set oList = Target.ListObject
      With oList
        ' calcul le numéro de colonne du tableau
        c = Target.Column - .Range.Column + 1 ' Calcul
        If Not Intersect(Target, .DataBodyRange) Is Nothing Then
           Debug.Print c & " DataBodyRange"
        End If
        ' Vérifie si Target est dans DataBodyRange
        If Not Intersect(Target, .HeaderRowRange) Is Nothing Then
           Debug.Print c & " HeaderRange"
        End If
      End With
      Set oList = Nothing
    End Sub
    Je compte sur vous, ayant renoncé à l'IA (qui fournit beaucoup de pistes, mais c'est toujours de l'à peu près)...
    L'IA est un excellent outil pour produire du code mais il faut tout de même connaître le sujet. Je l'utilise régulièrement aussi bien pour excel que pour Access

    Quelques tutoriels à lire éventuellement
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  15. #15
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Merci pour vos propositions! Je vais les tester et essayer de les adapter à mes besoins.

    Message à Philippe Tulliez: dans l'exemple proposé, mes macros de tri ou de filtrage viendraient à la ligne Debug.Print?

    J'ai oublié de préciser une chose: je n'aimerais pas que les boutons de filtre apparaissent lors de l'utilisation du fichier. Or, l'IA m'indique que l'on doit les laisser pour que le filtrage fait par Excel affiche toujours les résultats (rendre les boutons invisibles effacerait le filtrage et réafficherait toutes les lignes). Est-ce vrai? Si oui, peut-on trouver une parade (par exemple, lors du doubleclic dans mon cas, les faire apparaître, faire le filtrage, puis les cacher en fin de macro)?

  16. #16
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 936
    Points : 28 932
    Points
    28 932
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    dans l'exemple proposé, mes macros de tri ou de filtrage viendraient à la ligne Debug.Print?
    Oui, exactement. Soit les instructions soit l'invocation d'une autre procédure qui trie ou qui filtre

    Exemple
    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
    Sub SortFilter(Target As Range)
      Dim oList As ListObject
      Dim c As Integer
      Set oList = Target.ListObject
      With oList
        ' calcul le numéro de colonne du tableau
        c = Target.Column - .Range.Column + 1 ' Calcul
        If Not Intersect(Target, .DataBodyRange) Is Nothing Then
           If IsFilteredColumn(oList, c) Then
              .Range.AutoFilter Field:=c
            Else
              .Range.AutoFilter Field:=c, Criteria1:=Target.Value
           End If
        End If
        ' Vérifie si Target est dans DataBodyRange
        If Not Intersect(Target, .HeaderRowRange) Is Nothing Then
           Debug.Print c & " HeaderRange"
        End If
      End With
      Set oList = Nothing
    End Sub
    J'ai oublié de préciser une chose: je n'aimerais pas que les boutons de filtre apparaissent lors de l'utilisation du fichier. Or, l'IA m'indique que l'on doit les laisser pour que le filtrage fait par Excel affiche toujours les résultats (rendre les boutons invisibles effacerait le filtrage et réafficherait toutes les lignes).
    Non, il se trompe mais la question a t'elle été posée dans le contexte d'un tableau structuré ?

    Il est parfaitement possible de cacher ces boutons pour les tableaux structurés ainsi d'ailleurs que dans les TCD (voir illustration ci-dessous)

    Nom : 240727 dvp Filter Button.png
Affichages : 83
Taille : 16,7 Ko
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  17. #17
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Les premiers essais semblent concluants! ChatGPT m'a proposé ce qui suit pour les macros de tri et filtre:

    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
    Sub SortFilter(Target As Range)
      Dim oList As ListObject
      Dim c As Integer
      Set oList = Target.ListObject
      With oList
        ' Calcul du numéro de colonne du tableau
        c = Target.Column - .Range.Column + 1 ' Calcul
     
        ' Vérifie si Target est dans DataBodyRange
        If Not Intersect(Target, .DataBodyRange) Is Nothing Then
           ' Appeler la macro de filtrage
           FiltrerColonne oList, c, Target.Value
        End If
     
        ' Vérifie si Target est dans HeaderRowRange
        If Not Intersect(Target, .HeaderRowRange) Is Nothing Then
           ' Appeler la macro de tri
           TrierColonne oList, c
        End If
      End With
      Set oList = Nothing
    End Sub
     
    Sub TrierColonne(oList As ListObject, c As Integer)
      Dim Header As Range
      Set Header = oList.HeaderRowRange.Cells(1, c)
     
      ' Vérifier l'ordre de tri actuel et trier en conséquence
      If Right(Header.Value, 1) = " " Then
          Header.Value = Left(Header.Value, Len(Header.Value) - 1)
          oList.Sort.SortFields.Clear
          oList.Sort.SortFields.Add Key:=oList.ListColumns(c).Range, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
          Header.Interior.Color = RGB(172, 185, 202)
      Else
          Header.Value = Header.Value & " "
          oList.Sort.SortFields.Clear
          oList.Sort.SortFields.Add Key:=oList.ListColumns(c).Range, SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
          Header.Interior.Color = RGB(89, 89, 89)
      End If
      oList.Sort.Header = xlYes
      oList.Sort.Apply
     
      ' Repositionner la vue en haut
      ActiveWindow.ScrollRow = 1
    End Sub
     
    Sub FiltrerColonne(oList As ListObject, c As Integer, FilterValue As Variant)
      Dim Header As Range
      Set Header = oList.HeaderRowRange.Cells(1, c)
     
      ' Appliquer le filtre
      If Right(Header.Value, 1) = " " Then
          ' Enlever le filtre
          Header.Value = Left(Header.Value, Len(Header.Value) - 1)
          oList.Range.AutoFilter Field:=c
          Header.Interior.Color = RGB(172, 185, 202)
      Else
          ' Appliquer le filtre
          Header.Value = Header.Value & " "
          oList.Range.AutoFilter Field:=c, Criteria1:=FilterValue
          Header.Interior.Color = RGB(89, 89, 89)
      End If
     
      ' Repositionner la vue en haut
      ActiveWindow.ScrollRow = 1
    End Sub
    Cela vous semble-t-il correct?

    Je n'ai pas trouvé comment désactiver les boutons de filtrage! Je n'ai pas d'onglet correspondant à Table design (je suppose qu'il s'agit des tableaux dynamiques... que je n'utilse pas)
    Y a-t-il une autre manière de faire, par VBA, pour que cela ne réinitialise pas le filtrage?
    Oui, ma demande concerne bien un tableau structuré!

  18. #18
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 936
    Points : 28 932
    Points
    28 932
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    Si les tests sont concluants, c'est que le code est correct non ?

    Je n'ai pas trouvé comment désactiver les boutons de filtrage! Je n'ai pas d'onglet correspondant à Table design (je suppose qu'il s'agit des tableaux dynamiques... que je n'utilse pas)
    Table Design c'est l'onglet qui gère les tableaux structurés dans la version anglaise donc en français c'est l'onglet Création de tableau (tout au moins dans ma version car il peut porter un nom différent dans une autre version).

    Nom : 240727 dvp Filter Button_FR.png
Affichages : 80
Taille : 18,8 Ko
    Philippe Tulliez
    Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau)
    Lorsque vous avez la réponse à votre question, n'oubliez pas de cliquer sur et si celle-ci est pertinente pensez à voter
    Mes tutoriels : Utilisation de l'assistant « Insertion de fonction », Les filtres avancés ou élaborés dans Excel
    Mon dernier billet : Utilisation de la fonction Dir en VBA pour vérifier l'existence d'un fichier

  19. #19
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Bonjour,

    J'ai trouvé l'onglet Création de tableau (je cherchais du côté du ruban, mais il suffisait de cliquer dans le tableau structuré, pour que l'onglet apparaisse).

    Les premiers essais étaient concluants... mais pas ceux qui ont suivi.

    J'aimerais pouvoir, par double clic, trier ou filtrer des données.

    Lorsque le double clic a eu lieu dans les cellules de la ligne 7, qui correspondent aux entêtes du tableau, Excel doit toujours TRIER (si le tri en cours est de A à Z, il doit faire l'inverse (Z à A), en mentionnant, après l'entête, une flèche vers le haut; si le tri en cours est de Z à A, il doit faire l'inverse (A à Z), en mentionnant, après l'entête, une flèche vers le bas). Si je trie une autre colonne, il doit aussi effacer la flèche de la dernière colonne où j'ai fait un tri.

    Lorsque le double clic a lieu dans n'importe quelle autre cellule (dès ligne 8), Excel doit évaluer si un filtre est déjà actif DANS CETTE COLONNE (pas dans le tableau). Si c'est le cas, il doit enlever le filtre, ce qui réaffiche les valeurs. S'il n'y a pas de filtre actif, il doit filtrer. Le filtrage est simple: c'est toujours d'afficher la valeur de la cellule sur laquelle on a doublecliqué. Ensuite, pour que l'on repère quelles colonnes ont un filtre actif, Excel met la cellule d'entête, en ligne 7, dans une couleur plus foncée. Lorsqu'il enlève le filtrage, la cellule retrouve sa couleur originale. Je précise que le filtre ne s'applique que sur les cellules visibles, jamais sur celles qui sont cachées. De même lorsqu'un filtre est actif et qu'un doubleclic l'annule, il n'annule que le filtre de cette colonne-là, sans modifier les autres.

    Une macro, active à l'ouverture du fichier et disponible via un bouton, permet en un clic de réafficher toutes les données du tableau et de trier selon une colonne (la 2 en l'occurrence).

    Pourriez-vous me guider dans l'élaboration de ces deux macros, une qui trie, l'autre qui filtre? Si vous souhaitez, je peux joindre celles que m'a proposées Chat GPT.

    Merci!

  20. #20
    Nouveau membre du Club
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Janvier 2020
    Messages
    106
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2020
    Messages : 106
    Points : 36
    Points
    36
    Par défaut
    Pour mettre en avant les limitations de l'IA:

    - Pour le tri, il n'arrivait pas bien à déterminer si le tri dans la colonne était ascendant ou descendant. Je lui ai donc demandé de toujours commencer par un tri de A à Z, avec flèche vers le bas, puis de faire le contraire en cas de nouveau doubleclic

    - Pour le filtrage, il n'a jamais bien réussi à évaluer si un filtre était actif, non dans le tableau, mais DANS LA COLONNE! Je lui ai donc suggéré, lorsqu'il n'y avait pas de filtre, de laisser le nom de l'entête tel quel (par exemple "Client"). Par contre, lorsqu'un filtre était actif, d'ajouter un espace après le nom ("Client "). De cette manière, en cas de doubleclic, devait regarder l'entête: si la dernière lettre se terminait par un espace, il devait enlever le filtre, dans le cas contraire l'appliquer. Principe de base assez simple, mais qui a marché... une fois sur deux...

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [XL-365] Tri de colonne dans des tableaux structurés
    Par Kaytilou dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 06/04/2021, 18h35
  2. VBA EXCEL tableaux structurés
    Par steph7609123 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 01/02/2021, 19h46
  3. Réponses: 12
    Dernier message: 18/01/2020, 08h07
  4. [XL-2003] Problème avec tableaux Variant et X.rows.count sous VBA
    Par Anthony75 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 30/12/2009, 17h45
  5. [Tableaux] Tri d'un tableau avec des accents
    Par legide dans le forum Langage
    Réponses: 3
    Dernier message: 09/07/2009, 11h36

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