2014-01-22 2 views
3

Я работаю на надстройку Excel VBA, который обменивает объекты с COM-сервером, что-то вроде этого:Как удалить массив в VBA?

'get an array of objects 
Dim Ents() As ISomething 
ComObject.GetEntities Ents 

'send an array with 10 objects 
ReDim Ents(9) 
Set Ents(0) = ... 
... 
ComObject.SetEntities Ents 

Получение массивов хорошо работает: если массив содержит объекты, которые он работает, как и следовало ожидать, если массив пуст тогда UBound(Ents) = -1 и все работает как ожидалось.

Отправка массивов работает только с не пустыми массивами, потому что я не Redim Ents(-1) и Erase может ИНГ массив как VBA и аварии COM-сервер: Debug.Print UBound(Ents) сбой в VBA и кто знает, что происходит сбой сервера.

Похоже, что инструкция Erase оставляет массив неопределенным/поврежденным, а не пустым.

EDIT (разъяснения в комментарии ниже):

Выполнение этого кода происходит сбой, поскольку он не может рассчитать UBound:

Sub Test() 
    Dim Ents() As ISmartId 
    Debug.Print UBound(Ents) 
End Sub 

Но если добавить Ents в окне просмотра, а затем установите точка останова на строку Debug.Print и выполнить, отладчик показывает ISmartId(0 to -1) в столбце Тип. После этого выполнение продолжается без сбоев, а в окне Debug отображается ожидаемое -1.

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

+0

Я не думаю, что вы можете , AFAIK, вы можете удалить их, а затем поймать ошибки при попытке проверить их размер. Se here: http://stackoverflow.com/questions/206324/how-to-check-for-empty-array-in-vba-macro – RBarryYoung

+0

@RBarryYoung: я могу выполнить проверку на стороне VBA, но COM-сервер является сторонним приложением, и они просто ожидают пустой массив. Я только что нашел обходное решение, которое работает только со строковыми массивами: 'Split (" ")'. Мне нужно общее решение для 'IAnything'. Это помогает вашей фантазии? – stenci

+1

«Это помогает вашей фантазии?» «А? Извините, я не следую ..? – RBarryYoung

ответ

3

Для объектов, вы можете сделать это только путем копирования неопределенного массива в вариант и обратно:

Dim o() As Worksheet 
Dim v As Variant 
v = o 
o = v 

Для не-объектов, сделать пустой массив в варианте, а затем изменить его тип кода:

Private Declare Sub GetMem2 Lib "msvbvm60" (src As Any, dest As Any) 

Dim i() as Long 
Dim v as Variant 
v = Array() 

Dim NewTypeCode As Integer 
NewTypeCode = vbArray Or vbLong 
GetMem2 NewTypeCode, v 
i = v 
+0

Я принял этот ответ, потому что он очень близок к тому, что мне нужно, даже если он не дает мне того типа, который я хочу. Я заметил, что если у меня есть массив в окне часов и точка останова после «Erase», VBA инициализирует массив пустым массивом, и в этой точке я могу продолжить выполнение, и он работает хорошо. Вы знаете, что происходит под капотом этого окна часов? – stenci

+0

Не могли бы вы опубликовать код, который вы используете, и где точка останова? У меня возникли проблемы с пониманием того, что вы имеете в виду, когда говорите об утверждении «Стереть». – Chel

+1

@stenci Хорошо, я обновил свой ответ с гораздо более простым решением для ранних объектов. – Chel

0

Если вам нужен свежий массив можно создать функцию «фабрики», чтобы вернуть один

Function FreshArray() As ISomething() 
    Dim rv() As ISomething 
    FreshArray = rv 
End Function 

Ents = FreshArray() 
ComObject.GetEntities Ents 
+1

Это работает как «Стереть»: создает поврежденный/неопределенный массив. Он сбрасывает чтение 'UBound (FreshArray)'. – stenci

Смежные вопросы