[TẶNG] Thuật toán lọc tìm kiếm mới trên ComboBox.

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,590
Được thích
16,653
Giới tính
Nam
Mặc dù cách lọc mới này cũng là những vòng lặp để duyệt từng hàng trên mảng như những thuật toán lọc hiện hành, nhưng tôi "phát minh" ra một kiểu lọc mới có thể giảm được thời gian từ bằng việc lọc thông thường cho đến nhanh hơn rất nhiều.

Cụ thể là lọc thông thường các coder thường lấy mảng gốc để lọc cho bất cứ từ khóa (key) nào, còn tôi sẽ lọc được mảng nào lưu tạm lại mảng đó để dùng lọc cho các từ khóa sau. Vì vậy khi bạn gõ ký tự đầu tiên sẽ có thời gian lọc như các kiểu lọc thông thường, nhưng từ ký tự thứ 2 và thứ n sẽ giảm dần theo dữ liệu còn lại trên mảng lưu tạm.

Và cứ mỗi ký tự bị xóa nó sẽ trả lại mảng tương ứng đã lọc trước đó cho nên nó không mất thời gian cho việc lọc lại.

Code này tôi viết để lọc cho ComboBox, nhưng nếu ai muốn tùy biến trên TextBox và gán dữ liệu vào ListBox cũng không vấn đề gì.

Và code này tôi xin tặng các bạn nhân mùa dịch khủng khiếp này. Tôi cũng rất mong được các bạn góp ý cho những trường hợp làm cho nó hoàn thiện hơn, nhanh hơn.

Tôi tạm lấy hơn 11 ngàn phường xã trong nước x 10 lần để có số hàng 111,620 dòng để test.

PHP:
Private Sub cbxPhuongXa_Change()
    If cbxPhuongXa.Text = "" Then
        ReDim Preserve priArrPhuongXa(0 To 0)
        cbxPhuongXa.Column = priArrPhuongXa(0)
        GoTo ExitSub
    End If
 
    On Error GoTo ExitSub
    Dim c As Long, lngLenText As Long, lngUbd As Long
 
    lngLenText = Len(cbxPhuongXa.Text)
    lngUbd = UBound(priArrPhuongXa)
     
    c = lngLenText - 1
 
    If Not IsArray(priArrPhuongXa(c)) Then
        cbxPhuongXa.Clear
        ReDim Preserve priArrPhuongXa(0 To lngLenText)
        GoTo ExitSub
    End If
 
    If lngUbd > lngLenText Then
        If Not IsArray(priArrPhuongXa(lngLenText)) Then
            cbxPhuongXa.Clear
            cbxPhuongXa.ForeColor = &H800000
        Else
            cbxPhuongXa.Column = priArrPhuongXa(lngLenText)
        End If
        ReDim Preserve priArrPhuongXa(0 To lngLenText)
        GoTo ExitSub
    End If
     
    If Right(cbxPhuongXa.Text, 1) = "*" Or Right(cbxPhuongXa.Text, 1) = "?" Then
        ReDim Preserve priArrPhuongXa(0 To lngLenText)
        priArrPhuongXa(lngLenText) = priArrPhuongXa(lngUbd)
        GoTo ExitSub
    End If
     
    Dim arrFilter()
    Dim strType As String, strTemp As String, strColOne As String
    Dim n As Long, r As Long, t As Long, uCol As Long, uRow As Long
     
    c = lngLenText - 1
    lRow = LBound(priArrPhuongXa(c), 2): uRow = UBound(priArrPhuongXa(c), 2)
 
    strTemp = UCase(LoaiDauUni(cbxPhuongXa.Text))
    strType = "*" & strTemp & "*"
    strTypeTwo = strTemp & "*"
     
    For r = lRow To uRow
        strColOne = UCase(LoaiDauUni(priArrPhuongXa(c)(0, r)))
        If strColOne Like strType Then
            ReDim Preserve arrFilter(0 To 0, 0 To n)
            arrFilter(0, n) = priArrPhuongXa(c)(0, r)
            n = n + 1
        End If
    Next
 
    If n Then
        ReDim Preserve priArrPhuongXa(0 To lngLenText)
        priArrPhuongXa(lngLenText) = arrFilter
        cbxPhuongXa.Column = arrFilter
    Else
        cbxPhuongXa.Clear
        cbxPhuongXa.ForeColor = &H800000
        ReDim Preserve priArrPhuongXa(0 To lngLenText)
    End If

