VBA ile Excel'de son kullanılan hücreyi bulma hatası


179

Son kullanılan hücre değerini bulmak istediğimde şunu kullanıyorum:

Dim LastRow As Long

LastRow = Range("E4:E48").End(xlDown).Row

Debug.Print LastRow

Bir hücreye tek bir öğe koyduğumda yanlış çıktı alıyorum. Fakat hücreye birden fazla değer koyduğumda çıktı doğru. Bunun arkasındaki sebep nedir?


Yanıtlar:


309

NOT : Bunu Correctson satırı bulmak için kullanabileceğiniz bir "tek durak sonrası" yapmak niyetindeyim . Bu ayrıca son satırı bulurken izlenecek en iyi uygulamaları da kapsayacaktır. Ve böylece yeni bir senaryo / bilgi ile karşılaştığımda güncellemeye devam edeceğim.


Son satırı bulmanın güvenilir olmayan yolları

Son sırada güvenilir olmayan ve bu nedenle asla kullanılmaması gereken en yaygın yollardan bazıları.

  1. UsedRange
  2. xlDown
  3. COUNTA

UsedRangegerektiğini ASLA verilerine sahip son hücreyi bulmak için kullanılabilir. Son derece güvenilmez. Bu denemeyi deneyin.

Hücreye bir şey yazın A5. Şimdi son satırı aşağıda verilen yöntemlerden herhangi biriyle hesapladığınızda, size 5 değerini verecektir. Şimdi hücreyi A10kırmızı renklendirin . Şimdi aşağıdaki kodlardan herhangi birini kullanırsanız, yine de 5 Usedrange.Rows.Countelde edersiniz. 5 olmayacak.

İşte nasıl UsedRangeçalıştığını gösteren bir senaryo .

resim açıklamasını buraya girin

xlDown eşit derecede güvenilmezdir.

Bu kodu düşünün

lastrow = Range("A1").End(xlDown).Row

A1Verileri olan tek bir hücre ( ) olsaydı ne olurdu ? Sonunda çalışma sayfasındaki son satıra ulaşacaksınız! Hücreyi seçmek A1, sonra tuşuna Endbasmak ve sonra tuşuna Down Arrowbasmak gibidir. Bu, bir aralıkta boş hücreler varsa size güvenilir olmayan sonuçlar verir.

CountA aynı zamanda güvenilmezdir, çünkü arada boş hücreler varsa yanlış sonuç verir.

Ve dolayısıyla bir kullanmaktan kaçınmalıdır UsedRange, xlDownve CountAson hücreyi bulmak için.


Bir Sütundaki Son Satırı Bul

Col E'deki son Satırı bulmak için bunu kullanın

With Sheets("Sheet1")
    LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
End With

Daha .önce bir tane olduğunu fark ederseniz Rows.Count. Bunu sıklıkla görmezden gelmeyi tercih ettik. Alabileceğiniz olası hata hakkında BU soruya bakın . Ben her zaman .önce Rows.Countve kullanmanızı öneririz Columns.Count. Bu soru, Excel 2003 ve önceki sürümleri ile Excel 2007 ve sonraki sürümleri için Rows.Countdöndürdüğü 65536için kodun başarısız olacağı klasik bir senaryodur 1048576. Benzer şekilde sırasıyla ve değerini Columns.Countdöndürür .25616384

Yukarıdaki Excel 2007+ 1048576satırları olduğu gerçeği, satır değerini tutacak değişkeni her zaman bildirmemiz gerektiğine vurgu yapar, Longbunun yerine Integerbir Overflowhata alırsınız .

Bu yaklaşımın gizli satırları atlayacağını unutmayın. Yukarıdaki A sütununun ekran görüntüsüne baktığımda , 8. satır gizlenmişse, bu yaklaşım 5bunun yerine geri dönecektir 8.


Sayfadaki Son Satırı Bul

Sayfadaki Effectiveson satırı bulmak için bunu kullanın. Kullanımına dikkat edin Application.WorksheetFunction.CountA(.Cells). Bu gereklidir, çünkü çalışma sayfasında veri içeren hiçbir hücre .FindyoksaRun 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

