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

Liên hệ QC

viehoai

Thành viên gắn bó
Tham gia
22/5/09
Bài viết
2,599
Được thích
2,906
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ảm ơn mọi người đã hỗ trợ. Em kết hợp cả 2 cách của anh hpkhuong với anh dhn46 lại thì ra được kết quả rồi

Cảm ơn thầy BaTe đã khuyến mãi thêm 1 cách làm nữa.
 
Upvote 0
Gởi các bạn bài tập sử dụng mảng để tính subtotal cho các đối tượng, bài này tôi chỉ đưa ra ý tưởng là chèn thêm dòng total dưới các vị trí trùng nhau, các bạn có thể phát triển nó để có thể tính tổng con, đếm, hay tính trung bình của những nhóm, cái này tôi sử dụng mảng để chèn, và có sử dụng kỹ thuật chương trình con để làm
(code của tôi không có bẫy bất cứ lỗi gì? đây chỉ là ý tưởng nếu ai quan tâm thì có thể phát triển nhiều hướng cho mình, vì sử dụng chèn dòng trong excel với số lượng nhiều thì rất chậm)
Mã:
' Sub chen tung dong
Sub CHENDONG(VT_Chen As Long, Arr_D(), Sodong As Long)
Dim I As Long
   For I = Sodong To VT_Chen Step -1
     Arr_D(I, 1) = Arr_D(I - 1, 1)
   Next
   Arr_D(VT_Chen, 1) = "Total"
End Sub

Mã:
Sub Main()
Dim Arr_D(1 To 10000, 1 To 2)
Dim Arr_N()
Dim I As Long
Dim dongcuoi As Long
Dim VT_Chen As Long
Dim Sodong As Long


dongcuoi = Sheet1.Range("A10000").End(xlUp).Row
Arr_N = Sheet1.Range("A1:A" & dongcuoi + 1)
Sodong = UBound(Arr_N, 1)
'duyet tu dau den cuoi mang nguon gan vao mang dich
For I = 1 To UBound(Arr_N, 1)
  Arr_D(I, 1) = Arr_N(I, 1)
Next


' Kiem tra dieu kien tung phan tu neu Dung dieu kien thi goi sub chen dong
For I = UBound(Arr_N, 1) To 2 Step -1
  If (Arr_N(I, 1) <> Arr_N(I - 1, 1)) Then
     VT_Chen = I
     Sodong = Sodong + 1
     Call CHENDONG(VT_Chen, Arr_D, Sodong)
  End If
 Next


Sheet1.Range("B1:B10000").Clear
Sheet1.Range("B1").Resize(Sodong, 1) = Arr_D
End Sub
 

File đính kèm

  • subtotal.xlsb
    17 KB · Đọc: 34
Upvote 0
Gởi các bạn bài tập sử dụng mảng để tính subtotal cho các đối tượng, bài này tôi chỉ đưa ra ý tưởng là chèn thêm dòng total dưới các vị trí trùng nhau, các bạn có thể phát triển nó để có thể tính tổng con, đếm, hay tính trung bình của những nhóm, cái này tôi sử dụng mảng để chèn, và có sử dụng kỹ thuật chương trình con để làm
(code của tôi không có bẫy bất cứ lỗi gì? đây chỉ là ý tưởng nếu ai quan tâm thì có thể phát triển nhiều hướng cho mình, vì sử dụng chèn dòng trong excel với số lượng nhiều thì rất chậm)
Mã:
' Sub chen tung dong
Sub CHENDONG(VT_Chen As Long, Arr_D(), Sodong As Long)
Dim I As Long
   For I = Sodong To VT_Chen Step -1
     Arr_D(I, 1) = Arr_D(I - 1, 1)
   Next
   Arr_D(VT_Chen, 1) = "Total"
End Sub

Mã:
Sub Main()
Dim Arr_D(1 To 10000, 1 To 2)
Dim Arr_N()
Dim I As Long
Dim dongcuoi As Long
Dim VT_Chen As Long
Dim Sodong As Long


