IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Supprimez des lignes par la méthode Find


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de MarcelG
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    3 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3 449
    Billets dans le blog
    7
    Par défaut Supprimez des lignes par la méthode Find
    Bonjour le Forum,

    Un modeste astuce.

    Pour supprimer les lignes d'une feuille de calcul, s' l'une d'elle contient un mot dans une cellule, il est habituel de
    - considérer la dernière ligne
    - tester le mot
    - supprimer la ligne
    - boucler jusqu'à la première ligne en utilisant un pas négatif de -1.

    Récemment, pour connaître la dernière cellule vide d'une plage, l'ami Patrick m'a suggéré, judicieusement, l'argument Previous sur les cellules - spéciales - vides.

    Dès lors, je me suis demandé comment appliquer ce processus au test décrit ci-dessus.
    Réponse: Méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Public Sub testfindprev()
     
    Dim derlign As Long
    Dim c As Range
    Dim ladress As String
     
    With Worksheets("testprev")
            derlign = .Cells(.Rows.Count, 1).End(xlUp).Row
            With .Range("  A1:A" & derlign)
            Set c = .Find(What:="tata", LookIn:=xlValues, SearchDirection:=xlPrevious)
                If Not c Is Nothing Then
                    Do
                        ladress = c.Address
                        c.EntireRow.Delete
                        Set c = .FindPrevious(After:=.Range(ladress))
                    Loop While Not c Is Nothing
                End If
            End With
            Set c = Nothing
    End With
     
    End Sub
    Nous remarquons ici que l'enregistrement de l'adresse de la ligne à supprimer est obligatoire.

    En effet, coder

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    c.EntireRow.Delete
    Set c = .FindPrevious(After:=c)
    implique une erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1004: Impossible de lire la propriété FindPrevious de la classe Range
    Ce qui est logique du fait de la suppression de la ligne.

    Par avance, je vous remercie pour vos remarques et commentaires.

    En vous souhaitant une agréable journée.

    Marcel

  2. #2
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Bonjour Marcel
    Ne crois-tu pas plus astucieux (et simple et rapide) d'utiliser Find et Findnext pour constituer une plage (avec la méthode Union), puis
    (si P est cette variable range et P n'est pas Nothing) --->>
    ?

  3. #3
    Expert confirmé
    Avatar de MarcelG
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    3 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3 449
    Billets dans le blog
    7
    Par défaut
    Bonjour Unparia,

    Bien noté.
    A vrai dire, je n'y avais pas pensé.
    J'avais en tête cette notion de Previous et le souci, constant même si je parfois cède à la facilité, d'éviter les balayages.
    En règle générale, je préfère utiliser la méthode Find
    Cela dit,
    plus simple
    Il s'agit dans les 2 cas de la combinaison de 2 méthodes Find/FindPrevius et Find/FindNext. Non?
    plus rapide
    .Je pense qu'il faut tester.
    A priori, ce me semble possible, du fait que les lignes sont supprimées en une seule action.

    En toute simplicité, mon post aura au moins cet avantage de mettre en exergue ces deux solutions alternatives.

    Merci!

  4. #4
    Expert confirmé
    Avatar de MarcelG
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    3 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3 449
    Billets dans le blog
    7
    Par défaut
    Bonsoir,

    J'ai voulu tester les performances des différents codes en terme de temps d'exécution.

    L'alimentation de ma feuille de travail a été réalisée - trivialement - par ce code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Option Explicit
     
    Public Sub alim_rng()
     
    Dim i As Long
     
    For i = 1 To 30000 Step 5
            With Worksheets("testprev").Cells(i, 1)
                    .Value = .Row
            End With
    Next i
     
    For i = 1 To 30000
            With Worksheets("testprev").Cells(i, 1)
                    If .Value = "" Then .Value = "tata"
            End With
    Next i
     
    End Sub
    LA méthode "classique" et la méthode "Marcel" ont eu un temps d'exécution similaire : 12 secondes.
    J'en ai été étonné.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    Public Sub test_classique()
     
    Dim derlign As Long, i As Long, n As Long
     
    Dim t As Single
    t = Timer
     
    Application.ScreenUpdating = False
     
    n = 0
    With Worksheets("testprev")
            derlign = .Cells(.Rows.Count, 1).End(xlUp).Row
            For i = derlign To 1 Step -1
                    With .Cells(i, 1)
                            If .Value = "tata" Then
                                    n = n + 1
                                    .EntireRow.Delete
                            End If
                    End With
            Next i
    End With
     
    Debug.Print "Méthode classsique pour " & n & " lignes: " & Timer - t & "secondes"
     
    End Sub
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    Public Sub testfindprev_marcel()
     
    Dim derlign As Long
    Dim c As Range
    Dim ladress As String
     
    Dim t As Single
    Dim n As Long
    t = Timer
     
    Application.ScreenUpdating = False
     
    n = 0
    With Worksheets("testprev")
            derlign = .Cells(.Rows.Count, 1).End(xlUp).Row
            With .Range("A1:A" & derlign)
            Set c = .Find(What:="tata", LookIn:=xlValues, SearchDirection:=xlPrevious)
                If Not c Is Nothing Then
                    Do
                        n = n + 1
                        ladress = c.Address
                        c.EntireRow.Delete
                        Set c = .FindPrevious(After:=.Range(ladress))
                    Loop While Not c Is Nothing
                End If
            End With
            Set c = Nothing
    End With
     
    Debug.Print n & " \ " & Timer - t
     
    End Sub
    Pour la méthode Unparia, le code a généré une erreur
    91 Variable Objet du bloc With non définie
    sur la méthode Loop.
    c est alors Nothing.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    Public Sub testfindprev_unparia()
     
    Dim derlign As Long
    Dim c As Range
    Dim firstaddress As String
    Dim P As Range
     
    Dim t As Single
    t = Timer
     
    Application.ScreenUpdating = False
     
    With Worksheets("testprev")
            derlign = .Cells(.Rows.Count, 1).End(xlUp).Row
            With .Range("A1:A" & derlign)
                    Set c = .Find("tata", LookIn:=xlValues)
                    If Not c Is Nothing Then
                            firstaddress = c.Address
                            Set P = c
                            Do
                                    Set P = Union(P, c)
                                    Set c = .FindNext(c)
                            Loop While Not c Is Nothing And c.Address <> firstaddress
                    End If
                    Set c = Nothing
            End With
    End With
     
    If Not P Is Nothing Then P.EntireRow.Delete
     
    Debug.Print "Méthode Unparia" & P.Count & " \ " & Timer - t
     
    Set P = Nothing
     
    End Sub
    Dans la fenêtre Exécution, j'ai interrogé le nombre d'éléments du Range P alors atteint.
    Résultat: 14255
    Je ne vois pas pourquoi

  5. #5
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Pour la méthode Unparia, le code a généré une erreur
    Ce n'est pas la méthode, qui a généré ton erreur, mais ta manière de l'utiliser.
    Voici (exemple) comment procéder :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     Dim quoi As String, c As Range, p As Range, adr As String
      quoi = "toto" ' ce que l'on recherche
      Set c = ActiveSheet.Range("A:A").Find(what:=quoi)
      Set p = c
        If Not c Is Nothing Then
            adr = c.Address
            Do
                Set c = ActiveSheet.Range("A:A").FindNext(after:=c)
                If Not c Is Nothing Then Set p = Union(p, c)
            Loop Until c Is Nothing Or c.Address = adr
        End If
        MsgBox p.Address
        p.EntireRow.Delete

  6. #6
    Expert confirmé
    Avatar de MarcelG
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2009
    Messages
    3 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2009
    Messages : 3 449
    Billets dans le blog
    7
    Par défaut
    Ce n'est pas la méthode, qui a généré ton erreur, mais ta manière de l'utiliser
    C'est ce que je sous-entendais, bien sûr.

    Quoi qu'il en soit, merci pour ce retour

Discussions similaires

  1. [Débutant] Changer l'intitulé des colonnes et intitulé des lignes par programmes
    Par ammino222002 dans le forum MATLAB
    Réponses: 1
    Dernier message: 22/09/2009, 07h45
  2. Multiplier des lignes par la valeurs d'un champs
    Par Bronks59 dans le forum Développement
    Réponses: 7
    Dernier message: 23/05/2008, 13h33
  3. Trier des lignes par ordre alphabétique ?
    Par Evocatii dans le forum Eclipse
    Réponses: 0
    Dernier message: 11/08/2007, 11h26
  4. Réponses: 3
    Dernier message: 04/07/2007, 21h00
  5. Réponses: 2
    Dernier message: 07/08/2006, 16h43

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