excel-vba WorksheetFunction对象的执行速度快于等效的UDF
示例
VBA是在运行时编译的,这会对它的性能产生巨大的负面影响,内置的所有内容都会更快,请尝试使用它们。
作为示例,我正在比较SUM和COUNTIF函数,但是如果可以用WorkSheetFunctions解决任何问题,则可以使用if。
这些的第一个尝试是遍历范围并逐个单元(使用范围)对其进行处理:
Sub UseRange()
Dim rng as Range
Dim Total As Double
Dim CountLessThan01 As Long
Total = 0
CountLessThan01 = 0
For Each rng in Sheets(1).Range("A1:A100")
Total = Total + rng.Value2
Ifrng.Value< 0.1 Then
CountLessThan01 = CountLessThan01 + 1
End If
Next rng
Debug.PrintTotal & ", " & CountLessThan01
End Sub一种改进可以是将范围值存储在数组中,并进行以下处理:
Sub UseArray()
Dim DataToSummarize As Variant
Dim i As Long
Dim Total As Double
Dim CountLessThan01 As Long
DataToSummarize = Sheets(1).Range("A1:A100").Value2 'faster than .Value
Total = 0
CountLessThan01 = 0
For i = 1 To 100
Total = Total + DataToSummarize(i, 1)
If DataToSummarize(i, 1) < 0.1 Then
CountLessThan01 = CountLessThan01 + 1
End If
Next i
Debug.PrintTotal & ", " & CountLessThan01
End Sub但是,除了编写任何循环之外,您还可以使用Application.Worksheetfunction它来执行简单的公式:
Sub UseWorksheetFunction()
Dim Total As Double
Dim CountLessThan01 As Long
With Application.WorksheetFunction
Total = .Sum(Sheets(1).Range("A1:A100"))
CountLessThan01 = .CountIf(Sheets(1).Range("A1:A100"), "<0.1")
End With
Debug.PrintTotal & ", " & CountLessThan01
End Sub或者,对于更复杂的计算,您甚至可以使用Application.Evaluate:
Sub UseEvaluate()
Dim Total As Double
Dim CountLessThan01 As Long
With Application
Total = .Evaluate("SUM(" & Sheet1.Range("A1:A100").Address( _
external:=True) & ")")
CountLessThan01 = .Evaluate("COUNTIF('Sheet1'!A1:A100,""<0.1"")")
End With
Debug.PrintTotal & ", " & CountLessThan01
End Sub最后,每次在Subs上运行25,000次以上,以下是平均(5次测试)时间(以毫秒为单位)(当然,每台PC上的时间会有所不同,但与之相比,它们的行为类似):
UseWorksheetFunction:2156毫秒
UseArray:2219毫秒(+3%)
使用评估:4693毫秒(+118%)
使用范围:6530毫秒(+203%)