XL 2010 Trier une Variable Tableau en VBA

Nicodemius

XLDnaute Nouveau
Bonjour,
Je tente désespérément de créer une fonction pour Trier une variable Tableau.
Pour le moment elle fonctionne mais seulement en ordre croissant.
J'utilise le module de classe [Sorted List] de Jacques BOISGONTIER que j'ai trouvé sur un fil :
Fonction de tri d'une variable tableau en VBA (Sparrow, Décembre 2013)

Vu que le sujet date un peu, j'ai préféré créer une nouvelle discussion.

Si quelqu'un a une idée, surtout qu'il n'hésite pas. :rolleyes:

Bonne soirée à tous.
 

Pièces jointes

  • Public Function TrierCol.txt
    889 bytes · Affichages: 28
Solution
Classe Tris réduite


VB:
Sub TriCroissant()
   Tbl = [a3:D8].Value
   Set montab = New Tris       ' instanciation de la classe Tris
   montab.Tri Tbl, 2               ' tri col 2
   [a3:D8].Value2 = Tbl
End Sub

Sub TriDéCroissant()
   Tbl = [a3:D8].Value
   Set montab = New Tris        ' instanciation de la classe Tris
   montab.TriInv Tbl, 2            ' tri col 2
   [a3:D8].Value2 = Tbl
End Sub


Boisgontier

Staple1600

XLDnaute Barbatruc
Bonjour Dranreb

Merci pour tes précisions.