ExitSub:
    If cbxPhuongXa.ListCount > 0 Then cbxPhuongXa.DropDown
End Sub

Tôi cũng khuyến mại thêm cho các bạn Hàm LoaiDauUni để loại bỏ dấu tiếng Việt kiểu gõ Unicode (dựng sẵn).

PHP:
Function LoaiDauUni(ByVal strText As String) As String
    If strText = "" Then Exit Function
    Static ObjDict As Object
    Static blnInitial As Boolean
 
    If Not blnInitial Then
        Dim c As Byte
        Dim arrNoMarks, arrUnicode
        arrUnicode = Array(192, 193, 194, 195, 200, 201, 202, 204, 205, 210, 211, 212, _
                            213, 217, 218, 221, 224, 225, 226, 227, 232, 233, 234, 236, 237, _
                            242, 243, 244, 245, 249, 250, 253, 258, 259, 272, 273, 296, 297, _
                            360, 361, 416, 417, 431, 432, 7840, 7841, 7842, 7843, 7844, 7845, _
                            7846, 7847, 7848, 7849, 7850, 7851, 7852, 7853, 7854, 7855, 7856, _
                            7857, 7858, 7859, 7860, 7861, 7862, 7863, 7864, 7865, 7866, 7867, _
                            7868, 7869, 7870, 7871, 7872, 7873, 7874, 7875, 7876, 7877, 7878, _
                            7879, 7880, 7881, 7882, 7883, 7884, 7885, 7886, 7887, 7888, 7889, _
                            7890, 7891, 7892, 7893, 7894, 7895, 7896, 7897, 7898, 7899, 7900, _
                            7901, 7902, 7903, 7904, 7905, 7906, 7907, 7908, 7909, 7910, 7911, _
                            7912, 7913, 7914, 7915, 7916, 7917, 7918, 7919, 7920, 7921, 7922, _
                            7923, 7924, 7925, 7926, 7927, 7928, 7929)
        arrNoMarks = Array("A", "A", "A", "A", "E", "E", "E", "I", "I", "O", "O", "O", "O", _
                            "U", "U", "Y", "a", "a", "a", "a", "e", "e", "e", "i", "i", "o", "o", _
                            "o", "o", "u", "u", "y", "A", "a", "D", "d", "I", "i", "U", "u", "O", _
                            "o", "U", "u", "A", "a", "A", "a", "A", "a", "A", "a", "A", "a", "A", _
                            "a", "A", "a", "A", "a", "A", "a", "A", "a", "A", "a", "A", "a", "E", _
                            "e", "E", "e", "E", "e", "E", "e", "E", "e", "E", "e", "E", "e", "E", _
                            "e", "I", "i", "I", "i", "O", "o", "O", "o", "O", "o", "O", "o", "O", _
                            "o", "O", "o", "O", "o", "O", "o", "O", "o", "O", "o", "O", "o", "O", _
                            "o", "U", "u", "U", "u", "U", "u", "U", "u", "U", "u", "U", "u", "U", _
                            "u", "Y", "y", "Y", "y", "Y", "y", "Y", "y")
        Set ObjDict = CreateObject("Scripting.Dictionary")
        For c = 0 To 133
            ObjDict(arrUnicode(c)) = arrNoMarks(c)
        Next
        blnInitial = True
    End If
 
    Dim i As Long, j As Long, lngAscW As Long
    For i = 1 To Len(strText)
        lngAscW = AscW(Mid(strText, i, 1))
        If lngAscW > 191 Then
            Mid(strText, i, 1) = ObjDict.Item(lngAscW)
        End If
    Next
    LoaiDauUni = strText
