Các câu hỏi về mảng trong VBA (Array)

Liên hệ QC

viehoai

Thành viên gắn bó
Tham gia
22/5/09
Bài viết
2,599
Được thích
2,908
Xin các anh chị giúp đỡ Code Gán các giá trị của một Range là các phần tử của Mãng
Ví dụ: Tôi có các giá trị của Range("A1:A10"). Tôi muốn viết code để gán giá trị của các cells từ A1:A10 là các phần tử của Mãng Arr chẳn hạn.
Xin cảm ơn các anh chị
 
Thật ra là mình không cần biết cũng được anh nghĩa vì có nhiều cách gán mà, nhưng mà mình đi dạy nên phải phòng các trường hợp người ta có thể hỏi mình bất cứ thứ gì, nên phải phòng trước tới đâu hay tối đó hi hi
còn 3 chiều mình phải thêm dấu gì nữa thầy ndu

Cái vụ arr = [{1,2,3;4,5,6}] hay arr = Evaluate("{1,2,3;4,5,6}") là cách mình "ăn gian" kiểu gõ trên bảng tính:
- Quét chọn vùng 2 dòng 3 cột
- Gõ lên thanh Formula công thức: = {1,2,3;4,5,6}
- Bấm Ctrl + Shift + Enter

------------------
Vậy với cách này thì: thứ gì ta gõ được trên bảng tính gần như có thể chuyển được thành code.
Bởi vì bảng tính là Table, tương đương mảng 2D nên việc tương tác giữa bảng tính và mảng 2D là chuyện khá dễ dàng
Với mảng 3D, chưa từng thấy ai gõ được trực tiếp trên bảng tính bao giờ. Mà dù có gõ được thì ta sẽ nhận được kết quả ra làm sao? Bạn có tưởng tượng được không?
 
Upvote 0
Nói chung về hình hài và xử lý mảng 1, chiều ,2 chiều ,3 chiều ,4 chiều hay n chiều em xử lý rất tốt, vì cái này nói chung ý tưởng như những ngôn ngữ lập trình mà em đã học. Em đang nhận 1 lớp dạy VBA, em soạn về mảng tham khảo GPE thấy, có Array nhập mảng một chiều nên mới có ý định làm thêm 2, 3, hay nhiều chiều( tránh trường hợp người học hỏi còn biết đường trả lời)

Anh ndu cho em hỏi thêm. Em có xem trên diễn đàn để làm tư liệu trong bài giảng. Em thấy phần DIC của Kyo nguyễn khắc duy có phần này hình như là lơ tơ mơ thì phải

trích trong bài
http://www.giaiphapexcel.com/forum/showthread.php?60643-Tổng-quan-về-Scripting.Dictionary

Phương thức Keys: Phương thức Keys sẽ trả về giá trị mảng một chiều mà phần tử đầu tiên là phần tử 0 (dù cho bạn có sử dụng Option Base 1).

- Phương thức Items: Phương thức Items sẽ trả về giá trị mảng một chiều mà phần tử đầu tiên là phần tử 0 (dù cho bạn có sử dụng Option Base 1).

cái này đáng lẽ phải nói rõ ràng ra là:
cái nào trả về key được lưu trữ trong mảng một chiều
cái nào trả về giá trị của key tương ứng được lưu trữ trong mảng một chiều

vấn đề 2 là về khái niệm mảng của anh Lê Văn Duyệt
http://www.giaiphapexcel.com/diendan/threads/92936.Làm-việc-với-mảng-trong-VBA
Mảng là một tập hợp của nhiều biến liên quan (related variables) được gọi qua một tên. em thấy khái niệm như vậy không đúngTrong lập trình C, PASCAL
Mảng là một tập hợp các phần tử có cùng kiểu dữ liệu
nhưng trong VBA thì các phần tử trong mảng có thể khác kiểu dữ liệu
nên có thể khái niệm rằng
Mảng là một tập hợp các phần tử liên quan mới đúng hơn

 
Upvote 0
Anh ndu cho em hỏi thêm. Em có xem trên diễn đàn để làm tư liệu trong bài giảng. Em thấy phần DIC của Kyo nguyễn khắc duy có phần này hình như là lơ tơ mơ thì phải

