How to find the true Last Cell in any Worksheet

前端 未结 5 1913
遇见更好的自我
遇见更好的自我 2021-01-13 01:12

This question is now answered elegantly, thanks to Chris Neilsen, see the answer below. It is the one I will use from now on. The solution reliably finds the last cell in

5条回答
  •  轮回少年
    2021-01-13 01:54

    Best way I know to find "true Last Cell" is to use 2 steps:

    1. Pick last cell of UsedRange (i.e. UsedRange.Cells.CountLarge)
    2. Move left & up until you find last non-empty row & column with CountA (i.e. WorksheetFunction.CountA(Range)), as it is fast, and works with Hidden / AutoFiltered / Grouped ranges.

    This takes some time, so I've written an optimized code for the second step. Then I found @Chris' code edited on Nov 30, 2019, and it looked similar, though I was wondering why so different. I compared (...did my best to do apple v apple), and was surprised by the results.

    If my tests are reliable, then all what matters is how many searches you do with CountA. I call it cycle - it is actually the number of CountA functions! My routine does up to 34 cycles, and @Chris' routine seems to do up to 32..80+ cycles. His code seems to test the same ranges repeatedly.

    Please have a look at the test table Link, see my test results in VBA notes, and watch Immediate for your live results. You may test with any content, or even use an ActiveSheet in your own WorkBook. Play with parameters in VBA at "==== PARAMETERS TO BE CHANGED ====". You may zoom to 10%-15% to see painted cells showing the search ranges for each cycle. That's where the number of cycles becomes visible.

    Note: I have not found any side-effects or errors with this so far. I avoid using Range.Find, and changing its parameters behind the scenes. Some users will learn it the hard way... - like I did, when I then replaced text in the entire workbook, just to find it out days later. Note2: This is my first post, please excuse possible glitches here.

    Function GetLastSheetCellRng(ws As Excel.Worksheet) As Range
    'Returns the [Range] of last used cell of the specified [Worksheet], located in the cross-section of the bottom row and right column with non-empty cells
    Dim wf As Excel.WorksheetFunction: Set wf = Application.WorksheetFunction
    Dim Xfound&, Yfound&, Xfirst&, Yfirst&, Xfrom&, Yfrom&, Xto&, Yto As Long
    
    With ws
        '1. step: UsedRange last cell
        Set GetLastSheetCellRng = .UsedRange.Cells(.UsedRange.Cells.CountLarge) 'Getting UsedRange last cell
        Yfound = GetLastSheetCellRng.Row: Xfound = GetLastSheetCellRng.Column
    
        '2. step: Check non-empty cells in UsedRange last cell row & column
        'If not found, then search up for last non-empty row, and search left for last non-empty column
        If (wf.CountA(.Rows(Yfound)) = 0) And (Yfound > 1) Then
            Yto = Yfound
            Yfrom = Yto \ 2
            Yfirst = 0
            Do
                If wf.CountA(.Range(.Rows(Yfrom), .Rows(Yto))) <> 0 Then
                    Yfirst = Yfrom
                    Yfrom = (Yfirst + Yto + 0.5) \ 2
                Else
                    Yto = Yfrom - 1
                    Yfrom = (Yfrom + Yfirst) \ 2
                End If
            Loop Until Yfirst = Yfrom
            If Yfirst = 0 Then
                Yfound = 1 'If no cell found, then 1st row returned
            Else
                Yfound = Yfirst
            End If
        End If
        If (wf.CountA(.Columns(Xfound)) = 0) And (Xfound > 1) Then
            Xto = Xfound
            Xfrom = Xto \ 2
            Xfirst = 0
            Do
                If wf.CountA(.Range(.Columns(Xfrom), .Columns(Xto))) <> 0 Then
                    Xfirst = Xfrom
                    Xfrom = (Xfirst + Xto + 0.5) \ 2
                Else
                    Xto = Xfrom - 1
                    Xfrom = (Xfrom + Xfirst) \ 2
                End If
            Loop Until Xfirst = Xfrom
            If Xfirst = 0 Then
                Xfound = 1 'If no cell found, then 1st column returned
            Else
                Xfound = Xfirst
            End If
        End If
        Set GetLastSheetCellRng = .Cells(Yfound, Xfound)
    End With
    End Function
    

提交回复
热议问题