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

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

A.Add (Arr2) 

Come accedere allo Arr2 tramite A? Per esempio, io voglio fare le seguenti operazioni:Raccolta cumulativa con array

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

in modo che il sopra cambierebbe il primo elemento della prima matrice bidimensionale all'interno della collezione ...

risposta

7

Hmmm ... la sintassi è legale abbastanza senza avere VBA di fronte a me. Ho ragione che il tuo problema è che il tuo codice "compila" ed esegue senza generare un errore, ma che la matrice nella collezione non cambia mai? Se è così, penso che sia perché il tuo A.Item (1) potrebbe restituire una copia della matrice che hai archiviato nella collezione. Quindi accedi e modifichi l'elemento scelto bene, ma non ha l'effetto desiderato perché è l'istanza dell'array sbagliato.

In generale, le raccolte VBA funzionano meglio quando si memorizzano oggetti. Quindi funzioneranno come vuoi perché memorizzano i riferimenti. Stanno bene per la memorizzazione dei valori, ma penso che li copiano sempre, anche quelli "grandi" come le varianti di array, il che significa che non è possibile modificare il contenuto di un array memorizzato.

Considerate questa risposta solo una speculazione fino a quando qualcuno che conosce la roba di COM sottostante pesa meglio. Um ... cercapersone Joel Spolsky?

MODIFICA: dopo aver provato questo in Excel VBA, penso che ho ragione. Mettere una variante di un array in una collezione fa una copia, e così ne viene fuori una. Quindi non sembra essere un modo diretto per codificare ciò che hai effettivamente chiesto.

Sembra che ciò che realmente si desidera sia un array 3-D, ma il fatto che si stia tentando di utilizzare una raccolta per la prima dimensione implica che si desideri poter modificare la sua dimensione in quella dimensione. VBA ti permetterà solo di cambiare la dimensione dell'ultima dimensione di un array (vedi "redim preserve" nella guida). È possibile mettere gli array 2-D all'interno di un array di 1-D che è possibile modificare le dimensioni del, però:

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

Nota che una viene dichiarato con ReDim, si attenua in questo caso.

Infine, è abbastanza probabile che qualche altro approccio a qualunque cosa tu stia cercando di fare sarebbe meglio. Gli array 3D espandibili e mutevoli sono complessi e soggetti a errori, per usare un eufemismo.

4

@jtolle è corretto. Se si esegue il codice qui sotto e ispezionare i valori (Quick Watch è Maiusc-F9) di arr2 e X si vedrà che essi sono diversi:

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

Non penso che Arr2 (1, 1) = 11 cambi effettivamente la matrice nella raccolta. Vedi la mia risposta modificata, ma sembra che VBA faccia una copia dell'array quando aggiunge e legge dalla raccolta. – jtolle

+0

Forse sono solo fuorviato dal tuo commento? Quella linea altera Arr2, ma non la matrice memorizzata nella collezione. Vedo che cambia Arr2, ma non A.Item (1), che è solo una copia di Arr2 fatta da A.Add (Arr2). – jtolle

+0

@jtolle: mi scuso, ho appena ricontrollato e tu hai assolutamente ragione. Aggiornerò il codice sopra. È una copia di Arr2 nella collezione. –

1

Forse VBA fa una copia della matrice quando si assegna a la collezione? VB.net non lo fa. Dopo questo codice, a (3,3) è 20 in vba e 5 in 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

Recentemente ho avuto questo problema esatto. Ho fatto il giro popolando un array con l'array di elementi in questione, apportando la modifica a questo array, eliminando l'array di elementi dalla raccolta e quindi aggiungendo l'array modificato alla raccolta. Non carina ma ha funzionato .... e non riesco a trovare un altro modo.

0

Se si desidera che la raccolta abbia una copia dell'array e non un riferimento all'array, utilizzare la matrice.metodo 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 

Alla fine, myCollection conterrà la raccolta cumulativa di myDates().