【问题标题】:Nested Select Case for multiple conditions多个条件的嵌套选择案例
【发布时间】:2017-09-09 08:26:40
【问题描述】:

情况:我有一个代码,它遍历工作表中的一些数据,并给出某个单元格中的内容,它将某些内容粘贴到另一列(同一行)。

例如:如果我的 A5 是“Bond”,它会将 A5 和 B5 的内容连接起来并粘贴到 J5。

Obs1:第一、二、三、四列数据有几十个子条件。

到目前为止我所做的尝试:我能够创建一个非常长的嵌套 If 链并考虑所有条件。我还能够使用 Select case 来说明第一列条件。

问题:现在我正在尝试使用嵌套的 Select Case 来解决这种情况(考虑到 If 链庞大,并且太长而无法高效)。问题是我无法正确考虑多个条件的嵌套选择案例。

问题:当有多个条件时,使用嵌套 Select Case 的最佳方法是什么?

Obs2:根据之前的研究,我在这里发现了有关嵌套 if 的帖子,尤其是当存在真值或假值时。这对我不起作用,因为每一层都有更多的条件。

代码 1:这是我到目前为止使用 Select Case 得到的结果:

Function fxr2()

Dim lRow As Long, LastRow As Long
Dim w As Workbook
Dim ws As Worksheet

Set w = ThisWorkbook

Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual

LastRow = Worksheets("Fixer").Cells(Rows.Count, "A").End(xlUp).Row

For lRow = 7 To LastRow

Dim type1 As String, result As String
type1 = w.Worksheets("Fixer").Cells(lRow, 1).Text

Select Case type1
Case Is = "Bail-in"
    result = w.Worksheets("Fixer").Cells(lRow, 1)
Case Is = "Basel"
    result = w.Worksheets("Fixer").Cells(lRow, 1) & " " & w.Worksheets("Fixer").Cells(lRow, 2) & " " & w.Worksheets("Fixer").Cells(lRow, 3) & " " & w.Worksheets("Fixer").Cells(lRow, 4) & " " & w.Worksheets("Fixer").Cells(lRow, 5)
Case Is = "Collateral"
    result = w.Worksheets("Fixer").Cells(lRow, 1) & " " & w.Worksheets("Fixer").Cells(lRow, 2) & " " & w.Worksheets("Fixer").Cells(lRow, 3)
Case Is = "Design"
    result = w.Worksheets("Fixer").Cells(lRow, 1)
Case Is = "General"
    result = w.Worksheets("Fixer").Cells(lRow, 1) & " " & w.Worksheets("Fixer").Cells(lRow, 2) & " " & w.Worksheets("Fixer").Cells(lRow, 3)
Case Is = "Investment"
    result = w.Worksheets("Fixer").Cells(lRow, 1)
Case Is = "Lower"
    result = w.Worksheets("Fixer").Cells(lRow, 1) & " " & w.Worksheets("Fixer").Cells(lRow, 2) & " " & w.Worksheets("Fixer").Cells(lRow, 3)
Case Is = "Recapitalization"
    result = w.Worksheets("Fixer").Cells(lRow, 1)
Case Is = "Refinance"
    result = w.Worksheets("Fixer").Cells(lRow, 1)
Case Is = "Upper"
    result = w.Worksheets("Fixer").Cells(lRow, 1) & " " & w.Worksheets("Fixer").Cells(lRow, 2) & " " & w.Worksheets("Fixer").Cells(lRow, 3)
Case Else
    result = w.Worksheets("Fixer").Cells(lRow, 1) & " " & 
w.Worksheets("Fixer").Cells(lRow, 2)
End Select

w.Worksheets("Fixer").Cells(lRow, 10).Value = result

Next lRow

End Function

代码 2:这是我使用嵌套 Ifs 的一小部分代码:

ElseIf w.Worksheets("Fixer").Cells(lRow, 1) = "General" Then
    w.Worksheets("Fixer").Cells(lRow, 10) = 
