【问题标题】:Delete rows based on condition in a column根据列中的条件删除行
【发布时间】:2012-07-27 20:45:08
【问题描述】:

我已经在网上和这里搜索过,但找不到任何似乎符合要求和工作的东西。我有一些有效的代码,但是因为范围的长度在删除行时会发生变化,所以它不会捕获所有要删除的行,所以我最终运行了几次,这不是很好......所以我m 现在正在尝试此线程上推荐的 AutoFilter 方法。

我有一个包含几列的电子表格,其中一列是“成本”。我需要遍历“成本”列(有时可能是第 9 列,有时是第 10 列,因此下面的“查找”位)并删除成本为 0 的任何行...

以下是我到目前为止编写的代码,任何帮助将非常非常感谢!!!!

-- 编辑 3:进行了更多代码更改...新代码如下。

Sub RemoveRows()
    Dim cell As Range
    Dim lastRow As Long
    Dim lastColumn As Integer
    Dim criteraColumn As Integer
    Dim criteriaRange As Range

    lastRow = Cells.Find(What:="*", After:=Range("A1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row
    lastColumn = Cells.Find(What:="*", After:=Range("A1"), LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column

    Rows(1).EntireRow.Select
    criteriaColumn = Selection.Find(What:="Cost", After:=ActiveCell, LookIn:= _
                        xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
                        xlNext, MatchCase:=False, SearchFormat:=False).Column
    Set criteriaRange = Range("A1", Cells(lastRow, lastColumn))

    criteriaRange.AutoFilter Field:=criteriaColumn, Criteria1:="£0.00"
    AutoFilter.Range.Delete
    ActiveSheet.AutoFilterMode = False
End Sub

当我运行它时,它会将过滤器应用于正确的范围和正确的列。然后我收到错误消息:“运行时错误'424':需要对象”,适用于AutoFilter.Range.Delete 行。当我按下“结束”或“调试”并查看电子表格时,过滤器已应用于正确的列并检查了正确的选项(0.00 英镑),但没有返回任何结果(我知道我需要这样做将来出现这种情况时会进行一些错误处理,但目前该过滤器应该至少返回 10 行)。如果我在电子表格中的过滤器设置上手动按“确定”(不更改任何设置!)我的 10 个结果会正确显示,所以我不确定为什么当我以编程方式执行此操作时它们没有显示?

如果需要,很乐意提供电子表格示例,这真的让我很困惑!

电子表格可以找到here

【问题讨论】:

  • 如前所述,遍历范围是效率最低的方法。将范围存储在一个数组中,然后在其中循环将提供一些速度提升。另一种更快的方法是使用FindMATCH 函数而不是循环。但是,我发现最快的方法是使用自动过滤器。 SO上有许多其他示例(尽管此处提供了答案):delete special rowsdelete row based on condition
  • 谢谢 Zairja - 这也是我将按照其他几个人的建议使用的方法,非常感谢大家的帮助!

标签: vba excel excel-2007


【解决方案1】:

您应该能够使用 Excel 自动筛选来删除行。

Cells.AutoFilter Field:=criteriaColumn, Criteria1:="£0.00"
ActiveSheet.AutoFilter.Range.Offset(1).Delete
ActiveSheet.ShowAllData

这将过滤成本 = 0,然后删除与过滤器匹配的所有行。

运算符自动等于,因此您不需要“=£0.00”作为参数。

我在 ActiveSheet 中添加了 AutoFilter 以摆脱未找到的对象,并且 Offset 使其不删除标题。

【讨论】:

  • +1 很好的解决方案,易于实施。也打算用它来更新我的帖子,但你打败了我!
  • 太棒了 - 甚至没有想到这一点。非常感谢 Jon - 和 Scott!
  • 我想我一定是做错了——我已经修改了我的代码(我已经编辑了我原来的帖子)但是自动过滤器似乎根本没有做任何事情?
  • 我没有可用的 excel 2007 来测试它(只有 2010 年),但它似乎对我有用。确保您的条件列是正确的。
  • 我编辑了我的答案。它应该可以解决货币格式的问题。
【解决方案2】:

出于性能原因,我会以另一种方式进行(逐行读取+删除速度很慢)。 我之前回答过一个类似的问题,我认为它也很适用于你的帖子。

我建议你可以做什么:

  • 不是逐行读取工作表,而是将整个范围加载到一个数组中一次;
  • 不是逐行删除,而是将所需的值传输到内存中的第二个数组中;
  • 当你有你需要的数据时,应用 oRange.clearcontents 来清除当前范围;
  • 通过应用 oRange = vArray 将新的数据数组显示到工作表中。

读/转换数据在内存中进行,读写只进行一次。

在这个线程中,你有我之前写的代码: Execution of VBA code gets slow after many iterations

让我知道这是否可以帮助您,或者您是否希望收到更具体的信息/代码。

【讨论】:

  • 谢谢——明天我会重写它,让它更优雅!
【解决方案3】:

您需要在范围内后退一步,因为在 Excel 中,删除行会自动将行上移一格。

替换:

   For Each cell In criteriaRange.Cells
        If cell.Value = 0 Then
            cell.EntireRow.Delete
        End If
    Next cell

与:

Dim i As Integer

For i = criteriaRange.Rows.Count To 1 Step -1
    If criteriaRange.Cells(i) = 0 Then
        criteriaRange.Cells(i).EntireRow.Delete
    End If
Next

另外,ScreenUpdating 对宏的方法没有影响。它基本上会为宏执行的每个操作关闭“屏幕闪烁”,使其运行得更快、更流畅,从而获得用户体验。

【讨论】:

  • 是的,这很有意义。后退可避免任何跳行。
  • 这正是我所需要的,并且非常有意义,但不幸的是,当我尝试运行它时,它完全杀死了 excel - 我认为它陷入了循环,因此可能会按照 Kim Gyson 建议的方式重新编程
  • 您说的有道理,具体取决于您的数据深度。但是,尽管充分尊重@KimGyson 的方法,因为它是一种出色、高效的方法,您可能会发现 Jon 的AutoFilter 答案在易于实施和理解方面是最好的。 AutoFilter 快速高效。我在他的代码中唯一看到的是,它可能需要稍微调整以适应您的数据结构。我其实也打算这么建议的,但他抢先了!
【解决方案4】:

您可以拥有它,因此每当它删除一行时,它要么返回到列的顶部,要么您可以从计数中减去一个。无论哪种方式,它都不会跳过任何行。我会提供实际代码,但我是 VBA 新手,不太清楚该怎么做。

【讨论】:

  • 谢谢 - 我正在和某人讨论这个问题,只是得出了相同的结论,但是当我使用 For 循环时,我想我必须让它退出循环然后启动它再说一次,我想这似乎不是很有效-感谢您对此的帮助!我将继续搜索代码,如果找到答案,我会在此处发布 - 除非这里有人击败我!
  • 在这种情况下,您可以执行 Do While 循环而不是 For 循环。每当您不知道最终要执行多少次迭代时,请执行 Do While 循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
相关资源
最近更新 更多