Hướng dẫn cách sử dụng đối tượng Collection có thể thay thế cho Dictionary

Liên hệ QC

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,662
Được thích
16,719
Giới tính
Nam
Đối tương Collection không mới mẻ gì với diễn đàn ta, nhưng nó không phổ biến bằng Dictionary, vì thế tôi mạn phép giới thiệu lại để mọi người có nhiều phương pháp lọc duy nhất hơn.

Như các bạn đã biết đối tượng Dictionary để lọc duy nhất, thì Collection vẫn có thể thực hiện được các chức năng tương tự như thế.

Collection cũng có các thuộc tính Add, Count, Item, Remove

Lưu ý: Key của nó luôn luôn là dạng chuỗi nên khi Add key phải lồng hàm CStr này vào nhé!

Để dễ hình dung, ta có các thủ tục sau theo dữ liệu của một file:

1) Không dùng hàm tự tạo để kiểm tra sự tồn tại của Key (Nó khác với Dictionary không có thuộc tính Exists):

PHP:
Sub TestCollection1()
    On Error Resume Next
    Dim arrData, arrResult
    Dim objCollect As New Collection
    Dim lngCheck As Long, e As Long, m As Long, n As Long, r As Long, u As Long
  
    e = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
    arrData = Sheet1.Range("A2:B" & e).Value
    u = UBound(arrData)
  
    ReDim arrResult(1 To u, 1 To 2)
  
    For r = 1 To u
        lngCheck = VarType(objCollect.Item(arrData(r, 1)))
        If Err.Number <> 0 Then
            Err.Clear
            n = n + 1
            objCollect.Add n, CStr(arrData(r, 1))
            arrResult(n, 1) = arrData(r, 1)
            arrResult(n, 2) = arrData(r, 2)
        Else
            m = objCollect.Item(arrData(r, 1))
            arrResult(m, 2) = arrResult(m, 2) + arrData(r, 2)
        End If
    Next
    Sheet1.Range("D2:E2").Resize(n).Value = arrResult
End Sub

2) Sử dụng hàm tự tạo để kiểm tra Key tồn tại:

PHP:
Function Exists(ByRef objCollect As Collection, ByVal strKey As String) As Boolean
    On Error Resume Next
    Dim lngCheck As Long
    lngCheck = VarType(objCollect.Item(strKey))
    If Err.Number = 0 Then Exists = True
    Err.Clear
End Function


Thủ tục dùng hàm Exists:
PHP:
Sub TestCollection2()
    Dim arrData, arrResult
    Dim objCollect As New Collection
    Dim e As Long, m As Long, n As Long, r As Long, u As Long
  
    e = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
    arrData = Sheet1.Range("A2:B" & e).Value
    u = UBound(arrData)
  
    ReDim arrResult(1 To u, 1 To 2)
  
    For r = 1 To u
        If Not Exists(objCollect, arrData(r, 1)) Then
            n = n + 1
            objCollect.Add n, CStr(arrData(r, 1))
            arrResult(n, 1) = arrData(r, 1)
            arrResult(n, 2) = arrData(r, 2)
        Else
            m = objCollect.Item(arrData(r, 1))
            arrResult(m, 2) = arrResult(m, 2) + arrData(r, 2)
        End If
    Next
    Sheet1.Range("D2:E2").Resize(n).Value = arrResult
End Sub

Các bạn xem file và đánh giá nhé!
 

File đính kèm

  • CollectionObject.xlsm
    17 KB · Đọc: 12
Đánh giá:
Bạn cho biết khi nào thì dùng Collection có lợi hơn Dictionary.
Nếu không có chỗ nào lợi hơn thì chả có lý do gì để dùng Collection.

Khi bàn phím của bạn bị hư nút 'D', bạn khó khăn trong việc gõ chữ Dictionary thì mình sẽ gõ chữ Collection để thay thế. :D
 
Upvote 0
Lâu hơn, bất tiện, gõ Collection nhanh hơn chứ bạn.
Tôi chỉ cần copy-paste cho câu "Scripting.Di..." thôi (mà thực ra tôi cũng copy như vậy nhoài, không nhất thiết phải khi bàn phím hư). Tên đối tượng của tôi là BL (bộ lọc).

Trong thư viện code của tôi làm việc. Cái đít được chứa trong một class module. Với đầy đủ phương thức sử dụng như AccumulateValues, KeysToArray, ItemsToArray, KeysAndItemsToArray, ....
(theo đúng tinh thần hướng đối tượng, bên trong class tôi dùng cái gì, Dictionary hay Collection, hay ConChoGhe là chuyện của tôi. Người dùng không cần biết tới)
 
