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

  • Thread starter Thread starter viehoai
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

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ị
 
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ị
Như thế này nè bạn
PHP:
Dim Arr As Variant
Arr = [A1:A10].Value
 
Upvote 0
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ị

Có lẽ nên hỏi lại cho rõ là "gán giá trị của các cells từ A1:A10 các phần tử của Mãng Arr" có nghĩa là:
- Gán các giá trị của Cells từ A1 đến A10 vào 1 mảng Arr
- Gán các giá trị của Cells từ A1 đến A10 từ/ bằng 1 mảng Arr

Eo ôi, tiếng Việt!
 
Upvote 0
Có lẽ nên hỏi lại cho rõ là "gán giá trị của các cells từ A1:A10 các phần tử của Mãng Arr" có nghĩa là:
- Gán các giá trị của Cells từ A1 đến A10 vào 1 mảng Arr
- Gán các giá trị của Cells từ A1 đến A10 từ 1 mảng Arr

Eo ôi, tiếng Việt!
Dạ ý em là
PHP:
Gán các giá trị của Cells từ A1 đến A10 vào 1 mảng Arr
Em làm theo cách của anh huuthang_bd đã được nhưng sao em thử thí nghiệm xuất một phẩn tử theo dạng:
1. Arr(i) thì báo lỗi
2. Arr(i,1) cho kết quả giá trị của phần tử thứ i
3. Arr(1,i) thì báo lỗi
Em đang tự học về Mãng, xin các anh chị giải thích thêm. Xin cảm ơn
 
Upvote 0
Arr(i, j) là phần tử của mảng tại dòng i, cột j của mảng
Do khai báo Dim Arr As variant và không khai báo chiều, nên mặc định Arr là mảng 2 chiều
A1:A10 là mảng dọc, không có nghĩa là mảng 1 chiều, đó là mảng 2 chiều: 1 chiều 10 dòng và 1 chiều 1 cột.

Muốn khai báo mảng 1 chiều thì khai báo
Dim Arr As variant
Redim Arr(10)
Nhưng lúc này mặc định mảng 1 chiều lại là mảng ngang.
Và muốn cho là mảng 1 chiều thực sự, thì không được gán giá trị 1 lần cho nó bằng 1 range trong bảng tính.

Túm lại, mảng dọc bắt buộc là mảng 2 chiều. Mảng ngang thì tuỳ theo cách gán giá trị, gán bằng range trên sheet thì 2 chiều.

Thí dụ 2 sub sau:

PHP:
Sub Test1()
Dim Arr As Variant
ReDim Arr(1 To 10)
Arr = Range("A1:J1").Value
MsgBox Arr(4)
End Sub
PHP:
Sub Test2()
Dim Arr As Variant
ReDim Arr(1 To 10)
For i = 1 To 10
Arr(i) = Cells(1, i)
Next
MsgBox Arr(4)
End Sub
Test1 sẽ bị lỗi. Mà phải sửa thành MsgBox Arr(1, 4)
 
Lần chỉnh sửa cuối:
Upvote 0
Arr(i, j) là phần tử của mảng tại dòng i, cột j của mảng
Do khai báo Dim Arr As variant và không khai báo chiều, nên mặc định Arr là mảng 2 chiều
A1:A10 là mảng dọc, không có nghĩa là mảng 1 chiều, đó là mảng 10 dòng 1 cột.

Muốn khai báo mảng 1 chiều thì khai báo
Dim Arr As variant
Redim Arr(10)
Nhưng lúc này mặc định mảng 1 chiều lại là mảng ngang.

Túm lại, mảng dọc bắt buộc là mảng 2 chiều.
Xin anh giải thích thêm
1. Thế trường hợp Mãng 1 chiều là mãng ngang với các phần tử là giá trị từ A1 đến A10 không được hả anh ?
2. Như trên anh khái báo
PHP:
Dim Arr As variant
Redim Arr(10)
Không khai báo luôn
PHP:
Dim Arr(10)
Mà phải Redim ?
Cảm ơn anh nhiều
 
Upvote 0
Xin anh giải thích thêm
1. Thế trường hợp Mãng 1 chiều là mãng ngang với các phần tử là giá trị từ A1 đến A10 không được hả anh ?
2. Không khai báo luôn Dim Arr(10)Mà phải Redim
1. Mảng ngang với các giá trị từ A1 đến A10: Được, gán từng giá trị một.:

Nhưng vẫn là ngang nhé, nên nếu gán ngược xuống sheet thì phải coi chừng quên.

PHP:
Sub Test3 ()
Dim Arr(1 to 10)
For i = 1 to 10
Arr(i) = Cells(i, 1)
Next
Range("B1:B10") = Arr
Range("C5:L5") = Arr
End Sub
Ta sẽ thấy B1:B10 cả 10 ô có cùng giá trị của A1. trong khi đó C5:L5 hiện đầy đủ theo hàng ngang.

2. Khai báo Arr(10) hay Khai báo Arr rồi ReDim Arr(10):

Tác dụng giống nhau. Nhưng Redim có cái lợi hơn vì cứ khai báo mảng khi kích thước mảng chưa biết. Sau đó tính toán kích thước xong mới ReDim lại.

3. Ghi chú:
Mặc định phần tử đầu của mảng đánh số 0, nên Arr(10) sẽ có 11 phần tử từ 0 đến 10. Và khi gán Cell(i, j) cho phần tử, sẽ bị lỗi vì không có cells(0,j) hoặc cells(i, 0)
Có 2 cách để cho Arr bắt đầu bằng 1:

- Dùng câu lệnh Option Base 1 trên đầu module
- Khai báo Arr(1 to 10), hoặc Arr(1 to 10, 1 to 1)
 
Upvote 0
Xin anh giải thích thêm
1. Thế trường hợp Mãng 1 chiều là mãng ngang với các phần tử là giá trị từ A1 đến A10 không được hả anh ?
2. Như trên anh khái báo
PHP:
Dim Arr As variant
Redim Arr(10)
Không khai báo luôn
PHP:
Dim Arr(10)
Mà phải Redim ?
Cảm ơn anh nhiều
Ban chỉ cần nhớ điều này:
- Range và mảng không giống nhau
- 1 Range sau khi biến đổi thành mảng thì đó luôn là mảng 2 chiều
- Muốn biến thành mảng 1 chiều phải thêm các công đoạn khác, chẳng hạn dùng For... Next hoặc hàm TRANSPOSE
-----------
Hiểu thế là mọi chuyện êm xuôi
 
Upvote 0
Ban chỉ cần nhớ điều này:
- Range và mảng không giống nhau
- 1 Range sau khi biến đổi thành mảng thì đó luôn là mảng 2 chiều
- Muốn biến thành mảng 1 chiều phải thêm các công đoạn khác, chẳng hạn dùng For... Next hoặc hàm TRANSPOSE
-----------
Hiểu thế là mọi chuyện êm xuôi
3 ý trên em hiểu sâu được vấn đề hơn. Trường hợp "Muốn biến thành mảng 1 chiều phải thêm các công đoạn khác, chẳng hạn dùng For... Next hoặc hàm TRANSPOSE" em hiểu được nhưng cách làm theo Transpost thì chưa biết, xin Sư phụ cho ví dụ.
Cảm ơn Sư phụ và Thầy Mỹ
 
Upvote 0
3 ý trên em hiểu sâu được vấn đề hơn. Trường hợp "Muốn biến thành mảng 1 chiều phải thêm các công đoạn khác, chẳng hạn dùng For... Next hoặc hàm TRANSPOSE" em hiểu được nhưng cách làm theo Transpost thì chưa biết, xin Sư phụ cho ví dụ.
Cảm ơn Sư phụ và Thầy Mỹ
Ví dụ thế này:
- Bạn có dữ liệu tại A1:A10
- Bạn muốn nối chuổi từ các cell ở vùng trên
- Bạn nghĩ ra có thể dùng làm Join để làm điều này
- Nhưng hàm Join chỉ làm việc với mảng 1 chiều
- Vậy việc của bạn phải biến Range("A1:A10") thành 1 mảng và phải là mảng 1 chiều
Ta làm như sau:
PHP:
Sub Test()
  Dim Arr
  Arr = Range("A1:A10").Value
  Arr = WorksheetFunction.Transpose(Arr)
  Range("B1") = Join(Arr, ", ")
End Sub
Rút gọn:
PHP:
Sub Test()
  Dim Arr
  Arr = WorksheetFunction.Transpose(Range("A1:A10"))
  Range("B1") = Join(Arr, ", ")
End Sub
Rút gọn tiếp:
PHP:
Sub Test()
  Range("B1") = Join(WorksheetFunction.Transpose(Range("A1:A10")), ", ")
End Sub
Tóm lại:
- Với 1 Range là 1 vùng có nhiều dòng, 1 cột thì khi qua hàm TRANSPOSE nó sẽ biến thành mảng 1 chiều
- Với 1 Range là 1 vùng có nhiều cột, 1 dòng thì khi qua hàm TRANSPOSE nó sẽ biến thành mảng 2 chiều (có thể mường tượng là mảng dọc) ---> Lại qua hàm TRANSPOSE tiếp lần nữa, nó sẽ biến thành mảng 1 chiều
Ví dụ: Nối chuổi các cell trong vùng A1:J1
PHP:
Sub Test()
  With WorksheetFunction
    Range("A2") = Join(.Transpose(.Transpose(Range("A1:J1"))), ", ")
  End With
End Sub
Phải 2 lần TRANSPOSE mới có thể biến Range("A1:J1") thành mảng 1 chiều
-------------
Nói thêm:
- Đã gọi là mảng 1 chiều thì không mường tượng nó là DỌC NGANG gì cả... đơn giàn là MẢNG 1 CHIỀU thôi
- Mảng 1 chiều và 2 chiều có thể mường tượng chúng khác nhau như khi so sánh ĐƯỜNG THẰNG và MẶT PHẲNG vậy (đường thẳng chỉ có duy nhất chiều dài, còn mặt phẳng thì mới có 2 chiều DỌC, NGANG)
 