Tablodaki Son Satırı Bul (ListObject)

Aynı ilkeler, örneğin bir tablonun üçüncü sütunundaki son satırı almak için geçerlidir:

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

9
@phan: A5 hücresine bir şeyler yazın. Şimdi son satırı yukarıdaki yöntemlerden herhangi biriyle hesapladığınızda, size 5 verecektir. Şimdi A10 hücresini kırmızı renklendirin. Şimdi yukarıdaki kodlardan herhangi birini kullanırsanız, yine de 5 Usedrange.Rows.Countelde edersiniz. 5 sıra kullanılmayacaktır. Usedrange son satırı bulmak son derece güvenilmezdir.
Siddharth Rout

6
Ne yazık ki. Bul maalesef Bul iletişim kutusunda kullanıcının ayarlarını bozar - yani Excel'de iletişim kutusu için yalnızca 1 ayar kümesi vardır ve .Find bunları kullanır. Başka bir hile de UsedRange'ı kullanmaktır, ancak bunu doğru maksimum değeri belirlediğiniz mutlak (ancak güvenilmez) bir maksimum olarak kullanmaktır.
Carl Colijn

4
@CarlColijn: Ben buna karışıklık demezdim. :) Excel sadece remembersson ayar. Manuel olarak yaptığınız zaman bile, Findbu "gerçeği" biliyorsa aslında bir nimet olan son ayarı hatırlar
Siddharth Rout

3
@KeithPark: Lütfen devam edin :) Bilgi yayılırsa sadece bir anlamı vardır :)
Siddharth Rout

9
Bence UsedRange( veri içeren son hücreyi bulmak son derece güvenilmez ) açıklamanızın yanıltıcı olduğunu düşünüyorum. UsedRangebazı durumlarda doğru sonuç verebilmesine rağmen, bu amaç için tasarlanmamıştır. Önerilen deneyin karışıklığa katkıda bulunduğunu düşünüyorum. UsedRange($ A $ 1: $ A $ 8) ile elde edilen sonuç , ilk veri girilmesine ve silinmesine bağlı değildir. Sağdaki şekil, verileri silmeden ve silmeden bile aynı olacaktır. Lütfen cevabımı gör.
sancho.s ReinstateMonicaCellio

34

Not: Bu cevap bu yorum tarafından motive edilmiştir . Amacı, UsedRangeyukarıdaki cevapta belirtilenlerden farklıdır.

Son kullanılan hücreyi bulmanın doğru yoluna gelince, önce neyin kullanılmış olarak kabul edildiğine karar vermeli ve sonra uygun bir yöntem seçilmelidir . En az üç anlam düşünüyorum:

  1. Kullanılan = boş olmayan, yani veriye sahip .

  2. Kullanılan = "... kullanımda, yani veri veya biçimlendirme içeren bölüm ." Resmi belgelere göre , bu, tasarruf sırasında Excel tarafından kullanılan kriterdir. Ayrıca bu resmi belgelere de bakın . Biri bunun farkında değilse, ölçüt beklenmedik sonuçlar doğurabilir, ancak kasıtlı olarak (daha az sıklıkla, kesinlikle), örneğin, sonunda veri içermeyen belirli bölgeleri vurgulamak veya yazdırmak için de sömürülebilir. Ve elbette, bir çalışma kitabını kaydederken, çalışmalarının bir kısmını kaybetmemek için, aralığın kullanılması için bir kriter olarak arzu edilir.

  3. Kullanılan = "... kullanımda, yani veri veya biçimlendirme içeren bölüm " veya koşullu biçimlendirme. 2. ile aynı, ancak herhangi bir Koşullu Biçimlendirme kuralının hedefi olan hücreleri de içerir.

Son kullanılan hücre bağlıdır nasıl bulunur Eğer (senin ölçütünü) istiyorum .

