VB Excel删除单元格中指定值的行

时间:2015-05-27 15:51:14

标签: excel excel-vba vba

    For Each c In oSheet.Range("A1:A1000")
        If InStr(c.Value, "VALUE") Then
            c.EntireRow.Delete()
        End If
    Next

这只会删除指定范围内的一些行,问题是什么?

2 个答案:

答案 0 :(得分:3)

以下是基于条件删除整行的两种常见模式。主要思想是在迭代时无法从集合中删除。这意味着Delete不应出现在For Each中。这在大多数编程语言中都是相当标准的,有些甚至会抛出错误来阻止它。

选项1 ,使用整数来跟踪行并使其从末尾开始工作。您需要向后退,因为这是避免跳过行的简单方法。可以前进,你只需要在删除时考虑不增加。

Sub DeleteRowsWithIntegerLoop()

    Dim rng_delete As Range
    Set rng_delete = Range("A1:A1000")

    Dim int_start As Integer
    int_start = rng_delete.Rows.Count

    Dim i As Integer
    For i = int_start To 1 Step -1
        If InStr(rng_delete.Cells(i), "VALUE") > 0 Then
            rng_delete.Cells(i).EntireRow.Delete
        End If
    Next i

End Sub

选项2 ,使用Union-Delete模式构建一系列单元格,然后在最后一步中将它们全部删除。

Sub DeleteRowsWithUnionDelete()


    Dim rng_cell As Range
    Dim rng_delete As Range

    For Each rng_cell In Range("A1:A1000")
        If InStr(rng_cell, "VALUE") > 0 Then
            If rng_delete Is Nothing Then
                Set rng_delete = rng_cell
            Else
                Set rng_delete = Union(rng_delete, rng_cell)
            End If
        End If
    Next

    rng_delete.EntireRow.Delete

End Sub

有关代码的说明

对于选项2,当从第一个项目开始时,有一个额外的条件来创建rng_deleteUnion不适用于Nothing引用,因此我们先检查一下,如果是,Set查看第一项。所有其他人都通过Set行获得Union

<强>偏好

在两者之间进行选择时,我总是更喜欢选项2,因为我更喜欢在Excel中使用Ranges而不是使用计数器迭代Cells。这有一些限制。第二个选项也适用于不连续的Ranges以及所有其他各种奇怪的Ranges(例如,在调用SpecialCells之后),当您不确定自己将使用哪些数据时,它可以使其有价值处理。

<强>速度

我不确定速度比较。如果ScreenUpdating并且启用了计算,则两者都可能很慢。第一个选项使N-1调用Delete,而第二个选项执行单个选项。 Delete是一项昂贵的操作。但是,选项2会对N-1Union进行Set次调用。我认为它比基于它的第一个更快(它似乎在这里),但我没有描述它。

最后注释:InStr返回一个整数,指示找到值的位置。我总是喜欢在这里明确布尔covnersion并与>0进行比较。

答案 1 :(得分:1)

不要使用循环,请使用AutoFilter

等方法
Sub Recut()
Dim ws As Worksheet
Dim rng1 As Range

Set ws = ActiveSheet
Set rng1 = ws.[A1:A100]

ws.AutoFilterMode = False

Application.ScreenUpdating = False
With rng1
      .AutoFilter Field:=1, Criteria1:="*VALUE*"
      `assuming A1 is a header, and checking for at least 1 match on the filtered string
       If .SpecialCells(xlCellTypeVisible).Cells.Count > 1 Then .Offset(1, 0).Resize(rng1.Rows.Count - 1, 1).EntireRow.Delete
End With
ws.AutoFilterMode = False
Application.ScreenUpdating = True

End Sub