Lần chỉnh sửa cuối:
Upvote 1
Nói thêm:
- Đã gọi là mảng 1 chiều thì không mường tượng nó là DỌC NGANG gì cả... đơn giàn là MẢNG 1 CHIỀU thôi
- Mảng 1 chiều và 2 chiều có thể mường tượng chúng khác nhau như khi so sánh ĐƯỜNG THẰNG và MẶT PHẲNG vậy (đường thẳng chỉ có duy nhất chiều dài, còn mặt phẳng thì mới có 2 chiều DỌC, NGANG)

Dẫu rằng nói 1 chiều thì không có dọc ngang, tựa như đường thẳng, và khác với mặt phẳng. Nhưng đó là xét theo hệ quy chiếu là đứng trong không gian 1 chiều và đang chỉ nhận thức được 1 chiều.

Giả sử tồn tại 1 thế giới mà sinh vật ở đó chỉ nhận thức được 1 chiều trong không gian, thì khi 1 vật thể di chuyển dọc theo đường thẳng, anh ta sẽ trông thấy sự dịch chuyển. Nếu 1 sinh vật ở hành tinh khác đến và nhận thức được không gian 2 chiều, anh ta đi ra khỏi đường thẳng vào chiều thứ 2. Vậy sinh vật tại đó sẽ nghĩ gì? Nó cho rằng sinh vật lạ đã biến mất.
Còn đối với sinh vật ở hành tinh khác đến, thì nghĩ: tao đâu có biến mất, mày chỉ đi được theo chiều X của tao, còn tao đi 2 hướng, vừa X vừa Y.
(Suy luận tương tự giữa không gian 2 chiều, 3 chiều, và n chiều)

Và khi sinh vật lạ này kể cho đồng hương của nó nghe, nó sẽ kể: Tụi nó chỉ đi ngang hông à, hông có ra khỏi cái đường thẳng đó được.

Chữ ngang để làm chi? để vẽ ra cho đồng hương nó hiểu.

Tưởng tượng xong, quay về Array. Array 1 chiều mà gán xuống sheet (bảng 2 chiều), thì phải gán ngang. Gán dọc là sai.
Nên
vẫn phải
hình dung
mảng 1 chiều

mảng
ngang!

Vì ta là thành viên GPE, thế giới GPE là thế giới bảng tính có ít nhất 2 chiều, và ta là sinh vật nhận thức được n chiều.
 
Lần chỉnh sửa cuối:
Upvote 0
Chữ ngang để làm chi? để vẽ ra cho đồng hương nó hiểu.
Tưởng tượng xong, quay về Array. Array 1 chiều mà gán xuống sheet (bảng 2 chiều), thì phải gán ngang. Gán dọc là sai.
Dạ, cái này em biết nhưng nhiều lúc em sợ rằng mường tượng nhiều quá sẽ dẫn đến ngộ nhận
Giống như trường hợp Add List cho 1 ListBox
- Em có dữ liệu tại A1:A3
- Muốn muốn Add dữ liệu này vào ListBox1
- Mường tượng rằng ListBox được xếp theo chiều dọc, mà thằng A1:A3 cũng đang dọc, vậy thì cứ Add thoải mái
PHP:
Sub Test1()
  Sheet1.ListBox1.List() = Range("A1:A3").Value
End Sub
Test thử thấy OK
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
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)
???
Test tiếp 1 sub khác:
PHP:
Sub Test3()
  Dim Arr
  Arr = Array("a", "b", "c")
  Sheet1.ListBox1.List() = Arr
End Sub
Arr đương nhiên là mảng 1 chiều, và nó "ngang" theo cách nói của sư phụ, vậy mà vẫn Add vào ListBox được bình thường
Đồng ý rằng có sự "biến đổi" gì đó trong quá trình Add List nhưng nếu ngay từ đầu mình quá tin vào cái vụ "ngang" này thì không khỏi có lúc bị lúng túng (em đã từng bị vậy)
Cũng giống như trường hợp mảng 1 chiều khi gán vào Sheet thì phải gán theo chiều ngang, nhưng khi lấy dữ liệu "ngang" ấy từ sheet để biến nó thành mảng thì mảng ấy lại vẫn cứ... 2 chiều (chẳng làm cách nào cho nó "ngang" được nếu không thông qua quá trình biến đổi)
Thôi thì ngay từ đầu khẳng định rằng mảng 1 chiều không "ngang, dọc" gì cả... Có "ngang" chăng là do ta tự mường tượng ra cho phù hợp với những suy luận của riêng ta mà thôi
Ẹc... Ẹc...
(Mong sư phụ đừng giận em phản biện, vì đàng nào thì mấy cái Array này cũng do sư phụ dạy em)
 
Lần chỉnh sửa cuối:
Upvote 0
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ậy anh cho em xin 1 ví dụ nho nhỏ để em hiểu thêm về nó hen. Thanks
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
PHP:
Sub Test()
  Dim sArray, Arr(), i As Long, j As Long
  sArray = Range("A1:A10").Value
  ReDim Arr(1 To UBound(sArray), 1 To 1)
  For i = 1 To UBound(sArray)
    If sArray(i, 1) Mod 2 Then
       j = j + 1
      Arr(j, 1) = sArray(i, 1)
    End If
  Next
  Range("C1:C10") = Arr
End Sub


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??
Chú ý rằng mang( 1 to n, 1 to m) khác với mang(n, m) ---> Cái đầu thì vị trí phần tử đầu tiên được tính từ 1, còn cái sau, vị trí của phần tử đầu tiên được tính từ 0. Vậy mang(n, m) <===> mang(0 to n, 0 to m)
Có những mảng mà ta không khống chế được chỉ số của phần tử đầu tiên. Ví dụ:
- Mảng lấy từ 1 list của ListBox, ComboBox thì phần tử đầu tiên luôn bắt đầu bằng 0
- Mảng lấy từ Range thì phần tử đầu tiên luôn bắt đầu từ 1

Tóm lại: Chỉ có thể khống chế được chỉ số của phần tử đầu tiên đối với những mảng do chính ta tạo ra
 
Upvote 1
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
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
Code vậy là được rồi. Có điều A1:B10 đang bố trí có trật tự nên bạn chỉ dùng 1 vòng lập (bạn ngầm hiểu rằng nếu cột 1 là số lẻ thì cột 2 cũng là số lẻ). Trong trường hợp A1:B10 chứa số tùy ý và không theo trật tự nào thì bạn buộc phải dùng 2 vòng lập (duyệt từ trên xuống và từ trái qua phải)
PHP:
Sub Test1()
  Dim sArray, Arr(), i As Long, j As Long, iR As Long
  sArray = Range("A1:B10").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(Int(iR / 2) + 1, (iR Mod 2) + 1) = sArray(i, j)
        iR = iR + 1
     End If
    Next
  Next
  Range("C1:D10") = Arr
End Sub
Thử xem!
 
Lần chỉnh sửa cuối:
Upvote 1
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

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

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
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!
Gõ kí rì trên bảng tính? Có phải gõ =resizeArr(A2:C21, 7) hông?
Lỗi value hiện ra ở vùng kết quả hả? Đúng rồi!

Code này làm theo yêu cầu bài 30, với 1 Function đầu vào là Array, đầu ra cũng Array, kèm theo 1 Sub lấy Array nguồn từ bảng tính đấy chứ?
Nếu muốn lấy Array nguồn trực tiếp từ bảng tính (nghĩa là đầu vào có thể là Range) thì phải viết khác chứ? Đâu cần Sub nữa?

Cũng dễ thôi, chỉ cần thêm vào 1 câu:

SArr = SourceArr

và sửa câu:

ArrKQ(iKQ, jKQ) = SourceArr(iR, iC)

thành

ArrKQ(iKQ, jKQ) = SArr(iR, iC)

và không cần sub siếc, sub siếc để khi nào không muốn dùng công thức trên bảng tính mới dùng đến.

Bây giờ có thể thoải mái gõ: =resizeArr(A2:C21, 7), Ctrl Shift Enter
Đồng thời có thể truy xuất = Index(resizeArr(A2:C21, 7), 3, 6)
Sub siếc để nguyên và vẫn có thể chạy như cũ.

À hiểu rồi: câu này:
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
phải phối hợp với câu này mới hiểu: (cha mẹ ơi, hôm nay nói 1 câu, sang hôm sau mới nói tiếp 1 câu)
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
Nghĩa là không sắp xếp dữ liệu lại gì cả! ArrKQ(i, j) = SArr(i, j) (câu này chắc sang năm mới nói!)

Thôi, coi như bài tập mới, mai làm!
Mà Resize(m, n) của VBA liên quan gì đến gõ trên sheet hè?
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0

Mà Resize(m, n) của VBA liên quan gì đến gõ trên sheet hè?
Đúng ra hàm này dùng trong VBA là chính, nhưng em vẫn muốn mọi thứ được mở rộng theo hướng tổng quát nhất: Có thể hoạt động với Range, có thể hoạt động với Array (kể cả Array do công thức trả về) và có thể gõ được trên sheet
Ẹc... Ẹc...
 
Upvote 0
Đúng ra hàm này dùng trong VBA là chính, nhưng em vẫn muốn mọi thứ được mở rộng theo hướng tổng quát nhất: Có thể hoạt động với Range, có thể hoạt động với Array (kể cả Array do công thức trả về) và có thể gõ được trên sheet
Ẹc... Ẹc...

Bài trên bài trên (ẹc, mới gộp 2 bài), đã sửa để có thể lấy Range từ bảng tính, và đã có thể quánh công thức xuống bảng tính rồi đó.

Còn nếu chỉ đơn thuần là Resize như VBA, thì càng dễ hơn, chỉ cần gán ArrKQ (i, j) = sArr(i, j), với
i chạy từ 1 đến min(số dòng ArrKQ, số dòng sArr)
j chạy từ 1 đến Min(số cột ArrKQ, số cột sArr)

2 vòng lặp, khỏi If iếc. Nhường lại cho nmhung49 làm. Khà khà.
 
Upvote 0
Bài trên bài trên (ẹc, mới gộp 2 bài), đã sửa để có thể lấy Range từ bảng tính, và đã có thể quánh công thức xuống bảng tính rồi đó.

