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,600
Được thích
2,907
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ị
 
Ziận kí rì mà ziận. Có trao đổi mới cùng tiến bộ chứ.
Vấn đề ở trong bài của ndu vừa viết, so với việc "gán xuống sheet phải gán ngang" đó là 2 sự tương tác khác nhau:

- Gán xuống sheet là sự tương tác giữa 2 thế giới 1 chiều và 2 chiều.
- Xử lý Arr, xào nấu chế biến, mắm muối tương cà, đó là sự tương tác giữa thế giới 1 chiều với nhau.

Range của sheet, rõ ràng là 2 chiều. Array là sản phẩm của VBA, anh này thông minh, nên 1 chiều cũng lụm, 2 chiều cũng lụm. Nhưng hễ 1 chiều thì anh í thích "ngang" cơ. Nên lụm về là quất sang 1 chiều cho tụi dân bản địa nó xơi cho nhanh.

Còn khi gán vào Listbox, là sản phẩm của VBA (1 chiều hoặc 2 chiều), bản thân cái listbox là hàng xuất khẩu, đã thiết kế dọc cho người 2 chiều dùng, nên nó lại phải xoay dọc ra trước khi gán.

Code Test3 ở trên, nếu thêm 2 dòng lệnh này sẽ thấy:

PHP:
Sub Test3()
  Dim Arr
  Arr = Array("a", "b", "c")
  Sheet1.ListBox1.List() = Arr
  Range("C1:E1") = Arr
  Range("C2:E2") = ListBox1.List()
End Sub

Arr vẫn cứ ngang, còn Listbox thì vẫn cứ dọc. Vì listbox dùng để tương tác với cư dân 2 chiều. Còn Arr để bọn nó xơi với nhau.

Cáng nói càng thấy khó xơi, nhưng nếu hiểu bản chất thì tốt hơn.

Thôi thì Nó dọc ngang gì kệ nó, nhưng nhớ khi gán xuống sheet thì nó ngang, muốn gán dọc thì transpose.
Hoặc chẳng cần nhớ. Gán xuống thấy sai thì gán lại.
 
Upvote 0
Còn hơi nghi ngờ, Test thử bằng code thứ 2:
PHP:
 	 Sub Test2()
  Dim Arr
  Arr = Sheet1.ListBox1.List
  MsgBox IsArray(Arr)
End Sub
</span> </span>

Kết quả = TRUE???
Vậy là sao?
Từ 1 mảng "dọc" (2 chiều) sau cho vào ListBox, lấy ra kiểm tra nó lại thành "ngang" (1 chiều)

Khúc này ndu chưa test đúng cách. IsArray(Arr) = True đâu thể khẳng định nó 1 chiều, hay là ngang?

Phải Test thế này:

PHP:
Sub test4()
  Dim Arr
  Arr = Sheet1.ListBox1.List
  MsgBox IsArray(Arr)
    Range("C1:E1") = Arr
  Range("C2:E2") = ListBox1.List()
MsgBox Arr(1)

End Sub

Sẽ bị lỗi dòng cuối.

Nếu Arr là mảng ngang, sao gán xuống sheet hàng ngang bị sai?
Nếu Arr là mảng 1 chiều, sao không truy xuất được Arr(1)?

Vậy mà thay câu cuối bằng MsgBox Arr(1, 0) thì OK. Vì Arr là 2 chiều, kính thưa toàn thể đại biểu!
Vì Arr lấy giá trị từ Listbox, nên Listbox cũng 2 chiều, kính thưa toàn thể anh chị em quan viên hai họ!
 
Upvote 0
Nếu Arr là mảng ngang, sao gán xuống sheet hàng ngang bị sai?
Nếu Arr là mảng 1 chiều, sao không truy xuất được Arr(1)?

