Выступление в классе VBA - PullRequest
       2

Выступление в классе VBA

1 голос
/ 22 октября 2019

У меня есть этот код:

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 мс. Почему такая разница только от установки класса из массива в переменную?

1 Ответ

2 голосов
/ 22 октября 2019

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 для итерации коллекций объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...