Còn nếu chỉ đơn thuần là Resize như VBA, thì càng dễ hơn, chỉ cần gán ArrKQ (i, j) = sArr(i, j), với
i chạy từ 1 đến min(số dòng ArrKQ, số dòng sArr)
j chạy từ 1 đến Min(số cột ArrKQ, số cột sArr)

2 vòng lặp, khỏi If iếc. Nhường lại cho nmhung49 làm. Khà khà.
Nhưng cái này mới hay nè sư phụ:
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
Tức: Yêu cầu số dòng, số cột của mảng kết quả là bao nhiêu thì ta cứ giữ nguyên, và số phần tử thừa nếu có sẽ cho = Blank (không phải là chuổi rổng)
 
Upvote 0
Bài trên bài trên (ẹc, mới gộp 2 bài), đã sửa để có thể lấy Range từ bảng tính, và đã có thể quánh công thức xuống bảng tính rồi đó.

Còn nếu chỉ đơn thuần là Resize như VBA, thì càng dễ hơn, chỉ cần gán ArrKQ (i, j) = sArr(i, j), với
i chạy từ 1 đến min(số dòng ArrKQ, số dòng sArr)
j chạy từ 1 đến Min(số cột ArrKQ, số cột sArr)

2 vòng lặp, khỏi If iếc. Nhường lại cho nmhung49 làm. Khà khà.
Dạ em đâu có khả năng tới đó đâu Thầy ơi. Em nghe rằng mảng luôn cho tốc độ thuộc dạng khủng nhất nên em thử với dữ liệu 800.000 dòng để so sánh dùng Filter lọc dữ liệu mình cần thì thấy nó chậm kinh khủng mà trong khi đó mảng làm việc với tốc độ chống mặt mà sao dữ liệu bị biến đổi thành số mà không còn là dạng text nữa. Mà sao em lọc rồi copy bị báo lỗi "Microsoft office excel cannot create or use the data range reference because it is too complex" Không biết máy em có bị gì không mong anh chị test giúp em Thanks. Em tìm trên mạng thì trang này nó nói rằng http://www.mrexcel.com/forum/showthread.php?t=550686
 

File đính kèm

Upvote 0
Dạ em đâu có khả năng tới đó đâu Thầy ơi. Em nghe rằng mảng luôn cho tốc độ thuộc dạng khủng nhất nên em thử với dữ liệu 800.000 dòng để so sánh dùng Filter lọc dữ liệu mình cần thì thấy nó chậm kinh khủng mà trong khi đó mảng làm việc với tốc độ chống mặt mà sao dữ liệu bị biến đổi thành số mà không còn là dạng text nữa
Code của bạn chưa phải là mảng. Đoạn này If Cells(li, 1).Value = "111250000125" Then vẫn xem như chưa "thoát ly" khỏi Range đâu (vì phải dựa vào Cells(li, 1) ). Vì thế tốc độ vẫn chậm
Tôi sửa lại như sau:
PHP:
Sub hocmang()
  Dim Arr() As String, sArray, li As Long, lj As Long
  sArray = Range("A1:A808945").Value
  ReDim Arr(1 To UBound(sArray, 1), 1 To UBound(sArray, 2))
  For li = 1 To UBound(sArray, 1)
    If sArray(li, 1) = "111250000125" Then
      lj = lj + 1
      Arr(lj, 1) = sArray(li, 1)
    End If
  Next li
  Range("E1").Resize(lj).Value = Arr
End Sub
- Thứ nhất: Không cần Option Base 1 gì cả, khai báo trực tiếp rằng ReDim Arr(1 To UBound(sArray, 1), 1 To UBound(sArray, 2))
- Thứ hai: Dim Arr() As String sẽ bảo đảm kết quả luôn là chuổi
- Thứ ba: Chổ này arr(UBound(sarr, 1), LBound(sarr, 1)) xem bộ không chuẩn (phải giống cái trên mới đúng)
Thử lại code tôi vừa đưa ở trên xem tốc độ thế nào
---------------------------------------------------------------------------------
Mà sao em lọc rồi copy bị báo lỗi "Microsoft office excel cannot create or use the data range reference because it is too complex" Không biết máy em có bị gì không mong anh chị test giúp em Thanks. Em tìm trên mạng thì trang này nó nói rằng http://www.mrexcel.com/forum/showthread.php?t=550686
Không biết báo lỗi copy với dữ liệu lọc bằng AutoFilter hay với code? ---> Đoán là báo lỗi khi copy dữ liệu sau AutoFilter! Điều này rất bình thường. SpecialCells sẽ có giới hạn với dữ liệu lớn ---> Nếu dùng Filter thì nên chuyển sang Advanced Filter, sẽ hết lỗi liền (vì không phải copy, lọc và đưa kết quả thẳng đến nơi ta cần luôn)
 
Lần chỉnh sửa cuối:
Upvote 0
Sao lại vầy:
ReDim arr(UBound(sarr, 1), LBound(sarr, 1))

Như vầy mới đúng chứ:
ReDim arr(UBound(sarr, 1), UBound(sarr, 2))
hoặc:
ReDim arr(UBound(sarr, 1), 1)

Mấy anh bên đó chưa học Array từ GPE nên xử lý 550.000 dòng nhanh nhất là 5 phút. Con nmhung49 xơi 800.000 dòng có 15 giây! (Máy cùn P4 của công ty đó nha, máy khác còn khủng thế nào nữa à.)

Nói tới dữ liệu lớn thì đừng nói gì công thức, AutoFilter cũng chết ngắc. Copy, Paste sau khi Filter cũng đi die, vì nó gồm quá nhiều mảnh nhỏ ghép lại, không phải 1 range liên tục.
Đã thí nghiệm:
Để nguyên không filter: copy, paste 800.000 cells vẫn được.
Sau khi filter: Copy bị báo lỗi như trên.
---------------------
Quên để ý vụ cells(li, 1).Value
Thay bằng sarr(li, 1)
Code chạy dưới 1 giây!
 
Lần chỉnh sửa cuối:
Upvote 0
Sub hocmang()
Dim arr(), sarr As Variant, li As Long, lj As Long
sarr = Range("a1:a808945").Value
ReDim arr(UBound(sarr, 1), LBound(sarr, 1))
Cái em này khai báo "trật lấc", sửa lại như Thầy ptm & ndu
Còn nếu biết chắc là 1 cột thì khai báo vầy cho gọn Redim arr(1 to UBound(sarr),1 to 1)
For li = 1 To UBound(arr, 1)
Nếu cho chạy theo dòng chỉ cần UBound(arr)
If Cells(li, 1).Value = "111250000125" Then
Cái em này cũng trật lấc, may mà dữ liệu của bạn ở cột A chứ ở cột khác là code này "tèo" chắc
lj = lj + 1
arr(lj, 1) = sarr(li, 1)
End If
Next li
[d1:d130000] = arr
Cái em này lý ra bạn viết
[d1].Resize(lj) = arr
End Sub
Nói chung, bài này viết đúng nó chạy cái.....roẹt là xong
Thân
 
Upvote 0
Sao lại vầy:
ReDim arr(UBound(sarr, 1), LBound(sarr, 1))

Như vầy mới đúng chứ:
ReDim arr(UBound(sarr, 1), UBound(sarr, 2))
hoặc:
ReDim arr(UBound(sarr, 1), 1)

Mấy anh bên đó chưa học Array từ GPE nên xử lý 550.000 dòng nhanh nhất là 5 phút. Con nmhung49 xơi 800.000 dòng có 15 giây! (Máy cùn P4 của công ty đó nha, máy khác còn khủng thế nào nữa à.)

Nói tới dữ liệu lớn thì đừng nói gì công thức, AutoFilter cũng chết ngắc. Copy, Paste sau khi Filter cũng đi die, vì nó gồm quá nhiều mảnh nhỏ ghép lại, không phải 1 range liên tục.
Đã thí nghiệm:
Để nguyên không filter: copy, paste 800.000 cells vẫn được.
Sau khi filter: Copy bị báo lỗi như trên.
Code chạy dưới 1 giây!
Đọc xong mấy bài các anh và Thầy em thấy code mình củ chuối thiệt chứ, cố gắng cải thiện để mà hỏi tiếp ặc...ặc...--=0--=0;;;;;;;;;;; mà sao em thấy diễn đàn mình không là thành viên của MVP của Microsoft hen thấy cũng lạ
Quên để ý vụ cells(li, 1).Value
Thay bằng sarr(li, 1)
Cho em hỏi sarr(li,1) nó hoạt động làm sao theo em nghĩ thì có phải nó duyệt qua từ giá trị trong mảng sarr = range("a1:a808945").value phải không ah!!
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi sarr(li,1) nó hoạt động làm sao theo em nghĩ thì có phải nó duyệt qua từ giá trị trong mảng sarr = range("a1:a808945").value phải không ah!!

Bạn đã gán giá trị của range A1:A808945 vào mảng sarr trong câu:
sarr = Range("a1:a808945").Value

Vậy thì dò tìm, cũng dò tìm trên sarr, xét điều kiện, cũng xét điều kiện trên sarr, và truy xuất cũng truy xuất trên sarr.
Chứ mà cứ ngó ngó xuống cell thì ... gán sarr làm gì?

em nghĩ thì có phải nó duyệt qua từ giá trị trong mảng
Đúng, duyệt từng giá trị trong mảng, nhưng là mảng sarr, không phải range dưới sheet nữa. Có thế mới nhanh được chứ!
 
Upvote 0
Cho em hỏi có cách nào mình đổi tên sheet bằng cách dùng mảng không vậy các bạn. Thương ngày mình dùng code này để đổi tên mấy hôm nay tìm cách dùng mảng để đổi tên mà không tài nào biết được +-+-+-++-+-+-+. Mong các bạn giúp đỡ. Thanks
PHP:
Sub doiten()
Dim li As Long
For li = 1 To Sheets.Count
Sheets(li).Name = Cells(li, 1)
Next li
End Sub
 
