我正在尝试运行一个宏,该宏选择表列中的空白单元格并删除整行。
下面的脚本执行了除删除部分之外的所有操作,从而提示以下错误:
运行时错误 1004 - “删除 Range 类的方法失败”
我使用了以下代码:
Sub test()
Range("Table1[[New]]").Activate
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.EntireRow.Delete
End Sub
问得好!如果没有桌子,
.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
第 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
这本质上是使用辅助列过滤到表中要删除的行,选择表中的所有可见数据,然后取消过滤表。 我正在搜索如何删除表中的所有可见行,并找到了这个并摆弄直到我发现这可行。 将其与辅助列结合起来以选择带有任何空白的所有行似乎也是您想要的。
改编之前的答案:
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
这个 One 衬垫也会有帮助
on error resume next '如果表中没有找到空行则继续宏 .Range("Table1").Columns(1).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
'此删除空使用第一列作为检查空白的参考 '为表使用自定义名称,以便在代码中轻松操作
在 Excel 中使用 ListObjects 可以轻松使用以下内容删除空白行。
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
关于 Frej Lindstrom 解决方案的两个注释,我使用过但必须稍作调整:
(1) 在 Next 之前添加 End If
(2) 在 End If 之前添加“i = i - 1”
Why?
,因为如果您有一层一层的空白行,您将跳过一行,因为所有行的数字都向上移动一位。本质上,如果您删除了 row [N]
,则另一行现在是 row [N]
,您还需要对其进行测试,而不是立即移至 row [N + 1]
。
重要警告:如果你的最后一行是空白,这会给你一个卡住的循环。不过,我可能会放入一个 IF 来处理它。
我知道这是一个旧线程,但我想我会添加这个,以防其他人来寻找类似的解决方案。感谢 Frej - 你的代码真的很有帮助!
这是我的解决方案:
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
递减以便在下一次迭代中再次检查同一行的原因!但请注意,i
不需要超过一定的限制,这是通过两个 If
句子完成的。
感谢您的合作。我不断得到一个额外的空白行,因此我必须进行一些修改。总之,DeleteBlankTableRows 宏使用 GetMyTableName UDF 从活动单元格获取表名称。如果活动单元格不在表格内,则返回“N/A”,并向用户发送一条消息以选择表格内的任何单元格。
Option Explicit
Function GetMyTableName(myActiveCell As Range) As String
Dim myTableName As String
myTableName = ""
On Error GoTo ErrorHndler
myTableName = myActiveCell.ListObject.Name
GetMyTableName = myTableName
Exit Function
ErrorHndler:
GetMyTableName = "N/A"
End Function
Sub DeleteBlankTableRows()
Dim myBook As Workbook, mySheet As Worksheet, myRange As Range
Dim myActiveCell As Range, myTableName As String
Dim i As Long, j As Long, myCount As Long, myTable As ListObject
Set myBook = ActiveWorkbook
Set mySheet = myBook.ActiveSheet
Set myActiveCell = ActiveCell
myTableName = GetMyTableName(myBook.Worksheets(mySheet.Name).Range(myActiveCell.Address))
If Not myTableName = "N/A" Then
Set myTable = myBook.Sheets(mySheet.Name).ListObjects(myTableName)
i = myTable.Range.Rows.Count
For j = 2 To i
If Application.WorksheetFunction.CountA(Rows(j)) = 0 Then
Rows(j).EntireRow.Delete
i = myTable.Range.Rows.Count
myCount = myCount + 1
If j > i Then
Exit For
End If
j = j - 1
End If
Next j
MsgBox myCount & " blank rows deleted. " & Chr(10) & Chr(10) & _
"TableName: " & myTableName & Chr(10) & _
"Worksheet: '" & mySheet.Name & "'" & Chr(10) & _
"TableRange: " & myTable.Range.Address, _
vbInformation + vbOKOnly, "DeleteBlankTableRows Macro"
Else
MsgBox "Cell " & myActiveCell.Address & " is not within a table. Please select a cell within the table and run this macro again.", vbInformation + vbOKOnly, "DeleteBlankTableRows Macro"
End If
End Sub