[TẶNG] Thuật toán lọc tìm kiếm mới trên ComboBox. (1 người xem)

Liên hệ QC

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

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,725
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

Lần chỉnh sửa cuối:
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
Kỹ thuật lọc sáng tạo và rất hay, xem lại vài vấn đề code sẽ hoàn hảo hơn
Kết quả lọc còn trùng, ví dụ nhập "xa phu cha" hoặc "xa phu chau"
Tốc độ code còn chậm do hàm LoaiDauUni gọi quá nhiều lần xử lý cho cùng 1 dữ liệu, và ObjDict được tạo nhiều lần không cần thiết
Khi số ký tự nhập nhiều, mãng lưu trữ kết quả priArrPhuongXa phình to tốn bộ nhớ
Form thích hợp cho nhập từ bàn phím, nếu chọn 1 dòng dữ liệu từ danh sách sau đó xóa bớt vài ký tự code không lọc được
 
Upvote 0
Kỹ thuật lọc sáng tạo và rất hay, xem lại vài vấn đề code sẽ hoàn hảo hơn
Kết quả lọc còn trùng, ví dụ nhập "xa phu cha" hoặc "xa phu chau"
Tốc độ code còn chậm do hàm LoaiDauUni gọi quá nhiều lần xử lý cho cùng 1 dữ liệu, và ObjDict được tạo nhiều lần không cần thiết
Khi số ký tự nhập nhiều, mãng lưu trữ kết quả priArrPhuongXa phình to tốn bộ nhớ
Form thích hợp cho nhập từ bàn phím, nếu chọn 1 dòng dữ liệu từ danh sách sau đó xóa bớt vài ký tự code không lọc được
Nói về hàm LoaiDauUni trước đi.
Tôi đã tối ưu cho nó rất kỹ. Cái Dic nó chỉ được tạo ra đúng một lần đầu tiên chạy hàm, còn lại nó đã được lưu vào bộ nhớ tạm, cần tra "từ điển" là nó ra, không cần phải tạo lại. Bạn nên tham khảo kiểu biến được khai báo bằng Static.
 
Upvote 0
Nói về hàm LoaiDauUni trước đi.
Tôi đã tối ưu cho nó rất kỹ. Cái Dic nó chỉ được tạo ra đúng một lần đầu tiên chạy hàm, còn lại nó đã được lưu vào bộ nhớ tạm, cần tra "từ điển" là nó ra, không cần phải tạo lại. Bạn nên tham khảo kiểu biến được khai báo bằng Static.
Mình không nhầm về dic :)
Có cách nào 1 dữ liệu chỉ cần chạy LoaiDauUni 1 lần không
 
Upvote 0
Mình không nhầm về dic :)
Có cách nào 1 dữ liệu chỉ cần chạy LoaiDauUni 1 lần không
Cơ bản là nó cũng làm cho code chạy chậm tí xíu, nhưng nó đã nhanh hơn những hàm loại dấu Uni trước đây rồi đó bởi vì nó chỉ tốn vòng lặp đầu tiên để lưu trữ key, còn những lần sau nó chỉ xuất item chứ không làm gì nữa.

Bạn có thể thử dùng MsgBox và đặt trong If Not blnInitial Then để kiểm tra sẽ thấy MsgBox chạy đúng 1 lần duy nhất.
 
Upvote 0
Cơ bản là nó cũng làm cho code chạy chậm tí xíu, nhưng nó đã nhanh hơn những hàm loại dấu Uni trước đây rồi đó bởi vì nó chỉ tốn vòng lặp đầu tiên để lưu trữ key, còn những lần sau nó chỉ xuất item chứ không làm gì nữa.

Bạn có thể thử dùng MsgBox và đặt trong If Not blnInitial Then để kiểm tra sẽ thấy MsgBox chạy đúng 1 lần duy nhất.
Mã:
    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
strColOne = UCase(LoaiDauUni(priArrPhuongXa(c)(0, r)))
Mỗi lần nhập thêm ký tự lệnh trên sẽ chạy lại dữ liệu đã xử lý
 
Upvote 0
Nhưng tôi thắc mắc rằng khi gõ từ khóa tìm kiếm chẳng may gõ nhầm xóa đi gõ lại thì kết quả sẽ khác vì mảng gốc đã loại bỏ mất rồi
 
Upvote 0
Code này không dùng được trong trường hợp tổng quát. Vì muốn dùng thì phải nhập dữ liệu theo đúng trình tự mà bạn bắt buộc. Vd. tôi nhập "sương" và có loạt kết quả chứa "sương". Lúc này tôi mới nhận ra lỗi chính tả, phải là "xương". Tôi muốn click trước hoặc sau "s" rồi dùng Delete hoặc Backspace để xóa "s" thì không được. Trỏ văn bản cứ nhẩy về cuối khi tôi click ở giữa từ, nên tôi phải nhấn phím mũi tên trái 4 lần. Sau khi xóa "s" tôi nhấn "x" để có "xương" thì không có kết quả nào dù dữ liệu có "xương". Hoặc lẽ ra phải gõ "Phong" thì do nhấn phím hơi lâu nên thành "Phoong". Bây giờ có xóa 1 "o" thì cũng không có kết quả dù dữ liệu có "Phong". Nhớ danh sách cuối để lọc từ đó thì nhiều người cũng nghĩ tới rồi chứ không phải là điều mới, nhưng nó đòi hỏi nhập và chỉnh sửa theo một cách nhất định. Ngoài ra nếu tôi gõ "phu" là tôi muốn tìm "phu" chứ không phải cả "phù", "phủ", "phũ", "phú", "phụ".

