Làm sao truyền biến vào ParamArray (1 người xem)

Liên hệ QC

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

ndu96081631

Huyền thoại GPE
Thành viên BQT
Super Moderator
Tham gia
5/6/08
Bài viết
30,703
Được thích
53,970
Cũng không biết phải đặt tiêu đề thế nào mới đúng (vì mình thật sự không biết gọi vấn đề này là cái giống gì nữa)
Thôi thì mô tả vấn đề:
- Giả sử tôi có 1 Function
Mã:
Function EcEc(ParamArray sArray())
......
Code
......
End Function
- Ứng dụng hàm vào 1 sub khác:
Mã:
Sub Test
  Dim aData1, aData2, aData3, Arr
  aData1 = .. gì gì đó...
  aData2 = .. gì gì đó...
  aData3 = .. gì gì đó...
  Arr = EcEc(aData1, aData2, aData3)
......
End Sub
Vấn đề là mấy cái aData1, aData2, aData3 ấy có được thông qua 1 vòng lập, số lượng bao nhiêu thằng cũng chưa biết
Mã:
Sub Test
  Dim aData() Arr
  For i = 0 to...
    aData(i) = ... gì gì đó... ''<--- gì gì đó cũng là mảng
  Nex
......
End Sub
Các phần tử trong mảng aData là những mảng con
Vậy làm sao truyền toàn bộ những mảng con này vào ParamArray của Function EcEc
 
Anh thử cách củ chuối này thử xem
 

File đính kèm

Upvote 0
Anh thử cách củ chuối này thử xem
Cách củ chuối có nhiều lắm, tôi cũng đã tham khảo 1 số bài viết nước ngoài nhưng thật sự không hài lòng
Hổng lẽ hổng có cách nào khác CHÍNH QUY sao ta? Còn không thì mình thật sự chưa biết
 
Upvote 0
Cách củ chuối có nhiều lắm, tôi cũng đã tham khảo 1 số bài viết nước ngoài nhưng thật sự không hài lòng
Hổng lẽ hổng có cách nào khác CHÍNH QUY sao ta? Còn không thì mình thật sự chưa biết

Hay là Tổng của các mảng rồi gán vô được hôn Thầy (hên xui ẹc ẹc)

Mã:
Sub Test()
  Dim aData1, aData2, aData3, Arr, TongData
  aData1 = Array("a", "b", "c")
  aData2 = Array("d", "e", "f", 3)
  aData3 = Array("g", "h", "i", 3, 4)
  TongData = Array(aData1, aData2, aData3)
  For i = 0 To UBound(TongData)
      MsgBox UBound(TongData(i))
  Next
  'Arr = EcEc(TongData)
End Sub
 
Upvote 0
Hay là Tổng của các mảng rồi gán vô được hôn Thầy (hên xui ẹc ẹc)

Mã:
Sub Test()
  Dim aData1, aData2, aData3, Arr, TongData
  aData1 = Array("a", "b", "c")
  aData2 = Array("d", "e", "f", 3)
  aData3 = Array("g", "h", "i", 3, 4)
  TongData = Array(aData1, aData2, aData3)
  For i = 0 To UBound(TongData)
      MsgBox UBound(TongData(i))
  Next
  'Arr = EcEc(TongData)
End Sub

Thì tôi vẫn đang tạm dùng cách này (vì chưa nghĩ ra cách khác)
Có điều nếu là thế thì ta xây dựng cái ParamArray làm cóc khô gì đây? VÔ NGHĨA
 
Upvote 0
Thì tôi vẫn đang tạm dùng cách này (vì chưa nghĩ ra cách khác)
Có điều nếu là thế thì ta xây dựng cái ParamArray làm cóc khô gì đây? VÔ NGHĨA

Có những trường hợp đặc biệt đành phải chịu trận thôi chứ làm sao được Thầy! Mọi việc đâu phải là vạn năng đâu!
 