Lần chỉnh sửa cuối:
Upvote 0
Đánh giá:
Bạn cho biết khi nào thì dùng Collection có lợi hơn Dictionary.
Nếu không có chỗ nào lợi hơn thì chả có lý do gì để dùng Collection.
Câu hỏi quá hay nếu vượt ngoài khả năng trả lời của nghĩa... bạn có thể trả lời dùm ko ... Mạnh Học chút .... cảm ơn
 
Upvote 0
Câu hỏi quá hay nếu vượt ngoài khả năng trả lời của nghĩa... bạn có thể trả lời dùm ko ... Mạnh Học chút .... cảm ơn
Trước mắt thì Collection có thể làm được một điều mà Dictionary sẽ hơi chật vật:
Chèn vào vị trí mong muốn.
 
Upvote 0
Trước mắt thì Collection có thể làm được một điều mà Dictionary sẽ hơi chật vật:
Chèn vào vị trí mong muốn.
Tôi nào giờ cũng không dùng tới Collection (mặc dù có thấy một số người viết về nó), bác @VetMini nêu một số trường hợp nào thì dùng nó và code mẫu để em học hỏi với.
 
Upvote 0
Đánh giá:
Bạn cho biết khi nào thì dùng Collection có lợi hơn Dictionary.
Nếu không có chỗ nào lợi hơn thì chả có lý do gì để dùng Collection.

Trong bài viết của em:

Đối tương Collection không mới mẻ gì với diễn đàn ta, nhưng nó không phổ biến bằng Dictionary, vì thế tôi mạn phép giới thiệu lại để mọi người có nhiều phương pháp lọc duy nhất hơn.

Như các bạn đã biết đối tượng Dictionary để lọc duy nhất, thì Collection vẫn có thể thực hiện được các chức năng tương tự như thế.

Cũng tương tự tính tổng:
Thay vì hàm SUM(B1:B3) ta cũng có thể thay thế bằng =B1+B2+B3, chỉ thế thôi.
 
Upvote 0
Từ việc khai báo đến thiếu phương thức nên không dùng Collection. Có thể khai báo kiểu late biding không? Có thể kiểm tra sự tồn tại của key không? Có thay đổi giá trị của item không?
 
Upvote 0
Cho xin 1 code điển hình nhất xin cảm ơn
Anh Mạnh quên có bài viết chi tiết rồi sao. :p


1587309305629.png
 
Upvote 0
Đối tương Collection không mới mẻ gì với diễn đàn ta, nhưng nó không phổ biến bằng Dictionary, ...

Câu này chỉ đúng cho trường hợp bạn tự dựng lên đối tượng Collection.
Riêng các đối tượng Collection có sẵn thì rất phổ biến. Điển hình chúng chính là WorkBooks, WorkSheets, Range, Cells...

Tuy nhiên điều cần biết là Collection chính nó vốn không mạnh lắm. Có rất nhiều giới hạn. Các collections có sẵn như WorkSheets thực ra đã có nhiều phương thức và thuộc tính thêm vào để phù hợp với cách sử dụng.

... Có thể khai báo kiểu late biding không? ...
Câu này không thành vấn đề.
Không có lý do gì để phải khai báo kiểu late binding:
1. Collection là một class có sẵn trong VBA. Late binding chi cho mất hiệu quả?
2. VBA không phải là một ngôn ngữ "hướng đối tượng" thực thụ. Vì vậy, tính đa hình (metamorphism) rất giới hạn, "late binding" với một class có sẵn trong ngôn ngữ hoàn toàn chẳng cho một điều lợi nào cả.
3. Variant là một hình thức late binding.
 
Upvote 0
Từ việc khai báo đến thiếu phương thức nên không dùng Collection. Có thể khai báo kiểu late biding không? Có thể kiểm tra sự tồn tại của key không? Có thay đổi giá trị của item không?
Như đã nói ở bài #12 thì ai muốn dùng gì thì dùng.

Sẵn đây lọc duy nhất còn có thể dùng một control để thực hiện:

Với dạng gộp dữ liệu này, chúng ta có thể dùng Dictionary cũng được, Collection cũng được, xử lý trên Array hay Range cũng được, nhưng tôi sẽ giới thiệu cho các bạn một phương pháp mới, đó là sử dụng ComboBox để làm việc này, rất dễ hiểu để thực hiện.

Các bạn cần phải tạo một ComboBox trên UserForm (nên) hoặc trên Sheet để thực hiện nhé!

Đây là code của thủ tục này:

