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 99soit 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 SubBouton 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:=xlYesCordialement.
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 Subje 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 SubHello 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 !...
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 SubBouton 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:=xlAscendingBonjour à 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 !
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é...
(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...
Cordialement.
Bonne journée à tous.