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

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

我的代码显示在我的错误:

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

作为types不匹配

 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 

试试这个代码来解决你的问题。 它不仅解决了有问题的路线,而且还避免了一些其他的陷阱,从长远来看不可避免地会造成问题。

 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语句求Boolean 。 在幕后,口译员试图将"OI"转换为"OI" True或“ False "OI" ,但无法实现。 结果,你得到一个错误。 修复很简单:

If Selection.Value <> "SI" or Selection.Value <> "OI" Then 。 现在我们有两个Boolean语句,都检查是否相等。 口译员对此感到高兴,可以运行得很好。

除此之外,我还修复了您的非限定范围参考以及您的ActivateSelect练习。 尽pipe有人提出了一些build议,但都是非常不好的习惯。 您的代码将会中断,而且花费您的代价。 不要相信我? 阅读关于ActivateSelect其他任何post,你会看到同样的事情。

为什么这是一个坏主意? 在运行时,您完全不能控制ActiveSheetfunction。 当然你可以Activate它,但是会有一些东西进来,把焦点改成另一张纸,然后你就会有问题。 如果你不小心,这个bug可以花费几个小时的工作。

修复很简单。 只要声明一个variables(就像你几乎有),并使用该variables。 瞧! 没有更多的担心有错误的表。

最后, Excel非常善于理解使用索引来引用工作表部分的含义。 你不必Selection.Offset(1, 0).Select ,然后Selection.EntireRow.Delete因为所有这一切的真正意思是ActiveSheet.Rows(Selection.Row + 1).Delete ,我们可以重构,进一步使用工作表和索引Foo.Rows(i + 1).Delete 。 看到这里的模式? 变得更抽象,一步一步,直到你的代码变得坚实。

我改变的最后一件事是你的variables名称。 使用描述性名称,它使您的代码更易于维护。 另外,在理解Interfaces之前, 永远不要使用下划线“_”。 下划线对翻译有特殊的意义。

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

祝你好运!

正如卢克拉格所说,从底部开始。 也最好得到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 

个别删除行很慢(删除多次,所以删除时间很长)合并范围后,立即删除合并范围(使用联合方式)

 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 

只是修复线
If Selection.Value <> "SI" Or "OI" Then

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

一旦你用MFG_wb.Sheets("Aleris").Activate激活了表单, 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方法,这不是一个好的做法。 如果你有兴趣,我build议你阅读为什么你应该避免使用这样的function。