Hỏi: Cách duyệt nhiều Array trong VBA ? (1 người xem)

Liên hệ QC

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

tedaynui

(*_*)
Thành viên danh dự
Tham gia
12/8/06
Bài viết
1,875
Được thích
2,482
Trong VBA, giả sử tôi có 10 Array : Arr1, Arr2, Arr3, ..., Arr10
Xin hỏi có thể duyệt 10 Array trên bằng For được không ?
Ví dụ : đại loại thế này
PHP:
For i=1 to 10
    Arr(i) = [A5:A10]

    'Hoặc là
    Arr & i = [A5:A10]
next i
XIn cảm ơn

TDN
 
Trong VBA, giả sử tôi có 10 Array : Arr1, Arr2, Arr3, ..., Arr10
Xin hỏi có thể duyệt 10 Array trên bằng For được không ?
Ví dụ : đại loại thế này
PHP:
For i=1 to 10
    Arr(i) = [A5:A10]

    'Hoặc là
    Arr & i = [A5:A10]
next i
XIn cảm ơn

TDN

Ý anh là vậy phải không ? ===\.

PHP:
Sub Test()
Dim arr(1 To 3)
arr(1) = Array("a", "b", "c")
arr(2) = Array("d", "e", "f")
arr(3) = Array("g", "h", "i")

For i = 1 To 3
testvalue = arr(i)
For j = 0 To 2
MsgBox testvalue(j)
Next j
Next i
End Sub
 
Upvote 0
Cám ơn bạn, không phải vậy bạn à.
Ý mình thế này. Ví dụ gán giá trị [A5:A10] của 10 Sheet khác nhau vào 10 Array khác nhau (Arr1,....,Arr10)
For i = 1 to 10
Arr & i = Sheets("Sheet" & i).[A5:A10]
Next i

Nhưng Arr & i là không được : Vậy cách cách nào duyệt các Arr bằng For...Next không ?
 
Upvote 0
Trong VBA, giả sử tôi có 10 Array : Arr1, Arr2, Arr3, ..., Arr10
Xin hỏi có thể duyệt 10 Array trên bằng For được không ?
Ví dụ : đại loại thế này
PHP:
For i=1 to 10
    Arr(i) = [A5:A10]

    'Hoặc là
    Arr & i = [A5:A10]
next i
XIn cảm ơn

TDN
Tôi không rõ bài toán cụ thể mà bạn đang gặp là như thế nào, bạn thử tham khảo thử đoạn code này xem có giúp được gì không nhé.
Mã:
Sub test()
    Dim i As Integer
    Dim arr() As Variant
    Dim iSheet As Integer
    iSheet = Sheets.Count
    ReDim arr(1 To iSheet)
    For i = 1 To iSheet
        arr(i) = WorksheetFunction.Transpose(Sheets(i).Range("A1:A10"))
    Next
    
    For i = 1 To iSheet
        MsgBox Join(arr(i), "-")
    Next
End Sub
 
Upvote 0
Cảm ơn rollover79, theo cách của bạn, mình đã giải quyết được vấn đề.

TDN
 
Upvote 0
Phước thử dùng mảng 3 chiều xem:
PHP:
Sub abc()
Dim MyArr(1 To 15, 1 To 2, 1 To 10)
Dim i As Long, j As Long, k As Long
For i = 1 To 10
    For j = 1 To 15
        For k = 1 To 2
            MyArr(j, k, i) = Sheets(i).Cells(j + 1, k)
            Cells(2, 1).Offset(j - 1, i * 2 + k) = MyArr(j, k, i)
        Next
    Next
Next
''Xử lý riêng mảng 2 chiều của sheet3:
For i = 1 To 15
    For j = 1 To 2
        MyArr(i, j, 3) = MyArr(i, j, 3) & MyArr(i, j, 4)
        Cells(i + 18, j + 2) = MyArr(i, j, 3)
    Next
Next
End Sub

