Excel VBA - удалить пустые строки в таблице
Я пытаюсь запустить макрос, который выбирает пустые ячейки в столбце таблицы и удаляет всю строку.
Сценарий ниже делает все, кроме удаления части, которая запрашивает run-time error 1004 - "Delete method of Range class failed"
,
Есть идеи, как решить эту проблему? Спасибо
Sub test()
Range("Table1[[New]]").Activate
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.EntireRow.Delete
End Sub
8 ответов
Хороший вопрос! Без стола, .EntireRow.Delete
всегда работает, но внутри таблицы это выглядит как не работает.
Это работает:
Sub Test()
Dim Rng As Range
On Error Resume Next
Set Rng = Range("Table1[[New]]").SpecialCells(xlCellTypeBlanks)
On Error Goto 0
If Not Rng Is Nothing Then
Rng.Delete Shift:=xlUp
End If
End Sub
Вы действительно можете сделать это за один проход, но нужно использовать ListObject
объект и его DataBodyRange
а также ListColumns
свойства:
Sub ClearBlankCellsInColumnNew()
Dim rngBlanks As Excel.Range
With Worksheets("Sheet1").ListObjects("Table1")
On Error Resume Next
Set rngBlanks = Intersect(.DataBodyRange, .ListColumns("New").Range).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rngBlanks Is Nothing Then
rngBlanks.Delete
End If
End With
End Sub
Этот лайнер также поможет
при ошибке возобновить следующий ', чтобы продолжить макрос, если в таблице не найдено пустой строки.Range("Table1").Columns(1).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
'это удалить пусто, используя 1-й столбец в качестве справки для проверки пробелов' Использовать собственные имена для таблиц для упрощения манипуляций с кодами
Адаптация предыдущих ответов:
On Error Resume Next
Set Rng = ListObjects(1).DataBodyRange.SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not Rng Is Nothing Then
Rng.Delete Shift:=xlUp
End If
Шаг 1: Создайте вспомогательный столбец в таблице, где вы проверяете наличие пустых полей в этой строке. Например, если в вашей таблице 3 столбца: A (цена), B (количество) и C (стоимость), вы бы добавили четвертый столбец D и пометили его "Любые пропуски?". Уравнение будет =IF(OR(ISBLANK([@Price]),ISBLANK([@Quantity]),ISBLANK([@Cost])),"Yes","No")
Это даст вам столбец для фильтрации, чтобы просмотреть все пробелы.
Шаг 2: В VBA вы должны сделать следующее:
Range("MyTableNameHere").AutoFilter Field:=Range("MyTableNameHere[Any Blanks?]").Column, Criteria1:="Yes"
Application.DisplayAlerts = False
Range("MyTableNameHere").ListObject.DataBodyRange.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
Range("MyTableNameHere").AutoFilter Field:=Range("MyTableNameHere[Any Blanks?]").Column
По сути, это фильтрация строк, которые вы хотите удалить в таблице, используя вспомогательный столбец, выбор всех видимых данных в таблице и отфильтрование таблицы. Я искал, как удалить все видимые строки в таблице, и нашел это и возился, пока не понял, что это будет работать. Взяв это и объединив его со вспомогательным столбцом, чтобы выбрать все строки с любыми пробелами, кажется, что вы тоже хотели.
Использование ListObjects в Excel позволяет легко использовать следующее для удаления пустых строк.
Sub RemoveBlankRow(ByVal SheetName As String, TableName As String)
Dim rng As Integer
rng = Sheets(SheetName).ListObjects(TableName).DataBodyRange.Rows.Count
For i = 1 To rng
If Application.WorksheetFunction.CountA(Rows(i)) = 0 Then Rows(i).EntireRow.Delete
Next
End Sub
Это мое решение:
Public Sub remove_blank_rows(sh As Worksheet)
Dim tbl As ListObject
Set tbl = sh.ListObjects(1)
Dim i As Long
Dim ii As Long
Application.EnableEvents = False
ii = tbl.Range.rows.Count
For i = 2 To ii
If WorksheetFunction.CountA(rows(i)) = 0 Then
rows(i).EntireRow.Delete
ii = tbl.Range.rows.Count
If i >= ii Then
GoTo A
End If
If i > 1 Then
i = i - 1
End If
End If
Next
A:
Application.EnableEvents = True
End Sub
Обратите внимание, что когда вы удаляете строку, все строки под ней сдвигаются вверх на 1, поэтому индекс уменьшается, чтобы снова проверить ту же строку на следующей итерации! Однако обратите внимание, чтоi
не нужно выходить за определенные пределы, и это делается с помощью двухIf
предложения.
Два примечания относительно решения Фрея Линдстрома, которое я использовал, но пришлось немного подправить:
(1) добавьте End If перед Next
(2) добавьте "i = i - 1" непосредственно перед End If
Why?
потому что, если у вас есть пустые строки одна над другой, вы пропустите одну, поскольку номера всех строк просто сдвинуты на одну вверх. По сути, если вы удалилиrow [N]
, теперь другая строка row [N]
, и вам также нужно протестировать его, а не сразу переходить к row [N + 1]
.
BIG CAVEAT: если ваша последняя строка пуста, это приведет к зависанию цикла. Я, вероятно, поставлю IF, чтобы справиться с этим.
Я знаю, что это старый поток, но подумал, что добавлю его на случай, если кто-то еще найдет похожие решения. Спасибо Frej - ваш код действительно помог!