dongcuoi = Sheet1.Range("A10000").End(xlUp).Row
Arr_N = Sheet1.Range("A1:A" & dongcuoi + 1)
Sodong = UBound(Arr_N, 1)
'duyet tu dau den cuoi mang nguon gan vao mang dich
For I = 1 To UBound(Arr_N, 1)
  Arr_D(I, 1) = Arr_N(I, 1)
Next


' Kiem tra dieu kien tung phan tu neu Dung dieu kien thi goi sub chen dong
For I = UBound(Arr_N, 1) To 2 Step -1
  If (Arr_N(I, 1) <> Arr_N(I - 1, 1)) Then
     VT_Chen = I
     Sodong = Sodong + 1
     Call CHENDONG(VT_Chen, Arr_D, Sodong)
  End If
 Next


Sheet1.Range("B1:B10000").Clear
Sheet1.Range("B1").Resize(Sodong, 1) = Arr_D
End Sub

người viết ở trên quan tâm tới trường hợp số lượng lớn dòng dữ liệu trong excel , nhưng lại chọn cách viết code rất "hao xăng" để giải bài toán này ?
Tôi sẽ đi phân tích ý nghĩa đoạn ở trên . Giải thuật
Cứ gặp hiện tượng giá trị mảng của dòng hiện tại khác với dòng ngay trước nó
Mã:
If (Arr_N(I, 1) <> Arr_N(I - 1, 1)) Then
thì số dòng tổng cộng trong mảng kết quả phải điều chỉnh tăng 1 ( vì chèn thêm dòng "total")
và tiến hành duyệt mảng kết quả , sửa lại ghi đè tất cả các giá trị đã gán trước đó .
Vậy với mỗi lần xảy ra
Mã:
If (Arr_N(I, 1) <> Arr_N(I - 1, 1)) Then
lại tiến hành ghi đè tất cả các giá trị đã gán trước đó ?

Mã:
For I = Sodong To VT_Chen Step -1
     Arr_D(I, 1) = Arr_D(I - 1, 1)
   Next
như thế càng tiến gần về đích 2
Mã:
For I = UBound(Arr_N, 1) To 2 Step -1

thì số giá trị phải ghi đè càng lớn , điều này là đáng kể đối với excel dữ liệu lớn .
Nhưng tùy mỗi người nhận thức , có người cho rằng với bài này phải dùng kỹ thuật chia sub con mới là đỉnh cao của lập trình thì cũng được , tự do mà .
Với tôi thì theo đúng đề bài này tôi chỉ sử dụng 1 sub theo tinh thần duyệt mảng

Mã:
Public Sub hello()
Dim arr, dArr(1 To 100000, 1 To 1), r As Long, k As Long, ub As Long
arr = Sheet1.Range("A1:A" & Sheet1.[A10000].End(xlUp).Row).Value
ub = UBound(arr)
For r = 1 To ub Step 1
    k = k + 1
    dArr(k, 1) = arr(r, 1)
    If arr(r, 1) <> arr(WorksheetFunction.Min(r + 1, ub), 1) Or r = ub Then
        k = k + 1
        dArr(k, 1) = "total"
    End If
Next
Sheet1.Range("B1:B10000").Clear
Sheet1.Range("B1").Resize(k, 1) = dArr
End Sub
 
Upvote 0
người viết ở trên quan tâm tới trường hợp số lượng lớn dòng dữ liệu trong excel , nhưng lại chọn cách viết code rất "hao xăng" để giải bài toán này ?
Tôi sẽ đi phân tích ý nghĩa đoạn ở trên . Giải thuật
Cứ gặp hiện tượng giá trị mảng của dòng hiện tại khác với dòng ngay trước nó
Mã:
If (Arr_N(I, 1) <> Arr_N(I - 1, 1)) Then
thì số dòng tổng cộng trong mảng kết quả phải điều chỉnh tăng 1 ( vì chèn thêm dòng "total")
và tiến hành duyệt mảng kết quả , sửa lại ghi đè tất cả các giá trị đã gán trước đó .
Vậy với mỗi lần xảy ra
Mã:
If (Arr_N(I, 1) <> Arr_N(I - 1, 1)) Then
lại tiến hành ghi đè tất cả các giá trị đã gán trước đó ?