Dùng cách của RollOver, tôi chưa nghĩ ra cách xử lý riêng từng mảng Arr(i) (mỗi mảng Arr(i) lấy từ 1 sheet i có lẽ có nhu cầu xử lý riêng)
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Dùng cách của RollOver, tôi chưa nghĩ ra cách xử lý riêng từng mảng Arr(i) (mỗi mảng Arr(i) lấy từ 1 sheet i có lẽ có nhu cầu xử lý riêng)
Cảm ơn Anh rất nhiều, dùng mảng 3 chiều như anh rất hay và dễ hiểu hơn. Nhưng nhu cầu của em dùng mảng 2 chiều là đủ, dùng xong em xóa mảng đó luôn cho đỡ tốn bộ nhớ. Thay vì duyệt từng Sheet
(như trước đây em đã làm) thì em dùng mảng. Quả nhiên tốc độ kinh ngạc luôn.

Em cũng đã test cách của
rollover79 muốn xử lý từng giá trị trong mảng Arr(i) thì dùng như vầy là được Arr(i)(dòng, cột)

TDN
 
Upvote 0
Do mình chưa biết cách truy xuất phần tử con của Arr(i) nên mới phải dùng 3D. Nay biết cách truy xuất Arr(i) (j, k) thì Quả thực dùng cách của RollOver (Mảng trong mảng) nhanh hơn.
Thí dụ muốn gán 1 mảng Arr(i) xuống sheet, "Mảng trong mảng" sẽ gán 1 lần, còn mảng 3D phải gán từng phần tử.

Có điều không hiểu tại sao RollOver dùng Transpose? Tôi đã thử không dùng Transpose vẫn thao tác và xử lý được, kể cả mảng con Arr(i) 1 cột hay nhiều cột.

Thí dụ sau dùng file bài trên, dùng mảng trong mảng và không dùng transpose. Đã test với Arr(i) 1 cột hoặc nhiều cột.

PHP:
Sub def()
Dim MyArr(1 To 10)
Dim i As Long, j As Long, k As Long

For i = 1 To 10
    MyArr(i) = Sheets(i).Range("A2:b16")
    Cells(2, 24).Offset(0, i * 2).Resize(15, 2) = MyArr(i)
Next

'Xử lý riêng mảng Arr(3):'

For j = 1 To 15
    For k = 1 To 2
        MyArr(3)(j, k) = MyArr(3)(j, k) & MyArr(4)(j, k)
Next
Next
Cells(19, 26).Resize(15, 2) = MyArr(3)
End Sub
 
Upvote 0
Do mình chưa biết cách truy xuất phần tử con của Arr(i) nên mới phải dùng 3D. Nay biết cách truy xuất Arr(i) (j, k) thì Quả thực dùng cách của RollOver (Mảng trong mảng) nhanh hơn.
Thí dụ muốn gán 1 mảng Arr(i) xuống sheet, "Mảng trong mảng" sẽ gán 1 lần, còn mảng 3D phải gán từng phần tử.
Thí dụ sau dùng file bài trên, dùng mảng trong mảng và không dùng transpose. Đã test với Arr(i) 1 cột hoặc nhiều cột.

PHP:
Sub def()
Dim MyArr(1 To 10)
Dim i As Long, j As Long, k As Long

For i = 1 To 10
    MyArr(i) = Sheets(i).Range("A2:b16")
    Cells(2, 24).Offset(0, i * 2).Resize(15, 2) = MyArr(i)
Next

'Xử lý riêng mảng Arr(3):'

For j = 1 To 15
    For k = 1 To 2
        MyArr(3)(j, k) = MyArr(3)(j, k) & MyArr(4)(j, k)
Next
Next
Cells(19, 26).Resize(15, 2) = MyArr(3)
End Sub
Quá hay, thay vì dùng CombineTwoDArrays em dùng thử như sau.
Và cũng không biết Ph làm gì mà cần dùng nhiều Arr thế.
PHP:
Option Explicit
Dim i As Long, iR As Long, endR As Long
Sub GanArr()
Dim MyArr(1 To 3)
For i = 1 To 3
  With Sheets(i)
    endR = .Cells(65000, 1).End(xlUp).Row
    MyArr(i) = .Range("A1:B" & endR)
  End With
Next i
'Gan vao
iR = 1
For i = 1 To 3
  With Sheet4
    .Cells(iR, 1).Resize(UBound(MyArr(i)), 2) = MyArr(i)
  End With
  iR = iR + UBound(MyArr(i))
Next i
Erase MyArr
End Sub
 
