#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 предоставил решение, и оно отлично работает. Тем не менее, спасибо за вашу помощь 🙂