Upvote 0
Cho em hỏi có cách nào mình đổi tên sheet bằng cách dùng mảng không vậy các bạn. Thương ngày mình dùng code này để đổi tên mấy hôm nay tìm cách dùng mảng để đổi tên mà không tài nào biết được +-+-+-++-+-+-+. Mong các bạn giúp đỡ. Thanks
PHP:
Sub doiten()
Dim li As Long
For li = 1 To Sheets.Count
Sheets(li).Name = Cells(li, 1)
Next li
End Sub
Có chăng là đổi mấy thằng Cells(li, 1) thành những phần tử trong mảng, nhưng tôi nghĩ chẳng ăn thua gì
Thử nghĩ xem người ta dùng 1 file nhiều nhất cũng chừng độ vài chục sheet ---> Tương ứng vòng lập duyệt bao nhiêu đó lần ---> Chẳng đáng bao nhiêu mà phải mất thời gian nghiên cứu (mà dù cố thì chắc cũng hổng có cách nào khác)
 
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ới đoạn code trên của Thấy Mỹ vậy cho em hỏi nếu dữ liệu nhiều hơn Range("A2:B11") cỡ chừng A2:AA100 thì mình không thể dùng
PHP:
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
được phải không ah, vậy cho cách nào linh hoạt hơn không các bạn, anh chị em mới học mảng nhiều khi câu hỏi ngô ghê xin đừng cười ạ. Thanks
 
Lần chỉnh sửa cuối:
Upvote 0
Với đoạn code trên của Thấy Mỹ vậy cho em hỏi nếu dữ liệu nhiều hơn Range("A2:B11") cỡ chừng A2:AA100 thì mình không thể dùng
PHP:
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
được phải không ah, vậy cho cách nào linh hoạt hơn không các bạn, anh chị em mới học mảng nhiều khi câu hỏi ngô ghê xin đừng cười ạ. Thanks
Vầy đi:
- Bước đầu tiếp cận với mảng 2 chiều, bạn cứ hãy tưởng tượng nó là Range đi ---> Cách truy xuất tương tự.
- Ngoài ra, nghĩ được cái gì thì cứ thí nghiệm rồi rút ra kết luận
 
Upvote 0
Với đoạn code trên của Thấy Mỹ vậy cho em hỏi nếu dữ liệu nhiều hơn Range("A2:B11") cỡ chừng A2:AA100 thì mình không thể dùng
PHP:
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
được phải không ah, vậy cho cách nào linh hoạt hơn không các bạn, anh chị em mới học mảng nhiều khi câu hỏi ngô ghê xin đừng cười ạ. Thanks
Gợi ý như sau:
Do biết trước chỉ có 2 cột, nên ta dùng 2 biến iR1 và iR2
Không biết bao nhiêu cột thì dùng biến mảng iR()
ReDim iR(1 To cái gì đó thích hợp, suy nghĩ nha)

Rồi sau đó, j bằng bi nhiu, tăng iR(j) lên 1
rồi ....
 
Upvote 0
Gợi ý như sau:
Do biết trước chỉ có 2 cột, nên ta dùng 2 biến iR1 và iR2
Không biết bao nhiêu cột thì dùng biến mảng iR()
ReDim iR(1 To cái gì đó thích hợp, suy nghĩ nha)

Rồi sau đó, j bằng bi nhiu, tăng iR(j) lên 1
rồi ....

Dựa vào cách Thầy hướng dẫn em làm được file này lọc những ô có năm 2001, em nghĩ nó cũng giống cái lấy số lẻ. Mong Thầy và các bạn hướng dẫn giúp.Thanks
PHP:
Sub locdulieu1()
Dim mang, smang(), li As Long, lj As Long, lr As Long, rmang(), lm As Long
mang = [a1:d28]
ReDim smang(1 To UBound(mang, 1), 1 To UBound(mang, 2))
For li = 1 To UBound(mang, 2)
    For lj = 1 To UBound(mang, 1)
        If lj = 1 Then
        lr = lr + 1
        lm = 0
        End If
        ReDim rmang(1 To lr)
        If mang(lj, li) = "2001" Then
        smang(lm + 1, UBound(rmang, 1)) = mang(lj, li)
        lm = lm + 1
        End If
    Next
Next
[f1].Resize(UBound(mang, 1), UBound(mang, 2)) = smang
End Sub
 
Upvote 0
Như vậy sẽ gọn hơn:
PHP:
Sub locdulieu2()
Dim mang, smang(), li As Long, lj As Long, rmang() As Long
mang = [a1:d28]
ReDim smang(1 To UBound(mang, 1), 1 To UBound(mang, 2))
        ReDim rmang(1 To UBound(mang, 2))
For li = 1 To UBound(mang, 2)
    For lj = 1 To UBound(mang, 1)
        If mang(lj, li) = "2001" Then
        smang(rmang(li) + 1, li) = mang(lj, li)
        rmang(li) = rmang(li) + 1
        End If
    Next
Next
[f1].Resize(UBound(mang, 1), UBound(mang, 2)) = smang
End Sub
Khỏi cần lờ mờ, lờ rờ gì sất.
 
Lần chỉnh sửa cuối:
Upvote 0
Như vậy sẽ gọn hơn:
PHP:
Sub locdulieu2()
Dim mang, smang(), li As Long, lj As Long, rmang() As Long
mang = [a1:d28]
ReDim smang(1 To UBound(mang, 1), 1 To UBound(mang, 2))
        ReDim rmang(1 To UBound(mang, 2))
For li = 1 To UBound(mang, 2)
    For lj = 1 To UBound(mang, 1)
        If mang(lj, li) = "2001" Then
        smang(rmang(li) + 1, li) = mang(lj, li)
        rmang(li) = rmang(li) + 1
        End If
    Next
Next
[f1].Resize(UBound(mang, 1), UBound(mang, 2)) = smang
End Sub
Khỏi cần lờ mờ, lờ rờ gì sất.
ReDim rmang(1 To UBound(mang, 2)). Theo em hiểu cái này tương đương với Redim rmang(1 to 4) là 4 dòng 1 cột. Còn rmang(li) = rmang(li)+1 Nếu em xét theo từng cột đi hen ví dụ cột từ A1:A28 có xuất hiện 10 số 2001 đi thì rmang(li) nó nhảy từ 1 đến 10 mà trong khi Redim rmang có từ 1 đến 4 mà không bị lỗi ta. Em có lờ mờ lờ sờ lắm mong Thầy giải thích thêm. Thanks
 
Upvote 0
Ẹc ẹc,
1.
ReDim rmang(1 To UBound(mang, 2))
tức là
ReDim rmang(1 To 4)
vậy
rmang là mảng 1 chiều
nên
là mảng ngang
4 phần tử
sử dụng
tương ứng
4
cột

2. rmang(li) là giá trị phần tử thứ li, có thể thay đổi giá trị các phần tử đến bao nhiêu chẳng được?

3. đâu phải rmang(li) = 8 là phần tử thứ 8? Nên nhớ li chỉ chạy từ 1 đến 4 trong vòng lặp for thứ nhất.

TB:
lờ mờ là biến lm, lờ rờ là biến lr, ý là không cần 2 biến này nữa í!
 
Lần chỉnh sửa cuối:
Upvote 0
Ẹc ẹc,
1.
ReDim rmang(1 To UBound(mang, 2))
tức là
ReDim rmang(1 To 4)
vậy
rmang là mảng 1 chiều nên là mảng ngang 4 phần tử sử dụng tương ứng 4 cột
TB:
lờ mờ là biến lm, lờ rờ là biến lr, ý là không cần 2 biến này nữa í!
Ặc...ặc.... Khi mình khai báo ReDim rmang(1 To 4) thì nó làm mảng 1 chiều em mới biết em cứ tưởng nó giống mình khai bao này rmang(A1:A10) chứ
rmang(li) là giá trị phần tử thứ li, có thể thay đổi giá trị các phần tử đến bao nhiêu chẳng được?
Vậy cái này thay đổi bao nhiêu cũng được hả Thầy /-*+//-*+/
3. đâu phải rmang(li) = 8 là phần tử thứ 8? Nên nhớ li chỉ chạy từ 1 đến 4 trong vòng lặp for thứ nhất.
Cái này em biết tại em thắc mắc chạy không báo lỗi nên giờ mới hiểu ra mà cũng chưa hiều cho lắm ục...uc..+-+-+-+. Em nghĩ tới đây là đủ rồi để dành cho các bạn khác hỏi nữa, hỏi hoài Thầy cũng kỳ ặc...ặc....Thanks Thầy Mỹ nhiều ;;;;;;;;;;;}}}}}
 
Upvote 0
Có gì mà không hiểu lắm rồi là ục ục

Đã khai báo Rmang() As Long nên:
- giá trị của các phần tử có thể thay bằng giá trị số lên đến giới hạn của long (số lớn lắm à)
- Không cần gán giá trị ban đầu đã có thể lấy giá trị phần tử của nó cộng 1 (ban đầu = 0)

Đã Redim Rmang(1 To 4), nên khi Li chạy từ 1 đến 4, ta hiểu là đang ở cột Li của mảng ban đầu, và cả cột Li của mảng kết quả,
Thế là ta ăn gian lấy giá trị thứ Li cộng 1, làm số thứ tự dòng thêm vào của mảng kết quả. Cộng 1 là để khỏi đè lên dòng cũ của mảng kết quả. Sau đó phải cộng 1, để có số dòng hiện có của cột Li của mảng kết quả. Lát nữa, gặp nữa, cộng 1 nữa.
Vì Li chạy từ 1 đến 4, Li = bi nhiu ta lấy bấy nhiu, nên bảo đảm đúng thứ tự cột.
 
