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 :

Problème Tri ListView


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Avril 2008
    Messages
    136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 136
    Par défaut Problème Tri ListView
    Bonjour.

    Je reviens vers vous avec une question concernant le listView sur Excel.

    Apparemment, toutes les données dans un listview seraient considérées comme du texte, même les valeurs numériques. Donc cela complique la tache pour faire des tries sur la listView.

    Une des solutions que j'ai trouvé, est de rajouter une colonne "width = 0". Dans celle-ci, je convertie chaque chiffre d'un nombre par une lettre avec un "Select Case". Ensuite, je rajoute le code de tri sur la bonne colonne.

    Dans l'exemple ci-dessous.
    Colonne 1 = texte
    Colonne 2 = un nombre
    Colonne 3 = Colonne 2 convertie en lettre (Width de la colonne = 0)

    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
    Lacol = ColumnHeader.Index - 1
        If Lacol = 2  Then 
            Lacol = 3
        end if
     
        UserForm6.ListView1.Sorted = False
     
        UserForm6.ListView1.SortKey = Lacol
     
        If UserForm6.ListView1.SortOrder = lvwAscending Then
            UserForm6.ListView1.SortOrder = lvwDescending
        Else
            UserForm6.ListView1.SortOrder = lvwAscending
        End If
     
        UserForm6.ListView1.Sorted = True
    Cela fonctionne parfaitement. Seulement, lorsque la listview fait 10 colonnes et que mes colonnes numériques sont par exemple, colonne 2,4,5,8,9 ...... Cela commence à faire un peu beaucoup de colonnes supplémentaires à rajouter.

    Connaissez-vous une autre solution pour trier le listview ?

  2. #2
    Membre Expert
    Inscrit en
    Décembre 2002
    Messages
    993
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 993
    Par défaut
    Bonjour, une possibilité serait d'utiliser un tableau à deux dimensions pour stocker les données, trier le tableau en fonction des valeurs numériques et mettre à jour le contrôle ListView avec les données triées. Par 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    ' Créer un tableau à deux dimensions pour stocker les données
    Dim donnees(1 To 10, 1 To 3) As Variant ' 10 lignes et 3 colonnes
     
    ' Remplir le tableau avec des données
    donnees(1, 1) = "A"
    donnees(1, 2) = 10
    donnees(1, 3) = "J"
    donnees(2, 1) = "B"
    donnees(2, 2) = 5
    donnees(2, 3) = "E"
    ' ...
     
    ' Trier le tableau en fonction des valeurs numériques dans la deuxième colonne
    Dim i As Long
    Dim j As Long
    For i = 1 To UBound(donnees, 1) - 1
        For j = i + 1 To UBound(donnees, 1)
            If donnees(i, 2) > donnees(j, 2) Then
                ' Échanger les lignes i et j
                Dim temp(1 To UBound(donnees, 2)) As Variant
                temp = donnees(i)
                donnees(i) = donnees(j)
                donnees(j) = temp
            End If
        Next j
    Next i
     
    ' Mettre à jour le contrôle ListView avec les données triées
    UserForm6.ListView1.ListItems.Clear
    For i = 1 To UBound(donnees, 1)
        Dim item As ListItem
        Set item = UserForm6.ListView1.ListItems.Add(, , donnees(i, 1))
        item.SubItems(1) = donnees(i, 2)
        item.SubItems(2) = donnees(i, 3)
    Next i
    Cette approche peut être plus efficace si vous avez beaucoup de données à trier, car elle évite de manipuler le contrôle ListView à chaque itération de la boucle de tri.

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

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 244
    Par défaut
    Hello,
    c'est quelque chose comme ceci que tu veux ? :
    Nom : TriListView.gif