Upvote 0
Cũng không biết phải đặt tiêu đề thế nào mới đúng (vì mình thật sự không biết gọi vấn đề này là cái giống gì nữa)
Thôi thì mô tả vấn đề:
- Giả sử tôi có 1 Function
Mã:
Function EcEc(ParamArray sArray())
......
Code
......
End Function
- Ứng dụng hàm vào 1 sub khác:
Mã:
Sub Test
  Dim aData1, aData2, aData3, Arr
  aData1 = .. gì gì đó...
  aData2 = .. gì gì đó...
  aData3 = .. gì gì đó...
  Arr = EcEc(aData1, aData2, aData3)
 ......
End Sub
Vấn đề là mấy cái aData1, aData2, aData3 ấy có được thông qua 1 vòng lập, số lượng bao nhiêu thằng cũng chưa biết
Mã:
Sub Test
  Dim aData() Arr
  For i = 0 to...
    aData(i) = ... [COLOR=#ff0000][B]gì gì đó[/B][/COLOR]... ''<--- [COLOR=#ff0000][B]gì gì đó[/B][/COLOR] cũng là mảng
  Nex
 ......
End Sub
Các phần tử trong mảng aData là những mảng con
Vậy làm sao truyền toàn bộ những mảng con này vào ParamArray của Function EcEc

Tôi không hiểu vấn đề lắm.
Ta có
Mã:
Function EcEc(ParamArray sArray())
    
End Function

Trong hàm EcEc ta có thể kiểm tra LBound(sArray) và UBound(sArray)
Và có thể tính được mảng sArray có bao nhiêu phần tử

Với Arr = EcEc thì số phần tử là 0

Với
Mã:
Sub Button1_Click()
Dim Arr, aData
    ReDim aData(1 To 3)
    aData(1) = Array(1, 2, 3)
    aData(2) = Array(4, 5, 6, 7, 8)
    aData(3) = "b"
    Arr = EcEc(aData)
End Sub

Thì sArray là mảng chỉ có 1 phần tử duy nhất là sArray(0), và nếu kiểm tra thì ta thấy phần tử sArray(0) này là mảng có 3 phần tử. Nếu kiểm tra tiếp thì thấy 2 phần tử đầu trong 3 phần tử kia cũng là mảng ...

Với
Mã:
Sub Button1_Click()
Dim aData1, aData2, aData3, Arr
    aData1 = Array(1, 2, 3)
    aData2 = Array(4, 5, 6, 7, 8)
    aData3 = "b"
    Arr = EcEc(aData1, aData2, aData3)
End Sub

Thì sArray là mảng có 3 phần tử là sArray(0), sArray(1), sArray(2). Nếu kiểm tra tiếp thì thấy sArray(0), sArray(1) cũng là mảng. Cũng kiểm tra được chúng có bao nhiêu phần tử.
--------------
Còn chuyện cụ thể code của EcEc như thế nào thì tùy ta định làm gì chứ? Tức bài toán cụ thể.
Vd. tôi cho phép truyền vào EcEc một số lượng mảng bất kỳ cùng kích thước. EcEc sẽ nhân các phần tử cùng vị trí trong các mảng đó và trả về tổng của các tích đó. Thế thì trong EcEc:

Chạy từ LBound(sArray) tới UBound(sArray) và kiểm tra xem mỗi phần tử của sArray có là mảng không. Nếu là mảng cả thì chúng có cùng là một chiều hay hai chiều không. Nếu cũng đúng thì chúng có cùng số dòng, số cột không. Nếu cũng đúng thì mỗi phần tử của mỗi mảng có là số không. Nếu cũng đúng thì tính các tích rồi tính tổng các tích và trả về.
 
Upvote 0
Còn chuyện cụ thể code của EcEc như thế nào thì tùy ta định làm gì chứ? Tức bài toán cụ thể.
Vd. tôi cho phép truyền vào EcEc một số lượng mảng bất kỳ cùng kích thước. EcEc sẽ nhân các phần tử cùng vị trí trong các mảng đó và trả về tổng của các tích đó. Thế thì trong EcEc:

Chạy từ LBound(sArray) tới UBound(sArray) và kiểm tra xem mỗi phần tử của sArray có là mảng không. Nếu là mảng cả thì chúng có cùng là một chiều hay hai chiều không. Nếu cũng đúng thì chúng có cùng số dòng, số cột không. Nếu cũng đúng thì mỗi phần tử của mỗi mảng có là số không. Nếu cũng đúng thì tính các tích rồi tính tổng các tích và trả về.

Em ví dụ cụ thể luôn
Em có hàm này
Mã:
Function UniqueList(ParamArray sArray())
  Dim Item, tmpArr, SubArr, tmp
  On Error Resume Next
  With CreateObject("Scripting.Dictionary")
    For Each SubArr In sArray
      tmpArr = SubArr
      If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
      For Each Item In tmpArr
        tmp = CStr(Item)
        If Len(tmp) Then
          If Not .Exists(tmp) Then .Add tmp, ""
        End If
      Next
    Next
    UniqueList = .Keys
  End With
End Function
Giờ em muốn dùng nó để lọc duy nhất qua các vùng nằm ở tất cả các sheet
Mã:
Sub Main
  aData1 = Sheet1.Range("A1:A100").Value
  aData2 = Sheet2.Range("A1:A100").Value
  aData1 = Sheet3.Range("A1:A100").Value
  ......
  aDatan = Sheetn.Range("A1:A100").Value
  
End Sub
Các mảng từ aData1 đến aDatan được nạp vào sArray của hàm UniqueList
Đương nhiên em không thể liệt kê mấy mảng aData này vì em phải dùng vòng lập duyệt qua các sheet để lấy
-----------------------
Hàm UniqueList viết tổng quát thế, chả lẽ phải sửa lại cho trường hợp này sao anh?
 
Upvote 0
Em ví dụ cụ thể luôn
Em có hàm này
Mã:
Function UniqueList(ParamArray sArray())
  Dim Item, tmpArr, SubArr, tmp
  On Error Resume Next
  With CreateObject("Scripting.Dictionary")
    For Each SubArr In sArray
      tmpArr = SubArr
      If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
      For Each Item In tmpArr
        tmp = CStr(Item)
        If Len(tmp) Then
          If Not .Exists(tmp) Then .Add tmp, ""
        End If
      Next
    Next
    UniqueList = .Keys
  End With
End Function
Giờ em muốn dùng nó để lọc duy nhất qua các vùng nằm ở tất cả các sheet
Mã:
Sub Main
  aData1 = Sheet1.Range("A1:A100").Value
  aData2 = Sheet2.Range("A1:A100").Value
  aData1 = Sheet3.Range("A1:A100").Value
  ......
  aDatan = Sheetn.Range("A1:A100").Value
  
End Sub
Các mảng từ aData1 đến aDatan được nạp vào sArray của hàm UniqueList
Đương nhiên em không thể liệt kê mấy mảng aData này vì em phải dùng vòng lập duyệt qua các sheet để lấy
-----------------------
Hàm UniqueList viết tổng quát thế, chả lẽ phải sửa lại cho trường hợp này sao anh?

Chưa nghĩ tới tối ưu, mới viết để thử xem có chạy không

Mã:
Sub Button1_Click()
Dim aData1, aData2, aData3, Arr, aData, k As Long
    aData1 = Sheet1.Range("A1:A3").Value
    aData2 = Sheet2.Range("A1:A3").Value
    aData3 = Sheet3.Range("A1:A3").Value
    Arr = UniqueList(aData1, aData2, aData3)
    Range("C1").Resize(UBound(Arr) - LBound(Arr) + 1) = Application.WorksheetFunction.Transpose(Arr)
    
    ReDim aData(1 To 3)
    For k = 1 To 3
        aData(k) = Sheets(k).Range("A1:A3").Value
    Next k
    Arr = UniqueList(aData)
    Range("D1").Resize(UBound(Arr) - LBound(Arr) + 1) = Application.WorksheetFunction.Transpose(Arr)
End Sub

Function UniqueList(ParamArray sArray())
Dim Item, tmpArr, SubArr, tmp, count, Arr, index As Long
On Error Resume Next
    count = UBound(sArray) - LBound(sArray) + 1
    If count = 0 Then
        Exit Function
    ElseIf count = 1 Then
        count = UBound(sArray(0)) - LBound(sArray(0)) + 1
        ReDim Arr(1 To count)
        For index = 1 To count
            Arr(index) = sArray(0)(index + LBound(sArray(0)) - 1)
        Next index
    Else
        Arr = sArray
    End If
    
    With CreateObject("Scripting.Dictionary")
        For Each SubArr In Arr
            tmpArr = SubArr
            If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
            For Each Item In tmpArr
                tmp = CStr(Item)
                If Len(tmp) Then
                    If Not .Exists(tmp) Then .Add tmp, ""
                End If
            Next
        Next
        UniqueList = .Keys
    End With
End Function
 
Upvote 0
Chưa nghĩ tới tối ưu, mới viết để thử xem có chạy không

Vâng em hiểu rồi
Cuối cùng vẫn là sửa lại hàm UniqueList, xét trường hợp Array trong Array
Cảm ơn anh!
-----------------
Em thì nghĩ phải đệ quy gì gì đó.. vì có trường hợp Array trong Array trong Array... vân vân... tầng tầng lớp lớp lại phải sửa tiếp sao anh?
 
Upvote 0
Vâng em hiểu rồi
Cuối cùng vẫn là sửa lại hàm UniqueList, xét trường hợp Array trong Array

Sửa là đương nhiên vì code hiện thời có lường được mọi trường hợp mà Tuấn bây giờ mới "bịa" ra đâu.

Em thì nghĩ phải đệ quy gì gì đó.. vì có trường hợp Array trong Array trong Array... vân vân... tầng tầng lớp lớp lại phải sửa tiếp sao anh?

Làm thế thì đến bao giờ.
Dữ liệu phải sao cho Arr đã là mảng các chuỗi rồi, ngược lại thì lỗi. Thế thôi. Chả lý gì xét tới level 100, 1000 cả.
Tuấn thử liệt kê ra 1 th mà code kia chưa "đủ".
----------------
Mà thôi, đệ qui thì đệ qui.
Mới viết xong và test qua 3 lần.

Mã:
Sub Button1_Click()
Dim aData1, aData2, aData3, Arr, aData, k As Long
    aData1 = Sheet1.Range("A1:A3").Value
    aData2 = Sheet2.Range("A1:A3").Value
    aData3 = Sheet3.Range("A1:A3").Value
    
    ReDim aData(1 To 5)
    For k = 1 To 3
        aData(k) = Sheets(k).Range("A1:A3").Value
    Next k
    aData(4) = Array(aData2, aData3)
'   khong thiet lap aData(5)
    Arr = UniqueList(aData, aData1, aData2, aData3, Array("nang tien", "mong minh"), "mat nau")
    Range("D1").Resize(UBound(Arr) - LBound(Arr) + 1) = Application.WorksheetFunction.Transpose(Arr)
End Sub

Function UniqueList(ParamArray sArray())
Dim Item, tmpArr, SubArr, tmp, count
Static level As Long
Static dic As Object

On Error Resume Next
    count = UBound(sArray) - LBound(sArray) + 1
    If count = 0 Then GoTo end_
    
    If level = 0 Then Set dic = CreateObject("Scripting.Dictionary")
      
    With dic
        For Each SubArr In sArray
            tmpArr = SubArr
            If Not IsArray(tmpArr) Then tmpArr = Array(tmpArr)
            For Each Item In tmpArr
                If IsArray(Item) Then
                    level = level + 1
                    UniqueList Item
                    level = level - 1
                Else
                    tmp = CStr(Item)
                    If Len(tmp) Then
                        If Not .Exists(tmp) Then .Add tmp, ""
                    End If
                End If
            Next
        Next
    End With
    If level = 0 Then
        UniqueList = dic.Keys
        Set dic = Nothing
    End If
end_:
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng em hiểu rồi
Cuối cùng vẫn là sửa lại hàm UniqueList, xét trường hợp Array trong Array
Cảm ơn anh!
-----------------
Em thì nghĩ phải đệ quy gì gì đó.. vì có trường hợp Array trong Array trong Array... vân vân... tầng tầng lớp lớp lại phải sửa tiếp sao anh?

Cho em hỏi nha, mình không biết bao nhiêu mảng phát sinh thì làm sao biết được bao nhiêu biến mảng để đặt? Còn việc xác định được bao nhiêu biến mảng thì việc đưa vào EcEc thì không cần phải mảng trong mảng nữa.
 
Upvote 0
Cho em hỏi nha, mình không biết bao nhiêu mảng phát sinh thì làm sao biết được bao nhiêu biến mảng để đặt? Còn việc xác định được bao nhiêu biến mảng thì việc đưa vào EcEc thì không cần phải mảng trong mảng nữa.

Chính vậy mà ta phải cho các mảng con vào 1 mảng lớn và phải sửa lại hàm EcEc để nó nhận biết được đâu là mảng lớn chưa nhiều mảng con, đâu là mảng con cuối cùng
Vậy thôi!
 
Upvote 0
Mà thôi, đệ qui thì đệ qui.
Mới viết xong và test qua 3 lần.

Đã thí nghiệm và thành công mỹ mãn
---------------
Làm thế thì đến bao giờ.
Dữ liệu phải sao cho Arr đã là mảng các chuỗi rồi, ngược lại thì lỗi. Thế thôi. Chả lý gì xét tới level 100, 1000 cả.
Tuấn thử liệt kê ra 1 th mà code kia chưa "đủ".
Ví dụ trường hợp thu gom dữ liệu từ các sheet, mỗi sheet là 1 mảng, tất cả các mảng ở các sheet gom lại thành 1 mảng lớn... Rồi lại duyệt qua nhiều file, mỗi mảng lớn ấy lại được gom lại cho vào 1 mảng lớn hơn nữa. Tức mảng lớn nhất chứa nhiều mảng con, mỗi mảng con lại chứa nhiều mảng nhỏ hơn
 
Upvote 0
Đã thí nghiệm và thành công mỹ mãn
---------------

Ví dụ trường hợp thu gom dữ liệu từ các sheet, mỗi sheet là 1 mảng, tất cả các mảng ở các sheet gom lại thành 1 mảng lớn... Rồi lại duyệt qua nhiều file, mỗi mảng lớn ấy lại được gom lại cho vào 1 mảng lớn hơn nữa. Tức mảng lớn nhất chứa nhiều mảng con, mỗi mảng con lại chứa nhiều mảng nhỏ hơn

Tôi hiểu mảng lớn mảng con là như thế nào. Ý tôi là hãy chỉ ra th khi mà không thể "gom" dữ liệu để nó được chấp nhận bởi UniqueList.
Vì theo tôi luôn có thể gom được. Ta có mảng aData, Redim, Redim Preserve ở những chỗ cần thiết. Sau đó thì mảng từ file1.Sheet1 tới file1.Sheetn1 cho vào aData(1) tới aData(n1), từ file2.Sheet1 tới file2.Sheetn2 cho vào aData(n1 + 1) tới aData(n1 + n2), ..., từ filek.Sheet1 tới filek.Sheetnk cho vào aData(n1 + n2 + ... + n_(k-1) + 1) tới aData(n1 + n2 + ... + nk). Mọi mảng khác cần xét cũng cho vào mảng aData. Rồi truyền aData vào UniqueList. Như thế thì mảng aData(x) chỉ chứa các chuỗi chứ không chứa mảng con nào. Cách gom của Tuấn và của tôi "khó dễ" như nhau.

Nhưng nghĩ lại thì Tuấn có lý. Vì nếu ông A sử dụng UniqueList thì làm sao ông ta biết được là "bắt buộc" phải gom theo cách của siwtom? Vậy nếu ông ta có "sáng kiến" gom theo kiểu tương tự như của Tuấn thì "tèo".

Vậy đúng là code với đệ qui thân thiện hơn với user. Mà trông có vẻ "duyên dáng" hơn.
 
Upvote 0

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

Back
Top Bottom