Tôi viết nhanh một code mà bạn gọi là thuật toán lọc hiện hành, lấy mảng gốc để lọc. Bạn thử kiểm tra tốc độ xem. Cứ gõ ký tự 1, rồi 2, ...

Đố bạn biết chỗ nhanh ở đâu, cái gì nó làm code nhanh hẳn. :D
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Tác giả bài đăng thân mến, Mình thấy hay & áp dụng thử thấy OK,
Bạn cần xem xét thêm trường hợp:
Mình muốn tìm 'Xã Phú Tài'; (Thực tế không có tên xã này)
Mình gõ đến chuỗi 'Xã Phú T" thì ra danh sách cỡ 5 đến 60 địa danh có từ cuối là Thị, túc, thành, tiến, . . . . .
Đến đây mình gõ thêm ký tự 'a' nó đưa ra các địa danh có đuôi là Tân & Tâm (không ít)
Mình bỏ dấu huyền trên chữ 'a' thì danh sách trong ComboBox không suy xuyễn;
Mình muốn trường hợp này hiện trong ComboBox là 'Nothing', được không?

Chú thích: Ngã 3 Phú Tài ở Bình Định chắc là thị trấn hay gì gì khác chăng?
 
Lần chỉnh sửa cuối:
Upvote 0
Tác giả bài đăng thân mến, Mình thấy hay & áp dụng thử thấy OK,
Bạn cần xem xét thêm trường hợp:
Mình muốn tìm 'Xã Phú Tài'; (Thực tế không có tên xã này)
Mình gõ đến chuỗi 'Xã Phú T" thì ra danh sách cỡ 5 đến 60 địa danh có từ cuối là Thị, túc, thành, tiến, . . . . .
Đến đây mình gõ thêm ký tự 'a' nó đưa ra các địa danh có đuôi là Tân & Tâm (không ít)
Mình bỏ dấu huyền trên chữ 'a' thì danh sách trong ComboBox không suy xuyễn;
Mình muốn trường hợp này hiện trong ComboBox là 'Nothing', được không?

Chú thích: Ngã 3 Phú Tài ở Bình Định chắc là thị trấn hay gì gì khác chăng?
Thủ phạm là LoaiDauUni. Vì thế bạn gõ "a" mà nó tìm cả "a" có thêm dấu như bài #8 tôi đã viết ("a" có thêm dấu đi qua cái máy chém LoaiDauUni nó loại hết dấu chỉ còn "a" nên khớp với "a" đã gõ)
 
Upvote 0
Để tôi mô tả sơ về thuật toán này cho anh em rõ.

1) Vì sao tôi dùng hàm LoaiDauUni? Để khi tìm kiếm không cần gọi dấu nó cũng gợi ý cho tất cả các trường hợp liên quan đến nguyên âm hoặc phụ âm (Đ, đ) có chứa dấu hoặc không. Chính vì điều này nó sẽ liệt kê những thứ không cần thiết (nhưng cũng một phần do dữ liệu trùng đến 10 lần nên những dữ liệu na ná nó sẽ nhân lên 10 lần vì thế nó hơi rối mắt). Tuy nhiên, hãy nhìn Google, mình gõ không dấu/có dấu nó cũng liệt kê tất cả các trường hợp có dấu hoặc không dấu.

2) Vì sao nó nhanh hơn? Bởi vì nó lấy dữ liệu liền kề để lọc cho ký tự sau nên bỏ qua các công đoạn lọc trước.

3) Khi nó lưu mảng tạm trước đó, nếu ta gõ sai ký tự vừa gõ ta back lại ký tự đó thì nó trả lại mảng ta vừa lọc mà không phải lọc lại lần nữa. Và nếu gõ thêm ký tự mới nó vẫn sẽ lấy mảng liền kề để lọc nên vẫn sẽ rất nhanh.

4) Cũng chính vì điều này nên nó có một hạn chế là việc cho sửa chen ngang, nó chỉ cho ta sửa xóa chỉ 1 ký tự được xếp cuối cùng vì thế tôi mới dùng sự kiện MouseUp để ngăn đặt con trỏ vào các vị trí trước ký tự cuối. Nói chung cái này tôi nghĩ cũng không làm khó người gõ cho lắm (hoặc do tôi gõ mười ngón không nhìn bàn phím mà chỉ nhìn màn hình nên tôi phát hiện ngay lỗi mình gõ nên chủ quan chăng?!).

5) Và có thể còn nhiều khuyết điểm khác, nhưng qua bài này tôi tin rằng sẽ có nhiều cải tiến cho những code lỗi thời nhằm khắc phục giới hạn tốc độ.

Cám ơn mọi người đã chỉ ra những khiếm khuyết (đã lường trước và chưa lường trước) trong bài này.
 
Upvote 0
Để tôi mô tả sơ về thuật toán này cho anh em rõ.

1) Vì sao tôi dùng hàm LoaiDauUni? Để khi tìm kiếm không cần gọi dấu nó cũng gợi ý cho tất cả các trường hợp liên quan đến nguyên âm hoặc phụ âm (Đ, đ) có chứa dấu hoặc không. Chính vì điều này nó sẽ liệt kê những thứ không cần thiết (nhưng cũng một phần do dữ liệu trùng đến 10 lần nên những dữ liệu na ná nó sẽ nhân lên 10 lần vì thế nó hơi rối mắt). Tuy nhiên, hãy nhìn Google, mình gõ không dấu/có dấu nó cũng liệt kê tất cả các trường hợp có dấu hoặc không dấu.

2) Vì sao nó nhanh hơn? Bởi vì nó lấy dữ liệu liền kề để lọc cho ký tự sau nên bỏ qua các công đoạn lọc trước.

3) Khi nó lưu mảng tạm trước đó, nếu ta gõ sai ký tự vừa gõ ta back lại ký tự đó thì nó trả lại mảng ta vừa lọc mà không phải lọc lại lần nữa. Và nếu gõ thêm ký tự mới nó vẫn sẽ lấy mảng liền kề để lọc nên vẫn sẽ rất nhanh.

4) Cũng chính vì điều này nên nó có một hạn chế là việc cho sửa chen ngang, nó chỉ cho ta sửa xóa chỉ 1 ký tự được xếp cuối cùng vì thế tôi mới dùng sự kiện MouseUp để ngăn đặt con trỏ vào các vị trí trước ký tự cuối. Nói chung cái này tôi nghĩ cũng không làm khó người gõ cho lắm (hoặc do tôi gõ mười ngón không nhìn bàn phím mà chỉ nhìn màn hình nên tôi phát hiện ngay lỗi mình gõ nên chủ quan chăng?!).

5) Và có thể còn nhiều khuyết điểm khác, nhưng qua bài này tôi tin rằng sẽ có nhiều cải tiến cho những code lỗi thời nhằm khắc phục giới hạn tốc độ.

Cám ơn mọi người đã chỉ ra những khiếm khuyết (đã lường trước và chưa lường trước) trong bài này.
Tập tin của tôi và của bạn cùng có dữ liệu như nhau. Bạn đã thử gõ, vd. "p", rồi "h" xem tốc độ trong 2 tập tin chưa?
 
Upvote 0
Đố bạn biết chỗ nhanh ở đâu, cái gì nó làm code nhanh hẳn. :D
Để em trả lời bài này:
1) Nó không dùng hàm loại dấu,
2) Nó không cần xét chữ hoa thường (Option Compare Text), nên không dùng hàm UCase,
3) Ad một mảng trắng sẽ nhanh hơn phương thức Clear.

Và em cũng thắc mắc tại sao thêm 2 dòng rỗng ở dưới cho dữ liệu để rồi lại trừ đi 2?
 
Lần chỉnh sửa cuối:
Upvote 0
Thế bạn thử bỏ + 2 và xóa hết dữ liệu chỉ để tiêu đề trong A1 xem sao nhé. Mà + 2 nhưng sau đó không xét 2 dòng cuối thì "hòa cả làng" mà. Hoặc chỉ + 1 rồi chạy xem sao nhé.

Loại dấu và UCase cũng chưa chắc là thủ phạm chính.

Bạn hãy chạy code của tôi. Sau đó thay
Mã:
ReDim result(1 To 1, 1 To 1)
    ListBox1.List = result
    ListBox1.RemoveItem 0

bằng

Mã:
ListBox1.Clear

rồi lại chạy và so sánh nhé. Cả 2 đều có FOR với 111620 vòng mà code 1 nhanh hơn nhiều. Vậy FOR cũng chả là cái đinh gì. Thủ phạm nhìn rất ngây thơ, vô tội ...
 
Upvote 0
Thế bạn thử bỏ + 2 và xóa hết dữ liệu chỉ để tiêu đề trong A1 xem sao nhé. Mà + 2 nhưng sau đó không xét 2 dòng cuối thì "hòa cả làng" mà. Hoặc chỉ + 1 rồi chạy xem sao nhé.

Loại dấu và UCase cũng chưa chắc là thủ phạm chính.

Bạn hãy chạy code của tôi. Sau đó thay
Mã:
ReDim result(1 To 1, 1 To 1)
    ListBox1.List = result
    ListBox1.RemoveItem 0

bằng

Mã:
ListBox1.Clear

rồi lại chạy và so sánh nhé. Cả 2 đều có FOR với 111620 vòng mà code 1 nhanh hơn nhiều. Vậy FOR cũng chả là cái đinh gì. Thủ phạm nhìn rất ngây thơ, vô tội ...
Ở bài #13 em có thêm vô mục 3 đúng với cái vụ Clear này.

Vấn đề này bẫy lỗi dữ liệu "rỗng" cho chuẩn thì em cũng sẽ làm như sau:

1) Sẽ không add dữ liệu nếu e < 2

