Заполнение коллекции массивами - PullRequest
10 голосов
/ 10 сентября 2009
Dim A As Collection
Set A = New Collection

Dim Arr2(15, 5)
Arr2(1,1) = 0
' ...

A.Add (Arr2)

Как я могу получить доступ к Arr2 через A? Например, я хочу сделать следующее:

A.Item(1) (1,1) = 15

, поэтому приведенное выше изменит первый элемент первого двумерного массива внутри коллекции ...

Ответы [ 5 ]

8 голосов
/ 10 сентября 2009

Хммм ... синтаксис выглядит вполне законно без VBA передо мной. Прав ли я в том, что ваша проблема в том, что ваш код «компилируется» и выполняется без возникновения ошибки, но массив в коллекции никогда не изменяется? Если это так, я думаю, это потому, что ваш A.Item (1) может возвращать копию массива, который вы сохранили в коллекции. Затем вы просто получаете доступ и изменяете выбранный элемент, но он не дает желаемого эффекта, потому что это неправильный экземпляр массива.

Обычно коллекции VBA лучше всего работают при хранении объектов. Тогда они будут работать так, как вы хотите, потому что они хранят ссылки. Они хороши для хранения значений, но я думаю, что они всегда копируют их, даже «большие», такие как варианты массивов, что означает, что вы не можете изменить содержимое хранимого массива.

Считайте, что этот ответ всего лишь предположение, пока кто-то, кто знает базовый COM-материал, лучше не взвешивается. Хм ... пейджинг Джоэла Спольски?

РЕДАКТИРОВАТЬ: После испытания этого в Excel VBA, я думаю, что я прав. Помещение варианта массива в коллекцию делает копию, как и ее получение. Так что, похоже, нет прямого способа кодировать то, что вы на самом деле просили.

Похоже, что вам на самом деле нужен трехмерный массив, но тот факт, что вы пытались использовать коллекцию для первого измерения, подразумевает, что вы хотите иметь возможность изменять его размер в этом измерении. VBA позволит вам изменять только размер последнего измерения массива (см. «Redim preserve» в справке). Вы можете поместить свои двумерные массивы в одномерный массив, размер которого вы можете изменить, хотя:

ReDim a(5)
Dim b(2, 2)
a(2) = b
a(2)(1, 1) = 42
ReDim Preserve a(6)

Обратите внимание, что a объявляется с ReDim, а не Dim в этом случае.

Наконец, вполне возможно, что какой-то другой подход к тому, что вы пытаетесь сделать, был бы лучше. Растущие, изменяемые трехмерные массивы сложны и подвержены ошибкам, если не сказать больше.

5 голосов
/ 10 сентября 2009

@ jtolle правильно. Если вы запустите приведенный ниже код и проверите значения (Quick Watch is Shift-F9) Arr2 и x, вы увидите, что они различаются:

Dim A As Collection
Set A = New Collection
Dim Arr2(15, 5)

Arr2(1, 1) = 99

' ...

A.Add (Arr2) ' adds a copy of Arr2 to teh collection

Arr2(1, 1) = 11  ' this alters the value in Arr2, but not the copy in the collection

Dim x As Variant

x = A.Item(1)
x(1, 1) = 15  ' this does not alter Arr2
2 голосов
/ 10 сентября 2009

Может быть, VBA делает копию массива, когда назначает ее коллекции? VB.net не делает этого. После этого кода a (3,3) равно 20 в vba и 5 в vb.net.

Dim c As New Collection
Dim a(10, 10) As Integer

a(3, 3) = 20
c.Add(a)
c(1)(3, 3) = 5
1 голос
/ 14 сентября 2009

У меня недавно была именно эта проблема. Я обошел его, заполнив массив соответствующим массивом элементов, внеся изменения в этот массив, удалив массив элементов из коллекции и затем добавив измененный массив в коллекцию. Не красиво, но это сработало .... и я не могу найти другой путь.

0 голосов
/ 30 мая 2017

Если вы хотите, чтобы коллекция имела копию массива, а не ссылку на массив, используйте метод array.clone: ​​-

Dim myCollection As New Collection
Dim myDates() as Date
Dim i As Integer

Do
   i = 0
   Array.Resize(myDates, 0)
   Do
       Array.Resize(myDates, i + 1)
       myDates(i) = Now
       ...
       i += 1
   Loop
   myCollection.Add(myDates.Clone)
Loop

В конце myCollection будет содержать накопительную коллекцию myDates ().

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