it-swarm-vi.tech

Làm cách nào tôi có thể tìm thấy hàng cuối cùng chứa dữ liệu trong bảng Excel có macro?

Làm cách nào để tìm hàng cuối cùng chứa dữ liệu trong một cột cụ thể và trên một trang cụ thể?

56
Lipis

Làm thế nào về:

 Sub GetLastRow(strSheet, strColumn)
 Dim MyRange As Range
 Dim lngLastRow As Long

    Set MyRange = Worksheets(strSheet).Range(strColumn & "1")

    lngLastRow = Cells(Rows.Count, MyRange.Column).End(xlUp).Row
 End Sub

Nhận xét lại

Điều này

  Cells.Find("*",SearchOrder:=xlByRows,SearchDirection:=xlPrevious).Row

Sẽ trả về số hàng của ô cuối cùng ngay cả khi chỉ một ô duy nhất ở hàng cuối cùng có dữ liệu. 

42
Fionnuala

Bạn nên sử dụng .End(xlup) nhưng thay vì sử dụng 65536, bạn có thể muốn sử dụng:

sheetvar.Rows.Count

Theo cách đó, nó hoạt động cho Excel 2007 mà tôi tin rằng có hơn 65536 hàng

21
Jon Fournier

Đơn giản và nhanh chóng:

Dim lastRow as long
Range("A1").select
lastRow = Cells.Find("*",SearchOrder:=xlByRows,SearchDirection:=xlPrevious).Row

Ví dụ sử dụng:

cells(lastRow,1)="Ultima Linha, Last Row. Youpi!!!!"

'or 

Range("A" & lastRow).Value = "FIM, THE END"
7
user2988717
function LastRowIndex(byval w as worksheet, byval col as variant) as long
  dim r as range

  set r = application.intersect(w.usedrange, w.columns(col))
  if not r is nothing then
    set r = r.cells(r.cells.count)

    if isempty(r.value) then
      LastRowIndex = r.end(xlup).row
    else
      LastRowIndex = r.row
    end if
  end if
end function

Sử dụng:

? LastRowIndex(ActiveSheet, 5)
? LastRowIndex(ActiveSheet, "AI")
7
GSerg
Public Function LastData(rCol As Range) As Range    
    Set LastData = rCol.Find("*", rCol.Cells(1), , , , xlPrevious)    
End Function

Cách sử dụng: ?lastdata(activecell.EntireColumn).Address

3
Dick Kusleika

Đây là một giải pháp để tìm hàng cuối cùng, cột cuối cùng hoặc ô cuối cùng. Nó giải quyết tình trạng tiến thoái lưỡng nan Kiểu tham chiếu A1 R1C1 cho cột mà nó tìm thấy. Ước gì tôi có thể cung cấp tín dụng, nhưng không thể tìm/nhớ nơi tôi đã nhận được, vì vậy "Cảm ơn!" cho bất cứ ai đã đăng mã gốc ở đâu đó ngoài kia.

Sub Macro1
    Sheets("Sheet1").Select
    MsgBox "The last row found is: " & Last(1, ActiveSheet.Cells)
    MsgBox "The last column (R1C1) found is: " & Last(2, ActiveSheet.Cells)
    MsgBox "The last cell found is: " & Last(3, ActiveSheet.Cells)
    MsgBox "The last column (A1) found is: " & Last(4, ActiveSheet.Cells)
End Sub