End Function

P/S: Nếu muốn lọc mà không cần hàm LoaiDauUni để nhanh hơn, hãy xem bài #58.
 

File đính kèm

  • FilterTest-HTN.xlsm
    1.1 MB · Đọc: 246
Lần chỉnh sửa cuối:
Nói thêm là cái hay ở đây là "mảng ngược" nó có thể "resize" được số dòng mà từ trước đến nay chúng ta không ai phát hiện ra hoặc chưa áp dụng đến.
Bạn tưởng thế thôi. Hoặc bạn không đọc các bài của người khác hoặc đọc rồi bạn quên. Tôi không nhớ rõ tôi dùng Column lần đầu tiên khi nào vì tôi từng ngồi trên 2 diễn đàn. Thời gian ngay sau khi ban nick siwtom tôi chỉ ngồi ở diễn đàn Ba Lan.

Ngày 19/11/2017 trong bài #15


tôi đã viết:

Với dữ liệu nhiều (nhiều dòng thỏa) thì không nên dùng AddItem mà ghi vào mảng rồi nhập vào List (hoặc Column tùy theo mảng kia thế nào)
 
Upvote 0
Bạn tưởng thế thôi. Hoặc bạn không đọc các bài của người khác hoặc đọc rồi bạn quên. Tôi không nhớ rõ tôi dùng Column lần đầu tiên khi nào vì tôi từng ngồi trên 2 diễn đàn. Thời gian ngay sau khi ban nick siwtom tôi chỉ ngồi ở diễn đàn Ba Lan.

Ngày 19/11/2017 trong bài #15


tôi đã viết:

Với dữ liệu nhiều (nhiều dòng thỏa) thì không nên dùng AddItem mà ghi vào mảng rồi nhập vào List (hoặc Column tùy theo mảng kia thế nào)
Ý của em là thông thường người ta sẽ lọc mảng theo kiểu thông dụng là lọc để lấy số hàng thỏa điều kiện, sau đó mới có được tổng số dòng rồi thì bắt đầu người ta mới Redim một mảng khác rồi duyệt thêm một vòng lặp nữa. Còn em thì Resize cái mảng "ngược" của nó luôn vì mình lợi dụng thuộc tính hàng thì cố định, cột thì có thể co giãn được nên mình Redim Preserve mảng sau đó dùng thuộc tính của ComboBox/ListBox là Column để add list cho nó. Vấn đề này em chưa thấy ai làm vậy.
 
Upvote 0
Đây chỉ là ví dụ nhanh và bàn về lọc thôi. Không có chỗ nào nói về lọc duy nhất mà anh.
Sau bài "duy nhất" thì tôi cũng chỉ nói về lọc ra kết quả dư nhiều quá khi tìm kiếm đúng từ khoá "xạ" và "phú" (bài 26 và 33). Ngoài ra nếu lọc nhanh hoặc rất nhanh mà gõ chậm hiển thị thì không bù được với nhau. Tôi có ví dụ gõ liên tiếp 4 phím p, h, u, 1 để cho ra "phú", thì 1 giây sau 3 ký tự của chữ "phú" mới nhảy ra cùng lúc. Hoặc gõ "ph" xem kết quả, sau đó gõ thêm "ú" cũng phải chờ.
 
Upvote 0
Sau bài "duy nhất" thì tôi cũng chỉ nói về lọc ra kết quả dư nhiều quá khi tìm kiếm đúng từ khoá "xạ" và "phú" (bài 26 và 33). Ngoài ra nếu lọc nhanh hoặc rất nhanh mà gõ chậm hiển thị thì không bù được với nhau. Tôi có ví dụ gõ liên tiếp 4 phím p, h, u, 1 để cho ra "phú", thì 1 giây sau 3 ký tự của chữ "phú" mới nhảy ra cùng lúc. Hoặc gõ "ph" xem kết quả, sau đó gõ thêm "ú" cũng phải chờ.
Cái này thì đúng rồi. Code đeo huy hiệu "Lọc nhanh" mà mỗi lần gõ phải ngáp mấy cái mới có kết quả thì không được rồi. :D
 
