Vba 如果单元格不包含值,则删除行
我希望传递O列中某个范围内的所有单元格,并删除所有不包含值的行:OI和SI 我的代码显示以下位置的错误:Vba 如果单元格不包含值,则删除行,vba,excel,Vba,Excel,我希望传递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
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
使用MFG_wb.SheetsAleris.Activate激活图纸后,无需显式将其用于范围对象。在上述行之后,代码应该如下所示:
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方法,这不是一个好的做法。若你们感兴趣的话,我建议你们读一读为什么你们应该避免使用这些功能。只要修改一下就行了
如果选择值为SI或OI,则
到
如果Selection.Value SI或Selection.ValueOI,则如LUKLAG所述,从底部开始。另外,最好获取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 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或OI引起的,因为OI不能作为布尔语句计算。在幕后,口译员试图将OI转换为真或假,但未能成功。因此,您会得到一个错误。解决方法很简单:
如果选择.Value SI或选择.Value OI,则。现在我们有两个布尔语句,都在检查是否相等。口译员对此很满意,可以很好地运行
除此之外,我还修复了您不合格的范围引用,以及您的激活和选择实践。尽管其他人提出了一些建议,但这两个都是非常坏的习惯。你的代码将被破坏,这将使你付出代价。不相信我?阅读几乎所有其他关于激活和选择的帖子,你会看到同样的事情
为什么这是个坏主意?在运行时,您完全无法控制ActiveSheet是什么。当然,你可以激活它,但会有一段时间,有东西进来,改变焦点到另一张纸上,然后你会有问题。如果你不小心的话,这一个bug可能会花费数小时的工作时间
解决办法很简单。只需声明一个几乎所有的变量,然后使用该变量。瞧!不用再担心床单弄错了
最后,当您使用索引引用工作表的某些部分时,Excel非常善于理解您的意思。您不必先选择Selection.Offset1,0。然后选择Selection.EntireRow.Delete,因为这实际上意味着ActiveSheet.RowsSelection.Row+1.Delete,我们可以进一步重构它以使用工作表和Foo.Rowsi+1.Delete的索引。看到这里的图案了吗?一步一步地变得更加抽象,直到代码变得坚实
我最后更改的是变量名。使用描述性名称,可以使代码更易于维护。此外,在理解接口之前,永远不要在名称中使用下划线。下划线对口译员有特殊的意义
最后,查看Rubberduck项目:ruberduckvba.com。这是一个免费的插件,专门用于改善VBA编码体验。最好的部分是什么?这些反馈大多作为检查内置于研发中。它为你工作,你在这个过程中学习
祝你好运 单个删除行速度较慢。此删除行多次,因此删除时间较长 合并范围后,立即删除合并范围。使用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
添加更多信息:它如何不起作用?它会抛出一个错误,还是不做你想做的?另外,您使用的Office版本可能与@RealCheeseLord重复。它显示了一个错误:如果选择。值SI或OI,则作为类型不匹配删除行时,最佳做法是从底部开始,然后向上操作。这样你就不需要你的I=I-1。为此,将I=1到Dep更改为:I=1到Dep步骤-1最好完全避免激活,并保留对工作表的引用。您误解了我的意思,我想用SI或OI保留行,删除其他行。@RafaelOsipov,然后你的问题写得不够清楚。@MichałTurczyn使用Activate命令实际上是一种非常糟糕的做法,你建议Rafael使用不合格的范围和单元格引用,这使问题更加复杂。这是个糟糕的主意。最简单的例子是,如果在代码运行过程中激活了另一个工作表,该怎么办?提示:您不再使用您认为正在使用的工作表。您应该始终使用指向要使用的对象的变量来完全限定范围引用。非常好,谢谢!它完成了工作,但在几个循环之后,它停止并写入了range类的delete方法failedMaybe您的工作表包含一个带有标题的表,应该跳过它,我没有想到,如果是这样的话,只需返回到第二行:对于I=Dep到2步骤-1,还有关于best pract的注释
Brandon Barney的ICE非常有效,不使用selection、activate等。请确保在selection.ValueOI中添加间距。否则,你会发现。这就是应该引发以下错误的问题:。对于rngU.Entireow,范围类的Delete方法失败。Delete@RafaelOsipov,因为添加If rngU不是其他值,所以不应该失败。如果选择.Value SI或选择.Value OI,则将始终计算为True。如果.Value=OI,则默认情况下,.Value SI为真,反之亦然。它需要是If Selection.Value SI和Selection.Value OI Then。好的捕获。我知道这件事有点不对劲,但我没有想清楚。