Mã:
For I = Sodong To VT_Chen Step -1
     Arr_D(I, 1) = Arr_D(I - 1, 1)
   Next
như thế càng tiến gần về đích 2
Mã:
For I = UBound(Arr_N, 1) To 2 Step -1

thì số giá trị phải ghi đè càng lớn , điều này là đáng kể đối với excel dữ liệu lớn .
Nhưng tùy mỗi người nhận thức , có người cho rằng với bài này phải dùng kỹ thuật chia sub con mới là đỉnh cao của lập trình thì cũng được , tự do mà .
Với tôi thì theo đúng đề bài này tôi chỉ sử dụng 1 sub theo tinh thần duyệt mảng

Mã:
Public Sub hello()
Dim arr, dArr(1 To 100000, 1 To 1), r As Long, k As Long, ub As Long
arr = Sheet1.Range("A1:A" & Sheet1.[A10000].End(xlUp).Row).Value
ub = UBound(arr)
For r = 1 To ub Step 1
    k = k + 1
    dArr(k, 1) = arr(r, 1)
    If arr(r, 1) <> arr(WorksheetFunction.Min(r + 1, ub), 1) Or r = ub Then
        k = k + 1
        dArr(k, 1) = "total"
    End If
Next
Sheet1.Range("B1:B10000").Clear
Sheet1.Range("B1").Resize(k, 1) = dArr
End Sub
nếu không lại tiến hành ghi đè tất cả các giá trị đã gán trước đó ? Thì bạn cứ cho 1 giải thuật chèn dòng đi, theo sách vở thì tôi chỉ biết chèn dòng thì như vậy thôi, chả biết hơn nữa đâu(trong code của bạn thì bạn có lợi dụng hàm MIN trong excel, mà cái hàm đó suy cho cùng thì cũng dùng vòng lặp duyệt từ bên trong mà thôi). Ý thức tôi kém nên tôi mới biết tới là chia nhỏ chương trình con là đỉnh cao trong lặp trình thôi, còn những ý thức cao siêu thì tôi không biết
tôi chỉ biết là chương trình chính chỉ nên gọi các thủ tục và hàm, để người ta dễ hình dung chương trình làm gì và dễ kiểm soát lỗi thôi bạn
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chào đại gia đình GPE, trước tiên cho em cảm ơn đến tất cả các thành viên về các bài viết của anh chị đã giúp ích được rất nhiều người kể cả em.
em có 1 vấn đề này thắc mắc mà không biết giải quyết như thế nào? em có đọc bài anh lê văn duyệt về mảng nhưng chưa thực hành được
vấn đề 1:
em có đoạn code
Mã:
Dim Arr()
Arr = Array(Array(1, 2, 3))
dĩ nhiên Arr là mảng một chiều

nhưng lời của anh Lê văn duyệt
[FONT=&amp]Nếu dùng từ khóa Array, chỉ trả về mảng chỉ có một chiều nếu muốn trả về một mảng hai chiều chúng ta phải dùng [/FONT]Array(Array(…))

em muốn gán mảng 2 chiều theo yêu cầu này mà không được?
Mã:
Dim Arr()
Dim AB As Long
Arr = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))
MsgBox Arr(1)(1)

em chỉ làm được như vậy thôi, mà như vậy thì nó là mảng một chiều trong mảng một chiều?
có cách nào gán mảng 2 chiều trực tiếp bằng array?
cũng là vấn đề này em muốn khai báo mảng tường minh được không
ví dụ
Arr(1 to 10) đây là mảng một chiều
còn mảng 1 chiều trong mảng 1 chiều khai báo sao?