w.Worksheets("Fixer").Cells(lRow, 1) & " " & 
w.Worksheets("Fixer").Cells(lRow, 2) & " " & w.Worksheets("Fixer").Cells(lRow, 3)

    If w.Worksheets("Fixer").Cells(lRow, 4) = "Base" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Inte" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Tier" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "v" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Ba" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Bas" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Int" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Inte" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Inter" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Tie" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Tier-" Then
        w.Worksheets("Fixer").Cells(lRow, 11) = ""

    ElseIf w.Worksheets("Fixer").Cells(lRow, 4) = "" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Upp" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Uppe" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Upper" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "I" Or w.Worksheets("Fixer").Cells(lRow, 4) = "L" Or w.Worksheets("Fixer").Cells(lRow, 4) = "T" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "U" Then
        w.Worksheets("Fixer").Cells(lRow, 11) = ""

    ElseIf w.Worksheets("Fixer").Cells(lRow, 4) = "Design" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Inve" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Inv" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Low" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Lowe" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Proj" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Pro" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Ref" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Refi" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Stock" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Inve" Then
        w.Worksheets("Fixer").Cells(lRow, 11) = 
w.Worksheets("Fixer").Cells(lRow, 4)

    ElseIf w.Worksheets("Fixer").Cells(lRow, 4) = "LBO" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Working" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Work" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Wor" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Gre" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Gree" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Green" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Interc" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Intercom" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Intercompany" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Intermed" Then
        w.Worksheets("Fixer").Cells(lRow, 11) = 
w.Worksheets("Fixer").Cells(lRow, 4)

    ElseIf w.Worksheets("Fixer").Cells(lRow, 4) = "Low" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Lower" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "Lowe" Or 
w.Worksheets("Fixer").Cells(lRow, 4) = "No" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Pen" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Pens" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Pension" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Projec" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Project" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Refin" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Refina" Then
        w.Worksheets("Fixer").Cells(lRow, 11) = w.Worksheets("Fixer").Cells(lRow, 4)

    ElseIf w.Worksheets("Fixer").Cells(lRow, 4) = "Refinanc" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Refinance" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Stoc" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Sto" Or w.Worksheets("Fixer").Cells(lRow, 4) = "w" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Wor" Or w.Worksheets("Fixer").Cells(lRow, 4) = "W" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Tier-1" Or w.Worksheets("Fixer").Cells(lRow, 4) = "Tier-2" Then
        w.Worksheets("Fixer").Cells(lRow, 11) = w.Worksheets("Fixer").Cells(lRow, 4)

    End If

Obs3:为了更好地解释我的数据是如何组织的,这里是其中的一小部分。

【问题讨论】:

  • 您的许多案例都做同样的事情。您可以将它们组合如下:Case "Collateral", "General", "Lower"
  • 我不知道你的问题到底是什么。它不起作用还是您只是在寻找更有效的做事方式?
  • @jsheeran 的确,你是对的,我的问题是这些中的每一个都可以为后续列召唤不同的条件。例如,“General”将连接 A5、B5 和 C5,并会影响 D4 中的内容,而“Collat​​eral”将连接 A5 和 B5,不会影响其他列。
  • @SJR 我可以用 Ifs 做到这一点,而不是我试图用 Select Case 做同样的事情。但我无法满足子条件。
  • 我认为Select Case 的主要优点是更容易看。我怀疑有任何速度优势可言(尽管这里的其他人会更清楚)。为了避免If,当然不值得为自己打结!

标签: vba excel select-case


【解决方案1】:

您帖子的第 1 部分(代码 1)可能看起来像下面的较短和简化的版本(代码 cmets 内的解释):

Function fxr2()

Dim lRow As Long, LastRow As Long
Dim w As Workbook
Dim ws As Worksheet

Set w = ThisWorkbook
Set ws = w.Worksheets("Fixer") '<-- set the worksheet

Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual

Dim type1 As String, result As String '<-- There's no need to Dim them every time inside the loop

