1. #1
    Membre chevronné
    Femme Profil pro
    Étudiant
    Inscrit en
    octobre 2016
    Messages
    1 336
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2016
    Messages : 1 336
    Points : 2 147
    Points
    2 147

    Par défaut Filtre et suppression de lignes VBA

    Bonjour,

    Je ne connais pas bien la rubrique "Contribuez" sur le forum, mais je tente ... J'ai remarqué qu'une question (cf. plus bas) était très souvent posée sur le forum. Je me suis dit que ce serait donc intéressant d'écrire une petite explication par rapport à cette question. N'hésitez pas à me dire si la démarche n'est pas tout à fait correcte


    Sur le forum VBA, il y a souvent la question/l'étonnement suivant :
    J'ai fait une boucle dans laquelle je supprime des lignes selon un critère, mais toutes les lignes répondant au critère ne sont pas supprimées.
    Bien souvent, il est plus efficace de passer par les filtres automatiques pour faire ce type d'opération, mais dans la première partie de cet exposé, je vais d'abord expliquer pourquoi le problème soulevé ci-dessus apparaît.
    NB.: l'explication vaut pour la suppression de lignes, mais elle est aussi vraie pour l'insertion de lignes.

    1. Suppression de lignes avec une boucle.
    Supposons que nous voulions supprimer les lignes contenant A de la liste suivante :
    Nom : list debut.png
Affichages : 73
Taille : 1,5 Ko
    Une personne faisant la remarque citée au début aura fait le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Dim i As Long
    For i = 1 To 6
        If Range("A" & i).Value = "A" Then Rows(i).Delete
    Next i
    Suivons pas à pas ce que fait ce code :
    1. i = 1, on vérifie si A1 vaut A --> non : on ne fait rien.
    2. i = 2, on vérifie si A2 vaut A --> oui : on supprime la ligne. La liste devient :
      Nom : liste apres.png
Affichages : 73
Taille : 1,5 Ko
    3. i = 3, on vérifie si A3 vaut A --> non : on ne fait rien.

    Et là, c'est le drame ! On a sauté un "A". Pourquoi ? Parce qu'en supprimant une ligne, on a décalé toutes les lignes en dessous vers le haut. Ainsi, la ligne 3 se trouve en ligne 2 etc ... Mais l'itération de la boucle For continue : on passe bien de i = 2 à i = 3.
    Pour éviter ce problème, il faut faire la boucle en sens inverse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Dim i As Long
    For i = 6 To 1 Step -1
        If Range("A" & i).Value = "A" Then Rows(i).Delete
    Next i
    Suivons pas à pas ce que fait ce code :
    1. i = 6, on vérifie si A6 vaut A --> non : on ne fait rien.
    2. i = 5, on vérifie si A5 vaut A --> non : on ne fait rien.
    3. i = 4, on vérifie si A4 vaut A --> non : on ne fait rien.
    4. i = 3, on vérifie si A3 vaut A --> oui : on supprime la ligne. La liste devient :
      Nom : liste apres.png