Vấn đề 2:
khai báo mảng trong mảng, thao tác mảng trong mảng...
xin chân thành cảm ơn

 
Upvote 0
Xin chào đại gia đình GPE, trước tiên cho em cảm ơn đến tất cả các thành viên về các bài viết của anh chị đã giúp ích được rất nhiều người kể cả em.
em có 1 vấn đề này thắc mắc mà không biết giải quyết như thế nào? em có đọc bài anh lê văn duyệt về mảng nhưng chưa thực hành được
vấn đề 1:
em có đoạn code
Mã:
Dim Arr()
Arr = Array(Array(1, 2, 3))
dĩ nhiên Arr là mảng một chiều

nhưng lời của anh Lê văn duyệt
[FONT=&amp]Nếu dùng từ khóa Array, chỉ trả về mảng chỉ có một chiều nếu muốn trả về một mảng hai chiều chúng ta phải dùng [/FONT]Array(Array(…))

em muốn gán mảng 2 chiều theo yêu cầu này mà không được?
Mã:
Dim Arr()
Dim AB As Long
Arr = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))
MsgBox Arr(1)(1)

em chỉ làm được như vậy thôi, mà như vậy thì nó là mảng một chiều trong mảng một chiều?
có cách nào gán mảng 2 chiều trực tiếp bằng array?
cũng là vấn đề này em muốn khai báo mảng tường minh được không
ví dụ
Arr(1 to 10) đây là mảng một chiều
còn mảng 1 chiều trong mảng 1 chiều khai báo sao?

Vấn đề 2:
khai báo mảng trong mảng, thao tác mảng trong mảng...
xin chân thành cảm ơn

Vấn đề 1:

Đầu tiên, ta phải hiểu rằng Array là một hàm mảng một chiều.

Array Function

Returns a Variant containing an array.

Thứ 2, với kiểu triển khai như thế này:

Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))

được gọi là "mảng trong mảng", với mảng một chiều "mẹ" chứa các phần tử là các mảng một chiều "con" (có thể chứa thêm cháu chắt gì nữa cũng được).

Thứ 3, đã là hàm mảng 1 chiều thì không thể chuyển hàm Array thành mảng 2 chiều được. Vậy nên muốn có mảng 2 chiều, hoặc nhiều hơn thì ta phải khai báo.

Ví dụ:

Mã:
Dim Arr2D(1 To 5, 1 To 2)

Ta thấy rằng chiều "hàng" nó có 5 hàng, và chiều "cột" nó có 2 cột. Với mỗi hàng nó sẽ chứa 2 phần tử của cột, từ đó bạn sẽ hiểu tính chất của nó mà làm việc với mảng 2 chiều.

Khai báo mảng trong mảng 1 chiều ta chỉ khai báo 2 mảng, một mảng "mẹ" và một mảng "con" (nếu mảng con có số phần tử là bằng nhau).

Mã:
Dim Arr1D_Mother(1 To 10)
Dim Arr1D_Daugter(1 To 5)

Khi triển khai bạn cứ tạo mảng con trước sau đó "gán" nó thành một phần tử của mảng "mẹ" và cứ thế cho đến hết 10 phần tử.

Vấn đề 2:

Như đã nói ở phần màu xanh, dưới đây là code để chứng minh điều đó:

Mã:
Sub Test()
    Dim Arr1D_Mother(1 To 10)
    Dim Arr1D_Daugter(1 To 5)
    Dim c As Long, r As Long
    For r = 1 To 10
        For c = 1 To 5
            Arr1D_Daugter(c) = r & c
        Next
        Arr1D_Mother(r) = Arr1D_Daugter
    Next
    MsgBox Arr1D_Mother(3)(4)
End Sub

Như vậy, MsgBox sẽ cho ra kết quả là 34 (3 và 4) vì đó là số ghép giữa phần tử thứ 3 của mảng mẹ với phần tử thứ 4 của mảng con.

