Macro Excel: suppression de lignes sous conditions
Résolu/Fermé
cletess
Messages postés
38
Date d'inscription
jeudi 10 janvier 2013
Statut
Membre
Dernière intervention
5 avril 2018
-
10 janv. 2013 à 12:34
cletess Messages postés 38 Date d'inscription jeudi 10 janvier 2013 Statut Membre Dernière intervention 5 avril 2018 - 11 janv. 2013 à 12:50
cletess Messages postés 38 Date d'inscription jeudi 10 janvier 2013 Statut Membre Dernière intervention 5 avril 2018 - 11 janv. 2013 à 12:50
A voir également:
- Macro Excel: suppression de lignes sous conditions
- Telecharger macro convertir chiffre en lettre excel - Télécharger - Tableur
- Liste déroulante excel - Guide
- Si et excel - Guide
- Word et excel gratuit - Guide
- Aller à la ligne excel - Guide
11 réponses
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
10 janv. 2013 à 15:32
10 janv. 2013 à 15:32
Bonjour,
Voici une proposition de macro :
A tester
A+
Voici une proposition de macro :
Sub Supprimer() Dernligne = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row 'initialise les min avec une valeur arbitrairement grande A1min = 10000 A2min = 10000 A3min = 10000 'cherche le minimum pour chaque valeur de A For Ligne = 1 To Dernligne Select Case Cells(Ligne, 1) Case 1 If Cells(Ligne, 2) < A1min Then A1min = Cells(Ligne, 2) L1 = Ligne End If Case 2 If Cells(Ligne, 2) < A2min Then A2min = Cells(Ligne, 2) L2 = Ligne End If Case 3 If Cells(Ligne, 2) < A3min Then A3min = Cells(Ligne, 2) L3 = Ligne End If End Select Next Ligne 'élimine les lignes au delà des L1, L2 et L3 For Ligne = Dernligne To 1 Step -1 If (Cells(Ligne, 1) = 1 And Ligne > L1) Or (Cells(Ligne, 1) = 2 And Ligne > L2) Or (Cells(Ligne, 3) = 3 And Ligne > L3) Then Rows(Ligne).Delete Shift:=xlUp End If Next Ligne End Sub
A tester
A+
cletess
Messages postés
38
Date d'inscription
jeudi 10 janvier 2013
Statut
Membre
Dernière intervention
5 avril 2018
10 janv. 2013 à 15:37
10 janv. 2013 à 15:37
Merci beaucoup pour cette réponse, je teste ça dés demain matin !
Juste une clarification:
Les bases de données dans lesquelles je dois appliquer cette macro ont 56 différentes valeurs de A. Si je comprends bien cette macro, je devrais l'allonger pour chaque valeur de A, c'est bien correct ?
Encore milles fois merci
Juste une clarification:
Les bases de données dans lesquelles je dois appliquer cette macro ont 56 différentes valeurs de A. Si je comprends bien cette macro, je devrais l'allonger pour chaque valeur de A, c'est bien correct ?
Encore milles fois merci
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
Modifié par pilas31 le 10/01/2013 à 15:48
Modifié par pilas31 le 10/01/2013 à 15:48
Oui dans ce cas il est peut-être pertinent d'utiliser des structure de tableau car cela risque d'être pénible de faire un "case" avec 56 valeurs !
J'éssaies de trouver une variante de l'algorithme plus adaptée.
A+
J'éssaies de trouver une variante de l'algorithme plus adaptée.
A+
cletess
Messages postés
38
Date d'inscription
jeudi 10 janvier 2013
Statut
Membre
Dernière intervention
5 avril 2018
10 janv. 2013 à 15:57
10 janv. 2013 à 15:57
https://transvol.sgsi.ucl.ac.be/download.php?id=f030c3823725078f
Pour un exemple plus 'adéquat', voilà un des fichiers que je dois traiter (si vous pouvez y accèder).
Les 56 valeurs sont répertoriées dans la colonne 'Frame' et il faut que les minimums soient calculés sur 'LgObj Z'.
ça peut éventuellement aider pour visualiser !
Les bases de données sont démesurées, sans macro, ça me prends des heures pour faire un fichier et j'en ai 30 à faire :D
Merci beaucoup,
Pour un exemple plus 'adéquat', voilà un des fichiers que je dois traiter (si vous pouvez y accèder).
Les 56 valeurs sont répertoriées dans la colonne 'Frame' et il faut que les minimums soient calculés sur 'LgObj Z'.
ça peut éventuellement aider pour visualiser !
Les bases de données sont démesurées, sans macro, ça me prends des heures pour faire un fichier et j'en ai 30 à faire :D
Merci beaucoup,
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
10 janv. 2013 à 16:11
10 janv. 2013 à 16:11
Ok je regarde par rapport à ma dernière proposition de macro....
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
Modifié par pilas31 le 10/01/2013 à 16:06
Modifié par pilas31 le 10/01/2013 à 16:06
Voila une nouvelle proposition avec un tableau à 56 valeurs qui devrait être plus adaté.
Attention il y a deux prérequis implicites :
Les valeurs de A sont de 1 à 56
Les valeurs minimales sont toujours différentes de zéro
Sinon il faudra modifier le code :
finalement le code est plus simple....
A+
Cordialement,
Attention il y a deux prérequis implicites :
Les valeurs de A sont de 1 à 56
Les valeurs minimales sont toujours différentes de zéro
Sinon il faudra modifier le code :
Sub Supprimer56() Dim Tabmin(56, 2) As Integer Dernligne = Columns(1).Find("*", , , , xlByColumns, xlPrevious).Row 'cherche le minimum pour chaque valeur de A For Ligne = 1 To Dernligne If Cells(Ligne, 2) < Tabmin(Cells(Ligne, 1), 1) Or Tabmin(Cells(Ligne, 1), 1) = 0 Then Tabmin(Cells(Ligne, 1), 1) = Cells(Ligne, 2) Tabmin(Cells(Ligne, 1), 2) = Ligne End If Next Ligne 'élimine les lignes au delà des L1, L2 ....L56 For Ligne = Dernligne To 1 Step -1 If Ligne > Tabmin(Cells(Ligne, 1), 2) Then Rows(Ligne).Delete Shift:=xlUp End If Next Ligne End Sub
finalement le code est plus simple....
A+
Cordialement,
ccm81
Messages postés
10905
Date d'inscription
lundi 18 octobre 2010
Statut
Membre
Dernière intervention
27 décembre 2024
2 429
Modifié par ccm81 le 10/01/2013 à 16:42
Modifié par ccm81 le 10/01/2013 à 16:42
Bonjour à tous les deux
une autre proposition (pour un nombre quelconque de valeurs de A)
https://www.cjoint.com/?3AkqmlR3R3f
bonne suite
une autre proposition (pour un nombre quelconque de valeurs de A)
https://www.cjoint.com/?3AkqmlR3R3f
bonne suite
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
10 janv. 2013 à 16:47
10 janv. 2013 à 16:47
Bonjour
Et une troisième !!!
question:
et si il ya 2 valeurs de pic égale pour un m^me frame ?
Et une troisième !!!
Sub xxxxx() Dim Nbre As Byte, Cptr As Byte Dim Debut As Long, Fin As Long, Ligne As Long, Mini As Double Application.ScreenUpdating = False With Sheets("feuil2") Nbre = Application.Max(.Columns("D")) For Cptr = 1 To Nbre Debut = .Columns("D").Find(Cptr, .Range("D1")).Row Fin = Debut + Application.CountIf(.Columns("D"), Cptr) - 1 Mini = Application.Min(.Range(.Cells(Debut, "S"), .Cells(Fin, "S"))) Ligne = .Columns("S").Find(Mini, .Range("S1")).Row + 1 .Rows(Ligne).Delete Next End With End Sub
question:
et si il ya 2 valeurs de pic égale pour un m^me frame ?
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
10 janv. 2013 à 17:32
10 janv. 2013 à 17:32
Bonjour à vous deux michel et ccm81,
j'ai testé ma macro sur le fichier original qui fait 45849 lignes !!! c'est trés long. de l'ordre de 30 mn.
Je ne sais pas si avec vos propositions les performances sont meilleures..A tester
A+
j'ai testé ma macro sur le fichier original qui fait 45849 lignes !!! c'est trés long. de l'ordre de 30 mn.
Je ne sais pas si avec vos propositions les performances sont meilleures..A tester
A+
ccm81
Messages postés
10905
Date d'inscription
lundi 18 octobre 2010
Statut
Membre
Dernière intervention
27 décembre 2024
2 429
Modifié par ccm81 le 10/01/2013 à 18:00
Modifié par ccm81 le 10/01/2013 à 18:00
re salut à tous
évidemment sur 50000 lignes, ça change tout
une tentative d'optimisation et comme je n'ai qu'excel 2003 ....)
bonne suite
évidemment sur 50000 lignes, ça change tout
une tentative d'optimisation et comme je n'ai qu'excel 2003 ....)
Option Explicit Const lideb = 2 Const coA = "A" Const coB = "B" Private Sub btOK_Click() Dim lifin As Long, li As Long, mini, a, b Dim dico As Object, nudico As Long, nbdico As Long Dim lid As Long, lif As Long, limini As Long, lim As Long Application.ScreenUpdating = False ' ligne de fin lifin = Range(coA & Rows.Count).End(xlUp).Row ' dictionaire des valeurs colonne coA Set dico = CreateObject("Scripting.dictionary") For li = lideb To lifin a = Range(coA & li).Value b = Range(coB & li).Value If Not dico.exists(a) Then dico.Add a, b End If Next li ' nombre de valeurs colonne coA nbdico = dico.Count ' suppression lif = lifin For nudico = nbdico To 1 Step -1 b = dico.Item(nudico) ' ligne de (nudico,b) dans la feuille lid = Range(coB & lideb - 1 & ":" & coB & lif).Find(b, , , xlWhole).Row ' recherche ligne mini pour cette valeur de a mini = Application.Min(Range(coB & lid & ":" & coB & lif)) limini = Range(coB & lid - 1 & ":" & coB & lif).Find(mini, , , xlWhole).Row ' suppression lignes après limini If limini <> lif Then Rows(limini + 1 & ":" & lif).Delete lif = lid - 1 Next nudico Set dico = Nothing Application.ScreenUpdating = True End Sub
bonne suite
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
Modifié par michel_m le 10/01/2013 à 18:51
Modifié par michel_m le 10/01/2013 à 18:51
Pour moi 15,7 sec avec 512 Mo RAM proc 3 ghz
edit: il ya un pb du à une formule dans la colonne D, je regarde
Michel
edit: il ya un pb du à une formule dans la colonne D, je regarde
Michel
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
Modifié par michel_m le 10/01/2013 à 18:53
Modifié par michel_m le 10/01/2013 à 18:53
La macro modifiée
Sub xxxxx() Dim Nbre As Byte, Cptr As Byte, Derlig as Long Dim Debut As Long, Fin As Long, Ligne As Long, Mini As Double Start = Timer 'pour essai Application.ScreenUpdating = False With Sheets("feuil2") derlig = Columns("D").Find("*", , , , , xlPrevious).Row 'supprime les formules dans colonne D T_xx = Application.Transpose(.Range("D2:D" & derlig).Value) .Range("D2:D" & derlig) = Application.Transpose(T_xx) Nbre = Application.Max(.Columns("D")) For Cptr = 1 To Nbre Debut = .Columns("D").Find(Cptr, .Range("D1")).Row Fin = Debut + Application.CountIf(.Columns("D"), Cptr) - 1 Mini = Application.Min(.Range(.Cells(Debut, "S"), .Cells(Fin, "S"))) Ligne = .Columns("S").Find(Mini, .Range("S1")).Row + 1 Rows(Ligne).Delete Next End With MsgBox Timer - Start 'pour essai End Sub
cletess
Messages postés
38
Date d'inscription
jeudi 10 janvier 2013
Statut
Membre
Dernière intervention
5 avril 2018
10 janv. 2013 à 19:01
10 janv. 2013 à 19:01
Cette macro ne supprime-t'elle pas uniquement les lignes dans lesquelles se trouvent les minimums ?
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
11 janv. 2013 à 08:53
11 janv. 2013 à 08:53
Elle supprime la ligne en dessous du minimum comme demandé
Ligne = .Columns("S").Find(Mini, .Range("S1")).Row + 1
Rows(Ligne).Delete
Ligne = .Columns("S").Find(Mini, .Range("S1")).Row + 1
Rows(Ligne).Delete
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
11 janv. 2013 à 09:13
11 janv. 2013 à 09:13
Bonjour michel,
Je crois qu'il faut supprimer toutes les lignes qui suivent une fois que le minimum a été atteint.
Dans l'exemple de la demande initiale, il faut supprimer 2 22 et 2 66.
Mais je pense que ta methode et trés efficace et on doit pouvoir facilement l'adapter en supprimant les lignes de "Ligne" jusqu'a "Fin".
A+
Je crois qu'il faut supprimer toutes les lignes qui suivent une fois que le minimum a été atteint.
Dans l'exemple de la demande initiale, il faut supprimer 2 22 et 2 66.
Mais je pense que ta methode et trés efficace et on doit pouvoir facilement l'adapter en supprimant les lignes de "Ligne" jusqu'a "Fin".
A+
ccm81
Messages postés
10905
Date d'inscription
lundi 18 octobre 2010
Statut
Membre
Dernière intervention
27 décembre 2024
2 429
11 janv. 2013 à 09:39
11 janv. 2013 à 09:39
> michel
je sais bien que la curiosité est un vilain défaut, mais peux tu m'envoyer le fichier à tester au format excel 2003?
merci
cordialement CCM81
je sais bien que la curiosité est un vilain défaut, mais peux tu m'envoyer le fichier à tester au format excel 2003?
merci
cordialement CCM81
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
11 janv. 2013 à 10:05
11 janv. 2013 à 10:05
bonjour,
pour CCM81: Ok je t'envoie ça sans la macro puisque notre ami Pilas31 m'annonce qu'il faut supprimer toutes les lignes
pour Pilas31: en effet, mes yeux vieillissant ...
Donc je reprend le code; il y a aussi des formules dans la colonne T faisant appel à la colonne (celle du mini) d'où de splendides REF sur les lignes...."le" piège
pour CCM81: Ok je t'envoie ça sans la macro puisque notre ami Pilas31 m'annonce qu'il faut supprimer toutes les lignes
pour Pilas31: en effet, mes yeux vieillissant ...
Donc je reprend le code; il y a aussi des formules dans la colonne T faisant appel à la colonne (celle du mini) d'où de splendides REF sur les lignes...."le" piège
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
11 janv. 2013 à 10:39
11 janv. 2013 à 10:39
Re
ci joint le classeur 2003
https://www.cjoint.com/?3AlkI22h5sa
La macro est corrigée mais quelques vérifs à faire
ci joint le classeur 2003
https://www.cjoint.com/?3AlkI22h5sa
La macro est corrigée mais quelques vérifs à faire
cletess
Messages postés
38
Date d'inscription
jeudi 10 janvier 2013
Statut
Membre
Dernière intervention
5 avril 2018
11 janv. 2013 à 10:55
11 janv. 2013 à 10:55
Tout juste 3 secondes pour un fichier de 75.000 lignes ...
Je suis impressionné ! Merci infiniment !
Je suis impressionné ! Merci infiniment !
michel_m
Messages postés
16603
Date d'inscription
lundi 12 septembre 2005
Statut
Contributeur
Dernière intervention
16 décembre 2023
3 310
11 janv. 2013 à 10:59
11 janv. 2013 à 10:59
La macro corrigée en espèrant que.... (je vais bruler un cierge à l'église du coin) :o)
curieux durée 8 sec au lieu de 15 ... ?
curieux durée 8 sec au lieu de 15 ... ?
Sub xxxxx() Dim Derlig As Long, Nbre As Byte, Cptr As Byte Dim Debut As Long, Fin As Long, Ligne As Long, Mini As Double Dim start As Single start = Timer 'pour essai rapidité à supprimer Application.ScreenUpdating = False With Sheets("feuil2") 'supprime les formules dans colonne D Derlig = Columns("D").Find("*", , , , , xlPrevious).Row 'supprime les formules dans colonne D T_xx = Application.Transpose(.Range("D2:D" & Derlig).Value) .Range("D2:D" & Derlig) = Application.Transpose(T_xx) Nbre = Application.Max(.Columns("D")) 'nombre de frame For Cptr = 1 To Nbre 'recherche le pic mini de chaque frame Debut = .Columns("D").Find(Cptr, .Range("D1")).Row Fin = Debut + Application.CountIf(.Columns("D"), Cptr) - 1 Mini = Application.Min(.Range(.Cells(Debut, "S"), .Cells(Fin, "S"))) 'détruit les lignes sous le mini jusquau changement de frame Ligne = .Columns("S").Find(Mini, .Range("S1")).Row 'Si la ligne du mini n'est pas la dernière ligne du frame If Ligne <> Fin Then Rows(CStr(Ligne + 1) & ":" & CStr(Fin)).Delete Next 'recopie la formule colonne T Derlig = Columns("D").Find("*", , , , , xlPrevious).Row Range("T3").AutoFill Destination:=Range("T3:T" & Derlig) End With MsgBox Timer - start 'pour essai rapidité à supprimer End Sub
pilas31
Messages postés
1825
Date d'inscription
vendredi 5 septembre 2008
Statut
Contributeur
Dernière intervention
24 avril 2020
644
11 janv. 2013 à 12:14
11 janv. 2013 à 12:14
Re bonjour à vous deux,
Moi je ne suis plus dans la course, 8 secondes, 5 secondes, vous êtes des champions de l'optimisation !!!
Par contre michel j'ai un doute sur cette séquence :
'détruit les lignes sous le mini jusquau changement de frame
Ligne = .Columns("S").Find(Mini, .Range("S1")).Row
Je me demande si il ne faut pas plutot écrire..
Ligne = .Columns("S").Find(Mini, .Range("S" & Debut - 1)).Row
A votre avis
Moi je ne suis plus dans la course, 8 secondes, 5 secondes, vous êtes des champions de l'optimisation !!!
Par contre michel j'ai un doute sur cette séquence :
'détruit les lignes sous le mini jusquau changement de frame
Ligne = .Columns("S").Find(Mini, .Range("S1")).Row
Je me demande si il ne faut pas plutot écrire..
Ligne = .Columns("S").Find(Mini, .Range("S" & Debut - 1)).Row
A votre avis
ccm81
Messages postés
10905
Date d'inscription
lundi 18 octobre 2010
Statut
Membre
Dernière intervention
27 décembre 2024
2 429
Modifié par ccm81 le 11/01/2013 à 12:01
Modifié par ccm81 le 11/01/2013 à 12:01
re
> michel
Merci pour le fichier 2003, ça m'a permis de corriger quelques erreurs et de tester.
Au passage je t'ai pompé la suppression et la recopie des formules (re-merci)
Durée 5.5 s (sur un 2Ghz)
cordialement
> michel
Merci pour le fichier 2003, ça m'a permis de corriger quelques erreurs et de tester.
Au passage je t'ai pompé la suppression et la recopie des formules (re-merci)
Durée 5.5 s (sur un 2Ghz)
Option Explicit Const lideb = 2 Const coA = "D" Const coB = "S" Private Sub btOK_Click() Dim lifin As Long, li As Long, mini, a Dim dico As Object, nudico As Long, nbdico As Long Dim lid As Long, lif As Long, limini As Long Dim t, T_xx t = Timer Application.ScreenUpdating = False ' ligne de fin lifin = Range(coA & Rows.Count).End(xlUp).Row 'supprime les formules dans colonne coA T_xx = Application.Transpose(Range(coA & lideb & ":" & coA & lifin).Value) Range(coA & lideb & ":" & coA & lifin) = Application.Transpose(T_xx) ' dictionaire des valeurs colonne coA Set dico = CreateObject("Scripting.dictionary") For li = lideb To lifin a = Range(coA & li).Value If Not dico.exists(a) Then dico.Add a, 1 End If Next li ' nombre de valeurs colonne coA nbdico = dico.Count ' suppression lif = lifin For nudico = nbdico To 1 Step -1 ' ligne de a dans la feuille lid = Range(coA & lideb - 1 & ":" & coA & lif).Find(nudico, , , xlWhole).Row ' recherche ligne mini pour cette valeur de a mini = Application.Min(Range(coB & lid & ":" & coB & lif)) limini = Range(coB & lid - 1 & ":" & coB & lif).Find(mini, , , xlWhole).Row ' suppression lignes après limini If limini <> lif Then Rows(limini + 1 & ":" & lif).Delete lif = lid - 1 Next nudico Set dico = Nothing 'recopie la formule colonne T lifin = Columns(coA).Find("*", , , , , xlPrevious).Row Range("T3").AutoFill Destination:=Range("T3:T" & lifin) Application.ScreenUpdating = True MsgBox Timer - t & " s" End Sub
cordialement
cletess
Messages postés
38
Date d'inscription
jeudi 10 janvier 2013
Statut
Membre
Dernière intervention
5 avril 2018
11 janv. 2013 à 12:50
11 janv. 2013 à 12:50
Les deux fonctionnent à merveille maintenant:
3.7 sec pour celle de Ccm81 et 3.5 pour celle de Michel avec la correction.
Vous me tirez une épine d'une taille incroyable hors du pied ! Merci beaucoup encore à tous les trois !
CL
3.7 sec pour celle de Ccm81 et 3.5 pour celle de Michel avec la correction.
Vous me tirez une épine d'une taille incroyable hors du pied ! Merci beaucoup encore à tous les trois !
CL