' use With statement, will simplify and shorten your code later
With ws
    LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row '<-- fully qualify Rows.Count with "Fixer" sheet

    For lRow = 7 To LastRow
        type1 = .Cells(lRow, 1).Text

        Select Case type1
            Case "Bail-in", "Investment", "Recapitalization", "Refinance", "Design"
                result = .Cells(lRow, 1)

            Case "Basel"
                result = .Cells(lRow, 1) & " " & .Cells(lRow, 2) & " " & .Cells(lRow, 3) & " " & .Cells(lRow, 4) & " " & .Cells(lRow, 5)

            Case "Collateral", "General", "Lower", "Upper"
                result = .Cells(lRow, 1) & " " & .Cells(lRow, 2) & " " & .Cells(lRow, 3)

            Case Else
                result = .Cells(lRow, 1) & " " & .Cells(lRow, 2)

        End Select

        .Cells(lRow, 10).Value = result
    Next lRow
End With

End Function

代码 2 中的所有内容都是 2 个 Case 条件,由您尝试与之比较的多个 Strings 构成:

Select Case .Cells(lRow, 4)
    Case "Base", "Inte", "Tier", "v", "Ba", "Bas", "Int", "Inte", "Inter", "Tie", "Tier-", "", "Upp", "Uppe", "Upper", "I", "L", "T"
        .Cells(lRow, 11) = ""

    Case "Design", "Inve", "Inv", "Low", "Lowe", "Proj", "Pro", "Ref", "Refi", "Refin", "Refina", "Refinanc", "Refinance", "Stock", "Inve", "LBO", "Working", "Work", "Wor", "Gre", _
             "Gree", "Green", "Interc", "Intercom", "Intercompany", "Intermed", "Refinanc", "Stoc", "No", "Pen", "Pens", "Pension", "Projec", "Project", _
             "Sto", "Stoc", "w", "Wor", "Tier-1", "Tier-2"
        .Cells(lRow, 11) = .Cells(lRow, 4)

End Select

不确定这是否正是您想要放置的位置,但这只是一个示例,说明如何使用嵌套在另一个 Select Case 中的 Select Case

编辑的“合并”代码

Function fxr2()

Dim lRow As Long, LastRow As Long
Dim w As Workbook
Dim ws As Worksheet

Set w = ThisWorkbook
Set ws = w.Worksheets("Fixer") '<-- set the worksheet

Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual

Dim type1 As String, result As String '<-- There's no need to Dim them every time inside the loop

' use With statement, will simplify and shorten your code later
With ws
    LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row '<-- fully qualify Rows.Count with "Fixer" sheet

    For lRow = 7 To LastRow
        type1 = .Cells(lRow, 1).Text

        Select Case type1
            Case "Bail-in", "Investment", "Recapitalization", "Refinance", "Design"
                .Cells(lRow, 10).Value = .Cells(lRow, 1)

            Case "Basel"
                .Cells(lRow, 10).Value = .Cells(lRow, 1) & " " & .Cells(lRow, 2) & " " & .Cells(lRow, 3) & " " & .Cells(lRow, 4) & " " & .Cells(lRow, 5)

            Case "Collateral", "General", "Lower", "Upper"
                .Cells(lRow, 10).Value = .Cells(lRow, 1) & " " & .Cells(lRow, 2) & " " & .Cells(lRow, 3)

                ' ===== Added the Nested case here (just for example) =====
                 Select Case .Cells(lRow, 4)
                    Case "Base", "Inte", "Tier", "v", "Ba", "Bas", "Int", "Inte", "Inter", "Tie", "Tier-", "", "Upp", "Uppe", "Upper", "I", "L", "T"
                        .Cells(lRow, 11) = ""

                    Case "Design", "Inve", "Inv", "Low", "Lowe", "Proj", "Pro", "Ref", "Refi", "Refin", "Refina", "Refinanc", "Refinance", "Stock", "Inve", "LBO", "Working", "Work", "Wor", "Gre", _
                             "Gree", "Green", "Interc", "Intercom", "Intercompany", "Intermed", "Refinanc", "Stoc", "No", "Pen", "Pens", "Pension", "Projec", "Project", _
                             "Sto", "Stoc", "w", "Wor", "Tier-1", "Tier-2"
                        .Cells(lRow, 11) = .Cells(lRow, 4)

                End Select
                ' ==== End of Nested Select Case ====

            Case Else
                .Cells(lRow, 10).Value = .Cells(lRow, 1) & " " & .Cells(lRow, 2)

        End Select
    Next lRow
End With

End Function