Function Last(choice As Integer, rng As Range)
' 1 = last row
' 2 = last column (R1C1)
' 3 = last cell
' 4 = last column (A1)
    Dim lrw As Long
    Dim lcol As Integer

    Select Case choice
    Case 1:
        On Error Resume Next
        Last = rng.Find(What:="*", _
                        After:=rng.Cells(1), _
                        LookAt:=xlPart, _
                        LookIn:=xlFormulas, _
                        SearchOrder:=xlByRows, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).Row
        On Error GoTo 0

    Case 2:
        On Error Resume Next
        Last = rng.Find(What:="*", _
                        After:=rng.Cells(1), _
                        LookAt:=xlPart, _
                        LookIn:=xlFormulas, _
                        SearchOrder:=xlByColumns, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).Column
        On Error GoTo 0

    Case 3:
        On Error Resume Next
        lrw = rng.Find(What:="*", _
                       After:=rng.Cells(1), _
                       LookAt:=xlPart, _
                       LookIn:=xlFormulas, _
                       SearchOrder:=xlByRows, _
                       SearchDirection:=xlPrevious, _
                       MatchCase:=False).Row
        lcol = rng.Find(What:="*", _
                        After:=rng.Cells(1), _
                        LookAt:=xlPart, _
                        LookIn:=xlFormulas, _
                        SearchOrder:=xlByColumns, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).Column
        Last = Cells(lrw, lcol).Address(False, False)
        If Err.Number > 0 Then
            Last = rng.Cells(1).Address(False, False)
            Err.Clear
        End If
        On Error GoTo 0
    Case 4:
        On Error Resume Next
        Last = rng.Find(What:="*", _
                        After:=rng.Cells(1), _
                        LookAt:=xlPart, _
                        LookIn:=xlFormulas, _
                        SearchOrder:=xlByColumns, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).Column
        On Error GoTo 0
        Last = R1C1converter("R1C" & Last, 1)
        For i = 1 To Len(Last)
            s = Mid(Last, i, 1)
            If Not s Like "#" Then s1 = s1 & s
        Next i
        Last = s1

    End Select

End Function

Function R1C1converter(Address As String, Optional R1C1_output As Integer, Optional RefCell As Range) As String
    'Converts input address to either A1 or R1C1 style reference relative to RefCell
    'If R1C1_output is xlR1C1, then result is R1C1 style reference.
    'If R1C1_output is xlA1 (or missing), then return A1 style reference.
    'If RefCell is missing, then the address is relative to the active cell
    'If there is an error in conversion, the function returns the input Address string
    Dim x As Variant
    If RefCell Is Nothing Then Set RefCell = ActiveCell
    If R1C1_output = xlR1C1 Then
        x = Application.ConvertFormula(Address, xlA1, xlR1C1, , RefCell) 'Convert A1 to R1C1
    Else
        x = Application.ConvertFormula(Address, xlR1C1, xlA1, , RefCell) 'Convert R1C1 to A1
    End If
    If IsError(x) Then
        R1C1converter = Address
    Else
        'If input address is A1 reference and A1 is requested output, then Application.ConvertFormula
        'surrounds the address in single quotes.
        If Right(x, 1) = "'" Then
            R1C1converter = Mid(x, 2, Len(x) - 2)
        Else
            x = Application.Substitute(x, "$", "")
            R1C1converter = x
        End If
    End If
End Function
3
Greg Podesta

Tất cả các giải pháp dựa trên các hành vi tích hợp (như .Find.End) đều có những hạn chế không được ghi chép đầy đủ (xem câu trả lời khác của tôi để biết chi tiết).

Tôi cần một cái gì đó:

  • Tìm ô không trống cuối cùng (nghĩa là có bất kỳ công thức hoặc giá trị nào, ngay cả khi đó là một chuỗi trống) trong một cột cụ thể
  • Dựa vào nguyên thủy với hành vi được xác định rõ
  • Hoạt động đáng tin cậy với bộ lọc tự động và sửa đổi người dùng
  • Chạy nhanh nhất có thể trên 10.000 hàng (để được chạy trong trình xử lý Worksheet_Change mà không cảm thấy chậm chạp)
  • ... với hiệu suất không rơi xuống một vách đá với dữ liệu hoặc định dạng ngẫu nhiên được đặt ở cuối trang tính (tại ~ 1M hàng)

Giải pháp dưới đây:

  • Sử dụng UsedRange để tìm giới hạn trên cho số hàng (để thực hiện tìm kiếm "hàng cuối cùng" thực sự nhanh trong trường hợp phổ biến khi nó ở gần cuối của phạm vi được sử dụng);
  • Đi ngược lại để tìm hàng có dữ liệu trong cột đã cho;
  • ... sử dụng mảng VBA để tránh truy cập từng hàng riêng lẻ (trong trường hợp có nhiều hàng trong UsedRange chúng ta cần bỏ qua)

(Không có bài kiểm tra, xin lỗi)

