VBA — Удалить видимые строки после применения фильтра

#excel #vba

#vba #excel

Вопрос:

У меня есть два макроса, которые фильтруют столбец листа по дате, а затем удаляют нерелевантные столбцы.

Однако это очень глючит, и мне нужна помощь, чтобы исправить это, пожалуйста.

Это то, что должен делать второй макрос:

1) Просто удалите видимые строки после применения фильтра, за исключением первой строки (заголовки) — В настоящее время он удаляет ВСЕ видимые строки, включая первую строку, хотя у меня есть Offset функция в моем коде.

2) Удалите все фильтры — теперь это работает нормально

 Sub DeleteVisibleRows()

Dim ws1 As Worksheet
Dim WorkRng As Range

Set ws1 = ActiveWorkbook.Sheets("Consolidated")

On Error Resume Next

Set WorkRng = Application.Selection

Application.ScreenUpdating = False
With ws1

WorkRng.Offset(1, 0).Rows.SpecialCells(xlCellTypeVisible).EntireRow.Delete

ws1.AutoFilterMode = False

End With

Application.ScreenUpdating = True
End Sub
  

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

1. Проблема заключается в строке Set WorkRng = Application.Selection . Вам следует избегать использования Selection и попытаться лучше определить свой диапазон. Что такое Selection , когда выполняется этот макрос? Вы можете сделать смещение на 1, но все равно включить заголовки. Кроме того, On Error Resume Next в этом нет необходимости, и его сброс не позволит вам увидеть другие ошибки.

2. @DarrellH выбраны отфильтрованные данные после применения первого макроса. Итак, я отфильтровываю дату за предыдущий день, тогда отображаемые данные станут моим выбором. Я вижу, что многие люди категорически против следующего возобновления ошибок, я не программист vba, поэтому я не знаю, почему это так. Что я могу сделать вместо этого?

3. Я вижу, у вас теперь много вариантов. Причина против On Error Resume Next в том, что вы не можете отлаживать то, чего не знаете. В некоторых случаях это применимо, но вы должны знать почему.

4. @DarrellH Хорошо, спасибо за совет 🙂

Ответ №1:

Специальные ячейки будут работать так же, как предыдущий ответ.

     Sub Button1_Click()
    Dim sh As Worksheet, rng As Range, LstRw As Long

    Set sh = Sheets("Sheet1")
    With sh
        LstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
        Set rng = .Range("A2:A" amp; LstRw).SpecialCells(xlCellTypeVisible)
        rng.EntireRow.Delete
        .AutoFilterMode = False
    End With
End Sub
  

Ответ №2:

Удаление строк отфильтрованных данных — это то, что мне время от времени требовалось при работе с таблицами в Excel, но я никогда не мог доверять макросу, когда дело доходит до удаления важных данных. Если вы все еще хотите его использовать, это может сработать для вас:

 Sub DeleteVisibleRows()
Dim ws As Worksheet
Dim lastrow As Long, i As Long

Set ws = ThisWorkbook.Worksheets("Consolidated")
With ws
    lastrow = .Cells(.Rows.Count, "B").End(xlUp).Row
    For i = lastrow To 2 Step -1 'To 2 Assuming first row contains headers
        If .Rows(i).Hidden = False Then
            .Rows(i).Delete
        End If
    Next
.ShowAllData 'remove filtered data
End With
End Sub
  

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

1. @EitelDagnin Например, я забыл добавить ссылку ws в свой диапазон, который я сейчас отредактировал. Такие ошибки могут привести к удалению данных с неправильных / активных в данный момент листов.

2. Спасибо за ваш ответ. Я попробовал ваш код, к сожалению, код застревает в цикле, и я подождал около 2-3 минут, прежде чем фактически принудительно отменить макрос.

3. @EitelDagnin Каков диапазон вашей таблицы на «Консолидированном» листе? Есть ли какие-либо другие записи после вашей таблицы?

4. На листе нет «таблицы». Это просто необработанные данные в ячейках. Я не создавал таблицу из данных.

5. @EitelDagnin Хорошо, позвольте мне спросить вас таким образом: каков ваш диапазон фильтрации, включая заголовки?

Ответ №3:

Если вы используете SELECTION , нет необходимости определять рабочий лист. Все, что вам нужно, относится к вашему выбору — ваш выбор может отсутствовать на Consolidated листе, но он всегда будет находиться на родительском объекте вашего выбора.

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

 Public Sub DeleteVisibleRows()

    Dim WorkRng As Range

    Set WorkRng = Selection

    With WorkRng
        .Offset(1, 0).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
    End With

    WorkRng.Parent.AutoFilterMode = False

End Sub  
  

Редактировать: Этот код слишком длинный, я избавлюсь от части мусора.

 Public Sub DeleteVisibleRows()

    With Selection
        .Offset(1, 0).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
        .Parent.AutoFilterMode = False
    End With

End Sub
  

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

1. Я получаю ошибку, определяемую приложением или объектом @Darren

2. Это странно. Я не могу заставить его не работать. Я попытался поместить код позади Sheet1 и выбрал диапазон в Sheet2 , я попытался ввести код Book2 и выбрать диапазон в Book1 . Каждый раз, когда он удалял видимые строки в выделении, оставляя заголовок. Итак, что особенного в ваших данных, что может привести к …. заблокированы ли ваши ячейки и защищен ли лист в любом месте строк, которые вы пытаетесь удалить? Это вызвало бы ошибку — когда он не может удалить ячейки, о которых вы ему указываете.

3. Нет, ячейки не заблокированы, и на листе или рабочей книге нет защиты. Я, честно говоря, не знаю, что здесь сказать. Я скопировал код в ТОЧНОСТИ, который был в вашем блоке кода в разделе «Редактировать» в вашем вопросе, а затем запустил код, и это ошибка, которую я получаю..

4. Выделена только одна ячейка? Тогда только с одной ячейкой .Rows.Count вернется 1 и ?Selection.Resize(Selection.Rows.Count-1).Address будет возвращено сообщение об ошибке (изменение размера выделенного элемента до 0 строк).

5. Спасибо @Darren, это не проблема, Davesexcel предоставил решение, и оно отлично работает. Тем не менее, спасибо за вашу помощь 🙂