Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel VBA:创建;跌破;在嵌套的if-else语句中,是否也允许正常行为?_Vba_Excel - Fatal编程技术网

Excel VBA:创建;跌破;在嵌套的if-else语句中,是否也允许正常行为?

Excel VBA:创建;跌破;在嵌套的if-else语句中,是否也允许正常行为?,vba,excel,Vba,Excel,在我的Excel VBA宏中,我想尝试在一些嵌套的if-else语句中创建“fall-through”。但我也希望能像if-else语句一样正常工作 我下面的解决方案似乎有效。这个方法有什么问题吗 我知道使用Goto是不受欢迎的,但这是我能想到的解决问题的唯一方法 If fallThrough = True Then GoTo Cr1 If fallThrough = False and criteria = crit1 Then Cr1: 'MsgBox "Criteria

在我的Excel VBA宏中,我想尝试在一些嵌套的if-else语句中创建“fall-through”。但我也希望能像if-else语句一样正常工作

我下面的解决方案似乎有效。这个方法有什么问题吗

我知道使用
Goto
是不受欢迎的,但这是我能想到的解决问题的唯一方法

    If fallThrough = True Then GoTo Cr1

If fallThrough = False and criteria = crit1 Then
Cr1:
    'MsgBox "Criteria 1"        

ElseIf fallThrough = True Then GoTo Cr2

ElseIf fallThrough = False And criteria = crit2 Then
Cr2:
    'MsgBox "Criteria 2"    
    If fallThrough = True Then GoTo Cr3

ElseIf fallThrough = False And criteria = crit3 Then
Cr3:
    'MsgBox "Criteria 3"
    If fallThrough = True Then GoTo Cr4

ElseIf fallThrough = False And criteria = crit4 Then
Cr4:
    'MsgBox "Criteria 4"

End If

把你想做的事情分开,在一个正常的if中调用它们

Sub main(fallThrough As Boolean)
If fallThrough Then
    critsub1
    critsub2
    critsub3
    critsub4
Else
    If criteria = crit1 Then
        critsub1
    ElseIf criteria = crit2 Then
        critsub2
    ElseIf criteria = crit3 Then
        critsub3
    ElseIf criteria = crit4 Then
        critsub4
    End If
End If
End Sub

Sub critsub1()
MsgBox "Criteria 1"
End Sub

Sub critsub2()
MsgBox "Criteria 2"
End Sub

Sub critsub3()
MsgBox "Criteria 3"
End Sub

Sub critsub()
MsgBox "Criteria 4"
End Sub
是的,您可以在if中重复调用,但这更易于阅读和维护

另一种方法是创建单个Ifs:

If (Not fallThrough And criteria = crit1) Or fallThrough Then critsub1
If (Not fallThrough And criteria = crit2) Or fallThrough Then critsub2
If (Not fallThrough And criteria = crit3) Or fallThrough Then critsub3
If (Not fallThrough And criteria = crit4) Or fallThrough Then critsub4

这样就不会重复了

除非绝对必要,否则我强烈建议避免
GoTo
,如果你发现自己处于需要
GoTo
的情况,那么就找一个比你更有经验的人,他们会告诉你为什么没有

GoTo
有一些问题。首先,它允许我们创建更懒惰、更低效的流程来解决任务。请记住,几乎任何任务都可以通过正确的逻辑组合来处理,这只是训练我们编写逻辑的能力的问题编程是99%的逻辑,1%的代码。这可能是一种简化编程的思维方式,但大多数早期的编码问题可以用无数低效的方法解决,并且仍然有效,但我们的任务是用正确的方法解决问题

其次,
GoTo
使您很难看到您的代码真正在做什么

那么,我们如何解决这个问题,而不必
GoTo
?我们使用抽象

Public Funtion CriteriaMatches(ByVal ControlCriteria as String, ByVal TestCriteria as String) as Boolean
    CriteriaMatches = (ControlCriteria  = TestCriteria )
End Function
然后,我们实现我们的功能以减少第一层冗余:

If fallThrough = True Then GoTo Cr1

If fallThrough = False and CriteriaMatches(criteria, crit1) Then
Cr1:
    'MsgBox "Criteria 1"        

ElseIf fallThrough = True Then GoTo Cr2

