Rien qu'en supprimant manuellement une ligne, c'est évident …
Supposons les premiers zéros se situent en lignes 11 & 12.
En supprimant l'intégralité de la ligne 11 (manuellement comme par code), les lignes suivantes remontent d'un cran,
la ligne 12 devenant la nouvelle ligne 11. Mais dans le code, il y a le Next juste après la suppression,
donc le code passe à la ligne 12 (l'ancienne ligne 13) sans traiter cette nouvelle ligne 11, l'ancienne n°12 …
C'est donc juste logique, à chaque paire de zéros consécutifs, le deuxième n'est pas traité, d'où l'obligation de relancer le code …
Comme vu récemment dans un autre post avec oovaveoo, deux solutions possibles.
La première est une boucle classique, comme dans le code exposé, mais effectuant une remontée au lieu de scanner
les lignes en descente car, lors de la suppression d'une ligne, les suivantes remontant d'un cran ont déjà été traitées !
En passant, des p'tites remarques concernant le code de départ :
- définir une plage via une variable objet pour ne l'utiliser qu'une fois … autant utiliser directement la plage dans le code !
- La boucle scanne l'intégralité de la colonne même si, après la dernière cellule renseignée, beaucoup d'autres sont inutilisées,
que de temps perdu ! (Proust si tu m'entends, …) Pour éviter un tel gâchis, la remontée s'effectue depuis la dernière saisie.
Je préfère de loin une boucle For Each pointant sur les éléments d'une collection mais elle ne peut convenir dans ce cas …
- Une ligne est supprimée si la cellule = 0, et comme cela, tout simplement, et même si c'est logique,
c'est un gouffre se chiffrant non plus en secondes mais en minutes ‼
En effet, Excel considère une cellule vide, sans saisie, comme égale à zéro, le méchant piège ‼
Franchement, vous avez dû trouver le temps long en exécutant votre code car, si par exemple 30 000 cellules vides
suivent la dernière saisie de la colonne, c'est 30 000 suppressions inutiles ‼ Quoique qu'une pause café peut alors se justifier …
Évidemment ce dernier point est aussi pris en compte (moins sensible quand même en remontant à partir de la dernière saisie)
dans la première solution :
Code :
- Sub DelRowIf0()
- With Worksheets("Fichier" )
- For R = .Cells(.Rows.Count, 12).End(xlUp).Row To 1 Step -1
- If .Cells(R, 12) > "" And .Cells(R, 12) = 0 Then .Cells(R, 12).EntireRow.Delete
- Next
- End With
- End Sub
|
La deuxième solution repose sur les méthodes Find et FindNext :
Code :
- Sub Find0DelRow()
- Application.ScreenUpdating = False
- With Worksheets("Fichier" ).Columns(12)
- Set Rg = .Find(0, , xlValues, xlWhole)
- Do Until Rg Is Nothing
- L = Rg.Row + (Rg.Row > 1)
- Rg.EntireRow.Delete
- Set Rg = .FindNext(.Cells(L))
- Loop
- End With
- Application.ScreenUpdating = True
- End Sub
|
A armes égales, le rafraîchissement de l'écran désactivé (ScreenUpdating à False),
la première solution s'avère plus lente que cette dernière, pourtant dotée de plus de code et
tout en scannant l'intégralité de la colonne, comme le vérifie ce tableau de mesures en secondes :
Nombre de zéros Rafraîchissement DelRowIf0 Find0DelRow
Test 1 : 1008 Avec 9,111 7,861
Sans 3,574 2,449
Test 2 : 27 Avec 2,074 0,218
Sans 1,933 0,015 |
Protocole de tests : blocs de 28 cellules dont une à zéro répartis sur plus de 65 000 lignes.
Plus la plage est grande et moins il y a de lignes à supprimer, plus la méthode Find est redoutable de rapidité …
Message édité par Marc L le 21-02-2013 à 17:23:23