Với những gì tôi nêu trên, hy vọng bạn hiểu thêm về chúng.
 
Upvote 0
Cảm ơn anh nghĩa nhiều, vấn đề này em đã tham khảo trong topic này trang 17 rồi. Em cũng hiểu và vận dụng được

Sub Test()
Dim Arr1D_Mother(1 To 10)
Dim Arr1D_Daugter(1 To 5)
Dim c As Long, r As Long
For r = 1 To 10
For c = 1 To 5
Arr1D_Daugter(c) = r & c
Next
Arr1D_Mother(r) = Arr1D_Daugter
Next
MsgBox Arr1D_Mother(3)(4)
End Sub
ý em muốn biết là mình có khai báo tường minh mảng con trong mảng mẹ hay không thôi? và cách truy xuất và gán giá trị ?
và vấn đề thứ nhất của em Array đúng là mảng một chiều, nhưng em có đọc bài anh Lê Văn Duyệt có nói là làm được nên em muốn tò mò xem sao thôi.
Nguyên văn bài của anh Duyệt
Nếu dùng từ khóa Array, chỉ trả về mảng chỉ có một chiều nếu muốn trả về một mảng hai chiều chúng ta phải dùng
Array(Array(…))

cảm ơn anh Nghĩa đẹp trai đã giúp đỡ nhiệt tình
 
Lần chỉnh sửa cuối:
Upvote 0
em muốn gán mảng 2 chiều theo yêu cầu này mà không được?
Mã:
Dim Arr()
Dim AB As Long
Arr = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))
MsgBox Arr(1)(1)

em chỉ làm được như vậy thôi, mà như vậy thì nó là mảng một chiều trong mảng một chiều?
có cách nào gán mảng 2 chiều trực tiếp bằng array?

Tôi thường làm thế này:
Mã:
Sub Test2()
  Dim arr
  arr = [{1,2,3;4,5,6;7,8,9;10,11,12}]
  Range("A1:C4").Value = arr
End Sub
Thử xem.. hên thì được còn xui thì.. thôi vậy!
 
Upvote 0
Tôi thường làm thế này:
Mã:
Sub Test2()
  Dim arr
  arr = [{1,2,3;4,5,6;7,8,9;10,11,12}]
  Range("A1:C4").Value = arr
End Sub
Thử xem.. hên thì được còn xui thì.. thôi vậy!
cảm ơn anh ndu, xem như đã giải quyết được 1 yêu cầu rồi, cảm ơn anh ndu nhiều, tuy rằng những cái vấn đề này nó không quan trọng lắm nhưng mà em muốn biết tường tận để thỏa lòng thỏa dạ
 
Lần chỉnh sửa cuối:
Upvote 0
ý em muốn biết là mình có khai báo tường minh mảng con trong mảng mẹ hay không thôi? và cách truy xuất và gán giá trị ?
và vấn đề thứ nhất của em Array đúng là mảng một chiều, nhưng em có đọc bài anh Lê Văn Duyệt có nói là làm được nên em muốn tò mò xem sao thôi.
Nguyên văn bài của anh Duyệt
Nếu dùng từ khóa Array, chỉ trả về mảng chỉ có một chiều nếu muốn trả về một mảng hai chiều chúng ta phải dùng
Array(Array(…))
cảm ơn anh Nghĩa đẹp trai đã giúp đỡ nhiệt tình

Tôi không nghĩ với cách màu đỏ lại trở thành mảng 2 chiều được!
 
Upvote 0
Dạ cái đó là hên suôi, em cũng thử chưa ra, nhưng đọc bài của anh Duyệt thấy như vậy nên tò mò thôi anh, tò mò hoài không ra nên hỏi xem có đáp án nào không.
Vậy bạn đọc nó ở đâu? Bạn cho cái link đến đó để tôi nghiên cứu xem sao!
 
Upvote 0
Theo nghĩa rộng thì mảng của mảng có thể coi là mảng 2 chiều.
Theo nghĩa chính thức của lập trình thì mảng 2 chiều phải hội đủ 2 điều kiện sau:
1. các phần tử phải cùng một kiểu (type)
2. các phân tử phải liên tục nhau.