Affichages : 73
Taille : 1,5 Ko
    5. i = 2, on vérifie si A2 vaut A --> oui : on supprime la ligne.
    6. i = 1, on vérifie si A1 vaut A --> non : on ne fait rien

    Et vous voyez qu'on a bien visité toutes les cellules de la colonne A.

    2. Suppression de ligne avec le filtre automatique (à partir d'XL2007)
    Intuitivement, on effectue une boucle pour supprimer des lignes selon un critère. Mais avec Excel-VBA, il existe une méthode plus rapide et efficace : très intéressant s'il y a beaucoup de lignes à vérifier ! Pour cela, on peut utiliser les filtres automatiques. Avec l'enregistreur de macro, on retrouve rapidement la façon de les utiliser en VBA : Range.AutoFilter.
    Voici ce que nous allons faire :
    1. Filtrer sur la valeur à éliminer
    2. Supprimer les lignes restantes (donc celles qui contiennent la valeur à éliminer)
    3. Enlever le filtre pour ne voir que les valeurs non éliminées.

    Avant d'effectuer cela, on ajoute un en-tête à nos données :
    Nom : entete.png
Affichages : 73
Taille : 1,9 Ko
    Puis, on utilise AutoFilter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range("A1:A7").AutoFilter Field:=1, Criteria1:="A"
    Ceci va filtrer notre liste pour ne garder que les "A".
    Ensuite, il ne reste plus qu'à supprimer ces lignes :
    Et enfin, on n'oublie pas d'enlever le filtre (car maintenant, il n'y a plus de "A", donc si on filtre sur "A", on ne verra plus rien ...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Range("A1:A7").AutoFilter Field:=1
    Bien sûr, il est possible de filtrer sur plusieurs critères et sur plusieurs colonnes avant de supprimer les lignes. Tout ceci se découvre facilement avec l'enregistreur de macro.

    J'espère que ce petit message vous aura aidé à comprendre comment supprimer des lignes selon un critère.
    A bientôt sur le forum !

  2. #2
    Expert éminent sénior
    Avatar de patricktoulon
    Profil pro
    Inscrit en
    avril 2009
    Messages
    9 779
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Secteur : Bâtiment

    Informations forums :
    Inscription : avril 2009
    Messages : 9 779
    Points : 15 733
    Points
    15 733
    Billets dans le blog
    1

    Par défaut re

    Bonjour riaolle
    plutôt sympa pour une première contrib

    mais tu as oublié de parler d' un épisode important au niveau de ton paragraphe pour le delete après le filtre
    en effet tu ne démontre pas comment on obtient les lignes
    les lecteurs non avertis et débutants s'en trouveraient dépointés et ne comprendraient pas
    je te suggère donc de rectifier ce petit oubli

    peut être(surement même ) leur parler de "specialcells" et de xlCellTypeVisible

    oupss je l'ai dis

    a+
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : résolu: ça peut servir aux autres
    et n'oublie pas de voter

  3. #3
    Membre chevronné
    Femme Profil pro
    Étudiant
    Inscrit en
    octobre 2016
    Messages
    1 336
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2016
    Messages : 1 336
    Points : 2 147
    Points
    2 147

    Par défaut

    Bonjour patricktoulon,
    Lorsqu'on utilise Delete après avoir appliqué un filtre automatique (AutoFilter), pas besoin d'utiliser SpecialCells(xlCellTypeVisible) : c'est l'avantage du filtre. Delete, par défaut, ne va supprimer que les lignes visibles. Cela vaut aussi pour le copier-coller, par exemple.
    Petit exemple rapide :
    Nom : filtre delete.png
Affichages : 47
Taille : 49,8 Ko
    Si je me souviens bien, c'est Menhir qui m'avais fait la remarque, un jour où je voulais utiliser SpecialCells(xlCellTypeVisible), moi aussi

  4. #4
    Expert éminent sénior
    Avatar de patricktoulon
    Profil pro
    Inscrit en
    avril 2009
    Messages
    9 779
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Secteur : Bâtiment

    Informations forums :
    Inscription : avril 2009
    Messages : 9 779
    Points : 15 733
    Points
    15 733
    Billets dans le blog
    1

    Par défaut re

    OK je veux bien te croire
    si je comprends bien tu travaille a l'envers
    tu filtre avec un critères et c'est les cellules correspondant au critère que tu supprime
    ca doit effectivement simplifier les code après filtres


    il faudrait le préciser ce point dans un paragraphe explicite car en général c'est la méthode inverse qui est employée
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : résolu: ça peut servir aux autres
    et n'oublie pas de voter

  5. #5
    Expert éminent sénior
    Avatar de patricktoulon
    Profil pro
    Inscrit en
    avril 2009
    Messages
    9 779
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Secteur : Bâtiment

    Informations forums :
    Inscription : avril 2009
    Messages : 9 779
    Points : 15 733
    Points
    15 733
    Billets dans le blog
    1

    Par défaut re

    bon c'est bien ce que je pensais j'ai testé 2 critères "<" & ">" sur les dates ou des nombres ( comme dans une récente discussion)
    et comme tu travaille avec les cellule a rejeter j'ai donc inverser les critères
    et malheureusement le filtre ne fonctionne pas
    c'est donc une méthode utilisable uniquement sur une comparaison string stricte
    intéressant tout de même
    tu n'a qu'a faire un test sur une série de nombre et récupérer une partie entre le plus petit et le plus grand tu verra
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : résolu: ça peut servir aux autres
    et n'oublie pas de voter

  6. #6
    Membre chevronné
    Femme Profil pro
    Étudiant
    Inscrit en
    octobre 2016
    Messages
    1 336
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2016
    Messages : 1 336
    Points : 2 147
    Points
    2 147

    Par défaut

    Désolée, je ne suis pas sûre de bien comprendre ton problème
    J'ai essayé ceci :
    Nom : filtre.png
Affichages : 44
Taille : 40,3 Ko

  7. #7
    Expert éminent sénior
    Avatar de patricktoulon
    Profil pro
    Inscrit en
    avril 2009
    Messages
    9 779
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Secteur : Bâtiment

    Informations forums :
    Inscription : avril 2009
    Messages : 9 779
    Points : 15 733
    Points
    15 733
    Billets dans le blog
    1

    Par défaut re

    et oui tu n'a pas compris a ce que je vois


    j'ai une série de 1 a 50 je veux garder tout ce qui part de 25 jusqu'a 35 et bien essaie avec ta méthode

    j'ai fait un erreur en parlant de string stricte c'est plutôt valeur stricte(text ou numerique)

    a partir du moment ou je veux appliquer ta methode
    le critères du filtre doivent prendres les cellule a rejeter
    manque de pot dans le cadre ou je desire recuperer une fourchette entre deux nombres par exemple les critères devront etre
    <min voulu &>0 &>max voulu
    manque de pot les critères sont contradictoire tu le comprends bien et donc le filtre Walouh Walouh!!!
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : résolu: ça peut servir aux autres
    et n'oublie pas de voter

  8. #8
    Membre chevronné
    Femme Profil pro
    Étudiant
    Inscrit en
    octobre 2016
    Messages
    1 336
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 22
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2016
    Messages : 1 336
    Points : 2 147
    Points
    2 147

    Par défaut

    Est-ce que là, j'ai compris ?
    Nom : filtre.png
Affichages : 44
Taille : 29,4 Ko
    Est-ce le problème de l'opérateur ? And ou Or ?

  9. #9
    Expert éminent sénior
    Avatar de patricktoulon
    Profil pro
    Inscrit en
    avril 2009
    Messages
    9 779
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Secteur : Bâtiment

    Informations forums :
    Inscription : avril 2009
    Messages : 9 779
    Points : 15 733
    Points
    15 733
    Billets dans le blog
    1

    Par défaut re

    oui la ligne de filtre est logique mais ca ne peut pas marcher avec and ou or ou xor

    pour la simple et bonne raison que le critères 1 est contradictoire avec le critères 2 dans le cadre ou tu veux que le filtre affiche ce qui est avant et ce qui est après
    tu comprends ou pas ?

    ton criteres2 dit "ce qui est après 35" on est d'accords?
    il ecrase donc le critères 1 qui dit lui "avant 25"

    tandis que si j'utilise le filtre normalement

    le critere1 dirais ">=25" et le critere2 dirait "<=35" et la on garde la série
    et le critere2 n'écrase pas le critere 1 car " >25" reste toujours dans le cadre "<35"

    mais comme ton astuce du rows(....).delete est basé sur les rows visible tu vois le shmilblik

    il te faut faire donc ce que j'ai fait dans cette discutionset cette reponse a savoir inverser la plage résultat du filtre et plage complète en terme de visible/hdden)

    edit:
    autant pour moi le xlor fonctionne visiblement chez moi sous cette forme de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Sub test()
        derlig = Cells(Rows.Count, 1).End(xlUp)
       Set plage = Range("A3", Cells(derlig, 1))
        critere1 = 25
        critere2 = 35
     
         With plage
            .AutoFilter Field:=1, Criteria1:="<" & critere1, Operator:=xlOr, Criteria2:=">" & critere2
            Rows(plage.Row + 1 & ":" & plage.Row + plage.Rows.Count - 1).Delete
            .AutoFilter Field:=1
        .AutoFilter
        End With
    End Sub
    je merite un coup de tapette a mouche
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : résolu: ça peut servir aux autres
    et n'oublie pas de voter

Discussions similaires

  1. [VBA Excel] Pb Suppression de lignes non filtrées
    Par Filippo dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 25/09/2008, 11h55
  2. [VBA-E] Problème de suppression de lignes
    Par coxi77 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 28/07/2006, 14h01
  3. [VBA-E] Suppression de lignes à partir d'un point particulier
    Par coxi77 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 26/07/2006, 13h22
  4. [VBA]Excel - Suppression de ligne
    Par Jseb de Lyon dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 29/01/2006, 15h22
  5. [Excel - VBA] Problème de suppression de lignes...
    Par beholder2 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 28/01/2005, 17h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo