2009-09-10 12 views
9
Dim A As Collection 
Set A = New Collection 

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

A.Add (Arr2) 

Jak uzyskać dostęp do Arr2 do A? Na przykład, chcę wykonać następujące czynności:Wypełnianie kolekcji za pomocą tablic

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

więc powyższe byłoby zmienić pierwszy element pierwszego dwuwymiarowej tablicy wewnątrz kolekcji ...

Odpowiedz

7

Hmmm ... składnia wygląda prawny wystarczy bez VBA przede mną. Czy mam rację, że twój problem polega na tym, że twój kod "kompiluje się" i wykonuje bez podnoszenia błędu, ale tablica w kolekcji nigdy się nie zmienia? Jeśli tak, myślę, że to dlatego, że Twój A.Item (1) może zwracać kopię z tablicy przechowywanej w kolekcji. Następnie uzyskujesz dostęp do wybranego elementu i go modyfikujesz, ale nie ma pożądanego efektu, ponieważ jest to niewłaściwa instancja tablicy.

Ogólnie kolekcje VBA działają najlepiej podczas przechowywania obiektów. Wtedy będą działać tak, jak chcesz, ponieważ przechowują odniesienia. Są one odpowiednie do przechowywania wartości, ale myślę, że zawsze je kopiują, nawet "duże", takie jak warianty macierzy, co oznacza, że ​​nie można zmutować zawartości przechowywanej tablicy.

Rozważ tę odpowiedź tylko do czasu, aż ktoś, kto zna leżące u podstaw rzeczy COM, poczuje się lepiej. Um ... woła Joel Spolsky?

EDYCJA: Po wypróbowaniu tego w programie Excel VBA, myślę, że mam rację. Umieszczenie wariantu tablicowego w zbiorze powoduje utworzenie kopii, a więc jej usunięcie. Tak więc nie wydaje się, że istnieje bezpośredni sposób kodowania tego, o co prosiłeś.

Wygląda na to, czego faktycznie potrzebujesz, to tablica 3-D, ale fakt, że używałeś kolekcji dla pierwszego wymiaru, oznacza, że ​​chcesz mieć możliwość zmiany jej rozmiaru w tym wymiarze. VBA pozwoli ci tylko zmienić rozmiar ostatniego wymiaru tablicy (patrz "Zachowaj redim" w pomocy). Ci może umieścić tablice 2-D wewnątrz tablicy 1-D, które można zmienić rozmiar, choć:

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

pamiętać, że jest zadeklarowana z Redim nie Dim w tym przypadku.

Wreszcie jest całkiem możliwe, że inne podejście do tego, co próbujesz zrobić, byłoby lepsze. Growable, zmienne tablice 3-D są skomplikowane i podatne na błędy.

4

@ jtolle jest poprawny. Jeśli uruchomić poniższy kod i sprawdzić wartości (Quick Watch jest Shift-F9) z arr2 i X widać, że są one różne:

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 
+0

Nie sądzę, że Arr2 (1, 1) = 11 faktycznie zmienia tablicę w kolekcji. Zobacz moją edytowaną odpowiedź, ale wygląda na to, że VBA tworzy kopię tablicy podczas dodawania i czytania z kolekcji. – jtolle

+0

Może zostałem wprowadzony w błąd przez twój komentarz? Ta linia zmienia Arr2, ale nie tablicę zapisaną w kolekcji. Widzę, że zmienia Arr2, ale nie A.Item (1), który jest po prostu kopią Arr2 stworzoną przez A.Add (Arr2). – jtolle

+0

@jtolle: przepraszam, właśnie sprawdziłem i masz absolutną rację. Zaktualizuję powyższy kod. Jest to kopia Arr2 w kolekcji. –

1

Może VBA tworzy kopię tablicy, gdy przypisuje go do kolekcja? VB.net tego nie robi. Po tym kodzie wartość (3,3) wynosi 20 w vba i 5 w 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

Niedawno miałem dokładnie ten problem. Zająłem się tym, wypełniając tablicę przedmiotową tablicą przedmiotową, wprowadzając zmianę do tej tablicy, usuwając tablicę pozycji z kolekcji, a następnie dodając zmienioną tablicę do kolekcji. Nie ładne, ale działało .... i nie mogę znaleźć innej drogi.

0

Jeśli chcesz, aby kolekcja miała kopię tablicy, a nie odwołanie do tablicy, użyj tablicy.Metoda klonowania: -

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 

Na końcu myCollection będzie zawierał kolekcję kolekcji myDates().