Méthode de trie avancé

Bonjour à tous !

je suis en possession d'une liste de produits qui ont

soit un conditionnement vrac 99 dont le code conditionnement est 99
soit un conditionnement "sac" dont le code conditionnement peut prendre les valeurs suivantes [ 0 , 1 , 4 , 5 , 8 , 10, 12 , 15 , 20 25, 27 ou 50] ces produits forment notre première catégorie dont le code conditionnement est nombre < 99

soit un conditionnement BIG BAG dont le code conditionnement peut prendre les valeurs suivantes BY BI B2

ces produits forment notre 2ème catégorie dont le code conditionnement commençe par B

je suis à la recherche d'une méthode pour trier mes données selon ce premier critère de conditionnement

c'est à dire afficher tous les produits vrac puis tous les produits sac puis tous les produits big bag

par la suite tous ces produits ont aussi un code sous sous famille qui indique la destination du produits (pour quel animal il est destiné)

et ce code qui prend des valeurs de 0 à 100.

je voudrais appliquer ce deuxième critère de trie parmi chaque famille de produits 99 ; <99 et BIG BAG

c'est à dire trier tous les produits vrac par sous sous famille (SSF) ; tous les produits sacs par sous sous famille (SSF) ; et tous les produits BIG BAG par sous sous famille (SSF)

j'ai essayé tout un tas de méthodes avec FIND notamment mais les paramètres ascendant descendant ne permettent pas d'obtenir ce résultat

et je n'arrive pas à l'interieur d'une catégorie de produits (type de conditionnement) appliqué un deuxieme critère de trie qui est la ss ss famille

si quelqu'un a une idée ! je suis preneuse , je vous mets mon fichier en PJ

merci pour toute aide

Mathylde

Bonjour,

A essayer :

Sub TriCond()
    Dim tmp(), aa, i%, k%
    With ActiveSheet.Range("A1").CurrentRegion
        aa = .Value: k = .Columns.Count + 1
    End With
    ReDim tmp(1 To UBound(aa), 0): tmp(1, 0) = "Tmp"
    For i = 2 To UBound(aa)
        If IsNumeric(aa(i, 4)) Then
            tmp(i, 0) = IIf(aa(i, 4) = 99, 1, 2)
        Else
            tmp(i, 0) = 3
        End If
    Next i
    Application.ScreenUpdating = False
    ActiveSheet.Cells(1, k).Resize(UBound(tmp)).Value = tmp
    With ActiveSheet.Range("A1").CurrentRegion
        .Sort key1:=.Cells(1, k), order1:=xlAscending, key2:=.Cells(1, 4), _
         order2:=xlAscending, key3:=.Cells(1, 1), order3:=xlAscending, Header:=xlYes
        .Columns(k).ClearContents
    End With
End Sub

Bouton Test sur la feuille.

NB- Prendre en compte les petites modifications opérées...

Cordialement.

Bonjour et merci pour votre aide,

le premier critère de tri est respecté mais j'ai peut etre mal formulé ce que je voulais pour le deuxième critère ;

parmi chaque type de conditionnement c'est le tri par sous sous famille qui doit être prioritaire.

Le tri est fait par : Catégories de conditionnement (classés : 99, autres numériques, non numériques), puis par Conditionnement, puis par SSF.

Si le Conditionnement n'est pas un critère de tri, il suffit de le faire disparaître !

Remplacer la ligne de commande de tri par celle-ci :

        .Sort key1:=.Cells(1, k), order1:=xlAscending, key2:=.Cells(1, 1), _
         order2:=xlAscending, Header:=xlYes

Cordialement.

Bonjour,

Une méthode de tri peut orthodoxe avec une succession de filtrages. Tout d'abords, supprimes la fusion des cellules en ligne 1 puis supprime la ligne 2 devenue vide, ajoute une feuille nommée "Feuil2" et testes :