2) ActiveSheet.AutoFilterMode = False
 
Upvote 0
Ở bài #13 em có thêm vô mục 3 đúng với cái vụ Clear này.

Vấn đề này bẫy lỗi dữ liệu "rỗng" cho chuẩn thì em cũng sẽ làm như sau:

1) Sẽ không add dữ liệu nếu e < 2

2) ActiveSheet.AutoFilterMode = False
Trong rất nhiều sub nếu không có dữ liệu thì tôi dùng Exit Sub. Nhưng chuyện +2, +1 thì dĩ nhiên phải có. Vì nếu vẫn code ấy mà tôi không cộng gì trong khi A2 có dữ liệu, tức không RỖNG, thì vẫn sẽ có lỗi. Vậy trong trường hợp này phải +1. Mà đã +1 thì làm luôn +2 để phục vụ nốt trường hợp cả A2 cũng rỗng.
 
Upvote 0
Trong rất nhiều sub nếu không có dữ liệu thì tôi dùng Exit Sub. Nhưng chuyện +2, +1 thì dĩ nhiên phải có. Vì nếu vẫn code ấy mà tôi không cộng gì trong khi A2 có dữ liệu, tức không RỖNG, thì vẫn sẽ có lỗi. Vậy trong trường hợp này phải +1. Mà đã +1 thì làm luôn +2 để phục vụ nốt trường hợp cả A2 cũng rỗng.
Nhưng xét cho cùng, nếu em áp dụng code của em bỏ qua hàm Loại dấu thì từ ký tự thứ 2 trở đi vẫn nhanh hơn vì số vòng lặp được rút ngắn đáng kể so với dữ liệu ban đầu.
 
Upvote 0
Code này không dùng được trong trường hợp tổng quát. Vì muốn dùng thì phải nhập dữ liệu theo đúng trình tự mà bạn bắt buộc. Vd. tôi nhập "sương" và có loạt kết quả chứa "sương". Lúc này tôi mới nhận ra lỗi chính tả, phải là "xương". Tôi muốn click trước hoặc sau "s" rồi dùng Delete hoặc Backspace để xóa "s" thì không được. Trỏ văn bản cứ nhẩy về cuối khi tôi click ở giữa từ, nên tôi phải nhấn phím mũi tên trái 4 lần. Sau khi xóa "s" tôi nhấn "x" để có "xương" thì không có kết quả nào dù dữ liệu có "xương". Hoặc lẽ ra phải gõ "Phong" thì do nhấn phím hơi lâu nên thành "Phoong". Bây giờ có xóa 1 "o" thì cũng không có kết quả dù dữ liệu có "Phong". Nhớ danh sách cuối để lọc từ đó thì nhiều người cũng nghĩ tới rồi chứ không phải là điều mới, nhưng nó đòi hỏi nhập và chỉnh sửa theo một cách nhất định. Ngoài ra nếu tôi gõ "phu" là tôi muốn tìm "phu" chứ không phải cả "phù", "phủ", "phũ", "phú", "phụ".

Tôi viết nhanh một code mà bạn gọi là thuật toán lọc hiện hành, lấy mảng gốc để lọc. Bạn thử kiểm tra tốc độ xem. Cứ gõ ký tự 1, rồi 2, ...

Đố bạn biết chỗ nhanh ở đâu, cái gì nó làm code nhanh hẳn. :D
File này của anh, e nhập chữ Xa xong cách ra nó ra kết quả như hình, rõ ràng là còn rất nhiều xã nữa?

Snag_37ba73e.png
cảm ơn anh.
 
Upvote 0
File này của anh, e nhập chữ Xa xong cách ra nó ra kết quả như hình, rõ ràng là còn rất nhiều xã nữa?

View attachment 265622
cảm ơn anh.
Dĩ nhiên là nó sẽ liệt kê tất cả những chữ liên quan đến xa có dấu và không dấu. Bởi vì nó được Loại dấu nên tất cả đều thành "xa".
Cách search khôn ngoan là chọn các từ khóa không phổ biến (kể cả search google).
 
Upvote 0
Dĩ nhiên là nó sẽ liệt kê tất cả những chữ liên quan đến xa có dấu và không dấu. Bởi vì nó được Loại dấu nên tất cả đều thành "xa".
Cách search khôn ngoan là chọn các từ khóa không phổ biến (kể cả search google).
Tôi chưa thử vì chưa có nhu cầu lọc nhưng theo hình chụp bài 17 thì dù gõ xã hay xa hay bất kỳ cái gì thì list hiện ra cần phải lọc duy nhất. Google đâu có trùng như vậy.
 
Upvote 0
Dĩ nhiên là nó sẽ liệt kê tất cả những chữ liên quan đến xa có dấu và không dấu. Bởi vì nó được Loại dấu nên tất cả đều thành "xa".
Cách search khôn ngoan là chọn các từ khóa không phổ biến (kể cả search google).
Nếu đã nhập "xa" thì kết quả phải đủ là "xa" "xã" "xá" "xạ" "xả" đủ cả chứ anh nhỉ.
 
