【问题标题】:How to break up an If-not-->then statement with multiple "nots" into a block of code?如何将带有多个“not”的 If-not-->then 语句分解为代码块?
【发布时间】:2021-07-07 11:10:20
【问题描述】:

这是我到目前为止编写的代码,它只是不停地走,我想把它做成一个块(如果可能的话)以使其更易于管理。

代码的目的是在某个单元格中不存在任何已知名称时擦除某些单元格。如果存在 Namen,我还有其他基于每个名称的单独代码,这些代码将特定数据粘贴到特定单元格中:

Sub Eraser()
        If Range("E4").Value <> "Name1" And Range("E4").Value <> "Name2" And Range("E4").Value <> "Name3" And Range("E4").Value <> "Name4" And Range("E4").Value <> "Name5" And Range("E4").Value <> "Name6" And Range("E4").Value <> "Name7" And Range("E4").Value <> "Name8" And Range("E4").Value <> "Name9" And Range("E4").Value <> "Name10" And Range("E4").Value <> "Name11" And Range("E4").Value <> "Name12" And Range("E4").Value <> "Name13" Then
        Range("W4").Value = ""
        End If
End Sub

我尝试过类似的东西

Sub Eraser()
        If Range("E4").Value <> "Name1" & _ 
        Range("E4").Value <> "Name2" & _
        Range("E4").Value <> "Name3" & _
        Range("E4").Value <> "Name4" & _
        Range("E4").Value <> "Name5" & _
        Range("E4").Value <> "Name6" & _
        Range("E4").Value <> "Name7" & _
        Range("E4").Value <> "Name8" & _ 
        Range("E4").Value <> "Name9" & _
        Range("E4").Value <> "Name10" & _
        Range("E4").Value <> "Name11" & _
        Range("E4").Value <> "Name12" & _
        Range("E4").Value <> "Name13" Then
        Range("W4").Value = ""
        End If
End Sub

Sub Eraser()
       If Range("E4").Value <> "Name1" & _
       And Range("E4").Value <> "Name2" & _
       And Range("E4").Value <> "Name3" & _
       And Range("E4").Value <> "Name4" & _
       'And et cetera'

仅供参考,代码在单行时完美运行,我只是一个完美主义者

由于许多人提供了我认为与我试图做的事情相矛盾的代码,我将添加我的其他代码,这些代码是 Eraser Sub 旨在擦除的。如果有人对如何使它们更优雅或更简洁有任何想法,我很乐意。

Sub Name1()
    If Range("E4").Value = "Name1" Then
        Range("T6").Value = "EID1#"  'Employee ID Number
        Range("U10").Value = "SN1"   'Serial Number
        Range("I19").Value = "TN1"   'Trainer Name
        Range("AA19").Value = "TED1" 'Trainer Expiration Date
        Range("AB6").Value = "CN1"   'Course Name
    End If
End Sub

Sub Name2()
    If Range("E4").Value = "Name2" Then
        Range("T6").Value = "EID2"
        Range("U10").Value = "SN2"
        Range("I19").Value = "TN2"
        Range("AA19").Value = "TED2"
        Range("AB6").Value = "CN2"
    End If
End Sub

Sub Name3()
    If Range("E4").Value = "Name3" Then
        Range("T6").Value = "EID3"
        Range("U10").Value = "SN3"
        Range("I19").Value = "TN3"
        Range("AA19").Value = "TED3"
        Range("AB6").Value = "CN3"
    End If
End Sub

Sub Eraser()
    If Range("E4").Value <> "Name 1" _
        And Range("E4").Value <> "Name2" _
        And Range("E4").Value <> "Name3" Then
        Range("T6").Value = ""
        Range("U10").Value = ""
        Range("I19").Value = ""
        Range("AA19").Value = ""
        Range("AB6").Value = ""
    End If
End Sub

同样,我为此进行了大约 16 次不同的迭代,虽然我的一些团队拥有相同的信息,但其中很多人拥有不同的信息。所以我单独编写了每个代码,并编写了一个自动调用每个 Sub 的更新检查代码。 Eraser Sub 主要用于识别个人身份信息 (PII)

为了勤奋,这里是更新检查子

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = "$E$4" Then
        Call Name1
        Call Name2
        Call Name3
        Call Eraser 
    End If
End Sub

【问题讨论】:

  • Excel 的Match() 函数怎么样,如下所述:stackoverflow.com/questions/7031416/…
  • 您的第二个示例在条件之间缺少 And 关键字。但请不要这样做,这是一个糟糕的设计。
  • Call 由于官方的帮助已被弃用(尽管由于个人喜好而经常使用)。 @todayimgonnalearn

标签: excel vba if-statement


【解决方案1】:

首先你错过了“AND”。其次,为了更好地使用“选择案例”

Sub Eraser()
    Select Case (Range("E4").Value)
        Case "Name1", "Name2", "Name3", "Name4", "Name5"
            MsgBox "FOUND" 'code goes here if TRUE
        Case Else
            MsgBox "no finding" 'code goes here if FALSE
    End Select