Sub Test()

    Dim Plage As Range
    Dim Lig As Long
    Dim I As Integer
    Dim Tbl

    'ordre de tri
    Tbl = Array(99, "0", "1", "4", "5", "8", "10", "12", "15", "20", "25", "27", "50", "BY", "BI", "B2")

    Application.ScreenUpdating = False

    'feuille de transfert
    Worksheets("Feuil2").Cells.Clear

    With Worksheets("Feuil1")

        'supprime un éventuel filtre
        .AutoFilterMode = False

        'bouche sur les critères...
        For I = 0 To UBound(Tbl)

            'défini la plage sur la colonne D
            Set Plage = .Range(.Cells(1, 4), .Cells(.Rows.Count, 4).End(xlUp))

            'filtrage
            Plage.AutoFilter 1, Tbl(I)

            'recherche de la dernière ligne non vide
            Lig = Worksheets("Feuil2").Cells(.Rows.Count, 1).End(xlUp).Row

            'si c'est la 1, ne fait rien, feuille vide sinon, ajoute 1 pour être sur la première ligne vide
            If Lig > 1 Then Lig = Lig + 1

            'copie du filtrage
            .AutoFilter.Range.EntireRow.Copy Worksheets("Feuil2").Cells(Lig, 1)

            'comme les entêtes suivent le filtrage, supprime après le premier filtre
            If I > 0 Then Worksheets("Feuil2").Cells(Lig, 1).EntireRow.Delete

            'affiche tout pour le filtrage suivant
            Plage.AutoFilter

        Next I

        .AutoFilterMode = False

    End With

    'supprime les valeurs...
    Worksheets("Feuil1").Cells.Clear

    'puis copie du résultat sur la feuille "Feuil1" une fois trié
    With Worksheets("Feuil2")

        .Cells.Copy Worksheets("Feuil1").Cells(1, 1)
        .Cells.Clear

    End With

    Application.ScreenUpdating = True

End Sub

je vais étudier tout de près merci pour votre aide

Bonjour,

On peut peut-être éviter VBA.

Dans la feuille de calcul, faire le tri avec pour ordre, une liste personnalisée. Une fenêtre va s'ouvrir et crée la liste...

(99, B2, BI, BY, 0, 1, etc...)

Attention ! Cette liste est propre au poste...

Cdlt.

bonjour

une formule avec 2 SI()

et un TCD pour faire propre, mais un tri sur place avec les flèches de Tableau font aussi l'affaire

on oublie que les TCD sont les meilleures méthodes de tri

pas de VBA, pas de formule compliquée non plus. De l'Excel fraîchement pressé, pur jus

Hello jmd !

Tu m'excuseras mais je ne trouve pas que ton TCD ait la même gueule que le tableau original trié sur place !

Il est vrai que je demeure toujours quelque peu allergique à l'apparence des TCD, mais tu peux difficilement dire que c'est visuellement identique !

Dans ce cas particulier, je persiste à affirmer que VBA fournit la meilleure solution parce que la plus simple : permet d'ajouter une colonne, laquelle permet de procéder normalement au tri (et c'est toujours Excel qui fait le tri, je te le rappelle), puis on l'efface sans que l'utilisateur ait même eu à constater sa présence. Rien de plus simple.

C'est ce que j'aurais conseillé de faire manuellement à quelqu'un qui ne veut pas entendre parler de VBA, et dans ce cas, il aurait rempli sa colonne temporaire en utilisant une formule. Avec VBA ça se passe en toute transparence, on appuie sur un bouton et le tri est fait !

Pourquoi chercher des complications !

Cordialement.

bonjour à tous,

du coup j'ai regardé la solution de MFerrand mais j'avoue que j'ai du mal à saisir étape par étape ce que fait le code , le niveau est trop haut ^^

du coup je me suis servi du code de Theze à la suite duquel j'ai rajouté quelques lignes pour trier les sacs par catégorie

est le résultat est celui escompté ,

c'est opérationnel même si c'est dommage d'avoir affaire à une feuil2 de transfert