Upvote 0
Code bạn hay quá, mình test thử code thấy tốc độ nhanh hơn (bạn xem thử cách mình so sánh tốc độ vậy có đúng không).
- Theo mình thì khi dùng sự kiện change với dữ liệu lớn thì luôn có độ trễ khi gõ (với cá nhân mỗi người tốc độ gõ khác nhau, ai mà gõ nhanh thì sẽ thấy chữ thường xuất hiện sau 1 lúc gõ) vì vậy khi so sánh mình tạm bỏ qua cách gõ trực tiếp vào combobox mà mình dùng tạm 1 ô Textbox thay thế và dùng vòng for lấy từng ký tự dán vào ô combobox (không hiểu sao cách của bạn copy dán vào không lọc được).
- Mình thấy tốc độ rõ rệt nhanh hơn ở ký tự thứ 3 (còn 2 ký tự nhiều khi cách lọc mới của bạn vẫn chậm hơn)
- Mà khi tìm kiếm từ khóa trong đầu mỗi người đã có từ đó rồi nên cá nhân mình thường dùng sự kiện afterupdate (sau khi gõ xong mới lọc).
- LoaiDauUni cái funtion này mình thấy đưa vào khi lọc nó chậm hơn, chắc không cần thiết khi so sánh nên bỏ ra.
- Kiến thức mình còn hạn hẹp nên chỉ thấy được vậy thôi, có gì không đúng bạn bỏ qua.
 

File đính kèm

  • Combobox_2.JPG
    Combobox_2.JPG
    53.6 KB · Đọc: 26
  • Combobox_3.JPG
    Combobox_3.JPG
    48.4 KB · Đọc: 26
  • Test ListBox tim kiem nhanh.xlsm
    1.1 MB · Đọc: 28
Upvote 0
Code bạn hay quá, mình test thử code thấy tốc độ nhanh hơn (bạn xem thử cách mình so sánh tốc độ vậy có đúng không).
- Theo mình thì khi dùng sự kiện change với dữ liệu lớn thì luôn có độ trễ khi gõ (với cá nhân mỗi người tốc độ gõ khác nhau, ai mà gõ nhanh thì sẽ thấy chữ thường xuất hiện sau 1 lúc gõ) vì vậy khi so sánh mình tạm bỏ qua cách gõ trực tiếp vào combobox mà mình dùng tạm 1 ô Textbox thay thế và dùng vòng for lấy từng ký tự dán vào ô combobox (không hiểu sao cách của bạn copy dán vào không lọc được).
- Mình thấy tốc độ rõ rệt nhanh hơn ở ký tự thứ 3 (còn 2 ký tự nhiều khi cách lọc mới của bạn vẫn chậm hơn)
- Mà khi tìm kiếm từ khóa trong đầu mỗi người đã có từ đó rồi nên cá nhân mình thường dùng sự kiện afterupdate (sau khi gõ xong mới lọc).
- LoaiDauUni cái funtion này mình thấy đưa vào khi lọc nó chậm hơn, chắc không cần thiết khi so sánh nên bỏ ra.
- Kiến thức mình còn hạn hẹp nên chỉ thấy được vậy thôi, có gì không đúng bạn bỏ qua.
Thật ra lý do chậm cũng không phải do thuật toán mà do mình lồng thêm hàm LoaiDauUni cho những vấn đề gõ mà không cần bỏ dấu tiếng Việt, nếu phần đông không thích điều này thì mình cập nhật thêm phiên bản không có hàm đó. Chắc chắn sẽ nhanh hơn từ ký tự thứ 2 của bất kỳ code nào. Code của mình chuyên về gõ từ khóa, nên copy paste hoặc chen giữa chuỗi không khả thi, có lẽ mình sẽ thêm một bước lọc Before/AfterUpdate nữa mới trọn vẹn chăng?
 
