加速用户定义的函数

Posted

技术标签:

【中文标题】加速用户定义的函数【英文标题】:Speeding Up a User Defined Function 【发布时间】:2018-03-31 03:07:36 【问题描述】:

我有与其他 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

【问题讨论】:

能否请您稍微解释一下每个功能的目的是什么? 你回答了你自己的问题:it is is running through 2 other custom functions... 通过压缩为一个来提高效率,并确保任何给定的值只需要计算一次(如果需要重复,请使用变量或数组而不是函数。) ...而且,正如@JosephSerido 所说,您的函数需要 cmets 和其他解释,并且一些示例数据也会有所帮助关于您正在尝试做的事情的一些背景知识。 (否则就像说,“我的房子倒了,这锤子怎么了?”)见minimal reproducible example。 另外,我强烈建议在您的模块中指定Option Explicit,指定您的函数是public 还是private,始终说明您打算使用ByRef 还是ByVal,以及明确指定函数返回的类型public MyFunc(ByRef myString) As Boolean 使用函数的结果值而不是函数本身。并使用变体数组来获取结果。 【参考方案1】:

您在 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

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

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

If iRetval < 10 Then
   FL_PERIOD = "0" & CStr(iRetVal)
Else
   FL_PERIOD = CStr(iRetVal)
Endif

【讨论】:

以上是关于加速用户定义的函数的主要内容,如果未能解决你的问题,请参考以下文章

自定义 UIFieldBehavior 中的意外加速

使用用户定义的函数和左加入 oracle 10g 的分页速度很慢

杜鹃加速器的软件界面及功能介绍

〖IOS〗手机迅雷上架 IOS 商店

CDN加速,vue中使用CDN加速

03-Docker-配置用户组及加速器