trích trong bài

Cái nào liên quan đến lý thuyết xin đừng hỏi tôi!
Nói chung, món nào tôi có thể làm được thì điều đương nhiên tôi đã hiểu nó, thậm chí là hiểu rõ đến mức có thể "tung hoành ngang dọc" tùy ý. Tuy nhiên, kêu phát biểu cho thành câu cú đàng hoàng (dạng để làm sách giảng dạy) thì tôi... THUA
(có được học qua trường lớp ngày nào như các bạn đâu mà phát với biểu)
 
Upvote 0
... nhưng mà mình đi dạy nên phải phòng các trường hợp người ta có thể hỏi mình bất cứ thứ gì, nên phải phòng trước ...

Nếu tôi đi dạy thì tôi chỉ cho học sinh căn bản cách sử dụng bảng để thành lập bảng tính thôi. Tất cả những gì còn lại người ta sẽ từ kinh nghiệm mà suy ra. Một khi có căn bản về cơ cấu bảng tính thì nghiệm cái gì cũng dễ.

Để trả lời việc gán trị cho mảng thì lý thuyết như sau:

Như tôi đã có trình bày trong một thớt nọ (quên mất rồi, tự tìm lấy), người ta cũng dịch một range là mảng cho nên đôi khi gây ra sự lầm lẫn.

Trong Excel VBA, cái application là một object, object này có một collection là workbooks, mỗi workbook trong collection trên thì lại có collection worksheets. Mỗi worksheet là một object item (phần tử) của collection worksheets. Object worksheet có nhiều thuộc tính (tôi thỉnh thoảng quen gọi theo ngôn ngữ tổng quát là hàm). Trong những thuộc tính đó có thuộc tính Range. Vì range là đối tượng của một class cho nên chính nó cũng có nhiều thuộc tính và phương thức. Một trong những tính chất này là phép ngầm chuyển từ giá trị của range sang mảng và ngược lại (bạn nói mình đã học qua C++, thì có thể tạm coi như range có phép viết hàm chồng phép gán, toán tử =).

Lợi dụng tính chất này, VBA có thể sử dụng range theo nhiều cách khác nhau. Điển hình là 2 cách rất phổ biến trên diễn đàn này:
1. chuyển dữ liệu từ một range sang array và ngược lại. vd arr = Range("a1:b2")
2. Điển hình thứ hai là cách viết tắt hàm Evaluate của worksheet, tức là dấu []. vd [a1:b2]

Tất cả phần trên, bạn đã biết rồi. Còn phần nữa bạn cũng biết sử dụng nhưng không rõ cơ cấu lý thuyết của nó (lưu ý từ "cơ cấu", đó là tại sao tôi nói bạn hiểu cơ cấu thì học rất dễ): trong workbook/worksheet có cái gọi là range ảo, tức là một object range được excel tạo ra trong bộ nhớ. Và vì là ảo cho nên nó thiếu nhiều thuộc tính của range thường (ví dụ offset, address,...). Trên worksheet, bạn dùng ký tự {} để tạo ra cái range này. Đó là cái mà bạn gọi là mảng. { 1, 2, 3, 4 } tương đương với một mảng 4 phần tử. Vì là range cho nên tối đa nó chỉ có tới 2 chiều.

Lợi dụng tính chất range ảo này. Và lợi dụng cách viết tắt của hàm Evaluate, và lợi dụng đặc tính phép gán của range. Ta có thể tạo một mảng và đặt trị khởi đầu của nó như sau:

arr = [ { 1, 2, 3, 4 } ] ==> Dùng hàm evaluate của worksheet, tạo một range ảo với 4 cells 1,2,3,4, copy trị vào arr.

Như vậy, bạn cũng có thể dùng những tính chất này để gán cho mảng 2 chiều. Nhưng lưu ý:
Vì là range cho nên nó chỉ cho phép bạn tối đa 2 chiều. Và vì là phép ép range cho nên mảng được gán có chỉ số đầu tiên là 1.

