Kiedy chcę znaleźć ostatnio używaną wartość komórki, używam:
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
Otrzymuję nieprawidłowy wynik, gdy wstawiam pojedynczy element do komórki. Ale gdy wstawię więcej niż jedną wartość do komórki, wynik jest poprawny. Jaki jest tego powód?
excel
vba
excel-formula
James
źródło
źródło
Odpowiedzi:
UWAGA : Zamierzam uczynić z tego „postu z jednego miejsca”, w którym można znaleźć
Correct
sposób, aby znaleźć ostatni wiersz. Dotyczy to również najlepszych praktyk, które należy stosować przy znajdowaniu ostatniego rzędu. Dlatego będę go aktualizować za każdym razem, gdy napotkam nowy scenariusz / informacje.Niewiarygodne sposoby znalezienia ostatniego rzędu
Niektóre z najczęstszych sposobów znajdowania ostatniego rzędu, które są wysoce niewiarygodne i dlatego nigdy nie powinny być używane.
UsedRange
powinna nigdy być używane, aby znaleźć ostatnią komórkę, która ma dane. Jest wysoce zawodny. Wypróbuj ten eksperyment.Wpisz coś w komórce
A5
. Teraz, kiedy obliczysz ostatni wiersz dowolną z metod podanych poniżej, da ci 5. Teraz pokoloruj komórkę naA10
czerwono. Jeśli teraz użyjesz dowolnego z poniższych kodów, nadal otrzymasz 5. Jeśli skorzystasz zUsedrange.Rows.Count
tego, co otrzymasz? To nie będzie 5.Oto scenariusz pokazujący, jak
UsedRange
działa.xlDown
jest równie niewiarygodne.Rozważ ten kod
Co by się stało, gdyby tylko jedna komórka (
A1
) posiadała dane? W końcu dotrzesz do ostatniego wiersza w arkuszu! To tak, jakby wybrać komórkę,A1
a następnie nacisnąć Endklawisz, a następnie nacisnąć Down Arrowklawisz. Zapewni to również niewiarygodne wyniki, jeśli w zakresie będą puste komórki.CountA
jest również niewiarygodna, ponieważ da ci niepoprawny wynik, jeśli pomiędzy nimi będą puste komórki.A więc należy unikać stosowania
UsedRange
,xlDown
iCountA
aby znaleźć ostatnią komórkę.Znajdź ostatni wiersz w kolumnie
Aby znaleźć ostatni wiersz w kolumnie E, użyj tego
Jeśli zauważysz, że mamy
.
wcześniejRows.Count
. Często zdecydowaliśmy się to zignorować. Zobacz TO pytanie dotyczące możliwego błędu, który możesz otrzymać. Zawsze radzę używać.
przedRows.Count
iColumns.Count
. To pytanie jest klasycznym scenariuszem, w którym kod zawiedzie, ponieważRows.Count
zwraca wyniki65536
dla Excela 2003 i wcześniejszych oraz1048576
dla Excela 2007 i późniejszych. PodobnieColumns.Count
zwraca256
i16384
odpowiednio.Powyższy fakt, że Excel 2007+ ma
1048576
wiersze, podkreśla również fakt, że zawsze powinniśmy zadeklarować zmienną, która będzie przechowywać wartość wiersza, ponieważLong
zamiast tegoInteger
pojawi sięOverflow
błąd.Zauważ, że to podejście spowoduje pominięcie ukrytych wierszy. Patrząc wstecz na mój zrzut ekranu powyżej dla kolumny A , jeśli wiersz 8 byłby ukryty, to podejście powróciłoby
5
zamiast8
.Znajdź ostatni wiersz w arkuszu
Aby znaleźć
Effective
ostatni wiersz w arkuszu, użyj tego. Zwróć uwagę na użycieApplication.WorksheetFunction.CountA(.Cells)
. Jest to wymagane, ponieważ jeśli nie ma komórek z danymi w arkuszu, to.Find
da ciRun Time Error 91: Object Variable or With block variable not set
Znajdź ostatni wiersz w tabeli (ListObject)
Obowiązują te same zasady, na przykład aby uzyskać ostatni wiersz w trzeciej kolumnie tabeli:
źródło
Usedrange.Rows.Count
tego, co otrzymujesz? To nie będzie 5. Usedrange jest bardzo zawodny w znalezieniu ostatniego rzędu.remembers
ostatnie ustawienie. Nawet jeśli wykonasz ręcznie aFind
, pamięta ostatnie ustawienie, które jest dobrodziejstwem, jeśli ktoś zna ten „fakt”UsedRange
( znajdowanie ostatniej komórki zawierającej dane jest bardzo zawodny ) jest mylący.UsedRange
po prostu nie jest przeznaczony do tego celu, nawet jeśli w niektórych przypadkach może dać poprawny wynik. Myślę, że zaproponowany eksperyment zwiększa zamieszanie. Wynik uzyskany za pomocąUsedRange
($ A $ 1: $ A $ 8) nie zależy od pierwszego wprowadzenia danych i ich usunięcia. Liczba po prawej stronie pozostanie taka sama, nawet bez wpisania danych i ich usunięcia. Proszę zobaczyć moją odpowiedź.Uwaga: odpowiedź została uzasadniona tym komentarzem . Cel
UsedRange
jest inny niż wymieniony w powyższej odpowiedzi.Jeśli chodzi o właściwy sposób znalezienia ostatnio używanej komórki, najpierw należy zdecydować, co uważa się za wykorzystane , a następnie wybrać odpowiednią metodę . Rozumiem co najmniej trzy znaczenia:
Używane = niepuste, tzn. Posiadające dane .
Używany = „... w użyciu, co oznacza sekcję zawierającą dane lub formatowanie ”. Zgodnie z oficjalną dokumentacją jest to kryterium stosowane przez program Excel podczas zapisywania. Zobacz także tę oficjalną dokumentację . Jeśli nie jest się tego świadomym, kryterium może dawać nieoczekiwane wyniki, ale może być również celowo wykorzystywane (rzadziej, na pewno), np. W celu wyróżnienia lub wydrukowania określonych regionów, które ostatecznie mogą nie zawierać danych. I, oczywiście, pożądane jest jako kryterium zakresu do zastosowania podczas zapisywania skoroszytu, aby nie stracić części pracy.
Używany = „... w użyciu, co oznacza sekcję zawierającą dane lub formatowanie ” lub formatowanie warunkowe. To samo co 2., ale także z komórkami, które są celem dowolnej reguły formatowania warunkowego.
Jak znaleźć ostatnio używaną komórkę, zależy od tego, czego chcesz (twoje kryterium) .
W przypadku kryterium 1 proponuję przeczytać tę odpowiedź . Zauważ, że
UsedRange
jest cytowany jako niewiarygodny. Myślę, że jest to mylące (tzn. „Niesprawiedliwe”UsedRange
), ponieważUsedRange
po prostu nie ma na celu zgłoszenia ostatniej komórki zawierającej dane. Dlatego nie należy go stosować w tym przypadku, jak wskazano w tej odpowiedzi. Zobacz także ten komentarz .Dla kryterium 2
UsedRange
jest najbardziej niezawodną opcją w porównaniu z innymi opcjami również przeznaczonymi do tego zastosowania. Nie trzeba nawet zapisywać skoroszytu, aby upewnić się, że ostatnia komórka została zaktualizowana. Ctrl+ Endprzejdzie do niewłaściwej komórki przed zapisaniem („Ostatnia komórka nie jest resetowana, dopóki nie zapiszesz arkusza roboczego”, z http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10% 29.aspx . Jest to stare odniesienie, ale pod tym względem ważne).Dla kryterium 3 nie znam żadnej wbudowanej metody . Kryterium 2 nie uwzględnia formatowania warunkowego. Można mieć sformatowane komórki oparte na formułach, które nie są wykrywane przez +
UsedRange
lub . Na rysunku ostatnia komórka to B3, ponieważ formatowanie zostało do niej wyraźnie zastosowane. Komórki B6: D7 mają format wywodzący się z reguły formatowania warunkowego, a nawet nie jest to wykrywane . Uwzględnienie tego wymagałoby programowania VBA.CtrlEndUsedRange
Co do twojego konkretnego pytania : jaki jest tego powód?
Twój kod wykorzystuje pierwszą komórkę w swoim przedziale E4: E48 jako trampoliny, na skoki w dół
End(xlDown)
.„Błędne” dane wyjściowe zostaną uzyskane, jeśli w twoim zakresie nie ma niepustych komórek oprócz pierwszego. Następnie przeskakujesz w ciemności , tj. W dół arkusza roboczego (powinieneś zauważyć różnicę między pustym i pustym ciągiem !).
Uwaga:
Jeśli twój zakres zawiera niesąsiadujące niepuste komórki, to również da zły wynik.
Jeśli istnieje tylko jedna niepusta komórka, ale nie jest to pierwsza, kod nadal będzie dawał poprawny wynik.
źródło
Stworzyłem tę funkcję one-stop do określania ostatniego wiersza, kolumny i komórki, czy to dla danych, sformatowanych (zgrupowanych / skomentowanych / ukrytych) komórek, czy formatowania warunkowego .
Wyniki wyglądają następująco:
Aby uzyskać bardziej szczegółowe wyniki, niektóre wiersze w kodzie można odkomentować:
Istnieje jedno ograniczenie - jeśli w arkuszu znajdują się tabele, wyniki mogą stać się niewiarygodne, dlatego postanowiłem w tym przypadku unikać uruchamiania kodu:
źródło
Jedna ważna uwaga, o której należy pamiętać podczas korzystania z rozwiązania ...
... ma zapewnić, że twoja
LastRow
zmienna jestLong
typu:W przeciwnym razie w niektórych skoroszytach .XLSX wystąpią błędy PRZEPŁYWU w niektórych sytuacjach
To jest moja enkapsulowana funkcja, którą upuszczam do różnych zastosowań kodu.
źródło
Dodałbym do odpowiedzi udzielonej przez Siddarth Routa, aby powiedzieć, że wywołanie CountA może zostać pominięte, ponieważ funkcja Znajdź zwraca obiekt Range zamiast numeru wiersza, a następnie przetestuj zwracany obiekt Range, aby sprawdzić, czy jest to Nic (pusty arkusz roboczy) .
Chciałbym również, aby moja wersja dowolnej procedury LastRow zwróciła zero dla pustego arkusza roboczego, a następnie mogę wiedzieć, że jest pusta.
źródło
Zastanawiam się, że nikt o tym nie wspominał, ale najłatwiejszym sposobem uzyskania ostatnio używanej komórki jest:
To zasadniczo zwraca tę samą komórkę, którą otrzymujesz przez Ctrl+ Endpo wybraniu Komórki
A1
.Uwaga: program Excel śledzi najbardziej prawą dolną komórkę, jaką kiedykolwiek użyto w arkuszu. Więc jeśli na przykład wpiszesz coś w B3, a coś innego w H8, a następnie usuniesz zawartość H8 , naciśnięcie Ctrl+ Endnadal przeniesie Cię do komórki H8 . Powyższa funkcja będzie miała takie samo zachowanie.
źródło
Last Cell
w programie Excel czasami odnosi się do pustej komórki (odUsed Range
) innej niżLast Used Cell
;).Cells(1,1).Select()
jest to nieprawda, być możeActiveSheet.Cells(1,1).Select
; Również w VBA nie zaleca się używaniaSelect
;).Set
.Ponieważ oryginalne pytanie dotyczy problemów ze znalezieniem ostatniej komórki, w tej odpowiedzi wymienię różne sposoby uzyskania nieoczekiwanych wyników ; zobacz moją odpowiedź na „Jak znaleźć ostatni wiersz zawierający dane w arkuszu Excel z makrem?” za moje podejście do rozwiązania tego.
Zacznę od rozwinięcia odpowiedzi sancho.s i komentarza GlennFromIowa , dodając jeszcze więcej szczegółów:
Inne rzeczy, które warto rozważyć:
Mając to na uwadze, zobaczmy, w jaki sposób wspólne sposoby uzyskiwania „ostatniej komórki” mogą dawać nieoczekiwane wyniki:
.End(xlDown)
Kod z pytaniem złamie najłatwiej (np z jednym niepustym komórce lub gdy występują puste komórki w między ) z powodów wyjaśnionych w odpowiedzi przez Siddharth frezowania tutaj (wyszukaj „xlDown jest równie wiarygodne.” ) 👎Count
ing (CountA
lubCells*.Count
) lub.CurrentRegion
również ulegnie awarii w obecności pustych komórek lub wierszy 👎.End(xlUp)
na wyszukiwaniu wstecz od końca kolumny będzie, podobnie jak CTRL + UP, wyszukiwać dane (formuły generujące pustą wartość są uważane za „dane”) w widocznych wierszach (więc użycie go z włączonym autofiltrem może dawać nieprawidłowe wyniki ⚠️ ).Musisz uważać, aby uniknąć standardowych pułapek (w celu uzyskania szczegółowych informacji ponownie odniosę się tutaj do odpowiedzi Siddharth Rout , poszukaj sekcji „Znajdź ostatni wiersz w kolumnie” ), na przykład zakodowania ostatniego wiersza (
Range("A65536").End(xlUp)
) zamiast polegać nasht.Rows.Count
..SpecialCells(xlLastCell)
jest równoważne CTRL + END, zwracając najniżej położoną i prawą komórkę „używanego zakresu”, więc wszystkie zastrzeżenia dotyczące polegania na „używanym zakresie” dotyczą również tej metody. Ponadto „używany zakres” jest resetowany tylko podczas zapisywania skoroszytu i uzyskiwania dostępuworksheet.UsedRange
, więcxlLastCell
może dawać nieaktualne wyniki⚠️ z niezapisanymi modyfikacjami (np. Po usunięciu niektórych wierszy). Zobacz pobliską odpowiedź dotNET .sht.UsedRange
(opisany szczegółowo w odpowiedzi tutaj przez sancho.s ) uwzględnia zarówno dane, jak i formatowanie (choć nie formatowanie warunkowe) i resetuje „używany zakres” arkusza roboczego , który może, ale nie musi być tym, czego chcesz.Zauważ, że powszechnym błędem ️ jest użycie
.UsedRange.Rows.Count
⚠️, który zwraca liczbę wierszy w używanym zakresie, a nie ostatni numer wiersza (będą różne, jeśli kilka pierwszych wierszy będzie pustych). Szczegółowe informacje można znaleźć w odpowiedzi newguy na Jak znaleźć ostatni wiersz zawierający dane w arkuszu Excel z makrem?.Find
pozwala znaleźć ostatni wiersz z dowolnymi danymi (w tym formułami) lub niepustą wartością w dowolnej kolumnie . Możesz wybrać, czy interesują Cię formuły, czy wartości, ale haczyk polega na tym, że resetuje ustawienia domyślne w oknie dialogowym Znajdź w programie Excel ️️⚠️, co może być bardzo mylące dla użytkowników. Należy go również ostrożnie stosować, patrz odpowiedź Siddharth Rout tutaj (sekcja „Znajdź ostatni wiersz w arkuszu” )Cells
„w pętli” są na ogół wolniejsze niż ponowne użycie funkcji Excela (choć nadal może być wydajne), ale pozwalają dokładnie określić, co chcesz znaleźć. Zobacz moje rozwiązanie oparte naUsedRange
tablicach i VBA, aby znaleźć ostatnią komórkę z danymi w danej kolumnie - obsługuje ukryte wiersze, filtry, spacje, nie modyfikuje wartości domyślnych Znajdź i jest dość wydajny.Niezależnie od wybranego rozwiązania, zachowaj ostrożność
Long
zamiastInteger
do przechowywania numerów wierszy (aby uniknąć uzyskaniaOverflow
więcej niż 65 tysięcy wierszy) iDim ws As Worksheet ... ws.Range(...)
zamiastRange(...)
).Value
(co jest aVariant
) unikaj niejawnych rzutowań,.Value <> ""
ponieważ zakończą się niepowodzeniem, jeśli komórka zawiera wartość błędu.źródło
Jednak to pytanie ma na celu znalezienie ostatniego wiersza za pomocą VBA, myślę, że dobrze byłoby dołączyć formułę tablicową dla funkcji arkusza, ponieważ jest ona często odwiedzana:
Musisz wprowadzić formułę bez nawiasów, a następnie nacisnąć Shift+ Ctrl+, Enteraby stała się formułą tablicową.
To da ci adres ostatnio używanej komórki w kolumnie D.
źródło
Oto A65536ostatnia komórka w kolumnie A, ten kod został przetestowany w programie Excel 2003.
źródło
Szukałem sposobu naśladowania CTRL+ Shift+ End, więc rozwiązanie dotNET jest świetne, z wyjątkiem mojego Excela 2010 muszę dodać,
set
jeśli chcę uniknąć błędu:i jak to sprawdzić samemu:
źródło
Oto moje dwa centy.
IMHO ryzyko ukrytego wiersza z wykluczeniem danych jest zbyt duże, aby
xlUp
można było uznać je za odpowiedź One Stop . Zgadzam się, że jest to proste i będzie działać przez większość czasu, ale stwarza ryzyko zaniżenia ostatniego rzędu bez żadnego ostrzeżenia. To może produkować katastrofalnych wyników w pewnym poinit dla kogoś, kto skoczył na stosie Overlow i szukałem do „pewien sposób”, aby uchwycić tę wartość.Find
Metoda jest bez zarzutu, a ja pochwalam to jako jeden przystanek Odpowiedź . Jednak wada zmianyFind
ustawień może być denerwująca, szczególnie jeśli jest to część UDF.Pozostałe opublikowane odpowiedzi są w porządku, jednak złożoność staje się nieco nadmierna. Oto moja próba znalezienia równowagi między niezawodnością, minimalną złożonością i niestosowaniem
Find
.Dlaczego to jest dobre:
Find
ustawieńDlaczego to jest złe:
Uważam jednak, że rozwiązanie kompleksowe, które ma wadę polegającą na nieuporządkowaniu
find
ustawień lub spowolnieniu działania, jest lepszym rozwiązaniem ogólnym. Użytkownik może następnie majstrować przy swoich ustawieniach, aby spróbować poprawić, wiedząc, co się dzieje z ich kodem. KorzystaniexLUp
nie ostrzega przed potencjalnym ryzykiem i może kontynuować, kto wie, jak długo nie wiedząc, że ich kod nie działa poprawnie.źródło
Od ponad 3 lat są to funkcje, których używam do znajdowania ostatniego wiersza i ostatniej kolumny na zdefiniowaną kolumnę (dla wiersza) i wiersz (dla kolumny):
Ostatnia kolumna:
Ostatni wiersz:
W przypadku PO jest to sposób na uzyskanie ostatniego wiersza w kolumnie
E
:Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
Ostatni wiersz, licząc puste wiersze z danymi:
W tym przypadku możemy użyć dobrze znanych formuł Excela , które dają nam ostatni wiersz arkusza roboczego w Excelu, bez udziału VBA -
=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
Aby umieścić to w VBA i nie pisać niczego w Excelu, używając parametrów dla tych ostatnich funkcji, można mieć na myśli coś takiego:
źródło
EVAL()
słynnej formuły Excel. Chociaż ludzie mogą myśleć, żeEval()
to zło, to kolejna ciekawa historia, o której można pisać ...źródło