Vậy mà thay câu cuối bằng MsgBox Arr(1, 0) thì OK. Vì Arr là 2 chiều, kính thưa toàn thể đại biểu!
Vì Arr lấy giá trị từ Listbox, nên Listbox cũng 2 chiều, kính thưa toàn thể anh chị em quan viên hai họ!
Vâng, em sơ suất chổ này nhưng sư phụ test như vậy cũng nói lên rằng: Mảng 1 chiều (mà sư phụ cho là ngang ấy) sau khi đưa vào ListBox thì nó lại biến thành dọc ( 2 chiều) giống y chang trường hợp gán mảng vào Range
Ý em muốn nói rằng: Nếu ta nhìn vào Range trên sheet thì sau khi thí nghiệm ta sẽ cảm giác "Thì ra mảng 1 chiều nó hơi... ngang ngang"... Nhưng nếu lấy ListBox làm thí nghiệm thì ta lại nghĩ ngược lại: "Thì ra mảng 1 chiều nó hơi.. dọc dọc"
Khi nghiên cứu sâu hơn về mảng thì cái thuật ngữ "dọc, ngang" đôi lúc sẽ khiến ta bị rối
Ẹc... Ẹc...
(Ý em chỉ nới về sự mường tượng, sợ rằng "chấp nhận" sẽ khiến ta "ngộ nhận" chứ không phải em không đồng ý với các ý kiến của sư phụ)
--------------------------------------
Nói thêm 1 điều theo kinh nghiệm của em:Để biết mảng có phải 1 chiều hay không, em thường dùng hàm Join để test ---> Nếu báo lỗi thì đấy không phải là mảng 1 chiều
--------------------------------
Cuối cùng em kết nhất chổ này:
Thôi thì Nó dọc ngang gì kệ nó, nhưng nhớ khi gán xuống sheet thì nó ngang, muốn gán dọc thì transpose.
Hoặc chẳng cần nhớ. Gán xuống thấy sai thì gán lại.
Vì khi viết code em cũng từng làm thế
 
Lần chỉnh sửa cuối:
Upvote 0
(Ý em chỉ nới về sự mường tượng, sợ rằng "chấp nhận" sẽ khiến ta "ngộ nhận" chứ không phải em không đồng ý với các ý kiến của sư phụ)

Vậy mường tượng thêm 1 điều, Listbox và những cái tương tự là đồ xuất khẩu cho cư dân 2 chiều xài. Thì dân 1 chiều phải chế tác cho phù hợp con mắt 2 chiều mới bán được.

Còn cứ lấy sản phẩm 1 chiều của nó về xài, thì tự mình phải chế lại.
 
Lần chỉnh sửa cuối:
Upvote 0
Vậy mường tượng thêm 1 điều, Listbox và những cái tương tự là đồ xuất khẩu cho cư dân 2 chiều xài. Thì dân 1 chiều phải chế tác cho phù hợp con mắt 2 chiều mới bán được.
Còn cứ lấy sản phẩm 1 chiều của nó về xài, thì tự mình phải chế lại.
Cảm ơn sư phụ... Để tài rất thú vị!
Vậy sư phụ có dự định viết 1 bài về Array (1 chiều và 2 chiều) không nhỉ? Cũng cơ bản về dễ hiểu giống như bài viết về For.. Next ấy
(Em đã từng nhở bài viết ấy mà nên người)
 
Upvote 0
Hy vọng rằng đây chính là topic đó. Theo cách là ai có thắc mắc cứ vào đây hỏi, ai biết thì cứ trả lời. Mình sẽ sẵn sàng tham gia. Mà đã tham gia rồi đấy thôi? Nói kiểu không gian 1 chiều, 2 chiều, và sinh vật ngoài hành tinh cũng đâu có khó hiểu lắm nhỉ?
 
