Ketika saya ingin menemukan nilai sel yang terakhir digunakan, saya menggunakan:
Dim LastRow As Long
LastRow = Range("E4:E48").End(xlDown).Row
Debug.Print LastRow
Saya mendapatkan output yang salah ketika saya memasukkan satu elemen ke dalam sel. Tetapi ketika saya memasukkan lebih dari satu nilai ke dalam sel, hasilnya benar. Apa alasan di balik ini?
excel
vba
excel-formula
james
sumber
sumber
Jawaban:
CATATAN : Saya bermaksud menjadikan ini "pos satu atap" tempat Anda dapat menggunakan
Correct
cara untuk menemukan baris terakhir. Ini juga akan mencakup praktik terbaik yang harus diikuti ketika menemukan baris terakhir. Dan karenanya saya akan terus memperbaruinya setiap kali saya menemukan skenario / informasi baru.Cara yang tidak dapat diandalkan untuk menemukan baris terakhir
Beberapa cara paling umum untuk menemukan baris terakhir yang sangat tidak dapat diandalkan dan karenanya tidak boleh digunakan.
UsedRange
harus TIDAK PERNAH digunakan untuk menemukan sel terakhir yang memiliki data. Ini sangat tidak bisa diandalkan. Coba percobaan ini.Ketikkan sesuatu di sel
A5
. Sekarang ketika Anda menghitung baris terakhir dengan salah satu metode yang diberikan di bawah ini, itu akan memberi Anda 5. Sekarang warna selA10
merah. Jika sekarang Anda menggunakan salah satu kode di bawah ini, Anda masih akan mendapatkan 5. Jika Anda menggunakanUsedrange.Rows.Count
apa yang Anda dapatkan? Tidak akan 5.Berikut ini adalah skenario untuk menunjukkan cara
UsedRange
kerjanya.xlDown
sama-sama tidak bisa diandalkan.Pertimbangkan kode ini
Apa yang akan terjadi jika hanya ada satu sel (
A1
) yang memiliki data? Anda akan mencapai baris terakhir di lembar kerja! Ini seperti memilih selA1
dan kemudian menekan Endtombol dan kemudian menekan Down Arrowtombol. Ini juga akan memberi Anda hasil yang tidak dapat diandalkan jika ada sel kosong dalam rentang.CountA
juga tidak dapat diandalkan karena akan memberi Anda hasil yang salah jika ada sel kosong di antaranya.Dan karenanya seseorang harus menghindari penggunaan
UsedRange
,xlDown
danCountA
untuk menemukan sel terakhir.Temukan Baris Terakhir dalam Kolom
Untuk menemukan Baris terakhir di Kolom E gunakan ini
Jika Anda perhatikan bahwa kami memiliki
.
sebelumnyaRows.Count
. Kami sering memilih untuk mengabaikannya. Lihat pertanyaan INI tentang kemungkinan kesalahan yang mungkin Anda dapatkan. Saya selalu menyarankan menggunakan.
sebelumRows.Count
danColumns.Count
. Pertanyaan itu adalah skenario klasik di mana kode akan gagal karenaRows.Count
pengembalian65536
untuk Excel 2003 dan sebelumnya dan1048576
untuk Excel 2007 dan yang lebih baru. Demikian pulaColumns.Count
pengembalian256
dan16384
, masing-masing.Fakta di atas bahwa Excel 2007+ memiliki
1048576
baris juga menekankan pada fakta bahwa kita harus selalu mendeklarasikan variabel yang akan menyimpan nilai baris karenaLong
alih-alihInteger
Anda akan mendapatkanOverflow
kesalahan.Perhatikan bahwa pendekatan ini akan melewati setiap baris tersembunyi. Melihat kembali tangkapan layar saya di atas untuk kolom A , jika baris 8 disembunyikan, pendekatan ini akan kembali
5
sebagai gantinya8
.Temukan Baris Terakhir dalam Lembaran
Untuk menemukan
Effective
baris terakhir di lembar, gunakan ini. Perhatikan penggunaanApplication.WorksheetFunction.CountA(.Cells)
. Ini diperlukan karena jika tidak ada sel dengan data di lembar kerja maka.Find
akan memberi AndaRun Time Error 91: Object Variable or With block variable not set
Temukan Baris Terakhir dalam Tabel (ListObject)
Prinsip yang sama berlaku, misalnya untuk mendapatkan baris terakhir di kolom ketiga tabel:
sumber
Usedrange.Rows.Count
apa yang Anda dapatkan? Tidak akan menjadi 5. Usedrange sangat tidak dapat diandalkan untuk menemukan baris terakhir.remembers
pengaturan terakhir. Bahkan ketika Anda secara manual melakukanFind
, itu mengingat pengaturan terakhir yang sebenarnya adalah anugerah jika ada yang tahu "fakta" iniUsedRange
( sangat tidak dapat diandalkan untuk menemukan sel terakhir yang memiliki data ) menyesatkan.UsedRange
sama sekali tidak dimaksudkan untuk tujuan itu, meskipun dalam beberapa kasus mungkin memberikan hasil yang benar. Saya pikir eksperimen yang diajukan menambah kebingungan. Hasil yang diperoleh denganUsedRange
($ A $ 1: $ A $ 8) tidak bergantung pada memasukkan data terlebih dahulu dan menghapusnya. Angka di sebelah kanan akan tetap sama bahkan tanpa memasukkan data dan menghapusnya. Tolong lihat jawaban saya.Catatan: jawaban ini dimotivasi oleh komentar ini . Tujuannya
UsedRange
berbeda dari apa yang disebutkan dalam jawaban di atas.Adapun cara yang benar untuk menemukan sel yang terakhir digunakan, pertama-tama kita harus memutuskan apa yang dianggap digunakan , dan kemudian memilih metode yang sesuai . Saya mengandung setidaknya tiga makna:
Digunakan = tidak kosong, yaitu memiliki data .
Used = "... in use, artinya bagian yang berisi data atau pemformatan ." Sesuai dokumentasi resmi , ini adalah kriteria yang digunakan oleh Excel pada saat menyimpan. Lihat juga dokumentasi resmi ini . Jika seseorang tidak mengetahui hal ini, kriteria dapat menghasilkan hasil yang tidak terduga, tetapi kriteria tersebut juga dapat secara sengaja dieksploitasi (lebih jarang, pasti), misalnya, untuk menyorot atau mencetak wilayah tertentu, yang pada akhirnya mungkin tidak memiliki data. Dan, tentu saja, diinginkan sebagai kriteria untuk rentang untuk digunakan saat menyimpan buku kerja, jangan sampai kehilangan bagian dari pekerjaan seseorang.
Used = "... in use, artinya bagian yang berisi data atau pemformatan " atau pemformatan bersyarat. Sama seperti 2., tetapi juga termasuk sel yang menjadi target untuk aturan Pemformatan Bersyarat apa pun.
Cara menemukan sel yang terakhir digunakan tergantung pada apa yang Anda inginkan (kriteria Anda) .
Untuk kriteria 1, saya sarankan membaca jawaban ini . Catatan yang
UsedRange
disebut tidak dapat diandalkan. Saya pikir itu menyesatkan (yaitu, "tidak adil" untukUsedRange
), karenaUsedRange
tidak dimaksudkan untuk melaporkan sel terakhir yang berisi data. Jadi itu tidak boleh digunakan dalam kasus ini, seperti yang ditunjukkan dalam jawaban itu. Lihat juga komentar ini .Untuk kriteria 2,
UsedRange
adalah opsi yang paling dapat diandalkan , dibandingkan dengan opsi lain yang juga dirancang untuk penggunaan ini. Bahkan membuatnya tidak perlu untuk menyimpan buku kerja untuk memastikan bahwa sel terakhir diperbarui. Ctrl+ Endakan menuju ke sel yang salah sebelum menyimpan (“Sel terakhir tidak diatur ulang hingga Anda menyimpan lembar kerja”, dari http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10% 29.aspx . Ini adalah referensi lama, tetapi dalam hal ini valid).Untuk kriteria 3, saya tidak tahu metode bawaan apa pun . Kriteria 2 tidak memperhitungkan Pemformatan Bersyarat. Seseorang mungkin memiliki sel yang diformat, berdasarkan pada rumus, yang tidak terdeteksi oleh
UsedRange
atau Ctrl+ End. Dalam gambar, sel terakhir adalah B3, karena pemformatan diterapkan secara eksplisit padanya. Sel B6: D7 memiliki format yang berasal dari aturan Pemformatan Bersyarat, dan ini bahkan tidak terdeteksi olehUsedRange
. Akuntansi untuk ini akan memerlukan beberapa pemrograman VBA.Mengenai pertanyaan spesifik Anda : Apa alasan di balik ini?
Kode Anda menggunakan sel pertama dalam rentang Anda E4: E48 sebagai trampolin, untuk melompat turun bersama
End(xlDown)
.Output "keliru" akan diperoleh jika tidak ada sel non-kosong dalam rentang Anda selain mungkin yang pertama. Kemudian, Anda melompat dalam gelap , yaitu, turun worksheet (Anda harus mencatat perbedaan antara kosong dan string kosong !).
Perhatikan bahwa:
Jika rentang Anda berisi sel tidak kosong yang tidak bersebelahan, maka hasilnya juga akan salah.
Jika hanya ada satu sel yang tidak kosong, tetapi itu bukan yang pertama, kode Anda akan tetap memberikan hasil yang benar.
sumber
Saya membuat fungsi satu atap ini untuk menentukan baris, kolom, dan sel terakhir, baik itu untuk data, diformat (dikelompokkan / dikomentari / disembunyikan) sel atau pemformatan bersyarat .
Hasilnya terlihat seperti ini:
Untuk hasil yang lebih rinci, beberapa baris dalam kode dapat dibatalkan komentar:
Ada satu batasan - jika ada tabel dalam lembar, hasilnya bisa menjadi tidak dapat diandalkan, jadi saya memutuskan untuk menghindari menjalankan kode dalam kasus ini:
sumber
Satu catatan penting yang perlu diingat saat menggunakan solusi ...
... adalah untuk memastikan bahwa
LastRow
variabel AndaLong
bertipe:Kalau tidak, Anda akan mendapatkan kesalahan OVERFLOW dalam situasi tertentu di buku kerja .XLSX
Ini adalah fungsi enkapsulasi saya yang saya masukkan ke berbagai penggunaan kode.
sumber
Saya akan menambahkan ke jawaban yang diberikan oleh Siddarth Rout untuk mengatakan bahwa panggilan CountA dapat dilewati dengan memiliki Temukan mengembalikan objek Range, bukan nomor baris, dan kemudian menguji objek Range yang dikembalikan untuk melihat apakah itu bukan apa-apa (lembar kerja kosong) .
Juga, saya akan meminta versi saya dari prosedur LastRow mengembalikan nol untuk lembar kerja kosong, maka saya bisa tahu itu kosong.
sumber
Saya ingin tahu bahwa tidak ada yang menyebutkan ini, Tapi cara termudah untuk mendapatkan sel yang terakhir digunakan adalah:
Ini pada dasarnya mengembalikan sel yang sama dengan yang Anda dapatkan Ctrl+ Endsetelah memilih Cell
A1
.Peringatan: Excel melacak sel paling kanan bawah yang pernah digunakan dalam lembar kerja. Jadi jika misalnya Anda memasukkan sesuatu di B3 dan sesuatu yang lain di H8 dan kemudian menghapus konten H8 , menekan Ctrl+ Endmasih akan membawa Anda ke sel H8 . Fungsi di atas akan memiliki perilaku yang sama.
sumber
Last Cell
di Excel terkadang merujuk ke sel kosong (dariUsed Range
) yang berbeda dariLast Used Cell
;).Cells(1,1).Select()
itu mungkin tidak validActiveSheet.Cells(1,1).Select
; Juga di VBA tidak disarankan untuk digunakanSelect
;).Set
.Karena pertanyaan awal adalah tentang masalah dengan menemukan sel terakhir, dalam jawaban ini saya akan mencantumkan berbagai cara Anda bisa mendapatkan hasil yang tidak terduga ; lihat jawaban saya untuk "Bagaimana saya bisa menemukan baris terakhir yang berisi data dalam lembar Excel dengan makro?" untuk saya ambil pada pemecahan ini.
Saya akan mulai dengan memperluas jawaban oleh sancho.s dan komentar oleh GlennFromIowa , menambahkan lebih detail:
Hal-hal lain yang mungkin ingin Anda pertimbangkan:
Dengan mengingat hal itu, mari kita lihat bagaimana cara umum mendapatkan "sel terakhir" dapat menghasilkan hasil yang tidak terduga:
.End(xlDown)
kode dari pertanyaan akan mematahkan paling mudah (misalnya dengan sel non-kosong tunggal atau ketika ada sel kosong di antara ) untuk alasan yang dijelaskan dalam jawaban oleh Siddharth Rout sini (mencari "xlDown sama tidak bisa diandalkan." ) 👎Count
(CountA
atauCells*.Count
) atau.CurrentRegion
juga akan pecah di hadapan sel atau baris kosong 👎.End(xlUp)
pencarian mundur dari akhir kolom akan, sama seperti CTRL + UP, mencari data (rumus yang menghasilkan nilai kosong dianggap "data") dalam baris yang terlihat (jadi menggunakannya dengan autofilter yang diaktifkan mungkin menghasilkan hasil yang salah ⚠️ ).Anda harus berhati-hati untuk menghindari jebakan standar (untuk detail saya akan lagi merujuk pada jawaban oleh Siddharth Rout di sini, lihat bagian "Temukan Baris Terakhir dalam Kolom" ), seperti mengkodekan baris terakhir (
Range("A65536").End(xlUp)
) bukannya mengandalkansht.Rows.Count
..SpecialCells(xlLastCell)
setara dengan CTRL + END, mengembalikan sel paling bawah dan paling kanan dari "rentang yang digunakan", jadi semua peringatan yang berlaku untuk mengandalkan "rentang yang digunakan", berlaku untuk metode ini juga. Selain itu, "rentang yang digunakan" hanya direset saat menyimpan buku kerja dan saat mengaksesworksheet.UsedRange
, sehinggaxlLastCell
dapat menghasilkan hasil yang basi⚠️ dengan modifikasi yang belum disimpan (misalnya setelah beberapa baris dihapus). Lihat jawaban terdekat dengan dotNET .sht.UsedRange
(dijelaskan secara terperinci dalam jawaban oleh sancho.s di sini) mempertimbangkan data dan pemformatan (meskipun bukan pemformatan bersyarat) dan mengatur ulang "rentang yang digunakan" dari lembar kerja , yang mungkin atau mungkin tidak seperti yang Anda inginkan.Perhatikan bahwa kesalahan umum adalah ️ untuk digunakan
.UsedRange.Rows.Count
⚠️, yang mengembalikan jumlah baris dalam rentang yang digunakan, bukan nomor baris terakhir (mereka akan berbeda jika beberapa baris pertama kosong), untuk detail lihat jawaban newguy untuk Bagaimana saya dapat menemukan baris terakhir yang berisi data dalam lembar Excel dengan makro?.Find
memungkinkan Anda menemukan baris terakhir dengan data apa pun (termasuk rumus) atau nilai yang tidak kosong di kolom mana pun . Anda dapat memilih apakah Anda tertarik pada rumus atau nilai, tetapi yang menariknya adalah ia menyetel ulang default di dialog Temukan Excel ️️⚠️, yang dapat sangat membingungkan pengguna Anda. Ini juga perlu digunakan dengan hati-hati, lihat jawaban oleh Siddharth Rout di sini (bagian "Temukan Baris Terakhir dalam Lembaran" )Cells
- masing individu dalam satu lingkaran pada umumnya lebih lambat daripada menggunakan kembali fungsi Excel (meskipun masih bisa menjadi performan), tetapi membiarkan Anda menentukan dengan tepat apa yang ingin Anda temukan. Lihat solusi saya berdasarkan padaUsedRange
dan array VBA untuk menemukan sel terakhir dengan data di kolom yang diberikan - ini menangani baris tersembunyi, filter, kosong, tidak mengubah standar Cari dan cukup performan.Solusi apa pun yang Anda pilih, berhati-hatilah
Long
alih-alihInteger
menyimpan nomor baris (untuk menghindari mendapatkanOverflow
lebih dari 65 ribu baris) danDim ws As Worksheet ... ws.Range(...)
alih-alihRange(...)
).Value
(yang merupakanVariant
) hindari gips implisit seperti.Value <> ""
karena mereka akan gagal jika sel berisi nilai kesalahan.sumber
Namun pertanyaan ini mencari untuk menemukan baris terakhir menggunakan VBA, saya pikir akan lebih baik untuk memasukkan formula array untuk fungsi lembar kerja karena ini sering dikunjungi:
Anda harus memasukkan rumus tanpa tanda kurung dan kemudian tekan Shift+ Ctrl+ Enteruntuk menjadikannya rumus array.
Ini akan memberi Anda alamat sel yang terakhir digunakan di kolom D.
sumber
Di sini, A65536adalah sel terakhir di Kolom A kode ini diuji pada excel 2003.
sumber
Saya sedang mencari cara untuk meniru CTRL+ Shift+ End, jadi solusi dotNET sangat bagus, kecuali dengan Excel 2010 saya perlu menambahkan
set
jika saya ingin menghindari kesalahan:dan cara memeriksa ini sendiri:
sumber
Ini dua sen saya.
IMHO, risiko baris tersembunyi dengan data yang dikecualikan terlalu signifikan untuk
xlUp
dianggap sebagai jawaban One stop . Saya setuju itu sederhana dan akan bekerja PALING saat itu, tetapi itu menyajikan risiko mengecilkan baris terakhir, tanpa peringatan. Ini bisa menghasilkan hasil CATASTROPHIC di beberapa poinit untuk seseorang yang melompat di Stack Overlow dan mencari "cara pasti" untuk menangkap nilai ini.The
Find
Metode sempurna dan saya akan menyetujui itu sebagai Jawaban One Stop . Namun kelemahan dari mengubahFind
pengaturan dapat mengganggu, terutama jika ini adalah bagian dari UDF.Jawaban lain yang diposting tidak masalah, namun kerumitannya sedikit berlebihan. Jadi, inilah upaya saya untuk menemukan keseimbangan keandalan, kompleksitas minimal, dan tidak menggunakan
Find
.Kenapa ini bagus:
Find
pengaturanMengapa ini buruk:
Namun, saya pikir One-Stop-Solution yang memiliki kelemahan
find
pengaturan kacau atau melakukan lebih lambat adalah solusi keseluruhan yang lebih baik. Seorang pengguna kemudian dapat mengotak-atik pengaturan mereka untuk mencoba meningkatkan, mengetahui apa yang terjadi dengan kode mereka. MenggunakanxLUp
tidak akan memperingatkan potensi risiko dan mereka dapat melanjutkan untuk yang tahu berapa lama tidak mengetahui kode mereka tidak berfungsi dengan benar.sumber
Selama 3+ tahun terakhir ini adalah fungsi yang saya gunakan untuk menemukan baris terakhir dan kolom terakhir per kolom yang ditentukan (untuk baris) dan baris (untuk kolom):
Kolom Terakhir:
Baris terakhir:
Untuk kasus OP, ini adalah cara untuk mendapatkan baris terakhir di kolom
E
:Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)
Baris Terakhir, menghitung baris kosong dengan data:
Di sini kita dapat menggunakan rumus Excel yang terkenal , yang memberi kita baris terakhir lembar kerja di Excel, tanpa melibatkan VBA -
=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)
Untuk menempatkan ini dalam VBA dan tidak menulis apa pun di Excel, menggunakan parameter untuk fungsi yang terakhir, sesuatu seperti ini dapat diingat:
sumber
EVAL()
dan rumus Excel yang terkenal. Meskipun orang mungkin berpikir ituEval()
adalah kejahatan dan ini adalah kisah menarik lainnya untuk ditulis ...sumber