Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.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
VBA:24深嵌套IF语句的性能 原始问题_Vba_Excel_If Statement - Fatal编程技术网

VBA:24深嵌套IF语句的性能 原始问题

VBA:24深嵌套IF语句的性能 原始问题,vba,excel,if-statement,Vba,Excel,If Statement,我有一个24深嵌套IF语句的子语句 l=2 While l <= lmax 'lmax = 15000 If condition1 Then If condition2a or condition2b Then ... If condition24 then ReDim Preserve propositions(UBound(propositions) + 1)

我有一个24深嵌套IF语句的子语句

l=2
While l <= lmax                'lmax = 15000
   If condition1 Then
      If condition2a or condition2b Then
         ...
            If condition24 then
               ReDim Preserve propositions(UBound(propositions) + 1)
               propositions(UBound(propositions)) = l

您可以使用带有逗号分隔的条件列表的
Select Case
,而不是or,如下所示:

'If condition2a Or condition2b Then

Select Case True
Case condition2a, condition2b 'here comma means lazy 'OR' (like as OrElse in vb.net)
  's = s + 10
Case Else
  's = s + 20
End Select
此外,如果我们能看到您的代码,可能还有很多地方需要改进宏性能。立即,在一个循环中,对阵列进行重拨以向其添加一个或多个项目可能会非常耗时:

ReDim Preserve propositions(UBound(propositions) + 1)

你可以考虑在每次达到它的长度时增加它的10或100个项目(为下一个可能的使用保留一些空间),但是把实际的上界指数保持在变量……/P>


更新:

当您添加代码的某些部分时,我建议您为每个if使用一些帮助函数,如下所示:

'If condition2a Or condition2b Then

Select Case True
Case condition2a, condition2b 'here comma means lazy 'OR' (like as OrElse in vb.net)
  's = s + 10
Case Else
  's = s + 20
End Select

替换
x不是对引起混淆的评论的回答支持。


如果您共享您的代码,那么其他循环的
if
可能会被
Select Case
Match
等替换。我认为您的答案如下:这里还有一些有趣的解决方法:在VBA
中,if
语句不会短路。您可能希望使用
选择Case
构造,或者,如果所有这些条件都是关于从数据库中选择记录,则使用
AutoFilter()
或类似方法过滤数据库@Nathan_Sav,尽管
((1=1)+(2=3))
将等于
((1=1)或(2=3))
因为True=-1和False=0,但这不会阻止第二部分的条件检查(没有性能增益)关于阵列redim点,我实际上运行了一个测试(称为5000次),其中我创建了一个10000阵列,而不是每行对阵列进行redim或每1000行进行redim
(如果Int(l/1000)*1000=l然后重拨保留表AU3(l*10)
)。每次重拨肯定是性能最差的选项。但是,由于我使用数组的大小来过滤结果,所以预先标注尺寸对我来说不是一个选项。关于Select Case,24个深嵌套的
If
语句代码已经很难读取。将一些
案例嵌套在
If
中选择
。。。我甚至不确定我是否愿意这样做……将实际上界索引保留在变量中。一开始,我的代码是这样做的,但是由于我经常使用这个数组(在不同的子、模块和用户表单中),我去掉了我的array_size变量并切换到Ubound…:-(关于24个嵌套的if,如果可以合并或修改它们以获得更好的性能,我无法不看到它们。您只需要将一些
的if转换为选定的大小写(不是全部)这是为了获得更好的结果而应该付出的代价。关于array_size变量,也是一样的:为了获得更好的性能,您必须编写一些更复杂的代码(尽管我认为如果实现正确,使用这样的变量不会太难)。但最终的改进效果取决于场景中需要您衡量的许多方面。好的,所以我只是修改代码以完全避免阵列redim(通过声明一个固定大小(500)阵列并在超过500时退出),但性能几乎没有任何提高,因为大多数情况下(>90%),redim只调用一次(这就是我试图用嵌套的if语句实现的)!但是感谢您的输入。(实际上,如果Ubound>1,我甚至可能退出conditionaly…)
If (.Cells(l, 6).Formula="" Or .Cells(l, 6).Value-marge<=param3 Or param3=0) Then ...
If test(.Cells(l, 6).Value, marge, param3) Then ...
'or without '.Value': If test(.Cells(l, 6), marge, param3) Then ...
Function testLesser(v As Variant, marge As Double, param As Double) As Boolean

    'testLesser = (v = "" Or v - marge <= param3 Or param3 = 0)

    If v = "" Then
    ElseIf v - marge <= param Then
    ElseIf param = 0 Then
    Else
                testLesser = False: Exit Function
    End If
    testLesser = True

    '** Another option (using Select Case):
    'Select Case True
    'Case v = "", v - marge <= param, param = 0
    '    testLesser = True
    'Case Else
    '    testLesser = False
    'End Select

End Function
If (.Cells(l, 7).Formula="" Or .Cells(l, 7).Value+marge>=param3 Or param3=0) Then ...
Function testGreater(v As Variant, marge As Double, param As Double) As Boolean

    'testGreater = (v = "" Or v + marge >= param Or param = 0)

    If v = "" Then 'testLesser = True
    ElseIf v + marge >= param Then 'testLesser = True
    ElseIf param = 0 Then 'testLesser = True
    Else
                testLesser = False: Exit Function
    End If
    testLesser = True

    '** Another option (using Select Case):
    'Select Case True
    'Case v = "", v + marge >= param, param = 0
    '    testLesser = True
    'Case Else
    '    testLesser = False
    'End Select

End Function
'If (.Cells(l, 6).Formula = "" Or .Cells(l, 6).Value - marge <= param3 Or param3 = 0) Then
'If (.Cells(l, 7).Formula = "" Or .Cells(l, 7).Value + marge >= param3 Or param3 = 0) Then
'If (.Cells(l, 8).Formula = "" Or .Cells(l, 8).Value - marge <= param4 Or param4 = 0) Then
'If (.Cells(l, 9).Formula = "" Or .Cells(l, 9).Value + marge >= param4 Or param4 = 0) Then
'...

If testLesser(.Cells(l, 6), marge, param3) Then
If testGreater(.Cells(l, 7), marge, param3) Then
If testLesser(.Cells(l, 8), marge, param4) Then
If testGreater(.Cells(l, 9), marge, param4) Then
'...
Dim mySheet As Worksheet
Set mySheet = Sheets("Sheet1")
With mySheet 'Sheets("Sheet1")
myArray = Sheets("Sheet1").Range("A1:AG15000").Value
myArray(row, col) = myArray(row, col) + 1 
'row = 1 to UBound(myArray, 1) 'First array dimension is for rows
'col = 1 to UBound(myArray, 2) 'Second array dimension is for columns
Sheets("Sheet1").Range("A1:AG15000") = myArray