Upvote 0
hình như chậm là do nó ko biết bỏ qua khi nhấn phím tiếp theo ,
ví dụ nhấn a b c liên tục , thì nó tìm xong trường hợp a , rùi lại tìm đến trường hợp ab , rùi đến trường hợp abc
mình làm sao đó khi nó đang tìm trường hợp a được nửa chừng , tự nhiên nó thấy đã nhập xong abc rùi thì không cần xử lý trường hợp tìm a , ab nữa , bỏ qua và chỉ tìm tiếp abc sau cùng thôi thì cảm giác nhập vẫn mượt hơn ,

nữa là kiểu tìm kiếm tuần tự có vẻ làm chậm chương trình tí , mình cũng nghĩ thử tìm cách chuyển qua kiểu tìm kiếm nhị phân thì có vẻ tăng tốc độ hơn , mà điều kiện là tìm chuỗi con trong chuỗi thì cũng hơi đuối ^^
 
Upvote 0
hình như chậm là do nó ko biết bỏ qua khi nhấn phím tiếp theo ,
ví dụ nhấn a b c liên tục , thì nó tìm xong trường hợp a , rùi lại tìm đến trường hợp ab , rùi đến trường hợp abc
mình làm sao đó khi nó đang tìm trường hợp a được nửa chừng , tự nhiên nó thấy đã nhập xong abc rùi thì không cần xử lý trường hợp tìm a , ab nữa , bỏ qua và chỉ tìm tiếp abc sau cùng thôi thì cảm giác nhập vẫn mượt hơn ,

nữa là kiểu tìm kiếm tuần tự có vẻ làm chậm chương trình tí , mình cũng nghĩ thử tìm cách chuyển qua kiểu tìm kiếm nhị phân thì có vẻ tăng tốc độ hơn , mà điều kiện là tìm chuỗi con trong chuỗi thì cũng hơi đuối ^^
Bạn cứ tìm giải pháp tốt hơn, mình luôn trân trọng sự sáng tạo trong CODE, chứ đã rất lâu rồi người ta cứ dậm chân tại chỗ, "lối cũ ta về" chứ khống tìm ra con đường mới dù nó chông gai, dù nó lạ lùng. Bạn cứ thử phát triển cái mới nhé.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn cứ tìm giải pháp tốt hơn, mình luôn trân trọng sự sáng tạo trong CODE, chứ đã rất lâu rồi người ta cứ dậm chân tại chỗ, "lối cũ ta về" chứ khống tìm ra con đường mới dù nó chông gai, dù nó lạ lùng. Bạn cứ thử phát triển cái mới nhé.
Thế bạn đã test bài #8 của tôi chưa? Bạn có thể bật mí là khi gõ tìm kiếm bạn có phải đợi lâu không? Đơi khoảng bao nhiêu?

Tôi thấy lạ là rất nhiều người góp ý trong chủ đề này nhưng không một ai nói rõ: code ở bài này bài này chạy rất chậm. Mỗi khi gõ ký tự là phải chờ khoảng bằng này bằng này. Nhiều người còn không đọc kỹ, trong bài của mình tôi chỉ trích cách tìm "gần đúng", kiểu nhập "a" mà tìm cả "a" với dấu. Thế rồi người ta chụp màn hình tập tin của tôi và trách là nó không tìm cả "a" có dấu. Chịu, bó tay không hiểu ý người ta thế nào nữa. Mà một khia cạnh của chủ đề này là tốc độ. Vì tìm thì ai cũng biết cách rồi. Chỉ là tìm cách tìm nhanh thôi. Vậy tại sao không chỉ thẳng mặt, gọi thẳng tên: "Code trong bài này ... chạy rất chậm. Cụ thể là ..."
 
Upvote 0
Thế bạn đã test bài #8 của tôi chưa? Bạn có thể bật mí là khi gõ tìm kiếm bạn có phải đợi lâu không? Đơi khoảng bao nhiêu?