Mon message#116 signalait juste "l'erreur*" de terminologie de Nicodemius dans son premier message.
(Et ce n'est qu'aujourd'hui que j'ai cliqué sur son lien dans le message#1)

*: ou plutôt confusion.

PS: Que penses-tu de l'emploi de System.Collections.ArrayList dans le cas présent ?
 

Dranreb

XLDnaute Barbatruc
Jamais utilisé ça. Ça semble plus fait pour être utilisé en C. J'envisagerai peut être d'étudier ses possibilités s'il existe une référence VBA permettant d'éviter les liaisons tartives que j'ai vraiment en sainte horreur.
 

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Bonjour,

Module de classe Dictionnaire permettant de faire des tris multi-critères.


VB:
Sub TriTableau2DVilleInv()
Set d1 = New Dictionnaire
a = [A2:E9].Value
Dim b(), c()
ReDim c(LBound(a) To UBound(a), LBound(a, 2) To UBound(a, 2))
For i = LBound(a) To UBound(a)
   d1.ajout a(i, 4) & a(i, 1) & i, i
Next i
b = d1.TriInv             ' tri objet d1
For lig = LBound(a) To UBound(a)
  For col = LBound(a, 2) To UBound(a, 2)
    c(lig, col) = a(b(lig, 2), col)
  Next col
Next lig
[H2].Resize(UBound(c), UBound(c, 2)).Value2 = c
End Sub

Boisgontier
 

Pièces jointes

  • ClasseDictionnaireDico.zip
    326.3 KB · Affichages: 12

Nicodemius

XLDnaute Nouveau
Bonjour à tous

Bonjour laurent950

Oui, en effet. Tu as parfaitement raison. J'aurais dû préciser à l'ouverture du sujet que la variable tableau était multidimensionnelle. Vraiment désolé.


Enfin ce que je comprend :
* Dans un module standard vous avez créer une variable tableau 2 dimensions (Lignes / Colonnes)
* Vous avez besoin de faire un tri sur ce même tableau
* Tri Croissant OU Tri Décroissant (Aux choix)


Bravo. Tu as parfaitement cerné mes attentes.
Je n'ai commencé à travailler sur Excel que depuis une semaine. J'ai quelques notions de VB et je souhaitais juste me familiariser à l'environnement Excel que je suis très loin de maitriser.
J'ai découvert il y a peu les variables Tableau et j'avais dans l'idée d'approfondir le sujet par le biais d'un petit exercice me permettant de trier les données contenues dans ma variable.
Après avoir longuement parcouru les forums en quêtes de réponse à ma question, je suis tombé sur le fil que je vous ai donné dans mon premier Post.

* La vrai Question Pourquoi passé par un Module de Classe

J'ai été séduit par le travail de Mr BOISGONTIER qui répondait à toutes mes attentes tout en restant à ma portée. Après quelques tests, j'ai pu intégrer son exemple de code avec succès et parvenir à mes fins. (Il utilise notamment dans son exemple un module de classe qu'il a lui même réalisé et que je réutilise tel quel.)

* je connais parfaitement toutes les combinaisons, mais vous qu'elle est votre idée
* Pouvez vous écrire simplement les actions a faire.

Partant de là, Je me suis inspiré de son code pour créer une fonction pour trier une variable tableau à partir d'une variable tableau. J'ai testé cette fonction et elle fonctionne parfaitement.
Cependant, ma fonction à quelques limites que j'aimerais contourner sans savoir comment.
Je voudrais notamment intégrer un paramètre pour l'ordre de tri, voire même rajouter un second argument NumCol2 afin de trier sur une deuxième colonne comme il le fait dans son exemple.


@Dranreb
Merci pour ton travail. Mais son efficacité n'a d'égal que sa complexité.
En clair, le jeune Padawan que je suis n'arrive pas à la cheville du Maître Jedi que tu es.
Je cherche à progresser à mon rythme et je tiens à rester maître du code que j'intègre dans mon projet VBA. Nul doute qu'il me faudrait plusieurs décennie pour parvenir au résultat que tu me propose. Malheureusement je n'en suis pas encore là.


Pour terminer, je suis vraiment heureux de constater que le niveau d'entre aide sur ce forum dépasse largement toutes mes attentes. En cette période difficile où le premier ordre est de rester chez soi à l'abri de tout, je dois reconnaître que, face à mes petits problème sur Excel, je me sens moins seul.

Merci à tous.
 

Nicodemius

XLDnaute Nouveau
@BOISGONTIER
Merci Mr BOISGONTIER pour votre réponse.
J'avais déjà pris connaissance de ce bout de code.
Pourriez vous me dire si il existe une méthode pour passer d'un tri croissant à un tri décroissant ?

@Staple1600
Non !?! Tu es sérieux ?
Inutile de s'excuser pour si peu.
Après tout, c'est moi qui ai fait l'erreur d'omettre des éléments clés dans mon premier Post.
J'ai manqué de discernement. :confused:
Merci encore pour ton aide. J'apprécie énormément.
Au plaisir de te lire.
 

laurent950

XLDnaute Accro
Donc :
J'ai une variable tableau dans le module standard !
* Je choisie de faire un tri sur une colonne définit
* Aux Choix Croissant Ou Décroissant
* En Bonus je conserve aussi la structure de la variable tableau initial
Je vous poste le code

* Le module Standard : ModuleStandard
VB:
' Appelle du Module de classe en public
Public SL As New SListe
Sub test()
' Mise en mémoire d'un tableau 2 dimensions
Dim Tableau() As Variant
    Tableau = Range(Cells(1, 1), Cells(17, 3))
' Fonction Tri du tableau / Le tableau et la colonne 2
' Choix Croissant = Crois OU Decroissant = DeCrois
    Tableau = TrierCol(Tableau, 1, "DeCrois")
' Test Cellule(1,1)
    MsgBox Tableau(1, 1)
' Fin !
' *************************************************************************************************************
' NOTA : BONUS
' Donc je parler jutement de se qui était consigné dans la classe voila l'ancien tableau
' dans l'ordre d'origine !
    Dim TableauOrigine() As Variant
        TableauOrigine = SL.RecupTabOrigine
' Test Cellule(1,1)
    MsgBox TableauOrigine(1, 1)
' Fin !
End Sub
' **************************************************************************************************
Public Function TrierCol(ByRef Tableau() As Variant, ByVal NumCol1 As Integer, ByVal Ordre As String) As Variant()
' Ont injecte "Dans le Module de Classe" le Tableau dans le module de classe avec le numéro de colonne a trié !
    SL.ajout(Tableau) = NumCol1
' **********************************************************************************************
' AUX CHOIX POUR L'ORDRE DE TRI CROISSANT OU DECROISSANT CI-DESSOUS !
' -------------------------------------------------------------------
If Ordre = "Crois" Then
' tri Croissant (Ordre = Crois) sur la Colonne (2 = NumCol1) du tableau
   TabCible = SL.triCroissant ' Tri du tableau Croissant (dans le module de classe)
Else
' tri DeCroissant (Ordre = DeCrois) sur la Colonne (2 = NumCol1) du tableau
   TabCible = SL.triDeCroissant ' Tri du tableau Croissant (dans le module de classe)
End If
' **********************************************************************************************
' retourner le "tableau résultat"
   TrierCol = TabCible
End Function

Le Module de Classe : SListe
VB:
Private cls_TabOrigine() As Variant ' Ici je conserve la structure du tableau d'origine
' Element de travail ci-dessous !
    Private cls_Tabtemp() As Variant  ' Ici j'effectu les modification de structure du tableau de tri
    Private cls_NumCol1 As Integer    ' Avec le numéro de colonne a trié !
Property Let ajout(ByRef Tableau() As Variant, ByVal NumCol1 As Integer)
    cls_Tabtemp = Tableau ' Le tableau 2 dimension dans le module de classe
    cls_NumCol1 = NumCol1 ' Le choix de la colonne de tri
' Option Je conserve la structure d'origine du tableau initial non modifié !
    cls_TabOrigine = Tableau
End Property
Property Get RecupTabOrigine() As Variant()
    RecupTabOrigine = cls_TabOrigine
End Property
Property Get triCroissant() As Variant()
' Tri la variable tableau
    Croissant cls_Tabtemp, cls_NumCol1, LBound(cls_Tabtemp, 1), UBound(cls_Tabtemp, 1)
' Renvois le Resultat dans le Module Standard
    triCroissant = cls_Tabtemp
End Property
Property Get triDeCroissant()
' Tri la variable tableau
    DeCroissant cls_Tabtemp, cls_NumCol1, LBound(cls_Tabtemp, 1), UBound(cls_Tabtemp, 1)
' Renvois le Resultat dans le Module Standard
    triDeCroissant = cls_Tabtemp
End Property
Private Sub Croissant(a() As Variant, colTri, gauc, droi)
' Tri "Croissant" d'un tableau (Array) à 2 dimensions
  ref = a((gauc + droi) \ 2, colTri)
  g = gauc: d = droi
  Do
' Pour un tri Croissant
    Do While a(g, colTri) < ref: g = g + 1: Loop
    Do While ref < a(d, colTri): d = d - 1: Loop
        If g <= d Then
           For k = LBound(a, 2) To UBound(a, 2)
             temp = a(g, k): a(g, k) = a(d, k): a(d, k) = temp
           Next k
           g = g + 1: d = d - 1
        End If
  Loop While g <= d
  If g < droi Then Call Croissant(a, colTri, g, droi)
  If gauc < d Then Call Croissant(a, colTri, gauc, d)
End Sub
Private Sub DeCroissant(a() As Variant, colTri, gauc, droi)
' Tri "DéCroissant" d'un tableau (Array) à 2 dimensions
  ref = a((gauc + droi) \ 2, colTri)
  g = gauc: d = droi
  Do
' Pour un tri DéCroissant
    Do While a(g, colTri) > ref: g = g + 1: Loop
    Do While ref > a(d, colTri): d = d - 1: Loop
        If g <= d Then
           For k = LBound(a, 2) To UBound(a, 2)
             temp = a(g, k): a(g, k) = a(d, k): a(d, k) = temp
           Next k
           g = g + 1: d = d - 1
        End If
  Loop While g <= d
  If g < droi Then Call DeCroissant(a, colTri, g, droi)
  If gauc < d Then Call DeCroissant(a, colTri, gauc, d)
End Sub

Pour info :

Conformément à :
J'utilise le module de classe [Sorted List] de Jacques BOISGONTIER que j'ai trouvé sur un fil :
 
Dernière édition:

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Classe Tris réduite


VB:
Sub TriCroissant()
   Tbl = [a3:D8].Value
   Set montab = New Tris       ' instanciation de la classe Tris
   montab.Tri Tbl, 2               ' tri col 2
   [a3:D8].Value2 = Tbl
End Sub

Sub TriDéCroissant()
   Tbl = [a3:D8].Value
   Set montab = New Tris        ' instanciation de la classe Tris
   montab.TriInv Tbl, 2            ' tri col 2
   [a3:D8].Value2 = Tbl
End Sub


Boisgontier
 

Pièces jointes

  • ClasseTris.xls
    80.5 KB · Affichages: 26

laurent950

XLDnaute Accro
J'ai ajouté l'astuce
car toute la puissance du module de classe est la suivante !
Il n'y a pas besoin de la fonction je poste ! ici attendez un peux

Donc :
J'ai une variable tableau dans le module standard !
* Je choisie de faire un tri sur une colonne définit
* Aux Choix Croissant Ou Décroissant
* En Bonus je conserve aussi la structure de la variable tableau initial
Je vous poste le code
depuis le module standard (je me sert du module de classe pour effectuer mes actions)
* Cas d'école (je garde le tableau original que je stock dans mon module de classe)
Private cls_TabOrigine() As Variant
* puis je stock le même tableau dans une autres variable de mon module de classe
Private cls_Tabtemp() As Variant
Nota c'est deux tableaux identique sauf qu'il n'ont pas la même adresse dans le Tas !

Je travail dans le module de classe avec se tableau cls_Tabtemp
* Donc Modifier et conservé dans le module de classe

Suite a cela deux Options :
* Ont récupère la variable tableau du module de classe Stoké dans le module standard.
dans sa totalité :
soit : Tableau = SL.triDeCroissant (C'est un exemple) voir le code !
* Ou lecture directement dans le module de classe les information stoké dans la variable tableau
soit : Debug.Print SL.ContenuVarTab(SL.triCroissant, i, j) voir le code !

* Le module Standard : ModuleStandard
VB:
' Appelle du Module de classe en public
Public SL As New SListe
Sub test()
' Mise en mémoire d'un tableau 2 dimensions
Dim Tableau() As Variant
    Tableau = Range(Cells(1, 1), Cells(17, 3))

' Maintenant l'interet du module de classe !
' ******************************************
' Ont injecte "Dans le Module de Classe"
' la Variable "Tableau" 2 dimension
' Le Numéro de la colonne a trié
' Decryptage SL.ajout("Tableau = la variable tableau") = "1 = le numéro de la colonne"
    SL.ajout(Tableau) = 1

' ********************************************************************************************************
' AUX CHOIX POUR L'ORDRE DE TRI CROISSANT OU DECROISSANT CI-DESSOUS !
' -------------------------------------------------------------------
' tri Croissant par appelle depuis le module de classe.
' Pour l'exemple je choisie tri DeCroissant donc je Bloc cette ligne !
' --------------->>>>   Tableau = SL.triCroissant

'' tri DeCroissant par appelle depuis le module de classe.
   Tableau = SL.triDeCroissant
'   Test de lecture pour Resultat de la case Ligne 1 Colonne 1 de la variable tableau trié.
    MsgBox Tableau(1, 1)
' Fin !

' *************************************************************************************************************
' NOTA : BONUS (J'ai conservé votre tableau Original avant toute modification dans le module de classe)
' Private cls_TabOrigine() As Variant / Ce tableau est privé a la classe et sera jamais modifié
' Exemple
        Tableau = SL.RecupTabOrigine
' Test Cellule(1,1)
    MsgBox Tableau(1, 1)
' Fin !
' *************************************************************************************************************
' Alors Voici tous l'interet du Module de Classe
' Qu'elle tableau je veux :
'    * Celui trié DeCroissant ?          / appel depuis le module de classe SL.triDeCroissant
        Tableau = SL.triDeCroissant
        MsgBox Tableau(1, 1)
'    * Ou celui d'origine !!             / appel depuis le module de classe SL.RecupTabOrigine
        Tableau = SL.RecupTabOrigine
        MsgBox Tableau(1, 1)
'    * Celui trié Croissant ?            / appel depuis le module de classe SL.triCroissant
        Tableau = SL.triCroissant
        MsgBox Tableau(1, 1)
' Nota La variable Tableau "Tableau" est unique est pas besoin de créer une autres variable tableau !
' *************************************************************************************************************
' Bonus Complementaire (sans avoir besoin de transfert de la variable tableau dans le module de classe)
' Lecture directemet depuis le module de classe chaque case du bableau (Contenu dans le module de classse)
' Aux Choix
Dim i As Long, j As Long
' ************************************************************************************************
' Le tableau d'origine ................. Soit : SL.RecupTabOrigine
For i = LBound(SL.RecupTabOrigine, 1) To UBound(SL.RecupTabOrigine, 1)
    For j = LBound(SL.RecupTabOrigine, 2) To UBound(SL.RecupTabOrigine, 2)
            Debug.Print SL.ContenuVarTab(SL.RecupTabOrigine, i, j)
    Next j
Next i
' ********************************************************************************************************
' Par ajout dans le module de classe ceci !
''' ---- >>  Property Get ContenuVarTab(ByRef Tabtemp() As Variant, ByRef i As Long, ByRef j As Long)
''' ---- >>     ContenuVarTab = Tabtemp(i, j)
''' ---- >>  End Property
' Qui permet les resultat si dessous
' ********************************************************************************************************
' Bonnus = Copie du tableau en Cells(5,1)
    Cells(1, 5).Resize(UBound(SL.RecupTabOrigine, 1), UBound(SL.RecupTabOrigine, 2)) = SL.RecupTabOrigine
' ************************************************************************************************
' Ou le tableaux trié en DeCroissant...... Soit : SL.triDeCroissant
For i = LBound(SL.triDeCroissant, 1) To UBound(SL.triDeCroissant, 1)
    For j = LBound(SL.triDeCroissant, 2) To UBound(SL.triDeCroissant, 2)
            Debug.Print SL.ContenuVarTab(SL.triDeCroissant, i, j)
    Next j
Next i
' Bonnus = Copie du tableau en Cells(5,1)
    Cells(1, 5).Resize(UBound(SL.triDeCroissant, 1), UBound(SL.triDeCroissant, 2)) = SL.triDeCroissant
' ************************************************************************************************
' Ou le tableau trié en Croissant..... Soit : SL.triCroissant
For i = LBound(SL.triCroissant, 1) To UBound(SL.triCroissant, 1)
    For j = LBound(SL.triCroissant, 2) To UBound(SL.triCroissant, 2)
            Debug.Print SL.ContenuVarTab(SL.triCroissant, i, j)
    Next j
Next i
' Bonnus = Copie du tableau en Cells(5,1)
    Cells(1, 5).Resize(UBound(SL.triCroissant, 1), UBound(SL.triCroissant, 2)) = SL.triCroissant
' ************************************************************************************************
End Property

Le Module de Classe : SListe
VB:
Private cls_TabOrigine() As Variant ' Ici je conserve la structure du tableau d'origine
' Element de travail ci-dessous !
    Private cls_Tabtemp() As Variant  ' Ici j'effectu les modification de structure du tableau de tri
    Private cls_NumCol1 As Integer    ' Avec le numéro de colonne a trié !
Property Let ajout(ByRef Tableau() As Variant, ByVal NumCol1 As Integer)
    cls_Tabtemp = Tableau ' Le tableau 2 dimension dans le module de classe
    cls_NumCol1 = NumCol1 ' Le choix de la colonne de tri
' Option Je conserve la structure d'origine du tableau initial non modifié !
    cls_TabOrigine = Tableau
End Property
Property Get RecupTabOrigine() As Variant()
    RecupTabOrigine = cls_TabOrigine
End Property
Property Get triCroissant() As Variant()
' Tri la variable tableau
    Croissant cls_Tabtemp, cls_NumCol1, LBound(cls_Tabtemp, 1), UBound(cls_Tabtemp, 1)
' Renvois le Resultat dans le Module Standard
    triCroissant = cls_Tabtemp
End Property
Property Get triDeCroissant() As Variant()
' Tri la variable tableau
    DeCroissant cls_Tabtemp, cls_NumCol1, LBound(cls_Tabtemp, 1), UBound(cls_Tabtemp, 1)
' Renvois le Resultat dans le Module Standard
    triDeCroissant = cls_Tabtemp
End Property
Property Get ContenuVarTab(ByRef Tabtemp() As Variant, ByRef i As Long, ByRef j As Long)
    ContenuVarTab = Tabtemp(i, j)
End Property
Private Sub Croissant(a() As Variant, colTri, gauc, droi)
' Tri "Croissant" d'un tableau (Array) à 2 dimensions
  ref = a((gauc + droi) \ 2, colTri)
  g = gauc: d = droi
  Do
' Pour un tri Croissant
    Do While a(g, colTri) < ref: g = g + 1: Loop
    Do While ref < a(d, colTri): d = d - 1: Loop
        If g <= d Then
           For k = LBound(a, 2) To UBound(a, 2)
             temp = a(g, k): a(g, k) = a(d, k): a(d, k) = temp
           Next k
           g = g + 1: d = d - 1
        End If
  Loop While g <= d
  If g < droi Then Call Croissant(a, colTri, g, droi)
  If gauc < d Then Call Croissant(a, colTri, gauc, d)
End Sub
Private Sub DeCroissant(a() As Variant, colTri, gauc, droi)
' Tri "DéCroissant" d'un tableau (Array) à 2 dimensions
  ref = a((gauc + droi) \ 2, colTri)
  g = gauc: d = droi
  Do
' Pour un tri DéCroissant
    Do While a(g, colTri) > ref: g = g + 1: Loop
    Do While ref > a(d, colTri): d = d - 1: Loop
        If g <= d Then
           For k = LBound(a, 2) To UBound(a, 2)
             temp = a(g, k): a(g, k) = a(d, k): a(d, k) = temp
           Next k
           g = g + 1: d = d - 1
        End If
  Loop While g <= d
  If g < droi Then Call DeCroissant(a, colTri, g, droi)
  If gauc < d Then Call DeCroissant(a, colTri, gauc, d)
End Sub

Pour info :

' Pour restitution de la variable tableau vers la feuille excel (en evitant les boucles) #Poste 13

Conformément à :
J'utilise le module de classe [Sorted List] de Jacques BOISGONTIER que j'ai trouvé sur un fil :
 
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
312 169
Messages
2 085 929
Membres
103 047
dernier inscrit
Duuubee