Kriter 1 için bu cevabı okumanızı tavsiye ederim . Not UsedRangegüvenilmez olarak çağırılır. Ben sadece veri içeren son hücre bildirmek için değil UsedRangegibi yanıltıcı (yani, "haksız" olduğunu düşünüyorum UsedRange. Bu nedenle, bu cevapta belirtildiği gibi bu durumda kullanılmamalıdır. Ayrıca bu yoruma bakınız .

2. ölçüt için, UsedRange için, bu kullanım için de tasarlanmış diğer seçeneklerle karşılaştırıldığında en güvenilir seçenektir . Son hücrenin güncellendiğinden emin olmak için bir çalışma kitabını kaydetmeyi bile gereksiz hale getirir. Ctrl+ Endkaydetmeden önce yanlış bir hücreye gider ( http://msdn.microsoft.com/en-us/library/aa139976%28v=office.10% adresinden ( “Çalışma sayfasını kaydetinceye kadar son hücre sıfırlanmaz”) 29.aspx . O) eski bir referanstır fakat bu konuda geçerli.

Ölçüt 3 için herhangi bir yerleşik yöntem bilmiyorum . Ölçüt 2, Koşullu Biçimlendirme'yi açıklamıyor. Biri, + UsedRangeveya tarafından algılanmayan formüllere dayalı olarak biçimlendirilmiş hücrelere sahip olabilir.CtrlEnd . Şekilde, biçimlendirme açıkça uygulandığı için son hücre B3'tür. B6: D7 hücreleri, Koşullu Biçimlendirme kuralından türetilmiş bir biçime sahiptir ve bu bile tarafından algılanmaz UsedRange. Bunun muhasebeleştirilmesi için bazı VBA programlamaları gerekir.

resim açıklamasını buraya girin


Özel sorunuza gelince : Bunun arkasındaki sebep nedir?

Kodunuz E4: E48 aralığınızdaki ilk hücreyi trambolin olarak kullanır. aşağı atlamakEnd(xlDown) .

"Hatalı" çıktı, aralığınızda belki de ilkinden başka boş olmayan hücreler yoksa elde edilir . Daha sonra, karanlıkta , yani çalışma sayfasından aşağıya sıçrayacaksınız ( boş ve boş dize !).

Bunu not et:

  1. Aralığınız bitişik olmayan boş olmayan hücreler içeriyorsa, yanlış bir sonuç da verir.

  2. Yalnızca bir tane boş olmayan hücre varsa, ancak ilki değilse, kodunuz yine de size doğru sonucu verecektir.


3
Birinin ilk olarak neyin kullanıldığına karar vermesi gerektiğine katılıyorum . En az 6 anlam görüyorum. Hücre şunlara sahiptir: 1) muhtemelen boş bir değerle sonuçlanan veriler, yani bir formül; 2) bir değer, yani boş olmayan bir formül veya sabit; 3) biçimlendirme; 4) koşullu biçimlendirme; 5) hücrenin üzerine binen bir şekil (Yorum dahil); 6) Tabloya (Liste Nesnesi) dahil olma. Hangi kombinasyonu test etmek istiyorsunuz? Bazılarının (Tablolar gibi) test edilmesi daha zor olabilir ve bazıları nadir olabilir (veri aralığının dışındaki bir şekil gibi), ancak diğerleri duruma göre değişebilir (örn. Boş değerlere sahip formüller).
GlennFromIowa

20

Veri, biçimlendirilmiş (gruplandırılmış / yorumlanmış / gizli) hücreler veya koşullu biçimlendirme için olsun , son satırı, sütunu ve hücreyi belirlemek için bu tek durak işlevini oluşturdum .

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

Sonuçlar şöyle görünür:
son hücreyi belirle

Daha ayrıntılı sonuçlar için koddaki bazı satırlar önerilmeyebilir:
son sütun, satır

Bir sınırlama var - sayfada tablolar varsa, sonuçlar güvenilmez olabilir, bu yüzden bu durumda kodu çalıştırmaktan kaçınmaya karar verdim:

If .ListObjects.Count > 0 Then
    MsgBox "Cannot return reliable results, as there is at least one table in the worksheet."
    Exit Sub
