有没有一种方法可以优化嵌套的if子句?

时间:2018-07-06 07:04:23

标签: vba ms-access

一段时间以来,我试图在打开某些报告的打印预览时解决Access应用程序中速度降低的问题。我注意到缓慢的报告有一个共同点-长的嵌套if子句。我试图在Internet上搜索此问题的答案,但是某些解决方案不适用于Access VBA,或者对于我的应用程序来说,则无法实现。

我想知道是否有一些常用的方法来避免if子句的怪物?

编辑:一段代码-它主要根据某些条件处理报表的结构。

If (strCcDocNumber <> vbNullString) Then
    Dim strUpperPart As String, strLowerPart As String

    IDModule.placeIDStringsToPrivateVariables strCcDocNumber, ", "
    strUpperPart = IDModule.returnUpper()
    strLowerPart = IDModule.returnLower()

    txtIDs = strUpperPart & vbCrLf & strLowerPart
Else
    txtIDs = " " & vbCrLf & " "
End If

If (strOrderNumber = IO_OrderNumber.OrderNumberCode & "12345") Then
    txtIDs = txtIDs
    txtIDSpec1 = ModuleIDSpec1.getIDSpec1
    txtIDSpec2 = ModuleIDSpec2.getIDSpec2
    txtIDSpec1.Height = 330
    txtIDSpec2.Height = 330
    txtUpperLower = "- Ex" & vbCrLf & "- Ex2" & vbCrLf & vbCrLf & "- Ex3"
    On Error Resume Next
    For Each c In Me.Controls
        If (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1Table") Then c.Height = 0
        If (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1Table") Then c.Visible = False
        If (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1TableExtra") Then c.Height = 0
        If (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1TableExtra") Then c.Visible = False
        If (c.Tag = "IDSpec2Texts" Or c.Tag = "IDSpec1Texts") Then c.Visible = True
        If (c.Tag = "IDSpec2Texts" Or c.Tag = "IDSpec1Texts") Then c.Height = 330
        If (c.Tag = "IDSpec2Texts" Or c.Tag = "IDSpec1TextsExtra" And ModuleTarget.TargetGroup <> "23C") Then c.Visible = True
        If (c.Tag = "IDSpec2Texts" Or c.Tag = "IDSpec1TextsExtra" And ModuleTarget.TargetGroup <> "23C") Then c.Height = 330
        '+ many more tags
    Next
    On Error GoTo 0
    txtIDSpec1.Visible = True
    txtIDSpec2.Visible = True
    If (txtIDSpec1 = vbNullString And txtIDSpec2 = vbNullString) Then
        txtIDSpec1.Height = 0
        txtIDSpec2.Height = 0
        txtIDSpec1.Visible = False
        txtIDSpec2.Visible = False
    End If
Else
    '+a lot more similar conditions

编辑:我记得哪些if语句是最麻烦的。我认为您无法将这些条件更改为选择情况或ElseIf语句,因为需要检查所有条件...

它是这样的:

If (condition) Then
Do this
   If (differentCondition) Then
       Do this also
        If (completelyDifferentCondition) Then
            Do this as well
        Else
            Do this instead
        End If
   End If
Else
   If (yetAnotherCondition) Then
        Do this
   Else
        Do this instead
   End If
End If

2 个答案:

答案 0 :(得分:2)

  

我想知道是否有一些常用的方法用于   为了避免if子句怪物?

第一步是确定要实现的目标,而不是要实现的目标。在这种情况下,您想要设置高度和可见性。从这里,您可以确定设置此条件所需的条件。

第一次执行此操作时,您将有一些怪物条款-可以,因为您尚未阐明自己的想法。除非另有证明,否则从一个状态的假设进行工作。这是一个示例:

c.visible = True
If ((c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1Table") OR (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1TableExtra")) then c.visible = True

当然,第二行现在可以简化一点。

If (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1Table" Or c.Tag = "IDSpec1TableExtra") then c.visible = True

我也设置标记布尔值-例如:

IsSpecTable = (c.Tag = "IDSpec2Table" Or c.Tag = "IDSpec1Table")
IsMySpecialFriend = (c.Tag = "IDSpec1TextsExtra" And ModuleTarget.TargetGroup <> "23C")
[...]
c.Visible = IsSpecTable Or IsMySpecialFriend

这些是我用来简化复杂业务逻辑的两种技术。我也在看标志的使用,但这意味着将文本Tag转换为枚举值(我在VB.Net中这样做)。不过,这项技术可以根据需要使用AndOr运算符将表达式简化为简单的掩码。

答案 1 :(得分:1)

当您基于同一值有多个Select Case Statements时,请考虑使用If Statement

MSDN - Select Case Statement

  

根据表达式的值执行几组语句之一。

For Each c In Me.Controls
    Select Case c.Tag
    Case "IDSpec2Table", "IDSpec1Table", "IDSpec1TableExtra"
         c.Height = 0
         c.Visible = False
    Case "IDSpec2Texts", "IDSpec1Texts"
        c.Visible = True
        c.Height = 330
    Case "IDSpec1TextsExtra"
        If ModuleTarget.TargetGroup <> "23C" Then 
           c.Visible = True
           c.Height = 330
        End If
    End Select
Next

性能:选择区分大小写,假设条件和假设条件

我在评论中提到,使用Select Case的可读性远胜于性能。如果我们比较Select CaseIf ElseIf语句(读Which way is faster? If elseif or select case),这是正确的。

Select CaseIf ElseIf可能比多个If语句要快得多。这是因为VBA会评估If语句中的每个条件,并且会在Select Case语句中满足一个条件时停止评估。注意:并非所有语言都可以。

考虑这个简单的测试。

Sub Test()
    Debug.Print "Test:If Statement Test:"
    If ret(1) = 1 Or ret(2) = 2 Or ret(3) = 3 Or ret(4) = 4 Or ret(5) = 5 Then

    End If

    Debug.Print vbNewLine; "Test:If ElseIf Statement"

    If ret(1) = 1 Or ret(2) = 2 Then

    ElseIf ret(3) = 3 Then

    ElseIf ret(4) = 4 Then

    ElseIf ret(5) = 5 Then

    End If

    Debug.Print vbNewLine; "Test:Select Case Statement"

    Select Case 1
        Case ret(1), ret(2)

        Case ret(3)

        Case ret(4)

        Case ret(5)

    End Select
End Sub

Function ret(n As Long) As Long
    ret = n
    Debug.Print n,
End Function

enter image description here

请注意,If语句必须执行5个操作,即使它们都是正确的。 ElseIf必须执行2个操作,因为前2个操作被分组在单个If子句中。 Select Case仅执行了一个操作,即使两个操作被分组在一起。这是因为Select Case会在单个条件为true时始终停止评估条件。