Upvote 0
Nếu địa chỉ mảng cố định thì có thể dùng phương thức Union để nối, sau đó trình duyệt qua từng ô. Bác thử xem ở dưới đây:

Mã:
Sub RangesJoin()
    Dim Ranges As Range, CellRange As Range
    Set Ranges = Union(Range("B3:B11"), Range("D7:D18"), Range("F5:G12"), Range("H10:H20"))
    For Each CellRange In Ranges
        MsgBox CellRange.Value
    Next
    
    Set Ranges = Nothing
End Sub
 

File đính kèm

Upvote 0
Quá hay, thay vì dùng CombineTwoDArrays em dùng thử như sau.
Và cũng không biết Ph làm gì mà cần dùng nhiều Arr thế.
Em có 10 sheet và cần duyệt qua vùng A1:BA5000 của 10 Sheet này. Thật ra, em dùng đâu tới 10 mảng như vậy nhưng lấy ví dụ để tìm cách duyệt mảng bằng For cho nhanh, code gọn hơn để gán vùng A1:BA5000 của 10 sheet vào 1 mảng duy nhất. Nhưng không biết dùng tên mảng "động". Sau khi được các anh giúp đỡ, em thay đổi thuật toán tí : Em dùng For duyệt từng Sheet, gán A1:BA5000 vào mảng xử lý xong, kết quả đưa vào mảng tạm. Lần lượt 10 Sheet, như vậy em chỉ dùng có 2 mảng thôi.

Codes chạy thấy sướng tê người luôn, hi hi

Xin cám ơn các anh yêu rất nhiều nhiều!
 
Upvote 0

Em có 10 sheet và cần duyệt qua vùng A1:BA5000 của 10 Sheet này. Thật ra, em dùng đâu tới 10 mảng như vậy nhưng lấy ví dụ để tìm cách duyệt mảng bằng For cho nhanh, code gọn hơn để gán vùng A1:BA5000 của 10 sheet vào 1 mảng duy nhất. Nhưng không biết dùng tên mảng "động". Sau khi được các anh giúp đỡ, em thay đổi thuật toán tí : Em dùng For duyệt từng Sheet, gán A1:BA5000 vào mảng xử lý xong, kết quả đưa vào mảng tạm. Lần lượt 10 Sheet, như vậy em chỉ dùng có 2 mảng thôi.

Codes chạy thấy sướng tê người luôn, hi hi

Xin cám ơn các anh yêu rất nhiều nhiều!
Cũng có thể dùng Dictionary Object để làm điều này
- Khởi tạo ban đầu:
PHP:
Public Dic
Sub Initialize()
  Dim i As Long
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To Sheets.Count
    Dic.Add i, Sheets(i).Range("A1:B10").Value
  Next
End Sub
- Sau khi chạy xong code trên, giờ chỉ việc lấy ra mà xài thôi! Ví dụ
PHP:
Sub Test()
  MsgBox Dic.Item(2)(5, 2)
End Sub
Dic.Item(2)(5, 2) mang ý nghĩa lấy dữ liệu ở dòng 5, cột 2 của sheet thứ 2
 
Upvote 0
Cũng có thể dùng Dictionary Object để làm điều này
- Khởi tạo ban đầu:
PHP:
Public Dic
Sub Initialize()
  Dim i As Long
  Set Dic = CreateObject("Scripting.Dictionary")
  For i = 1 To Sheets.Count
    Dic.Add i, Sheets(i).Range("A1:B10").Value
  Next
End Sub
- Sau khi chạy xong code trên, giờ chỉ việc lấy ra mà xài thôi! Ví dụ
PHP:
Sub Test()
  MsgBox Dic.Item(2)(5, 2)
End Sub
Dic.Item(2)(5, 2) mang ý nghĩa lấy dữ liệu ở dòng 5, cột 2 của sheet thứ 2
i trong này là thứ tự sheet từ trái sang phải chứ không phải là name sheet hoặc code sheet dễ bị nhầm lẫn và nên chỉnh lại
 
Upvote 0
Quá hay, thay vì dùng CombineTwoDArrays em dùng thử như sau.
Và cũng không biết Ph làm gì mà cần dùng nhiều Arr thế.
PHP:
Option Explicit
Dim i As Long, iR As Long, endR As Long
Sub GanArr()
Dim MyArr(1 To 3)
For i = 1 To 3
  With Sheets(i)
    endR = .Cells(65000, 1).End(xlUp).Row
    MyArr(i) = .Range("A1:B" & endR)
  End With
