Re:=> DEMO UserForm tri multiple/suppression doublons
Bonjour à tous et toutes
J'ai eu l'occasion de déjeuner avec Akeya qui est for sympa. Il me posait quelques questions de compréhension, donc voici quelques explication sur une partie des codes employées et particulièrement pour le 'Tri'...
Private Sub TriTablo(ByVal C0 As Byte)
Dim T As Variant
Dim x As Integer, j As Integer, i As Integer, ii As Integer
Dim Tmp1 As String, Tmp2 As String, Tmp3 As String, Tmp4 As String
Dim Tmp5 As String, Tmp6 As String, Tmp7 As String, Tmp8 As String, Tmp9 As String
'Part AAA
With Database
If .FilterMode = True Then .ShowAllData
T = .Range('A2:H' & .Range('A65536').End(xlUp).Row)
End With
'Part BBB
For i = 1 To UBound(T, 1)
If T(i, 1) <> '' Then
ReDim Preserve Tablo(8, x)
Tablo(0, x) = CStr(T(i, 1))
Tablo(1, x) = CStr(T(i, 2))
Tablo(2, x) = CStr(T(i, 3))
Tablo(3, x) = CStr(T(i, 4))
Tablo(4, x) = CStr(T(i, 5))
Tablo(5, x) = CStr(T(i, 6))
Tablo(6, x) = CStr(T(i, 7))
Tablo(7, x) = CStr(T(i, 8))
Tablo(8, x) = CStr(i + 1)
x = x + 1
End If
Next
'Part CCC
For i = LBound(Tablo, 2) To UBound(Tablo, 2)
For j = LBound(Tablo, 2) + ii To UBound(Tablo, 2)
If Tablo(C0, i) > Tablo(C0, j) Then
Tmp1 = Tablo(0, j): Tmp2 = Tablo(1, j): Tmp3 = Tablo(2, j): Tmp4 = Tablo(3, j)
Tmp5 = Tablo(4, j): Tmp6 = Tablo(5, j): Tmp7 = Tablo(6, j): Tmp8 = Tablo(7, j): Tmp9 = Tablo(8, j)
Tablo(0, j) = Tablo(0, i): Tablo(1, j) = Tablo(1, i): Tablo(2, j) = Tablo(2, i): Tablo(3, j) = Tablo(3, i)
Tablo(4, j) = Tablo(4, i): Tablo(5, j) = Tablo(5, i): Tablo(6, j) = Tablo(6, i): Tablo(7, j) = Tablo(7, i): Tablo(8, j) = Tablo(8, i)
Tablo(0, i) = Tmp1: Tablo(1, i) = Tmp2: Tablo(2, i) = Tmp3: Tablo(3, i) = Tmp4
Tablo(4, i) = Tmp5: Tablo(5, i) = Tmp6: Tablo(6, i) = Tmp7: Tablo(7, i) = Tmp8: Tablo(8, i) = Tmp9
End If
Next j
ii = ii + 1
Next i
End Sub
Explications :
Part AAA
C’est un moyen d’envoyer toute la feuille dans la mémoire, c’est mille fois plus rapide que de travailler sur les cellules.
Je dois préciser dans quelle feuille, donc c’est ici :
With Database
NB Database est le Nom « CodeName » de la Feuille et pas le nom d’onglet (voir propriétés de la Feuille)
Au cas où, je libère la feuille de tout filtre automatique
If .FilterMode = True Then .ShowAllData
Et maintenant j’envoie toute la plage dans la mémoire dans une Array (Tableau) de type Variant « T »
T = .Range('A2:H' & .Range('A65536').End(xlUp).Row)
Part BBB
Voici la construction d’un tableau dynamique indexé séquentiellement de type String « Tablo() ».
Il faut savoir que par défaut, ce genre de Tableau est en base 0 (il démarre par la valeur 0 niveau ligne et colonne du premier enregistrement)
Mon algo est basé sur le nombre d’enregistrement contenu dans mon premier Tableau « T » obtenu en AAA. Je le mesure grace à cette instruction :
For i = 1 To UBound(T, 1)
Un condition, qui pourrait être bien plus pointue, ici c’est si colonne 1 de la ligne « i » est différent vide…
If T(i, 1) <> '' Then
Et c’est parti, il suffit que je dimensionne mon tableau « Tablo » comme suit :
ReDim Preserve Tablo(8, x)
Ce qui signifie au premier passage de al boucle, 8 lignes sur x colonne (x étant à 0). On notera que contrairement à « T » ce « Tablo » est inversé. (Obligatoire, on ne peut changer que la seconde dimension en Redim), mais ce n’est pas grave, contrairement à une feuille Excel, ce genre de tableau n’est pas limité à 255 colonnes. En fait c’est juste une vision de l’esprit, mais il faut bien comprendre que l’on est à l’envers.
Ensuite c’est une partie de mise en place toute simple :
Tablo(0, x) = CStr(T(i, 1))
On voit bien d’ailleurs que Tablo(0, x) (Colonne 0, Ligne x) = T(i, 1) (Ligne i, Colonne 1)
Soit à l’envers et en base Zéro
La petite exception sera la dernière incrémentation de données
Tablo(8, x) = CStr(i + 1)
Qui en fait consiste à envoyer le numéro de Ligne de « T » (qui correspond à celui de la Feuille + 1) dans le « Tablo » pour pouvoir le réutiliser plus tard à des fins de modifications sur la feuilles….
Et on incrémente notre « x » pour le passage suivant :
x = x + 1
Le «
CStr » est juste là pour une conversion de données pour avoir du type String.
Part CCC
Cette partie est un Algo qui va trier les items du tableau en s’appuyant sur une Double Boucle en décalage sur les lignes du Tableau. (Cette façon de faire a un nom que j’ai oublié, si quelqu’un peut me rafraîchir la mémoire)
En clair :
For i = LBound(Tablo, 2) To UBound(Tablo, 2) (boucle « i »)
Suivi de :
For j = LBound(Tablo, 2) + ii To UBound(Tablo, 2) ) (boucle « j »)
Génère cette Double Boucle en décalage, le décalage étant assuré par ii.
Ensuite, et bien il suffit de lire ce qu’il se passe :
If Tablo(C0, i) > Tablo(C0, j) Then
Ceci est la condition pour vérifier si ce qui est dans la boucle i est plus grand que dans la boucle J
Si tel est le cas on envoie dans une variable temporaire la valeur de ce qui est dans la boucle j :
Tmp1 = Tablo(0, j)
On aura autant de Variable Tmp que de colonne à traiter.
Ensuite on va envoyer en position j ce qui était dans la position i par cette instruction :
Tablo(0, j) = Tablo(0, i)
Il ne restera plus qu’à récupérer la valeur de la variable temporaire pour la remettre en i
Tablo(0, i) = Tmp1
Passage d’Argument
Avant de partir vers de nouvelles aventures, il serait dommage qu’un tel Algo ne serve qu’une fois… Donc
Private Sub TriTablo(ByVal C0 As Byte)
Et donc C0 est une variable en passage d'argument qui permet de faire mon tri sur la colonne que je souhaite, il suffit de passer l’argument en appelant la procédure
TriTablo 1 (colonne 2 de « Tablo » soit « Chaine »…
Comment ça Colonne 2 ??? si si si, zavez déjà oublié !!!
..... on est en base zéro, donc 1 = 2ème colonne (0, 1, 2)
Ou plus tard
TriTablo 2 (pour la troisième colonne « Code »)
Simple non ?
Bonne fin de journée
[ol]@+Thierry[/ol]