Als ik de laatst gebruikte celwaarde wil vinden, gebruik ik:
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
Ik krijg de verkeerde uitvoer wanneer ik een enkel element in een cel plaats. Maar als ik meer dan één waarde in de cel plaats, is de uitvoer correct.
Wat is de reden hierachter?
Antwoord 1, autoriteit 100%
OPMERKING: ik ben van plan om dit een “one-stop-post” te maken waar je de Correct
manier kunt gebruiken om de laatste rij te vinden. Dit omvat ook de best practices die moeten worden gevolgd bij het vinden van de laatste rij. En daarom zal ik het blijven updaten wanneer ik een nieuw scenario/informatie tegenkom.
Onbetrouwbare manieren om de laatste rij te vinden
Enkele van de meest voorkomende manieren om de laatste rij te vinden, zijn zeer onbetrouwbaar en mogen daarom nooit worden gebruikt.
- UsedRange
- xlOmlaag
- AantalA
UsedRange
mag NOOITworden gebruikt om de laatste cel met gegevens te vinden. Het is hoogst onbetrouwbaar. Probeer dit experiment.
Typ iets in cel A5
. Als je nu de laatste rij berekent met een van de onderstaande methoden, krijg je 5. Kleur nu de cel A10
rood. Als je nu een van de onderstaande codes gebruikt, krijg je nog steeds 5. Als je Usedrange.Rows.Count
gebruikt, wat krijg je dan? Het wordt geen 5.
Hier is een scenario om te laten zien hoe UsedRange
werkt.
xlDown
is even onbetrouwbaar.
Overweeg deze code
lastrow = Range("A1").End(xlDown).Row
Wat zou er gebeuren als er maar één cel (A1
) was met gegevens? Je komt uiteindelijk bij de laatste rij van het werkblad! Het is alsof u cel A1
selecteert en vervolgens op de End-toets drukt en vervolgens op de Pijl-omlaag-toets drukt. Dit geeft ook onbetrouwbare resultaten als er lege cellen in een bereik zijn.
CountA
is ook onbetrouwbaar omdat het een onjuist resultaat geeft als er lege cellen tussen staan.
En daarom moet men het gebruik van UsedRange
, xlDown
en CountA
vermijden om de laatste cel te vinden.
Vind laatste rij in een kolom
Gebruik dit om de laatste rij in Col E te vinden
With Sheets("Sheet1")
LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
End With
Als je merkt dat we een .
hebben vóór Rows.Count
. We hebben er vaak voor gekozen om dat te negeren. Zie DEZEvraag over de mogelijke fout die u kunt krijgen. Ik raad altijd aan om .
te gebruiken vóór Rows.Count
en Columns.Count
. Die vraag is een klassiek scenario waarbij de code zal mislukken omdat de Rows.Count
65536
voor Excel 2003 en eerder en 1048576
voor Excel 2007 en later. Op dezelfde manier retourneert Columns.Count
respectievelijk 256
en 16384
.
Het bovenstaande feit dat Excel 2007+ 1048576
rijen heeft, benadrukt ook het feit dat we altijd de variabele die de rijwaarde zal bevatten moeten declareren als Long
in plaats van Integer
anders krijg je een Overflow
-fout.
Houd er rekening mee dat deze aanpak alle verborgen rijen overslaat. Terugkijkend op mijn screenshot hierboven voor kolom A, als rij 8 verborgen was, zou deze benadering retourneer 5
in plaats van 8
.
Vind laatste rij in een blad
Gebruik deze om de Effective
laatste rij in het blad te vinden. Let op het gebruik van Application.WorksheetFunction.CountA(.Cells)
. Dit is vereist, want als er geen cellen met gegevens in het werkblad staan, geeft .Find
u Run Time Error 91: Object Variable or With block variable not set
With Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastrow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lastrow = 1
End If
End With
Vind laatste rij in een tabel (ListObject)
Dezelfde principes zijn van toepassing, bijvoorbeeld om de laatste rij in de derde kolom van een tabel te krijgen:
Sub FindLastRowInExcelTableColAandB()
Dim lastRow As Long
Dim ws As Worksheet, tbl as ListObject
Set ws = Sheets("Sheet1") 'Modify as needed
'Assuming the name of the table is "Table1", modify as needed
Set tbl = ws.ListObjects("Table1")
With tbl.ListColumns(3).Range
lastrow = .Find(What:="*", _
After:=.Cells(1), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
End With
End Sub
Antwoord 2, autoriteit 11%
Opmerking: dit antwoord werd gemotiveerd door deze opmerking. Het doel van UsedRange
is anders dan in het bovenstaande antwoord wordt vermeld.
Voor de juiste manier om de laatst gebruikte cel te vinden, moet men eerst beslissen wat als gebruiktwordt beschouwd en vervolgens een geschikte methode selecteren. Ik kan ten minste drie betekenissen bedenken:
-
Gebruikt = niet leeg, d.w.z. met gegevens.
-
Used = “… in gebruik, dat wil zeggen de sectie die gegevens of opmaakbevat.”
Volgens officiële documentatieis dit het criterium dat door Excel wordt gebruikt op het moment van opslaan. Zie ook deze officiële documentatie.
Als men zich dit niet bewust is, kan het criterium onverwachte resultaten opleveren, maar het kan ook opzettelijk worden gebruikt (minder vaak, zeker), bijvoorbeeld om specifieke regio’s te markeren of af te drukken, die uiteindelijk geen gegevens hebben.
En natuurlijk is het wenselijk als criterium voor het bereik dat moet worden gebruikt bij het opslaan van een werkmap, om te voorkomen dat een deel van het werk verloren gaat. -
Used = “… in gebruik, dat wil zeggen de sectie die gegevens of opmaak” of voorwaardelijke opmaak bevat.
Hetzelfde als 2., maar ook met cellen die het doel zijn voor elke regel voor voorwaardelijke opmaak.
Hoe u de laatst gebruikte cel kunt vinden, hangt af van wat uwilt (uw criterium).
Voor criterium 1 raad ik aan dit antwoordte lezen.
Merk op dat UsedRange
als onbetrouwbaar wordt beschouwd. Ik denk dat dat misleidend is (d.w.z. “oneerlijk” voor UsedRange
), aangezien UsedRange
gewoon niet bedoeld is om de laatste cel met gegevens te rapporteren. Het mag in dit geval dus niet worden gebruikt, zoals aangegeven in dat antwoord. Zie ook deze opmerking.
Voor criterium 2 is UsedRange
de meest betrouwbare optie, in vergelijking met andere opties die ook voor dit gebruik zijn ontworpen. Het maakt het zelfs overbodig om een werkmap op te slaan om ervoor te zorgen dat de laatste cel wordt bijgewerkt.
Ctrl+Endgaat naar een verkeerde cel voorafgaand aan het opslaan
(“De laatste cel wordt pas gereset als u het werkblad opslaat”, van
http://msdn.microsoft.com/en -us/library/aa139976%28v=office.10%29.aspx.
Het is een oude referentie, maar in dit opzicht geldig).
Voor criterium 3 ken ik geen ingebouwde methode.
Criterium 2 houdt geen rekening met voorwaardelijke opmaak. Men kan opgemaakte cellen hebben, gebaseerd op formules, die niet gedetecteerd worden door UsedRange
of Ctrl+End.
In de afbeelding is de laatste cel B3, omdat er expliciet opmaak op is toegepast. Cellen B6:D7 hebben een indeling die is afgeleid van een regel voor voorwaardelijke opmaak en dit wordt zelfs niet gedetecteerd door UsedRange
.
Om hier rekening mee te houden zou wat VBA-programmering nodig zijn.
Wat betreft uw specifieke vraag:
Wat is de reden hierachter?
Je code gebruikt de eerste cel in je bereik E4:E48 als trampoline, voor springennaar beneden met End(xlDown)
.
De “foutieve” uitvoer wordt verkregen als er geen niet-legecellen in uw bereik zijn, behalve misschien de eerste. Dan spring je in het donker, d.w.z. naar beneden op het werkblad
(let op het verschil tussen blancoen lege string!).
Let op:
-
Als uw bereik niet-aaneengesloten niet-lege cellen bevat, geeft dit ook een verkeerd resultaat.
-
Als er maar één niet-lege cel is, maar het is niet de eerste, geeft je code je nog steeds het juiste resultaat.
Antwoord 3, autoriteit 6%
Ik heb deze one-stop-functie gemaakt voor het bepalen van de laatste rij, kolom en cel, of het nu gaat om gegevens, opgemaakte (gegroepeerde/commentaar/verborgen) cellen of voorwaardelijke opmaak.
Sub LastCellMsg()
Dim strResult As String
Dim lngDataRow As Long
Dim lngDataCol As Long
Dim strDataCell As String
Dim strDataFormatRow As String
Dim lngDataFormatCol As Long
Dim strDataFormatCell As String
Dim oFormatCond As FormatCondition
Dim lngTempRow As Long
Dim lngTempCol As Long
Dim lngCFRow As Long
Dim lngCFCol As Long
Dim strCFCell As String
Dim lngOverallRow As Long
Dim lngOverallCol As Long
Dim strOverallCell As String
With ActiveSheet
If .ListObjects.Count > 0 Then
MsgBox "Cannot return reliable results, as there is at least one table in the worksheet."
Exit Sub
End If
strResult = "Workbook name: " & .Parent.Name & vbCrLf
strResult = strResult & "Sheet name: " & .Name & vbCrLf
'DATA:
'last data row
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lngDataRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lngDataRow = 1
End If
'strResult = strResult & "Last data row: " & lngDataRow & vbCrLf
'last data column
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lngDataCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Else
lngDataCol = 1
End If
'strResult = strResult & "Last data column: " & lngDataCol & vbCrLf
'last data cell
strDataCell = Replace(Cells(lngDataRow, lngDataCol).Address, "$", vbNullString)
strResult = strResult & "Last data cell: " & strDataCell & vbCrLf
'FORMATS:
'last data/formatted/grouped/commented/hidden row
strDataFormatRow = StrReverse(Split(StrReverse(.UsedRange.Address), "$")(0))
'strResult = strResult & "Last data/formatted row: " & strDataFormatRow & vbCrLf
'last data/formatted/grouped/commented/hidden column
lngDataFormatCol = Range(StrReverse(Split(StrReverse(.UsedRange.Address), "$")(1)) & "1").Column
'strResult = strResult & "Last data/formatted column: " & lngDataFormatCol & vbCrLf
'last data/formatted/grouped/commented/hidden cell
strDataFormatCell = Replace(Cells(strDataFormatRow, lngDataFormatCol).Address, "$", vbNullString)
strResult = strResult & "Last data/formatted cell: " & strDataFormatCell & vbCrLf
'CONDITIONAL FORMATS:
For Each oFormatCond In .Cells.FormatConditions
'last conditionally-formatted row
lngTempRow = CLng(StrReverse(Split(StrReverse(oFormatCond.AppliesTo.Address), "$")(0)))
If lngTempRow > lngCFRow Then lngCFRow = lngTempRow
'last conditionally-formatted column
lngTempCol = Range(StrReverse(Split(StrReverse(oFormatCond.AppliesTo.Address), "$")(1)) & "1").Column
If lngTempCol > lngCFCol Then lngCFCol = lngTempCol
Next
'no results are returned for Conditional Format if there is no such
If lngCFRow <> 0 Then
'strResult = strResult & "Last cond-formatted row: " & lngCFRow & vbCrLf
'strResult = strResult & "Last cond-formatted column: " & lngCFCol & vbCrLf
'last conditionally-formatted cell
strCFCell = Replace(Cells(lngCFRow, lngCFCol).Address, "$", vbNullString)
strResult = strResult & "Last cond-formatted cell: " & strCFCell & vbCrLf
End If
'OVERALL:
lngOverallRow = Application.WorksheetFunction.Max(lngDataRow, strDataFormatRow, lngCFRow)
'strResult = strResult & "Last overall row: " & lngOverallRow & vbCrLf
lngOverallCol = Application.WorksheetFunction.Max(lngDataCol, lngDataFormatCol, lngCFCol)
'strResult = strResult & "Last overall column: " & lngOverallCol & vbCrLf
strOverallCell = Replace(.Cells(lngOverallRow, lngOverallCol).Address, "$", vbNullString)
strResult = strResult & "Last overall cell: " & strOverallCell & vbCrLf
MsgBox strResult
Debug.Print strResult
End With
End Sub
De resultaten zien er als volgt uit:
Voor meer gedetailleerde resultaten kunnen sommige regels in de code worden verwijderd:
Er is één beperking: als er tabellen in het blad staan, kunnen de resultaten onbetrouwbaar worden, dus heb ik besloten de code in dit geval niet uit te voeren:
If .ListObjects.Count > 0 Then
MsgBox "Cannot return reliable results, as there is at least one table in the worksheet."
Exit Sub
End If
Antwoord 4, autoriteit 4%
Een belangrijke opmerking om in gedachten te houden bij het gebruik van de oplossing …
LastRow = ws.Cells.Find(What:="*", After:=ws.range("a1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
… is om ervoor te zorgen dat uw LastRow
-variabele van het type Long
is:
Dim LastRow as Long
Anders krijg je in bepaalde situaties OVERFLOW-fouten in .XLSX-werkmappen
Dit is mijn ingekapselde functie die ik gebruik voor verschillende codetoepassingen.
Private Function FindLastRow(ws As Worksheet) As Long
' --------------------------------------------------------------------------------
' Find the last used Row on a Worksheet
' --------------------------------------------------------------------------------
If WorksheetFunction.CountA(ws.Cells) > 0 Then
' Search for any entry, by searching backwards by Rows.
FindLastRow = ws.Cells.Find(What:="*", After:=ws.range("a1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
End If
End Function
Antwoord 5, autoriteit 4%
Aangezien de oorspronkelijke vraag gaat over problemenmet het vinden van de laatste cel, in dit antwoord zal ik de verschillende manieren opsommen waarop u onverwachte resultaten kunt krijgen; zie mijn antwoord op “Hoe vind ik de laatste rij die gegevens bevat in het Excel-blad met een macro?”voor mijn mening over het oplossen hiervan.
Ik zal beginnen met het antwoord door sancho.sen de opmerking van GlennFromIowa, nog meer details toevoegend:
[…] men moet eerst beslissen wat als gebruikt wordt beschouwd. Ik zie minstens 6 betekenissen. Cel heeft:
- 1) gegevens, d.w.z. een formule, mogelijk resulterend in een lege waarde;
- 2) een waarde, d.w.z. een niet-lege formule of constante;
- 3) opmaak;
- 4) voorwaardelijke opmaak;
- 5) een vorm (inclusief commentaar) die de cel overlapt;
- 6) betrokkenheid bij een tabel (lijstobject).
Op welke combinatie wilt u testen? Sommige (zoals tabellen) kunnen moeilijker te testen zijn en sommige zijn zeldzaam (zoals een vorm buiten het gegevensbereik), maar andere kunnen variëren op basis van de situatie (bijv. formules met lege waarden).
Andere dingen die u zou kunnen overwegen:
- A) Kunnen er verborgen rijen(bijv. autofilter), lege cellenof lege rijen zijn?
- B) Wat voor soort prestatie is acceptabel?
- C) Kan de VBA-macro de werkmap of de applicatie-instellingen op enigerlei wijze beïnvloeden?
Laten we met dat in gedachten eens kijken hoe de gebruikelijke manieren om de “laatste cel” te krijgen onverwachte resultaten kunnen opleveren:
- De
.End(xlDown)
-code van de vraag zal het gemakkelijkst breken (bijv. met een enkele niet-lege celof wanneer er lege cellen in tussen) om de redenen uitgelegd in de antwoord door Siddharth Routhier (zoek naar “xlDown is even onbetrouwbaar.”) 👎 - Elke oplossing op basis van
Count
ing (CountA
ofCells*.Count
) of.CurrentRegion
zal ook breken in aanwezigheid van lege cellen of rijen 👎 - Een oplossing met
.End(xlUp)
om achteruit te zoeken vanaf het einde van een kolom zal, net als CTRL+UP, zoeken naar gegevens(formules die een spatie produceren waarde worden beschouwd als “gegevens”) in zichtbare rijen(dus het gebruik ervan met autofilter ingeschakeld kan onjuiste resultaten opleveren ⚠️).Je moet ervoor zorgen dat je de standaard valkuilen vermijdt (voor details verwijs ik opnieuw naar het antwoord van Siddharth Routhier, zoek de sectie “Vind laatste rij in een kolom”), zoals hard-coding van de laatste rij (
Range("A65536").End(xlUp)
) in plaats van te vertrouwen opsht.Rows.Count
. .SpecialCells(xlLastCell)
is gelijk aan CTRL+END en retourneert de onderste en meest rechtse cel van het “gebruikte bereik”, dus alle voorbehouden die van toepassing zijn op het vertrouwen op het “gebruikte bereik”. bereik”, zijn ook van toepassing op deze methode. Bovendien wordt het “gebruikte bereik” alleen gereset bij het opslaan van de werkmap en bij het openen vanworksheet.UsedRange
, dusxlLastCell
kan verouderde resultaten opleveren⚠️ met niet-opgeslagen wijzigingen (bijv. rijen zijn verwijderd). Zie het antwoord in de buurt van dotNET.sht.UsedRange
(in detail beschreven in het antwoord van sancho.shier) houdt rekening met zowel gegevens als opmaak(hoewel niet voorwaardelijke opmaak) en stelt het “gebruikte bereik” van het werkblad opnieuw in, wat al dan niet is wat je wilt.Merk op dat een veelvoorkomende fout ️is om
.UsedRange.Rows.Count
⚠️ te gebruiken, wat het aantal rijenin het gebruikte bereik, niet het laatste rijnummer(ze zullen anders zijn als de eerste paar rijen leeg zijn), zie voor details newguy’s antwoord op Hoe kan ik de laatste rij met gegevens in het Excel-blad vinden met een macro?.Find
stelt u in staat om de laatste rij met alle gegevens (inclusief formules) of een niet-lege waarde in elke kolomte vinden. U kunt kiezen of u geïnteresseerd bent in formules of waarden, maar het addertje onder het gras is dat het de standaardinstellingen in het Excel-dialoogvenster Zoeken terugzet️️⚠️, wat zeer verwarrend kan zijn voor uw gebruikers. Het moet ook zorgvuldig worden gebruikt, zie het antwoord van Siddharth Routhier (sectie “Vind laatste rij in een blad”)- Explicietere oplossingen die individuele
Cells
‘ in een lus controleren, zijn over het algemeen langzamer dan het hergebruiken van een Excel-functie (hoewel dit nog steeds performant kan zijn), maar laten je precies specificeren wat je wilt vinden. Zie mijn oplossingop basis vanUsedRange
en VBA-arrays om de laatste cel met gegevens in de gegeven column — het behandelt verborgen rijen, filters, spaties, wijzigt de standaardwaarden voor zoeken niet en is behoorlijk performant.
Welke oplossing u ook kiest, wees voorzichtig
- om
Long
te gebruiken in plaats vanInteger
om de rijnummers op te slaan (om te voorkomen dat jeOverflow
krijgt met meer dan 65.000 rijen) en - om altijd het werkblad waarmee u werkt te specificeren (bijv.
Dim ws As Worksheet ... ws.Range(...)
in plaats vanRange(...)
) - bij gebruik van
.Value
(wat eenVariant
is), vermijd impliciete casts zoals.Value <> ""
omdat ze zullen mislukken als de cel een foutwaarde bevat.
Antwoord 6, autoriteit 2%
Ik zou aan het antwoord van Siddarth Rout willen toevoegen dat de CountA-aanroep kan worden overgeslagen door Find een Range-object te laten retourneren in plaats van een rijnummer, en vervolgens het geretourneerde Range-object te testen om te zien of het niets is ( leeg werkblad).
Ik zou ook willen dat mijn versie van een LastRow-procedure een nul retourneert voor een leeg werkblad, dan weet ik dat het leeg is.
Antwoord 7, autoriteit 2%
Ik vraag me af dat niemand dit heeft genoemd, maar de gemakkelijkste manier om de laatst gebruikte cel te krijgen is:
Function GetLastCell(sh as Worksheet) As Range
GetLastCell = sh.Cells(1,1).SpecialCells(xlLastCell)
End Function
Dit retourneert in wezen dezelfde cel die u krijgt door Ctrl+ Endna het selecteren van Cel A1
.
Een waarschuwing: Excel houdt de meest rechtse cel bij die ooit in een werkblad is gebruikt. Dus als u bijvoorbeeld iets invoert in B3en iets anders in H8en later de inhoud van H8verwijdert, drukt u op Ctrl + Endbrengt je nog steeds naar de cel H8. De bovenstaande functie zal hetzelfde gedrag vertonen.
Antwoord 8
sub last_filled_cell()
msgbox range("A65536").end(xlup).row
end sub
Hier is A65536de laatste cel in kolom A. Deze code is getest in Excel 2003.
Antwoord 9
Hoewel deze vraag de laatste rij probeert te vinden met VBA, denk ik dat het goed zou zijn om een matrixformule op te nemen voor de werkbladfunctie, aangezien deze vaak wordt bezocht:
{=ADDRESS(MATCH(INDEX(D:D,MAX(IF(D:D<>"",ROW(D:D)-ROW(D1)+1)),1),D:D,0),COLUMN(D:D))}
Je moet de formule invoeren zonder haakjes en vervolgens op Shift+ Ctrl+ Enterdrukken om er een matrixformule van te maken.
Dit geeft je het adres van de laatst gebruikte cel in de kolom D.
Met dank aan pgsystemtester, dit geeft je het rijnummer van de laatst gebruikte cel:
{=MATCH(INDEX(D:D,MAX(IF(D:D<>"",ROW(D:D)-ROW(D1)+1)),1),D:D,0)}
Antwoord 10
Bijgewerkt eind 2021
Met Excel’s nieuwe berekeningsengine en arrayfunctionaliteit, en Filterfunctie, ik denk dat dit onderwerp nu veel minder omstreden zou moeten zijn en dat de onderstaande opties de beste mix van snelheid, betrouwbaarheid en eenvoud bieden (wat moeilijk te balanceren is gebleken in het verleden, zoals de talrijke berichten hier illustreren).
Ook definieer ik last used
als NIET leegzoals gedefinieerd door de isBlankfunctie.
Excel-formule
Houd er rekening mee dat de filterfunctie het veel eenvoudiger maakt om een laatste cel te krijgen met behulp van de onderstaande formules voor een specifieke rij of kolom (in dit geval Column A
of Row 1
):
=MAX(FILTER(ROW(A:A),NOT(ISBLANK(A:A))))
=MAX(FILTER(COLUMN(1:1),NOT(ISBLANK(1:1))))
VBA-functie voor specifiek bereik laatste rij
Met de bovenstaande functie kunnen we het omzetten in een VBA-functie, maar het nog sneller maken door het bereik te beperken, terwijl we de mogelijkheden uitbreiden door meerdere kolommen te maken (dankzij Chris Neilsenvoor directe feedback, tweeken/suggesties). Ik vond ook een enorme snelheidsverbetering door het bereik van elke kolom alleen een bereik te maken met een rij HOGER dan de vorige laatste rij.
Function FindLastRowInRange(someColumns As Range) As Long
Const zFx = "=MAX(FILTER(ROW(????),NOT(ISBLANK(????)),0))"
Dim tRng As Range, i As Long, tRow As Long, nRng As Range
With someColumns.Worksheet
Set tRng = Intersect(someColumns.EntireColumn, .UsedRange)
For i = 1 To tRng.Columns.Count
Set pRng = Intersect(tRng.Columns(i), _
Range(.Rows(FindLastRowInRange + 1), .Rows(.Rows.Count)))
If Not pRng Is Nothing Then
tRow = .Evaluate(Replace(zFx, "????", _
pRng.Address, 1, -1))
If tRow > FindLastRowInRange Then _
FindLastRowInRange = tRow
End If
Next i
End With
End Function
VBA-functie voor laatste rij in werkblad
Om het hele werkblad (alle kolommen) te bekijken, raad ik aan een andere VBA-formule te gebruiken die naar de vorige verwijst, maar die een Vluchtige functie. Dit zorgt ervoor dat de formule wordt bijgewerkt met allewijzigingen in een werkblad. Het is duidelijk dat je deze twee formules kunt combineren, maar ik geef er de voorkeur aan het gebruik van vluchtige functies te beperken.
Function FindLastRowInSheet(anywhereInSheet As Range) As Long
Application.Volatile
FindLastRowInSheet = FindLastRowInRange(anywhereInSheet.Worksheet.UsedRange)
End Function
Voordelen in vergelijking met andere opties
- Maakt sommige of ALLE rijen/kolommen in werkblad mogelijk zonder de aanpak te veranderen.
- Geen mogelijkheid om verborgen rijen te missen, zoals een risico is met
xlup
- Negeert problemen met opgemaakt/gebruikt bereik.
- Beïnvloedt de instellingen van
Find
van de gebruiker niet. - Gebruikt werkbladfunctionaliteit die sneller is dan VBA-berekeningen.
- Geen telcellen (performance hog).
Hopelijk beëindigt dit het debat, maar als iemand hier zwakke punten in vindt, deel het dan alsjeblieft.
Antwoord 11
Ik was op zoek naar een manier om de CTRL+Shift+Endna te bootsen, dus de dotNET-oplossing is geweldig, behalve met mijn Excel 2010 Ik moet een set
toevoegen als ik een fout wil vermijden:
Function GetLastCell(sh As Worksheet) As Range
Set GetLastCell = sh.Cells(1, 1).SpecialCells(xlLastCell)
End Function
en hoe u dit zelf kunt controleren:
Sub test()
Dim ws As Worksheet, r As Range
Set ws = ActiveWorkbook.Sheets("Sheet1")
Set r = GetLastCell(ws)
MsgBox r.Column & "-" & r.Row
End Sub
Antwoord 12
Sub lastRow()
Dim i As Long
i = Cells(Rows.Count, 1).End(xlUp).Row
MsgBox i
End Sub
sub LastRow()
'Paste & for better understanding of the working use F8 Key to run the code .
dim WS as worksheet
dim i as long
set ws = thisworkbook("SheetName")
ws.activate
ws.range("a1").select
ws.range("a1048576").select
activecell.end(xlup).select
i= activecell.row
msgbox "My Last Row Is " & i
End sub
Antwoord 13
Voor de laatste 3+ jaar zijn dit de functies die ik gebruik voor het vinden van de laatste rij en laatste kolom per gedefinieerde kolom (voor rij) en rij (voor kolom):
Laatste kolom:
Function lastCol(Optional wsName As String, Optional rowToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
lastCol = ws.Cells(rowToCheck, ws.Columns.Count).End(xlToLeft).Column
End Function
Laatste rij:
Function lastRow(Optional wsName As String, Optional columnToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
lastRow = ws.Cells(ws.Rows.Count, columnToCheck).End(xlUp).Row
End Function
Voor het geval van de OP is dit de manier om de laatste rij in kolom E
te krijgen:
Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
Laatste rij, lege rijen met gegevens tellen:
Hier kunnen we de bekende Excel-formules, die ons de laatste rij van een werkblad in Excel geven, zonder VBA erbij te betrekken – =IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
Om dit in VBA te zetten en niets in Excel te schrijven, met behulp van de parameters voor de laatste functies, zou zoiets in gedachten kunnen worden gehouden:
Public Function LastRowWithHidden(Optional wsName As String, Optional columnToCheck As Long = 1) As Long
Dim ws As Worksheet
If wsName = vbNullString Then
Set ws = ActiveSheet
Else
Set ws = Worksheets(wsName)
End If
Dim letters As String
letters = ColLettersGenerator(columnToCheck)
LastRowWithHidden = ws.Evaluate("=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(" & letters & "))),ROW(" & letters & " )),0)")
End Function
Function ColLettersGenerator(col As Long) As String
Dim result As Variant
result = Split(Cells(1, col).Address(True, False), "$")
ColLettersGenerator = result(0) & ":" & result(0)
End Function
Antwoord 14
Laatste rij in een normaal bereik of een tabel (ListObject)
- Het vinden van de laatste rij vereist het gebruik van verschillende methoden als het bereik een normaal bereik of een tabel is (Lijstobject).
- Het vinden van de laatste rij in tabellen vereist het specificeren van aanvullende parameters (tabelnaam , de relatieve positie van de kolom ten opzichte van de eerste tabelkolom).
Ik heb deze universele functie voor de laatste rij gemaakt, ongeacht het bereiktype. Geef het gewoon welke celverwijzing dan ook en het zal de laatste rij retourneren.
Geen gedoe om bereikkenmerken te kennen, vooral als uw bereiken soms een normaal bereik zijn en soms een ListObject.
Het gebruik van een normale bereikmethode op een tabel kan verkeerde resultaten opleveren.
Natuurlijk kun je van tevoren plannen en elke keer de juiste methode gebruiken, maar waarom zou je je druk maken als je een universele functie kunt gebruiken?
Sub RunMyLastRow() Dim Result As Long Result = MyLastRow(Worksheets(1).Range("A1")) End Sub
Function MyLastRow(RefrenceRange As Range) As Long
Dim WS As Worksheet
Dim TableName As String
Dim ColNumber As Long
Dim LastRow As Long
Dim FirstColumnTable As Long
Dim ColNumberTable As Long
Set WS = RefrenceRange.Worksheet
TableName = GetTableName(RefrenceRange)
ColNumber = RefrenceRange.Column
''If the table (ListObject) does not start in column "A" we need to calculate the
''first Column table and how many Columns from its beginning the Column is located.
If TableName <> vbNullString Then
FirstColumnTable = WS.ListObjects(TableName).ListColumns(1).Range.Column
ColNumberTable = ColNumber - FirstColumnTable + 1
End If
If TableName = vbNullString Then
LastRow = WS.Cells(WS.Rows.Count, ColNumber).End(xlUp).Row
Else
LastRow = WS.ListObjects(TableName).ListColumns(ColNumberTable).Range.Find( _
What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
End If
MyLastRow = LastRow
End Function
''Get Table Name by Cell Range Function GetTableName(RefrenceRange As Range) As String If RefrenceRange.ListObject Is Nothing Then GetTableName = vbNullString Else GetTableName = RefrenceRange.ListObject.Name End If End Function