Upvote 0
Khi làm việc với mảng, ta nên làm theo hướng tổng quát, tức xem như không biết trước mảng thuộc Base 0 hay Base 1.
Với bài của nmhung49 do lấy mảng từ Range nên cứ ngầm hiểu mảng này thuộc Base 1 (tức phần tử đầu tiên bắt đầu = 1)
Giả định rằng mảng nguồn được lấy từ... đâu đó tùy ý thì... coi chừng. Ví dụ thế này sẽ biết:
PHP:
Sub locdulieu1()
  Dim mang, smang(), li As Long, lj As Long, lr As Long, rmang(), lm As Long
  Sheet1.ListBox1.List() = Sheet1.Range("A1:D28").Value
  mang = Sheet1.ListBox1.List
  '...........................
  '............................
  [f1].Resize(UBound(mang, 1), UBound(mang, 2)) = smang
End Sub
Thử xem
 
Upvote 0
Em có 1 thắc mắc không biết có cách nào mình lấy giá duy nhất của 1 vùng gán vào mảng không với điều kiện không dùng Scipting.dictionary. Em nghĩ tới dùng advance filter như phải dùng cột phụ không hay lắm
PHP:
Sub Loc()
Dim Rng As Range, arr
Sheet1.Range("b1").CurrentRegion.AdvancedFilter xlFilterCopy, , [d1], True
arr = Range("d1").CurrentRegion
End Sub
Vậy bác có cách nào lọc 1 mảng ảo không. Ví dụ mảng arr() có các giá trị như (1,2,3,2,3,4,7,8,1)
Và kết quả cho ra mng() có giá trị là (1,2,3,4,7,8).
Em đang cần.
Em thấy bài của anh Mr Okebab dùng công thức mà khó. Không biết mình có cách nào ngắn ngắn dễ hiểu không. Thanks
http://www.giaiphapexcel.com/forum/showthread.php?15834-%C4%90%E1%BA%BFm-s%E1%BB%91-ph%E1%BA%A7n-t%E1%BB%AD-%28duy-nh%E1%BA%A5t%29-c%C3%B3-trong-Dropdown-list-khi-AutoFilter/page3
http://www.giaiphapexcel.com/forum/showthread.php?37895-L%E1%BA%A5y-DM-duy-nh%E1%BA%A5t-theo-2-c%E1%BB%99t-Scripting.Dictionary%21
 
Upvote 0
Em có 1 thắc mắc không biết có cách nào mình lấy giá duy nhất của 1 vùng gán vào mảng không với điều kiện không dùng Scipting.dictionary. Em nghĩ tới dùng advance filter như phải dùng cột phụ không hay lắm
PHP:
Sub Loc()
Dim Rng As Range, arr
Sheet1.Range("b1").CurrentRegion.AdvancedFilter xlFilterCopy, , [d1], True
arr = Range("d1").CurrentRegion
End Sub
Em thấy bài của anh Mr Okebab dùng công thức mà khó. Không biết mình có cách nào ngắn ngắn dễ hiểu không. Thanks
http://www.giaiphapexcel.com/forum/showthread.php?15834-%C4%90%E1%BA%BFm-s%E1%BB%91-ph%E1%BA%A7n-t%E1%BB%AD-%28duy-nh%E1%BA%A5t%29-c%C3%B3-trong-Dropdown-list-khi-AutoFilter/page3
http://www.giaiphapexcel.com/forum/...-DM-duy-nhất-theo-2-cột-Scripting.Dictionary!
Không dùng Dictionary thì dùng Collection ---> Thuật toán tương tự và cách dùng cũng tương tự
Với giải pháp lọc duy nhất mà dùng code thì Dictionary mới chính là sở trường. Nó cũng đâu có khó hiểu lắm đâu ---> Bạn đang nghiên cứu về Array, thiết nghĩ cũng nên xem qua về Dictionary
Tôi cho bạn 1 ví dụ nhỏ
- Gõ vào vùng A1:A10 các số tùy ý (có thể trùng)
- Dùng code này thử kết quả
PHP:
Sub Test()
  Dim Clls As Range, Dic As Object
  Set Dic = CreateObject("Scripting.Dictionary")
  For Each Clls In Range("A1:A10")
    If Not Dic.Exists(Clls.Value) Then  '<--- Xét xem Clls.Value đã có trong Dic hay chưa, nếu chưa có thì thực hiện tiếp đoạn dưới
      Dic.Add Clls.Value, ""
      MsgBox Clls.Value
    End If
  Next
End Sub
 
Upvote 0
Tôi cho bạn 1 ví dụ nhỏ
- Gõ vào vùng A1:A10 các số tùy ý (có thể trùng)
- Dùng code này thử kết quả
PHP:
Sub Test()
  Dim Clls As Range, Dic As Object
  Set Dic = CreateObject("Scripting.Dictionary")
  For Each Clls In Range("A1:A10")
    If Not Dic.Exists(Clls.Value) Then  '<--- Xét xem Clls.Value đã có trong Dic hay chưa, nếu chưa có thì thực hiện tiếp đoạn dưới
      Dic.Add Clls.Value, ""
      MsgBox Clls.Value
    End If
  Next
End Sub
Theo code của NDU mày mò dùng tạm hàm Instr xem thế nào. Chắc là không thể nào nhanh bằng Dic.
PHP:
Sub TestInstr()
  Dim sTxt$
  Dim Clls As Range
  For Each Clls In Range("A1:A10")
    If Len(Clls.Value) > 0 Then
      If InStr(sTxt, vbBack & Clls.Value & vbBack) = 0 Then
        sTxt = sTxt & vbBack & Clls.Value & vbBack
      End If
    End If
  Next
  MsgBox Replace(sTxt, vbBack, "")
End Sub
 
Upvote 0
Theo code của NDU mày mò dùng tạm hàm Instr xem thế nào. Chắc là không thể nào nhanh bằng Dic.
PHP:
Sub TestInstr()
  Dim sTxt$
  Dim Clls As Range
  For Each Clls In Range("A1:A10")
    If Len(Clls.Value) > 0 Then
      If InStr(sTxt, vbBack & Clls.Value & vbBack) = 0 Then
        sTxt = sTxt & vbBack & Clls.Value & vbBack
      End If
    End If
  Next
  MsgBox Replace(sTxt, vbBack, "")
End Sub
Thứ nhất: Dùng phép xử lý chuổi thì chắc ăn không thể nào nhanh được ---> Dữ liệu nhiều chắc thè lưởi luôn
Thứ hai: Thuật toán cũng chắc gì đã dễ hiểu hơn Dictionary
Ẹc... Ẹc...
 
Upvote 0
Em có vùng từ [A1:A30] trong đó nó chỉ có 10 số liệu duy nhất thôi, vậy mình khi gán vào vùng nào đó do sợ không đủ nên mình cho mảng đó tới 20 dòng vậy dư thừa quá vậy mình chỉ có cách dùng countif không hả các anh?
PHP:
Sub Test()
  Dim Clls As Range, Dic As Object, arr(), i
  Set Dic = CreateObject("Scripting.Dictionary")
  ReDim Preserve arr(20, 1)             <--- Em thay khoi Preserve cung duoc vay khi nao minh can Preserve
  For Each Clls In Range("A1:A30")
    If Not Dic.Exists(Clls.Value) Then <--- Xét xem Clls.Value đã có trong Dic hay chưa, nếu chưa có thì thực hiện tiếp đoạn dưới 
     Dic.Add Clls.Value, ""
     i = i + 1
     arr(i, 1) = Clls.Value
     End If
  Next
   Sheet1.[D1].Resize(UBound(arr, 1)) = arr
End Sub
Với giải pháp lọc duy nhất mà dùng code thì Dictionary mới chính là sở trường. Nó cũng đâu có khó hiểu lắm đâu ---> Bạn đang nghiên cứu về Array, thiết nghĩ cũng nên xem qua về Dictionary
Bắt đầu em thấy thích Scipting.dictionary rồi đó nhen, cố gắng tìm hiểu mới được!!!! ...ăc…ặc…..Thanks
http://www.giaiphapexcel.com/forum/showthread.php?26987-Th%E1%BA%AFc-m%E1%BA%AFc-v%E1%BB%81-code-c%C3%B3-li%C3%AAn-quan-%C4%91%E1%BA%BFn-x%E1%BB%AD-l%C3%BD-m%C3%A3ng-%28Array%29
 
Lần chỉnh sửa cuối:
Upvote 0
Em có vùng từ [A1:A30] trong đó nó chỉ có 10 số liệu duy nhất thôi, vậy mình khi gán vào vùng nào đó do sợ không đủ nên mình cho mảng đó tới 20 dòng vậy dư thừa quá vậy mình chỉ có cách dùng countif không hả các anh?
Tuyệt đối đừng dùng các hàm của Excel vào code, nó là nguyên nhân khiến code chậm đi
Mảng dư cũng đâu có sao, phần tử nào chưa gán giá trị thì nó sẽ = rổng thôi
Ví dụ:
PHP:
Sub Test()
  Dim Clls As Range, Dic As Object, arr(), i As Long, Tmp
  Set Dic = CreateObject("Scripting.Dictionary")
  ReDim arr(1 To 20, 1 To 1)
  For Each Clls In Range("A1:A30")
    If Not Dic.Exists(Clls.Value) Then
      Dic.Add Clls.Value, ""
      i = i + 1
      arr(i, 1) = Clls.Value
    End If
  Next
  Range("D1").Resize(Dic.Count).Value = arr
End Sub
(Code của bạn có sai mấy chổ, tôi đã sửa lại)
Ngoài ra, nếu bạn cương quyết tạo mảng có kích thước vừa đủ thì sau khi Add vào Dictionary xong, bạn thêm 1 vòng lập nữa:
PHP:
Sub Test2()
  Dim Dic As Object, arr(), sArray, i As Long, Item, Tmp
  Set Dic = CreateObject("Scripting.Dictionary")
  sArray = Range("A1:A30").Value
  For Each Item In sArray
    If Not Dic.Exists(Item) Then
      Dic.Add Item, ""
    End If
  Next
  ReDim arr(1 To Dic.Count, 1 To 1)
  Tmp = Dic.Keys
  For i = 1 To Dic.Count
    arr(i, 1) = Tmp(i - 1)
  Next
  Range("D1").Resize(Dic.Count).Value = arr
