Une question apparemment simple: quel est le numéro de la dernière ligne valorisée (formule ou constante) d'une colonne ?
Je pense que beaucoup d'entre nous répondraient un truc du genre: DerniereLigneUtilisée = Range("X" & Rows.Count).End(xlUp).Row 'où X est la colonne donnée
ou encore: DerniereLigneUtilisée = ActiveSheet.Columns(X).Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row
SAUF que ça ne marche pas toujours quand par exemple il y a un filtre actif sur la colonne et que la dernière ligne réelle est masquée par le filtre (voir fichier joint).
Donc la question est, à part la méthode "artisanale" employée dans le fichier joint, y a-t-il un autre moyen de connaître cette ligne ?
Merci par avance.
Comparatif des méthodes qui fonctionnent mis à jour en tenant compte des plus récents posts.
Tirée de lointains souvenirs, une fonction personnalisée :
VB:
Function NumDerLig&(plage As Range, Optional relatif)
NumDerLig = Application.Max(Application.IfError(Application.Match("z", plage.Columns(1)), 0), _
Application.IfError(Application.Match(9 ^ 99, plage.Columns(1)), 0))
If NumDerLig > 0 Then If IsMissing(relatif) Then NumDerLig = plage.Row - 1 + NumDerLig
End Function
J'ai supprimé mon message parce qu'en effet la solution avait déjà été donnée.
Voyez le fichier joint, cette solution est sûrement très rapide :
VB:
Function Derlig(colonne As Range)
Dim tablo, i&
Set colonne = colonne.EntireColumn 'sécurité
tablo = colonne.Resize(colonne.Parent.UsedRange.Row + colonne.Parent.UsedRange.Rows.Count) 'matrice, plus rapide, au moins 2 éléments
For i = UBound(tablo) To 1 Step -1
If Not IsEmpty(tablo(i, 1)) Then Derlig = i: Exit Function
Next
End Function
Même pas le courage de tester la solution de @job75 sur ma bécane (31,5° C chez moi, je vais craquer ).
Je pense que la solution de @job75 est la seule pour l'instant qui puisse éliminer la chaine vide. De toute manière, j'ai rarement rencontré des cas où la détermination de la dernière ligne se fait plus d'une fois au cours d'un programme. La durée a donc (selon moi) rarement de l'importance.
On pourrait peut-être déterminer une première limite pour tablo() plus basse (plutôt que celle de UsedRange) mais est-ce bien utile ?
Alors n'utilisons pas de matrice, voyez ce fichier (2) :
VB:
Function Derlig(colonne As Range)
Dim tablo, i&
Set colonne = colonne.EntireColumn.Cells 'sécurité
With colonne.Parent.UsedRange
i = .Row + .Rows.Count - 1
End With
For i = i To 1 Step -1
If Not IsEmpty(colonne(i)) Then Derlig = i: Exit Function
Next
End Function
Avec 140 000 lignes la durée du recalcul de la fonction est maintenant de 19 ms...
J'ai aussi comparé toutes les méthodes que j'ai pu répertorier (voir fichier) exécutées 100 fois sur une colonne de 26 éléments dans un UsedRange de 100.000 lignes.
- Par ColumnDifferences (~ 3.00 sec)
- Par Scan de la colonne (dans le UsedRange) chargée en table mémoire (~2.25 sec)
- Par SpecialCells (~ 2.00 sec)
- Par Match (~0.03 sec)
Donc le Match est pratiquement 100 fois plus rapide (exécuté 1 fois on ne peut même pas détecter sa durée = 0).
La 2ème meilleure méthode est de compter par SpecialCells qui n'a pas la limitation due aux valeurs arbitraires qu'on doit placer dans le Match mais prend quand même plus de 50 fois le temps d'un Match.
re
bonjour @Dudu2
j'ai toujours mis "zzz" et le type (inférieur à) (1)
VB:
Sub test2()
With Application: NumDerLig = .Max(.IfError(.Match("zzz", [A:A], 1), 0), .IfError(.Match(9 ^ 99, [A:A], 1), 0)): End With
MsgBox NumDerLig
End Sub
Ça marche tant que la dernière ligne ne contient pas "zzza" ou un chiffre > 9 ^ 99 (on peut aller jusqu'à 1299 ^99).
Ok "zzza" c'est plus que rare mais j'ai mis String(20 "z") qui ne fait que repousser la limite.
Par contre pour le chiffre j'ai essayé de mettre le plus grand possible (limites Excel) mais il je n'y arrive pas, les 2 derniers chiffres (58) sont tronqués à la saisie pour arriver à 1.79769313486231 * (10 ^ 308).