Next i
'Gan vao
iR = 1
For i = 1 To 3
  With Sheet4
    .Cells(iR, 1).Resize(UBound(MyArr(i)), 2) = MyArr(i)
  End With
  iR = iR + UBound(MyArr(i))
Next i
Erase MyArr
End Sub
Bạn chỉ cần 1 vòng lặp
iR = 1
For i = 1 To 3
With Sheets(i)
endR = .Cells(65000, 1).End(xlUp).Row
MyArr(i) = .Range("A1:B" & endR)
End With
Sheet4.Cells(iR, 1).Resize(UBound(MyArr(i)), 2) = MyArr(i)
iR = iR + UBound(MyArr(i))
Next i
 
Upvote 0
Bạn chỉ cần 1 vòng lặp
iR = 1
For i = 1 To 3
With Sheets(i)
endR = .Cells(65000, 1).End(xlUp).Row
MyArr(i) = .Range("A1:B" & endR)
End With
Sheet4.Cells(iR, 1).Resize(UBound(MyArr(i)), 2) = MyArr(i)
iR = iR + UBound(MyArr(i))
Next i
Anh ơi vấn đề là không phải là gán từ sheet(i) vào sheet4 mà là vận dụng tạo nhiều Array từ nhiều sh, và mỗi array này tác giả muốn thực hiện những yêu cầu riêng.
Còn nếu theo yêu cầu trên thì cũng kg cần dùng array mà nếu dùng cũng chỉ cần 1 array thôi. Gán xong, chép xuống và gán tiếp.
 
