How to find the true Last Cell in any Worksheet

前端 未结 5 1827
遇见更好的自我
遇见更好的自我 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:39

    Based on @Gary's method, but optimised to work fast when the UsedRange is Large but not reflective of the True Last Cell (as can happen when a cell on the extreames of a worksheet is inadvertently formatted)

    It works by, starting with the UsedRange, counting cells in half the range and halving the referenced test range above or below the split point depending on the count result, and repeating until it reaches < 5 rows/columns, then uses a linear search from there.

    Function TrueLastCell( _
      ws As Excel.Worksheet, _
      Optional lRealLastRow As Long, _
      Optional lRealLastColumn As Long _
      ) As Range
        Dim lrTo As Long, lcTo As Long, i As Long
        Dim lrFrom As Long, lcFrom As Long
        Dim wf As WorksheetFunction
        Set wf = Application.WorksheetFunction
    
        With ws.UsedRange
            lrTo = .Rows.Count
            lcTo = .Columns.Count
    
            lrFrom = lrTo \ 2
            Do While (lrTo - lrFrom) > 2
                If wf.CountA(.Rows(lrFrom & ":" & lrTo)) = 0 Then
                    lrTo = lrFrom - 1
                    lrFrom = lrFrom \ 2
                Else
                    lrFrom = (lrTo + lrFrom) \ 2
                End If
            Loop
    
            If wf.CountA(.Rows(lrFrom & ":" & lrTo)) = 0 Then
                lrTo = lrFrom - 1
            Else
                For i = lrTo To lrFrom Step -1
                    If wf.CountA(.Rows(i)) <> 0 Then
                        Exit For
                    End If
                Next i
                lrTo = i
            End If
    
            lcFrom = lcTo \ 2
            Do While (lcTo - lcFrom) > 2
                If wf.CountA(Range(.Columns(lcFrom), .Columns(lcTo))) = 0 Then
                    lcTo = lcFrom - 1
                    lcFrom = lcFrom \ 2
                Else
                    lcFrom = (lcTo + lcFrom) \ 2
                End If
            Loop
    
    
            If wf.CountA(Range(.Columns(lcFrom), .Columns(lcTo))) = 0 Then
                lcTo = lcFrom - 1
            Else
                For i = lcTo To 1 Step -1
                    If wf.CountA(.Columns(i)) <> 0 Then
                        Exit For
                    End If
                Next i
                lcTo = i
            End If
    
            Set TrueLastCell = .Cells(lrTo, lcTo)
            lRealLastRow = lrTo + .Row - 1
            lRealLastColumn = lcTo + .Column - 1
        End With
    End Function
    

    On my hardware it runs in about 2ms on a sheet with UsedRange extending to the sheet limits and True Last Cell at F5, and 0.1ms when UsedRange reflects the True Last Cell at F5

    Edit: slightly more optimised search

提交回复
热议问题