si quelqu'un a une idée pour éviter cela je suis preneuse

je vous mets le code ici en entier

merci à tous

pour la question des tableaux croisés dynamique c'est une bonne idée , mais cette portion de code dont j'ai besoin s'inscrit dans un code plus grand, c'est pour ça que j'ai besoin de gérer cette étape en VBA

Sub Test()

    Dim Plage As Range
    Dim Lig As Long
    Dim i As Integer
    Dim Tbl

    'ordre de tri
    Tbl = Array(99, "0", "1", "4", "5", "8", "10", "12", "15", "20", "25", "27", "50", "BY", "BI", "B2")

    Application.ScreenUpdating = False

    'feuille de transfert
    Worksheets("Feuil2").Cells.Clear

    With Worksheets("EXPORTS")

        'supprime un éventuel filtre
        .AutoFilterMode = False

        'bouche sur les critères...
        For i = 0 To UBound(Tbl)

            'défini la plage sur la colonne D
            Set Plage = .Range(.Cells(1, 4), .Cells(.Rows.Count, 4).End(xlUp))

            'filtrage
            Plage.AutoFilter 1, Tbl(i)

            'recherche de la dernière ligne non vide
            Lig = Worksheets("Feuil2").Cells(.Rows.Count, 1).End(xlUp).Row

            'si c'est la 1, ne fait rien, feuille vide sinon, ajoute 1 pour être sur la première ligne vide
            If Lig > 1 Then Lig = Lig + 1

            'copie du filtrage
            .AutoFilter.Range.EntireRow.Copy Worksheets("Feuil2").Cells(Lig, 1)

            'comme les entêtes suivent le filtrage, supprime après le premier filtre
            If i > 0 Then Worksheets("Feuil2").Cells(Lig, 1).EntireRow.Delete

            'affiche tout pour le filtrage suivant
            Plage.AutoFilter

        Next i

        .AutoFilterMode = False

    End With

    'supprime les valeurs...
   Worksheets("EXPORTS").Cells.Clear

    'puis copie du résultat sur la feuille "Feuil1" une fois trié
    With Worksheets("Feuil2")

        .Cells.Copy Worksheets("EXPORTS").Cells(1, 1)
        .Cells.Clear

    End With

    Application.ScreenUpdating = True

Dim derlg As Long, x As Long
'valeurcible = "99"
With Sheets("EXPORTS")
derlg = .Range("d" & .Rows.Count).End(xlUp).Row
For x = derlg To 1 Step -1
    If .Range("d" & x).Value = 99 Then Exit For
    ligneder99 = Range("d" & x).Row
    colder99 = Range("d" & x).Column

'End If
Next x
'MsgBox .Range("d" & x).Address
ligneder99 = Range("d" & x).Row
colder99 = Range("d" & x).Column

ligne1ersac = ligneder99 + 1
col1ersac = colder99 + 1

'With Sheets("EXPORTS")
derlg = .Range("d" & .Rows.Count).End(xlUp).Row
For x = 27 To derlg
    If .Range("d" & x).Value Like "B*" Then Exit For

'End If
Next x
 ligne1erBB = Range("d" & x).Row - 1
col1erBB = Range("d" & x).Column

'MsgBox .Range("d" & x).Address

End With

  Range(Cells(ligne1ersac, 1), Cells(ligne1erBB, 10)).Sort Key1:=Range("a27"), Order1:=xlAscending

End Sub

Hello jmd !

Tu m'excuseras mais je ne trouve pas que ton TCD ait la même gueule que le tableau original trié sur place !

Il est vrai que je demeure toujours quelque peu allergique à l'apparence des TCD, mais tu peux difficilement dire que c'est visuellement identique !

Dans ce cas particulier, je persiste à affirmer que VBA fournit la meilleure solution parce que la plus simple : permet d'ajouter une colonne, laquelle permet de procéder normalement au tri (et c'est toujours Excel qui fait le tri, je te le rappelle), puis on l'efface sans que l'utilisateur ait même eu à constater sa présence. Rien de plus simple.

