XL 2010 Tri Croissant Array 2D sur 2 colonnes

cathodique

XLDnaute Barbatruc
Bonjour:),

Sur le site de Jacques Boisgontier (ce lien), j'ai récupéré un code de tri d'un array.
Sur le fichier joint, le tableau figurant sur la feuille1 est le tableau obtenu de mon fichier de réel.
Donc, sur ce fichier je parviens bien à obtenir le résultat escompté.
Par contre, sur mon véritable fichier qui est conséquent en données et confidentielles.
Je n'arrive pas à adapter le code de Jacques.
Cela fait, 2 jours que je tourne en rond. Mon code fonctionne bien, Les problèmes commencent au tri du tableau.
Merci de déceler mes erreurs dans code ci-dessous.
Avec mes remerciements anticipés.
NB: fichier joint modifié.
VB:
Option Explicit
Option Compare Text

Sub Regroupe_Sous_Total()
   Dim F_Cmpt As Worksheet, d1 As Object, TbRes(), tbd, dl As Long, Ncol As Byte, ligne As Long
   Dim clé, lig As Integer, col As Byte, a()

   Set d1 = CreateObject("Scripting.Dictionary")
   Set F_Cmpt = Sheets("comptes")
   tbd = F_Cmpt.Range("A2:F" & F_Cmpt.[A65000].End(xlUp).Row).Value
   dl = F_Cmpt.Range("a" & Rows.Count).End(xlUp).Row
   With F_Cmpt.Range("A6:L" & dl)
      tbd = Application.Index(.Value, Evaluate("row(1:" & .Rows.Count & ")"), Array(3, 4, 6, 7, 10, 11))
   End With
   ReDim TbRes(1 To UBound(tbd), 1 To 6)
   For ligne = 1 To UBound(tbd)
      clé = tbd(ligne, 1)
      If d1.exists(clé) Then
         lig = d1(clé)
      Else
         d1(clé) = d1.Count + 1
         lig = d1.Count  ' index
         TbRes(lig, 1) = tbd(ligne, 1)
         TbRes(lig, 2) = tbd(ligne, 2)
         TbRes(lig, 4) = tbd(ligne, 5)
         TbRes(lig, 5) = tbd(ligne, 6)
      End If
      col = IIf(tbd(ligne, 5) = "Dépenses", 3, 4)
      TbRes(lig, 3) = TbRes(lig, 3) + tbd(ligne, col)
   Next ligne
   'tri croissant Tbd 1ère colonne
   Tri TbRes(), 1, LBound(TbRes, 1), UBound(TbRes, 1)

   'tri croissant TbRes 2ème colonne
   Tri TbRes(), 2, LBound(TbRes, 1), UBound(TbRes, 1)

   Feuil11.[a1].Resize(d1.Count, 6).ClearContents
   Feuil11.[a1].Resize(d1.Count, 6) = TbRes
End Sub
' TRI D'UN ARRAY 2D via la colonne N°colTri
' a() = le tableau à trier
' gauc = indice bas du tableau
' droi = indice haut du tableau
' colTri = la colonne sur laquelle on effectue le tri
' http://boisgontierjacques.free.fr/
Sub Tri(TbRes(), ColTri, gauc, droi)   ' Quick sort
   Dim ref, g, d, k As Integer, temp
   ref = TbRes((gauc + droi) \ 2, ColTri)
   g = gauc: d = droi
   Do
      Do While TbRes(g, ColTri) < ref: g = g + 1: Loop
      Do While ref < TbRes(d, ColTri): d = d - 1: Loop
      If g <= d Then
         For k = LBound(TbRes, 2) To UBound(TbRes, 2)
            temp = TbRes(g, k): TbRes(g, k) = TbRes(d, k): TbRes(d, k) = temp
         Next k
         g = g + 1: d = d - 1
      End If
   Loop While g <= d
   If g < droi Then Call Tri(TbRes, ColTri, g, droi)
   If gauc < d Then Call Tri(TbRes, ColTri, gauc, d)
End Sub
 

Pièces jointes

  • TriCroissant Array 2D_2Colones.xlsm
    65.9 KB · Affichages: 11
Dernière édition:

Paf

XLDnaute Barbatruc
Bonjour,

pas facile de voir ce qui ne va pas avec des données où ça fonctionne.


