Lorsque je veux trouver la dernière valeur de cellule utilisée, j'utilise:
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
J'obtiens une mauvaise sortie lorsque je mets un seul élément dans une cellule. Mais lorsque je mets plus d'une valeur dans la cellule, la sortie est correcte. Quelle est la raison derrière cela?
excel
vba
excel-formula
James
la source
la source
Réponses:
REMARQUE : j'ai l'intention d'en faire un «article à guichet unique» où vous pouvez utiliser le
Correct
moyen de trouver la dernière ligne. Cela couvrira également les meilleures pratiques à suivre lors de la recherche de la dernière ligne. Et par conséquent, je continuerai à le mettre à jour chaque fois que je rencontre un nouveau scénario / information.Manières peu fiables de trouver la dernière ligne
Certaines des méthodes les plus courantes pour trouver la dernière ligne sont très peu fiables et ne doivent donc jamais être utilisées.
UsedRange
ne doit JAMAIS être utilisé pour trouver la dernière cellule contenant des données. C'est très peu fiable. Essayez cette expérience.Tapez quelque chose dans la cellule
A5
. Maintenant, lorsque vous calculez la dernière ligne avec l'une des méthodes ci-dessous, cela vous donnera 5. Maintenant, colorez la cellule enA10
rouge. Si vous utilisez maintenant l'un des codes ci-dessous, vous obtiendrez toujours 5. Si vous utilisezUsedrange.Rows.Count
ce que vous obtenez? Ce ne sera pas 5.Voici un scénario pour montrer comment
UsedRange
fonctionne.xlDown
est également peu fiable.Considérez ce code
Que se passerait-il s'il n'y avait qu'une seule cellule (
A1
) contenant des données? Vous finirez par atteindre la dernière ligne de la feuille de calcul! C'est comme sélectionner une celluleA1
, puis appuyer sur la Endtouche puis sur la Down Arrowtouche. Cela vous donnera également des résultats peu fiables s'il y a des cellules vides dans une plage.CountA
est également peu fiable car il vous donnera un résultat incorrect s'il y a des cellules vides entre les deux.Et par conséquent , il faut éviter l'utilisation de
UsedRange
,xlDown
etCountA
de trouver la dernière cellule.Rechercher la dernière ligne dans une colonne
Pour trouver la dernière ligne de la colonne E, utilisez ceci
Si vous remarquez que nous avons un
.
avantRows.Count
. Nous avons souvent choisi d'ignorer cela. Consultez CETTE question sur l'erreur possible que vous pourriez obtenir. Je conseille toujours d'utiliser.
avantRows.Count
etColumns.Count
. Cette question est un scénario classique dans lequel le code échouera car lesRows.Count
retours65536
pour Excel 2003 et versions antérieures et1048576
pour Excel 2007 et versions ultérieures. De mêmeColumns.Count
renvoie256
et16384
, respectivement.Le fait ci-dessus qu'Excel 2007+ a des
1048576
lignes met également l'accent sur le fait que nous devons toujours déclarer la variable qui contiendra la valeur de la ligne carLong
au lieu de celaInteger
, vous obtiendrez uneOverflow
erreur.Notez que cette approche ignorera toutes les lignes masquées. En regardant ma capture d'écran ci-dessus pour la colonne A , si la ligne 8 était masquée, cette approche reviendrait à la
5
place de8
.Rechercher la dernière ligne d'une feuille
Pour trouver la
Effective
dernière ligne de la feuille, utilisez ceci. Notez l'utilisation deApplication.WorksheetFunction.CountA(.Cells)
. Cela est nécessaire car s'il n'y a pas de cellules avec des données dans la feuille de calcul.Find
, vousRun Time Error 91: Object Variable or With block variable not set
Rechercher la dernière ligne d'une table (ListObject)
Les mêmes principes s'appliquent, par exemple pour obtenir la dernière ligne de la troisième colonne d'un tableau:
la source
Usedrange.Rows.Count
ce que vous obtenez? Ce ne sera pas 5. Usedrange est très peu fiable pour trouver la dernière ligne.remembers
le dernier paramètre. Même lorsque vous faites manuellement unFind
, il se souvient du dernier réglage qui en fait est une aubaine si l'on connaît ce "fait"UsedRange
( il est très peu fiable de trouver la dernière cellule contenant des données ) est trompeuse.UsedRange
n'est tout simplement pas destiné à cette fin, même si dans certains cas, il peut donner le résultat correct. Je pense que l'expérience proposée ajoute à la confusion. Le résultat obtenu avecUsedRange
($ A $ 1: $ A $ 8) ne dépend pas de la première saisie des données et de leur suppression. Le chiffre de droite sera toujours le même même sans avoir saisi les données et les avoir supprimées. S'il vous plaît voir ma réponse.Remarque: cette réponse a été motivée par ce commentaire . Le but de
UsedRange
est différent de ce qui est mentionné dans la réponse ci-dessus.Quant à la manière correcte de trouver la dernière cellule utilisée, il faut d'abord décider de ce qui est considéré comme utilisé , puis sélectionner une méthode appropriée . Je conçois au moins trois significations:
Utilisé = non vide, c'est-à-dire ayant des données .
Used = "... en cours d'utilisation, c'est-à-dire la section contenant des données ou une mise en forme ." Selon la documentation officielle , c'est le critère utilisé par Excel au moment de l'enregistrement. Voir aussi cette documentation officielle . Si l'on n'en est pas conscient, le critère peut produire des résultats inattendus, mais il peut aussi être intentionnellement exploité (moins souvent, sûrement), par exemple pour mettre en évidence ou imprimer des régions spécifiques, qui peuvent éventuellement ne pas avoir de données. Et, bien sûr, il est souhaitable comme critère pour la plage à utiliser lors de l'enregistrement d'un classeur, de peur de perdre une partie de son travail.
Utilisé = "... en cours d'utilisation, signifiant la section qui contient des données ou une mise en forme " ou une mise en forme conditionnelle. Identique à 2., mais incluant également les cellules qui sont la cible de toute règle de mise en forme conditionnelle.
Comment trouver la dernière cellule utilisée dépend de ce que vous voulez (votre critère) .
Pour le critère 1, je suggère de lire cette réponse . Notez que cela
UsedRange
est cité comme peu fiable. Je pense que c'est trompeur (c'est-à-dire "injuste" pourUsedRange
), car ilUsedRange
n'est tout simplement pas destiné à signaler la dernière cellule contenant des données. Il ne devrait donc pas être utilisé dans ce cas, comme indiqué dans cette réponse. Voir aussi ce commentaire .Pour le critère 2,
UsedRange
c'est l'option la plus fiable , par rapport aux autres options également conçues pour cet usage. Cela rend même inutile l'enregistrement d'un classeur pour s'assurer que la dernière cellule est mise à jour. Ctrl+ Endira dans une mauvaise cellule avant l'enregistrement ("La dernière cellule n'est pas réinitialisée tant que vous n'avez pas enregistré la feuille de calcul", à partir de http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10% 29.aspx . C'est une référence ancienne, mais à cet égard valable).Pour le critère 3, je ne connais aucune méthode intégrée . Le critère 2 ne tient pas compte du formatage conditionnel. On peut avoir des cellules formatées, basées sur des formules, qui ne sont pas détectées par
UsedRange
ou Ctrl+ End. Dans la figure, la dernière cellule est B3, car la mise en forme lui a été appliquée explicitement. Les cellules B6: D7 ont un format dérivé d'une règle de mise en forme conditionnelle, et cela n'est pas détecté même parUsedRange
. La comptabilisation de cela nécessiterait une programmation VBA.Quant à votre question spécifique : quelle est la raison derrière cela?
Votre code utilise la première cellule de votre gamme E4: E48 comme trampoline, pour sauter avec
End(xlDown)
.La sortie "erronée" sera obtenue s'il n'y a pas de cellules non vides dans votre plage autre que peut-être la première. Ensuite, vous êtes bondissant dans l'obscurité , à savoir, en bas de la feuille de calcul (vous devez noter la différence entre blanc et chaîne vide !).
Notez que:
Si votre plage contient des cellules non vides non contiguës, cela donnera également un résultat erroné.
S'il n'y a qu'une seule cellule non vide, mais ce n'est pas la première, votre code vous donnera toujours le résultat correct.
la source
J'ai créé cette fonction unique pour déterminer la dernière ligne, colonne et cellule, que ce soit pour les données, les cellules formatées (groupées / commentées / masquées) ou la mise en forme conditionnelle .
Les résultats ressemblent à ceci:
Pour des résultats plus détaillés, certaines lignes du code peuvent être décommentées:
Une limitation existe - s'il y a des tables dans la feuille, les résultats peuvent devenir peu fiables, j'ai donc décidé d'éviter d'exécuter le code dans ce cas:
la source
Une note importante à garder à l'esprit lors de l'utilisation de la solution ...
... est de vous assurer que votre
LastRow
variable est deLong
type:Sinon, vous obtiendrez des erreurs de SURFLUX dans certaines situations dans les classeurs .XLSX
C'est ma fonction encapsulée que j'utilise pour diverses utilisations de code.
la source
J'ajouterais à la réponse donnée par Siddarth Rout pour dire que l'appel CountA peut être ignoré en demandant à Find de renvoyer un objet Range, au lieu d'un numéro de ligne, puis de tester l'objet Range renvoyé pour voir s'il s'agit de Nothing (feuille de calcul vierge) .
En outre, ma version de toute procédure LastRow renvoie un zéro pour une feuille de calcul vierge, puis je peux savoir qu'elle est vide.
la source
Je me demande que personne n'ait mentionné cela, mais le moyen le plus simple d'obtenir la dernière cellule utilisée est:
Cela renvoie essentiellement la même cellule que celle obtenue par Ctrl+ Endaprès avoir sélectionné Cellule
A1
.Un mot d'avertissement: Excel garde la trace de la cellule la plus en bas à droite jamais utilisée dans une feuille de calcul. Donc si, par exemple, vous entrez quelque chose dans B3 et autre chose dans H8 , puis supprimez plus tard le contenu de H8 , appuyer sur Ctrl+ vous Endamènera toujours à la cellule H8 . La fonction ci-dessus aura le même comportement.
la source
Last Cell
dans Excel fait parfois référence à une cellule vide (deUsed Range
) différente deLast Used Cell
;).Cells(1,1).Select()
n'est pas valide, peut-êtreActiveSheet.Cells(1,1).Select
; Aussi dans VBA, il n'est pas recommandé d'utiliserSelect
;).Set
.Étant donné que la question d'origine concerne les problèmes de recherche de la dernière cellule, dans cette réponse, je vais énumérer les différentes façons dont vous pouvez obtenir des résultats inattendus ; voir ma réponse à "Comment puis-je trouver la dernière ligne contenant des données dans la feuille Excel avec une macro?" pour mon avis sur la résolution de ce problème.
Je vais commencer par développer la réponse de sancho.s et le commentaire de GlennFromIowa , en ajoutant encore plus de détails:
Autres éléments à prendre en compte:
Dans cet esprit, voyons comment les méthodes courantes d'obtention de la "dernière cellule" peuvent produire des résultats inattendus:
.End(xlDown)
code de la question se cassera le plus facilement (par exemple avec une seule cellule non vide ou lorsqu'il y a des cellules vides entre les deux ) pour les raisons expliquées dans la réponse de Siddharth Rout ici (recherchez "xlDown est également peu fiable." ) 👎Count
ing (CountA
ouCells*.Count
) ou.CurrentRegion
se cassera également en présence de cellules ou de lignes vides 👎.End(xlUp)
à rechercher en arrière à partir de la fin d'une colonne recherchera, tout comme CTRL + UP, des données (les formules produisant une valeur vide sont considérées comme des «données») dans les lignes visibles (donc l'utiliser avec le filtre automatique activé peut produire des résultats incorrects ⚠️ ).Vous devez faire attention pour éviter les pièges standard (pour plus de détails, je vais à nouveau consulter la réponse de Siddharth Rout ici, recherchez la section "Rechercher la dernière ligne dans une colonne" ), comme le codage en dur de la dernière ligne (
Range("A65536").End(xlUp)
) au lieu de compter sursht.Rows.Count
..SpecialCells(xlLastCell)
équivaut à CTRL + FIN, renvoyant la cellule la plus basse et la plus à droite de la "plage utilisée", donc toutes les mises en garde qui s'appliquent au fait de s'appuyer sur la "plage utilisée" s'appliquent également à cette méthode. De plus, la «plage utilisée» n'est réinitialisée que lors de l'enregistrement du classeur et lors de l'accèsworksheet.UsedRange
, ellexlLastCell
peut donc produire des résultats périmés⚠️ avec des modifications non enregistrées (par exemple après la suppression de certaines lignes). Voir la réponse à proximité par dotNET .sht.UsedRange
(décrit en détail dans la réponse de sancho.s ici) considère à la fois les données et le formatage (mais pas le formatage conditionnel) et réinitialise la "plage utilisée" de la feuille de calcul , qui peut ou non être ce que vous voulez.Notez qu'une erreur courante est d'utiliser
.UsedRange.Rows.Count
⚠️, qui renvoie le nombre de lignes dans la plage utilisée, pas le numéro de la dernière ligne (elles seront différentes si les premières lignes sont vides), pour plus de détails, voir la réponse de newguy à Comment puis-je trouver dernière ligne qui contient des données dans la feuille Excel avec une macro?.Find
vous permet de trouver la dernière ligne avec toutes les données (y compris les formules) ou une valeur non vide dans n'importe quelle colonne . Vous pouvez choisir si vous êtes intéressé par des formules ou des valeurs, mais le hic, c'est que cela réinitialise les valeurs par défaut dans la boîte de dialogue Rechercher d'Excel ️️⚠️, ce qui peut être très déroutant pour vos utilisateurs. Il doit également être utilisé avec précaution, voir la réponse de Siddharth Rout ici (section "Trouver la dernière ligne d'une feuille" )Cells
dans une boucle sont généralement plus lentes que la réutilisation d'une fonction Excel (bien qu'elles puissent toujours être performantes), mais vous permettent de spécifier exactement ce que vous voulez trouver. Voir ma solution basée surUsedRange
et les tableaux VBA pour trouver la dernière cellule avec des données dans la colonne donnée - il gère les lignes cachées, les filtres, les blancs, ne modifie pas les valeurs par défaut de recherche et est assez performant.Quelle que soit la solution que vous choisissez, soyez prudent
Long
place deInteger
pour stocker les numéros de ligne (pour éviter d'avoirOverflow
plus de 65k lignes) etDim ws As Worksheet ... ws.Range(...)
à- dire au lieu deRange(...)
).Value
(qui est aVariant
), évitez les transtypages implicites,.Value <> ""
car ils échoueront si la cellule contient une valeur d'erreur.la source
Cependant, cette question cherche à trouver la dernière ligne en utilisant VBA, je pense qu'il serait bon d'inclure une formule matricielle pour la fonction de feuille de calcul car elle est visitée fréquemment:
Vous devez entrer la formule sans crochets, puis appuyez sur Shift+ Ctrl+ Enterpour en faire une formule matricielle.
Cela vous donnera l'adresse de la dernière cellule utilisée dans la colonne D.
la source
Voici A65536la dernière cellule de la colonne A ce code a été testé sur Excel 2003.
la source
Je cherchais un moyen d'imiter le CTRL+ Shift+ End, donc la solution dotNET est excellente, sauf avec mon Excel 2010, je dois ajouter un
set
si je veux éviter une erreur:et comment le vérifier par vous-même:
la source
Voici mes deux cents.
À mon humble avis, le risque d'une ligne cachée avec des données exclues est trop important pour
xlUp
être considéré comme une réponse unique . Je conviens que c'est simple et fonctionnera la plupart du temps, mais cela présente le risque de sous-estimer la dernière ligne, sans aucun avertissement. Cela pourrait produire CATASTROPHIQUE résultats à un moment donné pour quelqu'un qui a sauté sur Stack Overlow et cherchait un "moyen sûr" de capturer cette valeur.La
Find
méthode est sans faille et je l'approuverais comme une réponse unique . Cependant, l'inconvénient de changer leFind
paramètres peut être gênant, en particulier si cela fait partie d'un UDF.Les autres réponses affichées sont correctes, mais la complexité devient un peu excessive. Voici donc ma tentative de trouver un équilibre entre fiabilité, complexité minimale et non utilisation
Find
.Pourquoi c'est bon:
Find
paramètresPourquoi c'est mauvais:
Cependant, je pense qu'une solution unique qui présente l'inconvénient de gâcher les
find
paramètres ou de fonctionner plus lentement est une meilleure solution globale. Un utilisateur peut ensuite bricoler ses paramètres pour essayer de s'améliorer, sachant ce qui se passe avec son code. L'utilisationxLUp
n'avertira pas des risques potentiels et ils pourraient continuer pendant qui sait combien de temps ne sachant pas que leur code ne fonctionnait pas correctement.la source
Au cours des 3 dernières années, ce sont les fonctions que j'utilise pour trouver la dernière ligne et la dernière colonne par colonne définie (pour ligne) et ligne (pour colonne):
Dernière colonne:
Dernière rangée:
Pour le cas de l'OP, voici la façon d'obtenir la dernière ligne de la colonne
E
:Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
Dernière ligne, en comptant les lignes vides avec des données:
Ici, nous pouvons utiliser les formules Excel bien connues , qui nous donnent la dernière ligne d'une feuille de calcul dans Excel, sans impliquer VBA -
=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
Afin de mettre cela dans VBA et de ne rien écrire dans Excel, en utilisant les paramètres de ces dernières fonctions, quelque chose comme ça pourrait être à l'esprit:
la source
EVAL()
la fameuse formule Excel. Bien que les gens puissent penser queEval()
c'est mal et que c'est une autre histoire intéressante sur laquelle écrire ...la source