如果单元格为空,则删除整行

时间:2018-07-11 08:03:52

标签: excel vba excel-vba

在Excel中,如果单元格为空,我想删除整行。 这应该算作A17:A1000。 运行脚本会返回错误:

  

运行时1004错误
  全局对象失败的方法范围

如果我将A17:A1000替换为A,则会删除一些行。

Sub DeleteBlanks()
    Dim r As Long
    Dim m As Long
    Application.ScreenUpdating = False
    m = Range("A17:A1000" & Rows.Count).End(xlUp).Row
    For r = m To 1 Step -1
        If Range("A17:A1000" & r).Value = "" Or Range("A17:A1000" & r).Value = 0 Then
            Range("A17:A1000" & r).EntireRow.Delete
        End If
    Next r
    Application.ScreenUpdating = True
End Sub

3 个答案:

答案 0 :(得分:3)

代码中的主要问题是计数错误。 "A17:A1000" & r不会将行数向上计数,而是将数字r附加到该字符串。因此,例如,如果r = 500会导致"A17:A1000500"而不是您期望的"A17:A1500"


要删除A列为空白单元格的所有行,可以使用

Option Explicit

Public Sub DeleteRowsWithBlankCellsInA()
    Worksheets("Sheet1").Range("A17:A1000").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub

该命令可一次删除所有空白行,因此速度非常快。同样,它不需要禁用ScreenUpdating,因为它只是一项操作。


或者如果需要删除空白和零个单元格,则使用

Option Explicit

Public Sub DeleteRowsWithBlankOrZeroCellsInA()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1") 'define which worksheet

    Dim LastRow As Long
    LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    Dim iRow As Long
    For iRow = LastRow To 1 Step -1
        If ws.Cells(iRow, "A").Value = vbNullString Or ws.Cells(iRow, "A").Value = 0 Then
            ws.Rows(iRow).Delete
        End If
    Next iRow
End Sub

此命令逐行删除。每个删除操作都会花费时间,因此删除更多行会花费更长的时间。另外,它可能需要禁用ScreenUpdating,否则您会看到逐行操作。

另一种方法是使用Union()收集要删除的所有行,然后立即删除它们。

Option Explicit

Public Sub DeleteRowsWithBlankOrZeroCellsInA()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Sheet1")  'define which worksheet

    Dim LastRow As Long
    LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    Dim DeleteRange As Range

    Dim iRow As Long
    For iRow = LastRow To 1 Step -1 'also forward looping is possible in this case: For iRow = 1 To LastRow
        If ws.Cells(iRow, "A").Value = vbNullString Or ws.Cells(iRow, "A").Value = 0 Then
            If DeleteRange Is Nothing Then
                Set DeleteRange = ws.Rows(iRow)
            Else
                Set DeleteRange = Union(DeleteRange, ws.Rows(iRow)) 'collect rows to delete
            End If
        End If
    Next iRow

    DeleteRange.Delete 'delete all at once
End Sub

这也非常快,因为您再次只有一个删除操作。同样,它不需要禁用ScreenUpdating,因为它只是一项操作。

在这种情况下,也不必向后循环Step -1,因为它只收集循环中的行并立即删除(在循环之后)。因此,从For iRow = 1 To LastRow循环也可以。

答案 1 :(得分:1)

您的代码中存在多个错误。

  1. 首先,您的过程应声明其作用域。 大概是您的情况Private
  2. 您错误地定义了Range(),请查看its definition
  3. Range.Value = 0Range = ""不同或更好,IsEmpty(Range)
  4. 删除单个行时从头到尾的循环会引起复杂性(给定它们的索引 [indices(?)] 更改)-或更好地说一句-这是一种有效的做法,但是您应该知道您在使用索引做什么。在您的情况下,按照LIFO顺序进行操作对他们来说似乎容易得多。
  5. 最后但并非最不重要的一点是,您不必要地将代码与某些声明复杂化(可以说不是一个错误,但有待改进)

考虑所有因素后,您的代码应如下所示:

Option Explicit
Private Sub remove_empty_rows()
Dim ws as Worksheet: Set ws = Sheets("Your Sheet Name")
Dim lr as Long
lr = ws.Cells(Rows.Count, 1).End(xlUp).Row

Dim i as Long
For i = lr to 1 Step -1
   If IsEmpty(ws.Cells(i, 1)) Then
      ws.Rows(i).Delete
   End If
Next i

End Sub

通常来说,听起来并不逊色,但是您似乎在编码实践中有一些学习上的空白。在实际自己编写这样的代码之前,我会先推荐您正确阅读一些文档或教程。

答案 2 :(得分:1)

考虑到A17单元是标头,您可以使用AutoFilter而不是遍历单元格:

Sub FastDeleteMethod()
    Dim rng As Range, rngFiltered As Range
    Set rng = Range("A17:A" & Cells(Rows.Count, "A").End(xlUp).Row)
    With rng
        .AutoFilter Field:=1, Criteria1:=0, Operator:=xlOr, Criteria2:="="
        On Error Resume Next
        Set rngFiltered = rng.SpecialCells(xlCellTypeVisible)
        If Err = 0 Then rngFiltered.EntireRow.Delete
        On Error GoTo 0
    End With
End Sub
相关问题