Affichages : 351
Taille : 199,5 Ko

    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
    Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
    With ListView1
        .SortKey = ColumnHeader.Index - 1
        If .SortOrder = lvwAscending Then
            .SortOrder = lvwDescending
        Else
            .SortOrder = lvwAscending
        End If
        If ColumnHeader.Index = 4 Then
                SortDataWithNumbers
            Else
                .Sorted = True
            End If
    End With
    End Sub
     
     
    Sub SortDataWithNumbers()
        Dim sTemp As String * 10
        Dim lvCount As Long
        Dim i As Integer
     
        With ListView1
            lvCount = .ListItems.Count
     
            For i = 1 To lvCount
                sTemp = vbNullString
     
                If .SortKey Then
                    'RSet - right align a string within a string variable.
                    RSet sTemp = .ListItems(i).SubItems(.SortKey)
                    .ListItems(i).SubItems(.SortKey) = sTemp
                Else
                    RSet sTemp = .ListItems(i)
                    .ListItems(i).Text = sTemp
                End If
            Next
     
            .Sorted = True
     
            For i = 1 To lvCount
                If .SortKey Then
                    .ListItems(i).SubItems(.SortKey) = _
                    LTrim$(.ListItems(i).SubItems(.SortKey))
                Else
                    .ListItems(i).Text = LTrim$(.ListItems(i))
                End If
            Next
        End With
    End Sub



    Ami calmant, J.P

  4. #4
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Avril 2008
    Messages
    136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 136
    Par défaut
    Franc, ta solution fonctionne mais sur un tableau à 2 colonnes, la il y aurait une dizaine de colonne, dont plusieurs ayant des chiffres. Sa fait une variable list à X items et 10 colonnes. Un peu lourd peu être.

    Jurassic pork, Ce que tu fais c'est de multiplier par 10 la valeur "Dim sTemp As String * 10". Je ne connais pas l'instruction "RSet" ????
    Par contre, cela fonctionne t-il avec des valeurs comme "10,6 ; 8,5 ; 14,2" à virgule. Et j'imagine que l'idée c'est de multiplier les valeurs par le type de valeur la plus grande. Si la valeur la plus grande est < 100. On multiplie par 10, si c'est < 1000 on multiplie par 100, etc etc....

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

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 244
    Par défaut
    Hello,
    Citation Envoyé par kitcarflo Voir le message
    Par contre, cela fonctionne t-il avec des valeurs comme "10,6 ; 8,5 ; 14,2" à virgule. Et j'imagine que l'idée c'est de multiplier les valeurs par le type de valeur la plus grande. Si la valeur la plus grande est < 100. On multiplie par 10, si c'est < 1000 on multiplie par 100, etc etc....
    Non cela ne fonctionne pas car l'idée c'était de créer des chaines de 10 caractères (* 10) d'aligner à droite en chaine et d'utiliser le tri texte puis de revenir à gauche.
    Par contre avec le listview de l'activeX VbCcr17 le tri numérique est possible .
    This project is intended to replace the MS common controls for VB6.

    The "MSCOMCTL.OCX" (respectively "COMCTL32.OCX") can be replaced completly.
    The "MSCOMCT2.OCX" (respectively "COMCT232.OCX") can be replaced completly.
    The "RICHTX32.OCX" can be replaced completly.
    The "COMDLG32.OCX" can be replaced completly.
    The "COMCT332.OCX" can be replaced completly.
    The "MCIWNDX.OCX" (shipped with VB5) can be replaced completly.
    The "SYSINFO.OCX" can be replaced completly.
    Unicode is supported for all the stated controls. Also these are full DPI-Aware.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     Private Sub ListView2_ColumnClick(ByVal ColumnHeader As VBCCR17.LvwColumnHeader)With ListView2
        .SortKey = ColumnHeader.Index - 1
        If .SortOrder = lvwAscending Then
            .SortOrder = lvwDescending
        Else
            .SortOrder = lvwAscending
        End If
        If .SortKey = 3 Then .SortType = LvwSortTypeNumeric Else .SortType = LvwSortTypeText
         .Sorted = True
    End With
    End Sub
    Nom : ListeviewTri.gif
Affichages : 327
Taille : 189,1 Ko

    Ami calmant, J.P

  6. #6
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 244
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 244
    Par défaut
    Hello,
    en ce qui concerne le ListView de Microsoft, on peut modifier la routine SortDataWithNumbers() pour que cela fonctionne avec des nombres à virgule . Il suffit d'utiliser une chaine fixe de longueur suffisante (nombre max de digits utilisés dans les valeurs) , de travailler temporairement en double en les multipliant par un coefficient proportionnel au nombre max de chiffres utilisés après la virgule (ex : pour 5 -> 100000). et de revenir en divisant par le coefficient et en remettant la valeur en chaine :
    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
     Sub SortDataWithNumbers() 
        Const maxDigits As Integer = 20
        Const CoeffDec As Long = 10 ^ 5
        Dim sTemp As String * maxDigits
        Dim lvCount As Long, i As Integer    
        With ListView1
            lvCount = .ListItems.Count      
            For i = 1 To lvCount
                sTemp = vbNullString          
                If .SortKey Then
                    'RSet - right align a string within a string variable.
                    RSet sTemp = CStr(CDbl(.ListItems(i).SubItems(.SortKey) * CoeffDec))
                    .ListItems(i).SubItems(.SortKey) = sTemp
                Else
                    RSet sTemp = .ListItems(i)
                    .ListItems(i).Text = sTemp
                End If
            Next        
            .Sorted = True       
            For i = 1 To lvCount
                If .SortKey Then
                    .ListItems(i).SubItems(.SortKey) = _
                    LTrim$(CStr(CDbl(.ListItems(i).SubItems(.SortKey) / CoeffDec)))
                Else
                    .ListItems(i).Text = LTrim$(.ListItems(i))
                End If
            Next
        End With
    End Sub
    Nom : ListeviewAlignCol.gif
Affichages : 293
Taille : 126,6 Ko

    Ami calmant, J.P

Discussions similaires

  1. [Tableaux] Problème tri de tableau à deux dimensions
    Par squall62 dans le forum Langage
    Réponses: 21
    Dernier message: 24/05/2006, 18h18
  2. Problème tri tutoriel selection multiple
    Par qbihlmaier dans le forum Access
    Réponses: 24
    Dernier message: 14/03/2006, 11h24
  3. [PERL] problème tri de tableau
    Par LE NEINDRE dans le forum Langage
    Réponses: 2
    Dernier message: 31/08/2005, 15h42
  4. Problême tri par ardre croissant
    Par vince86000 dans le forum ASP
    Réponses: 2
    Dernier message: 28/04/2005, 13h10
  5. [C#] Problème avec ListView
    Par yannick dans le forum Windows Forms
    Réponses: 4
    Dernier message: 03/06/2004, 17h29

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