如果单元格不包含值,则删除行

时间:2017-08-28 09:56:12

标签: excel vba excel-vba

我想传递O列中某个范围内的所有单元格,并删除所有不包含值的行:OI和SI。

我的代码在以下位置显示错误:

If Selection.Value <> "SI" Or "OI" Then

作为类型不匹配

Sub CHECK()
Dim MFG_wb As Workbook
Dim Dep As Integer
Dim I As Integer

Set MFG_wb = Workbooks.Open _
("C:\Users\rosipov\Desktop\eliran\MFG - GSS\MFG Daily\Fast Daily " & Format(Now(), "ddmmyy") & ".xlsx", _
UpdateLinks:=False, IgnoreReadOnlyRecommended:=True)
MFG_wb.Sheets("Aleris").Activate

Dep = MFG_wb.Sheets("Aleris").Range("O2", Range("O2").End(xlDown)).Count

Range("O2").Select

For I = 1 To Dep

    If Selection.Value <> "SI" Or "OI" Then
        EntireRow.Delete
    Else
        Selection.Offset(1, 0).Select
    End If

Next I

End Sub

5 个答案:

答案 0 :(得分:5)

尝试使用此代码来解决您的问题。它不仅修复了有问题的界限,而且避免了其他一些陷阱,从长远来看也不可避免地会引发问题。

Sub CHECK()
    Dim ManufacturingFile As Workbook
    Set ManufacturingFile = Workbooks.Open _
                 ("C:\Users\rosipov\Desktop\eliran\MFG - GSS\MFG Daily\Fast Daily " & Format(Now(), "ddmmyy") & ".xlsx", _
                  UpdateLinks:=False, IgnoreReadOnlyRecommended:=True)

    Dim Aleris As Worksheet
    Set Aleris = ManufacturingFile.Worksheets("Aleris")

    Dim TotalRows As Long
    TotalRows = Aleris.Range("O2", Aleris.Range("O2").End(xlDown)).Count

    ' Avoid Select at all costs
    ' Range("O2").Select

    Dim i As Long
    For i = TotalRows To 1 Step -1
        If Aleris.Range("O" & i).Value <> "SI" And Aleris.Range("O" & i).Value <> "OI" Then
            Aleris.Rows(i).Delete
        End If
    Next i
End Sub

首先,您的问题是由If Selection.Value <> "SI" Or "OI" Then引起的,因为"OI"无法作为Boolean语句进行评估。在幕后,口译员试图将"OI"转换为TrueFalse,但无法将其转换为If Selection.Value <> "SI" or Selection.Value <> "OI" Then。结果,您收到错误。修复很简单:

Boolean。现在我们有两个Activate语句,都检查是否相等。口译员对此很满意,并且运行得很好。

除此之外,我修复了您的不合格范围参考,以及SelectActivate的练习。尽管其他人提出了一些建议,但这些都是非常坏习惯。您的代码中断,而 会花费您的代价。别相信我?几乎阅读关于SelectActiveSheet的任何其他帖子,您会看到同样的事情。

为什么这是一个坏主意?您无法控制Activate在运行时的状态。当然你可以Excel它,但是会有一些时间进入并将焦点转移到另一张纸上,然后你就会遇到问题。如果您不小心,这一个错误可能会花费数小时的工作量。

修复很简单。只需声明一个变量(就像你几乎拥有的那样),并使用该变量。瞧!不再担心错误的表格。

最后,当您使用索引引用工作表的某些部分时,Selection.Offset(1, 0).Select非常擅长理解您的意思。您不必Selection.EntireRow.Delete然后ActiveSheet.Rows(Selection.Row + 1).Delete,因为所有这些真正意味着Foo.Rows(i + 1).Delete,我们可以进一步重构以使用工作表和{{1}的索引}。看到这里的模式?逐步变得更抽象,直到你的代码变得稳固。

我改变的最后一件事是你的变量名。使用描述性名称,它使您的代码更易于维护。此外,永远不会使用下划线&#34; _&#34;直到你理解Interfaces为止。下划线对翻译有特殊意义。

最后,查看Rubberduck项目:rubberduckvba.com。它是一个免费的插件,致力于改善VBA编码体验。最好的部分?大部分反馈都作为检查内置于RD中。它为你工作,你可以在这个过程中学习。

祝你好运!

答案 1 :(得分:3)

正如Luuklag所说,从底部开始。最好还是获取xlLastCell(不会停留在空白单元格)来计算行数并调整if语句以检查SI和OI:

Dep = MFG_wb.Sheets("Aleris").Range("O2").SpecialCells(xlLastCell).Row


For I = Dep To 2 Step -1
    Cells(I, 15).Select
    If Not (Selection.Value = "SI" Or Selection.Value = "OI") Then
        Rows(I).Delete
    End If
Next I

答案 2 :(得分:2)

单个删除行很慢。(此删除行多次,因此需要很长时间才能删除) 合并范围后,立即删除合并范围。(使用Union方法)

Sub CHECK()
Dim MFG_wb As Workbook
Dim Dep As Long
Dim i As Long '<~~  if your data is large then use long
Dim Ws As Worksheet
Dim s As String
Dim rngU As Range


    Set MFG_wb = Workbooks.Open _
    ("C:\Users\rosipov\Desktop\eliran\MFG - GSS\MFG Daily\Fast Daily " & Format(Now(), "ddmmyy") & ".xlsx", _
    UpdateLinks:=False, IgnoreReadOnlyRecommended:=True)
    'MFG_wb.Sheets("Aleris").Activate

    Set Ws = MFG_wb.Sheets("Aleris") '<~~ instead activate, use variable
    With Ws
        Dep = .Range("O2").End(xlDown).Row
    'Range("O2").Select '<~~ select mothod is not goo.
        For i = 2 To Dep
            s = .Range("o" & i)
            If s = "SI" Or s = "OI" Then
            Else
                If rngU Is Nothing Then
                    Set rngU = .Range("o" & i)
                Else
                    Set rngU = Union(rngU, .Range("o" & i))
                End If
            End If
        Next i
    End With
    If rngU Is Nothing Then
    Else
        rngU.EntireRow.Delete
    End If
MFG_wb.Save
MFG_wb.Close (0)
End Sub

答案 3 :(得分:1)

使用MFG_wb.Sheets("Aleris").Activate激活工作表后,您无需明确将其与Range个对象一起使用。在提到的行之后,代码应如下所示:

Dim s As Sheet
Set s = MFG_wb.Sheets("Aleris")
'determine last row in O column
Dep = s.Cells(s.Rows.Count, 15).End(xlUp).Row

For I = 1 To Dep Step -1
    If InStr(1, s.Cells(I, 15).Value, "SI") + InStr(1, s.Cells(I, 15).Value, "OI") = 0  Then
        s.Cells(I, 15).EntireRow.Delete
    End If
Next I

您发布的代码更改的主要原因是您使用Select方法,这不是一个好习惯。如果您有兴趣,我建议您阅读为什么您应该避免使用这些功能。

答案 4 :(得分:1)

只需修理线路 If Selection.Value <> "SI" Or "OI" Then
为了
If Selection.Value <> "SI" Or Selection.Value<>"OI" Then