Mã:
Sub GopDuLieu()
    Dim arrNguon
    Dim c As Byte
    Dim cbxGopDuLieu As MSForms.ComboBox
    Dim e As Long, n As Long, r As Long, u As Long
   
    e = Sheets("Query result").Range("A" & Rows.Count).End(xlUp).Row
    arrNguon = Sheets("Query result").Range("A2:F" & e).Value
   
    u = UBound(arrNguon, 1)
   
    Set cbxGopDuLieu = UserForm1.ComboBox1
    cbxGopDuLieu.Clear
    With cbxGopDuLieu
        For r = 1 To u
            .Text = arrNguon(r, 1)
            If Not .MatchFound Then
                .AddItem arrNguon(r, 1), n
                For c = 1 To 5
                    .List(n, c) = "'" & arrNguon(r, c + 1)
                Next
                n = n + 1
            Else
                For c = 1 To 5
                    .List(.ListIndex, c) = .List(.ListIndex, c) & vbLf & arrNguon(r, c + 1)
                Next
            End If
        Next
        r = .ListCount + 1
    End With
   
    Sheets("KQ_ComboBox").Range("A2:F" & Rows.Count).Clear
    With Sheets("KQ_ComboBox").Range("A2:F" & r)
        .Value = cbxGopDuLieu.List
        .Borders.LineStyle = 1
        .VerticalAlignment = xlTop
        .WrapText = True
    End With
End Sub
 
Upvote 0
Như đã nói ở bài #12 thì ai muốn dùng gì thì dùng.

Sẵn đây lọc duy nhất còn có thể dùng một control để thực hiện:
Dictionary là công cụ của Scripting Engine, không phải của VBA.
Vì là code của Scripting Engine cho nên nó được cải tiến rất đều đặn và rất hiệu quả. Kỹ thuật bảng băm dùng để tra keys rất cao.

Vì vậy, với con số nhỏ (vài trăm), và key ngắn thì Collection có thể nhanh hơn Dictionary. Nhưng khi con số bắt đầu lớn (hàng ngàn) và/hoặc key phức tạp, dài thì Dictionary sẽ bắt đầu trội hơn.

Đương nhiên, dictionary chính thức nó là bảng tra, và collection chính thức nó là một tập hợp. Dùng để lọc duy nhất chỉ là lợi dụng tính chất key duy nhất của chúng thôi.
 
Upvote 0
Bài viết này chỉ có thể đánh lừa được các bạn không biết hoặc biết quá ít về VBA.

Collection không thể thay thế cho Dictionary. Collection đơn giản hơn Dictionary quá nhiều.


Collection là thư viện chính thống của VBA, Dictionaty thì không phải.

Dictionary sử dụng hash table để sắp xếp và truy xuất nên tuy nhập vào có thể chậm nhưng truy xuất rất là nhanh.

Collection thường sử dụng để lưu trữ đối tượng, ít khi sử dụng cho xử lý dữ liệu.

Collection không kiểm tra được sự tồn tại của Khóa và Giá trị.
Collection không thể xuất tập các Key hoặc tập các giá trị.
Collection không thể xử lý dữ liệu lớn.

Để thay thế cho Dictionary phải kể đến như: Hashtable trong thư viện mscorlib, System.Collections ArrayList SortedList, ...
 
Upvote 0
Bài viết này chỉ có thể đánh lừa được các bạn không biết hoặc biết quá ít về VBA.

Collection không thể thay thế cho Dictionary. Collection đơn giản hơn Dictionary quá nhiều.


Collection là thư viện chính thống của VBA, Dictionaty thì không phải.

Dictionary sử dụng hash table để sắp xếp và truy xuất nên tuy nhập vào có thể chậm nhưng truy xuất rất là nhanh.

Collection thường sử dụng để lưu trữ đối tượng, ít khi sử dụng cho xử lý dữ liệu.

Collection không kiểm tra được sự tồn tại của Khóa và Giá trị.
Collection không thể xuất tập các Key hoặc tập các giá trị.
Collection không thể xử lý dữ liệu lớn.

Để thay thế cho Dictionary phải kể đến như: Hashtable trong thư viện mscorlib, System.Collections ArrayList SortedList, ...
Bạn và anh Vetmini nói đều không sai, tuy nhiên cho tới nay chưa thấy ai dùng Dictionary để thực hiện hầu hết các việc mà bạn liệt kê, nó cũng chi dùng để lọc duy nhất cho đến thời điểm này, vậy thì Collection dùng để làm điều đó cũng không phải là không được.
 
Upvote 0
Web KT

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

Back
Top Bottom