Upvote 0
Trong mỗi vòng lặp mình đã tạo được bốn mảng con có kích thước bằng nhau là Arr1(1 to n,1); Arr2(1 to n,1); Arr3(1 to n,1) và
Arr4(1to n,1). Mỗi vòng lặp kích thước mảng (giá trị n) khác nhau.
Nhờ các bạn chỉ cho đoạn code:
Trong vòng lặp đó nối dần các mảng con thành:
- Mảng dạng ma trận bốn cột ArrTg(Arr1, Arr2, Arr3, Arr4) số dòng bằng tổng các kích thước của tất cả các lần lặp (xích ma(n)).
- Hoặc nối thành các mảng (bốn mảng) một chiều có cùng kích thước (mình nghĩ cái này khả thi hơn) nhờ các bạn làm cho kiểu này nhé!
 
Lần chỉnh sửa cuối:
Upvote 0
Trong mỗi vòng lặp mình đã tạo được bốn mảng con có kích thước bằng nhau là Arr1(1 to n,1); Arr2(1 to n,1); Arr3(1 to n,1) và
Arr4(1to n,1). Mỗi vòng lặp kích thước mảng (giá trị n) khác nhau.
Nhờ các bạn chỉ cho đoạn code:
Trong vòng lặp đó nối dần các mảng con thành:
- Mảng dạng ma trận bốn cột ArrTg(Arr1, Arr2, Arr3, Arr4) số dòng bằng tổng các kích thước của tất cả các lần lặp (xích ma(n)).
- Hoặc nối thành các mảng (bốn mảng) một chiều có cùng kích thước (mình nghĩ cái này khả thi hơn) nhờ các bạn làm cho kiểu này nhé!
Hổng biết ý anh có phải là gộp 4 mảng ấy thành Arr(1 to n, 1 to 4) không nhỉ? ---> Mảng này nếu gán vào bảng tính thì mỗi cột của nó sẽ đúng = 1 mảng con
Nếu không phải như em suy đoán thì anh cứ đưa ví dụ cụ thế lên đi
 
Upvote 0
Hổng biết ý anh có phải là gộp 4 mảng ấy thành Arr(1 to n, 1 to 4) không nhỉ? ---> Mảng này nếu gán vào bảng tính thì mỗi cột của nó sẽ đúng = 1 mảng con
Nếu không phải như em suy đoán thì anh cứ đưa ví dụ cụ thế lên đi
Tối qua mình làm được rồi,đánh vật với thằng mảng này đau đầu, không dám mang file lên cơ quan (sợ lo mãi mê rồi bỏ việc), để tạo được bốn mảng này phải qua nhiều bước xử lý dữ liệu lằng ngoằng, trong đó có ứng dụng hàm của ndu tại đây. (bài của mình cũng gần giống bài của topic đó, chỉ khác là dữ liệu định mức nằm trên nhiều sheet của một file khác,và mình duyệt toàn bộ mã hiệu của sheet khối lượng một lần, dùng dic, left, right, Ucase ... kiểm tra mã hiệu thuột dạng nào mới lấy định mức của sheet tương ứng (xây lắp, sửa chữa, lắp đặt, khảo sát ...) trong file định mức).
Code đại khái là: (Mình nói thuật toán thôi)

Sub ...

....

For i= 1 to dòng cuối

.....
Arr1 = ... ' Chứa mã hiệu
Arr2 = ... ' Chứa tên công việc, tên vật liệu, nhân công ....
Arr3 = ... ' Chứa đơn vị vật liệu, nhân công...
Arr4 = ... ' Chứa định mức vật liệu, nhân công...

...............'Chuyển các Arr1,2,3,4 thành mảng ngang

For j = 1 to n ' n = chiều dài của Arr1 '(cũng là chiều dài của các Arr2,3,4)

k=h+j

ReDim Preserve ArrTong1(k) = Arr1(j)
ReDim Preserve ArrTong2(k) = Arr2(j)
ReDim Preserve ArrTong3(k) = Arr3(j)
ReDim Preserve ArrTong4(k) = Arr4(j)

Next j

h = k

.......

Next i

.............. ' chuyển các ArrTong thành mảng dọc, gán xuống Range
.............

