Расчет VBA LastRow не работает

У меня есть рабочий лист с автоматически отфильтрованным диапазоном, который начинается в ячейке B3. Столбец A содержит несколько кнопок макросов, но фактически пуст. Две верхние строки содержат информацию о данных в основном диапазоне.

В VBA я использую стандартный метод определения последней строки на листе (в этом случае я не могу полагаться на метод .End для одного столбца):

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

Однако иногда это возвращает значение, равное единице, даже если у меня есть тысячи строк данных. Кажется, это происходит только тогда, когда установлены фильтры (но в них все еще видны строки с данными), но даже в этом случае это не всегда происходит, и я не вижу закономерности.

Я знаю, что есть и другие решения — вместо этого я перешел на метод UsedRange, но очень расстраивает, что этот конкретный метод терпит неудачу, поскольку в противном случае он был бы наиболее эффективным в этой ситуации.

Кто-нибудь знает, почему это происходит?


person BBaxter    schedule 12.03.2013    source источник
comment
Я нахожу метод Find иногда странным. Вы пытались указать Lookin:=xlValues в своем вызове Find (или, если все формулы переключаются на xlFormulas)?   -  person CuberChase    schedule 13.03.2013


Ответы (8)


Думали ли вы об использовании ответа Грега, но зациклились, чтобы найти самую высокую строку из всех столбцов? Что-то типа:

LastRow = 1
With ActiveSheet
   For i = 1 to .UsedRange.Columns.Count
      If .Cells(.Rows.Count, i).End(xlUp).Row > LastRow Then
         LastRow = .Cells(.Rows.Count, i).End(xlUp).Row
      EndIf
   Next i
End With

Это решение позволит случайным образом заполнить пустые значения в нижних строках. UsedRange сложна, так как возвращает самую дальнюю удаленную строку/столбец, который когда-либо редактировался (даже если он в настоящее время пуст). По моему опыту Range.End(xlUp) ведет себя так, как и следовало ожидать, если вы нажмете Ctrl-Up, находясь на листе. Это немного более предсказуемо.

Если вы настроены на использование .Find, попробуйте изучить аргумент After:=[A1]. Я не исследовал особенности этой функции, но с этой проблемы я бы начал.

person GetUserName    schedule 13.03.2013

попробуй это...

Dim LastRow as long

With ActiveSheet
    LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With

Это позволит получить последнюю строку в столбце A.

person Greg R    schedule 12.03.2013
comment
Спасибо, но я уже знаю о других решениях, и в этом случае я не могу полагаться на один столбец. Метод .find был бы наиболее эффективным, если бы работал в этой ситуации. Я обновил вопрос соответственно. - person BBaxter; 13.03.2013

Предлагаем вам попробовать использовать Find, указав поиск XlFormulas, так как в отличие от XlValues с этим аргументом будут обнаружены скрытые ячейки (но не отфильтрованные ячейки).

Sub Test()
Dim rng1 As Range
Set rng1 = ActiveSheet.Cells.Find("*", [a1], xlFormulas, , xlByRows, xlPrevious)
If Not rng1 Is Nothing Then MsgBox rng1.Row
End Sub
person brettdj    schedule 20.12.2014

Я столкнулся с точно такой же проблемой сегодня утром.

Сначала я был уверен, что функция ".find" нестабильна.

Но, повозившись некоторое время, я обнаружил непустую ячейку в слишком глубоком номере строки в моем листе, думаю, это было 1000 или 10 000 или что-то подобное. Я удалил его, и «.find» снова работает. Возможно, пределы некоторых внутренних переменных VBA недостаточно велики.

Сделай это:

1) Нажмите CTRL+END

2) Определите непустую ячейку (ячейки), предполагая, что она была случайно заполнена, и удалите ее.

person user6651685    schedule 28.07.2016

Попробуйте ниже код:

Sub GetColA_LastRow()
    Dim ws As Worksheet
    Dim lRow As Long

    Set ws = ThisWorkbook.Sheets("Sheet1")

    With ws
        lRow = .Range("A" & .Rows.Count).End(xlUp).Row
    End With

    MsgBox "The last row which has data in Col A of Sheet1 is " & lRow
End Sub

OR