Upvote 0
Tôi chưa thử vì chưa có nhu cầu lọc nhưng theo hình chụp bài 17 thì dù gõ xã hay xa hay bất kỳ cái gì thì list hiện ra cần phải lọc duy nhất. Google đâu có trùng như vậy.
Chỉ một chữ "xa" thôi, google đã cho ra 726 triệu trang web/page/từ căn cứ vào đâu nói nó không trùng? Từ trang này chia sẻ trang kia, copy trang nọ, nó liệt kê tất tần tật.

1631067390333.png
 
Lần chỉnh sửa cuối:
Upvote 0
Cái vụ tìm "xa" phải ra "xá, xạ..." tuỳ theo thuật tìm kiếm mình muốn như thế nào thì viết thôi, không phải qui định phải tìm kiếm giống Google hay công cụ nào khác. Có người thích gõ "xa" thì chỉ hiện kết quả "*xa*", có người làm biếng gõ tiếng Việt có dấu thì muốn tìm "xa" phải hiện đủ các từ có đủ dấu thanh ("xa họi" thì phải trả về kết quả vừa có dấu vừa không dấu. Sống sao cho vừa lòng nhỉ. :D
Tôi nghĩ cứ theo suy luận thông thường là càng thêm dữ liệu thì càng giới hạn tìm kiếm lại là được rồi.
 
Upvote 0
726 triệu kết quả đi nữa, thì cái list hiện ra (có thể đã sort theo thứ tự nhiều người dùng nhất), chỉ trong khoảng 10 - 20 và chắc chắc không trùng. Xem hình bài 22.
Tôi cũng vừa thử file bài 1. Gõ từ khoá đàng hoàng: Tôi muốn tìm Phú Sơn và tôi gõ "phú", nó ra nào là Phụng, nào là Phương, nào là Phùng, nào là Phượng, ...
Nếu lọc tốt thì chỉ có Phú, Phúc, Phún, Phúng, Phút (nếu có xã tên đó).
Chưa nói lọc có nhanh hay không, hay là rất nhanh, tôi thấy gõ ký tự thứ 2 trở đi, nhất là khi gõ dấu, phải chờ khoảng gần 1 giây mới xuất hiện ký tự vừa gõ.

1631068004288.png
 
Upvote 0
Nếu đã nhập "xa" thì kết quả phải đủ là "xa" "xã" "xá" "xạ" "xả" đủ cả chứ anh nhỉ.
Đúng rồi em, nó liệt kê hết tất cả, nhưng cứ nghĩ đi, tổng số phường và tổng số xã nó ngang nhau, như vậy cho rằng số xã nó là 5 ngàn dòng đi sau đó nhân cho 10 lần vậy là chỉ riêng chữ xã đầu câu thôi thì nó đã ngốn hết 50 ngàn dòng rồi còn gì, như vậy 1 xã nó có ít nhất là 10 dòng chưa kể bên trong nó có chứa các chữ xa có dấu.
Bài đã được tự động gộp:

sao của tôi nó mất đi đâu 1 ít ta :D:D:D

View attachment 265636
Do nó thấy GPE nói về nó quá nó đổi thuật toán xóa ngay những bài trùng hay sao ta? kakaka
 
Upvote 0
Xin các bạn bàn thêm về hướng ứng dụng của việc này vô nhập dữ liệu; (Mà chắc là ứng dụng nhập dữ liệu nhân sụ)
Vấn đề nêu ra là nhập địa danh tỉnh-Huyện-Xã (phường) như thế nào:
Nhập chung vô 1 cột hay nhập 3 cột riêng rẽ?
Nếu nhập chung trong 1 cột thì khó ứng dụng đề cương này, nhỉ?
Còn nếu nhập riêng rẽ 3 cột thì mệt mỏi khi ông nhà nước nhập-tách các xã-huyện hay tỉnh.

Chúc các bạn vui khỏe, trãi 2ua đợt dịch IV này!
 
Upvote 0
Xin các bạn bàn thêm về hướng ứng dụng của việc này vô nhập dữ liệu; (Mà chắc là ứng dụng nhập dữ liệu nhân sụ)
Vấn đề nêu ra là nhập địa danh tỉnh-Huyện-Xã (phường) như thế nào:
Nhập chung vô 1 cột hay nhập 3 cột riêng rẽ?
Nếu nhập chung trong 1 cột thì khó ứng dụng đề cương này, nhỉ?
Còn nếu nhập riêng rẽ 3 cột thì mệt mỏi khi ông nhà nước nhập-tách các xã-huyện hay tỉnh.

Chúc các bạn vui khỏe, trãi 2ua đợt dịch IV này!
Đúng là thuật toán này tuy có nhanh nhưng còn có mặt hạn chế chèn chữ. Tuy nhiên chỉ cần dùng thuộc tính .Column để thay thế cho .List để không phải duyệt thêm 1 vòng lặp nữa là đã thấy nhanh hơn rồ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.
 
Upvote 0
Cái vụ tìm "xa" phải ra "xá, xạ..." tuỳ theo thuật tìm kiếm mình muốn như thế nào thì viết thôi, không phải qui định phải tìm kiếm giống Google hay công cụ nào khác. Có người thích gõ "xa" thì chỉ hiện kết quả "*xa*", có người làm biếng gõ tiếng Việt có dấu thì muốn tìm "xa" phải hiện đủ các từ có đủ dấu thanh ("xa họi" thì phải trả về kết quả vừa có dấu vừa không dấu. Sống sao cho vừa lòng nhỉ. :D
Tôi nghĩ cứ theo suy luận thông thường là càng thêm dữ liệu thì càng giới hạn tìm kiếm lại là được rồi.
em lại thít kiểu này
Capture 2.JPGCapture 1.JPGCapture 3.JPG
 
Upvote 0
Xin các bạn bàn thêm về hướng ứng dụng của việc này vô nhập dữ liệu; (Mà chắc là ứng dụng nhập dữ liệu nhân sụ)
Vấn đề nêu ra là nhập địa danh tỉnh-Huyện-Xã (phường) như thế nào:
Nhập chung vô 1 cột hay nhập 3 cột riêng rẽ?
Nếu nhập chung trong 1 cột thì khó ứng dụng đề cương này, nhỉ?
Còn nếu nhập riêng rẽ 3 cột thì mệt mỏi khi ông nhà nước nhập-tách các xã-huyện hay tỉnh.

Chúc các bạn vui khỏe, trãi 2ua đợt dịch IV này!
Hi bác Sa,
Về ứng dụng trong việc nhập liệu nhanh, chính xác thì trước đây em thấy anh @ndu96081631 đã có làm hàm Filter2DArray. em quay lại ứng dụng về nhập liệu, có thể lọc, sắp xếp theo nhiều tiêu chí. Data nguồn thì đang lấy từ một FIle khác, để tránh việc chỉnh sửa dữ liệu gốc.

 
Lần chỉnh sửa cuối:
Upvote 0
Tôi thấy kết hợp lại cũng có mặt tốt:
- nếu gõ "xa" chữ không dấu: Liệt kê các từ chứa nhóm chữ "xa" không dấu và cả có dấu (đủ 5 dấu, trừ dấu tạo ra từ không có nghĩa hoặc không có trong danh sách)
- nếu gõ có dấu, thì ví dụ trong danh sách phường xã có xã "Xạ Hương" hay "Hương Xạ" gì đó, tôi gõ thêm dấu nặng thành "xạ" thì chỉ liệt kê phường xã có chữ "xạ" mà thôi. xã xả xá gì đó phải loại ra. Nếu tôi tìm "xạ" mà liệt kê ra 50 ngàn chữ "xã" thì coi như tìm kiếm cũng như không. Cũng như ví dụ bài trên tôi nói về "phú", nếu tôi gõ "phú" thì chỉ còn "phú", "Phúc", "Phút" chứ không có phương, phường, phượng gì hết
- Nếu tôi gõ chữ không dấu kèm 1 khoảng trắng ("xa "), nghĩa là tôi dứt khoát chọn không dấu, thì chỉ còn xa, không còn xã xạ xả xá xà gì hết
Và quan trọng là list hiện ra để chọn đã lọc trùng. Về lý thuyết khi đã nói danh sách sẽ rút ngắn khi gõ thêm ký tự thì phải rút ngắn.
 
Upvote 0
Tôi thấy kết hợp lại cũng có mặt tốt:
- nếu gõ "xa" chữ không dấu: Liệt kê các từ chứa nhóm chữ "xa" không dấu và cả có dấu (đủ 5 dấu, trừ dấu tạo ra từ không có nghĩa hoặc không có trong danh sách)
- nếu gõ có dấu, thì ví dụ trong danh sách phường xã có xã "Xạ Hương" hay "Hương Xạ" gì đó, tôi gõ thêm dấu nặng thành "xạ" thì chỉ liệt kê phường xã có chữ "xạ" mà thôi. xã xả xá gì đó phải loại ra. Nếu tôi tìm "xạ" mà liệt kê ra 50 ngàn chữ "xã" thì coi như tìm kiếm cũng như không. Cũng như ví dụ bài trên tôi nói về "phú", nếu tôi gõ "phú" thì chỉ còn "phú", "Phúc", "Phút" chứ không có phương, phường, phượng gì hết
- Nếu tôi gõ chữ không dấu kèm 1 khoảng trắng ("xa "), nghĩa là tôi dứt khoát chọn không dấu, thì chỉ còn xa, không còn xã xạ xả xá xà gì hết
Và quan trọng là list hiện ra để chọn đã lọc trùng. Về lý thuyết khi đã nói danh sách sẽ rút ngắn khi gõ thêm ký tự thì phải rút ngắn.
Cái điều đơn giản hết sức đó tưởng người mới viết code thắc mắc còn coi được. Chỉ cần xóa cái hàm LoaiDauUni ra thì được rồi, vả lại nó còn nhanh hơn rất nhiều.
 
Upvote 0
Cái điều đơn giản hết sức đó tưởng người mới viết code thắc mắc còn coi được. Chỉ cần xóa cái hàm LoaiDauUni ra thì được rồi, vả lại nó còn nhanh hơn rất nhiều.
1. Tiêu đề của chủ đề là "TẶNG" viết hoa, và trong bài viết là xin nhận "góp ý cho những trường hợp làm cho nó hoàn thiện hơn". Tôi thấy những góp ý từ anh @batman1 , đến @Cá ngừ F1, @HieuCD đến tôi, chưa thấy nhận là đúng hay là sai, cũng không nhận để sửa cho hoàn thiện, cả việc gõ 2, 3 ký tự xong phải 1 giây sau mới hiện ra, cũng không thấy "làm cho hoàn thiện hơn".
Cho nên tôi thấy cần phải ghi ra những nhận xét để mọi thành viên biết khi nhận quà TẶNG sẽ được hưởng những gì. Huống hồ tôi đang trả lời ý chung cho cụ thể là bài của @thuyyeu99
2. Nếu xoá hàm đó ra mà xài thì không chắc người nhận quà TẶNG đã biết cách xoá. Nhận xong không xài đúng ý mình thì chắc không nhận.
 
Upvote 0
Hi bác Sa,
Về ứng dụng trong việc nhập liệu nhanh, chính xác thì trước đây em thấy anh @NDU đã có làm hàm Filter2DArray. em quay lại ứng dụng về nhập liệu, có thể lọc, sắp xếp theo nhiều tiêu chí. Data nguồn thì đang lấy từ một FIle khác, để tránh việc chỉnh sửa dữ liệu gốc.

Mình tin cái hàm Filter2DArray này khi sử dụng trên ComboBox hay ListBox thì có thể cải tiến để chạy nhanh hơn và không cần dùng tới Dic để ghim số hàng.
 
Upvote 0
1. Tiêu đề của chủ đề là "TẶNG" viết hoa, và trong bài viết là xin nhận "góp ý cho những trường hợp làm cho nó hoàn thiện hơn". Tôi thấy những góp ý từ anh @batman1 , đến @Cá ngừ F1, @HieuCD đến tôi, chưa thấy nhận là đúng hay là sai, cũng không nhận để sửa cho hoàn thiện, cả việc gõ 2, 3 ký tự xong phải 1 giây sau mới hiện ra, cũng không thấy "làm cho hoàn thiện hơn".
Cho nên tôi thấy cần phải ghi ra những nhận xét để mọi thành viên biết khi nhận quà TẶNG sẽ được hưởng những gì. Huống hồ tôi đang trả lời ý chung cho cụ thể là bài của @thuyyeu99
2. Nếu xoá hàm đó ra mà xài thì không chắc người nhận quà TẶNG đã biết cách xoá. Nhận xong không xài đúng ý mình thì chắc không nhận.
Vâng hihi.
Cái mục đích em nói là khi viết nhằm để người dùng có thể thao tác tìm kiếm thuận tiện nhất và kết quả sát với từ mình tìm kiếm nhất để dễ nhìn nhất.
Cái hình em Post Chữ đồng là 1800 kết quả, chữ đông là 3230 kết quả. Còn cái kia là nó sẽ láy hết dong, đông, đòng.....
Còn về thuật toán em không nhận xét
Bài đã được tự động gộp:

Form này có nhiều tuỳ chọn. Mục tiêu cuối cùng là thiết kế để người dùng có thể thao tác tìm kiếm thuận tiện nhất, ít bối rối nhất là tốt rồi.
Combobox theo em thì có nhiều cái bất tiện và nhìn không đẹp nên em không mặn mà lắm nên em lấy cái form đó làm Combobox luôn
 
Lần chỉnh sửa cuối:
Upvote 0
Combobox theo em thì có nhiều cái bất tiện và nhìn không đẹp nên em không mặn mà lắm nên em lấy cái form đó làm Combobox luôn

Đúng hay đó em. Thiết kế thì không nên bó buộc trong những cái mặc định của ứng dụng. Chẳng hạn như cái MsgBox, đâu nhất thiết phải dùng cái Msgbox của hệ thống, có thể dùng Form làm Msgbox để tuỳ biến được cao hơn, phù hợp với ứng dụng mình đang viết. :)
 
Upvote 0
Tôi chưa thử vì chưa có nhu cầu lọc nhưng theo hình chụp bài 17 thì dù gõ xã hay xa hay bất kỳ cái gì thì list hiện ra cần phải lọc duy nhất. Google đâu có trùng như vậy.
Đâ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.
Muốn lọc duy nhất thì chỉ cần làm 1 lần: lọc duy nhất rồi mới đưa vào mảng gốc.
Bài đã được tự động gộp:

Nếu đã nhập "xa" thì kết quả phải đủ là "xa" "xã" "xá" "xạ" "xả" đủ cả chứ anh nhỉ.
Code tôi viết là tìm đúng. Gõ Xa thì chỉ tìm Xa. Xem các bài của tôi thì thấy tôi chỉ trích kiểu gõ Phu mà lại tìm cả Phù, Phủ, Phũ, Phú, Phụ (bài #8). Không tìm kiểu "gần đúng" là dụng ý của tôi mà. Chả nhẽ tôi chỉ trích kiểu tìm như thế mà tôi lại viết code để tìm kiểu như thế?
 
Lần chỉnh sửa cuối:
Upvote 0
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

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

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

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
Gửi chủ topic:

Có những mẹo mực trong sử dụng viết code của bạn khá hay ***&&%, giúp cho mọi người có thểá p dụng vào thể loại bài khác tương tự

Tuy nhiên:

+ Ở đây có vẻ lạm dụng từ: phát minh, thuật toán tìm kiếm mới, chưa ai làm-- (cũng có thể tôi nhầm chăng vơi các nghĩa của từ này của Việt nam ta?)

+ Khẳng định rằng đây không có gì mới, vì nhanh trong hạn chế ứng dụng (đánh đúng thứ tự, không được lùi xóa, tìm kiếm không chính xác cả từ, cụm từ). - thì đó không phải là nhanh thật

+ So sánh nhanh thì phải cùng trường hợp, còn hạn chế so với tổng quát (tìm cả cụm từ có dấu và không hạn chế phải gõ theo đúng thứ tự) ---> thì khó rồi
 
Lần chỉnh sửa cuối:
Upvote 0
Mã:
    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
strColOne = UCase(LoaiDauUni(priArrPhuongXa(c)(0, r)))
Mỗi lần nhập thêm ký tự lệnh trên sẽ chạy lại dữ liệu đã xử lý
em đang tìm hiểu về userform anh có thể chỉ giúp em mục đích của Redim Preserve ở đây có ý nghĩa như nào không, theo em hiểu Redim Preserve chỉ tăng kích thước ở chiều thứ 2 và muốn chuyển sang dòng phải qua Transpose
 
Upvote 0
Upvote 0
em đang tìm hiểu về userform anh có thể chỉ giúp em mục đích của Redim Preserve ở đây có ý nghĩa như nào không, theo em hiểu Redim Preserve chỉ tăng kích thước ở chiều thứ 2 và muốn chuyển sang dòng phải qua Transpose
Redim Preserve dùng để khai báo thêm bớt chiều thứ 2 (chiều cuối cùng). Do chúng ta lấy mảng từ ComboBox từ Column chứ không phải từ List nên hàng trở thành cột và cột trở thành hàng, nói nôm na là vậy, vì thế nó có thể thay đổi chiều thứ 2 mà không cần phải Transpose, thuật toán này sẽ nhanh hơn kiểu thông thường.
 
Lần chỉnh sửa cuối:
Upvote 0
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ả.
Mình hơi kém cái này nên cho mình hỏi thêm chút nha, mình muốn tìm kiếm trên nhiều cột khác của bản dữ liệu thì mình làm sao?
 
Upvote 0
Code này không dùng được trong trường hợp tổng quát. Vì muốn dùng thì phải nhập dữ liệu theo đúng trình tự mà bạn bắt buộc. Vd. tôi nhập "sương" và có loạt kết quả chứa "sương". Lúc này tôi mới nhận ra lỗi chính tả, phải là "xương". Tôi muốn click trước hoặc sau "s" rồi dùng Delete hoặc Backspace để xóa "s" thì không được. Trỏ văn bản cứ nhẩy về cuối khi tôi click ở giữa từ, nên tôi phải nhấn phím mũi tên trái 4 lần. Sau khi xóa "s" tôi nhấn "x" để có "xương" thì không có kết quả nào dù dữ liệu có "xương". Hoặc lẽ ra phải gõ "Phong" thì do nhấn phím hơi lâu nên thành "Phoong". Bây giờ có xóa 1 "o" thì cũng không có kết quả dù dữ liệu có "Phong". Nhớ danh sách cuối để lọc từ đó thì nhiều người cũng nghĩ tới rồi chứ không phải là điều mới, nhưng nó đòi hỏi nhập và chỉnh sửa theo một cách nhất định. Ngoài ra nếu tôi gõ "phu" là tôi muốn tìm "phu" chứ không phải cả "phù", "phủ", "phũ", "phú", "phụ".

Tôi viết nhanh một code mà bạn gọi là thuật toán lọc hiện hành, lấy mảng gốc để lọc. Bạn thử kiểm tra tốc độ xem. Cứ gõ ký tự 1, rồi 2, ...

Đố bạn biết chỗ nhanh ở đâu, cái gì nó làm code nhanh hẳn. :D
code này hay quá anh ơi, cho em hỏi muốn tìm kiếm thêm ở các cột khác trong bảng dữ liệu thì làm sao?
 
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
Tôi test như sau: chèn 1 dòng trống vào vùng dữ liệu, cụ thể là dòng 2, chạy code bị lỗi. Chèn dòng trống bất kỳ từ dòng 3 trở đi: Code chạy OK. Chèn dòng trống vào dòng 1: code lỗi. chèn dòng trống vào dòng 1 và sửa code cho tương thích với vùng dữ liệu từ A2 thay vì A1: vẫn bị lỗi. Xin hỏi mọi người nguyên nhân lỗi và tùy biến code trên như thế nào để lọc từ 1 vùng bất kỳ trên trang tính. Cám ơn.
 
Upvote 0
Tôi có câu hỏi ở #68 không thấy ai trả lời giúp. Hai Lúa Miền Tây có thể trả lời giúp được không ??? xin cám ơn
 
Upvote 0

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

Back
Top Bottom