Phép gán qua range như trên chỉ áp dụng được cho trị hằng, bởi vì range ảo của Excel chỉ có thể dùng trị hằng. Nếu một trong những trị cần gán là biến thì bắt buộc phải dùng hàm Array để gán. Hàm Array nhận tham là mảng tham cho nên chỉ gán được mảng 1 chiều.

Bạn có thể dùng
arr = Array( Array( 1, 2), Array( 3, 4) )
Nhưng kết quả vẫn là mảng 1 chiều, mỗi phần tử của nó là một mảng. Tức là bạn cóp thể dùng arr(1)(1), chứ không thể dùng arr(1,1).

Chú thích:
Việc bạn nói về định nghĩa mảng như thế nào cho đúng lại là việc khác, nếu rảnh tôi sẽ viết trong bài khác. Lưu ý là nếu viết, tôi cũng sẽ thêm ý kiến chứ không bài bác cách định nghĩa của người khác.

Thuộc tính keys của object dictionary lại là một việc khác nữa. Nếu tôi rảnh, tôi sẽ bàn trong bài khác.
 
Upvote 0
mới phát hiện ra vụ này bị lỗi trong VBA
Mã:
Dim Arr()
    [B][COLOR=#ff0000]    Arr = Range("A1:A1") [/COLOR][/B]
trong khi áp dụng code của anh ndu( có chỉnh sửa lại theo ý riêng) chọn các file trung thư mục thì phát hiện ra lỗi sau
nếu chọn nhiều file lưu tên các file vào trong Arr thì không vấn đề gì
nhưng chỉ chọn 1 file để lưu tên vào arr thì nó bị lỗi.
Sau đó test trực tiếp trên mảng thì phất hiện ra như sau

Nếu Arr được gán với vùng có 2 ô trở lên thì ok
mà nếu Arr được gán với vùng có 1 ô thì báo lỗi( cái này mới biết)
 
Upvote 0
mới phát hiện ra vụ này bị lỗi trong VBA
Mã:
Dim Arr()
    [B][COLOR=#ff0000]    Arr = Range("A1:A1") [/COLOR][/B]
trong khi áp dụng code của anh ndu( có chỉnh sửa lại theo ý riêng) chọn các file trung thư mục thì phát hiện ra lỗi sau
nếu chọn nhiều file lưu tên các file vào trong Arr thì không vấn đề gì
nhưng chỉ chọn 1 file để lưu tên vào arr thì nó bị lỗi.
Sau đó test trực tiếp trên mảng thì phất hiện ra như sau

Nếu Arr được gán với vùng có 2 ô trở lên thì ok
mà nếu Arr được gán với vùng có 1 ô thì báo lỗi( cái này mới biết)
Trời ơi, cái này mình nói nhiều trên đây rồi mà! Mảng trên Range luôn luôn phải là 2 cell trở lên!
 
Upvote 0
Những trường hợp đặc biệt này nhiều khi không để ý tới nên không quan tâm dẫn đến không biết là chuyện bình thường mà. Khi nào đụng chuyện rồi mới lòi ra à thì ra nó thế này thế kia.
 
Upvote 0
Những trường hợp đặc biệt này nhiều khi không để ý tới nên không quan tâm dẫn đến không biết là chuyện bình thường mà. Khi nào đụng chuyện rồi mới lòi ra à thì ra nó thế này thế kia.
Cho nên nhờ kinh nghiệm của người này, người kia trên diễn đàn mà mình được học hỏi và có thêm các kinh nghiệm khác đó phihndhsp.
 
Upvote 0
Chào cả nhà,
Tôi cũng mới tập-tành VBA, nên gặp vấn-đề về Array như sau:
- tôi muốn gán giá-trị là công-thức Excel vào mảng dạng R1C1 (như "=RIGHT(RC4,5)") để đưa công thức vào cell của excel.
thì phải làm như thế nào?
Xin cảm ơn cả nhà
 
Upvote 0
Chào cả nhà,
Tôi cũng mới tập-tành VBA, nên gặp vấn-đề về Array như sau:
- tôi muốn gán giá-trị là công-thức Excel vào mảng dạng R1C1 (như "=RIGHT(RC4,5)") để đưa công thức vào cell của excel.
thì phải làm như thế nào?
Xin cảm ơn cả nhà

Mã:
Sub GPE()
    Dim arr(1 To 10)
    arr(1) = "=RIGHT(RC4,5)"
    Range("A3").FormulaR1C1 = arr(1)
End Sub
đoán đại phải như vậy không? dự đoán là hên suôi
 
Upvote 0
Trong VBA nếu tính toán được mảng 3 chiều xong thì làm sao đập dữ liệu từ mảng xuống sheet?

ví dụ như tôi muốn tổng hợp từ nhiều sheet sang 1 sheet, trước kia viết 1 sub có tham số truyền và khi muốn lấy dữ liệu sheet nào thì truyền sheet đó vào là ok, nhưng bây giờ muốn mở rộng thêm để phục vụ công tác giảng dạy nên muốn tìm hiểu thêm

giả sử tôi đã tính toán và đưa dữ liệu vào mảng 3 chiều, vậy làm sao đưa được dữ liệu mảng đó vào trong sheet

nếu mảng 2 chiều thì có câu lệnh, sheet1.range("A1").resize(...)=arr
còn mảng 3 chiều thì làm sao? không bàn đến là duyệt từng phần tử đưa xuống nha, chỉ bàn đến đưa xuống 1 lần thôi

Mã:
Sub GPE()Dim sh As Worksheet
Dim Arr(1 To 10, 1 To 10, 1 To 10)
Arr(1, 1, 1) = 1


For Each sh In Worksheets
    For i = 1 To 10
        For j = 1 To 10
                If (sh.Name <> "TH") Then
                    Arr(sh.Index, i, j) = sh.Cells(i, j)
                End If
         Next
    Next
 Next
[B]......................?[/B]
End Sub
 
Upvote 0
Excel thiết kế 1 range có bao gồm dạng một array 2 chiều. Vì vậy có những method ngầm để chuyển dữ liệu giữa range và mảng 2 chiều.
Mảng 3 chiều còn gọi là quyển (book) 2 chiều đầu là trang (page) và chiều thứ ba là số trang. Điều kiện của quyển là các trang phải có dạng giống nhau. Trong khi đó, các sheets của workbook không bắt buộc phải giống nhau. Vì vậy không thể dùng phép áp (map) trực tiếp được.

Tuy nhiên, với yêu cầu của ban thì cứ dựa theo điều kiện mà làm tới. Bởi vì bạn suy nghĩ theo kiểu mảng 3 chiều cho nên kẹt. Nhưngg nếu bạn suy nghĩ rộng hơn trên quan điểm "đóng tập những tờ giấy khác nhau" thì sẽ có hướng giả quyết. Đại khái bạn có thể thử dùng mảng của mảng; một mảng mà mỗi phần tử của nó là một mảng 2 chiều.
 
Upvote 0
Excel thiết kế 1 range có bao gồm dạng một array 2 chiều. Vì vậy có những method ngầm để chuyển dữ liệu giữa range và mảng 2 chiều.
Mảng 3 chiều còn gọi là quyển (book) 2 chiều đầu là trang (page) và chiều thứ ba là số trang. Điều kiện của quyển là các trang phải có dạng giống nhau. Trong khi đó, các sheets của workbook không bắt buộc phải giống nhau. Vì vậy không thể dùng phép áp (map) trực tiếp được.

Tuy nhiên, với yêu cầu của ban thì cứ dựa theo điều kiện mà làm tới. Bởi vì bạn suy nghĩ theo kiểu mảng 3 chiều cho nên kẹt. Nhưngg nếu bạn suy nghĩ rộng hơn trên quan điểm "đóng tập những tờ giấy khác nhau" thì sẽ có hướng giả quyết. Đại khái bạn có thể thử dùng mảng của mảng; một mảng mà mỗi phần tử của nó là một mảng 2 chiều.

ý anh có phải vậy không? em chỉ muốn biết chính xác là đưa mảng 3 chiều xuống được như mảng 2 chiều không thôi. cái đây là thông qua 1 kiểu định nghĩa mới mà mỗi phần tử của nó là mảng 2 chiều
Mã:
Type Rec
     Book(1 To 1000, 1 To 3) As Variant
End Type
Sub GPE()
Dim sh As Worksheet
Dim Arr() As Rec
Dim dongcuoi As Long
ReDim Arr(1 To 5)
Dim Dem As Byte
Dim i As Long
Dim j As Long
Dim Rng As Range
For Each sh In Worksheets
    If (sh.Name <> "TH") Then
        Dem = Dem + 1
            dongcuoi = sh.Range("A60000").End(xlUp).Row
            Set Rng = sh.Range("A1:C" & dongcuoi)
            For i = 1 To dongcuoi
                For j = 1 To 3
                    Arr(Dem).Book(i, j) = Rng(i, j).Value
                Next
            Next
    End If
Next
For i = 1 To Dem
    Sheet5.Range("A60000").End(xlUp).Offset(1, 0).Resize(UBound(Arr(i).Book, 1), 3) = Arr(i).Book
Next
End Sub
đây là dạng bài tổng hợp số liệu từ nhiều bảng sang 1 bảng tổng hợp, sử lý theo cách đưa dữ liệu từ sheet và mảng 2 chiều,và những mảng 2 chiều đó lại đưa vào mảng một chiều,
bài tập này cũng có cách làm khác là 1 viết sub khuôn mẫu, muốn lấy dữ liệu sheet nào,thì chỉ cần truyền tham số mảng và tham số sheet là được
 

File đính kèm

  • Book1.xlsb
    22.7 KB · Đọc: 35
Lần chỉnh sửa cuối:
Upvote 0
Của bạn hơi rườm rà quá.

Mã:
sub t()
[COLOR=#008000]' demo mảng 3 chiều
[/COLOR]dim quyen()
redim quyen(1 to 3)
dim i as integer
for i = 1 to 3 [COLOR=#008000]' nạp vào mảng, mỗi sheet vào 1 trang[/COLOR]
quyen(i) = sheets(i).Range("A1:F10") [COLOR=#008000]' range gì tuỳ theo bạn tính ra[/COLOR]
next i
[COLOR=#008000]' biến đổi dữ liệu gì đó ở đây[/COLOR]
dim i1 as integer, i2 as integer
for i = 1 to 3 [COLOR=#008000]' duyệt trang[/COLOR]
for i1 = 1 to 10 [COLOR=#008000]' duyệt dòn[/COLOR]g
for i2 = 1 to 6 [COLOR=#008000]' duyệt cột[/COLOR]
quyen(i)(i1,i2) = quyen(i)(i1,i2) + 1
next i2
next i1
Next i
[COLOR=#008000]' chép trở lại[/COLOR]
for i = 1 to 3
sheets(i).Range("A1:C10") = quyen(i)
next i
end sub
 
Upvote 0
e chào cả nhà. E đang tập tành VBA, có 1 vấn đề này nhờ sự giúp đỡ của các bác. E đã tạo 1 Combo Box (Activex Control) khi mình click chuột vào và nhập bất kỳ 1 ký tự nào thì danh sách xổ xuống sẽ chỉ bao gồm những ký tự đó. Nhưng những thao tác đó khi e chạy Record Macro lại không được ghi lại. Tại sao lại nhưu vậy ạ ???
 
Upvote 0
e chào cả nhà. E đang tập tành VBA, có 1 vấn đề này nhờ sự giúp đỡ của các bác. E đã tạo 1 Combo Box (Activex Control) khi mình click chuột vào và nhập bất kỳ 1 ký tự nào thì danh sách xổ xuống sẽ chỉ bao gồm những ký tự đó. Nhưng những thao tác đó khi e chạy Record Macro lại không được ghi lại. Tại sao lại nhưu vậy ạ ???
Hỏi gì thì cũng phải có file chứ bạn?
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom