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

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

A.Add (Arr2) 

¿Cómo puedo acceder al Arr2 a través de A? Por ejemplo, quiero hacer lo siguiente:Completando la colección con matrices

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

lo que lo anterior podría cambiar el primer elemento de la primera matriz de dos dimensiones dentro de la colección ...

Respuesta

7

Hmmm ... la sintaxis es legal suficiente sin tener VBA delante de mí. ¿Tengo razón en que tu problema es que tu código "compila" y se ejecuta sin generar un error, pero que la matriz en la colección nunca cambia? Si es así, creo que es porque su A.Item (1) podría estar devolviendo una copia de la matriz que almacenó en la colección. A continuación, accedes y modificas el elemento elegido muy bien, pero no está teniendo el efecto que deseas porque es la instancia de matriz incorrecta.

En general, las colecciones VBA funcionan mejor cuando se almacenan objetos. Entonces funcionarán como quieras porque almacenan referencias. Están bien para almacenar valores, pero creo que siempre los copian, incluso los "grandes" como las variantes de matriz, lo que significa que no se puede mutar el contenido de una matriz almacenada.

Considera esta respuesta solo como una especulación hasta que alguien que conozca el material COM subyacente pesa mejor. ¿Um ... buscando a Joel Spolsky?

EDITAR: Después de probar esto en Excel VBA, creo que estoy en lo cierto. Poner una variante de matriz en una colección hace una copia, y también sale una. Por lo tanto, no parece haber una forma directa de codificar lo que realmente ha pedido.

Parece que lo que realmente quiere es una matriz 3-D, pero el hecho de que estaba escribiendo para usar una colección para la primera dimensión implica que desea poder cambiar su tamaño en esa dimensión. VBA solo le permitirá cambiar el tamaño de la última dimensión de una matriz (consulte "redim preserve" en la ayuda). Usted puede poner sus matrices 2-D dentro de una matriz 1-D que puede cambiar el tamaño de, sin embargo:

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

Tenga en cuenta que una se declara con ReDim, se atenúa en este caso.

Finalmente, es bastante posible que algún otro enfoque sea lo que sea que intentes hacer sería mejor. Las matrices en 3-D creíbles y mutables son complejas y propensas a errores, por decir lo menos.

4

@jtolle es correcto. Si se ejecuta el código de abajo e inspeccionar los valores (Inspección rápida es Shift-F9) de Arr2 y X verá que son diferentes:

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

No creo que el Arr2 (1, 1) = 11 realmente cambie la matriz de la colección. Vea mi respuesta editada, pero parece que VBA hace una copia de la matriz al agregar y leer desde la colección. – jtolle

+0

Tal vez me deje engañar por tu comentario? Esa línea altera Arr2, pero no la matriz almacenada en la colección. Lo veo cambiando Arr2, pero no A.Item (1), que es solo una copia de Arr2 hecha por A.Add (Arr2). – jtolle

+0

@jtolle: disculpas, acabo de volver a verificar y tienes toda la razón. Actualizaré el código de arriba. Es una copia de Arr2 en la colección. –

1

Tal VBA hace una copia de la matriz cuando se asigna a ¿la colección? VB.net no hace esto. Después de este código, a (3,3) es 20 en vba y 5 en 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

Recientemente tuve este problema exacto. Lo redondeé poblando una matriz con la matriz de elementos en cuestión, realizando el cambio a esta matriz, eliminando la matriz de elementos de la colección y luego añadiendo la matriz modificada a la colección. No es bonita, pero funcionó ... y no puedo encontrar otra manera.

0

Si desea que la colección tenga una copia de la matriz y no una referencia a la matriz, utilice la matriz.método 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 

Al final, myCollection contendrá la colección acumulativo de myDates().

Cuestiones relacionadas