End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Em có đọc 1 bài của anh LeVanDuyet về mảng mà quen đường dẫn tìm trên diễn đàn mà không thấy trong đó có đoạn code như thế này với range (a1:a10) có giá trị từ 1 đến 10
PHP:
Sub mang1()
Dim mang(1 To 10, 1) As Variant, i As Long
For i = 1 To 10
mang(i, 1) = Cells(i, 1)
Next i
[c1:c10] = mang
End Sub
Theo em đọc chủ đề này là mảng 2 chiều 10 dòng và 1 cột, Nếu mình khải báo mảng mang(1 to 10, 1)sẽ tạo mảng 2 chiều, mà mảng 2 chiều là "mảng dọc" vì vậy để muốn cho [c1:c10] có giá trị giống [a1:a10] thì mình phải dùng vòng lập trên không biết có phải không?
PHP:
Dim mang As Variant
mang = [a1:a10].Value
[C1:C10] = mang
Mà khi em thử với code này vẫn ra kết quả mong muốn, theo em hiểu nếu mình khai mang như đoạn code này thì nó luôn tạo mảng 2 chiều như Thấy Mỹ nói ở bài #5 vậy sao không dùng đoạn code này mà phải dùng đoạn code trên mà kết quả không khác nhau???. Mong ACE trên diễn đàn giải thích giúp em có mơ mơ về mảng không hiểu gì lắm có gì mong ACE bỏ qua.Thanks
 
Upvote 0
Em có đọc 1 bài của anh LeVanDuyet về mảng mà quen đường dẫn tìm trên diễn đàn mà không thấy trong đó có đoạn code như thế này với range (a1:a10) có giá trị từ 1 đến 10
PHP:
Sub mang1()
Dim mang(1 To 10, 1) As Variant, i As Long
For i = 1 To 10
mang(i, 1) = Cells(i, 1)
Next i
[c1:c10] = mang
End Sub
Theo em đọc chủ đề này là mảng 2 chiều 10 dòng và 1 cột, Nếu mình khải báo mảng mang(1 to 10, 1)sẽ tạo mảng 2 chiều, mà mảng 2 chiều là "mảng dọc" vì vậy để muốn cho [c1:c10] có giá trị giống [a1:a10] thì mình phải dùng vòng lập trên không biết có phải không?
PHP:
Dim mang As Variant
mang = [a1:a10].Value
[C1:C10] = mang
Mà khi em thử với code này vẫn ra kết quả mong muốn, theo em hiểu nếu mình khai mang như đoạn code này thì nó luôn tạo mảng 2 chiều như Thấy Mỹ nói ở bài #5 vậy sao không dùng đoạn code này mà phải dùng đoạn code trên mà kết quả không khác nhau???. Mong ACE trên diễn đàn giải thích giúp em có mơ mơ về mảng không hiểu gì lắm có gì mong ACE bỏ qua.Thanks
Đây chỉ là ví dụ thôi, tùy trường hợp cụ thể mà dùng. Trường hợp thứ 2, lấy giá trị từ range này sang range khác thì cần gì vòng lập
Dùng vòng lập chăng là trong quá trình di dời, ta có tính toán hoặc biến đổi gì đó
-------------
Mà hình như code của bạn thiếu cái gì đó
- Một là phải khai báo theo kiểu Dim mang(1 to 10, 1 to 1)
- Hai là: Nếu giữ nguyên kiểu mang(1 to 10, 1) thì trên đầu code phải có dòng Option Base 1
 
Upvote 0
Đây chỉ là ví dụ thôi, tùy trường hợp cụ thể mà dùng. Trường hợp thứ 2, lấy giá trị từ range này sang range khác thì cần gì vòng lập
Dùng vòng lập chăng là trong quá trình di dời, ta có tính toán hoặc biến đổi gì đó
Vậy anh cho em xin 1 ví dụ nho nhỏ để em hiểu thêm về nó hen. Thanks
Mà hình như code của bạn thiếu cái gì đó
- Một là phải khai báo theo kiểu Dim mang(1 to 10, 1 to 1)
- Hai là: Nếu giữ nguyên kiểu mang(1 to 10, 1) thì trên đầu code phải có dòng Option Base 1
Anh nói đoạn code thứ 2 phải không anh, mà sao nó vẫn hiểu nó hay thiệt chứ. Mà chắc mang( 1 to n, 1 to m,...) cái này rất quan trọng phải không anh, vì em thấy nếu khai báo mang (1 to 10) thì nó sẽ là mảng 1 chiều liền??
 
