Найдите последнюю непустую строку в диапазоне ячеек, содержащих формулу

#excel #vba

Вопрос:

Как я могу найти последнюю строку в диапазоне ячеек, содержащих формулу, где результатом формулы является фактическое значение, а не пустое?

Скажем упрощенно, что диапазон ячеек ("E1:E10") содержит формулу, относящуюся к ячейкам от A1 до A10, как показано ниже =IF("A1"="","","A1") . Но только ячейки с A1 по A6 имеют заполненное значение, поэтому результат формулы для ячеек с E7 по E10 будет пустым.

Пытаюсь сделать это с помощью:

 lastRow = ActiveSheet.Range("E" amp; Rows.Count).End(xlUp).Row
 

приводит к тому, что последнее значение имеет значение 10 . Я хочу, чтобы значение lastRow было 6 в этом примере.

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

Ответ №1:

Я думаю, что более элегантный способ, чем был предложен @D_Bester , — это использовать find() опцию без зацикливания на диапазоне ячеек:

 Sub test()
    Dim cl As Range, iamp;
    Set cl = Range("E1:E" amp; Cells(Rows.Count, "E").End(xlUp).Row)
    i = cl.Find("*", , xlValues, , xlByRows, xlPrevious).Row
    Debug.Print "Last row with data: " amp; i
End Sub
 

тест

введите описание изображения здесь

Кроме того, более короткая версия кода, которая была предоставлена выше, является:

 Sub test2()
    Debug.Print [E:E].Find("*", , xlValues, , xlByRows, xlPrevious).Row
End Sub
 

Комментарии:

1. Отлично работает и было больше того, что я искал. У меня только один вопрос: что означает амперсанд amp; в объявлении переменной i ? (Поскольку, похоже, это работает точно так же без амперсанда)

2. @Pascale это значит Dim i as Long , что если вы удалите amp; , то i будет объявлено as Variant . Это просто сокращенный метод кодирования, например % , есть Integer , amp; есть Long , $ есть String , @ есть Currency , ! есть Single , # есть Double , если не указано, то Variant

3. @Василий, спасибо, что дал мне весь список сокращенных объявлений и -1 для Micrososft за то, что они не включили их в общую страницу объявления переменных

4. Этот ответ элегантен! Россия красиво

Ответ №2:

Вы хотите найти последнюю ячейку в столбце, которая не является пустой и не является пустой строкой(«»).

Просто следуйте последнему шагу с проверкой цикла на наличие непустой ячейки.

 lastrow = ActiveSheet.Range("E" amp; ActiveSheet.Rows.Count).End(xlUp).Row
Do
    If ActiveSheet.Cells(lastrow, 5).Value <> "" Then
        Exit Do
    End If
    lastrow = lastrow - 1
Loop While lastrow > 0

If lastrow > 0 Then
    Debug.Print "Last row with data: " amp; lastrow
Else
    Debug.Print "No data in the column"
End If
 

Обратите внимание, что вы Rows.count не указываете, на каком листе. Это означает, что он будет использовать активный лист. Конечно ActiveSheet.Range() , также находится на активном листе. Но это плохая практика-смешивать Range или Rows с .Range или .Rows . Это указывает на бездумное использование, которое может укусить вас, если вы изменили ActiveSheet , но не изменили неуказанную ссылку.

Комментарии:

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

2. Спасибо вам за ваш ответ и за то, что вы объяснили, как улучшить использование строк. Подсчет и ведомость активов.

3. Я думаю, что есть, попробуйте использовать подход «разделяй и властвуй». Как 2^20 равно 1048576. В этом и заключается ценность Rows.Count . Тем не менее, вы Do...Loop никогда не будете повторять более 20 раз, чтобы достичь lastrow .

4. @D_Bester есть еще один вариант, чтобы найти последнюю непустую ячейку с помощью find() опции, без зацикливания по диапазону

Ответ №3:

Это должно помочь вам определить последнюю строку, содержащую формулу (в столбце A на листе Sheet1 1).:

 lastRow  = Split(Split(Sheet1.Range("A:A").SpecialCells(xlCellTypeFormulas).Address, ",")(UBound(Split(Sheet1.Range("A:A").SpecialCells(xlCellTypeFormulas).Address, ","))), "$")(2)
 

SpecialCells используется для определения диапазона всех ячеек, содержащих формулу. Затем этот диапазон анализируется с использованием Split . При Ubound этом последняя из этих ячеек извлекается. Результат снова разделяется, чтобы извлечь номер строки.

Комментарии:

1. Я попытался применить ваш код, но он возвращает первую строку с формулой в ней. (Диапазон на моем листе от строки 3 до строки 26, и ваш последний ряд возвращает 3: когда я распечатываю его с помощью MsgBox, когда я ожидал, что он будет 21) Не уверен, что мне нужно настроить или даже если это хороший подход. Вы говорите: «Это должно помочь вам определить последнюю строку, содержащую формулу», но мне нужна последняя строка, содержащая формулу, в которой результат этой формулы не «» (пустая строка). Извините, если я неправильно понял ваш ответ, но у меня вообще нет опыта работы с vba, поэтому я полностью полагаюсь на то, что нахожу в stackoverflow.

2. @Ralph Свойство адреса ограничено строкой из 255 символов и поэтому может включать не все области, содержащие формулы.

Ответ №4:

 Function returnLastRow()
    With ActiveSheet.UsedRange
    returnLastRow = .Find("*", , xlValues, , xlByRows, xlPrevious).Row
    End With
End Function