sub getLastRow()
 dim lastRow as long
 lastRow = Sheets("sheet1").Range("A65000").End(xlUp).Row

end sub

вы также можете перейти по ссылке для получения более подробной информации http://www.siddharthrout.com/2012/10/02/find-last-row-in-an-excel-sheetvbavb-net/

Обновите код после комментариев:

Sub getLastRow()

    Dim rng As Range, lastRow As Long
    Set rng = Cells.Find("mango") ' here you enter whatever you want to find

    If Not rng Is Nothing Then
        lastRow = Sheets("sheet1").Cells(65000, rng.Column).End(xlUp).Row
    End If

End Sub
person Community    schedule 12.03.2013
comment
Спасибо, но я уже знаю о других решениях, и в этом случае я не могу полагаться на один столбец. Метод .find был бы наиболее эффективным, если бы работал в этой ситуации. Я обновил вопрос соответственно. - person BBaxter; 13.03.2013
comment
взгляните на мое решение, а затем используйте объект UsedRange. - person Our Man in Bananas; 13.03.2013

как насчет:

with activesheet.usedrange
    LastRow = .rows.count
end with

хт Филипп

person Our Man in Bananas    schedule 12.03.2013

Мой аналогичный вопрос заключался в том, какая последняя строка и столбец использовались независимо от пустых ячеек до этого с фильтрацией или без нее. Я собрал это из кусочков, которые смог найти, и он делает то, что, как мне кажется, нужно и вам, и мне, по крайней мере, для ячеек, заполненных данными.

Function FindLastUsedRowAndCol(ByVal ws As Worksheet) As Variant()

Dim LastColRange As Range
Dim LastCol As Integer
Dim LastRow As Long
Dim LastRowTmp As Long
Dim RowXCol(2) As Variant


Set LastColRange = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
    xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False)
LastCol = LastColRange.Column

LastRow = 1

For i = 1 To LastCol Step 1
    If ws.FilterMode Then
        LastRow = ws.AutoFilter.Range.Rows.Count
        LastRowTmp = Cells(ws.Rows.Count, i).End(xlUp).row
        If LastRowTmp > LastRow Then LastRow = LastRowTmp
    Else
        LastRowTmp = Cells(ws.Rows.Count, i).End(xlUp).row
        If LastRowTmp > LastRow Then LastRow = LastRowTmp
    End If
Next i

RowXCol(1) = LastRow
RowXCol(2) = LastCol
FindLastUsedRowAndCol = RowXCol

End Function

И для проверки:

Sub testit()
Dim ws As Worksheet
Set ws = Application.Worksheets("Sheet1")
cr = FindLastUsedRowAndCol(ws)
MsgBox "row: " & cr(1) & " col: " & cr(2)
End Sub
person chipfall    schedule 07.03.2015
comment
поцарапать выше. работает не во всех ситуациях - person chipfall; 08.03.2015

Я знаю, что это старый пост, но я видел именно эту проблему и не видел ответов, касающихся этой проблемы. Кажется, иногда это происходит в наборе данных, где есть строки, скрытые сразу после последней строки. Неважно, настроены ли вы на просмотр xlformulas или xlvalues, и я пробовал каждую перестановку команды find, которую я мог найти, и она постоянно возвращает значение 1. (Как говорит OP) Приведенные выше решения не исправить это. Мне пришлось создать функцию, которая выполняет итерацию, чтобы найти последнюю строку в этом случае (ключевой фрагмент кода ниже - в моем случае мне нужно было найти последнюю строку в первых двух столбцах различных таблиц данных):

On Error GoTo ExitLoop
StartRow = 1
LastRow = .Columns("A:B").Find(What:="*", SearchDirection:=xlNormal, LookIn:=xlValues, SearchOrder:=xlByRows).Row
StartRow = LastRow + 1
Do Until WorksheetFunction.CountA(.Range(.Cells(StartRow, 1), .Cells(1048576, 2))) = 0
    FindLastRow = .Range(.Cells(StartRow, 1), .Cells(1048576, 2)).Find(What:="*", SearchDirection:=xlNormal, LookIn:=xlValues, SearchOrder:=xlByRows).Row
    StartRow = LastRow + 1
Loop
ExitLoop:
person Tom Annable    schedule 15.07.2019