End Sub
Dù thêm vòng lập nữa nhưng chắc chắn tốc độ vẫn sẽ nhanh hơn so với khi bạn dùng COUNTIF
Lưu ý:
- Đoạn code dưới mới đúng là làm việc hoàn toàn với mảng, cái trên chưa phải
- Các đoạn code vẫn chưa có động tác bẩy lỗi và loại bỏ phần tử rổng
 
Lần chỉnh sửa cuối:
Upvote 0
Em muốn lây dữ liệu vùng A2:A14 để cho ra kết quả ơ cột C mà sao thấy đoạn code nó hơi sao sao đó. Mặt dù em test thử thì tốc độ vẫn ok nếu dữ liệu nhiều chắc chắc có trục trặc mong anh chị các bạn giúp đỡ.Thanks
PHP:
Sub noimang()
Dim arr, sarr(), li As Long, lj As Long, item, dic As Object
arr = [A2:B14]
Set dic = CreateObject("Scripting.Dictionary")
ReDim sarr(1 To UBound(arr), 1 To UBound(arr, 2))
For li = 1 To UBound(arr)
If Len(arr(li, 1)) = 4 Then
        lj = lj + 1
        sarr(lj, 1) = arr(li, 1) & " - " & arr(li, 2)
    End If
Next
lj = 0
For Each item In sarr
    If Not dic.exists(item) Then
        dic.Add item, ""
        lj = lj + 1
        sarr(lj, 1) = item
    End If
Next
Sheet1.[e1].Resize(dic.Count) = sarr
End Sub

Cho em hỏi đoạn code trên có nghĩ là gì
 

File đính kèm

Upvote 0
Em muốn lây dữ liệu vùng A2:A14 để cho ra kết quả ơ cột C mà sao thấy đoạn code nó hơi sao sao đó. Mặt dù em test thử thì tốc độ vẫn ok nếu dữ liệu nhiều chắc chắc có trục trặc mong anh chị các bạn giúp đỡ.Thanks
PHP:
Sub noimang()
Dim arr, sarr(), li As Long, lj As Long, item, dic As Object
arr = [A2:B14]
Set dic = CreateObject("Scripting.Dictionary")
ReDim sarr(1 To UBound(arr), 1 To UBound(arr, 2))
For li = 1 To UBound(arr)
If Len(arr(li, 1)) = 4 Then
        lj = lj + 1
        sarr(lj, 1) = arr(li, 1) & " - " & arr(li, 2)
    End If
Next
lj = 0
For Each item In sarr
    If Not dic.exists(item) Then
        dic.Add item, ""
        lj = lj + 1
        sarr(lj, 1) = item
    End If
Next
Sheet1.[e1].Resize(dic.Count) = sarr
End Sub
Cho em hỏi đoạn code trên có nghĩ là gì
Tôi thì làm vầy:
PHP:
Sub Noimang()
  Dim sArray, Arr(), lR As Long, n As Long, Dic As Object, Tmp As String
  On Error Resume Next
  sArray = Sheet1.Range("A2:B11").Value
  Set Dic = CreateObject("Scripting.Dictionary")
  ReDim Arr(1 To UBound(sArray), 1 To 1)
  For lR = 1 To UBound(sArray, 1)
    If Len(sArray(lR, 1)) = 4 Then
      Tmp = sArray(lR, 1) & " - " & sArray(lR, 2)
      If Not Dic.Exists(Tmp) Then
        Dic.Add Tmp, ""
        n = n + 1
        Arr(n, 1) = Tmp
      End If
    End If
  Next
  Sheet1.Range("E1").Resize(Dic.Count).Value = Arr
End Sub
1 vòng lập thôi bạn à ---> Lúc add dữ liệu vào Dictionary Object, đồng thời ta lấy dữ liệu cho vào Array kết quả luôn
Lưu ý:
- Địa chỉ vùng dữ liệu nên ghi rõ ràng, có đầy đủ tên sheet
- Tên biến nên đặt sao cho dễ nhìn nhất (với dữ liệu nguồn, tôi thường đặt nó tên là sArray <===> Source Array)
 
Upvote 0
Cho em hỏi thêm 1 câu nữa là dữ liệu vùng A2:B11 nằm không theo thứ tự A-->Z chẳng hạn, mà em muốn dữ liệu đầu ra của mình phải theo thứ tự A--> Z. Vậy mình làm thế nào để dữ liệu đầu ra theo thứ tự với điều kiện không làm thay đổi thứ tự vung A2:B11. Em thử phương pháp Sort mà không được vì nó làm thay đổi dữ liệu đầu vào. Em có tham khảo cách Sort mảng 2 chiều của anhtuan1066 mà không biết áp dụng thế nào mong các anh chị, các bạn hướng dẫn giúp thanks
http://www.giaiphapexcel.com/forum/showthread.php?47929-Sort-m%E1%BA%A3ng-2-chi%E1%BB%81u
 
Upvote 0
Cho em hỏi thêm 1 câu nữa là dữ liệu vùng A2:B11 nằm không theo thứ tự A-->Z chẳng hạn, mà em muốn dữ liệu đầu ra của mình phải theo thứ tự A--> Z. Vậy mình làm thế nào để dữ liệu đầu ra theo thứ tự với điều kiện không làm thay đổi thứ tự vung A2:B11. Em thử phương pháp Sort mà không được vì nó làm thay đổi dữ liệu đầu vào. Em có tham khảo cách Sort mảng 2 chiều của anhtuan1066 mà không biết áp dụng thế nào mong các anh chị, các bạn hướng dẫn giúp thanks
http://www.giaiphapexcel.com/forum/showthread.php?47929-Sort-m%E1%BA%A3ng-2-chi%E1%BB%81u
Bạn đưa dữ liệu lên đi (bao gồm cả kết quả mong muốn) rồi tôi sẽ thử xem thế nào
 
Upvote 0

File đính kèm

Upvote 0
Em đưa dữ liệu anh xem giúp nhen, chủ yếu dữ liệu em đưa vào Combobox để lấy dữ liệu ở từng Chi Nhánh. Thanks

Có phải Mã số nào thì tương ứng với Chi nhánh đó đúng không? Rồi sau đó tại cột C kết quả sẽ cho ra cấu trúc "MS - CN" đúng thế không? Nếu vậy thì quá đơn giản!

Tại A2:B14 tôi tạm đặt name là DuLieu, bạn có thể cho nó thành name động càng tốt.

Tại Combobox chọn thuộc tính ColumnCount = 2, ListFillRange = DuLieu

Viết thêm đoạn code cho Combobox nữa là xong:

PHP:
Private Sub ComboBox1_Change()
  With ComboBox1
    [C65536].End(xlUp).Offset(1).Value = .Value & " - " & .Column(1)
  End With
End Sub

Không cần phải dùng mảng gì cho phức tạp vụ!
 

File đính kèm

Upvote 0
Có phải Mã số nào thì tương ứng với Chi nhánh đó đúng không? Rồi sau đó tại cột C kết quả sẽ cho ra cấu trúc "MS - CN" đúng thế không? Nếu vậy thì quá đơn giản!

Tại A2:B14 tôi tạm đặt name là DuLieu, bạn có thể cho nó thành name động càng tốt.

Tại Combobox chọn thuộc tính ColumnCount = 2, ListFillRange = DuLieu

Viết thêm đoạn code cho Combobox nữa là xong:

PHP:
Private Sub ComboBox1_Change()
  With ComboBox1
    [C65536].End(xlUp).Offset(1).Value = .Value & " - " & .Column(1)
  End With
End Sub

Không cần phải dùng mảng gì cho phức tạp vụ!
Không phải anh ơi, Ý em là muốn thừa hưởng kết quả ở bài 64, có nghĩa là khi lấy giá trị duy nhất rồi đưa vào combobox cái này em làm được từ bài 64 nhưng mà lỡ dữ liệu không theo thứ tự thì sẽ làm khó trong việc tìm dữ liệu trong combobox thôi, nên em muốn rồi mình sort dữ liệu trong combobox theo thứ tự vậy thôi, em muốn học cách sort dữ liệu trực tiếp trên mảng luôn đó mà chỉ vậy thôi. Cảm ơn
 
Upvote 0
Không phải anh ơi, Ý em là muốn thừa hưởng kết quả ở bài 64, có nghĩa là khi lấy giá trị duy nhất rồi đưa vào combobox cái này em làm được từ bài 64 nhưng mà lỡ dữ liệu không theo thứ tự thì sẽ làm khó trong việc tìm dữ liệu trong combobox thôi, nên em muốn rồi mình sort dữ liệu trong combobox theo thứ tự vậy thôi, em muốn học cách sort dữ liệu trực tiếp trên mảng luôn đó mà chỉ vậy thôi. Cảm ơn
Nếu vậy thì chỉ là Sort mảng 1 chiều thôi (đâu phải 2 chiều)
Code như vầy:
1> Hàm Sort mảng 1 chiều
PHP:
Function Sort1DArray(ByVal Arr, Optional ByVal isText As Boolean = False, Optional ByVal isDESC As Boolean = False)
  Dim sCommand As String
  sCommand = "('" & Join(Arr, vbBack) & "').split('" & vbBack & "').sort("
  If isText Then
    sCommand = sCommand & ")"
  Else
    sCommand = sCommand & "function(a,b){return (a-b)})"
  End If
  If isDESC Then sCommand = sCommand & ".reverse()"
  sCommand = sCommand & ".join('" & vbBack & "')"
  With CreateObject("MSScriptControl.ScriptControl")
    .Language = "JavaScript"
    Sort1DArray = Split(.Eval(sCommand), vbBack)
  End With
End Function
2> Code nạp ComboBox
PHP:
Sub AddCombo()
  Dim sArray, Arr(), lR As Long, n As Long, Dic As Object, Tmp As String
  On Error Resume Next
  sArray = Sheet1.Range("A2:B11").Value
  Set Dic = CreateObject("Scripting.Dictionary")
  For lR = 1 To UBound(sArray, 1)
    If Len(sArray(lR, 1)) = 4 Then
      Tmp = sArray(lR, 1) & " - " & sArray(lR, 2)
      If Not Dic.Exists(Tmp) Then
        Dic.Add Tmp, ""
        n = n + 1
        ReDim Preserve Arr(1 To n)
        Arr(n) = Tmp
      End If
    End If
  Next
  Sheet1.ComboBox1.List() = Sort1DArray(Arr, True)
