vba - VBA 类性能
问题描述
我有这个代码:
For i = 0 To .Fields.Count - 1
Set qc = qcolumns(i)
If qc.XlGrouped = True Then
...
对我来说奇怪的是,如果我改变qc.XlGrouped = True
它qcolumns(i).XlGrouped = True
需要 200 毫秒,而第一个需要 0 毫秒。为什么与将类从数组设置为变量有如此大的区别?
解决方案
200ms 是轶事,但可以解释开销。
Dim qcolumns As Variant
那是你的数组,但对于 VBA 它只是一个Variant
:为了知道它正在查看一个数组,VBA 需要(在运行时)取消引用变体指针,检查保存子类型元数据的字节,获取数组指针,......并取消引用数组指针。
显式数组声明的开销会更少:
Dim qcolumns(1 To 10) As SettingsColumns
现在,我们并不真正关心数组......我们只是试图迭代它的内容:
Set qc = qcolumns(i)
所以在每次迭代中,变体/数组解引用需要发生,并且对象指针被复制到qc
. 但是为什么打会员电话要慢qcolumns(i)
呢?
因为qcolumns
是 a Variant
,所以对它进行的任何成员调用都必须是后期绑定的,即在运行时解决。XlGrouped
在成员调用成功之前,VBA 不知道该属性,并且成员调用只有在查询IUnknown
对象的接口后才能成功(如果失败,则会引发错误 438)。
当你这样做时Dim qc As SettingsColumn
,你会在编译时尽早绑定。现在编译器已经知道在哪里可以找到XlGrouped
成员,并且不需要IUnknown
通过Variant
指针查询:一切都简单得多......通常更简单意味着更快。
但是您正在迭代一个对象数组:无论如何,这将比它需要的要慢。
对象想要在 a 中迭代Collection
,使用For Each
循环。
Dim qc As SettingsColumn
For Each qc In myCollection
If qc.XlGrouped Then '<~ note =True is redundant
'...
End If
Next
有关更多信息和性能基准,请参阅For vs For Each。底线是,使用循环迭代对象Collection
并按For
索引检索每个项目,总是比For Each
循环慢得多;用于For
迭代值数组,For Each
迭代对象集合。
推荐阅读
- php - Laravel(5.6)最后一条消息的雄辩顺序
- r - 使用 purrr 迭代时间序列数据
- javascript - 调试模式下的 Vue 反应性
- php - PHP/Wordpress 如何从数组中获取键/索引值
- java - 从 .key 和 .cer 文件实例化 java.security 类 PrivateKey 和 X509Certificate
- python - Colorgram:从每个元素中删除 Rgb
- html - 在 HERE 地图上设置块
- ruby - 在 Scala 中寻找“整齐的数字”
- javascript - Navigo JS 路由器 - 重复路由问题
- php - Order_by 错误 1 10 11 12