ElseIf fallThrough = False And CriteriaMatches(criteria, crit2) Then
Cr2:
    'MsgBox "Criteria 2"    
    If fallThrough = True Then GoTo Cr3

ElseIf fallThrough = False And CriteriaMatches(criteria, crit3) Then
Cr3:
    'MsgBox "Criteria 3"
    If fallThrough = True Then GoTo Cr4

ElseIf fallThrough = False And CriteriaMatches(criteria, crit4) Then
Cr4:
    'MsgBox "Criteria 4"

End If
除了在函数调用中包装比较之外,这没有什么作用,但这里的主要好处是,如果
ControlCriteria=TestCriteria
变成
controlcriteriatestcriteria
,那么我们可以在一个地方进行此更改

接下来,如果我们的
出错,我们需要某种方法允许函数返回
False
。我们希望返回
False
值的原因是,如果
FallThrough
为true,我们希望跳过该操作。这很简单,可以做到:

Public Funtion CriteriaMatches(ByVal ControlCriteria as String, ByVal TestCriteria as String, Optional byVal ReturnFalse as Boolean = False) as Boolean
    If ReturnFalse Then CriteriaMatches = (ControlCriteria  = TestCriteria )
End Function
由于
Boolean
函数的隐式值返回为
False
,我们不需要添加
If/Else

现在我们的代码变成:

If CriteriaMatches(criteria, crit1, PassThrough) Then
    'MsgBox "Criteria 1"        
ElseIf CriteriaMatches(criteria, crit1, PassThrough) Then
    'MsgBox "Criteria 2"    
ElseIf CriteriaMatches(criteria, crit2, PassThrough) Then
    'MsgBox "Criteria 3"
ElseIf CriteriaMatches(criteria, crit3, PassThrough) Then
    'MsgBox "Criteria 4"
End If
代码更加整洁、易于阅读,并且仍然以相同的方式执行(除了重复标签放置时可能发生的
msgbox
命令)

我确信这段代码可以进一步简化(比如传入一个要比较的参数列表,并返回匹配参数的位置),但现在这样就可以了

这里的关键是学习新的代码模式,这些模式可以帮助您解决以前无法解决的问题。VBA有模式和反模式,这是有充分理由的,尽可能避免它们,这一点很重要。

设置标志 设置标志是一种非常简单且易于维护的方法,可以创建一个故障:

Dim Break As Boolean

If Not Break And Condition1 Then
    'Do Something
End If

If Not Break And Condition2 Then
    'Do Something
End If

If Not Break And Condition3 Then
    'Do Something
    Break = True 'Stop doing anything else
End If


If Not Break And Condition4 Then
    'Do Something
    Break = True 'Stop doing anything else
End If
For循环和Select case 虽然有点滑稽,但我认为这种模式最好模仿其他语言的Select语句

For i = 1 To 5
    Select Case i
    Case 1
        'Do Something
    Case 2
        'Do Something
    Case 3
        'Do Something
        Exit For ' Break Code
    Case 4
        Exit For ' Break Code
    Case Else

    End Select
Next i

这看起来很难维护,甚至很难遵循。你想用它解决什么具体问题吗?@TimWilliams只是想减少代码,提高效率,所以我没有重复我自己。碰巧我需要一个子程序来处理这些if-else,另一个子程序将它们视为正常,所以我id这一点。感谢您的详细回复。非常有用。当
PassThrough
为真时,这不会产生所有四个结果。一旦IF发现第一个为真,它将不会测试其他结果。当
PassThrough
时,它只会执行第一个,而不会执行其他三个。您需要将
ElseIF
更改为个人
如果
那么它检查所有四个如果我正确阅读了他的代码,
故障
会导致代码完全故障,并跳过所有条件。这里使用If/ElseIf是故意的。我注意到我故意没有让它重复命令(
msgbox“Message One”
等),但这可以很容易地添加,或者正如您所注意到的,这可以转换为一个
If's
块,但是在这样做之前,我会非常小心创建这样一个构造的任何需要,因为实际上整个块应该包装在
If PassThrough中,然后
,因为PassThrough是不变的,并且只有要检查的条件larify,如果他确实想要一块
if
的vs,
ElseIf
,我只建议在第一次检查时将它包装起来。不过,我确实更新了函数,使
PassThrough
成为可选的,以允许这种风格。