Upvote 0
Ví dụ thế này:
- A1:A10 chứa các số nào đó
- Dùng vòng lập lấy các số lẻ trong A1:A10 và chuyển sang cột C
Đương nhiên ta có tính toán (để biết số nào lẻ) chứ không chuyển nguyên vùng nên buộc phải vòng lập rồi
Em hiểu như thế này có đúng không mảng (Array) sẽ nạp những ô nào là lẽ ở vùng A1:A10 vào trong Array tức là {1,3,5,7,9} với thứ tự này nó sẽ bung ra ở vùng B1:B10 thật ra mình chỉ cần B1:B5 là đủ rồi, mà sao có khi em nạp dữ liệu vào mạng khi bung ra có xuất hiện chữ #N/A là sao anh
PHP:
Sub Test()
  Dim sArray, Arr(), i As Long, j As Long
  sArray = Range("A1:B10").Value
  ReDim Arr(1 To UBound(sArray), 1 To UBound(sArray,2))
  For i = 1 To UBound(sArray)
    If sArray(i, 1) Mod 2 Then
        j = j + 1
      Arr(j, 1) = sArray(i, 1)
      Arr(j, 2) = sArray(i, 2)
   End If
  Next
  Range("C1:D10") = Arr
End Sub
Với đoạn code này em sẽ lấy nhưng số lẽ ở vùng A1:B10 với B1:B10 giá trị từ 11 đến 20 vậy mình có cách nào ngắn hơn hay không anh. Thanks
 
Lần chỉnh sửa cuối:
Upvote 0
Em hiểu như thế này có đúng không mảng (Array) sẽ nạp những ô nào là lẽ ở vùng A1:A10 vào trong Array tức là {1,3,5,7,9} với thứ tự này nó sẽ bung ra ở vùng B1:B10 thật ra mình chỉ cần B1:B5 là đủ rồi, mà sao có khi em nạp dữ liệu vào mạng khi bung ra có xuất hiện chữ #N/A là sao anh
PHP:
Sub Test()
  Dim sArray, Arr(), i As Long, j As Long
  sArray = Range("A1:B10").Value
  ReDim Arr(1 To UBound(sArray), 1 To UBound(sArray,2))
  For i = 1 To UBound(sArray)
    If sArray(i, 1) Mod 2 Then
        j = j + 1
      Arr(j, 1) = sArray(i, 1)
      Arr(j, 2) = sArray(i, 2)
   End If
  Next
  Range("C1:D10") = Arr