End Sub
 

File đính kèm

Upvote 0
Giúp em học VBA với

Hi em không phải dan chuyên tin nhưng phải làm việc với exel nhiều, nhiều lúc gặp phải vấn đề khó muốn viết một chương trình đơn giản để giải quyết nhưng không viết được mong các bác chỉ giáo cho em vai đường cơ bản với, em cung đang đọc VBA rồi nhưng hơi khó hiểu chút, bác nào giỏ về khoản này chỉ cho em cách học thế nào cho dễ hiểu thi nhanh quá. Thank trước nha!--=0
 
Upvote 0
Giả sử tôi có mãng Arr = Array("a", "b", "c", "d")Vậy có hàm VBA để tìm kiếm (giá trị "c" chẳng hạn) trong mãng cho kết quả là 2 không?
Có thể áp dụng như Set Rng=sRng.Find("a",,,xlWhole) được không?
Xin các anh chị giúp đỡ (không dùng vòng lập). Xin cảm ơn các anh chị
 
Lần chỉnh sửa cuối:
Upvote 0
Giả sử tôi có mãng Arr = Array("a", "b", "c", "d")Vậy có hàm VBA để tìm kiếm (giá trị "c" chẳng hạn) trong mãng cho kết quả là 2 không?
Có thể áp dụng như Set Rng=sRng.Find("a",,,xlWhole) được không?
Xin các anh chị giúp đỡ (không dùng vòng lập). Xin cảm ơn các anh chị
Nhanh nhất là dùng WorksheetFunction.Match("c", Arr, 0)
 
Upvote 0
Làm sao để giữ nguyên định dạng của dữ liệu số khi chuyển từ bảng sang mảng

Mong các Bác hướng dẫn làm cách nào để có thể giữ nguyên định dạng của dữ liệu dạng số, với ListBox có nguồn từ một mảng.

Yêu cầu cụ thể như trong file đính kèm.

Trân trọng
 

File đính kèm

Upvote 0
Mong các Bác hướng dẫn làm cách nào để có thể giữ nguyên định dạng của dữ liệu dạng số, với ListBox có nguồn từ một mảng.

Yêu cầu cụ thể như trong file đính kèm.

Trân trọng
Cell C2 ta nhìn thấy là 0.67 nhưng giá trị thật của nó là 0.6666666....6666 (vì =2/3)
Với mảng được lấy từ những dữ liệu này, đương nhiên các phần tử của mảng phải là những giá trị thật chứ không phải cái mà ta nhìn thấy ---> Vấn đề của chúng ta là phải xử lý mảng này trước khi nạp vào ListBox
Ví dụ thế này:
PHP:
Private Sub UserForm_Initialize()
  Dim Arr, Clls As Range, i As Long
  With Sheet1.Range("C2:C5")
    Arr = .Value
    For Each Clls In .Cells
      i = i + 1
      Arr(i, 1) = Clls.Text
    Next
  End With
  Me.ListBox1.List() = Arr
End Sub
Ngoài ra cũng có chiêu khác:
PHP:
Private Sub UserForm_Initialize()
  Dim Arr
  With Sheet1.Range("C2:C5")
    Arr = Evaluate("TRANSPOSE(TEXT(" & .Address & ", ""0.00""))")
    Arr = WorksheetFunction.Transpose(Arr)
    Me.ListBox1.List() = Arr
  End With
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Mong các Bác hướng dẫn làm cách nào để có thể giữ nguyên định dạng của dữ liệu dạng số, với ListBox có nguồn từ một mảng.

Yêu cầu cụ thể như trong file đính kèm.

Trân trọng
Mình nghĩ phải trải qua 1 bước nữa tại vì source nguồn của nó là như thế nên nó luôn gán vào đúng source nguồn của nó nên phải thế thôi
PHP:
Private Sub UserForm_Initialize()
Dim arrSource, arr(), lRow As Long
arrSource = Sheet1.Range("C2:C5").Value
ReDim arr(1 To UBound(arrSource, 1), 1 To 1)
For lRow = 1 To UBound(arrSource, 1)
arr(lRow, 1) = Format(arrSource(lRow, 1), "0.00")
Next lRow
Sheet1.Range("C2:C5").Name = "Dulieu"
Me.ListBox1.List() = arr
Me.ListBox2.RowSource = "Dulieu"
End Sub
 
