VBA: Что является причиной того, что этот строковый аргумент, передаваемый ParamArray, изменяется на число (которое выглядит подозрительно как указатель)? - PullRequest
11 голосов
/ 31 июля 2010

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: Это действительно ошибка компилятора - см. Принятый ответ.

Используя VBA в Excel 2007, у меня есть следующий код в 'Class1':

Option Explicit

Public Function strange(dummy As String, ParamArray pa())
    Debug.Print pa(LBound(pa))
End Function

Public Sub not_strange(dummy As String, ParamArray pa())
    Debug.Print pa(LBound(pa))
End Sub

Public Function also_not_strange(ParamArray pa())
    Debug.Print pa(LBound(pa))
End Function

и некоторый код режима в модуле:

Option Explicit

Public Function not_strange_either(dummy As String, ParamArray pa())
    Debug.Print pa(LBound(pa))
End Function

Public Sub outer(v)
    Dim c As Class1
    Set c = New Class1

    Call c.strange("", v(LBound(v)))
    Call c.not_strange("", v(LBound(v)))
    Call c.also_not_strange(v(LBound(v)))

    Call not_strange_either("", v(LBound(v)))
End Sub

Если вызвать 'external' из окна Immediate следующим образом:

call outer(array("a"))

Я получаю вывод, который кажется странным:

 102085832 
a
a
a

Кажется, имеет значение, находится ли вызываемая подпрограмма в модуле класса или нет, является ли она подпрограммой или функцией, и существует ли начальный аргумент или нет.Я что-то упускаю из-за того, как должен работать VBA?Есть идеи?

Странное число меняется от запуска к бегу.Я говорю «выглядит подозрительно, как указатель», потому что, если я назову это:

Public Sub outer2(v)
    Dim c As Class1
    Set c = New Class1

    Dim ind As Long
    For ind = LBound(v) To UBound(v)
        Call c.strange("", v(ind))
    Next ind
End Sub

примерно так:

call outer2(array("a","b","c"))

Я получу обратно вывод как:

 101788312 
 101788328 
 101788344 

Это увеличение на 16 делает меня подозрительным, но я действительно не знаю.Кроме того, передача значения, скажем, путем вызова:

Call c.strange("", CStr(v(ind)))

работает просто отлично.

РЕДАКТИРОВАТЬ: немного больше информации ... Если я назначу возвращаемое значение из 'c.strange'к чему-то вместо того, чтобы выбросить это, я получаю то же поведение:

Public Sub outer3(v)
    Dim c As Class1
    Set c = New Class1

    Dim x
    x = c.strange("", v(LBound(v)))

    Call c.not_strange("", v(LBound(v)))
    Call c.also_not_strange(v(LBound(v)))

    Call not_strange_either("", v(LBound(v)))
End Sub

Интересно, что если я вызываю мои тестовые процедуры, как указано выше, с аргументом, который получается в результате вызова 'Array', значения предполагаемого указателяизменения.Однако, если я позвоню так:

call outer([{1,2,3}])

Я получу один и тот же номер, даже если я сделаю вызов несколько раз.(Число изменится, если я переключусь на другое приложение в Windows, например, в моем браузере.) Итак, теперь я заинтригован тем, что оценщик Excel (вызывается в скобках), по-видимому, кэширует его результаты ...

1 Ответ

7 голосов
/ 31 июля 2010

Теперь это круто.

Воспроизведено в Office 2003.
Похоже на ошибку компилятора.

Проблема в этой строке:

Call c.strange("", v(LBound(v)))

Здесь компилятор создает Variant, который содержит одномерный массив Variant, единственным элементом которого является указатель вместо значения.Затем этот указатель переходит к функции strange, что на самом деле не странно, он печатает только переданное ей значение Variant\Long.

Этот прием возвращает здравомыслие компилятора:

Call c.strange("", (v(LBound(v))))

EDIT

Да, это магическое число является указателем на структуру VARIANT, которая должна быть передана методу strange.Первое поле которого 8, которое vbString, и поле данных содержит указатель на фактическую строку "a".

Следовательно, это определенно ошибка компилятора ... Еще однаОшибка компилятора VB в отношении массивов;)

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