Tôi thấy lạ là rất nhiều người góp ý trong chủ đề này nhưng không một ai nói rõ: code ở bài này bài này chạy rất chậm. Mỗi khi gõ ký tự là phải chờ khoảng bằng này bằng này. Nhiều người còn không đọc kỹ, trong bài của mình tôi chỉ trích cách tìm "gần đúng", kiểu nhập "a" mà tìm cả "a" với dấu. Thế rồi người ta chụp màn hình tập tin của tôi và trách là nó không tìm cả "a" có dấu. Chịu, bó tay không hiểu ý người ta thế nào nữa. Mà một khia cạnh của chủ đề này là tốc độ. Vì tìm thì ai cũng biết cách rồi. Chỉ là tìm cách tìm nhanh thôi. Vậy tại sao không chỉ thẳng mặt, gọi thẳng tên: "Code trong bài này ... chạy rất chậm. Cụ thể là ..."
Thật ra thuật toán mới nhanh ở chỗ này:
- Lấy mảng gốc để lọc ký tự đầu tiên, lấy mảng vừa lọc để lọc cho ký tự thứ 2 và cứ như thế đến n ký tự. Suy ra nó chỉ chậm khi lọc ở ký tự đầu tiên.
- Thuật toán lọc trước đây sẽ dùng đến 2 vòng lặp, vòng duyệt đúng điều kiện để "GetRows" và vòng lặp thứ 2 là từ GetRows để đưa kết quả lọc chính thức. Còn thuật toán của em lợi dụng lấy mảng "ngược" từ thuộc tính Column của ComboBox để lọc và Resize "độ dài" của cột bằng Redim Preserve để lấy kết quả ngay. Suy ra nó sẽ nhanh hơn một vòng lặp.
Từ đó sẽ biết nó nhanh hơn những kiểu lọc trước đây.

Vì sao chậm?
- Do "tài lanh" khuyến mãi thêm hàm LoaiDauUni nên mỗi Item nó đều loại dấu vì thế sẽ tốn thời gian
- Dùng thuộc tính Clear thay vì Add list bằng một mảng rỗng.
- Dùng mảng Private để lưu mảng tạm.

Hạn chế:
- Chỉ được gõ hoặc xóa tại ký tự cuối cùng
- Không cho copy paste.

Tổng hơp lại tất cả các bài góp ý, em cho rằng thuật toán có sự bức phá về cách nghĩ cách làm, tuy nhiên cần phải xét đến nhiều trường hợp để sau này cải tiến cho nó hoàn thiện hơn.

Cuối cùng là CÁM ƠN tất cả các thành viên đặc biệt là Thầy batman1 đã góp ý cũng như động viên em tiếp tục cải thiện những điều mới mẽ.
Trân trọng.
 
Upvote 0
Thật ra thuật toán mới nhanh ở chỗ này:
Bạn đọc kỹ lại đi. Tôi không hỏi về code của bạn. Tôi hỏi bạn có test code bài #8 của tôi không. Code chạy nhanh hay chậm, nếu chậm thì vd. gõ ký tự đầu tiên thì chờ khoảng bao nhiêu mới có kết quả. Thế thôi.
 
Upvote 0
Bạn đọc kỹ lại đi. Tôi không hỏi về code của bạn. Tôi hỏi bạn có test code bài #8 của tôi không. Code chạy nhanh hay chậm, nếu chậm thì vd. gõ ký tự đầu tiên thì chờ khoảng bao nhiêu mới có kết quả. Thế thôi.
Code chạy nhanh, nhưng để em không dùng hàm Loại dấu, nếu lấy ít nhất tổng thời gian của 3 ký tự (gõ mỗi lần đo mỗi lần) em tin rằng code của em sẽ nhanh hơn đấy! Em sẽ dùng TextBox và ListBox như thầy để chứng minh.
 
Upvote 0
Góp vui chút về cái lọc này.
Mã:
Dim rst As Object
Private Sub cbxPhuongXa_Change()
    Dim arr As Variant
    With cbxPhuongXa
        If .Text = "" Then
            rst.Filter = 0
        Else
            rst.Filter = "[" & Sheet2.Range("A1") & "] Like '*" & .Text & "*'"
        End If
        If rst.EOF Then
            .Clear
        Else
            arr = rst.getrows()
            .Column = arr
            .DropDown
        End If
    End With
