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

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

A.Add (Arr2) 

Làm cách nào để truy cập vào Arr2 qua A? Ví dụ, tôi muốn làm như sau:Bộ sưu tập tuyển tập có mảng

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

nên trên sẽ thay đổi phần tử đầu tiên của mảng hai chiều đầu tiên trong bộ sưu tập ...

Trả lời

7

Hmmm ... cú pháp trông pháp lý đủ mà không có VBA trước mặt tôi. Tôi có đúng là vấn đề của bạn là mã của bạn "biên dịch" và thực hiện mà không gây ra lỗi, nhưng mảng trong bộ sưu tập không bao giờ thay đổi? Nếu vậy, tôi nghĩ rằng đó là vì A.Item (1) của bạn có thể trả lại bản sao của mảng bạn đã lưu trữ trong bộ sưu tập. Sau đó, bạn truy cập và sửa đổi phần tử đã chọn tốt, nhưng nó không có hiệu ứng mà bạn muốn bởi vì nó là một thể hiện mảng sai.

Nói chung, bộ sưu tập VBA hoạt động tốt nhất khi lưu trữ các đối tượng. Sau đó, họ sẽ làm việc như bạn muốn bởi vì họ lưu trữ tài liệu tham khảo. Chúng tốt cho việc lưu trữ các giá trị, nhưng tôi nghĩ rằng chúng luôn sao chép chúng, thậm chí là những cái "lớn" như các biến thể mảng, có nghĩa là bạn không thể thay đổi nội dung của một mảng được lưu trữ.

Hãy xem xét câu trả lời này chỉ là một suy đoán cho đến khi ai đó biết công cụ COM tiềm ẩn tốt hơn. Um ... phân trang Joel Spolsky?

EDIT: Sau khi thử tính năng này trong Excel VBA, tôi nghĩ tôi đúng. Đặt một biến thể mảng trong một bộ sưu tập tạo ra một bản sao, và do đó không nhận được một. Vì vậy, có vẻ như không phải là cách trực tiếp để mã hóa những gì bạn đã thực sự yêu cầu.

Dường như những gì bạn thực sự muốn là một mảng 3-D, nhưng thực tế là bạn đã buộc phải sử dụng bộ sưu tập cho thứ nguyên đầu tiên ngụ ý rằng bạn muốn có thể thay đổi kích thước của nó trong thứ nguyên đó. VBA sẽ chỉ cho phép bạn thay đổi kích thước của kích thước cuối cùng của một mảng (xem "redim preserve" trong phần trợ giúp). Bạn có thể đưa mảng 2-D của bạn bên trong một mảng 1-D mà bạn có thể thay đổi kích thước, mặc dù:

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

Lưu ý rằng một tuyên bố với ReDim, không Dim trong trường hợp này.

Cuối cùng, hoàn toàn có thể là một số cách tiếp cận khác với bất kỳ điều gì bạn đang cố gắng làm sẽ tốt hơn. Các mảng 3-D có thể thay đổi, dễ phát triển phức tạp và dễ bị lỗi, để nói ít nhất.

4

@jtolle là chính xác. Nếu bạn chạy mã dưới đây và kiểm tra các giá trị (Quick Watch Shift-F9) của Arr2 và X bạn sẽ thấy rằng họ là khác nhau:

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

Tôi không nghĩ rằng Arr2 (1, 1) = 11 thực sự thay đổi mảng trong bộ sưu tập. Xem câu trả lời đã chỉnh sửa của tôi, nhưng có vẻ như VBA tạo một bản sao của mảng khi thêm vào và đọc từ bộ sưu tập. – jtolle

+0

Có lẽ tôi chỉ bị lừa bởi nhận xét của bạn? Dòng đó thay đổi Arr2, nhưng không thay đổi mảng được lưu trữ trong bộ sưu tập. Tôi thấy nó thay đổi Arr2, nhưng không phải A.Item (1), mà chỉ là một bản sao của Arr2 được thực hiện bởi A.Add (Arr2). – jtolle

+0

@jtolle: xin lỗi, tôi vừa kiểm tra lại và bạn hoàn toàn chính xác. Tôi sẽ cập nhật mã ở trên. Nó là một bản sao của Arr2 trong bộ sưu tập. –

1

lẽ VBA tạo một bản sao của mảng khi nó gán nó vào bộ sưu tập? VB.net không làm điều này. Sau mã này, một (3,3) là 20 trong vba và 5 trong 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

Gần đây, tôi đã gặp sự cố chính xác này. Tôi đã làm tròn nó bằng cách điền một mảng với mảng item đang được đề cập đến, thay đổi mảng này, xóa mảng item khỏi collection và sau đó thêm mảng đã thay đổi vào collection. Không đẹp nhưng nó hoạt động .... và tôi không thể tìm thấy một cách khác.

0

Nếu bạn muốn bộ sưu tập có bản sao của mảng và không phải là tham chiếu đến mảng đó, thì hãy sử dụng mảng.phương pháp sao chép: -

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 

Cuối cùng, sưu tập của tôi sẽ chứa bộ sưu tập tích lũy của myDates().