End Sub

【讨论】:

    【解决方案2】:

    “&”应该是AND。 “&”用于将字符串连接在一起。 AND 用于计算布尔表达式。

    Sub Eraser()
            If Range("E4").Value <> "Name1" _
            And Range("E4").Value <> "Name2" _
            And Range("E4").Value <> "Name3" _
            And Range("E4").Value <> "Name4" _
            And Range("E4").Value <> "Name5" _
            And Range("E4").Value <> "Name6" _
            And Range("E4").Value <> "Name7" _
            And Range("E4").Value <> "Name8" _
            And Range("E4").Value <> "Name9" _
            And Range("E4").Value <> "Name10" _
            And Range("E4").Value <> "Name11" _
            And Range("E4").Value <> "Name12" _
            And Range("E4").Value <> "Name13" Then
                Range("W4").Value = ""
            End If
    End Sub
    

    另外,为了节省处理时间并使代码看起来更简洁,我建议使用变量作为常用重复引用的昵称。

    Sub Eraser()
        Dim rVal As Variant
        rVal = Range("E4").Value
        
        If rVal <> "Name1" _
            And rVal <> "Name2" _
            And rVal <> "Name3" _
            And rVal <> "Name4" _
            And rVal <> "Name5" _
            And rVal <> "Name6" _
            And rVal <> "Name7" _
            And rVal <> "Name8" _
            And rVal <> "Name9" _
            And rVal <> "Name10" _
            And rVal <> "Name11" _
            And rVal <> "Name12" _
            And rVal <> "Name13" Then
                Range("W4").Value = ""
        End If
    End Sub
    

    最后,如果您要检查的名称越来越多,我建议将它们添加到数组或dictionary 并创建一个函数来遍历数组或使用dictionary.Exists 作为评估您的表达。

    【讨论】:

    • 谢谢,您的回答是迄今为止最优雅的。这正是我所需要的。另外,感谢您对 & vs AND 的解释。我不知道有什么不同。我也试过 Sub Eraser() If Range("E4").Value "Name1" & _ And Range("E4").Value "Name2" & _
    【解决方案3】:

    两个函数检查搜索词是否存在

    只是为了演示其他几种检查术语存在的简单方法。

    这两种方法都假定逗号分隔的列表作为第二个参数(例如"Name1,Name2,Name3"

    a) 通过在VBA.Filter()执行后计数元素

    按逗号对拆分列表项进行正向过滤会产生一个从零开始的数组。找到的元素的上限 (UBound()) 增加 1 会导致布尔函数返回值 True-1 用于未找到的结果加上 1 会导致 False (-1+1=0)。

    Function IsListed(ByVal term As String, List) As Boolean
       Dim elems: elems = Split(LCase(List), ",")
       'return boolean function result
       IsListed = UBound(Filter(elems, LCase(term), True)) + 1
    End Function
    

    b) 通过 Excel 函数FilterXML()

    将传递的列表字符串转换为格式良好的(类似 html 标记的)xml 内容允许在其上应用 Excel 的 FilterXML() 函数(自 2013+ 版本起可用)。

    Function IsListed(ByVal term As String, List) As Boolean
        Dim content: content = "<r><s>" & Replace(List, ",", "</s><s>") & "</s></r>"
       'return boolean function result
        IsListed = Not IsError(Application.FilterXML(content, "//s[.='" & term & "']"))
    End Function
    

    可能的示例调用

    Sub Eraser()
            Dim rVal: rVal = Sheet1.Range("E4")
            If IsListed(rVal, "Name1,Name2,Name3") Then
                Debug.Print rVal & " found"                  'code goes here if TRUE
            Else
                Debug.Print rVal & " not found!"             'code goes here if FALSE
                'do further stuff
                Sheet1.Range("W4") = vbNullString     
            End If
    

    【讨论】:

    • 我认为问题的复杂之处在于,我已经为每个检测到输入的个案编写了代码。比如Sub N1() If Range("A6").Value = "'Name 1'" Then Range("T6").Value = "'Employee ID Number'" Range("U10").Value = "'Serial Number'" Range("I19").Value = "'Trainer Name'" Range("AA19").Value = "'Trainer Expiration Date'" Range("AB6").Value = "'Course Name.'" End If End Sub
    • If 条件的 TRUE 部分插入一个子调用,将其命名为例如doReplaces rVal(注意传递的参数rVal!)并通过Select Case rVal ...Case "Name 1"....End Select结构在子过程Sub doReplaces(byval rVal as String)内执行所有情况.您甚至可以通过简单的N1N2 等从不同的Case 选择中调用您的原子化子潜艇。如果有帮助,请随时投票(向上排列):) @todayimgonnalearn
    猜你喜欢
    • 2011-10-04
    • 2021-10-20
    • 2020-08-24
    • 2011-11-15
    • 1970-01-01
    • 2016-02-19
    • 2011-03-23
    • 2018-08-25
    • 1970-01-01
    相关资源
    最近更新 更多