WorksheetFunction 对象的执行速度比 UDF 等效对象快
VBA 是在运行时编译的,它对它的性能有很大的负面影响,内置的所有内容都会更快,尝试使用它们。
作为一个例子,我正在比较 SUM 和 COUNTIF 函数,但你可以使用 if 来解决任何你可以使用 WorkSheetFunctions 解决的问题。
对它们的第一次尝试是循环遍历范围并逐个单元地处理它(使用范围):
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
If rng.Value < 0.1 Then
CountLessThan01 = CountLessThan01 + 1
End If
Next rng
Debug.Print Total & ", " & 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.Print Total & ", " & 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.Print Total & ", " & 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.Print Total & ", " & CountLessThan01
End Sub
最后,每次运行超过 2.5,000 次,这里是平均(5 次测试)时间(以毫秒为单位)(当然,每台电脑上都会有所不同,但相互比较它们的行为类似):
- UseWorksheetFunction:2156 ms
- UseArray:2219 毫秒(+ 3%)
- UseEvaluate:4693 ms(+ 118%)
- UseRange:6530 毫秒(+ 203%)