Upvote 0
Anh ơi vấn đề là không phải là gán từ sheet(i) vào sheet4 mà là vận dụng tạo nhiều Array từ nhiều sh, và mỗi array này tác giả muốn thực hiện những yêu cầu riêng.
Còn nếu theo yêu cầu trên thì cũng kg cần dùng array mà nếu dùng cũng chỉ cần 1 array thôi. Gán xong, chép xuống và gán tiếp.
Có 1 điều nữa mình nghĩ là quan trong (như bài #13) , i là thứ tự , nếu không thì hỏng khó lường
 
Upvote 0
Có 1 điều nữa mình nghĩ là quan trong (như bài #13) , i là thứ tự , nếu không thì hỏng khó lường
Đúng rối anh ạ. Tuy vậy, những code bên trên chỉ là code mẫu, khi vận dụng phải tuỳ biến. Thí dụ phải đặt tên sheet theo dang số hoặc Ký tự kèm số. Sau đó vận dụng như sau:

- Nếu tên sheet là số:

Sheets(Str(Trim(i))

- Nếu tên sheet có dạng Th1, Th2:

Sheets("Th" & Str(Trim(i))

- Nếu tên sheet bất kỳ, thì phải sắp thứ tự và giữ nguyên thứ tự đó. Hoặc sửa code name thành dạng số

- nếu tên sheet bất kỳ và không đảm bảo được thứ tự, thì không áp dụng được phương pháp "sướng tê người" này.
 
Upvote 0
i trong này là thứ tự sheet từ trái sang phải chứ không phải là name sheet hoặc code sheet dễ bị nhầm lẫn và nên chỉnh lại
Với Dictionary thì hoàn toàn có thể sử dụng key là name của sheet như sau
Mã:
Public Dic
Sub Initialize()
    Dim i As Long
    Set Dic = CreateObject("Scripting.Dictionary")
    Dim sh As Worksheet
    For Each sh In Sheets
        Dic.Add sh.Name, sh.Range("A1:B10")
    Next
End Sub

Sub Test()
    Dim sName As String
    ' Gan ten sheet vao day de test
    sName = "Sheet3"
    If Dic.exists(sName) Then
        MsgBox Dic.Item(sName)(5, 2)
    Else
        MsgBox "Sheet khong ton tai!"
    End If
End Sub
To ptm: Trong ví dụ trước của tôi sử dụng transpose để chuyển vùng thành mảng để test(có sử dụng join). Khi sử dụng mọi người nên phân biệt khái niệm giữa Range và Array, về ý nghĩa thì cơ bản là nó giống nhau, tuy nhiên cũng có nhiều điểm không giống nhau.
 
Upvote 0
Lấy 1 phần Array

Nhờ các bạn giúp cách lấy 1 phần trong array , ví dụ :
arr1=[A1:Z30] , muốn thông qua arr1 để lấy arr2=[A10:Z20]
Cảm ơn
 
Upvote 0
Upvote 0
Nhờ các bạn giúp cách lấy 1 phần trong array , ví dụ :
arr1=[A1:Z30] , muốn thông qua arr1 để lấy arr2=[A10:Z20]
Cảm ơn
Đọc cái yêu cầu này tôi không hiểu lắm, không rõ lấy thông qua arr1 là như thế nào? Bạn có thể đưa ra vấn đề cụ thể đang gặp lên không? Và tôi cũng nhắc lại là Array và Range là không hoàn toàn giống nhau. Tốt nhất khi có thắc mắc cụ thể là vấn đề gì thì có thể cho 1 ví dụ cụ thể sẽ dễ hình dung hơn.
 
Upvote 0
chào các anh chị! hôm nay em qua topic này đọc thấy hay và áp dung cho công việc của em thì có vấn đề kính mong các anh chị chỉ giáo.
nếu khai báo array như sau
dim Arr(1 to 2)
for I = 1 to 2
arr(I)=sheet(I).range("A1:A10")
next I
sau đó ta định lại kich thước cho mảng Arr(I) như sau
redim preserve Arr(I)(1 to 10,1 to 2)
thì báo lỗi ngay tại dòng này sai cú pháp mong các anh chị giải thích dùm
 
Upvote 0
chào các anh chị! hôm nay em qua topic này đọc thấy hay và áp dung cho công việc của em thì có vấn đề kính mong các anh chị chỉ giáo.
nếu khai báo array như sau
dim Arr(1 to 2)
for I = 1 to 2
arr(I)=sheet(I).range("A1:A10")
next I
sau đó ta định lại kich thước cho mảng Arr(I) như sau
redim preserve Arr(I)(1 to 10,1 to 2)
thì báo lỗi ngay tại dòng này sai cú pháp mong các anh chị giải thích dùm

Đương nhiên lỗi vì sai cú pháp
Bạn có thể làm theo cách:
- Lấy mảng con ra ngoài bằng 1 biến tạm nào đó
- Chỉnh lại kích thước của mảng con (chính là biến tạm)
- Xong, "nhét" ngược cái biến tạm (tức mảng con) vào trong mảng lớn
Ví dụ:
Mã:
Sub Test()
  Dim i As Long
  Dim arr(1 To 2), aTmp
  For i = 1 To 2
    arr(i) = Sheets(i).Range("A1:A10")
  Next i
  aTmp = arr(2) 'Lay mang con ra ngoài
  ReDim Preserve aTmp(1 To 10, 1 To 2) 'Thay doi kich thuoc mang
  arr(2) = aTmp 'Cho mang con nguoc vào mang lon
End Sub
 
Upvote 0
Trong câu lệnh này:
redim preserve Arr(I)(1 to 10,1 to 2)
Trình dịch không phân biệt nổi redim nên áp dụng cho Arr hay là Arr(I). Vì cả Arr lẫn Arr(I) đều là mảng. Vì vậy nó đành báo lỗi.

Để khắc phục, bạn phải dùng câu lệnh cho rõ rệt. Một trong những cách là dùng biến phụ như bài #23 (của ndu96081633)

Có một cách khác, không phải dùng biến phụ, nhưng phải dùng kiểu tự lâp
Mã:
Private Type MangTrongMang
ATrong As Variant
End Type

Sub Test()
  Dim i As Long
  Dim arr(1 To 2) As MangTrongMang
  For i = 1 To 2
    arr(i).ATrong = Sheets(i).Range("A1:A10")
  Next i
  ReDim Preserve arr(2).ATrong(1 To 10, 1 To 2) 'Thay doi kich thuoc mang
End Sub

Trong trường hợp này, toán tử dấu chấm giữa arr(2) và ATrong(...) cho trình dịch biết cái bạn muốn áp dụng redim vào là cái phần sau dấu chấm
 
Lần chỉnh sửa cuối:
Upvote 0

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

Back
Top Bottom