Détermination de la dernière ligne REELLE d'une colonne Excel

Résolu
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 - 17 févr. 2016 à 22:13
pijaku Messages postés 12259 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 9 août 2022 - 22 févr. 2016 à 11:43
Bonjour,

Je suis "tombé" sur une discussion ouverte sur un autre site et relative à la détermination de la dernière ligne "réelle" d'une colonne d'une feuille Excel.
Le demandeur entendait par "dernière ligne réelle", la dernière cellule remplie (précédée ou non de lignes vides) d'une colonne, y compris si cette ligne faisait partie de lignes masquées.
Aucune des solutions proposées ne le satisfaisait dans la mesure où :
- certaines n'étaient valables que si la colonne était totalement remplie jusqu'à cette dernière ligne
- d'autres étaient "justes", mais passaient par un tremplin (une autre feuille). Lourd
- d'autres fonctionnaient, mais à condition de faire "harakiri" des lignes masquées (ce qui est gênant) ...
Ce qui m'a par ailleurs étonné, c'est d'une part que ceux qui ont proposé ces solutions boiteuses ne sont pas des débutants et que, d'autre part, des forumeurs à la fois avancés et d'habitude toujours présents n'ont pas proposé de solutions.
Je me suis dans un premier temps interrogé sur l'utilité de la "chose", mais, après réflexion, j'en ai trouvé plus d'une (dans certains cas).
Je m'y suis donc attelé.
Le but, donc : que les lignes visibles ou masquées contiennent ou non une ou plusieurs lignes (voire la totalité) vides, déterminer la dernière ligne remplie, masquée ou non, d'une colonne, quel que soit le nombre de plages masquées présentes.
Voici où j'en suis, qui fonctionne sans faille :
Private Function derlig_reelle(plage As Range) As Long
Dim plage_visible As Range, plageutile As Range, colonne As Long, ou As Long
Application.ScreenUpdating = False
With plage.Worksheet
Set plagevisible = .Columns(plage.Column).SpecialCells(xlCellTypeVisible)
ou = plagevisible.Areas(plagevisible.Areas.Count).Row
If ou = 1 Then
derlig_reelle = .Cells(Rows.Count, plage.Column).End(xlUp).Row
Else
Set plageutile = .Range(.Cells(1, plage.Column), .Cells(ou, plage.Column))
plageutile.EntireRow.Hidden = False
derlig_reelle = .Cells(Rows.Count, plage.Column).End(xlUp).Row
plageutile.EntireRow.Hidden = True
plagevisible.EntireRow.Hidden = False
End If
Application.ScreenUpdating = True
End With
End Function

Fonction appelable ainsi, au gré de chacun (exemples) :
 MsgBox derlig_reelle(Worksheets("Feuil1").Columns(1))
MsgBox derlig_reelle(Worksheets("Feuil1").Columns("A"))
MsgBox derlig_reelle(Worksheets("Feuil2").Range("B:B"))

Un snippet en sera fait, mais pas avant que d'autres ici n'aient cherché une solution éventuellement meilleure.
Je compte sur vous pour tenter de perfectionner (si possible).
Merci d'avance à ceux qui s'y mettront.
-

3 réponses

ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 236
Modifié par ucfoutu le 18/02/2016 à 07:07
Une autre manière de procéder pourrait être celle-ci :
Dim plage_visible As Range, ou As Long, tabl
Application.ScreenUpdating = False
With plage.Worksheet
derlig = .Cells(Rows.Count, plage.Column).End(xlUp).Row
Set plagevisible = .Columns(plage.Column).SpecialCells(xlCellTypeVisible)
ou = plagevisible.Areas(plagevisible.Areas.Count).Row
If derlig >= ou Then
derlig_r = derlig
Else
tabl = .Range(.Cells(1, plage.Column), .Cells(ou, plage.Column))
derlig_r = derlig
For i = UBound(tabl, 1) To 1 Step -1
If tabl(i, 1) <> "" Then derlig_r = i: Exit For
Next
End If
End With
Application.ScreenUpdating = True

Celle-ci présente l'avantage de ne pas jouer au ping-pong avec les lignes visibles et masquées. Son inconvénient est la boucle, qui pourrait être source de ralentissement dans le cas (bien que peu probable) de la présence d'un grand nombre de ligne vides successives.
________________________
Nul ne saurait valablement coder ce qu'il ne saurait exposer clairement.
0
Whismeril Messages postés 17820 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 3 octobre 2022 618
18 févr. 2016 à 09:29
Bonjour Uc, c'est du VBA non?
0
jordane45 Messages postés 36372 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 2 octobre 2022 350 > Whismeril Messages postés 17820 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 3 octobre 2022
18 févr. 2016 à 09:47
Hello Whism.
Oui. Je déplace donc le sujet dans le "bon" forum.
Merci.
0
pijaku Messages postés 12259 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 9 août 2022 14
22 févr. 2016 à 09:45
Bonjour Jacques,

A ma connaissance, il n'y a rien de plus "simple" que la méthode find. Utilisée avec son paramètre SearchDirection réglé sur xlPrevious, elle devrait répondre à ton problème du jour.
Mais, son défaut est de retourner une erreur en cas de "plage" vide. Il suffit alors de tester avec CountA par exemple.

Cela nous donne, en VBA excel, cette fonction :
Private Function DrLig_Reelle(plage As Range) As Long

   If WorksheetFunction.CountA(plage) = 0 Then DrLig_Reelle = 1: Exit Function
   DrLig_Reelle = plage.Find("*", , , , , xlPrevious).Row
End Function

0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 236
22 févr. 2016 à 11:20
Bonjour, Franck,
Il ne m'était (que je suis stupide ...) pas venu à l'idée que la méthode Find était capable également de rechercher parmi les lignes masquées ...
Ta solution est impeccable.
Dépose un petit snippet à ce propos.
Amitiés
0
pijaku Messages postés 12259 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 9 août 2022 14
22 févr. 2016 à 11:43
Dépose un petit snippet à ce propos.
C'est chose faite : ICI

A bientôt
0