Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

VBA : Tri Shell dans variable tableau - multicritère.

  • Initiateur de la discussion Initiateur de la discussion dionys0s
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

dionys0s

XLDnaute Impliqué
Bonjour le forum

Je souhaiterais obtenir de l'aide sur une fonction (ou sous sub) de tri de table définie à partir d'un range.

Dans mon fichier exemple, il s'agit de faire un tri décroissant sur la colonne 2 (numérique) puis un croissant sur la colonne 1 (texte). Je ne sais pas s'il est possible de créer une fonction totalement générique pour ça, mais je l'espère !

J'ai d'ores-et-déjà intégré la première partie (Tri Shell décroissant sur la dimension qui contient des numériques, mais qui est loin d'être optimisée), mais je lutte un maximum pour la suite.

Je ne veux pas me faire mâcher le boulot, mais avoir quelques pistes m'aiderait sûrement beaucoup, j'ai l'impression d'être en panne d'idées là... 😕

D'avance merci pour votre aide !

dionys0s
 

Pièces jointes

Re : VBA : Tri Shell dans variable tableau - multicritère.

Bonjour.
Je peux vous proposer mon module de classe TableIndex, et mon module MDictionnArbo qui contient une procédure permettant ces classements. Mais il n'utilise pas le tri Shell et d'ailleurs … il ne trie pas ! En revanche il donne successivement les numéros de lignes dans le tableau permettant de le parcourir dans l'ordre des arguments demandés. En d'autre terme ce n'est pas le tableau lui même qu'il trie mais ses numéros de lignes. Et l'expérience prouve que c'est nettement plus pratique: on a presque toujours besoin, ensuite, de ces numéros de lignes pour accéder à des informations dans d'autres colonnes qui ne participaient pas au tri.
 
Re : VBA : Tri Shell dans variable tableau - multicritère.

Et pour compléter ma réponse j'ai les deux, la Fonction et la Sub
en 1er paramètre la plage à classer, ensuite une série d'entiers <> 0 dont la valeur absolue donne le n°de colonne dans la plage et le signe le sens de classement.
 

Pièces jointes

Re : VBA : Tri Shell dans variable tableau - multicritère.

Waow...

Bonsoir/jour à tout le monde.

Merci à vous pour vos réponses. Un parcours "rapide" de vos suggestions me fait penser que mon bonheur se trouve bien là. Merci beaucoup à vous. Si je lutte je reviendrai vers vous à partir de lundi. Voir mardi, le temps de potasser/adapter/tester tout ça.
 
Re : VBA : Tri Shell dans variable tableau - multicritère.

Bonjour le forum
Re Dranreb, JB, Efgé

Bon alors en fait je n'ai utilisé aucune de vos méthodes.
Je travaille sur MAC, et ton code Dranreb utilise des fonctionnalités qui me sont à priori inaccessibles :
VB:
Private Declare PtrSafe Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
   (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
   #Else
Private Declare Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
   (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
De plus mon patron est moyen chaud pour l'utilisation de modules de classe. Et moi même serais bien en berne de les comprendre dans l'état des mes capacités VBA.

Et à moins que j'ai mal interprété le code, JB je n'ai pas l'impression que tes exemples me permettent de faire un tri croissant sur un critère puis un décroissant sur l'autre, mais permettent en fait d'associer les critères pour en faire un seul critère de tri, donc 2 critères soumis forcément à la même méthode (croissant ou décroissant).

J'ai donc quand même planché un petit peu, et j'aimerais avoir vos avis de brontosaures barbatruc d'Excel sur mon fichier.

Je vous expose la logique de ma démarche.
J'utilise un algo de tri Shell. Ma nullité congénitale en mathématiques fait que j'ai pas mal de difficultés à la comprendre. J'ai tout de même réussi à l'adapter un peu pour lui passer en paramètres sur quelle portion du tableau l'algo doit travailler, ce qui permet de faire mes tris secondaire, en lui passant un paramètre 'ColCompare' : tant que les valeurs dans ColCompare sont identiques, on ne trie pas, puis quand c'est différent, on trie la portion de tableau qui contient des valeurs identiques dans ColCompare (Est-ce que je m'ai bien fait compris ?).

J'ai donc séparé mes macros de tris en 4 macros distinctes (histoire d'avoir des procédures un peu lisibles) => une procédure de tri croissant, une de tri décroissant, une de tri secondaire croissant et une de tri secondaire décroissant. Les procédures de tri secondaires ne servent en réalité qu'à isoler les "sous tableau" à retrier avec une nouvelle clé, puis à lancer le bon tri (croissant ou décroissant) avec les bons paramètres.

Donc j'aimerais avoir votre avis sur tout ce qui vous passe par la tête. Le tri Shell est-il mieux/moins bien/on sait pas que le tri rapide (Quick Sort) ? Est-ce que j'ai loupé des trucs importants (notamment sur la gestion du multicritère) etc. Est-ce que quelqu'un serait assez dévoué pour m'expliquer la logique de l'algo (la littérature sur Internet est assez pauvre à ce sujet je trouve).

Voilà voilà. Merci d'avance. J'espère que je n'abuse pas trop.

😎
dionys0s

EDIT : mon fichier est un peu volumineux : j'y ai mis un tableau de 10 000 lignes et 3 colonnes.
 

Pièces jointes

Dernière édition:
Re : VBA : Tri Shell dans variable tableau - multicritère.

Bonjour.
Je travaille sur MAC
Alors modifie comme suit la directive en tête du module TableIndex :
VB:
#Const AvecMoveMemory = 0 ' = 1 normalement, à corriger = 0 si MoveMemory n'est pas disponible sur votre machine.
D'après Wikipedia, parmi les méthodes de tri analysées, le Shell est le plus rapide pour de petits tableaux. Mais l'ordre de grandeur du nombre d'éléments à partir duquel il est battu par le QuickSort n'est de quelques centaines.
La littérature sur les méthodes de tri me parait assez abondante sur Internet, encore que je trouve que la méthode par insertion avec recherche dichotomique de l'élément à insérer dans la partie déjà classée n'est pas assez étudiée à cause du nombre de déplacements d'éléments qu'elle implique pour effectuer ensuite l’insertion. Si ce ne sont que des numéros, même si, comme dans ton cas, on est privé de la possibilité de les décaler massivement en mémoire, je crois qu'il existe une limite inférieure au nombre d'éléments en dessous duquel c'est la méthode la plus efficace. Je l'emploie donc pour les petites partitions subsistantes du Quick-Sort.
 
Re : VBA : Tri Shell dans variable tableau - multicritère.

Re,

et que fais-je du code que je citais dans mon post un peu plus haut ?

Cette partie-ci s'affiche même en rouge dans mon VBE (non exploitable donc) :
VB:
Private Declare PtrSafe Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
   (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
 
Re : VBA : Tri Shell dans variable tableau - multicritère.

Je n'ai pas encore regardé le code, mais je suppose que les comparaisons ne sont pas dissociées de la méthode de tri, de sorte que ça ne m'intéresse guère.

Chez moi aussi ça s'affiche en rouge, mais ça n'affecte en rien la compilation du projet VBA car des directives lui demandent expressément de ne le compiler que si les constantes de compilation AvecMoveMemory et VBA7 sont <> 0. Si chez toi ça bloque quand même à la compilation ne garde que les instructions qui ne sont pas soumises à AvecMoveMemory Juste garder :
VB:
Const LimiteDicho = 40

Beaucoup plus bas :
#If AvecMoveMemory Then
MoveMemory TIdx(IFin + 1), TIdx(IFin), (I1 - IFin) * 4
#Else
For I2 = I1 - 1 To IFin Step -1: TIdx(I2 + 1) = TIdx(I2): Next I2
#End If
Ne garder que :
VB:
For I2 = I1 - 1 To IFin Step -1: TIdx(I2 + 1) = TIdx(I2): Next I2
 
Re : VBA : Tri Shell dans variable tableau - multicritère.

Bonjour.
J'ai quand même fini par ouvrir ton dernier classeur. J'y ai ajouté mes modules.
Après vérification, même avec #Const AvecMoveMemory = 0, cette procédure, affectée à un second bouton est un peu plus rapide :
VB:
Sub LancemQS()
Dim TABLO() As Variant, Key1 As Integer, Key2 As Integer, Key3 As Integer, TDép As Single
TABLO = ActiveSheet.Range("A1").CurrentRegion.Value
Key1 = 2
Key2 = 3
Key3 = 1
TDép = Timer
Depose TableauClassé(TABLO, -Key1, Key2, Key3), ActiveSheet, 1, 5
MsgBox Timer - TDép
End Sub
Mais le gain n'est pas très important: 25% environ

Il est à noter que le résultat serait différent si des données de types différents figuraient dans une même colonne: ils se retrouveraient regroupés par types, tandis qu'avec des comparaisons sans précaution le résultat pourrait être imprévisible et aberrant selon qu'il convertit ou non en numérique, lors de chaque comparaison, des textes de chiffres avec "0" non significatifs devant par exemple.
 
Dernière édition:
Re : VBA : Tri Shell dans variable tableau - multicritère.

Bonjour tout le monde,

Re Dranreb,

merci d'avoir regardé mon bout de code. Je l'ai un peu amélioré depuis.

J'ai essayé de me pencher sur ton fichier mais très honnêtement je n'y comprends pas grand chose. Il faudrait que je commence par me plonger dans un tuto sur les modules de classe. Et de plus, je ne sais pas si c'est normal, mais je ne peux pas exécuter tes macros.

Du coup vu ce que tu me dis je vais faire avec mon bout de code pour le moment, et je me remettrai dessus un peu plus tard.

Merci encore à toi

dionys0s
 
Re : VBA : Tri Shell dans variable tableau - multicritère.

Déjà est-ce qu'il marche tel quel ?

Si oui, il sera toujours temps de voir mes explications à propos de ce que tu ne comprends pas au juste ?
Si non, j'abrégerai désormais toute discussion où il est subitement question d'arriver à faire tourner le truc sur un Mac…
 

Pièces jointes

Dernière édition:
Re : VBA : Tri Shell dans variable tableau - multicritère.

C'est très étonnant !
Chez moi la tienne (bouton TRIER, Sub Lancement que j'ai aussi équipé de la vérif Timer) m'affiche systématiquement entre 1,3125 et 1,3475 tandis que la mienne entre 0,90625 et 0,96875
Maintenant j'ai aussi retrouvé cette note dans l'aide sur Timer:
Avec Microsoft Windows, la fonction Timer renvoie une valeur avec une précision de l'ordre de la fraction de seconde. Sur Macintosh, la précision est d'une seconde.
 
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…