Excel 您能帮助优化我的UDF以提高性能吗?

Excel 您能帮助优化我的UDF以提高性能吗?,excel,vba,Excel,Vba,我已经创建了一个UDF来执行自定义过程。我添加了第三个参数(c作为范围),这样当我的数据发生变化时,UDF会自动重新计算(替代添加波动性,因为这会对性能造成更大的负担)。尽管这个UDF可以工作并且比添加volatile参数更高效,但它仍然会使我的电子表格性能降低一点。我处理的行总数约为200行,但行数可能会发生变化,因此我无法硬编码这部分。有没有人对优化代码有什么建议,这样我的Excel性能就不会受到太大的影响?我会非常感激的 Public Function XtrainCheck(a As R

我已经创建了一个UDF来执行自定义过程。我添加了第三个参数(c作为范围),这样当我的数据发生变化时,UDF会自动重新计算(替代添加波动性,因为这会对性能造成更大的负担)。尽管这个UDF可以工作并且比添加volatile参数更高效,但它仍然会使我的电子表格性能降低一点。我处理的行总数约为200行,但行数可能会发生变化,因此我无法硬编码这部分。有没有人对优化代码有什么建议,这样我的Excel性能就不会受到太大的影响?我会非常感激的

Public Function XtrainCheck(a As Range, b As Range, c As Range)
Dim counter As Long
x = a.Row
y = b.Row

For i = x To y
    If Application.Evaluate("IFERROR(IF(AND(K" & i & "<>0,A" & i & "<>$K$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($K$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(L" & i & "<>0,A" & i & "<>$L$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($L$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(M" & i & "<>0,A" & i & "<>$L$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($L$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(N" & i & "<>0,A" & i & "<>$N$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($N$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(O" & i & "<>0,A" & i & "<>$O$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($O$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(P" & i & "<>0,A" & i & "<>$P$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($P$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(Q" & i & "<>0,A" & i & "<>$Q$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($Q$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(R" & i & "<>0,A" & i & "<>$R$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($R$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(S" & i & "<>0,A" & i & "<>$S$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($S$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(T" & i & "<>0,A" & i & "<>$T$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($T$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(U" & i & "<>0,A" & i & "<>$U$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($U$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(V" & i & "<>0,A" & i & "<>$V$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($V$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
    If Application.Evaluate("IFERROR(IF(AND(W" & i & "<>0,A" & i & "<>$W$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i & ",'Default Shifts'!$B:$B,0),MATCH($W$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        counter = counter + 1
    End If
Next i
If counter <> 0 Then
    XtrainCheck = "CHECK CROSS-TRAINED CAPACITY"
End If
公共函数XtrainCheck(a作为范围,b作为范围,c作为范围)
昏暗的柜台一样长
x=a.行
y=b.行
对于i=x到y
如果应用程序。评估(“IFEROR(如果(和(K“&i&“0,A”&i&“$K$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($K$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(如果(和(L“&i&“0,A”&i&“$L$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($L$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFERROR(如果(和(M“&i&“0,A”&i&“$L$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($L$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(如果(和(N“&i&“0,A”&i&“$N$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($N$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序.Evaluate(“IFEROR(如果(和(O)&i&“0,A”&i&“$O$11,索引('Default Shifts'!$B:$AB,匹配(B”&i&“,'Default Shifts'!$B:$B,0),匹配($O$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(如果(和(P“&i&“0,A”&i&“$P$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($P$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(如果(和(Q“&i&“0,A”&i&“$Q$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($Q$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(和(R“&i&“0,A”&i&“$R$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($R$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
If Application.Evaluate(“IFERROR(和(S“&i&“0,A”&i&“$S$11,索引('Default Shifts'!$B:$AB,匹配(B”&i&“,'Default Shifts'!$B:$B,0),匹配($S$11,'Default Shifts'!$2:$2,0)-1)”)=1
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(如果(和(T“&i&“0,A”&i&“$T$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($T$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFEROR(如果(和(U“&i&“0,A”&i&“$U$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($U$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFERROR(如果(和(V“&i&“0,A”&i&“$V$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($V$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
如果应用程序。评估(“IFERROR(如果(和(W“&i&“0,A”&i&“$W$11,索引('Default Shifts'!$B:$AB,匹配(B“&i&“,'Default Shifts'!$B:$B,0),匹配($W$11,'Default Shifts'!$2:$2,0)-1)”)=1,然后
计数器=计数器+1
如果结束
接下来我
如果计数器为0,则
XtrainCheck=“检查交叉培训能力”
如果结束
结束功能

性能问题
  • 如果
    计数器
    不能为负数,为消除混淆,应使用
    如果计数器>0,则使用
  • 由于任何大于0的值都是“可接受的”(例如
    1
    ),一旦找到“匹配项”,就可以退出该函数。不再需要检查或计数。根本不需要
    计数器
代码

没有测试

Option Explicit

Public Function XtrainCheck(a As Range, b As Range, c As Range) As String
    
    Dim Cols As Variant: Cols = Array("K", "L", "M", "N", "O", "P", _
                                      "Q", "R", "S", "T", "U", "V", "W")
    
    Dim x As Long: x = a.Row
    Dim y As Long: y = b.Row
    Dim i As Long, j As Long
    
    For i = x To y
        For j = 0 To UBound(Cols)
            GoSub checkCols
        Next j
    Next i

Exit Function

checkCols:
    If Application.Evaluate("IFERROR(IF(AND(" & Cols(j) _
      & i & "<>0,A" & i & "<>$" & Cols(j) _
      & "$11,INDEX('Default Shifts'!$B:$AB,MATCH(B" & i _
      & ",'Default Shifts'!$B:$B,0),MATCH($" & Cols(j) _
      & "$11,'Default Shifts'!$2:$2,0)-1)<>""X""),1,0),"""")") = 1 Then
        XtrainCheck = "CHECK CROSS-TRAINED CAPACITY"
        Exit Function
    End If
    Return

End Function
选项显式
公共函数XtrainCheck(a作为范围,b作为范围,c作为范围)作为字符串
Dim Cols作为变量:Cols=数组(“K”、“L”、“M”、“N”、“O”、“P”)_
“Q”、“R”、“S”、“T”、“U”、“V”、“W”)
尺寸x的长度:x=a.行
尺寸y与长度相同:y=b.行
我和我一样长,我和我一样长
对于i=x到y
对于j=0到UBound(Cols)
GoSub checkCols
下一个j
接下来我
退出功能
支票:
如果应用程序。评估(“IFERROR”(如果)和(“&Cols(j))_
&i&“0,A”&i&“$”和Cols(j)_
&$11,索引('Default Shift')!$B:$AB,匹配(B)&i_
&“,‘默认移位’!$B:$B,0),匹配($”&Cols(j)_
&“$11,'Default Shifts'!$2:$2,0)-1)”“X”“、1,0)、“)”=1
XtrainCheck=“检查交叉培训能力”
退出功能
如果结束
返回
端函数

我认为最好不要使用
Evaluate
,而是将数据写入数组以更高效地执行计算,因为此操作应该在一瞬间运行。尝试问另一个问题,说明代码的作用并提供一些示例数据。

应用程序。Evaluate
对传递给它的任何公式使用ActiveSheet上下文,因此UDF的结果会有所不同