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. #21
    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,
    Pour le filtrage, il n'a jamais bien réussi à évaluer si un filtre était actif, non dans le tableau, mais DANS LA COLONNE!
    J'ai pourtant publié le code qui permet de savoir si une colonne, d'un tableau structuré, est filtrée ou pas
    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

  2. #22
    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,
    Il me semblait avoir répondu à votre demande avec le code fourni au message numéro 13, et indiqué la procédure à suivre.
    Suis je passé à côté de quelque chose ?

  3. #23
    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 réponses!

    laurent_ott: non vous n'êtes pas passé à côté de quelque chose! C'est simplement que mes compétences ne sont pas à la hauteur des vôtres.
    J'ai incorporé les fonctions appelées dans la macro, indiqué le nom de mon tableau structuré, mais j'ai "une erreur de syntaxe" dans la macro Public Function TS_TrierUneColonne, à la ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    'Pose le tri sur la colonne
    TS.ListObject.Sort.SortFields.Add etc
    Du coup, je n'ai pas su comment continuer, surtout que, pour mon niveau, vos macros sont déjà complexes!


    Philippe Tulliez: c'est bien la macro que vous m'avez suggérée que j'ai utilisée:
    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
    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
    ...mais je n'ai pas su comment insérer le code permettant de savoir si une colonne est filtrée ou triée. Du coup, j'ai passé par l'IA, qui s'est assez vite égarée...

    Si je reviens à vos propositions, celle qui suit est bien à placer dans un module standard?
    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
    Mais comment l'insérer dans la macro FiltrerColonne oList?

    Mes questions vous paraîtront sans doute basiques, mais pour moi, elles ne sont pas si simples...

    Merci de votre aide!

  4. #24
    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'ai réussi à implémenter, en fonction de la structure que vous m'avez donnée, les macros de tri et de filtrage. Surtout, qui fonctionnent correctement... Cela n'a pas été si facile que ça, en fonction de mon degré de connaissances. Mais cela a fonctionné, avec l'aide (approximative) de Chat GPT. Merci pour votre aide!

  5. #25
    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'ai réussi à implémenter, en fonction de la structure que vous m'avez donnée, les macros de tri et de filtrage. Surtout, qui fonctionnent correctement... Cela n'a pas été si facile que ça, en fonction de mon degré de connaissances. Mais cela a fonctionné, avec l'aide (approximative) de Chat GPT. Merci pour votre aide!
    Ravi d'apprendre que cela fonctionne
    Comme j'étais en train de rédiger ma réponse, je la publie tout de même.

    La procédure événementielle Workbook_SheetBeforeDoubleClick vérifie si un double-clic a lieu dans un tableau structuré du classeur. Si c'est le cas, elle invoque la procédure SortFilter (présente dans un module Standard).

    La procédure SortFilter détermine si le double-clic a eu lieu dans la zone des titres ou dans celle des données du tableau :
    Si l'événement a eu lieu dans la zone des données (DataBodyRange), elle filtre sur la valeur de la cellule où le double-clic a été effectué, ou supprime le filtre si la colonne était déjà filtrée.
    Si l'événement a eu lieu dans la zone des titres, elle invoque la procédure SortTable en effectuant un tri croissant si la colonne n'était pas triée, ou si la colonne était triée par ordre décroissant.

    Comment savoir si une colonne est filtrée ?
    En invoquant la fonction IsFilteredColumn.

    Comment savoir si une colonne est triée par ordre croissant ou décroissant ?
    Lorsque l'on trie une ou plusieurs colonnes, le tri reste en mémoire. Il suffit donc de vérifier quelques propriétés du premier niveau de tri.

    Comment savoir si le double-clic a eu lieu dans la zone des titres ou des données ?
    En invoquant soit la fonction IsHeaderRowRange, soit la fonction IsDataBodyRange.

    En pièce jointe, un classeur de test avec deux feuilles contenant chacune un tableau structuré. N'ayant pas plus de temps à consacrer à ce sujet, le filtre ne fonctionne pas avec les dates.

    Code des procédures utilisées

    Procédure événementielle Workbook_SheetBeforeDoubleClick
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Private Sub Workbook_SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
      Dim oList As ListObject
      Set oList = Target.ListObject
      ' Si le DoubleClick à lieu dans un tableau structuré on invoque SortFilter
      If Not oList Is Nothing Then SortFilter Target: Cancel = True
      Set oList = Nothing
    End Sub
    La procédure SortFilter
    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
    Sub SortFilter(Target As Range)
      ' Trie ou filtre la colonne d'un tableau structuré suivant un contexte
      '  Trie la colonne de Target si celui-ci se trouve dans Row
      ' Argument
      '   Target   Cellule où a eu lieu le DoubleClick
      ' Déclaration des variables
      Dim oList As ListObject
      Dim c As Integer
      Set oList = Target.ListObject
      With oList
        ' Calcule le numéro de colonne du tableau
        c = Target.Column - .Range.Column + 1
        ' Vérifie si Target est dans HeaderRowRange
        If IsDataBodyRange(Target) Then
         ' Si Target est dans DataBodyRange on filtre ou on supprime le filtre
         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 IsHeaderRowRange(Target) Then
           SortTable oList, IIf(GetSortOrder(oList, c) = 1, "-", "") & .ListColumns(c)
        End If
      End With
      Set oList = Nothing
    End Sub
    La procédure SortTable
    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
    Function SortTable(oList As ListObject, _
                       Optional LabelList As String, _
                       Optional CustomList As String, _
                       Optional CaseSensitive As Boolean)
      ' Fonction de tri pour ListObject
      ' Trie Ascendant/Descendant de colonne(s) d'un tableau structuré
      ' Author  : Philippe Tulliez (www.magicoffice.be)
      ' Date    : 05/07/2021
      ' Version : 3.1
      ' Arguments
      '   oList           (ListObject)
      '   [LabelList]     (String)     (Nom des étiquettes de colonne à trier séparé par ; (Exemple Voiture;Logement)
      '                                 Si l'étiquette est précédée par un signe négatif, le tri est descendat
      '                                   Exemple ("Service;-Logement;-Voiture")
      '                                   signifie que la colonne "Service" sera triée par ordre croissant, les deux autres par ordre décroisant
      '   [CustomList]    String
      '   [CaseSensitive] Boolean
      ' Déclaration & Affectation
      Dim Sc As Range   ' Colonne à trier
      Dim So As Byte    ' Ordre de tri
      Dim Sl As Variant ' Liste des champs à trier
      Dim El As Integer ' Variable de boucle
      ' Liste des champs à trier suivant argument [LabelList] (Si vide l'Array prend l'étiquette de la première colonne)
      Sl = IIf(Len(LabelList), Split(LabelList, ";"), Array(oList.ListColumns(1).Name))
      '
      With oList
      .Sort.SortFields.Clear
       ' Insert level sort
       For El = LBound(Sl) To UBound(Sl)
        So = 1 + Abs(Left(Sl(El), 1) = "-"): Set Sc = .ListColumns(Mid(Sl(El), So)).DataBodyRange
       .Sort.SortFields.Add Key:=Sc, SortOn:=xlSortOnValues, Order:=So
       Next
       ' Sort
       With .Sort: .MatchCase = CaseSensitive: .Apply: End With
      End With
      Set Sc = Nothing
    End Function
    Code des fonctions booléennes IsHeaderRowRange, IsDataBodyRange et IsFilteredColumn

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Function IsHeaderRowRange(oRange As Range) As Boolean
      ' Renvoie True si oRange est dans HeaderRowRange
      Dim oList As ListObject
      Set oList = oRange.ListObject
      If Not oList Is Nothing Then
         IsHeaderRowRange = Not Intersect(oRange, oList.HeaderRowRange) Is Nothing
         Set oList = Nothing
      End If
    End Function
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Function IsDataBodyRange(oRange As Range) As Boolean
      ' Renvoie True si oRange est dans DataBodyRange
      Dim oList As ListObject
      Set oList = oRange.ListObject
      If Not oList Is Nothing Then
         IsDataBodyRange = Not Intersect(oRange, oList.DataBodyRange) Is Nothing
         Set oList = Nothing
      End If
    End Function
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function IsFilteredColumn(oList As ListObject, Column As Variant) As Boolean
     ' Renvoie True si la colonn est filtrée
     ' Arguments
     '   oList    Tableau structuré
     '   Column   N° ou nom de la colonne
     '
      With oList
       If VarType(Column) = vbString Then Column = .ListColumns(Column).Index
       IsFilteredColumn = .AutoFilter.Filters.Item(Column).On
      End With
    End Function
    La procédure GetSortOrder
    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
    Function GetSortOrder(oList As ListObject, colIndex As Integer) As Integer
      ' Renvoie
      '  0 si la colonne n'est pas triée
      '  1 si la colonne est triée par ordre croissant
      '  2 si la colonne est triée par ordre décroissant
      With oList.Sort
       If .SortFields.Count > 0 Then
        With .SortFields(1)
          If (.Key.Column - oList.Range.Column + 1 = colIndex) And .SortOn = xlSortOnValues Then
             GetSortOrder = .Order
          End If
        End With
       End If
      End With
    End Function
    Fichiers attachés Fichiers attachés
    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

  6. #26
    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 toutes ces précisions, qui m'auront été très utiles!

    J'ai deux questions encore sur les tableaux structurés:

    1) Comment, dans une macro comme celle que j'ai utilisée pour le DoubleClick (voir ci-dessous), peut-on ignorer certaines colonnes (pour le filtre, pour le tri, voire pour les deux? Comment indiquer à Excel, dans ce cas, qu'il ne doit rien faire en cas de double clic dans ces colonnes-là?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        Application.ScreenUpdating = False
        Application.EnableEvents = False
     
        ' Vérifier si la cellule double-cliquée fait partie du tableau structuré "Rapports_finaux"
        If Not Intersect(Target, ActiveSheet.ListObjects("Rapports_finaux").Range) Is Nothing Then
            ' Appeler la macro pour trier ou filtrer en fonction de la cellule double-cliquée
            SortFilter Target
            ' Annuler l'événement de double-clic par défaut
            Cancel = True
        End If
     
        Application.EnableEvents = True
    End Sub
    2) Peut-on laisser, dans un tableau structuré, certaines colonnes vides (sans valeurs, verrouillées, juste pour séparer visuellement certaines colonnes)?

  7. #27
    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,
    1) Comment, dans une macro comme celle que j'ai utilisée pour le DoubleClick (voir ci-dessous), peut-on ignorer certaines colonnes (pour le filtre, pour le tri, voire pour les deux? Comment indiquer à Excel, dans ce cas, qu'il ne doit rien faire en cas de double clic dans ces colonnes-là?
    En utilisant une structure décisionnelle comme If...End If ou un Select...Case. Voir l'exemple

    2) Peut-on laisser, dans un tableau structuré, certaines colonnes vides (sans valeurs, verrouillées, juste pour séparer visuellement certaines colonnes)?
    Un tableau structuré doit avoir un titre à chaque colonne.

    Attention que la protection de la feuille bloque la propagation des lignes d'un tableau structuré

    Dans l'exemple ci-dessous, on ne traite pas les colonnes "DATE FACTURE", "DATE D'ECHEANCE" et "Réalisé" mais attention que si l'on doit traiter plusieurs tableaux, il faudra éventuellement inclure le nom de la table.
    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
    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
      ' Si le DoubleClick à lieu dans un tableau structuré on invoque SortFilter
      If Not oList Is Nothing Then
         With oList
           c = Target.Column - .Range.Column + 1
           Select Case LCase(.ListColumns(c))
             Case "date facture", "date d'echeance", "réalisé"
             Case Else
               SortFilter Target: Cancel = True
           End Select
         End With
      End If
      Set oList = Nothing
    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

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

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