200 мсек анекдотичны, но издержки можно объяснить.
Dim qcolumns As Variant
Это ваш массив, но для VBA это просто Variant
: чтобы знать, что он смотрит на массив, нужен VBA(во время выполнения) для разыменования указателя варианта, проверки байтов, в которых хранятся метаданные подтипа, получения указателя массива и ... разыменования указателя массива.
С явным объявлением массива было бы меньше накладных расходов:
Dim qcolumns(1 To 10) As SettingsColumns
Теперь нам не важен массив ... мы просто пытаемся перебрать его содержимое:
Set qc = qcolumns(i)
Итак, на каждой итерации вариант /Разыменование массива должно произойти, и указатель объекта будет скопирован в qc
. Но почему медленнее сделать вызов участника против qcolumns(i)
?
Поскольку qcolumns
является Variant
, любой вызов участника, сделанный против него, должен иметь позднюю привязку, то есть разрешаться во время выполнения,XlGrouped
свойство не известно на VBA, пока преуспевает вызов член, вызов член может добиться успеха только после того, запрашивая IUnknown
интерфейс объекта (если это не удается, ошибка 438 возникает).
1022* Когда вы делаете
Dim qc As SettingsColumn
, вы связываетесь рано, во время компиляции. Теперь компилятор уже знает, где найти член
XlGrouped
, и ему не нужно запрашивать
IUnknown
через указатель
Variant
: все намного проще ... и обычно проще означает быстрее.
Но вы перебираете массив объектов: это будет медленнее, чем нужно, несмотря ни на что.
Объекты хотят быть перебраны в 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
для итерации коллекций объектов.