cái mảng này:
Arr = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9), Array(10, 11, 12))

Khong BẢO ĐẢM 2 điều kiên trên. Vì vậy, theo định nghĩa của lập trình, nó khong phải là mảng 2 chiều.
Một số ngôn ngữ gọi nó là mảng răng cưa (jagged array).
 
Upvote 0
Các Bạn cho mình hỏi có cách nào khác duyệt File như code sau ngắn gọn hơn Mà không sử dụng Array

mà vẫn duyệt được không ... xin cảm ơn

Mã:
[/B]Sub CheckFile()
    Dim MyFile(), i As Long
    MyFile = [COLOR=#ff0000][B]Array[/B][/COLOR]("x1.xls", "x2.xlsb", "x3.xlsx")
    For i = 0 To UBound(MyFile)
        MsgBox MyFile(i)
    Next
End Sub
[B]
 
Upvote 0
Các Bạn cho mình hỏi có cách nào khác duyệt File như code sau ngắn gọn hơn Mà không sử dụng Array

mà vẫn duyệt được không ... xin cảm ơn

Mã:
Mã:
Sub CheckFile()
    Dim MyFile(), i As Long
    MyFile = [COLOR=#ff0000][B]Array[/B][/COLOR]("x1.xls", "x2.xlsb", "x3.xlsx")
    For i = 0 To UBound(MyFile)
        MsgBox MyFile(i)
    Next
End Sub

Khong dùng Array? bạn muốn nói hàm Array?

for each f in split("x,y,z", ",")
 
Upvote 0
Khong dùng Array? bạn muốn nói hàm Array?

for each f in split("x,y,z", ",")
Chi tiết là vầy ...Nếu ta có 100 File ở nhiều Folder khác nhau thì Cái Array thấy dài quá ...

Vậy mình đang nghĩ có cách nào viết khác mà không phải xài Array cho nó gọn lại đó mà ...mà mục đích cũng vậy

Và cách khai báo này thấy hoài nên cũng đang nghĩ xem khai phá cách viết mới xúc tích ngắn gọn và dễ xài hơn không

Mã:
Private Sub CheckFile1()
    Dim MyFile(), i As Long
    Dim File1 As String, File2 As String, File3 As String
    File1 = "D:\Manh\x1.xls"
    File2 = "E:\Anh\x2.xlsb"
    File3 = "C:\XX\x3.xlsx"
    MyFile = [COLOR=#ff0000][B]Array[/B][/COLOR](File1, File2, File3)
    For i = 0 To UBound(MyFile)
        MsgBox MyFile(i)
    Next
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Chào các bác.
Các bác có thể chuyển dữ liệu tử vùng 1 sang vùng 2 như att file giúp em được ko ạ
Em xin cảm ơn!
 

File đính kèm

  • Book1.xlsx
    9.6 KB · Đọc: 20
Upvote 0
Chào các bác.
Các bác có thể chuyển dữ liệu tử vùng 1 sang vùng 2 như att file giúp em được ko ạ
Em xin cảm ơn!

Mã:
Public Sub GPE()
Dim sArr, dArr(1 To 10000, 1 To 1), I As Long, J As Long, K As Long
sArr = Range("A1").CurrentRegion.Value
For I = 1 To UBound(sArr)
    For J = 1 To sArr(I, 2)
        K = K + 1
        dArr(K, 1) = sArr(I, 1) & J
    Next J
Next I
    Range("G1").Resize(K).Value = dArr
End Sub
 
Upvote 0
Cám ơn bác rất nhiều. Nhưng lần này em có yêu cầu còn khó hơn nhiều, mong bác lại giúp đỡ. ^^ --=0
 

File đính kèm

  • Book1.xlsx
    20.6 KB · Đọc: 29
Upvote 0
Web KT
Back
Top Bottom