加速用户定义的功能

时间:2018-03-31 03:07:37

标签: vba excel-vba user-defined-functions excel

我有用户定义的功能,它与其他2个用户定义的功能相关联,当我更新单元格时,它可能需要几分钟(5-10),因为文件最多有400k单元格,并且正在运行另外2个其他单元格自定义函数,用于创建我们在工作中使用的日期格式。它似乎在循环它们并需要很长时间。

以下是自定义功能:

Function FL_YR_PDxWK(MY_DATE)
    FL_YR_PDxWK = FL_YEAR(MY_DATE) & "_" & Right("00" & FL_PERIOD(MY_DATE), 
2) & "x" & FL_WEEK(MY_DATE)
End Function

哪看这些2:

Function FL_PERIOD(MY_DATE)

If DatePart("yyyy", MY_DATE + (7 - Weekday(MY_DATE))) = DatePart("yyyy", 
MY_DATE) Then
        If Application.WorksheetFunction.Ceiling((DatePart("ww", MY_DATE) / 
4), 1) = 14 Then
            FL_PERIOD = 
Application.WorksheetFunction.Ceiling((DatePart("ww", MY_DATE) / 4), 1) - 1
       Else
            FL_PERIOD = 
Application.WorksheetFunction.Ceiling((DatePart("ww", MY_DATE) / 4), 1)
End If
Else
    FL_PERIOD = 1
End If
End Function

Function FL_WEEK(MY_DATE)

If DatePart("yyyy", MY_DATE + (7 - Weekday(MY_DATE))) = DatePart("yyyy", 
MY_DATE) Then
        If DatePart("ww", MY_DATE) Mod 4 = 0 Then
            FL_WEEK = 4
        Else
            If DatePart("ww", MY_DATE) = 53 Then
                FL_WEEK = 5
            Else
                FL_WEEK = DatePart("ww", MY_DATE) Mod 4
            End If
        End If
    Else
        FL_WEEK = 1
    End If

End Function

1 个答案:

答案 0 :(得分:0)

您使用相同的参数在FL_PERIOD中调用.Ceiling(...两次,并进行两次相同的计算。替换

If Application.WorksheetFunction.Ceiling((DatePart("ww", MY_DATE) / 4), 1) = 14 Then

Dim iWeek as Long
Dim iRetVal as Long
iWeek = If Application.WorksheetFunction.Ceiling((DatePart("ww", MY_DATE) / 4), 1)
If iWeek = 14 Then
      iRetVal = iWeek - 1
      ...
FL_PERIOD = iRetVal

您可以在FL_WEEK上应用相同的概念,在其中两次调用If DatePart("ww", MY_DATE)

加速代码的另一个选项是使用正确和特定的类型。当前版本执行许多类型转换,因为Function FL_YR_PDxWK(MY_DATE)生成一个字符串,而其他函数生成整数。实际发生的事情是VBA使用Variants并尝试将它们转换为所需的形式。你应该做的是正确指定类型:

Function FL_PERIOD(MY_DATE as Date) as String     ' will return string
...

作为奖励,您可以在函数中进行格式化以返回所需的2位数格式,如下所示:

FL_PERIOD = Format (iRetVal, "00")
End Function

因此您可以省略Right中的FL_YR_PDxWK函数调用。

考虑到大量的计算,我会建议另一个通过减少系统调用次数来节省额外秒数的技巧:因为你可以确定iRetVal在1到53之间,你可以使用它代替{{1} }

Format