quelques remarques :
- l'utilisation de tbd = F_Cmpt.Range("A2:F" & F_Cmpt.[A65000].End(xlUp).Row).Value si les données dépassent 65000 lignes
-dans la sub tri, la déclaration de k en integer s'i y a plus de 32767 lignes : Dim ref, g, d, k As Integer, temp ; mais il y aurait un message d'erreur
-le fait de trier le tableau une première fois sur la colonne 1 puis sur la colonne 2 donne le même résultat que de trier directement sur la colonne 2; on peut donc supprimer le tri sur colonne 1

Pas sûr que ça résolve le problème.
A+
 

cathodique

XLDnaute Barbatruc
Bonjour,

S'il s'agit d'un tri dans le tableur:

Code:
Sub MaBD()
  Feuil1.Range("a1").CurrentRegion.Copy Feuil1.[G1]
  Feuil1.[G1].CurrentRegion.Sort key1:=Feuil1.[G1]
End Sub

Boisgontier
Bonjour Jacques:),

Content que tu répondes à mon message.
Il ne s'agit pas d'un tri dans le tableur.
C'est le tri d'un array résultant obtenu par code.

J'ai repris ton code que je suis parvenu à adapter au fichier joint.

Merci.;)
 

cathodique

XLDnaute Barbatruc
Re,;)
Je reviens aux nouvelles.

J'ai supprimé des lignes ainsi que les données confidentielles. J'ai donc mis à jour le fichier de post#1.
J'ai bien un rendu sur la feuille "resultat" sans tri, mais dès que j'active le tri, on dirait qu'il ne se passe rien ou plutôt le tableau TbRes est vidé de son contenu. J'avoue que ça m'échappe; je n'arrive pas à trouver mon erreur.

En vous remerciant.
 

Paf

XLDnaute Barbatruc
bonjour,

on dimentionne TbRes comme Tbd soit 725 "lignes"

par la boucle on crée le dico et on insère des ligne dans TbRes. Il n'y a que 30 lignes d'insérées (d1.Count=30). les 695 lignes suivantes sont vides.

on fait le tri croissant sur la colonne 2, donc les vides ou blancs sont en premiers . Les lignes pleines vont de 695 à 725.

Et pour finir on colle les données en feuille2
Feuil2.[a1].Resize(d1.Count, 6) = TbRes

Mais le resize ne prend que les 30 premières lignes de TbRes, on ne copie donc que des lignes vides.

Il faudrait peut-être que TbRes soit dynamique en allouant une ligne à chaque fois que c'est nécessaire( Redim Preserve) . TbRes serait alors transmis avec 30 lignes au tri , et comme il n'y a pas de lignes vides ... pas de soucis

A+
 

cathodique

XLDnaute Barbatruc
Merci beaucoup Paf. Je vais essayer de m'en sortir avec tes explications.

J'ai commencé à monter ce code ligne par ligne et j'ai oublié le transfert.

En effet, TbRes devrait être dynamique. Redim Preserver :rolleyes::oops:, je ne l'ai jamais utilisé mais il faut bien plonger pour apprendre à nager. Merci, au cas où je risque la noyade puis-je revenir vers toi?

Encore merci pour ton aide.
 
Dernière édition:

cathodique

XLDnaute Barbatruc
Il faudrait peut-être que TbRes soit dynamique en allouant une ligne à chaque fois que c'est nécessaire( Redim Preserve) . TbRes serait alors transmis avec 30 lignes au tri , et comme il n'y a pas de lignes vides ... pas de soucis

Re,:)
Ta proposition aurait été l'idéal. Mais j'avoue que je suis perdu.
Je me suis basé sur les exemples de Boisgontier.
En fait, pour chaque code en col 1 du tableau tbd , je somme suivant le cas col 3 ou col 4 de tbd
et récupère 2 autres données (opération et previ), basé sur une indexation du code (col1 de tbd).
Je ne vois pas à quel niveau introduire le Redim Preserve ni comment.
Je suis intéressé par cette solution, bien que j'en ai trouvé une autre. Dites-moi où?!!!
Sur le site de Boisgontier. Supprimer les lignes vides du tableau.
VB:
'supprimer lignes vides du tableau TbRes
   For i = 1 To UBound(TbRes)
      If TbRes(i, 1) <> "" Then n = n + 1
   Next i
   j = 0
   Dim TbRes2(): ReDim TbRes2(1 To n, 1 To UBound(TbRes, 2))
   For i = 1 To UBound(TbRes)
      If TbRes(i, 1) <> "" Then j = j + 1
      For k = 1 To UBound(TbRes, 2)
         TbRes2(j, k) = TbRes(i, k)
      Next k
   Next i