End If

2
@franklin - Sadece gözden geçirenler tarafından reddedilen düzeltmenizle bir gelen kutusu mesajı fark ettim. Bu hatayı düzelttim. Zaten ihtiyaç duyduğumda bu işlevi bir kez kullandım ve tekrar kullanacağım, çok teşekkürler, arkadaşım!
ZygD

11

Çözümü kullanırken akılda tutulması gereken önemli bir not ...

LastRow = ws.Cells.Find(What:="*", After:=ws.range("a1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

... LastRowdeğişkeninizin şu Longtürden olmasını sağlamaktır :

Dim LastRow as Long

Aksi takdirde .XLSX çalışma kitaplarındaki belirli durumlarda OVERFLOW hataları alırsınız

Bu, çeşitli kod kullanımlarına bıraktığım kapsüllenmiş işlevim.

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

8

Siddarth Rout tarafından verilen yanıta CountA çağrısının bir satır numarası yerine bir Range nesnesi döndürerek atlanabileceğini ve daha sonra hiçbir şey olup olmadığını görmek için döndürülen Range nesnesini sınayabileceğini söylemek için yanıta eklenirim (boş çalışma sayfası) .

Ayrıca, boş bir çalışma sayfası için sıfır herhangi bir LastRow yordamı sürümüm olurdu, o zaman boş olduğunu biliyorum.


8

Kimsenin bundan bahsetmediğini merak ediyorum, ama son kullanılan hücreyi almanın en kolay yolu:

Function GetLastCell(sh as Worksheet) As Range
    GetLastCell = sh.Cells(1,1).SpecialCells(xlLastCell)
End Function

Bu aslında aldığınız hücreyi döndürür CtrlEnd Hücre seçildikten sonra + ileA1 .

Dikkatli bir kelime: Excel, bir çalışma sayfasında kullanılan en sağ alt hücreyi izler. Örneğin, B3'e bir şey ve H8'e başka bir şey girerseniz ve daha sonra H8'in içeriğini silerseniz, Ctrl+ tuşuna basmak Endsizi H8 hücresine götürür . Yukarıdaki işlev aynı davranışa sahip olacaktır.


2
Last CellExcel'de bazen ; Used Rangeden farklı olan boş bir hücreyi (from ) ifade eder Last Used Cell.
shA.t

1
OP'nin sadece son satıra ihtiyacı vardı ama haklısın, son hücre H5 olmalı ; Ama A5 değer sildikten sonra fonksiyonunuzu test edebilirsiniz Son hücre boş hücre olduğunu göreceksiniz ve kodunuzun böyle Cells(1,1).Select()geçersiz bazı düzenlemelere ihtiyacı olduğunu düşünüyorum ActiveSheet.Cells(1,1).Select; Ayrıca VBA'da kullanılması tavsiye edilmez Select;).
shA.t

5
Bu, Excel VBA için iki temel kuralı ihlal eder: Seçme! Ve istediğiniz sayfanın aktif olduğunu varsaymayın.
Rachel Hettinger

1
Bu eski bir cevap ama eksik Set.
BigBen

8

Asıl soru son hücreyi bulma problemleri ile ilgili olduğundan , bu cevapta beklenmedik sonuçlar elde etmenin çeşitli yollarını listeleyeceğim ; bkz cevabım "Nasıl bir makro ile Excel sayfasında veri içeren son satırı bulabilirim?"bunu çözmem için.

Ben genişleterek başlayacağız sancho.s tarafından cevap ve GlennFromIowa tarafından yorumun daha da ince ayrıntıları ekleyerek:

[...] ilk önce neyin kullanıldığı düşünülmelidir. En az 6 anlam görüyorum. Hücre:

  • 1) muhtemelen boş bir değerle sonuçlanan veriler, yani bir formül;
  • 2) bir değer, yani boş olmayan bir formül veya sabit;
  • 3) biçimlendirme;
  • 4) koşullu biçimlendirme;
  • 5) hücrenin üzerine binen bir şekil (Yorum dahil);
  • 6) Tabloya (Liste Nesnesi) dahil olma.