End Sub

Private Sub UserForm_Initialize()
    Set rst = CreateObject("ADODB.Recordset")
    Dim objXML As Object
    Set objXML = CreateObject("MSXML2.DOMDocument")
    objXML.LoadXML Sheet2.Range("A1:A111621").Value(12)
    rst.Open objXML
End Sub
 

File đính kèm

  • FilterTest-HTN.xlsm
    1.1 MB · Đọc: 65
Upvote 0
Góp vui chút về cái lọc này.
Mã:
Dim rst As Object
Private Sub cbxPhuongXa_Change()
    Dim arr As Variant
    With cbxPhuongXa
        If .Text = "" Then
            rst.Filter = 0
        Else
            rst.Filter = "[" & Sheet2.Range("A1") & "] Like '*" & .Text & "*'"
        End If
        If rst.EOF Then
            .Clear
        Else
            arr = rst.getrows()
            .Column = arr
            .DropDown
        End If
    End With
End Sub

Private Sub UserForm_Initialize()
    Set rst = CreateObject("ADODB.Recordset")
    Dim objXML As Object
    Set objXML = CreateObject("MSXML2.DOMDocument")
    objXML.LoadXML Sheet2.Range("A1:A111621").Value(12)
    rst.Open objXML
End Sub
Nhanh lắm em ơi, thật tuyệt vời. Anh thấy cần cải tiến xíu xiu cho nhanh hơn nhé.
Anh thấy cái này nên cho nó trực tiếp:
arr = rst.getrows()
.Column = arr

thành:
.Column = rst.getrows()

Như vậy nó đỡ mất 2 lần gán dữ liệu.

Và thay .Clear

thành:
.List = arr
.RemoveItem 0

Với arr được khai báo: Dim arr(0 To 0, 0 To 0)
Kinh nghiệm cho thấy Clear sẽ chạy chậm hơn gán một mảng rỗng.

Code:
PHP:
Private Sub cbxPhuongXa_Change()
    Dim arr(0 To 0, 0 To 0)
    With cbxPhuongXa
        If .Text = "" Then
            rst.Filter = 0
        Else
            rst.Filter = "[" & Sheet2.Range("A1") & "] Like '*" & .Text & "*'"
        End If
        If rst.EOF Then
            .List = arr
            .RemoveItem 0
        Else
            .Column = rst.GetRows()
            .DropDown
        End If
    End With
End Sub
 
Upvote 0
Không biết máy các bạn sao chứ trên laptop tôi gõ từ khoá thấy có độ trễ khi hiển thị từ khoá nhiều quá, cảm thấy không trơn tru khi gõ, cảm giác không thoải mái cho lắm. Không nói về tốc độ dữ liệu trả về. Của bác batman1 thì hiển thị sau khi gõ nhanh hơn và load form lên cũng nhanh.



 
Upvote 0
Không biết máy các bạn sao chứ trên laptop tôi gõ từ khoá thấy có độ trễ khi hiển thị từ khoá nhiều quá, cảm thấy không trơn tru khi gõ, cảm giác không thoải mái cho lắm. Không nói về tốc độ dữ liệu trả về. Của bác batman1 thì hiển thị sau khi gõ nhanh hơn và load form lên cũng nhanh.



Bạn đang nói cái code của bài #54 phải không? Code này là của bạn Hai Lúa Miền Tây. Riêng với máy mình đúng là load form hơi chậm, nhưng gõ rất bình thường.
 