【讨论】:

  • 感谢您的回答。实际上,使用 with 和您建议的其他更改肯定会使代码更易于管理。但是如何在每个 Select Case(原始问题)中使用子条件?
  • @DGMS89 w.Worksheets("Fixer").Cells(lRow, 4) 应该在哪里?在Select Case type1 里面,比如合并?还是之后?
  • @DGMS89 看到我编辑的答案,所以现在的问题是你想把这些条件放在哪里?在第一个 Select Case 内?还是这些是不同的标准?
  • 是的。例如,我在code2中:选择我在A5中有“General”的case1,然后连接A5、B5和C5;之后,仍然在这个案例中,选择 Case1.1,其中 D5 是“投资”(然后做某事),或选择 Case1.2,其中 D5 是“Tier”(然后做其他事情),对于每个初始案例(让我们说初始情况是第 1 列的条件),有“子情况”。抱歉,如果不能更好地解释它。
  • 感谢您的帮助,这正是我所需要的。
【解决方案2】:

可以像 IF 一样嵌套大小写:

Select Case a
    Case 10
        Select Case b
            Case 1
                'a is 10, b is 1
            Case 2
                'a is 10, b is 2
            Case 3
                'a is 10, b is 3
        End Select
    Case 20
        Select Case b
            Case 1
                'a is 20, b is 1
            Case 2
                'a is 20, b is 2
            Case 3
                'a is 20, b is 3
        End Select
End Select

【讨论】:

    【解决方案3】:

    这可能不是您所期望的答案,但如果您将其应用于您自己的案例,则该逻辑完美无缺。

    让我们假设,VBA 由 Microsoft 定期更新。至少和 C# 一样频繁。然后我们就会有一些东西,叫做[FLAGS],这个问题会很容易。但是,我们没有它,因此我们应该单独构建这样的东西。

    想象一下,您有 7 种产品(AAA、BBB、CCC、DDD、EEE、FFF、GGG)并且您想知道您选择了哪一种。我认为这是您问题的核心。这很简单,如果你使用二进制数学 - 那么第一个乘积的值为 1,第二个为 2,第三个为 4,第四个为 8,依此类推。

    • 27表示你选择了1+2+8+16。 (AAA、BBB、DDD、EEE)
    • 28表示你选择了4+8+16。 (CCC、DDD、EEE)

    因此,如果我们假设您有号码并且想要产品,那么这样的事情可能会奏效。数字是 lngNumber,LngToBinary 为您提供数字的二进制值。在Sub TestMe 中,您实际上可以对它们进行一些操作,而不是打印产品。

    Option Explicit
    Option Private Module
    
    Public Sub TestMe()
    
        Dim arrProducts     As Variant
        Dim lngCounter      As Long
        Dim lngValue        As Long
        Dim strBinary       As String
        Dim lngNumber       As Long
    
        arrProducts = Array("AAA", "BBB", "CCC", "DDD", "EEE", "FFF", "GGG")
                               '1,     2,     4,     8,    16,    32,    64
        lngNumber = 28 '1+2+8+16
        strBinary = StrReverse(LngToBinary(lngNumber))
    
        For lngCounter = 1 To Len(strBinary)
            lngValue = Mid(strBinary, lngCounter, 1)
    
            If lngValue Then
                Debug.Print arrProducts(lngCounter - 1)
            End If
    
        Next lngCounter
    
    End Sub
    
    Function LngToBinary(ByVal n As Long) As String
    
        Dim k As Long
    
        LngToBinary = vbNullString
    
        If n < -2 ^ 15 Then
            LngToBinary = "0"
            n = n + 2 ^ 16
            k = 2 ^ 14
    
        ElseIf n < 0 Then
    
            LngToBinary = "1"
            n = n + 2 ^ 15
            k = 2 ^ 14
    
        Else
    
            k = 2 ^ 15
    
        End If
    
        Do While k >= 1
            LngToBinary = LngToBinary & Fix(n / k)
            n = n - k * Fix(n / k)
            k = k / 2
        Loop
    
    End Function
    

    在此处了解有关 [FLAGS] 的更多信息:https://msdn.microsoft.com/en-us/library/system.flagsattribute(v=vs.110).aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 2015-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-13
      相关资源
      最近更新 更多