Hangi kombinasyonu test etmek istiyorsunuz? Bazılarının (Tablolar gibi) test edilmesi daha zor olabilir ve bazıları nadir olabilir (veri aralığının dışındaki bir şekil gibi), ancak diğerleri duruma göre değişebilir (örn. Boş değerlere sahip formüller).

Dikkate almak isteyebileceğiniz diğer şeyler:

  • A) Gizli satırlar (örn. Otomatik filtre), boş hücreler veya boş satırlar olabilir mi?
  • B) Ne tür bir performans kabul edilebilir?
  • C) VBA makrosu çalışma kitabını veya uygulama ayarlarını herhangi bir şekilde etkileyebilir mi?

Bunu göz önünde bulundurarak, "son hücreyi" elde etmenin ortak yollarının nasıl beklenmedik sonuçlar üretebileceğini görelim :

  • Buradaki Siddharth Rout'un cevabında açıklanan nedenlerden dolayı .End(xlDown), sorudaki kod en kolay şekilde kırılacaktır (örneğin, boş olmayan tek bir hücre ile veya aralarında boş hücreler olduğunda ) ( "xlDown eşit derecede güvenilir değildir." )
  • İng Count( CountAveya Cells*.Count) tabanlı herhangi bir çözüm veya .CurrentRegionboş hücreler veya satırların varlığında da kırılacaktır 👎
  • Bir .End(xlUp)sütunun sonundan geriye doğru arama yapmayı içeren bir çözüm , tıpkı CTRL + UP gibi, verileri arar (boş bir değer üreten formüller "veri" olarak kabul edilir) görünür satırlarda (bu nedenle, otomatik filtre etkinken kullanmak yanlış sonuçlar verebilir) ).

    Standart tuzaklardan kaçınmaya dikkat etmelisiniz (ayrıntılar için yine Siddharth Rout'un cevabına tekrar bakacağım , son satırı sabit kodlama gibi "Bir Sütunda Son Satırı Bul" bölümünü arayın Range("A65536").End(xlUp)) güvenmek yerine sht.Rows.Count.

  • .SpecialCells(xlLastCell)"kullanılan aralık" ın en alt ve en sağdaki hücresini döndüren CTRL + END ile eşdeğerdir, bu nedenle "kullanılan aralık" a dayanarak uygulanan tüm uyarılar da bu yönteme uygulanır. Buna ek olarak, "kullanılan aralık" yalnızca çalışma kitabını kaydederken ve erişirken sıfırlanır worksheet.UsedRange, bu nedenle xlLastCellkaydedilmemiş değişikliklerle eski sonuçlar⚠️ üretebilir (örn. Bazı satırlar silindikten sonra). DotNET tarafından verilen cevaba bakın .
  • sht.UsedRange( sancho.s tarafından verilen yanıtta ayrıntılı olarak açıklanmıştır ) hem verileri hem de biçimlendirmeyi (koşullu biçimlendirme olmasa da ) dikkate alır ve ve çalışma sayfasının istediğiniz veya olmayabilecek "kullanılmış aralığını" sıfırlar .

    Genel bir hatanın , son satır numarasını değil, kullanılan aralıktaki satır sayısını.UsedRange.Rows.Count döndüren ⚠️ kullanmak olduğunu unutmayın (ilk birkaç satır boşsa bunlar farklı olacaktır), ayrıntılar için newguy'un Nasıl bulabilirim Excel sayfasında bir makro ile veri içeren son satır?

  • .Findherhangi bir sütunda herhangi bir veriyle (formüller dahil) veya boş olmayan bir değerle son satırı bulmanızı sağlar . Formüllerle veya değerlerle ilgilenip ilgilenmediğinizi seçebilirsiniz, ancak yakalama, Excel'in Bul iletişim kutusundaki ️️⚠️ varsayılanları sıfırlayarak kullanıcılarınız için oldukça kafa karıştırıcı olabilir. Ayrıca dikkatle kullanılması gerekir, Siddharth Rout'un cevabına buradan bakın (bölüm "Bir Sayfadaki Son Satırı Bul" )
  • CellsBir döngüdeki bireyi kontrol eden daha belirgin çözümler genellikle bir Excel işlevini yeniden kullanmaktan daha yavaştır (yine de performans gösterebilir), ancak tam olarak ne bulmak istediğinizi belirtmenize izin verir. Bkz benim çözüm dayalı UsedRangeverilen sütundaki verilerle son hücreyi bulup VBA diziler - bu Bulma varsayılan değiştirmez gizli satırlar, filtreler, boşlukları, kolları ve oldukça performanslısı.

Hangi çözümü seçerseniz seçin, dikkatli olun

  • satır numaralarını saklamak Longyerine kullanmak Integer(Overflow 65 bin satırdan fazla almaktan ) ve
  • her zaman birlikte çalıştığınız çalışma sayfasını belirtmek için (ör Dim ws As Worksheet ... ws.Range(...).Range(...) )
  • .Value(a Variant) yöntemini kullanırken .Value <> "", hücre bir hata değeri içeriyorsa başarısız olacağı için dolaylı dökümlerden kaçının .

4

Ancak bu soru VBA kullanarak son satırı bulmaya çalışıyor, bu sık sık ziyaret alır gibi çalışma sayfası işlevi için bir dizi formülü eklemek iyi olacağını düşünüyorum:

{=ADDRESS(MATCH(INDEX(D:D,MAX(IF(D:D<>"",ROW(D:D)-ROW(D1)+1)),1),D:D,0),COLUMN(D:D))}

Formülü parantez olmadan girmeniz ve ardından Shift+ Ctrl+ tuşlarına basmanız gerekir.Enter dizi formülü yapmak için tuşuna basmanız gerekir.

Bu size D sütununda en son kullanılan hücrenin adresini verecektir.


1
Bunu severim. Yalnızca satır numarasını almak için biraz değişebilirim ... '{= MAÇ (DİZİN (D: D, MAX (EĞER (D: D <> "", SATIR (D: D) -ROW (D1) +1)) , 1), D: D, 0)} '
PGSystemTester

3
sub last_filled_cell()
msgbox range("A65536").end(xlup).row
end sub

Burada, A65536A sütunundaki son hücre bu kod excel 2003'te test edilmiştir.


Kodunuzun bu eski soruyu nasıl yanıtladığını açıklayabilir misiniz?
shoover

1
Bu cevap muhtemelen doğru ve yararlı olsa da , sorunun çözülmesine nasıl yardımcı olduğunu açıklamak için bununla birlikte bir açıklama eklemeniz tercih edilir . Bu, özellikle çalışmayı durdurmasına neden olan bir değişiklik varsa (muhtemelen ilgisiz) ve kullanıcıların bir zamanlar nasıl çalıştığını anlamaları gerekiyorsa, özellikle yararlı olur.
Kevin Brown

2

CTRL+ Shift+ ' EndYı taklit etmenin bir yolunu arıyordum , bu yüzden dotNET çözümü harika, Excel 2010'um dışında setbir hatayı önlemek istiyorsanız bir eklemem gerekiyor :

Function GetLastCell(sh As Worksheet) As Range
  Set GetLastCell = sh.Cells(1, 1).SpecialCells(xlLastCell)
End Function

ve bunu kendiniz için nasıl kontrol edersiniz:

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

1

İşte benim iki sentim.

IMHO, verilerin hariç tutulduğu gizli bir satırın riski, Tek noktadan yanıtxlUp olarak kabul edilmek için çok önemlidir . Basit ve çoğu zaman işe yarayacağına katılıyorum, ancak herhangi bir uyarı yapmadan son satırı anlama riski sunuyor. Bu KATASTROFİK üretebilir Stack Overlow atlayıp bu değeri yakalamak için "emin bir şekilde" isteyen birisi için bazı poinit de sonuçları.

FindYöntem kusursuz ve ben bir şekilde bunu kabul edeceğini Tek Noktadan Yanıt . Ancak değiştirmenin dezavantajıFind ayarları , özellikle bu bir UDF'nin parçasıysa sinir bozucu olabilir.

Gönderilen diğer cevaplar iyidir, ancak karmaşıklık biraz aşırı olur. İşte benim güvenilirlik dengesi, minimum karmaşıklık ve kullanmama dengesini bulmaya çalışıyorum Find.

Function LastRowNumber(Optional rng As Range) As Long

If rng Is Nothing Then
    Set rng = ActiveSheet.UsedRange
Else
    Set rng = Intersect(rng.Parent.UsedRange, rng.EntireColumn)
    If rng Is Nothing Then
        LastRowNumber = 1
        Exit Function
    ElseIf isE = 0 Then
        LastRowNumber = 1
        Exit Function

    End If

End If

LastRowNumber = rng.Cells(rng.Rows.Count, 1).Row

Do While IsEmpty(Intersect(rng, _
    rng.Parent.Rows(LastRowNumber)))

    LastRowNumber = LastRowNumber - 1
Loop

End Function

Bu neden iyi:

  • Oldukça basit, çok fazla değişken değil.
  • Birden çok sütuna izin verir.
  • FindAyarları değiştirmez
  • Tüm sütun seçiliyken bir UDF olarak kullanılırsa dinamik.

Bu neden kötü:

  • Çok büyük veri kümeleri ve belirtilen aralıklarda kullanılan aralık ile son satır arasında büyük bir boşluk olduğunda, bu daha yavaş, nadir durumlarda ÖNEMLİ şekilde daha yavaş gerçekleşir.

Ancak, findayarları karıştırmanın veya daha yavaş çalışmanın bir dezavantajı olan bir One-Stop-Solution'ın daha iyi bir genel çözüm olduğunu düşünüyorum. Daha sonra bir kullanıcı, kodlarında neler olup bittiğini bilerek iyileştirmeye çalışmak için ayarlarını değiştirebilir. Kullanmak xLUppotansiyel riskleri uyarmaz ve kodlarının ne kadar süre bilmediğini kimin doğru çalışmadığını bilenlere devam edebilir.


1

Son 3+ yıldır bunlar, tanımlanmış sütun (satır için) ve satır (sütun için) başına son satır ve son sütunu bulmak için kullandığım işlevlerdir:

Son Sütun:

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

Son Sıra:

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

OP için, sütundaki son satırı almanın yolu budur E:

Debug.Print lastRow(columnToCheck:=Range("E4:E48").Column)

Son Satır, verileri içeren boş satırları sayar:

Burada , VBA içermeden bize Excel'deki bir çalışma sayfasının son satırını veren iyi bilinen Excel formüllerini kullanabiliriz -=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)

Bunu VBA'ya koymak ve Excel'de herhangi bir şey yazmamak için, ikinci işlevlerin parametrelerini kullanarak, bunun gibi bir şey aklınızda olabilir:

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

Son satır / sütun gizlenirse bu yanlış bir sonuç döndürür.
PGSystemTester

@PGSystemTester - evet, ama anladığım kadarıyla, onu programladığımda, gizli ise, gerekli olan son sütun / satır değildir.
Vityata

Bunun sizin için çalışmasına sevindim. Durumunuzun tipik bir kullanım örneği olmadığından şüpheleniyorum. Ben geçen satır gerek müşterilerle çalışırken Daha sık, onlar verilere değil, en düşük ile en düşük hücre için seaching olan görünür verilerle hücrede. Her neyse ... işe yaradığına sevindim. 👍
PGSystemTester

@PGSystemTester - Demek istediğim, ama yapıyla ilgilenmek ve görünmez hücrelere izin vermemek bir cazibe gibi çalışıyor.
Vityata

@PGSystemTester - evet, görev muhtemelen boş satırlara izin veriyorsa, muhtemelen EVAL()ve ünlü Excel formülünü kullanırdım. Her ne kadar insanlar bu Eval()kötü olduğunu düşünebilir ve bu üzerine yazmak için başka ilginç bir hikaye ...
Vityata

0
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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.