' Returns the 1-based row number of the last row having a non-empty value in the given column (0 if the whole column is empty)
Private Function getLastNonblankRowInColumn(ws As Worksheet, colNo As Integer) As Long
    ' Force Excel to recalculate the "last cell" (the one you land on after CTRL+END) / "used range"
    ' and get the index of the row containing the "last cell". This is reasonably fast (~1 ms/10000 rows of a used range)
    Dim lastRow As Long: lastRow = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row - 1 ' 0-based

    ' Since the "last cell" is not necessarily the one we're looking for (it may be in a different column, have some
    ' formatting applied but no value, etc), we loop backward from the last row towards the top of the sheet).
    Dim wholeRng As Range: Set wholeRng = ws.Columns(colNo)

    ' Since accessing cells one by one is slower than reading a block of cells into a VBA array and looping through the array,
    ' we process in chunks of increasing size, starting with 1 cell and doubling the size on each iteration, until MAX_CHUNK_SIZE is reached.
    ' In pathological cases where Excel thinks all the ~1M rows are in the used range, this will take around 100ms.
    ' Yet in a normal case where one of the few last rows contains the cell we're looking for, we don't read too many cells.
    Const MAX_CHUNK_SIZE = 2 ^ 10 ' (using large chunks gives no performance advantage, but uses more memory)
    Dim chunkSize As Long: chunkSize = 1
    Dim startOffset As Long: startOffset = lastRow + 1 ' 0-based
    Do ' Loop invariant: startOffset>=0 and all rows after startOffset are blank (i.e. wholeRng.Rows(i+1) for i>=startOffset)
        startOffset = IIf(startOffset - chunkSize >= 0, startOffset - chunkSize, 0)
        ' Fill `vals(1 To chunkSize, 1 To 1)` with column's rows indexed `[startOffset+1 .. startOffset+chunkSize]` (1-based, inclusive)
        Dim chunkRng As Range: Set chunkRng = wholeRng.Resize(chunkSize).Offset(startOffset)
        Dim vals() As Variant
        If chunkSize > 1 Then
            vals = chunkRng.Value2
        Else ' reading a 1-cell range requires special handling <http://www.cpearson.com/Excel/ArraysAndRanges.aspx>
            ReDim vals(1 To 1, 1 To 1)
            vals(1, 1) = chunkRng.Value2
        End If

        Dim i As Long
        For i = UBound(vals, 1) To LBound(vals, 1) Step -1
            If Not IsEmpty(vals(i, 1)) Then
                getLastNonblankRowInColumn = startOffset + i
                Exit Function
            End If
        Next i

        If chunkSize < MAX_CHUNK_SIZE Then chunkSize = chunkSize * 2
    Loop While startOffset > 0

    getLastNonblankRowInColumn = 0
End Function
2
Nickolay

Tôi muốn thêm một cách đáng tin cậy hơn bằng cách sử dụng UsedRange để tìm hàng được sử dụng cuối cùng:

lastRow = Sheet1.UsedRange.Row + Sheet1.UsedRange.Rows.Count - 1

Tương tự để tìm cột được sử dụng cuối cùng, bạn có thể xem cái này

 enter image description here

Kết quả trong cửa sổ ngay lập tức:

?Sheet1.UsedRange.Row+Sheet1.UsedRange.Rows.Count-1
 21 
1
newguy
  Last_Row = Range("A1").End(xlDown).Row

Chỉ cần xác minh, giả sử bạn muốn in số hàng của hàng cuối cùng với dữ liệu trong ô C1.

Range("C1").Select
Last_Row = Range("A1").End(xlDown).Row
ActiveCell.FormulaR1C1 = Last_Row
0
Sumit Pokhrel
Public Function GetLastRow(ByVal SheetName As String) As Integer
    Dim sht As Worksheet
    Dim FirstUsedRow As Integer     'the first row of UsedRange
    Dim UsedRows As Integer         ' number of rows used

    Set sht = Sheets(SheetName)
    ''UsedRange.Rows.Count for the empty sheet is 1
    UsedRows = sht.UsedRange.Rows.Count
    FirstUsedRow = sht.UsedRange.Row
    GetLastRow = FirstUsedRow + UsedRows - 1

    Set sht = Nothing
End Function

sheet.UsedRange.Rows.Count: lấy lại số lượng hàng được sử dụng, không bao gồm hàng trống phía trên hàng đầu tiên được sử dụng

nếu hàng 1 trống và hàng được sử dụng cuối cùng là 10, thì OLX.Rows.Count sẽ trả về 9, không phải 10.

Hàm này tính toán số hàng đầu tiên của OLX cộng với số lượng hàng Được sử dụng.

0