Upvote 0
Cám ơn Bác NDU và bạn nmhung49.
Mã:
[LEFT][COLOR=#007700][FONT=monospace]Private [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Sub UserForm_Initialize[/FONT][/COLOR][COLOR=#007700][FONT=monospace]()
  [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Dim Arr
  With Sheet1[/FONT][/COLOR][COLOR=#007700][FONT=monospace].[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Range[/FONT][/COLOR][COLOR=#007700][FONT=monospace]([/FONT][/COLOR][COLOR=#DD0000][FONT=monospace]"C2:C5"[/FONT][/COLOR][COLOR=#007700][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr [/FONT][/COLOR][COLOR=#007700][FONT=monospace]= [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Evaluate[/FONT][/COLOR][COLOR=#007700][FONT=monospace]([/FONT][/COLOR][COLOR=#DD0000][FONT=monospace]"TRANSPOSE(TEXT(" [/FONT][/COLOR][COLOR=#007700][FONT=monospace]& .[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Address [/FONT][/COLOR][COLOR=#007700][FONT=monospace]& [/FONT][/COLOR][COLOR=#DD0000][FONT=monospace]", ""0.00""))"[/FONT][/COLOR][COLOR=#007700][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr [/FONT][/COLOR][COLOR=#007700][FONT=monospace]= [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]WorksheetFunction[/FONT][/COLOR][COLOR=#007700][FONT=monospace].[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Transpose[/FONT][/COLOR][COLOR=#007700][FONT=monospace]([/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr[/FONT][/COLOR][COLOR=#007700][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Me[/FONT][/COLOR][COLOR=#007700][FONT=monospace].[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]ListBox1[/FONT][/COLOR][COLOR=#007700][FONT=monospace].List() = [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr
  End With
End Sub[/FONT][/COLOR][/LEFT]
Theo tôi cách của Bác NDU hay hơn, vì không dùng vòng For...Next -> thời gian xử lý nhanh hơn.

Nhờ thầy NDU giải thích thêm đoạn code này có phải là xử trên mảng không?
 
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn Bác NDU và bạn nmhung49.
Mã:
[LEFT][COLOR=#007700][FONT=monospace]Private [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Sub UserForm_Initialize[/FONT][/COLOR][COLOR=#007700][FONT=monospace]()
  [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Dim Arr
  With Sheet1[/FONT][/COLOR][COLOR=#007700][FONT=monospace].[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Range[/FONT][/COLOR][COLOR=#007700][FONT=monospace]([/FONT][/COLOR][COLOR=#DD0000][FONT=monospace]"C2:C5"[/FONT][/COLOR][COLOR=#007700][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr [/FONT][/COLOR][COLOR=#007700][FONT=monospace]= [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Evaluate[/FONT][/COLOR][COLOR=#007700][FONT=monospace]([/FONT][/COLOR][COLOR=#DD0000][FONT=monospace]"TRANSPOSE(TEXT(" [/FONT][/COLOR][COLOR=#007700][FONT=monospace]& .[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Address [/FONT][/COLOR][COLOR=#007700][FONT=monospace]& [/FONT][/COLOR][COLOR=#DD0000][FONT=monospace]", ""0.00""))"[/FONT][/COLOR][COLOR=#007700][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr [/FONT][/COLOR][COLOR=#007700][FONT=monospace]= [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]WorksheetFunction[/FONT][/COLOR][COLOR=#007700][FONT=monospace].[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Transpose[/FONT][/COLOR][COLOR=#007700][FONT=monospace]([/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr[/FONT][/COLOR][COLOR=#007700][FONT=monospace])
    [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Me[/FONT][/COLOR][COLOR=#007700][FONT=monospace].[/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]ListBox1[/FONT][/COLOR][COLOR=#007700][FONT=monospace].List() = [/FONT][/COLOR][COLOR=#0000BB][FONT=monospace]Arr
  End With
End Sub[/FONT][/COLOR][/LEFT]
Theo tôi cách của Bác NDU hay hơn, vì không dùng vòng For...Next -> thời gian xử lý nhanh hơn.

Nhờ thầy NDU giải thích thêm đoạn code này có phải là xử trên mảng không?
Xét về tốc độ thì không chắc sẽ nhanh hơn so với vòng lập đâu
Mảng này tương đương với công thức mảng trên Excel thôi =TEXT(C2:C5, "0.00")
 
Upvote 0
PHP:
  Dim sArray, Arr()
Cho em hỏi cách DIM như trên thì sArray là biến gì & Arr()??
tại sao sau Arr có () mà sArray không có?

Cám ơn
 
Upvote 0
PHP:
  Dim sArray, Arr()
Cho em hỏi cách DIM như trên thì sArray là biến gì & Arr()??
tại sao sau Arr có () mà sArray không có?

Cách Dim như trên, sArray có thể là bất kỳ giá trị nào, đồng thời có thể là biến đơn hoặc biến mảng. Tuy nhiên, ngay sau khi gán giá trị 1 range vào, nó trở thành biến mảng. Khai báo trước là mảng cũng không sao.
Còn Dim Arr() tức là đã khai báo trước cho nó là mảng rồi. Mục đích khai báo trước nó là mảng, là để có thể ReDim. Biến chưa biết là mảng hay đơn thì không thể ReDim được.
 
Upvote 0
Biến chưa biết là mảng hay đơn thì không thể ReDim được.
Theo thí nghiệm dưới đây thì vẫn ReDim được sư phụ à:
PHP:
Sub Test()
  Dim Arr, i As Long
  ReDim Arr(1 To 10)
  For i = 1 To 10
    Arr(i) = i
  Next
  Range("A1").Resize(, 10).Value = Arr
End Sub
 
Upvote 0
Hic, vậy thì phải sửa lại:

Khai báo Dim sArray thì sArray có thể là biến đơn và cũng có thể là biến mảng
Khai báo Dim Arr() thì đã là khai báo biến mảng rồi.
 
Upvote 0
Bắt đầu học mảng: 1.Sự khác nhau giữa range và mảng hai chiều

Nếu trên diễn đàn đã có topic này rồi, MOD move giúp em về đúng chỗ quy định
Nếu chưa có, em xin tạo topic để tiện cho việc học mảng

Em bắt đầu với câu hỏi đầu tiên
Câu hỏi 1. Sự khác nhau giữa range & và mảng hai chiều là gì?
Câu hỏi 2. Có bao nhiêu loại mảng (ví dụ: mảng 1 chiều, mảng 2 chiều, mảng 3 chiều...)
Câu hỏi 3. Có phải từ mảng ngang & dọc là do thói quen tư duy của người dùng và không nhất thiết phải phân biệt ngang & dọc phải không?
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu trên diễn đàn đã có topic này rồi, MOD move giúp em về đúng chỗ quy định
Nếu chưa có, em xin tạo topic để tiện cho việc học mảng

Em bắt đầu với câu hỏi đầu tiên
1. Sự khác nhau giữa range & và mảng hai chiều là gì?
Theo mình hiểu:
Range = mảng 1 chiều: Mảng 1 cột nhiều dòng hoặc 1 dòng nhiều cột
Array = mảng 2 chiều: Mảng nhiều cột nhiều dòng
 
Upvote 0
Cám ơn bạn, theo mình tìm đọc trên GPE (nên mình mới hỏi câu "sự khác nhau giữa range & mảng 2 chiều" vì mình đọc thấy câu này
1. Range luôn là mảng 2 chiều
Ví dụ: vì Join chỉ làm việc với mảng 1 chiều nên
bạn không thể dùng hàm Join để nối một Range mà phải qua 2 lần transpose
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Thoat
With Target
   If .Column < 5 And .Value <> "" Then
        Range("F" & .Row) = Join(WorksheetFunction.Transpose( _
        WorksheetFunction.Transpose(Range("A" & .Row & ":E" & .Row))), "")
    End If
End With
    
Thoat:
End Sub

2. Nhưng.....range là range mà Mảng là mảng

Chính vì thế mình hỏi lại để hiểu cặn kẽ hơn về mảng
 
Lần chỉnh sửa cuối:
Upvote 0
Câu hỏi 4.
4. Mục đích của việc chuyển dữ liệu từ range thành mảng --> chủ yêu để tăng tốc xử lý
Vậy ngoài mục đích trên thì mảng còn ý nghĩa nào khác?
 
Upvote 0
Câu hỏi 3. Có phải từ mảng ngang & dọc là do thói quen tư duy của người dùng và không nhất thiết phải phân biệt ngang & dọc phải không?
Đọc lại bài 11 topic này, nhưng tốt nhất lá đọc hết từ đầu

Dẫu rằng nói 1 chiều thì không có dọc ngang, tựa như đường thẳng, và khác với mặt phẳng. Nhưng đó là xét theo hệ quy chiếu là đứng trong không gian 1 chiều và đang chỉ nhận thức được 1 chiều.

Giả sử tồn tại 1 thế giới mà sinh vật ở đó chỉ nhận thức được 1 chiều trong không gian, thì khi 1 vật thể di chuyển dọc theo đường thẳng, anh ta sẽ trông thấy sự dịch chuyển. Nếu 1 sinh vật ở hành tinh khác đến và nhận thức được không gian 2 chiều, anh ta đi ra khỏi đường thẳng vào chiều thứ 2. Vậy sinh vật tại đó sẽ nghĩ gì? Nó cho rằng sinh vật lạ đã biến mất.
Còn đối với sinh vật ở hành tinh khác đến, thì nghĩ: tao đâu có biến mất, mày chỉ đi được theo chiều X của tao, còn tao đi 2 hướng, vừa X vừa Y.
(Suy luận tương tự giữa không gian 2 chiều, 3 chiều, và n chiều)

Và khi sinh vật lạ này kể cho đồng hương của nó nghe, nó sẽ kể: Tụi nó chỉ đi ngang hông à, hông có ra khỏi cái đường thẳng đó được.

Chữ ngang để làm chi? để vẽ ra cho đồng hương nó hiểu.

Tưởng tượng xong, quay về Array. Array 1 chiều mà gán xuống sheet (bảng 2 chiều), thì phải gán ngang. Gán dọc là sai.
Nên
vẫn phải
hình dung
mảng 1 chiều

mảng
ngang!

Vì ta là thành viên GPE, thế giới GPE là thế giới bảng tính có ít nhất 2 chiều, và ta là sinh vật nhận thức được n chiều.
 
Lần chỉnh sửa cuối:
Upvote 0
Đọc câu này của bạn thấy hơi kỳ kỳ! Vậy mảng {A1;A2;...;An} gọi là gì ạ? Theo mình nó cũng là mảng 1 chiều, và là mảng dọc.
Có lẽ bạn cần đọc lại từ đầu topic này (tôi mới gộp vào topic cũ). Tôi nói hình dung mảng 1 chiều là mảng ngang

Nhắc lại 1 ý chính:
{A1;A2;...;An} tức là Range A1:A5, đó không phải mảng, mà là Range. Range là Range, mà mảng là mảng.
Range luôn là 2 chiều.
Mảng có thể từ 1 chiều đến n chiều.

Tôi nói hình dung mảng 1 chiều là mảng ngang, chứ không nói range A1:A5 là mảng ngang.
 
Upvote 0
Mình xin đính chính lại:
Range: có thể là 1 ô, 1 khối ô (1 hoặc 2 chiều)
Array: 2 ô trở lên
Bạn vẫn cần phải đọc lại:
Range có thể là 1 ô hoặc nhiều ô, nhưng khi gán vào mảng luôn luôn là 2 chiều.
Array (mảng VBA), có thể có 1 chiều hoặc n chiều.
Array không bao gồm ô, Array bao gồm các phần tử.
Array có thể có 1 phần tử như thường.
 
Upvote 0
hỏi 2 lần transpose

Em xin được hỏi lại thuật toán khi mình dùng 2 hàm Transpose lồng vào nhau.
Quá trình nó xảy ra như nào để biến Range thành mảng 1 chiều

Cám ơn Anh/Chị
 
Upvote 0
Em xin được hỏi lại thuật toán khi mình dùng 2 hàm Transpose lồng vào nhau.
Quá trình nó xảy ra như nào để biến Range thành mảng 1 chiều

Cám ơn Anh/Chị
Lấy ví dụ cho dễ hiểu:
- 1 Range nhiều dòng, 1 cột, qua hàm TRANSPOSE luôn trở thành mảng 1 chiều
- Các trường hợp còn lại của Range (trừ trường hợp 1 cell), qua hàm TRANSPOSE luôn trở thành mảng 2 chiều
- TRANSPOSE cũng biểu hiện tương tự như thế khi làm việc với Array
------------
Về lý thuyết thì đúng ra hàm TRANSPOSE chỉ xoay dữ liệu 90 độ và giữ nguyên số chiều, ngoại trừ trường hợp đăc biệt ở trên (nó bỏ luôn chiều thứ nhất khiến mảng kết quả trở thành mảng 1 chiều)
 
Upvote 0
Tại sheet1.range("A1:A10") có dữ liệu.
Tại sheet1, em insert 1 listbox1
Tại module em cho 1 sub như sau
PHP:
 Sub test()
    Sheet1.listbox1.List() = Sheet1.Range("A1:A10").Value
 End Sub

Không hiểu sau khi chạy sub em không thấy dữ liệu từ A1:A10 sheet1 nạp vào list box1?
Nó báo lỗi và bôi vàng tại chữ Listbox1

Xin chỉ giúp
 
Lần chỉnh sửa cuối:
Upvote 0
Tại sheet1.range("A1:A10") có dữ liệu.
Tại sheet1, em insert 1 listbox1
Tại module em cho 1 sub như sau
PHP:
 Sub test()
    Sheet1.listbox1.List() = Sheet1.Range("A1:A10").Value
 End Sub

Không hiểu sau khi chạy sub em không thấy dữ liệu từ A1:A10 sheet1 nạp vào list box1?
Nó báo lỗi và bôi vàng tại chữ Listbox1

Xin chỉ giúp
Code này đúng ra không có vấn đề. Tuy nhiên, nếu bạn test bị lỗi thì có thể đưa nguyên file lên đây để tìm nguyên nhân (có thể sai chổ nào đó mà bạn chưa biết, chẳng hạn sai tên sheet hoặc giả cái ListBox mà bạn chèn không phải thuộc nhóm ActiveX....)
 
Upvote 0
Code này đúng ra không có vấn đề. Tuy nhiên, nếu bạn test bị lỗi thì có thể đưa nguyên file lên đây để tìm nguyên nhân (có thể sai chổ nào đó mà bạn chưa biết, chẳng hạn sai tên sheet hoặc giả cái ListBox mà bạn chèn không phải thuộc nhóm ActiveX....)

Em kiểm tra lại, đúng như anh NDU nói, Listbox em đang dùng không thuộc ActiveX Control mà thuộc Form Controll

Vậy khi nào mình dùng
ActiveX Control và khi nào dùng
Form Controll
 
Upvote 0
Em kiểm tra lại, đúng như anh NDU nói, Listbox em đang dùng không thuộc ActiveX Control mà thuộc Form Controll

Vậy khi nào mình dùng
ActiveX Control và khi nào dùng
Form Controll
Bạn dùng cái gì cũng được cả, miễn sao cảm thấy hợp lý về mặt sử dụng
Code đương nhiên cũng phải được viết hợp lý cho từng loại object
 
Upvote 0
PHP:
 ReDim Arr(1 To UBound(sArray), 1 To UBound(sArray, 2))


Trong đoạn code trên tại sao mình không dùng là
1 to 2
mà phải là
1 To UBound(sArray, 2)


 
Upvote 0

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

Back
Top Bottom