Upvote 0
Upvote 0
Bạn đọc kỹ lại đi. Tôi không hỏi về code của bạn. Tôi hỏi bạn có test code bài #8 của tôi không. Code chạy nhanh hay chậm, nếu chậm thì vd. gõ ký tự đầu tiên thì chờ khoảng bao nhiêu mới có kết quả. Thế thôi.
Code chạy nhanh, nhưng để em không dùng hàm Loại dấu, nếu lấy ít nhất tổng thời gian của 3 ký tự (gõ mỗi lần đo mỗi lần) em tin rằng code của em sẽ nhanh hơn đấy! Em sẽ dùng TextBox và ListBox như thầy để chứng minh.
Sau khi không dùng hàm LoaiDauUni và sử dụng trên TextBox + ListBox để so sánh thời gian, test trên 2 chữ: Phú và Xã, kết quả thế này:

1631164123938.png

Rút ra kết luận, vòng lặp chạy bao nhiêu Item không quá mất thời gian, chỉ mất thời gian nó tìm được bao nhiêu mục, càng tìm nhiều nó càng chạy chậm.
 

File đính kèm

  • FilterTest-HTN-Time.xlsm
    1.1 MB · Đọc: 40
Lần chỉnh sửa cuối:
Upvote 0
Sau khi không dùng hàm LoaiDauUni và sử dụng trên TextBox + ListBox để so sánh thời gian, test trên 2 chữ: Phú và Xã, kết quả thế này:
Rút ra kết luận, vòng lặp chạy bao nhiêu Item không quá mất thời gian, chỉ mất thời gian nó tìm được bao nhiêu mục, càng tìm nhiều nó càng chạy chậm.
Tôi đã viết cho bạn ở bài #8 chả nhẽ bạn không hiểu. Ý tưởng lọc từ mảng gần nhất chứ không từ mảng gốc không phải bây giờ bạn mới là người nghĩ ra. Nhiều người cũng từng có ý tưởng đó nhưng do nó không cho phép tìm kiếm theo cách tùy ý nên nhiều người không muốn dùng nó. Thế thôi. Còn chuyện vd. như thay Clear bằng load mảng rỗng 1 phần tử và Remove phần tử đó là do tôi đưa ra chứ không phải bạn.
Tôi cũng viết rõ là tôi dùng thuật toán mà bạn gọi là thuật toán lọc hiện hành, lấy mảng gốc để lọc. Không phải là tôi không nhìn thấy ưu điểm của lọc từ mảng gần nhất, chỉ là tôi không dùng vì nó không cho phép tìm kiếm tùy ý. Cũng chính tôi chỉ ra rằng FOR với hàng trăm nghìn vòng lặp chả là cái đinh gì, cái khác mới là "phanh hãm" chính, kiểu như dùng Clear.
 
Upvote 0
Tôi đã viết cho bạn ở bài #8 chả nhẽ bạn không hiểu. Ý tưởng lọc từ mảng gần nhất chứ không từ mảng gốc không phải bây giờ bạn mới là người nghĩ ra. Nhiều người cũng từng có ý tưởng đó nhưng do nó không cho phép tìm kiếm theo cách tùy ý nên nhiều người không muốn dùng nó. Thế thôi. Còn chuyện vd. như thay Clear bằng load mảng rỗng 1 phần tử và Remove phần tử đó là do tôi đưa ra chứ không phải bạn.
Tôi cũng viết rõ là tôi dùng thuật toán mà bạn gọi là thuật toán lọc hiện hành, lấy mảng gốc để lọc. Không phải là tôi không nhìn thấy ưu điểm của lọc từ mảng gần nhất, chỉ là tôi không dùng vì nó không cho phép tìm kiếm tùy ý. Cũng chính tôi chỉ ra rằng FOR với hàng trăm nghìn vòng lặp chả là cái đinh gì, cái khác mới là "phanh hãm" chính, kiểu như dùng Clear.
Cái vụ Clear hay thay bằng mảng rỗng chỉ xảy ra khi và chỉ khi không lọc được gì, điều này không ảnh hưởng gì đến thời gian lọc 3 ký tự hay nhiều hơn thế trên code của em. Nhưng qua đây em cũng trải nghiệm ra được nhiều điều thú vị để tiếp tục khám phá ra những điều mới mẻ hơn nữa.
Cám ơn vì tất cả.
 
Upvote 0
Web KT
Back
Top Bottom