VBA Excel - 有没有办法根据两列中的条件删除行?

时间:2013-03-14 17:28:45

标签: excel excel-vba vba

我一直在研究一个宏来清理生成并复制到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行。

我没有广泛的宏观知识(显然),如此详细解释某些部分如何工作将是值得赞赏的。 提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

是的,不需要循环

您的公式(在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 也是可能的:)

菲利普

答案 1 :(得分:1)

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

假设您的代码在Sheet 1上。我已经对代码进行了评论,以便您更轻松地遵循。如果您不想将行1-5视为删除,请将For loop值设置为6,因为代码中的注释会显示。

请注意,删除是从下往上进行的,因为当您删除行时,totalRows计数会在循环中发生变化。为了避免循环丢失行,我只是按相反顺序进行。

<强> CODE

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

<强> BEFORE

enter image description here

<强> AFTER

enter image description here