如何批量删除行避免‘Range类Delete方法’报错?及VBA数组使用疑问
解决VBA删除空单元格行时的"Delete method of the range class failed"错误,以及数组使用问题
首先直接回答你的核心问题:你对数组和ReDim Preserve的使用语法上是正确的,它确实能动态收集到空单元格所在的行号。不过这个写法有优化空间(后面会提到),但它并不是导致你删除报错的原因。
报错的真正原因
你代码里初始化Amass范围的方式出了问题:
Set Amass = Sheets("Quotation").Range("10000:10000")
这个初始的第10000行完全是多余的:
- 如果你的目标区域
I17:I3816里没有任何空单元格,D的值会是0,第二个循环根本不会执行,最后执行Amass.EntireRow.Delete时就会错误删除第10000行;如果该行被工作表保护、或者有合并单元格/锁定内容,就会触发你看到的"Delete method of the range class failed"错误。 - 就算找到了空单元格,这个无关的第10000行也会被一并Union进去,最后被错误删除,造成不必要的数据丢失。
修正后的代码
我帮你调整了代码,解决了报错问题,同时优化了数组的使用效率:
Sub DeleteBlankRows() ' 重命名子程序避免和内置Delete方法冲突 Dim B As Range, Blank As Range Dim Deletion() As Long Dim D As Long, i As Long Set Blank = Sheets("Quotation").Range("I17:I3816") D = 0 ' 第一步:先统计空单元格数量 For Each B In Blank If IsEmpty(B.Value) Then D = D + 1 End If Next B ' 如果没有空单元格,直接退出,避免后续操作 If D = 0 Then MsgBox "没有找到空单元格,无需删除行" Exit Sub End If ' 一次性初始化数组大小,避免多次ReDim Preserve的性能损耗 ReDim Deletion(1 To D) D = 0 ' 第二步:收集空单元格的行号 For Each B In Blank If IsEmpty(B.Value) Then D = D + 1 Deletion(D) = B.Row End If Next B Dim Amass As Range ' 初始化为Nothing,避免引入无关行 Set Amass = Nothing ' 收集要删除的行范围 For i = 1 To UBound(Deletion) If Amass Is Nothing Then Set Amass = Sheets("Quotation").Rows(Deletion(i)) Else Set Amass = Union(Amass, Sheets("Quotation").Rows(Deletion(i))) End If Next i ' 执行删除 If Not Amass Is Nothing Then Amass.Delete MsgBox "成功删除" & D & "行空单元格所在行" End If End Sub
额外优化说明
- 把原来的子程序名
Delete改成了DeleteBlankRows,避免和VBA内置的Delete方法重名,减少潜在冲突。 - 先统计空单元格数量再一次性初始化数组,比每次
ReDim Preserve更高效(尤其是当数据量很大的时候)。 - 增加了无空单元格时的判断和提示,避免无意义的操作。
- 直接用
Rows(行号)来引用整行,比拼接字符串Range(Deletion(i) & ":" & Deletion(i))更简洁可靠。
内容的提问来源于stack exchange,提问作者Ben Gerry