Cependant, je suis resté sur ma soif suite à ton idée.
Merci à vous de me proposer une solution avec Redim Preserve.

Bonne soirée à vous.;)
 

Paf

XLDnaute Barbatruc
Le principe est simple, on déclare la nouvelle taille du tableau juste avant d'insérer une nouvelle ligne.
le preserve est là pour conserver ce qu'on a déjà écrit.
pour un tableau deux dimensions c'est plus ennuyeux car on ne peux modifier que la deuxième dimension. ce qui oblige à déclarer le tableau " à l'envers" puis à remettre dans l'ordre avec application.transpose (si le nombre de ligne est < 65000 lignes si je me souviens bien)

Exemple:
VB:
dim T()
...
For ligne = 1 To UBound(tbd)
     If aaaaaaaaa  Then
            .../...
      Else
 
          x = x + 1
         ReDim Preserve T(1 to 6,1 to x)
         T(1,x) = tbd(ligne, 1)
         T(2,x) = tbd(ligne, 2)
         T(3,x) = tbd(ligne, 5)
         T(4,x) = tbd(ligne, 6)
         ...
      End If
.../...
next


pas si simple dans le cas présent
le plus simple serait peut être d'effacer les lignes vides de TbRes
 

cathodique

XLDnaute Barbatruc
Le principe est simple, on déclare la nouvelle taille du tableau juste avant d'insérer une nouvelle ligne.
le preserve est là pour conserver ce qu'on a déjà écrit.
pour un tableau deux dimensions c'est plus ennuyeux car on ne peux modifier que la deuxième dimension. ce qui oblige à déclarer le tableau " à l'envers" puis à remettre dans l'ordre avec application.transpose (si le nombre de ligne est < 65000 lignes si je me souviens bien)

Exemple:
VB:
dim T()
...
For ligne = 1 To UBound(tbd)
     If aaaaaaaaa  Then
            .../...
      Else

          x = x + 1
         ReDim Preserve T(1 to 6,1 to x)
         T(1,x) = tbd(ligne, 1)
         T(2,x) = tbd(ligne, 2)
         T(3,x) = tbd(ligne, 5)
         T(4,x) = tbd(ligne, 6)
         ...
      End If
.../...
next


pas si simple dans le cas présent
le plus simple serait peut être d'effacer les lignes vides de TbRes
Bonjour Paf:),

Merci beaucoup pour tes explications. Normalement, les lignes ne dépasseront pas les 65536 lignes.
Je ne maitrise pas parfaitement la manipulation des "Arrays". C'est pour cela qu'à chaque fois, je transfère sur une feuille pour constater si le résultat est juste avant de passer à l'étape suivante de mon code.

Oui, le plus simple est de supprimer les lignes vides. Et c'est ce que j'ai fait (adaptant le code de JB).
Cependant, après le tri la dernier ligne du tableau trié est manquante.
J'ai remarqué 2 choses bizarres:
1- une ligne qui manque au lieu de 30, sur la feuille 29 lignes (dans la fenêtre espion TbRes(30) est vide.)
2- Sur la feuille le transfert s'effectue à partir de A2 au lieu de A1
d'après cette ligne de code: (Feuil2.[a1].Resize(UBound(TbRes2), UBound(TbRes2, 2)) = TbRes2)

Et ce, en n'utilisant qu'un seul tri (c-à-d sur une seul colonne).
Je soupçonne le code de tri de JB. Mais je n'ai pas encore atteint votre niveau pour bien l'analyser et déterminer la faille.
Je suis déçu de mon piètre résultat.

Je te suis vraiment connaissant de m'avoir consacré de ton temps et partager avec moi tes connaissances.

Bonne journée.:)

Edit: Désolé. Je viens de m'apercevoir que c'est le code de suppression de lignes vides du tableau qui pose problème. En effet, après l’exécution du code TbRes(30) est vide.
 
Dernière édition:

Discussions similaires

Réponses
17
Affichages
304

Statistiques des forums

Discussions
312 087
Messages
2 085 198
Membres
102 815
dernier inscrit
Henridic