Các câu hỏi về mảng trong VBA (Array) (1 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ị
 
Các anh cho e hỏi. E có 1 mãng từ A1:A10. Em muốn tìm giá trị của cell B1 trong mãng nói trên nếu có thì xuất giá trị đó vào cell C1. Em phải code như thế nào vậy các anh
Nghĩ cũng lạ, nếu trong dãy A1:A10 có chứa giá trị của B1 thì C1 được gán giá trị đó, vậy sao không dùng công thức tại C1: =IF(COUNTIF(A1:A10,B1),B1,"") luôn cho rồi cần gì phải tính trong mảng chứ?
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các Thầy hướng dẫn (hoặc cho link) về gộp 2 mảng 2 chiều thành 1 mảng 2 chiều khác.
Cụ thể sArr1(1 to n,1 to 2); sArr2(1 to m, 1 to 2); mảng mới sArr(1 to n+m, 1 to 2).
Gộp 2 mảng 1 chiều thì tạm thời em dùng Split sau đó Join lại. Gộp 2 mảng 2 chiều thì tìm chưa thấy.
Chân thành cảm ơn!
 
Upvote 0
Nhờ các Thầy hướng dẫn (hoặc cho link) về gộp 2 mảng 2 chiều thành 1 mảng 2 chiều khác.
Cụ thể sArr1(1 to n,1 to 2); sArr2(1 to m, 1 to 2); mảng mới sArr(1 to n+m, 1 to 2).
Gộp 2 mảng 1 chiều thì tạm thời em dùng Split sau đó Join lại. Gộp 2 mảng 2 chiều thì tìm chưa thấy.
Chân thành cảm ơn!

bạn đọc bài #469 trong topic này của Thầy Ndu là có ngay đáp án !
 
Upvote 0
Em có 2 câu hỏi?
Câu 1:
Ví dụ với i = 20 thì
Range("A1:B" & i).select sẽ có giá trị mảng là bao nhiêu vậy ah.

Để biết mảng đó trên cửa số Immediate, thì mình dùng lệnh gì vậy?

Câu 2: Khai báo Dim endR& dấu & đây mang nghĩa là gì ah
 
Upvote 0
Em có 2 câu hỏi?
Câu 1:
Ví dụ với i = 20 thì
Range("A1:B" & i).select sẽ có giá trị mảng là bao nhiêu vậy ah.

Để biết mảng đó trên cửa số Immediate, thì mình dùng lệnh gì vậy?

Câu 2: Khai báo Dim endR& dấu & đây mang nghĩa là gì ah
Tôi trả lời câu hỏi của bạn

1/ Câu 1:
Mã:
Ví dụ với i = 20 thì
Range("A1:B" & i).select sẽ có giá trị mảng là bao nhiêu vậy ah.

=> Bạn thế i vào chỗ range sẽ được: Range("A1:B20").Select => Vùng A1:B20 được bôi đen (có .select). Đây đơn thuần chỉ là lựa chọn một vùng chứ chẳng liên quan gì tới mảng cả

2/ Câu 2:
Mã:
[COLOR=#000000]Khai báo Dim endR[/COLOR][B]& dấu & đây mang nghĩa là gì ah[/B]
Bạn tham khảo topic sau sẽ rõ, song đây là cách khai báo biến không tường minh nên tôi nghĩ là thói quen không tốt.

http://www.giaiphapexcel.com/forum/showthread.php?82192-Khai-báo-biến-trong-VBA
 
Upvote 0
Em có 2 câu hỏi?
Câu 1:
Ví dụ với i = 20 thì
Range("A1:B" & i).select sẽ có giá trị mảng là bao nhiêu vậy ah.

Để biết mảng đó trên cửa số Immediate, thì mình dùng lệnh gì vậy?

Câu 2: Khai báo Dim endR& dấu & đây mang nghĩa là gì ah
Câu 1: Phương thức Select là chọn vùng, không có mảng nào được tạo ra ở đây cả. Mà tôi không hiểu giá trị mảng bạn đề cập là cái gì, là số phần tử, là giá trị của các phần tử hay là độ lớn của chiều 1, chiều 2...
Câu 2: & là khai báo biến dạng Long: endR& ~ endR As Long
 
Upvote 0
Câu 1: Phương thức Select là chọn vùng, không có mảng nào được tạo ra ở đây cả. Mà tôi không hiểu giá trị mảng bạn đề cập là cái gì, là số phần tử, là giá trị của các phần tử hay là độ lớn của chiều 1, chiều 2...
Câu 2: & là khai báo biến dạng Long: endR& ~ endR As Long
Đoạn cụ thể ntn chú ah
endR = .Cells(400, 3).End(xlUp).Row
Arr = .Range("A2:C" & endR).Value

Với cháu hỏi thêm xúi. câu lênh để đưa kết quả địa chỉ ARR lên msgbox hoặc công cụ intemediate
 
Lần chỉnh sửa cuối:
Upvote 0
Đoạn cụ thể ntn chú ah
endR = .Cells(400, 3).End(xlUp).Row
Arr = .Range("A2:C" & endR).Value

Với cháu hỏi thêm xúi. câu lênh để đưa kết quả địa chỉ ARR lên msgbox hoặc công cụ intemediate
Mảng Arr thì không có địa chỉ, chỉ có phần tử trong mảng thôi.
Có thể truy vấn thế này
MsgBox Arr(1,1) sẽ trả về phần tử đầu tiên. Dùng vòng lặp để duyệt hết các phần tử trong mảng
 
Upvote 0
Nhờ các Thầy hướng dẫn (hoặc cho link) về gộp 2 mảng 2 chiều thành 1 mảng 2 chiều khác.
Cụ thể sArr1(1 to n,1 to 2); sArr2(1 to m, 1 to 2); mảng mới sArr(1 to n+m, 1 to 2).
Gộp 2 mảng 1 chiều thì tạm thời em dùng Split sau đó Join lại. Gộp 2 mảng 2 chiều thì tìm chưa thấy.
Chân thành cảm ơn!
Nếu chưa có cách nào hay thì dùng tạm cách của anh xem sao. Kiểu gì cũng mần được nhưng hơi kỳ kỳ chút
PHP:
Sub test()
Dim arr1(), Arr2(), Arr3(), i, j
arr1 = [A1:B3].Value
Arr2 = [E1:F3].Value
ReDim Arr3(1 To UBound(arr1) + UBound(Arr2), 1 To 2)
For i = 1 To UBound(arr1)
   Arr3(i, 1) = arr1(i, 1)
   Arr3(i, 2) = arr1(i, 2)
Next
For j = 1 To UBound(Arr2)
   Arr3(j +UBound(arr1), 1) = Arr2(j, 1)
   Arr3(j +UBound(arr1), 2) = Arr2(j, 2)
Next
[H1].Resize(UBound(Arr3), 2) = Arr3
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Nối 2 mảng:
Nếu đã có chỗ chép mảng ra thì tội gì phải làm phép nối.
- Chép mảng 1 vào vị trí đầu.
- Chép mảng 2 vào vị trí với Offset số dòng = số dòng (Ubound) mảng 1
- Đọc vùng vừa chép vào mảng 3; số dòng = Ubound(mảng 1) + Ubound(mảng 2)

Nối 2 mảng, không có chỗ chép xuống:

Mã:
' code này đặt trên giả thuyết là mảng lấy từ range; LBound là 1
' nếu LBound là 0 thì phải chỉnh sửa lại cách đếm.
' Tuy nhiên nguyên tắc giải thuật thì vẫn vậy
d1 = UBound(mang1,1) ' số dòng mảng 1
d2 = UBound(mang2,1) ' số dòng mảng 2
c1 = UBound(mang1,2) ' số cột mảng 1
c2 = UBound(mang2,2) ' số cột mảng 2
' định độ lớn mảng 3, số dòng là tổng số dòng, số cột là số lớn hơn giữa 2 số cột
Redim mang3(1 to d1 + d2, 1 to IIf(c1 > c2, c1, c2))
For d0 = 1 To d1 ' chép mảng 1
  For c0 = 1 To c1
    mang3(d0,c0) = mang1(d0,c0)
  Next c0
Next d0
For d0 = 1 To d2 ' chép mảng 2
  For c0 = 1 To c2
    mang3(d0+d1,c0) = mang2(d0,c0)
  Next c0
Next d0
 
Lần chỉnh sửa cuối:
Upvote 0
Hình như có thể chép thẳng mảng 1 vào mảng 3 (1 lênh mang3 = mang1). Kế đó Redim Preserve thnahf tổng số dòng và số cột lớn. Sau cùng là chép từng phần tử mảng 2 vào.
Cách này chưa thử nên chưa biết chắc.

Có cách chép nhanh hơn nhưng phải dùng hàm Memcpy của Library. Hàm này chép thẳng một khối dữ liệu trong bộ nhớ từ vùng này sang vùng kia. Hình như hàm này viết bằng C hay gì đó Assembly nên rất hiệu quả.
 
Upvote 0
Hình như có thể chép thẳng mảng 1 vào mảng 3 (1 lênh mang3 = mang1). Kế đó Redim Preserve thnahf tổng số dòng và số cột lớn. Sau cùng là chép từng phần tử mảng 2 vào.
Cách này chưa thử nên chưa biết chắc.

Có cách chép nhanh hơn nhưng phải dùng hàm Memcpy của Library. Hàm này chép thẳng một khối dữ liệu trong bộ nhớ từ vùng này sang vùng kia. Hình như hàm này viết bằng C hay gì đó Assembly nên rất hiệu quả.
Cái phần màu đỏ là chưa có chuẩn, vì Redim Preserve chỉ có tác dụng đối với cột còn dòng là không được anh VetMini nhỉ?
 
Upvote 0
Ờ xem kỹ lại thì có chuyện giới hạn đối với mảng nhiều hơn 1 chiều. Tiếc nhỉ.
 
Upvote 0
Cái phần màu đỏ là chưa có chuẩn, vì Redim Preserve chỉ có tác dụng đối với cột còn dòng là không được anh VetMini nhỉ?

Nói tổng quát hơn, ReDim Preserve chỉ cho phép thay đổi kích thước chiều cuối cùng của mảng. Nghĩa là mảng 1 chiều có thể thay đổi kích thước, mảng 2 chiều chỉ có thể thay đổi kích thước chiều thứ 2, mảng n chiều chỉ cho thay đổi kích thước chiều thứ n.
 
Upvote 0
Cái phần màu đỏ là chưa có chuẩn, vì Redim Preserve chỉ có tác dụng đối với cột còn dòng là không được anh VetMini nhỉ?

Nói tổng quát hơn, ReDim Preserve chỉ cho phép thay đổi kích thước chiều cuối cùng của mảng. Nghĩa là mảng 1 chiều có thể thay đổi kích thước, mảng 2 chiều chỉ có thể thay đổi kích thước chiều thứ 2, mảng n chiều chỉ cho thay đổi kích thước chiều thứ n.

Tôi nói đến vấn đề "hình như..." là vì nó là chuyện quá khứ đâu đó (*) mà tôi quên mất. Đến chừng xem kỹ lại thì quả là không được.
VBA dùng kỹ thuật thiết lập mảng "trọng cột" (column major) cho nên khi code ReDim chép lại vào mảng mới thì nó chỉ có thể nới rộng hoặc cắt đi phần sau; tức là phần cột (**).

(*) Chuyện quá khứ đó xảy ra ở môi trường khác. Tức là ở môi trường mà mảng được thiết lập theo kiểu "trọng cột" (row major), và code thể dùng con trỏ để copy mảng theo từng khối.

(**) Tôi không rõ đi sâu hơn về kỹ thuật dòng-cột có làm các bạn buòn ngủ hay không nên dừng ở đây. Nếu bạn nào muón tìm hiểu thêm thì cứ việc hỏi. Tôi tim chắc rằng sẽ có bạn trả lời rõ hơn.
 
Upvote 0
(*) Chuyện quá khứ đó xảy ra ở môi trường khác. Tức là ở môi trường mà mảng được thiết lập theo kiểu "trọng cột" (row major), và code thể dùng con trỏ để copy mảng theo từng khối.

(**) Tôi không rõ đi sâu hơn về kỹ thuật dòng-cột có làm các bạn buòn ngủ hay không nên dừng ở đây. Nếu bạn nào muón tìm hiểu thêm thì cứ việc hỏi. Tôi tim chắc rằng sẽ có bạn trả lời rõ hơn.

Bạn gõ nhầm. Chỗ đỏ đỏ là "trọng dòng", do trong ngoặc là row major.

Trong Delphi thì mảng được ghi trong bộ nhớ theo từng DÒNG - HÀNG (tức "trọng dòng" như bạn nói). Tức các ô của dòng là liên tiếp nhưng các cột không hẳn là các vùng liên tiếp. Có thể dùng CopyMemory để copy từng hàng.

Trong VBA cũng chắc chắn là mảng được ghi trong bộ nhớ theo từng CỘT (tức "trọng cột" như bạn nói). Tức các ô của cột là liên tiếp nhưng theo tôi (tức không dám chắc như tôi dám chắc trong Delphi) thì các cột cũng không hẳn là các vùng liên tiếp. Nhưng cũng có thể dùng CopyMemory để copy cả cột.
 
Upvote 0
Tôi nói đến vấn đề "hình như..." là vì nó là chuyện quá khứ đâu đó (*) mà tôi quên mất. Đến chừng xem kỹ lại thì quả là không được.
VBA dùng kỹ thuật thiết lập mảng "trọng cột" (column major) cho nên khi code ReDim chép lại vào mảng mới thì nó chỉ có thể nới rộng hoặc cắt đi phần sau; tức là phần cột (**).
Tôi không rành về ngôn ngữ khác, cả VBA cũng chưa nghiên cứu sâu đến mức row major hay column major, vì tôi chỉ nghiên cứu để thực hành là chính.
Trong thực hành tôi bị báo lỗi khi ReDim Preserve dòng trong mảng 2 chiều, tìm hiểu help thì biết chỉ có thể thay đổi kích thước chiều sau cùng:
If you use the Preserve keyword, you can resize only the last array dimension and you can't change the number of dimensions at all. For example, if your array has only one dimension, you can resize that dimension because it is the last and only dimension. However, if your array has two or more dimensions, you can change the size of only the last dimension and still preserve the contents of the array.

Nhân tiện cũng lạm bàn:
Tôi không biết trọng cột hay trọng dòng là như thế nào, nhưng theo thiển ý thì khi dùng ReDim Preserve để thay đổi kích thước mảng 1 chiều thì không có khái niệm dòng cột, khi dùng để thay đổi kích thước mảng 2 chiều thì chỉ thay đổi kích thước chiều thứ 2 là cột. Nhưng khi thay đổi kích thước chiều thứ 3 của mảng 3 chiều, hay chiều thứ n của mảng n chiều thì lại chẳng phải dòng, cũng chẳng phải cột. Mà VBA hỗ trợ mảng tối đa lên 60 chiều:

Dimensions of an array variable; up to 60 multiple dimensions may be declared

Nên tôi e rằng không liên quan đến trọng dòng trọng cột, hoặc liên quan ở chỗ nào mà tôi không biết?
 
Lần chỉnh sửa cuối:
Upvote 0
Trong hầu hết các ngôn ngữ lập trình, mảng được chứa theo dạng một vùng nhớ liên tục (nếu là chuỗi thì mảng thực ra chứa địa chỉ của những chuỗi, và các địa chỉ này cũng được chứa trong vùng nhớ liên tục).

Tuy nhiên, địa chỉ bộ nhớ được truy cập theo 1 chiều cho nên mảng bắt buộc phải có cách chuyển từ n chiều thành 1 chiều.

Ví dụ, tôi có mảng 1 chiều a (1 to 3) thì trong vùng nhớ, các phần tử được sắp xếp như sau:

| a(1) | a(2) | a(3) |

giả sử mỗi phần tử mảng là một đơn vị địa chỉ (một ô trong bộ nhớ), và mảng bắt đầu từ địa chỉ 1001:

a(1) ở địa chỉ 1001; a(2) ở địa chỉ 1002; a(3) ở địa chỉ 1003

Tuy nhiên, nếu tôi có mảng 2 chiều: a (1 to 3, 1 to 2) [3 dòng, 2 cột] thì sao?

Cách xếp trọng cột, tức là xếp cột 1 trước cột 2::

| a(1,1)| a(2,1) | a(3,1) | a(1,2) | a(2,2) | a(3,2) |

a((1,1) ở 1001; a(2,1) ở 1002; a(3,1) ở 1003, a(1,2) ở 1004; a(2,2) ở 1005; a(3,2) ở 1006

Cách xếp trọng dòng, tức là xếp dòng 1 trước dòng 2 trước dòng 3:

| a(1,1) | a(1,2) | a(2,1) | a(2,2) | a(3,1) | a(3,2) |

a((1,1) ở 1001; a(1,2) ở 1002; …

Lệnh ReDim:

Lệnh này lập một vùng nhớ mới; trỏ mảng vào vùng nhớ này; và báo cho hệ thống biết là vùng nhớ cũ không còn xài nữa.

Lệnh ReDim Preserve:

Tương tự như vậy, nhưng thêm phần chép dữ liệu vùng nhớ cũ vào vùng nhớ mới.

Nếu trong mảng 1 chiều trên, a được đổi thành a(1 to 5) thì lệnh sẽ lấy một khoảng bộ nhớ khác với 5 ô (ví dụ ở 2001-2005). Ta có a mới:

| a(1) | a(2) | a(3) | a(4) | a(5) |

a(1) ở 2001; a(2) ở 2002; a(3) ở 2003; a(4) ở 2004; a(5) ở 2005

Để thực hiện copy dữ liệu, Redim Preserve sẽ dùng hàm tượng tự như MemCpy (hàm này cóp py từng khối chứ không phải từng ô) cóp py 1001-1003 vào 2001-2003.

Nếu trong mảng 2 chiều trên, a được đổi thành a(1 to 4, 1 to 2) [tăng lên 1 dòng] thì sao?

Cách xếp trọng cột:

| a(1,1)| a(2,1) | a(3,1) | a(4,1) | a(1,2) | a(2,2) | a(3,2) | a(4,2) |

Đến lúc cóp py dữ liệu Preserve không thể nào cóp py 1001-1006 vào 2001-2006 được. Vì chép 1001-1003 thì xuôi, nhưng đến 1004 thì vốn là a(1,2), nếu chép vào 2004 thì bị trật phần tử (2004 là địa chỉ mới của a(4,1), trong khi địa chỉ mới của a(1,2) phải là 2005).

Mặt khác, cũng với cách xếp trọng cột, a được đổi thành a(1 to 3, 1 to 3) [tăng lên 1 cột] thì sao?

| a(1,1)| a(2,1) | a(3,1) | a(1,2) | a(2,2) | a(3,2) | a(3,3) | a(2,3) | a(3,3) |

Ta thấy 1001-1006 có thể chép thẳng vào 2001-2006.

Vì vậy ngôn ngữ trọng cột bắt buộc không cho phép thay đổi số hàng. Mà chỉ được thay đổi số cột

@siwtom: cảm ơn bạn đã nhắc, tôi gõ nhầm thật: tôi gõ "trọng cột" (row major); trong khi "trọng dòng" (row major) mới đúng.
Hầu hết các ngôn ngữ sau này đều dùng "trọng dòng". Tôi nhớ mang máng Delphi vốn gần với Pascal, mà Pascal thì vốn được đặt ra để dạy Angol 60 cho nên nó thiết kế theo ý nghĩa đại số hơn. Theo tôi nghĩ thì BASIC vốn đi đôi với FORTRAN, là ngôn ngữ cổ cho nên nó dùng trọng cột (nghĩ vậy chứ chả có gì quyết đoán).
 
Lần chỉnh sửa cuối:
Upvote 0
....

Để thực hiện copy dữ liệu, Redim Preserve sẽ dùng hàm tượng tự như MemCpy (hàm này cóp py từng khối chứ không phải từng ô) cóp py 1001-1003 vào 2001-2003.

....

Tôi thấy bài viết của Nguyễn Duy Tuân rất tuyệt trong việc cắt, ghép, delete, insert trong mảng:

http://www.giaiphapexcel.com/forum/...rong-bộ-nhớ-Tốc-độ-nhanh!&p=479565#post479565

Các bạn theo link trên mà tham khảo nhé!
 
Upvote 0
Trong hầu hết các ngôn ngữ lập trình, mảng được chứa theo dạng một vùng nhớ liên tục (nếu là chuỗi thì mảng thực ra chứa địa chỉ của những chuỗi, và các địa chỉ này cũng được chứa trong vùng nhớ liên tục).

Tuy nhiên, địa chỉ bộ nhớ được truy cập theo 1 chiều cho nên mảng bắt buộc phải có cách chuyển từ n chiều thành 1 chiều.
Như vậy, với những ví dụ của VetMini thì tôi đã hiểu nếu ReDim Preserve chiều thứ nhất (dòng) thì không chép được nguyên khối dữ liệu của mảng sang vị trí mới của bộ nhớ.
Mảng 3 chiều trở lên cũng có thể suy ra tương tự.

Như vậy chuyện "trọng cột" chắc cũng chỉ là dùng từ ngữ 1 cách tương đối thôi, chứ chiều thứ 3 có thể gọi là chiều "sâu", chiều thứ 4 trở lên chăng biết gọi là gì, chẳng phải dòng, cột, nên "trọng cột" theo nghĩa đen không phù hợp nữa. Phải là "trọng sâu" hoặc nói chung là "trọng cuối", (he he, tèn tèn, ẹc ẹc, hic hic)
 
Upvote 0
Nhờ các Thầy đoạn code sau, xem có vấn đề gì về giải thuật không, mà em kiểm tra hoài không thấy, xem như các điều kiện trong code đều thoả mãn.
[gpecode=vb]
Sub Button2_Click()
Dim iR As Long, jR As Long, kR As Long, sArr(), CpArr(), rArr()
sArr = Sheet2.Range("A2:Q" & Sheet2.[C1000000].End(3).Row).Value
CpArr = Sheet3.Range("J10:J" & Sheet3.[J1000000].End(3).Row).Value
ReDim rArr(LBound(CpArr, 1) To UBound(CpArr, 1), 1 To 7)
Sheet1.[A4].CurrentRegion.ClearContents
For iR = 1 To UBound(sArr, 1)
If Len(sArr(iR, 1)) Then
If Left(sArr(iR, 1), 1) = "C" And Mid(sArr(iR, 1), 4, 1) = "K" Then
For jR = 1 To UBound(CpArr, 1)
If sArr(iR, 2) = CpArr(jR, 1) Then
kR = kR + 1
rArr(kR, 1) = kR
rArr(kR, 2) = sArr(iR, 1)
rArr(kR, 3) = sArr(iR, 2)
rArr(kR, 4) = sArr(iR, 3)
rArr(kR, 5) = sArr(iR, 16)
rArr(kR, 6) = sArr(iR, 17)
rArr(kR, 7) = sArr(iR, 4)
End If
Next jR
End If
End If
Next iR
If kR Then
Sheet1.[A5].Resize(kR, 7) = rArr
End If
End Sub
[/gpecode]
---
Sheet2 là Data (dữ liệu hơn 200k dòng, 17 cột) với cột 1 là mã hàng, cột 2 là số hoá đơn.
Sheet3 là số hoá đơn đã thanh toán.
Sheet1 là báo cáo hoá đơn đã thanh toán: Lọc 6 cột từ Data và 1 cột Stt.
---
Chân thành cảm ơn!
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các Thầy đoạn code sau, xem có vấn đề gì về giải thuật không, mà em kiểm tra hoài không thấy, xem như các điều kiện trong code đều thoả mãn.
[gpecode=vb]
Sub Button2_Click()
Dim iR As Long, jR As Long, kR As Long, sArr(), CpArr(), rArr()
sArr = Sheet2.Range("A2:Q" & Sheet2.[C1000000].End(3).Row).Value
CpArr = Sheet3.Range("J10:J" & Sheet3.[J1000000].End(3).Row).Value
ReDim rArr(LBound(CpArr, 1) To UBound(CpArr, 1), 1 To 7)
Sheet1.[A4].CurrentRegion.ClearContents
For iR = 1 To UBound(sArr, 1)
If Len(sArr(iR, 1)) Then
If Left(sArr(iR, 1), 1) = "C" And Mid(sArr(iR, 1), 4, 1) = "K" Then
For jR = 1 To UBound(CpArr, 1)
If sArr(iR, 2) = CpArr(jR, 1) Then
kR = kR + 1
rArr(kR, 1) = kR
rArr(kR, 2) = sArr(iR, 1)
rArr(kR, 3) = sArr(iR, 2)
rArr(kR, 4) = sArr(iR, 3)
rArr(kR, 5) = sArr(iR, 16)
rArr(kR, 6) = sArr(iR, 17)
rArr(kR, 7) = sArr(iR, 4)
End If
Next jR
End If
End If
Next iR
If kR Then
Sheet1.[A5].Resize(kR, 7) = rArr
End If
End Sub
[/gpecode]
---
Sheet2 là Data (dữ liệu hơn 200k dòng, 17 cột) với cột 1 là mã hàng, cột 2 là số hoá đơn.
Sheet3 là số hoá đơn đã thanh toán.
Sheet1 là báo cáo hoá đơn đã thanh toán: Lọc 6 cột từ Data và 1 cột Stt.
---
Chân thành cảm ơn!
Sau không dùng Dic ta? Duyệt kiểu này e rằng hơi chậm.
 
Upvote 0
Nhờ các Thầy đoạn code sau, xem có vấn đề gì về giải thuật không, mà em kiểm tra hoài không thấy, xem như các điều kiện trong code đều thoả mãn.

Chân thành cảm ơn!

Lấn cấn ở chỗ này đây:

Mã:
CpArr = Sheet3.Range("J10:J" & Sheet3.[J1000000].End(3).Row).Value
ReDim rArr(LBound(CpArr, 1) To [COLOR=#ff0000][B]UBound(CpArr, 1)[/B][/COLOR], 1 To 7)

Ta giả sử

2 vòng lặp For đều thõa mãn với các điều kiện thì mảng rArr sẽ bị tràn dòng, bởi kR là kết quả của 1 phép nhân.

Một thủ tục cơ bản dưới đây sẽ cho thấy k không phải là 10 mà là 100

Mã:
Sub test()
    Dim i, j, k
    For i = 1 To 10
        For j = 1 To 10
            k = k + 1
        Next
    Next
    MsgBox k
End Sub

Vì thế nếu thủ tục của Thảo thỏa hết mọi điều kiện thì thủ tục sẽ báo lỗi tràn dòng.
 
Lần chỉnh sửa cuối:
Upvote 0
Lấn cấn ở chỗ này đây:

Mã:
CpArr = Sheet3.Range("J10:J" & Sheet3.[J1000000].End(3).Row).Value
ReDim rArr(LBound(CpArr, 1) To [COLOR=#ff0000][B]UBound(CpArr, 1)[/B][/COLOR], 1 To 7)
Ta giả sử
2 vòng lặp For đều thõa mãn với các điều kiện thì mảng rArr sẽ bị tràn dòng, bởi kR là kết quả của 1 phép nhân.
Một thủ tục cơ bản dưới đây sẽ cho thấy k không phải là 10 mà là 100
Mã:
Sub test()
    Dim i, j, k
    For i = 1 To 10
        For j = 1 To 10
            k = k + 1
        Next
    Next
    MsgBox k
End Sub
Vì thế nếu thủ tục của Thảo thỏa hết mọi điều kiện thì thủ tục sẽ báo lỗi tràn dòng.
Em kiểm tra thì kR = 0.
Vòng For jR chỉ lấy được 1 giá trị thỏa mãn, không phải thỏa hết nên làm sao nó thành cấp số nhân được?
 

File đính kèm

Upvote 0
Nhờ các Thầy đoạn code sau, xem có vấn đề gì về giải thuật không, mà em kiểm tra hoài không thấy, xem như các điều kiện trong code đều thoả mãn.
[gpecode=vb]
Sub Button2_Click()
Dim iR As Long, jR As Long, kR As Long, sArr(), CpArr(), rArr()
sArr = Sheet2.Range("A2:Q" & Sheet2.[C1000000].End(3).Row).Value
CpArr = Sheet3.Range("J10:J" & Sheet3.[J1000000].End(3).Row).Value
ReDim rArr(LBound(CpArr, 1) To UBound(CpArr, 1), 1 To 7)
Sheet1.[A4].CurrentRegion.ClearContents
For iR = 1 To UBound(sArr, 1)
If Len(sArr(iR, 1)) Then
If Left(sArr(iR, 1), 1) = "C" And Mid(sArr(iR, 1), 4, 1) = "K" Then
For jR = 1 To UBound(CpArr, 1)
If sArr(iR, 2) = CpArr(jR, 1) Then
kR = kR + 1
rArr(kR, 1) = kR
rArr(kR, 2) = sArr(iR, 1)
rArr(kR, 3) = sArr(iR, 2)
rArr(kR, 4) = sArr(iR, 3)
rArr(kR, 5) = sArr(iR, 16)
rArr(kR, 6) = sArr(iR, 17)
rArr(kR, 7) = sArr(iR, 4)
End If
Next jR
End If
End If
Next iR
If kR Then
Sheet1.[A5].Resize(kR, 7) = rArr
End If
End Sub
[/gpecode]
---
Sheet2 là Data (dữ liệu hơn 200k dòng, 17 cột) với cột 1 là mã hàng, cột 2 là số hoá đơn.
Sheet3 là số hoá đơn đã thanh toán.
Sheet1 là báo cáo hoá đơn đã thanh toán: Lọc 6 cột từ Data và 1 cột Stt.
---
Chân thành cảm ơn!

Thế "mà em kiểm tra CÁI GÌ hoài không thấy"?
Code có lỗi? Code không có lỗi error nhưng kết quả nhận được không đúng ý? Bạn hỏi kiểu đó thì khó cho người giúp rồi.

Bạn không nói mục đích code làm gì, có lỗi hay kết quả không đúng nên tôi chỉ đoán. Bạn không nhận được bất cứ kết quả nào? Vì như bạn nói ở bài #525 thì kR = 0.

Bạn hãy sửa

Mã:
If sArr(iR, 2) = CpArr(jR, 1) Then

thành

Mã:
If [COLOR=#ff0000]CLng([/COLOR]sArr(iR, 2)[COLOR=#ff0000])[/COLOR] = CpArr(jR, 1) Then
 
Upvote 0
Nhờ các Thầy đoạn code sau, xem có vấn đề gì về giải thuật không, mà em kiểm tra hoài không thấy, xem như các điều kiện trong code đều thoả mãn.
[gpecode=vb]
Sub Button2_Click()
Dim iR As Long, jR As Long, kR As Long, sArr(), CpArr(), rArr()
sArr = Sheet2.Range("A2:Q" & Sheet2.[C1000000].End(3).Row).Value
CpArr = Sheet3.Range("J10:J" & Sheet3.[J1000000].End(3).Row).Value
ReDim rArr(LBound(CpArr, 1) To UBound(CpArr, 1), 1 To 7)
Sheet1.[A4].CurrentRegion.ClearContents
For iR = 1 To UBound(sArr, 1)
If Len(sArr(iR, 1)) Then
If Left(sArr(iR, 1), 1) = "C" And Mid(sArr(iR, 1), 4, 1) = "K" Then
For jR = 1 To UBound(CpArr, 1)
If sArr(iR, 2) = CpArr(jR, 1) Then
kR = kR + 1
rArr(kR, 1) = kR
rArr(kR, 2) = sArr(iR, 1)
rArr(kR, 3) = sArr(iR, 2)
rArr(kR, 4) = sArr(iR, 3)
rArr(kR, 5) = sArr(iR, 16)
rArr(kR, 6) = sArr(iR, 17)
rArr(kR, 7) = sArr(iR, 4)
End If
Next jR
End If
End If
Next iR
If kR Then
Sheet1.[A5].Resize(kR, 7) = rArr
End If
End Sub
[/gpecode]
---
Sheet2 là Data (dữ liệu hơn 200k dòng, 17 cột) với cột 1 là mã hàng, cột 2 là số hoá đơn.
Sheet3 là số hoá đơn đã thanh toán.
Sheet1 là báo cáo hoá đơn đã thanh toán: Lọc 6 cột từ Data và 1 cột Stt.
---
Chân thành cảm ơn!
Một bên là Chuỗi, một bên là số thì làm sao mà so sánh được.
Bạn sửa dòng
PHP:
If sArr(iR, 2) = CpArr(jR, 1) Then
thành
PHP:
If CLng(sArr(iR, 2)) = CLng(CpArr(jR, 1)) Then
là được
 
Upvote 0
Thế "mà em kiểm tra CÁI GÌ hoài không thấy"?
Code có lỗi? Code không có lỗi error nhưng kết quả nhận được không đúng ý? Bạn hỏi kiểu đó thì khó cho người giúp rồi.
Bạn không nói mục đích code làm gì, có lỗi hay kết quả không đúng nên tôi chỉ đoán. Bạn không nhận được bất cứ kết quả nào? Vì như bạn nói ở bài #525 thì kR = 0.
Bạn hãy sửa
Mã:
If sArr(iR, 2) = CpArr(jR, 1) Then
thành
Mã:
If [COLOR=#ff0000]CLng([/COLOR]sArr(iR, 2)[COLOR=#ff0000])[/COLOR] = CpArr(jR, 1) Then
Dạ, em có hỏi về giải thuật, xem có vấn đề gì không, đúng là câu hỏi còn thiếu nhiều vế quá, mong Thầy thông cảm!
Cho em hỏi tại sao phải chuyển phần tử mảng sArr qua biến Long, vì em đã test thử, gán sArr(61706,2) xuống sheet thì trả ra kết quả số?
Cảm ơn Thầy và huuthang_bd!
 
Upvote 0
Dạ, em có hỏi về giải thuật, xem có vấn đề gì không, đúng là câu hỏi còn thiếu nhiều vế quá, mong Thầy thông cảm!
Cho em hỏi tại sao phải chuyển phần tử mảng sArr qua biến Long, vì em đã test thử, gán sArr(61706,2) xuống sheet thì trả ra kết quả số?
Cảm ơn Thầy và huuthang_bd!
Nếu gán dữ liệu là một chuỗi số vào một ô thì kết quả còn tùy thuộc vào kiểu định dạng của ô đó.
Bạn thử lệnh này với ActiveCell được định dạng lần lượt là General, Text và Number xem.
PHP:
ActiveCell.Value = "0000001"
 
Upvote 0
Dạ, em có hỏi về giải thuật, xem có vấn đề gì không, đúng là câu hỏi còn thiếu nhiều vế quá, mong Thầy thông cảm!
Cho em hỏi tại sao phải chuyển phần tử mảng sArr qua biến Long, vì em đã test thử, gán sArr(61706,2) xuống sheet thì trả ra kết quả số?
Cảm ơn Thầy và huuthang_bd!

Dĩ nhiên, nhưng bạn có 11160 chứ không phải là 0011160. Tôi nghĩ là Excel "dọc đường" đi xuống sheet đã convert 0011160 thành số.

Vì lý do nào đó mà khi so sánh "sArr(iR, 2) = CpArr(jR, 1)" thì Excel không convert sArr(iR, 2) thành số. Nhưng nếu bạn có "CLng(sArr(iR, 2)) = CpArr(jR, 1)" thì vế trái đã bị ép thành số.

Cũng có thể
Mã:
Dim tmp As Long
...
                If iR = 61706 Then
                    MsgBox "he"
                End If
                [COLOR=#ff0000]tmp = sArr(iR, 2)[/COLOR]
                For jR = 1 To UBound(CpArr, 1)
                    If tmp = CpArr(jR, 1) Then
                        kR = kR + 1
                        rArr(kR, 1) = kR
                        rArr(kR, 2) = sArr(iR, 1)
                        rArr(kR, 3) = sArr(iR, 2)
                    End If
                Next jR

Vì tmp là Long nên chỗ đỏ đỏ đã có việc convert "sArr(iR, 2)" thành số để "nhồi" vào tmp.

Tốt nhất là dùng tmp = sArr(iR, 2). Vì chả lý gì trong vòng lặp lặp vd. 1000 lần thì convert 1000 lần sArr(iR, 2) thành số như code "CLng(sArr(iR, 2)) = CpArr(jR, 1)". Dùng tmp = sArr(iR, 2) ta chỉ convert 1 lần duy nhất.
 
Upvote 0
Tốt nhất là dùng tmp = sArr(iR, 2). Vì chả lý gì trong vòng lặp lặp vd. 1000 lần thì convert 1000 lần sArr(iR, 2) thành số như code "CLng(sArr(iR, 2)) = CpArr(jR, 1)". Dùng tmp = sArr(iR, 2) ta chỉ convert 1 lần duy nhất.
Vì em mới vọc vào mảng nên có nhiều điều chưa hiểu cũng như về cách diễn đạt. Em hay kiểm tra thử kết quả trả về rồi gán lên sheet để biết tìm lỗi và cách giải quyết. Vì vậy mà "kiểm tra hoài không thấy" nguyên nhân không đạt kết quả.
Cảm ơn Thầy và huuthang_bd đã hướng dẫn!
 
Upvote 0
Em kiểm tra thì kR = 0.
Vòng For jR chỉ lấy được 1 giá trị thỏa mãn, không phải thỏa hết nên làm sao nó thành cấp số nhân được?
Chỉ vậy thôi sao? Nếu thỏa hết điều kiện thì tính sao? Thay vì CSDL gốc có 10 dòng, và CSDL so sánh có 20 dòng, nếu lặp đi lặp lại phải chăng là có gì đó rất thừa không, còn nếu cứ để luôn vậy và đúng hết thì mảng kết quả chỉ được ReDim có 10 dòng, trong khi đó kR lại hơn số đó thì tính sao?

Với lại nói thêm là:

Thay vì thế này:

Mã:
        If Len(sArr(iR, 1)) Then
            If Left(sArr(iR, 1), 1) = "C" And Mid(sArr(iR, 1), 4, 1) = "K" Then
.
.
.
            End If
        End If

Thì chỉ cần như thế này là đủ:

Mã:
[COLOR=#0000ff]If [/COLOR][COLOR=#ff0000]CStr[/COLOR][COLOR=#0000ff](ArrSh2(R2, 1)) [/COLOR][COLOR=#ff0000]Like [/COLOR][COLOR=#008080]"C??K*"[/COLOR][COLOR=#0000ff] Then
[/COLOR].
.
.
[COLOR=#0000ff]End If[/COLOR]
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Đúng. Chỉ khi thỏa mãn điều kiện If thì kR mới tăng 1, nên không thể nào là nhân.

Chắc ý Nghĩa là nói về trường hợp khi dữ liêu với tất cả các dòng đều có dạng "C??K" ở cột 1 và đều là xyz ở cột 2, đồng thời với mọi dòng của CpArr đều có CpArr(jR, 1) = xyz = sArr(iR, 2)

Lúc đó có kR = UBound(sArr, 1) * UBound(CpArr, 1)

Nhưng dữ liệu như thế có lẽ không có, nó quái đản quá.

Câu hỏi leonguyenz. Do bạn không mô tả bạn định làm gì, yêu cầu thế nào nên tôi hỏi.

Vd. ta có 5 dòng và chỉ 5 dòng trong sheet2 y như nhau, tức cột 1 là "C??K" và cột 2 là vd. 0011160. Giả dụ trong sheet3 có 2 dòng là 11160. Như thế kết quả của bạn sẽ là 10 dòng y như nhau chỉ trừ cột đầu là kR = 1, 2, ..., 10

Bạn cần 10 dòng y như nhau để làm gì?
 
Upvote 0
Chắc ý Nghĩa là nói về trường hợp khi dữ liêu với tất cả các dòng đều có dạng "C??K" ở cột 1 và đều là xyz ở cột 2, đồng thời với mọi dòng của CpArr đều có CpArr(jR, 1) = xyz = sArr(iR, 2)

Lúc đó có kR = UBound(sArr, 1) * UBound(CpArr, 1)

Nhưng dữ liệu như thế có lẽ không có, nó quái đản quá.

Câu hỏi leonguyenz. Do bạn không mô tả bạn định làm gì, yêu cầu thế nào nên tôi hỏi.

Vd. ta có 5 dòng và chỉ 5 dòng trong sheet2 y như nhau, tức cột 1 là "C??K" và cột 2 là vd. 0011160. Giả dụ trong sheet3 có 2 dòng là 11160. Như thế kết quả của bạn sẽ là 10 dòng y như nhau chỉ trừ cột đầu là kR = 1, 2, ..., 10

Bạn cần 10 dòng y như nhau để làm gì?
Theo giải thích của leo mà tôi hiểu được, thì
- Sheet Data liệt kê tất cả các hóa đơn đã bán hàng, với sự kết hợp C??K và số hóa đơn thì gần như số hóa đơn là duy nhất
- Sheet3 liệt kê hóa đơn đã thanh toán thì cũng duy nhất (1 hóa đơn đã thanh toán không liệt kê 2 lần)
Tất nhiên cũng có thể có lỗi dữ liệu và có thể trùng, nhưng đa phần là không, nếu có cũng không đến nỗi nhân lên.
Ngoài ra, code dùng đễ test ra kết quả 10 x 10 = 100 không hề có cái điều kiện If iếc nảo, nên không phù hợp để test với dữ liệu và code gốc.
 
Lần chỉnh sửa cuối:
Upvote 0
Theo giải thích của leo mà tôi hiểu được, thì
- Sheet Data liệt kê tất cả các hóa đơn đã bán hàng, với sự kết hợp C??K và số hóa đơn thì gần như số hóa đơn là duy nhất
- Sheet3 liệt kê hóa đơn đã thanh toán thì cũng duy nhất (1 hóa đơn đã thanh toán không liệt kê 2 lần)
Tất nhiên cũng có thể có lỗi dữ liệu và có thể trùng, nhưng đa phần là không, nếu có cũng không đến nỗi nhân lên.
Ngoài ra, code dùng đễ test ra kết quả 10 x 10 = 100 không hề có cái điều kiện If iếc nảo, nên không phù hợp để test với dữ liệu và code gốc.

Tôi chỉ đoán ý của Nghĩa thôi chứ rõ ràng không có dữ liệu nào quái đản đến mức 200000 dòng như nhau và bên kia cũng 200000 dòng như nhau để dẫn tới kR quá lớn (hàng chục tỷ). Còn nếu thậm chí 100.000 dòng như nhau và 10.000 dòng như nhau thì cũng chỉ là kR = 1000.000.000 (1 tỷ) chưa tràn được bộ nhớ.

À mà sheet trong Excel mới nhất có thể có bao nhiêu dòng nhỉ?
 
Upvote 0
Tôi chỉ đoán ý của Nghĩa thôi chứ rõ ràng không có dữ liệu nào quái đản đến mức 200000 dòng như nhau và bên kia cũng 200000 dòng như nhau để dẫn tới kR quá lớn (hàng chục tỷ). Còn nếu thậm chí 100.000 dòng như nhau và 10.000 dòng như nhau thì cũng chỉ là kR = 1000.000.000 (1 tỷ) chưa tràn được bộ nhớ.

À mà sheet trong Excel mới nhất có thể có bao nhiêu dòng nhỉ?
ý của Nghĩa không phải tràn bộ nhớ mà là "tràn dòng". Bên trên Redim mảng kết quả vừa bằng số dòng của các hóa đơn đã thanh toán, nên chỉ cần trùng 1 lần đã có thể "tràn dòng" (subscript out of range)
Chỉ có điều là test không đúng trường hợp: code gốc có xét điều kiện, code test thì không, sinh ra bài toán nhân.
 
Upvote 0
ý của Nghĩa không phải tràn bộ nhớ mà là "tràn dòng". Bên trên Redim mảng kết quả vừa bằng số dòng của các hóa đơn đã thanh toán, nên chỉ cần trùng 1 lần đã có thể "tràn dòng" (subscript out of range)
Chỉ có điều là test không đúng trường hợp: code gốc có xét điều kiện, code test thì không, sinh ra bài toán nhân.

Tôi chỉ đọc lướt qua 1 lần nên nhớ mang máng. Thì ra là tràn dòng. He he.
 
Upvote 0
Tôi chỉ đoán ý của Nghĩa thôi chứ rõ ràng không có dữ liệu nào quái đản đến mức 200000 dòng như nhau và bên kia cũng 200000 dòng như nhau để dẫn tới kR quá lớn (hàng chục tỷ). Còn nếu thậm chí 100.000 dòng như nhau và 10.000 dòng như nhau thì cũng chỉ là kR = 1000.000.000 (1 tỷ) chưa tràn được bộ nhớ.

À mà sheet trong Excel mới nhất có thể có bao nhiêu dòng nhỉ?

Em diễn giải trên sheet vấn đề này, dữ liệu như thế không thể là quái đản được!

Nếu gán số dòng là 30 của mảng 2 thì số dòng kR sẽ tăng lên 40, chỉ cần kR = 31 đã phát sinh lỗi tràn dòng.
 

File đính kèm

Upvote 0
Em diễn giải trên sheet vấn đề này, dữ liệu như thế không thể là quái đản được!

Nếu gán số dòng là 30 của mảng 2 thì số dòng kR sẽ tăng lên 40, chỉ cần kR = 31 đã phát sinh lỗi tràn dòng.

Tôi lấy những con số 100.000, 200.000 chẳng qua là tôi nhầm là bạn viết về tràn bộ nhớ, tràn biến (kR as Long). Vì thế tôi mới nói là 200.000 dòng dữ liệu có 2 cột như nhau là quái đản.
 
Upvote 0
Cũng trên bài này, sau khi sửa lại (dùng biến tạm Tmp As String để thay cho phần tử mảng) và ra kết quả. Em có nhu cầu triển khai theo hướng khác, nhờ các Thầy cho giải thuật:
- Dữ liệu: Sheet2: Data bán hàng, Sheet3: SoHD khách hàng, Sheet4: SoHD Khách hàng đã thanh toán.
- Liệt kê ở Sheet1 MaKH và SoHD từ Sheet2, có trùng SoHD ở Sheet3, nhưng không trùng SoHD đã thanh toán ở Sheet4
- Ghi thêm MaKH và SoHD thanh toán (đợt này) ở Sheet4.
Xin chân thành cảm ơn!
 

File đính kèm

Upvote 0
Mã:
Sub quay()
Dim Aparent(1 To 5), Achild(1 To 3), i As Long


Aparent(1) = Achild
For i = 2 To 3
    Aparent(1)(i) = i
Next i
Aparent(1) = Aparent(1)(2) + Aparent(1)(3)


MsgBox Aparent(1)(2)


End Sub
E đang thử sử dụng mảng trong mảng. Các Anh, Chị và các Thầy cho e hỏi là sau khi e cộng dồn các kết quả con vào Aparent(1) thì không còn truy xuất kết quả con được nữa !
E xin cám ơn !
 
Upvote 0
Mã:
Sub quay()
Dim Aparent(1 To 5), Achild(1 To 3), i As Long


Aparent(1) = Achild
For i = 2 To 3
    Aparent(1)(i) = i
Next i
Aparent(1) = Aparent(1)(2) + Aparent(1)(3)


MsgBox Aparent(1)(2)


End Sub
E đang thử sử dụng mảng trong mảng. Các Anh, Chị và các Thầy cho e hỏi là sau khi e cộng dồn các kết quả con vào Aparent(1) thì không còn truy xuất kết quả con được nữa !
E xin cám ơn !

Đùa với Variant thì phải chịu khó coi chừng kiểu sau khi gán. Nếu không biết cách xét kiểu thì tốt hơn hết là đừng nên chạm vào loại dữ lioệu này, kẻo có ngày bỏng tay.

Thêm vào code trên các lệnh hiển thị kiểu của Aparent(1) sau mỗi lần gán thì sẽ biết tại sao.

Tóm lại, bài này không hẳn là vấn đề của mảng. Nó là vấn đề của kiểu dữ liệu.

Giải thích cho các bạn chưa rõ về kiểu dữ liệu:
Khi không khai báo kiểu thì kiểu được mặc định là Variant.
Vì vậy kiểu của Achild là Variant() - mảng variant; kiểu của Aparent cũng là Variant() - mỗi phần tử của Aparent là Variant, kiểu của Aparent(1) là Variant.
Vì Variant là loại dữ liệu biến hoá được, cho nên khi gán Aparent(1) = Achild thì kiểu của Aparent(1) tự động đổi theo, tức là đổi thành Variant()
Tuy nhiên, khí gán Aparent(1)(i) = i thì kiểu của Aparent(1)(i) đổi thành Long. Lưu ý là đến đây vẫn chưa xác định kiểu rõ rệt cho nên kiểu của Aparent(1) vẫn giữ là Variant().
Khi gán Aparent(1) = Aparent(1)(2) + Aparent(1)(3) thì hệ thống đã xác định được kiểu Long cho Aparent(1); vì Aparent(1)(2) và Aparent(1)(3) là Long nên kết quả của phép cộng chúng là Long
Vì kiểu của Aparent(1) là Long cho nên phép tính truy phần tử mảng theo chỉ số, Aparent(1)(2) không áp dụng được --> lỗi Type Mismatch
 
Upvote 0
Mã:
Sub quay()
Dim Aparent(1 To 5), Achild(1 To 3), i As Long


Aparent(1) = Achild
For i = 2 To 3
    Aparent(1)(i) = i
Next i
Aparent(1) = Aparent(1)(2) + Aparent(1)(3)


MsgBox Aparent(1)(2)


End Sub
E đang thử sử dụng mảng trong mảng. Các Anh, Chị và các Thầy cho e hỏi là sau khi e cộng dồn các kết quả con vào Aparent(1) thì không còn truy xuất kết quả con được nữa !
E xin cám ơn !


Aparent(1) = Achild

Lần gán thứ nhất cho phần tử thứ nhất đã được gán là một mảng Achild (có 3 phần tử)

Aparent(1) = Aparent(1)(2) + Aparent(1)(3)

Lần gán thứ 2 cũng cho phần tử thứ 1 lại là một giá trị.

Như vậy thì làm sao mà bạn có thể bắt nó từ một giá trị trả về lại là một mảng được?

Để nó có thể thực hiện được thì bạn phải làm như sau:

Aparent(1)(2) = Aparent(1)(2) + Aparent(1)(3)

Tức lấy phần tử của mảng con cộng dồn cho chính nó thì mới thực hiện được.

Nhưng nếu là tôi, thì tôi sẽ tính toán cho mảng Achild(1 To 3) này trước, sau đó mới gán mảng đó lên mảng chính Aparent(1) = Achild

Có nghĩa là tôi sẽ làm như thế này:

Mã:
Sub quay()
    Dim i As Long
    Dim Aparent(1 To 5), Achild(1 To 3)
[COLOR=#0000ff]    ''Xu ly mang "con" Achild[/COLOR]
    For i = 2 To 3
        Achild(i) = i
    Next i
    Achild(1) = Achild(2) + Achild(3)
[COLOR=#0000ff]    ''Gan mang Achild vao mang "me" Aparent[/COLOR]
    Aparent(1) = Achild
[COLOR=#0000ff]    ''Kiem tra:[/COLOR]
    For i = 1 To 3
        MsgBox Aparent(1)(i)
    Next
End Sub
 
Upvote 0
E cám ơn A VetMini đã giải thích tường tận . Bây giờ thì e đã hiểu thêm chút ít về kiểu Variant này ( e toàn học lớm và chấp vá nên có nhiều cái chưa hiểu cặn kẽ ) . Mong a chỉ bảo thêm những bài sau ! :)

To a Hoàng Trọng Nghĩa : do tình huống e làm nó phát sinh thằng Aparent này trước, còn thằng A child này xuất hiện phụ thuộc vào Aparent. Nhưng e qua góp ý của a , e sẽ thay đổi và vận dụng . E cám ơn A !
 
Upvote 0
Cũng trên bài này, sau khi sửa lại (dùng biến tạm Tmp As String để thay cho phần tử mảng) và ra kết quả. Em có nhu cầu triển khai theo hướng khác, nhờ các Thầy cho giải thuật:
- Dữ liệu: Sheet2: Data bán hàng, Sheet3: SoHD khách hàng, Sheet4: SoHD Khách hàng đã thanh toán.
- Liệt kê ở Sheet1 MaKH và SoHD từ Sheet2, có trùng SoHD ở Sheet3, nhưng không trùng SoHD đã thanh toán ở Sheet4
- Ghi thêm MaKH và SoHD thanh toán (đợt này) ở Sheet4.
Xin chân thành cảm ơn!
Đọc giải thích sao khó hiểu quá, Leo xem file rồi nhập kết quả muốn có vào file xem sao.
Nhớ giải thích vì sao để có kết quả như vậy?
 

File đính kèm

Upvote 0
Đọc giải thích sao khó hiểu quá, Leo xem file rồi nhập kết quả muốn có vào file xem sao.
Nhớ giải thích vì sao để có kết quả như vậy?
Đúng rồi đó bác Ba Tê, Sheet4 sẽ trả về kết quả là thêm các giá trị bác đã tô màu vàng, vì những số đã có rồi thì không cần lặp lại ở sheet4. Sheet1 chỉ trả về kế quả tô vàng thôi, không cần lấy hết các giá trị khác.
 
Upvote 0
Đúng rồi đó bác Ba Tê, Sheet4 sẽ trả về kết quả là thêm các giá trị bác đã tô màu vàng, vì những số đã có rồi thì không cần lặp lại ở sheet4. Sheet1 chỉ trả về kế quả tô vàng thôi, không cần lấy hết các giá trị khác.
Vậy kiểm tra lại file này xem sao
 

File đính kèm

Upvote 0
CODE 1:
Mã:
Sub CT_Tach_cot()
    Dim i As Integer
    Dim[COLOR=#ff0000] [B]Tach_cot[/B][/COLOR]
    
    For i = 1 To 4
        Tach_cot = Split(Range("B8").Offset(i, 0), "-", 4)
        Range("B13").Offset(i, 0) = Tach_cot(0)
        Range("B13").Offset(i, 1) = Tach_cot(1)
        Range("B13").Offset(i, 2) = Tach_cot(2)
        Range("B13").Offset(i, 3) = Tach_cot(3)
    Next
End Sub

Anh chị cho em hỏi:
Thông thường,:
+ Khi khai báo biến, ta khai báo thế này:
Mã:
dim str as String
+ khi khai bao mảng, ta khai báo thế này:
Mã:
Dim str(5) as String             'mảng cố định
Dim str(1 to 20, 1 to 30)       'mảng từ....đến....
Dim str()                            ' mảng động

Vấn đề là: Trong CODE 1:
Khi dùng hàm split tách chuỗi thì nó sẽ trả về giá trị là một mảng.

Nhưng tại sao: tach_cot lại được khai báo như là kiểu một biến
dim tach_cot

chứ không phải kiểu một mảng?
dim tach_cot()

Em đã tìm hiểu nhiều nhưng vẫn chưa hiểu chỗ này, mong anh chỉ giải thích.


_______________________***______________________

CODE 2
Mã:
Sub test()
Dim [COLOR=#ff0000]arr[/COLOR]
arr = Array(1, 2, 3, 4, 5)
End Sub

CÂU HỎI 2:

TRONG CODE 2: Thông thường, khi khai báo mảng động, ta phải redim lại mảng động số phần tử trong mảng mới sử dụng được. Nhưng khi dùng hàm array nó sẽ tự nhận biết và gán luôn số phần tử cho mảng động ?Nó làm điều này như thế nào, mong anh chị giải thích cho em thông suốt ! Nếu có code diễn giải càng tốt.

Thanks anh chị !
 
Lần chỉnh sửa cuối:
Upvote 0
CODE 1:
Mã:
Sub CT_Tach_cot()
    Dim i As Integer
    Dim[COLOR=#ff0000] [B]Tach_cot[/B][/COLOR]
    
    For i = 1 To 4
        Tach_cot = Split(Range("B8").Offset(i, 0), "-", 4)
        Range("B13").Offset(i, 0) = Tach_cot(0)
        Range("B13").Offset(i, 1) = Tach_cot(1)
        Range("B13").Offset(i, 2) = Tach_cot(2)
        Range("B13").Offset(i, 3) = Tach_cot(3)
    Next
End Sub

Anh chị cho em hỏi:
Thông thường,:
+ Khi khai báo biến, ta khai báo thế này:
Mã:
dim str as String
+ khi khai bao mảng, ta khai báo thế này:
Mã:
Dim str(5) as String             'mảng cố định
Dim str(1 to 20, 1 to 30)       'mảng từ....đến....
Dim str()                            ' mảng động

Vấn đề là: Trong CODE 1:
Khi dùng hàm split tách chuỗi thì nó sẽ trả về giá trị là một mảng.

Nhưng tại sao: tach_cot lại được khai báo như là kiểu một biến
dim tach_cot

chứ không phải kiểu một mảng?
dim tach_cot()

Em đã tìm hiểu nhiều nhưng vẫn chưa hiểu chỗ này, mong anh chỉ giải thích.


_______________________***______________________

CODE 2
Mã:
Sub test()
Dim [COLOR=#ff0000]arr[/COLOR]
arr = Array(1, 2, 3, 4, 5)
End Sub

CÂU HỎI 2:

TRONG CODE 2: Thông thường, khi khai báo mảng động, ta phải redim lại mảng động số phần tử trong mảng mới sử dụng được. Nhưng khi dùng hàm array nó sẽ tự nhận biết và gán luôn số phần tử cho mảng động ?Nó làm điều này như thế nào, mong anh chị giải thích cho em thông suốt ! Nếu có code diễn giải càng tốt.

Thanks anh chị !
Theo tôi được biết nếu khai báo Dim Tach_cot (không có as ...) thì máy hiểu là Variant là nhận bất cứ kiểu gì.
- Câu 1: hàm split trả mảng 1 chiều, nếu bạn khai báo Dim Tach_cot as String (hay gì đó khác mảng) thì nó la làng ngay.
Khai báo Dim Tach_cot() là được
- Câu 2: cũng tương tự như câu 1 thôi.
Khai báo dim Arr() là được
 
Lần chỉnh sửa cuối:
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ị

For Each Cll In Rng
I = I + 1
ARR(I, 1) = Cll
Next



anh thử xem cái này xem sao
 
Upvote 0
Theo tôi được biết nếu khai báo Dim Tach_cot (không có as ...) thì máy hiểu là Variant là nhận bất cứ kiểu gì.
- Câu 1: hàm split trả mảng 1 chiều, nếu bạn khai báo Dim Tach_cot as String (hay gì đó khác mảng) thì nó la làng ngay.
Khai báo Dim Tach_cot() là được
- Câu 2: cũng tương tự như câu 1 thôi.
Khai báo dim Arr() là được
Nhân câu hỏi này cho em hỏi thêm về việc khai báo này một chút.
1/ Khi làm như anh Viehoai hướng dẫn nhưng máy em báo Error 13. Nhưng nếu khai báo

Mã:
Dim Tach_cot() As String
Thì được

2/ Tại sao các kiểu khai báo sau đều gây lỗi

Mã:
'Cach 1
Sub Test1()
    Dim arr() As String
    arr = Array(1, 2, 3, 4, 5)
End Sub


'Cach 2
Sub Test2()
    Dim arr() As Long
    arr = Array(1, 2, 3, 4, 5)
End Sub

'Cach 3
Sub Test3()
    Dim arr() As String
    arr = Array("1", "2", "3", "4", "5")
End Sub

mà chỉ có khai báo sau mới được

Mã:
Sub Test()
    Dim arr()
    arr = Array(1, 2, 3, 4, 5)
End Sub

3/ Khi gán giá trị 1 vùng trên sheet vào Array thì tại sao các code khai bảo mảng sau gây lỗi


Mã:
'Cach 1
Sub Test4()
    Dim arr() As String
    arr = Range("a1:a10")
End Sub

'Cach 2
Sub Test5()
    Dim arr() As Long
    arr = Range("a1:a10")
End Sub


'Cach 3
Sub Test6()
    Dim arr() As Long
    arr = Range("a1:a10").Value
End Sub


'Cach 4
Sub Test7()
    Dim arr() as String
    arr = Range("a1:a10").Text
End Sub


'Cach 5
Sub Test8()
    Dim arr()
    arr = Range("a1:a10").Text
End Sub

Trong khi khai báo sau lại được
Mã:
Sub Test9()
    Dim arr()
    arr = Range("a1:a10").Value
End Sub


Sub Test9()
    Dim arr()
    arr = Range("a1:a10").Value2
End Sub

Xin cảm ơn!
 
Upvote 0
Chào bạn dhn46,
Mình sẽ trả lời câu hỏi số 2 của bạn:
Mã:
'Cach 1
Sub Test1()
    Dim arr() As String
    arr = Array(1, 2, 3, 4, 5)
End Sub

'Cach 2
Sub Test2()
    Dim arr() As Long
    arr = Array(1, 2, 3, 4, 5)
End Sub

'Cach 3
Sub Test3()
    Dim arr() As String
    arr = Array("1", "2", "3", "4", "5")
End Sub

Khi bạn dùng arr =Array() thì giá trị mà hàm Array() trả về là một Variant (bắt buộc)
Nên nếu bạn có khai báo kiểu cho arr thì phải khai báo kiểu là: variant thì nó mới chịu.

Thân ái !


Quay lại câu hỏi của em
http://www.giaiphapexcel.com/forum/...về-mảng-trong-VBA-(Array)&p=573733#post573733

Khi ta khai báo:
dim tach_cot
nếu không khai báo luôn kiểu cho biến thì nó sẽ cho kiểu mặc định là variant
Cái này em biết rồi. Không bàn tán nữa !

Vấn đề em không hiểu là tại sau:

trong khai báo tach_cot không có dấu hiệu khai báo mảng, mà nó hiểu là mảng ?
Mong anh chị giải đáp cho em được hiểu !

tại không không phải là dim tach_cot()

mà chỉ là dim tach_cot ???

Mong anh chị giải đáp cho em rõ, em xin cảm ơn !
 
Lần chỉnh sửa cuối:
Upvote 0
Quay lại câu hỏi của em
http://www.giaiphapexcel.com/forum/...về-mảng-trong-VBA-(Array)&p=573733#post573733

Khi ta khai báo:
dim tach_cot
nếu không khai báo luôn kiểu cho biến thì nó sẽ cho kiểu mặc định là variant
Cái này em biết rồi. Không bàn tán nữa !

Vấn đề em không hiểu là tại sau:

trong khai báo tach_cot không có dấu hiệu khai báo mảng, mà nó hiểu là mảng ?
Mong anh chị giải đáp cho em được hiểu !

tại không không phải là dim tach_cot()

mà chỉ là dim tach_cot ???

Mong anh chị giải đáp cho em rõ, em xin cảm ơn !

Khi bạn khai báo
Mã:
Dim tach_cot

Thì biến tách cột là dạng Variant. Đã là Variant thì biến đó mang dữ liệu gì mà chả được dù là mảng, số, chuỗi ... Lỗi của mình tại câu 2 bài trên đó là quên mất Help, bạn đọc help về Variant sẽ hiểu.
 
Upvote 0
Mã:
[FONT=Verdana]For Each Ten In Range([c16], [c65536].End(3))           [/FONT] If Ten > 0 And Ten.Font.ColorIndex <> 3 Then  '
                Doc = .Documents.Open(ThisWorkbook.Path & "\" & [d1] & ".doc")
[FONT=Verdana]                .Selection.Find.Execute [c12], , , , , , , , , Ten, [/FONT][COLOR=#ff0000][FONT=Verdana]2[/FONT][/COLOR]
Dạ cho em hỏi số 2 chữ màu đỏ có ý nghĩa gì ạ
 
Upvote 0
Mã:
[FONT=Verdana]For Each Ten In Range([c16], [c65536].End(3))           [/FONT] If Ten > 0 And Ten.Font.ColorIndex <> 3 Then  '
                Doc = .Documents.Open(ThisWorkbook.Path & "\" & [d1] & ".doc")
[FONT=Verdana]                .Selection.Find.Execute [c12], , , , , , , , , Ten, [/FONT][COLOR=#ff0000][FONT=Verdana]2[/FONT][/COLOR]
Dạ cho em hỏi số 2 chữ màu đỏ có ý nghĩa gì ạ
Có 3 số: 0,1,2
0 là không thay gì cả
1 là thay chỉ 1 cụm khi tìm thấy
2 là thay tất cả
Cái này có thể đọc trong VBA Help thì sẽ thấy rõ hơn
 
Upvote 0
dạ cho em hỏi thêm một chút
Mã:
.Selection.Find.Execute [c13], , , , , , , , , Ten([COLOR=#ff0000]1, 3[/COLOR]), 2
Số 1 và 3 màu đỏ ý nghĩ gì vậy ? Em tìm câu trả lời của nó mà tìm mãi không có. Em xin cám ơn
 
Upvote 0
dạ cho em hỏi thêm một chút
Mã:
.Selection.Find.Execute [c13], , , , , , , , , Ten([COLOR=#ff0000]1, 3[/COLOR]), 2
Số 1 và 3 màu đỏ ý nghĩ gì vậy ? Em tìm câu trả lời của nó mà tìm mãi không có. Em xin cám ơn
Ten có thể là một Array 2 chiều, cũng có thể là một Range

Ten(1, 3) có thể hiểu là phần tử của Array hoặc một ô của một Range, nó ở vị trí hàng thứ 1 và cột thứ 3.

Một thí nghiệm về Range:

Mã:
Sub TestRange()
    Dim Ten As Range
    Set Ten = Range("A1:D5")
    Ten(1, 3).Select
    ''cell C3 se duoc chon
End Sub

Và một thí nghiệm cho Array:

Mã:
Sub TestArray()
    Dim Ten(1 To 5, 1 To 7)
    Dim c As Byte, r As Byte
    For r = 1 To 5
        For c = 1 To 7
            Ten(r, c) = r & "/" & c
        Next
    Next
    MsgBox Ten(1, 3)
End Sub
 
Upvote 0
dạ cho em hỏi thêm một chút
Mã:
.Selection.Find.Execute [c13], , , , , , , , , Ten([COLOR=#ff0000]1, 3[/COLOR]), 2
Số 1 và 3 màu đỏ ý nghĩ gì vậy ? Em tìm câu trả lời của nó mà tìm mãi không có. Em xin cám ơn
Với 1 Range thì nó có thể là như vầy:

Mã:
Sub TestRange2()
    Dim Ten As Range
    Set Ten = Range("A1")
    Ten(1, 3).Select
    ''cell C3 se duoc chon
End Sub

Mặc dù Range chỉ là 1 ô duy nhất, nhưng khi tham chiếu nó vẫn có thể "di chuyển" đúng hàng và cột bắt đầu từ điểm xuất phát là cell gốc (A1) đó.

Nhưng với Array thì không được như thế, sẽ báo lỗi tràn dòng nếu phần tử có số hàng hoặc số cột lớn hơn mảng gốc.

Tuy nhiên, căn cứ vào code của bạn thì nó chính là một RANGE chứ không phải là một Array:

Mã:
For Each [COLOR=#ff0000][B]Ten [/B][/COLOR][COLOR=#0000ff][B]In Range([c16], [c65536].End(3))[/B][/COLOR]        If Ten > 0 And Ten.Font.ColorIndex <> 3 Then  '
                Doc = .Documents.Open(ThisWorkbook.Path & "\" & [d1] & ".doc")
                .Selection.Find.Execute [c12], , , , , , , , , Ten, 2
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Sub Excel_Word()
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    On Error Resume Next
    With CreateObject("Word.Application")
        .Visible = True
        For Each Ten In Range([b8], [b65536].End)
            If Ten > 0 And Ten.Font.ColorIndex <> 3 Then  '
                Doc = .Documents.Open(ThisWorkbook.Path & "\BBNghienthu.doc")
                .Selection.Find.Execute [b6], , , , , , , , , Ten, 2
                .Selection.Find.Execute [b7], , , , , , , , , Ten(1, 3), 2
                For Each cls In [c3:c11]
                    If cls > 0 Then .Selection.Find.Execute cls, , , , , , , , , cls(1, 2), 2
                Next
                End If
        Next
        .Quit
    End With
End Sub
Anh cho em hỏi, đoạn câu này chỉ xuất ra 1 trang, với 1 dãy dữ liêu ở 1 hàng tương ứng. Nếu em muốn xuất tất cả các giá trị ở ô B8 trở về dưới và tất cả phải nằm trong 1 file word gồm nhiều trang với các giá trị của các ô từ ô B8 trở về dưới.
Em mới học vba để áp dụng cho công việc nên mong anh chị và các thầy cô giúp đỡ!
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
Sub Excel_Word()
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    On Error Resume Next
    With CreateObject("Word.Application")
        .Visible = True
        For Each Ten In [COLOR=#ff0000][B]Range([b8], [b65536].End)[/B][/COLOR]
            If Ten > 0 And Ten.Font.ColorIndex <> 3 Then  '
                Doc = .Documents.Open(ThisWorkbook.Path & "\BBNghienthu.doc")
                .Selection.Find.Execute [b6], , , , , , , , , Ten, 2
                .Selection.Find.Execute [b7], , , , , , , , , Ten(1, 3), 2
                For Each cls In [c3:c11]
                    If cls > 0 Then .Selection.Find.Execute cls, , , , , , , , , cls(1, 2), 2
                Next
                End If
        Next
        .Quit
    End With
End Sub
Anh cho em hỏi, đoạn câu này chỉ xuất ra 1 trang, với 1 dãy dữ liêu ở 1 hàng tương ứng. Nếu em muốn xuất tất cả các giá trị ở ô B8 trở về dưới và tất cả phải nằm trong 1 file word gồm nhiều trang với các giá trị của các ô từ ô B8 trở về dưới.
Em mới học vba để áp dụng cho công việc nên mong anh chị và các thầy cô giúp đỡ!


Bạn thử cái mà tôi tô đỏ thành cái dưới đây xem sao:

Range([b8], [b65536].End(xlUp))
 
Upvote 0
Thay đổi cách xác định mảng

- Em có code sử dụng mảng đang chạy rất ngon lành như sau:
PHP:
Public Sub Cach1()
Dim sArr(), Arr1(), Arr2(), I As Long, J As Long, Num As Long
sArr = Range("D11:AL501").Value
ReDim Arr1(1 To UBound(sArr, 1), 1 To 1)
ReDim Arr2(1 To UBound(sArr, 1), 1 To 1)
For I = 1 To UBound(sArr, 1)
    Num = 0
    For J = 8 To UBound(sArr, 2)
        If sArr(I, J) > 0 Then
            Num = Num + sArr(I, J)
   Next J
    If Num > 0 Then       Arr2(I, 1) = sArr(I, 1) - (sArr(I, 35) + Num)
   If sArr(I, 2) <> "" Or sArr(I, 1) - Num = 0 Then     Arr1(I, 1) = "x"
Next I
[AM11:AM501].Value = Arr2
[E11:E501].Value = Arr1
End Sub
- Nay em vọc code về mảng muốn thay thế bằng một cách viết khác khi sử dụng mảng. Em có sửa lại code trên thành:
PHP:
Public Sub Cach2()
Dim sArr(), Arr1(), Arr2(), I As Long, J As Long, Num As Long, K As Long
    sArr = .Range(.[D11], .[D65000].End(xlUp)).Value
    K = UBound(sArr, 1)
    'sArr = Range("D11:AL501").Value'
ReDim Arr1(1 To K, 1 To 1)
ReDim Arr2(1 To K, 1 To 1)
For I = 1 To UBound(sArr, 1)
    Num = 0    
   For J = 8 To UBound(sArr, 2)
        If sArr(I, J) > 0 Then Num = Num + sArr(I, J)
    Next J
    If Num > 0 Then Arr2(I, 1) = sArr(I, 1) - Num
    If sArr(I, 2) <> "" Or sArr(I, 1) - Num = 0 Then Arr1(I, 1) = "x"
Next I
.[AM11].Resize(K, 1).Value = Arr2
.[E11].Resize(K, 1).Value = Arr1
End Sub
Thì code này báo lỗi như hình:
Loi.jpg
- Như vậy em chỉ biết là mình viết chưa đúng. Các Bác giúp em sửa lại với. Em xin cảm ơn!.
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Bạn Copy Code lên diễn đàn bị lỗi nên rất khó nhìn. Tôi đoán lỗi của bạn như sau
Code của bạn có đoạn lỗi

Mã:
sArr = .Range(.[D11], .[D65000].End(xlUp)).Value
Bạn để ý cái dấu chấm, dấu chấm đó có có nghĩa là chỉ ra cells sau dấu chấm sẽ thuộc đối tượng lớp cao hơn, ở đấy là worksheet. Do đó bạn xem sheet cần tham chiếu là gì để sửa. Bạn sửa theo dạng như sau

Mã:
With sheet1
sArr = .Range(.[D11], .[D65000].End(xlUp)).Value  
End with
 
Upvote 0
Bạn Copy Code lên diễn đàn bị lỗi nên rất khó nhìn. Tôi đoán lỗi của bạn như sau
Code của bạn có đoạn lỗi

Mã:
sArr = .Range(.[D11], .[D65000].End(xlUp)).Value
Bạn để ý cái dấu chấm, dấu chấm đó có có nghĩa là chỉ ra cells sau dấu chấm sẽ thuộc đối tượng lớp cao hơn, ở đấy là worksheet. Do đó bạn xem sheet cần tham chiếu là gì để sửa. Bạn sửa theo dạng như sau

Mã:
With sheet1
sArr = .Range(.[D11], .[D65000].End(xlUp)).Value  
End with
- Cảm ơn bạn nhé!. Mọi người post code lên coi rất đẹp mà sao mình post để có màu mè như trên thì khung nó lại nhỏ xíu!.
- Theo gơi ý của bạn mình đã sửa lại như sau:
PHP:
Public Sub Cach2()
Dim sArr(), Arr1(), Arr2(), I As Long, J As Long, Num As Long, K As Long
With Sheets("Sheet1")
    sArr = .Range(.[D11], .[D65000].End(xlUp)).Value
    K = UBound(sArr, 1)
End With
'sArr = Range("D11:AL501").Value
ReDim Arr1(1 To K, 1 To 1)
ReDim Arr2(1 To K, 1 To 1)
For I = 1 To UBound(sArr, 1)
    Num = 0
    For J = 8 To UBound(sArr, 2)
        If sArr(I, J) > 0 Then Num = Num + sArr(I, J)
    Next J
    If Num > 0 Then Arr2(I, 1) = sArr(I, 1) - Num
    If sArr(I, 2) <> "" Or sArr(I, 1) - Num = 0 Then Arr1(I, 1) = "x"
Next I
With Sheets("Sheet1")
.[AM11].Resize(K, 1).Value = Arr2
.[E11].Resize(K, 1).Value = Arr1
End With
End Sub
- Bị lỗi dòng này:
If sArr(I, 2) <> "" Or sArr(I, 1) - Num = 0 Then Arr1(I, 1) = "x"
. Các bạn xem giúp mình với!.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
- Cảm ơn bạn nhé!. Mọi người post code lên coi rất đẹp mà sao mình post để có màu mè như trên thì khung nó lại nhỏ xíu!.
- Theo gơi ý của bạn mình đã sửa lại như sau:
PHP:
Public Sub Cach2()
Dim sArr(), Arr1(), Arr2(), I As Long, J As Long, Num As Long, K As Long
With Sheets("Sheet1")
    sArr = .Range(.[D11], .[D65000].End(xlUp)).Value
    K = UBound(sArr, 1)
End With
'sArr = Range("D11:AL501").Value
ReDim Arr1(1 To K, 1 To 1)
ReDim Arr2(1 To K, 1 To 1)
For I = 1 To UBound(sArr, 1)
    Num = 0
    For J = 8 To UBound(sArr, 2)
        If sArr(I, J) > 0 Then Num = Num + sArr(I, J)
    Next J
    If Num > 0 Then Arr2(I, 1) = sArr(I, 1) - Num
    If sArr(I, 2) <> "" Or sArr(I, 1) - Num = 0 Then Arr1(I, 1) = "x"
Next I
With Sheets("Sheet1")
.[AM11].Resize(K, 1).Value = Arr2
.[E11].Resize(K, 1).Value = Arr1
End With
End Sub
- Bị lỗi dòng này: . Các bạn xem giúp mình với!.

Sai đoạn này bạn ơi,

Mã:
sArr = .Range(.[D11], .[D65000].End(xlUp)).Value

thay bằng:

Mã:
sArr = .Range(.[D11], .[D65000].End(xlUp))[COLOR=#ff0000].Resize(, 35)[/COLOR].Value
 
Upvote 0
- Cảm ơn bạn nhé!. Mọi người post code lên coi rất đẹp mà sao mình post để có màu mè như trên thì khung nó lại nhỏ xíu!.
- Theo gơi ý của bạn mình đã sửa lại như sau:
PHP:
Public Sub Cach2()
Dim sArr(), Arr1(), Arr2(), I As Long, J As Long, Num As Long, K As Long
With Sheets("Sheet1")
    sArr = .Range(.[D11], .[D65000].End(xlUp)).Value
    K = UBound(sArr, 1)
End With
'sArr = Range("D11:AL501").Value
ReDim Arr1(1 To K, 1 To 1)
ReDim Arr2(1 To K, 1 To 1)
For I = 1 To UBound(sArr, 1)
    Num = 0
    For J = 8 To UBound(sArr, 2)
        If sArr(I, J) > 0 Then Num = Num + sArr(I, J)
    Next J
    If Num > 0 Then Arr2(I, 1) = sArr(I, 1) - Num
    If sArr(I, 2) <> "" Or sArr(I, 1) - Num = 0 Then Arr1(I, 1) = "x"
Next I
With Sheets("Sheet1")
.[AM11].Resize(K, 1).Value = Arr2
.[E11].Resize(K, 1).Value = Arr1
End With
End Sub
- Bị lỗi dòng này: . Các bạn xem giúp mình với!.
Mảng có 1 cột D thì lấy đâu ra số 2 chứ
If sArr(I, 1) <> "" Or sArr(I, 1) - Num = 0 Then Arr1(I, 1) = "x"
 
Upvote 0
tôi đang có 1 thắc mắc cũng không có khó lắm nhưng không biết cấu trúc như thế nào mong được học hỏi thêm
ví dụ nếu là mảng một chiều thì tôi nhập giá trị trực tiếp như sau
Dim Arr()
Arr = Array(1, 2, 3, 4, 4, 5, 6)

còn mảng 2 chiều thì nhập như thế nào? xin cảm ơn
 
Upvote 0
tôi đang có 1 thắc mắc cũng không có khó lắm nhưng không biết cấu trúc như thế nào mong được học hỏi thêm
ví dụ nếu là mảng một chiều thì tôi nhập giá trị trực tiếp như sau
Dim Arr()
Arr = Array(1, 2, 3, 4, 4, 5, 6)

còn mảng 2 chiều thì nhập như thế nào? xin cảm ơn

Trùi ui, phải vậy không đó?

Dim Arr2D(1 to 2, 1 to 2)

Arr2D(1, 1) = "Hoàng"
Arr2D(1, 2) = "Trọng"
Arr2D(2, 1) = "Nghĩa"
Arr2D(2, 2) = "Đẹp trai"
 
Upvote 0
Trùi ui, phải vậy không đó?

Dim Arr2D(1 to 2, 1 to 2)

Arr2D(1, 1) = "Hoàng"
Arr2D(1, 2) = "Trọng"
Arr2D(2, 1) = "Nghĩa"
Arr2D(2, 2) = "Đẹp trai"
ý em muốn sử dụng cái này nè
Array(1, 2, 3, 4, 4, 5, 6)
vì em thấy mảng một chiều nhập trực tiếp như vậy, mà mảng 2 hay nhiều chiều có như vậy được không?


 
Upvote 0
ý em muốn sử dụng cái này nè
Array(1, 2, 3, 4, 4, 5, 6)
vì em thấy mảng một chiều nhập trực tiếp như vậy, mà mảng 2 hay nhiều chiều có như vậy được không?



Hiện tại thì chưa thấy có thể gán mảng 2 chiều trở lên bằng hàm Array!
 
Upvote 0
tôi đang có 1 thắc mắc cũng không có khó lắm nhưng không biết cấu trúc như thế nào mong được học hỏi thêm
ví dụ nếu là mảng một chiều thì tôi nhập giá trị trực tiếp như sau
Dim Arr()
Arr = Array(1, 2, 3, 4, 4, 5, 6)

còn mảng 2 chiều thì nhập như thế nào? xin cảm ơn

Cách chính thống là người ta nạp từng phần tử vào mảng 2 chiều (dùng vòng lập)
Cách khác nạp 1 lần luôn không cần vòng lập cũng có, chẳng hạn:
Mã:
Sub Test()
  Dim arr
  arr = [{1,2,3;4,5,6}]
  MsgBox arr(1, 1)
  MsgBox arr(1, 2)
  MsgBox arr(1, 3)
  MsgBox arr(2, 1)
  MsgBox arr(2, 2)
  MsgBox arr(2, 3)
End Sub
arr là mảng 2 chiều
 
Lần chỉnh sửa cuối:
Upvote 0
Cách chính thống là người ta nạp từng phần tử vào mảng 2 chiều (dùng vòng lập)
Cách khác nạp 1 lần luôn không cần vòng lập cũng có, chẳng hạn:
Mã:
Sub Test()
  Dim arr
  arr = [{1,2,3;4,5,6}]
  MsgBox arr(1, 1)
  MsgBox arr(1, 2)
  MsgBox arr(1, 3)
  MsgBox arr(2, 1)
  MsgBox arr(2, 2)
  MsgBox arr(2, 3)
End Sub
arr là mảng 2 chiều

Hay quá Thầy ơi, giờ mới biết cách này:

arr = [{1,2,3;4,5,6}]
 
Upvote 0
Hay quá Thầy ơi, giờ mới biết cách này:

arr = [{1,2,3;4,5,6}]
Thật ra là mình không cần biết cũng được anh nghĩa vì có nhiều cách gán mà, nhưng mà mình đi dạy nên phải phòng các trường hợp người ta có thể hỏi mình bất cứ thứ gì, nên phải phòng trước tới đâu hay tối đó hi hi
còn 3 chiều mình phải thêm dấu gì nữa thầy ndu
 
Lần chỉnh sửa cuối:
Upvote 0
Thật ra là mình không cần biết cũng được anh nghĩa vì có nhiều cách gán mà, nhưng mà mình đi dạy nên phải phòng các trường hợp người ta có thể hỏi mình bất cứ thứ gì, nên phải phòng trước tới đâu hay tối đó hi hi
còn 3 chiều mình phải thêm dấu gì nữa thầy ndu

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

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

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

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

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

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

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

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

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

trích trong bài

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Của bạn hơi rườm rà quá.

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

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

Back
Top Bottom