C'est ce que j'aurais conseillé de faire manuellement à quelqu'un qui ne veut pas entendre parler de VBA, et dans ce cas, il aurait rempli sa colonne temporaire en utilisant une formule. Avec VBA ça se passe en toute transparence, on appuie sur un bouton et le tri est fait !

Pourquoi chercher des complications !

Cordialement.

salut à tous

MFerrand,

on peut modifier l'aspect d'un TCD, et se rapprocher de très près de la présentation dont on rêve

je viens de jeter un oeill sur le code de Mathylde,

il y a 1832 mille huit-cent trente-deux caractères

comment peux-tu dire que "VBA fournit la meilleure solution parce que la plus simple" ?

Un tel code est très difficile à maîtriser (c'est d'ailleurs pourquoi de (trop) nombreuses questions sur ce forum se rapportent à VBA.

et en plus ce n'est pas stable au cours du temps (versions de Windows, Mac...) Tu le sais bien, mais évidemment étant un expert, tu corriges en quelques heures.

Donc je maintiens qu'il faut autant qu'on peut se passer de VBA. En pratique 100% du temps.

Bonjour à tous,

Je reviens avec ma proposition d'utiliser la fonctionnalité des listes personnalisées.

Une proposition sans VBA mais propre au seul poste de l'utilisateur !...

Celle-ci peut être automatisée, si nécessaire.

Et les procédures de MFerrand et Theze, simplifiées (à vérifier !... ). [Bon, je peux me tromper]

Cdlt.

Bonjour,

A essayer :

Sub TriCond()
    Dim tmp(), aa, i%, k%
    With ActiveSheet.Range("A1").CurrentRegion
        aa = .Value: k = .Columns.Count + 1
    End With
    ReDim tmp(1 To UBound(aa), 0): tmp(1, 0) = "Tmp"
    For i = 2 To UBound(aa)
        If IsNumeric(aa(i, 4)) Then
            tmp(i, 0) = IIf(aa(i, 4) = 99, 1, 2)
        Else
            tmp(i, 0) = 3
        End If
    Next i
    Application.ScreenUpdating = False
    ActiveSheet.Cells(1, k).Resize(UBound(tmp)).Value = tmp
    With ActiveSheet.Range("A1").CurrentRegion
        .Sort key1:=.Cells(1, k), order1:=xlAscending, key2:=.Cells(1, 4), _
         order2:=xlAscending, key3:=.Cells(1, 1), order3:=xlAscending, Header:=xlYes
        .Columns(k).ClearContents
    End With
End Sub

Bouton Test sur la feuille.

NB- Prendre en compte les petites modifications opérées...

Cordialement.

j'ai adapté votre code la manière suivante, ça semble être la meilleure solution (pas de feuille transitoire)

merci beaucoup

  
dernierligneexport = Sheets("exports").Cells(Rows.Count, 1).End(xlUp).Row

  Dim tmp(), aa, i%, k%
    With ActiveSheet.Range("A1").Range(Cells(27, 1), Cells(dernierligneexport, 10))
        aa = .Value: k = .Columns.Count + 1
    End With
    ReDim tmp(1 To UBound(aa), 0): tmp(27, 0) = "Tmp"
    For i = 2 To UBound(aa)
        If IsNumeric(aa(i, 4)) Then
            tmp(i, 0) = IIf(aa(i, 4) = 99, 1, 2)
        Else
            tmp(i, 0) = 3
        End If
    Next i
    Application.ScreenUpdating = False
    ActiveSheet.Cells(27, k).Resize(UBound(tmp)).Value = tmp
    With ActiveSheet.Range("A1").Range(Cells(27, 1), Cells(dernierligneexport, 15))
        .Sort key1:=.Cells(1, k), order1:=xlAscending
        ' , key2:=.Cells(27, 4),
       '  order2:=xlAscending ' , key3:=.Cells(27, 1), order3:=xlAscending, Header:=xlYes
        .Columns(k).ClearContents
    End With

Dim derlg As Long, s As Long
'valeurcible = "99"
With Sheets("EXPORTS")
derlg = .Range("d" & .Rows.Count).End(xlUp).Row
For s = derlg To 1 Step -1
    If .Range("d" & s).Value = 99 Then Exit For
    ligneder99 = Range("d" & s).Row
    colder99 = Range("d" & s).Column

'End If
Next s
'MsgBox .Range("d" & s).Address
ligneder99 = Range("d" & s).Row
colder99 = Range("d" & s).Column

ligne1ersac = ligneder99 + 1
col1ersac = colder99 + 1

'With Sheets("EXPORTS")
derlg = .Range("d" & .Rows.Count).End(xlUp).Row
For s = 27 To derlg
    If .Range("d" & s).Value Like "B*" Then Exit For

'End If
Next s
 ligne1erBB = Range("d" & s).Row - 1
col1erBB = Range("d" & s).Column

'MsgBox .Range("d" & s).Address

End With

'tri des sacs en fonction des SSF
Range(Cells(ligne1ersac, 1), Cells(ligne1erBB, 10)).Sort key1:=Range("a27"), order1:=xlAscending

Bonjour à tous,

@jmd

on peut modifier l'aspect d'un TCD, et se rapprocher de très près de la présentation dont on rêve

Je prendrai certainement le temps un jour de regarder de plus près la manipulation des TCD (en VBA ! ) mais je t'accorde que l'ordre de préséance nécessaire est toujours l'acquisition manuelle avant d'en venir à faire de même en VBA...

Et je suis toujours avec attention les codes de Jean-Eric quand ils touchent à ces outils Excel... Je lui dois déjà d'avoir très nettement amélioré mon approche des ListObjects que j'avais tendance à laisser de côté il y a 2 ou 3 ans...

Un tel code est très difficile à maîtriser (c'est d'ailleurs pourquoi de (trop) nombreuses questions sur ce forum se rapportent à VBA.

VBA souffre certainement du fait qu'on l'a rendu accessible à l'amateurisme (mais pas l'amateurisme éclairé... ), utilisable sans en acquérir un minimum de maîtrise, mais VBA n'y est pour rien...

(Je réserve ce type de développement pour ton sujet sur l'histoire de chacun avec Excel...)

@Jean-Eric : Sur le présent sujet je n'ai pas retenu l'utilisation d'une liste personnalisée, car une telle liste va être vraisemblablement mouvante, les codes de conditionnement ne sont pas limités, d'autres peuvent se rajouter, et en outre Mathylde ayant précisé que le code SSF devait primer sur le code de conditionnement, on se trouve avec un critère principal de tri ne figurant dans aucune colonne !

Ce critère étant ternaire, il demeure relativement simple de générer une colonne en la dotant des 3 valeurs (1, 2 ou 3 !) dévolues à l'application du critère principal de tri, et la faire disparaître après usage... Elle permet d'opérer le tri voulu dans des conditions normales.

@Mathylde : Peut-être n'ai-je pas pris en compte tous les arcanes du tri que tu souhaites... J'avais émis un premier correctif suite à ta remarque et pour l'instant il me paraît que la question demeure sur l'ordonnancement des critères de tri, et qu'on n'a aucun besoin d'en sortir, dès lors qu'on aura clairement défini l'odre d'application...

J'ai donc le sentiment que tes modifications sont plutôt en train de démolir mon code pour le compliquer inutilement (outre le faire déroger aux règles d'écriture que je m'emploie à respecter aussi scrupuleusement que possible... ), mais mon programme du jour ne me laisse pas le temps de m'y pencher immédiatement, je reviendrai donc dans la soirée...

Cordialement.

Bonne journée à tous.

Rechercher des sujets similaires à "methode trie avance"