
# Trouver la dernière ligne non vide en VBA rapidement
L’identification de la dernière ligne utilisée dans une feuille Excel représente l’une des opérations les plus fréquentes en programmation VBA. Que vous développiez une macro pour automatiser l’insertion de données, générer des rapports dynamiques ou nettoyer des bases de données volumineuses, connaître précisément où se termine votre jeu de données constitue un prérequis fondamental. Pourtant, cette tâche apparemment simple cache de nombreux pièges techniques qui peuvent compromettre la fiabilité de vos applications. Entre les cellules formatées mais vides, les plages discontinues et les différences de performance entre méthodes, vous devez maîtriser les subtilités de chaque approche pour construire des solutions robustes et performantes.
Les méthodes natives VBA pour identifier la dernière ligne utilisée
Excel VBA propose plusieurs approches natives pour déterminer la dernière ligne contenant des données. Chacune présente des caractéristiques distinctes en termes de précision, de performance et de fiabilité selon le contexte d’utilisation. Comprendre ces différences vous permettra de choisir la méthode la plus adaptée à votre situation spécifique.
La propriété Range.End(xlUp) et son exploitation optimale
La méthode Range.End(xlUp) constitue l’approche la plus répandue pour identifier la dernière ligne non vide d’une colonne. Son fonctionnement imite le raccourci clavier Ctrl+Flèche, partant d’une cellule de référence pour se déplacer jusqu’à la première cellule non vide rencontrée. L’implémentation classique s’écrit ainsi : derniereLigne = Cells(Rows.Count, 1).End(xlUp).Row. Cette instruction part de la toute dernière ligne de la feuille (1 048 576 pour Excel 2007 et versions ultérieures) dans la colonne A, puis remonte jusqu’à trouver une donnée.
L’avantage principal de cette méthode réside dans sa rapidité d’exécution et sa simplicité syntaxique. Elle fonctionne parfaitement lorsque votre colonne de référence ne contient aucune cellule vide au milieu des données. Toutefois, vous devez rester vigilant : si des cellules vides existent dans la plage, la méthode s’arrêtera à la première cellule non vide rencontrée en remontant, ce qui peut ne pas correspondre à la véritable dernière ligne de votre tableau. Pour cette raison, il est recommandé de choisir une colonne servant de clé primaire dans votre base de données, c’est-à-dire une colonne garantissant une valeur sur chaque ligne utilisée.
Une variante consiste à utiliser la notation avec une lettre de colonne : Range("A" & Rows.Count).End(xlUp).Row. Cette syntaxe offre une meilleure lisibilité lorsque vous travaillez avec des colonnes spécifiques identifiées par leur lettre. Pour obtenir la première ligne vide suivant vos données, il suffit d’ajouter 1 au résultat : premiereLigneVide = Cells(Rows.Count, 1).End(xlUp).Row + 1. Cette valeur s’avère particulièrement utile lors de l’insertion de nouvelles entrées dans une base de données existante.
La méthode Cells.Find avec SearchDirection:=xlPrevious
La méthode Find représente une alternative puissante et extrêmement flexible pour localiser la dernière cellule contenant des données dans
la feuille, sans se limiter à une colonne précise. En combinant Cells.Find avec le paramètre SearchDirection:=xlPrevious, vous pouvez rechercher la dernière cellule non vide dans tout le UsedRange de la feuille :
Dim ws As WorksheetDim c As RangeDim derniereLigne As LongSet ws = ActiveSheetSet c = ws.Cells.Find(What:="*", _ After:=ws.Cells(1, 1), _ LookIn:=xlFormulas, _ LookAt:=xlPart, _ SearchOrder:=xlByRows, _ SearchDirection:=xlPrevious, _ MatchCase:=False)If Not c Is Nothing Then derniereLigne = c.RowElse derniereLigne = 0 'feuille entièrement videEnd If
Ici, nous cherchons n’importe quel contenu ("*") en balayant la feuille par lignes (SearchOrder:=xlByRows) et en partant de la fin vers le début (SearchDirection:=xlPrevious). L’avantage est que cette méthode ne dépend pas d’une colonne de référence : la dernière ligne non vide sera trouvée même si vos données sont réparties sur plusieurs colonnes. Elle est particulièrement pratique pour des feuilles de calcul « vivantes » sur lesquelles plusieurs modules VBA ou utilisateurs écrivent dans différentes zones.
Vous pouvez adapter le paramètre LookIn pour affiner la recherche : xlFormulas tient compte des formules et de leurs résultats, tandis que xlValues se concentre sur les valeurs affichées. En pratique, xlFormulas reste plus robuste pour détecter la dernière ligne utilisée, surtout lorsque des formules renvoient des chaînes vides. Gardez en tête que Find conserve certains paramètres entre deux appels : il est donc préférable de toujours spécifier tous les arguments importants pour éviter des comportements inattendus.
L’utilisation de UsedRange et ses limitations techniques
La propriété UsedRange fournit une vision globale de la zone « utilisée » d’une feuille : elle englobe toutes les cellules qui ont, à un moment ou à un autre, contenu une valeur, une formule ou une mise en forme. Pour obtenir la dernière ligne non vide via UsedRange, la syntaxe classique ressemble à ceci :
Dim ws As WorksheetDim derniereLigne As LongSet ws = ActiveSheetWith ws.UsedRange derniereLigne = .Rows(.Rows.Count).RowEnd With
Cette approche peut sembler idéale : une seule ligne de code, un résultat immédiat, et aucune notion de colonne de référence. Pourtant, dans la pratique, UsedRange est souvent source de confusion. La raison principale vient du fait qu’Excel considère comme « utilisée » toute cellule qui a reçu une mise en forme, un bordure, une couleur ou une validation de données, même si son contenu a été effacé par la suite.
Concrètement, si vous coloriez la cellule G500000 puis que vous supprimez son contenu, UsedRange étendra toujours sa limite jusqu’à cette cellule tant que la mise en forme reste présente. Résultat : la « dernière ligne utilisée » peut pointer bien plus bas que la dernière vraie donnée. Dans un contexte de recherche de dernière ligne non vide pour insérer des données, cela peut vous faire perdre en précision et vous amener à travailler sur des lignes inutilement éloignées du tableau réel.
Autre point important : UsedRange n’est pas automatiquement rafraîchi après certaines opérations (comme la suppression de lignes ou colonnes entières). Il peut donc conserver une trace « fantôme » d’anciennes données. Vous pouvez parfois forcer sa mise à jour en enregistrant puis rouvrant le fichier, mais cela reste peu pratique dans un scénario d’automatisation VBA. C’est pourquoi UsedRange convient plutôt à des diagnostics globaux ou à des macros de nettoyage, qu’à la détermination précise de la dernière ligne non vide.
La propriété SpecialCells(xlCellTypeLastCell) et ses pièges
Une autre méthode souvent citée pour trouver la dernière cellule utilisée est d’exploiter la propriété SpecialCells(xlCellTypeLastCell). Celle-ci retourne la cellule située à l’extrémité inférieure droite de la feuille, telle qu’Excel la considère comme dernière cellule utilisée :
Dim ws As WorksheetDim derniereLigne As LongSet ws = ActiveSheetOn Error Resume NextderniereLigne = ws.Cells.SpecialCells(xlCellTypeLastCell).RowOn Error GoTo 0
À première vue, cette solution semble élégante : une seule instruction permet de récupérer la dernière ligne non vide d’une feuille. Toutefois, elle partage exactement les mêmes problèmes que UsedRange. En réalité, xlCellTypeLastCell se base sur le même mécanisme interne qu’UsedRange pour déterminer la zone utilisée. Par conséquent, toute mise en forme résiduelle ou cellule ayant contenu des données par le passé va fausser le résultat.
Un autre piège concerne les feuilles nouvellement créées ou entièrement vides : selon le contexte, SpecialCells(xlCellTypeLastCell) peut lever une erreur de type « aucune cellule trouvée ». C’est la raison pour laquelle il est courant d’encadrer cet appel par un On Error Resume Next. Mais masquer l’erreur ne résout pas le problème de fond : vous obtenez une information dont la fiabilité est discutable pour localiser précisément la dernière ligne contenant une vraie donnée exploitable.
Dans un scénario de production, il est donc recommandé de réserver xlCellTypeLastCell à des macros de diagnostic ou de maintenance, par exemple pour analyser la taille réelle d’un classeur avant de l’optimiser. Pour déterminer la dernière ligne non vide en VBA rapidement et de manière fiable, privilégiez Range.End(xlUp) ou Cells.Find, et considérez SpecialCells(xlCellTypeLastCell) comme une solution de secours plutôt que comme méthode principale.
Optimisation des performances avec Range.End versus Cells.Find
Analyse comparative des temps d’exécution sur grands datasets
Lorsque vous travaillez sur de grands fichiers Excel (plusieurs centaines de milliers de lignes), la performance des macros devient un enjeu majeur. L’identification de la dernière ligne non vide en VBA étant souvent appelée dans des boucles, chaque milliseconde compte. Comment Range.End(xlUp) se comporte-t‑il face à Cells.Find sur de gros volumes de données ?
Dans la plupart des tests empiriques réalisés sur des jeux de données dépassant 100 000 lignes, Range.End(xlUp) se révèle légèrement plus rapide lorsqu’on connaît déjà la colonne de référence. La raison est simple : l’algorithme interne d’Excel n’a qu’une seule colonne à parcourir, en partant de la fin vers le haut, ce qui est extrêmement optimisé. Cells.Find, de son côté, doit analyser une plage plus large, ce qui ajoute un surcoût, surtout lorsque le UsedRange couvre plusieurs dizaines de colonnes.
Cependant, la différence de temps d’exécution reste souvent marginale à l’échelle d’un appel isolé (quelques millisecondes de plus ou de moins). Là où l’écart devient significatif, c’est lorsqu’on exécute la recherche de dernière ligne non vide des milliers de fois dans une boucle imbriquée. Dans ce cas, une mauvaise stratégie peut faire passer un traitement de quelques secondes à plusieurs minutes. Une approche courante consiste donc à calculer la dernière ligne une seule fois, à stocker le résultat dans une variable, puis à réutiliser cette variable plutôt que de rappeler systématiquement End(xlUp) ou Find.
Par analogie, imaginez que vous deviez vérifier l’adresse d’un entrepôt avant chaque livraison : si vous la recherchez sur Internet à chaque fois, vous perdez un temps considérable. Notez-la une bonne fois pour toutes et réutilisez-la tant que les données n’ont pas changé. La même logique s’applique à la dernière ligne non vide : calculez-la au début de votre macro, sauf si vous ajoutez ou supprimez des lignes en cours de route, et ne recalculer qu’en cas de besoin réel.
Impact de la mémoire cache et du calcul automatique excel
Au-delà de l’algorithme utilisé, d’autres facteurs influencent la rapidité de la recherche de dernière ligne en VBA : la gestion de la mémoire cache par Excel et le mode de calcul des formules. Lorsque le calcul automatique est activé (Application.Calculation = xlCalculationAutomatic), chaque modification de cellule peut déclencher un recalcul global ou partiel, impactant la performance globale de vos macros.
Cela signifie que si votre macro insère, modifie ou supprime des lignes tout en cherchant régulièrement la dernière ligne utilisée, vous risquez d’empiler des recalculs inutiles. Une bonne pratique consiste donc à désactiver temporairement le calcul automatique avant les traitements lourds, puis à le réactiver à la fin :
Dim calcMode As XlCalculationWith Application calcMode = .Calculation .Calculation = xlCalculationManual .ScreenUpdating = FalseEnd With' ... vos traitements, y compris la recherche de dernière ligne ...With Application .Calculation = calcMode .ScreenUpdating = TrueEnd With
En réduisant le nombre de recalculs, vous laissez davantage de ressources à la navigation dans les cellules et au traitement VBA pur. De plus, Excel utilise des mécanismes de cache internes pour optimiser l’accès aux cellules fréquemment lues. Lorsque vous limitez les allers-retours superflus (par exemple, en évitant .Select et .Activate), vous facilitez le travail de ce cache et améliorez indirectement la rapidité des recherches de dernière ligne non vide.
On peut comparer cela à un navigateur Internet : si vous rechargez sans arrêt la même page, vous surchargez la bande passante et la mémoire. Si au contraire vous laissez le cache faire son travail, les consultations suivantes seront plus rapides. En VBA, limiter les changements de contexte (sélections, activations, recalculs) permet à Excel d’optimiser lui-même ses accès aux données, et par ricochet, la performance de vos fonctions LastRow.
Gestion des plages discontinues et cellules formatées vides
Un cas fréquent dans les fichiers de production est celui des plages discontinues : vous pouvez avoir des blocs de données séparés par des lignes vides, éventuellement avec des cellules simplement formatées (colorées, bordées) mais ne contenant pas de valeur. Comment trouver la dernière ligne non vide de manière fiable dans ces conditions ?
Avec Range.End(xlUp), la réponse dépend exclusivement de la colonne choisie : si cette colonne contient une valeur pour chaque ligne de vos blocs (y compris en présence de lignes vides dans d’autres colonnes), la méthode reste fiable. En revanche, si votre base de données autorise des lignes « partiellement vides » dans la colonne de référence, End(xlUp) risque de s’arrêter sur la dernière ligne complète, en ignorant un enregistrement dont seule une partie des colonnes est remplie. Dans ce cas, Cells.Find avec la recherche sur tout le UsedRange s’avère plus pertinent.
Les cellules simplement formatées sans valeur posent un autre problème : elles étendent artificiellement la zone utilisée de la feuille, ce qui peut fausser aussi bien UsedRange que SpecialCells(xlCellTypeLastCell). Pour contourner ce problème, une approche consiste à vérifier explicitement la présence de valeurs ou de formules via .Value ou .HasFormula plutôt que de se fier au statut « utilisé » de la cellule. On peut par exemple parcourir un ensemble de colonnes clés et déterminer le maximum des dernières lignes non vides trouvées dans chacune.
Vous pouvez aussi mettre en place, en amont, une discipline de structuration de vos données : réserver certaines colonnes comme identifiants obligatoires, éviter les mises en forme « décoratives » loin du tableau, et centraliser vos données dans une zone compacte. Plus votre feuille sera structurée, plus les méthodes de recherche de dernière ligne non vide en VBA seront simples, rapides et fiables.
Construction d’une fonction VBA personnalisée GetLastRow robuste
Implémentation de la validation des paramètres WorkSheet et column
Plutôt que de réécrire sans cesse le même bout de code pour trouver la dernière ligne non vide, vous pouvez encapsuler la logique dans une fonction personnalisée GetLastRow. L’idée est de disposer d’un point d’entrée unique, réutilisable dans tous vos projets. La première étape consiste à définir clairement les paramètres : une feuille de calcul (Worksheet) et une colonne (numéro ou lettre).
Une implémentation robuste doit valider ces paramètres dès le départ. Par exemple, vérifier que l’objet feuille n’est pas Nothing, ou que la colonne demandée est dans l’intervalle autorisé (1 à 16384 pour les versions récentes d’Excel). Vous pouvez permettre à l’utilisateur de passer une lettre de colonne ("A", "B", …) ou un numéro (1, 2, …), et convertir systématiquement en numéro :
Public Function GetLastRow(ByVal ws As Worksheet, _ ByVal Col As Variant) As Long Dim colNum As Long 'Validation de la feuille If ws Is Nothing Then GetLastRow = 0 Exit Function End If 'Conversion de la colonne If IsNumeric(Col) Then colNum = CLng(Col) Else colNum = Columns(UCase$(CStr(Col)) & ":" & UCase$(CStr(Col))).Column End If 'Validation du numéro de colonne If colNum < 1 Or colNum > ws.Columns.Count Then GetLastRow = 0 Exit Function End If 'La suite du traitement viendra ici...End Function
En appliquant cette validation systématique, vous évitez un grand nombre d’erreurs difficiles à diagnostiquer plus tard dans vos macros. Si la fonction retourne 0, vous savez immédiatement que le problème se situe au niveau des paramètres d’appel, et non dans le cœur de l’algorithme de recherche de dernière ligne non vide. Vous gagnez ainsi en fiabilité et en maintenabilité.
Intégration de la gestion d’erreurs avec on error resume next
Un autre volet de la robustesse de votre fonction GetLastRow concerne la gestion d’erreurs. Certaines méthodes, comme SpecialCells ou même Find, peuvent lever des erreurs si aucune cellule ne correspond au critère. Plutôt que de laisser l’erreur remonter au niveau de l’appelant, vous pouvez la capturer localement et renvoyer une valeur par défaut, comme 0.
La clé est d’utiliser On Error Resume Next de manière ciblée, sur un bloc de code court, puis de restaurer le gestionnaire d’erreurs avec On Error GoTo 0. Par exemple, pour gérer le cas d’une colonne entièrement vide :
Dim lastCell As RangeOn Error Resume NextSet lastCell = ws.Cells(ws.Rows.Count, colNum).End(xlUp)On Error GoTo 0If lastCell Is Nothing Then GetLastRow = 0 Exit FunctionEnd IfGetLastRow = lastCell.Row
Vous pouvez étendre cette logique en ajoutant un mécanisme de secours : si la méthode principale échoue ou renvoie 1 alors que la feuille est vide, basculer temporairement vers une méthode alternative (Find sur tout le UsedRange, par exemple). L’objectif n’est pas de masquer les problèmes, mais de rendre votre fonction GetLastRow tolérante aux cas extrêmes (feuilles entièrement vides, colonnes non utilisées, etc.).
En utilisant judicieusement On Error Resume Next, vous améliorez la résilience de vos macros sans rendre le débogage impossible. La bonne approche consiste à cerner précisément les appels susceptibles d’échouer, à les entourer de ce bloc, puis à suivre une politique claire de valeur de retour en cas de problème.
Optimisation du code avec Application.ScreenUpdating et calculation
Pour que votre fonction GetLastRow reste aussi rapide que possible, surtout si elle est appelée fréquemment, vous pouvez jouer sur deux leviers globaux d’Excel : Application.ScreenUpdating et Application.Calculation. Nous avons déjà évoqué le mode de calcul, mais combiné à la désactivation du rafraîchissement d’écran, il peut faire une vraie différence sur des projets complexes.
La bonne pratique consiste toutefois à ne pas inclure systématiquement ces optimisations à l’intérieur de la fonction GetLastRow elle-même, sous peine de multiplier les basculements de mode. Mieux vaut souvent les gérer dans la macro appelante, avant et après un bloc de traitements dans lequel GetLastRow sera invoquée plusieurs fois. Néanmoins, dans certains cas (fonction utilisée seule dans un module autonome), vous pouvez encapsuler la désactivation de ScreenUpdating directement dans la fonction :
Public Function GetLastRowFast(ByVal ws As Worksheet, _ ByVal Col As Variant) As Long Dim prevCalc As XlCalculation Dim prevScreen As Boolean prevCalc = Application.Calculation prevScreen = Application.ScreenUpdating Application.Calculation = xlCalculationManual Application.ScreenUpdating = False '... appel de GetLastRow interne ou logique de recherche ... Application.Calculation = prevCalc Application.ScreenUpdating = prevScreenEnd Function
En préservant les valeurs initiales et en les restaurant systématiquement, vous évitez de perturber l’environnement de l’utilisateur final. L’essentiel est de garder en tête que la recherche de dernière ligne non vide, en elle-même, est rapide : c’est la combinaison avec d’autres traitements (recalculs, rafraîchissements de graphiques, mises en forme conditionnelles) qui peut devenir coûteuse. À vous de choisir où placer ces optimisations en fonction de la structure de votre projet VBA.
Retour de valeur long versus integer pour grandes feuilles
Un point souvent négligé par les débutants concerne le type de la valeur retournée par la fonction GetLastRow. Sur les versions modernes d’Excel, une feuille peut contenir jusqu’à 1 048 576 lignes. Le type Integer, lui, est limité à 32 767, ce qui est largement insuffisant pour adresser l’ensemble des lignes possibles. Utiliser Integer pour stocker la dernière ligne non vide risque donc de provoquer un dépassement de capacité.
Pour cette raison, vous devez systématiquement déclarer les variables de ligne en Long (ou LongLong en 64 bits, mais Long reste le standard suffisant pour Excel). Cela vaut aussi bien pour le type de retour de la fonction que pour toutes les variables intermédiaires manipulant des numéros de lignes. Voici une signature correcte :
Public Function GetLastRow(ByVal ws As Worksheet, _ ByVal Col As Variant) As Long
Le faible gain de mémoire offert par Integer ne justifie absolument pas le risque de bug silencieux une fois que votre classeur sera déployé chez d’autres utilisateurs ou migré sur des données plus volumineuses. En adoptant systématiquement le type Long pour tout ce qui se rapporte aux lignes et colonnes, vous vous assurez que votre fonction de recherche de dernière ligne non vide restera fiable quels que soient la taille et l’évolution de vos tableaux.
Traitement des cas particuliers et cellules fusionnées
Détection des dernières lignes avec formules renvoyant des chaînes vides
Un scénario courant dans les fichiers Excel avancés consiste à utiliser des formules qui renvoient une chaîne vide ("") au lieu de 0 ou d’une erreur. Visuellement, la cellule apparaît vide, mais pour Excel, elle contient bel et bien une formule. Cela complique la recherche de la « dernière ligne non vide » : souhaitez-vous considérer ces cellules comme remplies ou non ?
Si vous utilisez Range.End(xlUp) avec LookIn:=xlFormulas (via Find), ces cellules seront prises en compte, car Excel voit la formule. En revanche, si vous voulez ignorer ces formules renvoyant "", vous devrez effectuer une vérification plus fine sur la valeur retournée. Par exemple, après avoir trouvé la dernière ligne candidate, vous pouvez remonter tant que la cellule de la colonne clé contient une chaîne vide :
Dim r As Longr = ws.Cells(ws.Rows.Count, colNum).End(xlUp).RowDo While r > 1 And ws.Cells(r, colNum).Value = "" r = r - 1LoopGetLastRow = r
C’est ici que la définition même de « dernière ligne non vide » doit être clarifiée dans votre projet : parlez-vous de la dernière ligne contenant une formule, ou de la dernière ligne affichant une valeur visible ? En fonction de l’objectif (export, impression, reporting), la réponse peut varier. L’important est d’aligner le comportement de votre fonction GetLastRow sur ce besoin métier précis, plutôt que de vous fier uniquement à la présence de formules.
Gestion des plages MergeArea et propriété MergeCells
Les cellules fusionnées (merged cells) ajoutent un niveau de complexité supplémentaire. Lorsqu’une plage de cellules est fusionnée, une seule valeur est stockée pour l’ensemble de la zone, généralement dans la cellule supérieure gauche, tandis que les autres cellules de la zone sont techniquement masquées. Pour déterminer la dernière ligne non vide dans une colonne qui contient des fusions, vous devez être vigilant.
La propriété MergeCells vous permet de savoir si une cellule fait partie d’une fusion, et la propriété MergeArea de récupérer l’ensemble de la zone fusionnée. Lors de la recherche de dernière ligne, il peut être judicieux de vous baser sur la ligne inférieure du MergeArea, et non sur la cellule elle-même. Par exemple :
Dim lastRow As LongDim r As RangeSet r = ws.Cells(ws.Rows.Count, colNum).End(xlUp)If r.MergeCells Then lastRow = r.MergeArea.Rows(r.MergeArea.Rows.Count).RowElse lastRow = r.RowEnd If
De cette manière, si la valeur se trouve sur une cellule fusionnée couvrant plusieurs lignes, vous considérez que la dernière ligne utilisée est celle du bas de la fusion, ce qui reflète mieux la réalité visuelle de votre tableau. Bien sûr, cela suppose que vos cellules fusionnées sont cohérentes (pas de fusions « sauvages » au milieu des données), car ces structures restent délicates à automatiser en VBA.
Contournement des lignes masquées avec SpecialCells(xlCellTypeVisible)
Un autre cas particulier à prendre en compte concerne les lignes masquées, qu’elles le soient manuellement, via un filtre ou une mise en forme conditionnelle. Souhaitez-vous que la dernière ligne non vide en tienne compte, ou cherchez-vous plutôt la dernière ligne visible ? Pour ce second besoin, vous pouvez vous appuyer sur SpecialCells(xlCellTypeVisible).
L’idée est de restreindre la recherche à la partie visible d’une colonne ou d’un tableau filtré. Par exemple, pour trouver la dernière ligne visible non vide dans une colonne donnée :
Dim visRange As RangeDim lastRowVisible As LongOn Error Resume NextSet visRange = ws.Range(ws.Cells(1, colNum), _ ws.Cells(ws.Rows.Count, colNum)).SpecialCells(xlCellTypeVisible)On Error GoTo 0If Not visRange Is Nothing Then lastRowVisible = visRange.Areas(visRange.Areas.Count).Rows( _ visRange.Areas(visRange.Areas.Count).Rows.Count).RowElse lastRowVisible = 0End If
Cette approche tient compte des éventuels filtres appliqués sur la feuille, ce qui est très utile dans des scénarios de reporting ou de génération de PDF où seules les lignes filtrées doivent être prises en compte. Là encore, la question initiale « que signifie dernière ligne non vide pour vous ? » est cruciale : sans réponse claire, il est difficile de choisir entre la dernière ligne toute donnée confondue et la dernière ligne parmi les seules données visibles.
Automatisation avancée avec array et boucles for each optimisées
Lorsque vous devez analyser de très grands tableaux pour déterminer la dernière ligne non vide selon des critères complexes, il peut être plus performant de charger les données en mémoire dans un Array plutôt que de parcourir les cellules une par une. La lecture d’un bloc de cellules dans un tableau VBA est étonnamment rapide, et les opérations en mémoire sont souvent bien plus efficaces que les accès répétés au modèle objet Excel.
Par exemple, vous pouvez récupérer toute une colonne dans un tableau 2D, puis la parcourir à rebours pour trouver la dernière ligne contenant une valeur exploitable :
Dim data As VariantDim i As LongDim lastRow As LongDim firstRow As LongDim lastRowSheet As LongfirstRow = 1lastRowSheet = ws.Rows.Countdata = ws.Range(ws.Cells(firstRow, colNum), _ ws.Cells(lastRowSheet, colNum)).ValueFor i = UBound(data, 1) To 1 Step -1 If Len(CStr(data(i, 1))) > 0 Then lastRow = i + firstRow - 1 Exit For End IfNext i
Dans ce schéma, l’accès aux éléments du tableau data est quasi instantané, même pour plusieurs centaines de milliers de lignes. Vous pouvez aussi combiner cette technique avec des boucles For Each sur des Range préfiltrées, par exemple en utilisant SpecialCells pour limiter les cellules analysées aux non vides. L’objectif reste toujours le même : minimiser les allers-retours entre VBA et Excel, qui constituent le principal goulot d’étranglement.
En fin de compte, la combinaison de ces techniques (chargement dans des arrays, boucles optimisées, filtrage préalable des plages) vous permet de construire des routines de détection de dernière ligne non vide à la fois fiables et extrêmement rapides, même sur des classeurs lourds. Vous vous demandez si cela vaut vraiment la peine pour un simple numéro de ligne ? Sur un petit fichier, peut-être pas. Mais sur un reporting quotidien exécuté sur des millions de cellules, ces optimisations font toute la différence.
Débogage et tests unitaires des fonctions LastRow en VBA
Pour terminer, un aspect souvent négligé mais essentiel : le débogage et les tests unitaires de vos fonctions LastRow. Une fonction aussi centrale que GetLastRow mérite d’être testée systématiquement dans différents scénarios : feuilles vides, colonnes entièrement vides, lignes fusionnées, formules renvoyant "", filtres actifs, etc. Sans cette phase, vous risquez de découvrir des bugs en production, dans les pires conditions.
Vous pouvez par exemple créer une procédure de test dédiée qui prépare plusieurs feuilles de test et vérifie que la fonction renvoie bien les résultats attendus :
Sub Test_GetLastRow() Debug.Print "Feuille1, Col A : "; GetLastRow(Sheets("Feuille1"), "A") Debug.Print "Feuille2, Col B : "; GetLastRow(Sheets("Feuille2"), 2) Debug.Print "Feuille3 (vide), Col A : "; GetLastRow(Sheets("Feuille3"), "A")End Sub
En comparant les valeurs retournées avec ce que vous observez visuellement dans Excel, vous pouvez ajuster vos choix techniques (End(xlUp), Find, filtrage des chaînes vides, etc.) jusqu’à obtenir un comportement cohérent avec vos besoins métiers. N’hésitez pas à ajouter des Debug.Print ou des MsgBox temporaires pour tracer l’exécution : voir les valeurs intermédiaires (numéro de colonne calculé, contenu de la dernière cellule trouvée) facilite grandement le diagnostic.
En mettant en place cette petite batterie de tests et en l’exécutant après chaque modification majeure de votre fonction, vous vous créez une sorte de « filet de sécurité » qui vous alerte immédiatement en cas de régression. À long terme, cette approche vous fera gagner un temps précieux et vous permettra de déployer des macros de recherche de dernière ligne non vide en VBA à la fois rapides, fiables et faciles à maintenir.