【问题标题】:VBA Excel - Is there a way to delete rows based on criteria in two columns?VBA Excel - 有没有办法根据两列中的条件删除行?
【发布时间】:2013-03-03 05:00:44
【问题描述】:

我一直在研究一个宏来清理生成并复制到 Excel 中的表单。在我需要删除包含多余公式的行的最后阶段之前,我已经弄清楚了一切。 示例:

400000  |  Smith, John| 2.4   | 5.66|   =C1+D1
400001  |  Q, Suzy    | 4.6   | 5.47|   =C2+D2
400002  |  Schmoe, Joe| 3.8   | 0.14|   =C3+D3
Blank   |             |       |     |   #VALUE
Blank   |             |       |     |   #VALUE

是否有一个公式可以将“A”列与“E”列进行比较,并让它删除所有在“A”中没有值但在“E”中有值的行?

我尝试了一个基本的循环公式,仅通过空的“A”列,它可以永久删除我想要保留的信息下方的行,我在这个网站上找到了一个处理过滤器的公式(来自brettdj) 但我不知道如何编辑它以正确捕获我需要的内容。

这是我从 brettdj 那里得到的:

Sub QuickKill()
Dim rng1 As Range, rng2 As Range, rng3 As Range
Set rng1 = Cells.Find("*", , xlValues, , xlByColumns, xlPrevious)
Set rng2 = Cells.Find("*", , xlValues, , xlByRows, xlPrevious)
Set rng3 = Range(Cells(rng2.Row, rng1.Column), Cells(1, rng1.Column))
Application.ScreenUpdating = False
Rows(1).Insert
With rng3.Offset(-1, 1).Resize(rng3.Rows.Count + 1, 1)
    .FormulaR1C1 = "=OR(RC1="",RC1<>"")"
    .AutoFilter Field:=2, Criteria1:="TRUE"
    .EntireRow.Delete
    On Error Resume Next
    'in case all rows have been deleted
    .EntireColumn.Delete
    On Error GoTo 0
End With
Application.ScreenUpdating = True

其他一些信息:

我要忽略的工作表的前 5 行,它们包含列标题和报告名称等。

40#### 填充的行数发生了变化,所以我不能简单地让宏将第 4 行删除。

我对宏(显然)没有广泛的了解,因此对某些部分如何工作的详细解释将不胜感激。 提前感谢您的帮助。

【问题讨论】:

  • 嗯,公式 FormulaR1C1 = "=OR(RC1="",RC1"")" 从 A1="" 或 A1" 返回 TRUE "
  • 我在下面添加了一个答案,该答案使用 SpecialCells 技巧来查找您要删除的所有行......但是,这取决于您是否获得正确的公式来测试是否应该删除一行!

标签: excel vba


【解决方案1】:

是的,有一种方法不需要循环

您的公式(在 Excel 电子表格中)将是这样的:

=IF(AND(A:A="",E:E<>""),"DELETE THIS ROW","LEAVE THIS ROW")

现在,可以让该公式将错误放在我测试返回 True 的行中。我们这样做的原因是 Excel 的一个称为 SpecialCells 的功能。

在 Excel 中选择任何空单元格,然后在编辑栏中输入

=NA()

接下来,按 F5 或 CTRL+G(转到...编辑 菜单上)然后单击 特殊 按钮以显示SpecialCells 对话框。

在该对话框中,单击“公式”旁边的单选按钮并在其下方清除复选框,以便仅选中 错误。现在点击确定

Excel 应该选择了工作表中包含错误 (#N/A) 的所有单元格。

下面的代码利用了这个技巧,通过在 H 列中创建一个公式,将 #N/A 放在要删除的所有行中,然后调用 SpecialCells 来查找行,并清除(删除)它们...

    Sub clearCells()
    '
    Dim sFormula As String
    '
    ' this formula put's an error if the test returns true, 
    ' so we can use SpecialCells function to highlight the
    ' rows to be deleted!
sFormula = "=IF(AND(A:A="""",E:E<>""""),NA(),"""")"
'
' put a formula into column H, to find the rows that ned to be deleted...
Range("H5:H" & Range("E65536").End(xlUp).Row).Formula = sFormula
'
Stop ' next line clears multiple rows, could also delete the entire row!
' now clear the cells returned by SpecialCells ...
Range("H5:H" & Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlErrors).Offset(0, -7).Clear ' ' EntireRow .Delete shift:=xlup
'
' clean up the formula
Range("H5:H" & Range("E65536").End(xlUp).Row).Clear    '
    End Sub

复制粘贴并使用 F8 单步执行 ...

那么我们可以为您提供更多帮助...

希望你能开始

顺便说一句,如果您真的想要一个,也可以 WITH A LOOP :)

菲利普

【讨论】:

  • 谢谢菲利普!这非常有效,我唯一遇到的问题是在测试我的“E”列中的公式时实际上没有值,所以它们都是#value!这抛弃了你的公式。一旦我确定公式有实际的答案,一切都点击了。它也跑得非常快,这太棒了。我也很欣赏你提供的细节。很有帮助!
【解决方案2】:

我不知道为什么 Philip 认为使用循环是一件坏事。这是一个简单的宏,它遍历每一行并删除Column A 为空且Column E 具有某些值的行。

假设您的代码在Sheet 1 上。我已经对代码进行了注释,以使您更容易理解。如果您不想考虑删除行 1-5,请按照代码中的注释将 For loop 值设置为 6

请注意,删除是自下而上进行的,因为当您删除一行时,循环中的totalRows 计数会发生变化。为了避免缺少行的循环,我只是按相反的顺序进行。

代码

Public Sub DeleteWhereEmpty()
    Dim colARowCount As Integer
    Dim colERowCount As Integer
    Dim totalRows As Integer
    Dim currentRow As Integer
    Dim colA As Integer
    Dim colE As Integer
    Dim colACurrentValue As String
    Dim colECurrentValue As String

    colA = 1
    colE = 5
    colARowCount = Sheet1.Cells(Rows.Count, colA).End(xlUp).Row
    colERowCount = Sheet1.Cells(Rows.Count, colE).End(xlUp).Row

    'set total number of rows to look at
    totalRows = colARowCount
    If colARowCount < colERowCount Then
        totalRows = colERowCount 'E has more rows, so use it
    End If

    'to stop deleting at row 5, replace 'To 1' with 'To 6'
    For currentRow = totalRows To 1 Step -1
        colACurrentValue = Cells(currentRow, colA).Value
        colECurrentValue = Cells(currentRow, colE).Text

        'if A is empty and E has data in it, delete the row
        If colACurrentValue = "" Or IsEmpty(colACurrentValue) _
           And Len(colECurrentValue) > 0 Then
            Cells(currentRow, colA).EntireRow.Delete
        End If
    Next
End Sub

之前

之后

【讨论】:

  • 谢谢你的循环版本,山姆。尽管公式在“E”列中没有正确的答案,但它运行完美,这是我在测试 Philip's 时遇到的问题,尽管它需要一点时间才能完成。以防万一,我会将这两个版本都保留在我的工作表中。非常感谢您的帮助!
猜你喜欢
  • 2014-11-09
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2021-11-04
  • 2011-11-30
  • 1970-01-01
相关资源
最近更新 更多