Excel VBA 数组的工作表函数与代码的性能
Excel VBA performance of worksheetfunction vs code, for arrays
为了加快我的 VBA 代码速度,我在网上搜索了一些方法。很多方法都经过了,其中一个不断返回的方法似乎是在可能的情况下使用工作表函数代替代码。
然而,我的经验与该提示相反。我发现 worksheetfunctions 往往比我的代码 慢。我下面的简单测试表明代码比工作表函数快两倍。我发现其他函数的结果相同,例如 MATCH。
那么我的问题是,你们 VBA 的人倾向于使用代码还是工作表函数?是否有理由在代码上使用函数(除了几行额外代码)?
Sub testSum()
Dim testarray(0 To 10000) As Variant
Dim val As Variant
Dim valSum As Variant
Dim i As Long, j As Long
Dim t As Single
' create testarray
For i = 0 To 10000
testarray(i) = Rnd
Next
For i = 0 To 10000 Step 100
testarray(i) = "text"
Next
' measure code
t = Timer
For j = 1 To 10000
valSum = 0
For Each val In testarray
If IsNumeric(val) Then valSum = valSum + val
Next
Next
Debug.Print "Array: ", Int(valSum), Timer - t
' measure function
t = Timer
For j = 1 To 10000
valSum = 0
valSum = Application.WorksheetFunction.Sum(testarray)
Next
Debug.Print "Sum: ", Int(valSum), Timer - t
End Sub
我几乎只使用代码。
这可能是个问题,但我讨厌使用函数,因为我发现我总是必须返回并编辑位,这只会让我感到困惑,如果我可以只用一个 Sub
m 使用代码。
为了回答您的代码,我可能会说只使用数组求和 - 这会减少几皮秒
尝试并使用 Code Review 来让那些聪明人提高你的速度
我更喜欢使用工作表中的工作表功能。在宏中测量函数是一种不公平的测试,因为 VBA 环境必须切换到 Excel 环境才能获得结果,这会增加否则不存在的开销。
作为一般编码规则,我的优先事项是:
- 使用原生 Excel 公式,包括设置辅助单元格或
列。
- 对数组使用 VBA
- 使用 VBA 和 运行ges
作为测试:
- 使用 运行dom 数字设置 10,000 行
- 在一个单元格中设置公式 (
B1
) =Sum(A1:A10000)
- select
B1
并计算单元格
设置一个宏 - 下面是基于您上面的代码的快速而粗略的 - 通过使用适当限定的 运行ges 和 Option Explicit
.
可能会更整洁
Sub TestNativeSpeed()
Dim j As Long
Dim t As Single
t = Timer
For j = 1 To 10000
Range("B1").Dirty
Next
Debug.Print "Native Sum: ", Int(Range("B1").Value), Timer - t
End Sub
我使用公式 =Rand()
设置了我的单元格并得到了结果(仅限单个 运行):
Native Sum: 4990 16.53125
我仅将它们重置为值(与您的代码一致)并且我得到了结果(仅 运行):
Native Sum: 4990 1.765625
我运行你的代码并得到了(仅运行):
Array: 4917 4.386719
Sum: 4917 27.73438
以上显示的是原生 Excel 通常是最快和最有效的方法。但是数组(不需要在 VBA 和 Excel 模型之间切换)在效率方面是次要的。
为了加快我的 VBA 代码速度,我在网上搜索了一些方法。很多方法都经过了,其中一个不断返回的方法似乎是在可能的情况下使用工作表函数代替代码。
然而,我的经验与该提示相反。我发现 worksheetfunctions 往往比我的代码 慢。我下面的简单测试表明代码比工作表函数快两倍。我发现其他函数的结果相同,例如 MATCH。
那么我的问题是,你们 VBA 的人倾向于使用代码还是工作表函数?是否有理由在代码上使用函数(除了几行额外代码)?
Sub testSum()
Dim testarray(0 To 10000) As Variant
Dim val As Variant
Dim valSum As Variant
Dim i As Long, j As Long
Dim t As Single
' create testarray
For i = 0 To 10000
testarray(i) = Rnd
Next
For i = 0 To 10000 Step 100
testarray(i) = "text"
Next
' measure code
t = Timer
For j = 1 To 10000
valSum = 0
For Each val In testarray
If IsNumeric(val) Then valSum = valSum + val
Next
Next
Debug.Print "Array: ", Int(valSum), Timer - t
' measure function
t = Timer
For j = 1 To 10000
valSum = 0
valSum = Application.WorksheetFunction.Sum(testarray)
Next
Debug.Print "Sum: ", Int(valSum), Timer - t
End Sub
我几乎只使用代码。
这可能是个问题,但我讨厌使用函数,因为我发现我总是必须返回并编辑位,这只会让我感到困惑,如果我可以只用一个 Sub
m 使用代码。
为了回答您的代码,我可能会说只使用数组求和 - 这会减少几皮秒
尝试并使用 Code Review 来让那些聪明人提高你的速度
我更喜欢使用工作表中的工作表功能。在宏中测量函数是一种不公平的测试,因为 VBA 环境必须切换到 Excel 环境才能获得结果,这会增加否则不存在的开销。
作为一般编码规则,我的优先事项是:
- 使用原生 Excel 公式,包括设置辅助单元格或 列。
- 对数组使用 VBA
- 使用 VBA 和 运行ges
作为测试:
- 使用 运行dom 数字设置 10,000 行
- 在一个单元格中设置公式 (
B1
)=Sum(A1:A10000)
- select
B1
并计算单元格
设置一个宏 - 下面是基于您上面的代码的快速而粗略的 - 通过使用适当限定的 运行ges 和 Option Explicit
.
Sub TestNativeSpeed()
Dim j As Long
Dim t As Single
t = Timer
For j = 1 To 10000
Range("B1").Dirty
Next
Debug.Print "Native Sum: ", Int(Range("B1").Value), Timer - t
End Sub
我使用公式 =Rand()
设置了我的单元格并得到了结果(仅限单个 运行):
Native Sum: 4990 16.53125
我仅将它们重置为值(与您的代码一致)并且我得到了结果(仅 运行):
Native Sum: 4990 1.765625
我运行你的代码并得到了(仅运行):
Array: 4917 4.386719
Sum: 4917 27.73438
以上显示的是原生 Excel 通常是最快和最有效的方法。但是数组(不需要在 VBA 和 Excel 模型之间切换)在效率方面是次要的。