End Sub
Với đoạn code này em sẽ lấy nhưng số lẽ ở vùng A1:B10 với B1:B10 giá trị từ 11 đến 20 vậy mình có cách nào ngắn hơn hay không anh. Thanks
Theo tôi thì code dài ngắn mà mình hiểu là OK.
Báo NA là do khai báo ReDim Arr(1 To UBound(sArray), mà UBound(sArray) là 10 trong khi đó ta chỉ lấy sổ lẻ là có 5 thôi.
Vậy code trên sửa lại thế này, mình chi lấy theo j dòng thôi, ie nếu thỏa thì j=j+1.
PHP:
Sub Test() 
  Dim sArray, Arr(), i As Long, j As Long 
  sArray = Range("A1:B10").Value 
  ReDim Arr(1 To UBound(sArray), 1 To UBound(sArray,2)) 
j=0
  For i = 1 To UBound(sArray) 
    If sArray(i, 1) Mod 2 Then 
        j = j + 1 
      Arr(j, 1) = sArray(i, 1) 
      Arr(j, 2) = sArray(i, 2) 
   End If 
  Next 
  Range("C1").resize(j,2) = Arr 
End Sub
 
Upvote 0
Em hiểu như thế này có đúng không mảng (Array) sẽ nạp những ô nào là lẽ ở vùng A1:A10 vào trong Array tức là {1,3,5,7,9} với thứ tự này nó sẽ bung ra ở vùng B1:B10 thật ra mình chỉ cần B1:B5 là đủ rồi, mà sao có khi em nạp dữ liệu vào mạng khi bung ra có xuất hiện chữ #N/A là sao anh

Với đoạn code này em sẽ lấy nhưng số lẽ ở vùng A1:B10 với B1:B10 giá trị từ 11 đến 20 vậy mình có cách nào ngắn hơn hay không anh. Thanks

Với cả 2 thí dụ trên, ta đã biết trước trong 10 ô có 5 số lẻ, trong 20 ô có 10 số lẻ.
Thực chất ta không biết trước chuyện này, nên vẫn phải khai báo mảng với kích thước tối thiểu bằng với mảng gốc.
Ngoài ra, số số lẻ trong cột A chưa chắc bằng số số lẻ cột B, và chưa chắc nó nằm ngang hàng. Nếu cho 1 vùng số bất kỳ thì không thể dùng code trên mà phải 2 vòng lặp: 1 cho cột và 1 cho dòng.

Nếu dùng Scripting Dictionary ta sẽ giới hạn được phần nào mảng dư kích thước, nhưng đó lại là chuyên đề khác.
 
Lần chỉnh sửa cuối:
Upvote 0
Thay đổi kích thước mảng 2 chiều

Nhân tiện có bài này cho các bạn thực hành về mảng 2 chiều: Hãy xây dựng 1 hàm Resize2DArray từ 1 mảng 2 chiều cho trước theo cú pháp sau:
PHP:
Function Resize2DArray(ByVal sArray, ByVal rowSize As Long, ByVal colSize As Long)
Mảng kết quả sẽ có kích thước chiều 1 = rowSize và kích thước chiều 2 = colSize (lấy chuẩn Base 1)
Nếu kích thước mảng kết quả > kịch thước mảng cho trước thì những phần tử thừa sẽ cho = Blank (Blank <==> Blank cell, không phải "" nha)
Cuối cùng khi đã có hàm Resize2DArray rồi, ta sẽ viết code thực thi theo dạng như sau:
PHP:
Sub Test()
 Dim sArray, Arr
 sArray = Range("A1:C20").Value
 Arr = Resize2DArray(sArray, 30, 6)
 Range("H1:M30").Value = Arr
End Sub
Thử xem, không khó lắm đâu
 
Upvote 0
Nhân tiện có bài này cho các bạn thực hành về mảng 2 chiều: Hãy xây dựng 1 hàm Resize2DArray từ 1 mảng 2 chiều cho trước theo cú pháp sau:
PHP:
Function Resize2DArray(ByVal sArray, ByVal rowSize As Long, ByVal colSize As Long)
Mảng kết quả sẽ có kích thước chiều 1 = rowSize và kích thước chiều 2 = colSize (lấy chuẩn Base 1)
Nếu kích thước mảng kết quả > kịch thước mảng cho trước thì những phần tử thừa sẽ cho = Blank (Blank <==> Blank cell, không phải "" nha)
Cuối cùng khi đã có hàm Resize2DArray rồi, ta sẽ viết code thực thi theo dạng như sau:
PHP:
Sub Test()
 Dim sArray, Arr
 sArray = Range("A1:C20").Value
 Arr = Resize2DArray(sArray, 30, 6)
 Range("H1:M30").Value = Arr
End Sub
Thử xem, không khó lắm đâu
Mấy anh tham gia vô đi để em học hỏi với về function kể như là em mù bị knockout rồi, chắc chủ nhật này phải lên HCM để mua sách học rồi tại vì lần trước lặn lội từ dưới quê lên mua mà hết sách buồn quá !$@!!!$@!!
 
Upvote 0
Code Test1 trong bài #29 của ndu đọc Mảng ban đầu lấy số lẻ xong phân phối cho mảng kết quả theo thứ tự ưu tiên hàng ngang trước, dọc sau.

Xin giới thiệu code Test2, lấy số lẻ xong, của cột nào để nguyên cột đó:

PHP:
Sub Test2()
  Dim sArray, Arr(), i As Long, j As Long, iR1 As Long, iR2
  sArray = Range("A2:B11").Value
  ReDim Arr(1 To UBound(sArray), 1 To UBound(sArray, 2))
  For i = 1 To UBound(sArray, 1)
    For j = 1 To UBound(sArray, 2)
      If sArray(i, j) Mod 2 Then
        Arr(IIf(j = 1, iR1, iR2) + 1, j) = sArray(i, j)
        If j = 1 Then
            iR1 = iR1 + 1
        Else
            iR2 = iR2 + 1
        End If
     End If
    Next
  Next
  Range("E2:F11") = Arr
End Sub
Và giới thiệu luôn Code Test3, lấy số lẻ 2 cột và sắp lại dồn thành 1 cột.

PHP:
Sub test3()
  Dim sArray, Arr(), i As Long, j As Long, iR As Long
  sArray = Range("A2:B11").Value
  ReDim Arr(1 To UBound(sArray) * UBound(sArray, 2), 1 To 1)
For j = 1 To UBound(sArray, 2)
    For i = 1 To UBound(sArray, 1)
      If sArray(i, j) Mod 2 Then
      Arr(iR + 1, 1) = sArray(i, j)
      iR = iR + 1
        End If
    Next
  Next
  Range("G2:G" & iR + 1) = Arr
      
End Sub
Nếu để ý, sẽ thấy code Test3 For theo cột nằm ngoài, For theo dòng nằm trong.
Nếu đảo lại For theo cột nằm trong, ta sẽ có kết quả khác (Sub Test4)

Coi như đây là 1 số thí dụ về những cách sử dụng Array 1 cách linh hoạt cho những yêu cầu khác nhau.
 

File đính kèm

  • ArrayLocLe.xls
    36.5 KB · Đọc: 339
Lần chỉnh sửa cuối:
Upvote 0
Đề bài Thay đổi kích thước mảng 2 chiều (bài #30) của ndu sửa lại 1 chút cho phù hợp với thực tế:

Cho 1 vùng dữ liệu cho trước m dòng và n cột, do m quá lớn, sắp xếp lại thành vùng dữ liệu mới có số cột nhiều hơn, để cho số dòng ít lại.
Hoặc nếu nhiều cột quá và muốn sắp xếp gọn lại ít cột hơn, số dòng sẽ nhiều hơn.

Thường thì với vùng dữ liệu ban đầu bất kỳ, khi sắp xếp lại ta chỉ biết rằng ta muốn 5 cột, 10 cột, chứ số dòng không muốn tính trước hoặc tính nhẩm không đúng. Để máy nó tính cho khoẻ.

Vậy Function chỉ có 2 tham số như sau:
PHP:
Function resizeArr(ByVal SourceArr, ByVal NewC As Long)
Dim OldR As Long, OldC As Long, NewR As Long, iR As Long, iC As Long
Dim ArrKQ, iKQ, jKQ
iKQ = 1: jKQ = 1
OldR = UBound(SourceArr, 1)
OldC = UBound(SourceArr, 2)
NewR = Int(OldR * OldC / NewC) 
If (OldR * OldC) Mod NewC > 0 Then NewR = NewR + 1
ReDim ArrKQ(1 To NewR, 1 To NewC)
For iC = 1 To OldC
    For iR = 1 To OldR
        ArrKQ(iKQ, jKQ) = SourceArr(iR, iC)
        iKQ = iKQ + 1
        If iKQ > NewR Then iKQ = 1: jKQ = jKQ + 1
    Next
Next
resizeArr = ArrKQ
End Function
Ghi chú:
Kết quả đang sắp xếp dọc trước, ngang sau. Nếu muốn thay đổi ngang trước dọc sau thì thay
PHP:
        iKQ = iKQ + 1
        If iKQ > NewR Then iKQ = 1: jKQ = jKQ + 1
bằng

PHP:
        jKQ = jKQ + 1
        If jKQ > NewC Then jKQ = 1: iKQ = iKQ + 1
Và dĩ nhiên, ta có thể chọn số cột ít hơn số cột ban đầu, số dòng sẽ tự tính lại để sắp xếp.
 

File đính kèm

  • ResizeArr.xls
    35.5 KB · Đọc: 178
Lần chỉnh sửa cuối:
Upvote 0
Đề bài Thay đổi kích thước mảng 2 chiều (bài #30) của ndu sửa lại 1 chút cho phù hợp với thực tế:

Cho 1 vùng dữ liệu cho trước m dòng và n cột, do m quá lớn, sắp xếp lại thành vùng dữ liệu mới có số cột nhiều hơn, để cho số dòng ít lại.
Hoặc nếu nhiều cột quá và muốn sắp xếp gọn lại ít cột hơn, số dòng sẽ nhiều hơn.

Thường thì với vùng dữ liệu ban đầu bất kỳ, khi sắp xếp lại ta chỉ biết rằng ta muốn 5 cột, 10 cột, chứ số dòng không muốn tính trước hoặc tính nhẩm không đúng. Để máy nó tính cho khoẻ.

Vậy Function chỉ có 2 tham số như sau:
PHP:
Function resizeArr(ByVal SourceArr, ByVal NewC As Long)
Dim OldR As Long, OldC As Long, NewR As Long, iR As Long, iC As Long
Dim ArrKQ, iKQ, jKQ
iKQ = 1: jKQ = 1
OldR = UBound(SourceArr, 1)
OldC = UBound(SourceArr, 2)
NewR = Int(OldR * OldC / NewC) 
If (OldR * OldC) Mod NewC > 0 Then NewR = NewR + 1
ReDim ArrKQ(1 To NewR, 1 To NewC)
For iC = 1 To OldC
    For iR = 1 To OldR
        ArrKQ(iKQ, jKQ) = SourceArr(iR, iC)
        iKQ = iKQ + 1
        If iKQ > NewR Then iKQ = 1: jKQ = jKQ + 1
    Next
Next
resizeArr = ArrKQ
End Function
Ghi chú:
Kết quả đang sắp xếp dọc trước, ngang sau. Nếu muốn thay đổi ngang trước dọc sau thì thay
PHP:
        iKQ = iKQ + 1
        If iKQ > NewR Then iKQ = 1: jKQ = jKQ + 1
bằng

PHP:
        jKQ = jKQ + 1
        If jKQ > NewC Then jKQ = 1: iKQ = iKQ + 1
Và dĩ nhiên, ta có thể chọn số cột ít hơn số cột ban đầu, số dòng sẽ tự tính lại để sắp xếp.
Em mới test sơ qua, code của sư phụ không thể gõ trực tiếp trên bảng tính được. Nó toàn lỗi #VALUE!
----------------
Nói thêm là em muốn xây dựng hàm Resize Array này sao cho nó hoạt động y chang như Resize Property của VBA. Lý do vì thông thường khi tạo mảng ta dùng ReDim Preserve chỉ có thể thay đổi kích thước chiều thứ hai mà chẳng thể làm gì được đối với chiều thứ nhất (trong khi chiều thứ nhất này mới là chiều mà mọi người quan tâm)... Còn cái mà sư phụ đang làm thì có vẽ không giống như ý nghĩa của Resize lắm
Ẹc... Ẹc...
----------------
Xong món này ta sẽ xử tiếp món Office Array
 
Upvote 0
Web KT
Back
Top Bottom