VNFastSearch – DLL tìm kiếm tiếng Việt tốc độ cao cho Excel VBA (2 người xem)

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

  • Tôi tuân thủ nội quy khi đăng bài

    phuongnam366377

    Thành viên thường trực
    Tham gia
    25/10/19
    Bài viết
    267
    Được thích
    237
    # VNFastSearch – DLL tìm kiếm tiếng Việt tốc độ cao cho Excel VBA

    ## Giới thiệu

    Khi làm việc với dữ liệu lớn trong Excel (vài nghìn đến hàng chục nghìn dòng), việc tìm kiếm chuỗi **tiếng Việt không phân biệt dấu** bằng VBA thuần hoặc ADODB (SQL LIKE) thường gặp các vấn đề:

    * Tốc độ chậm, lag khi gõ tìm realtime
    * Không xử lý tốt tiếng Việt có dấu
    * UserForm / TextBox dễ làm Excel bị đơ
    * Code VBA phức tạp, khó tối ưu

    **VNFastSearch.dll** được xây dựng để giải quyết các vấn đề trên bằng cách đưa phần tìm kiếm sang **DLL C++**, còn VBA chỉ đóng vai trò giao tiếp.

    ---

    ## Nguyên lý hoạt động

    1. Excel chuyển dữ liệu Range → chuỗi Unicode
    (phân tách cột bằng Tab, dòng bằng CRLF)
    2. DLL:

    * Tách dòng / cột
    * Chuẩn hoá tiếng Việt (bỏ dấu + lowercase)
    * Cache dữ liệu vào RAM
    3. Khi tìm kiếm:

    * VBA chỉ truyền keyword
    * DLL trả về index các dòng phù hợp
    4. VBA lấy lại dữ liệu gốc từ Sheet theo index

    DLL **không thay đổi dữ liệu Excel**, chỉ dùng để tìm kiếm.

    ---

    ## Khai báo API DLL trong VBA

    Tạo một **Module VBA** và khai báo:

    Mã:
    Option Explicit
    
    Public Declare PtrSafe Sub LoadVNCache Lib "VNFastSearch.dll" ( _
    ByVal txtPtr As LongPtr, _
    ByVal colCount As Long _
    )
    
    Public Declare PtrSafe Function FindVNRows Lib "VNFastSearch.dll" ( _
    ByVal keyPtr As LongPtr, _
    ByVal colMask As Long, _
    ByRef rows As Long, _
    ByVal maxCount As Long _
    ) As Long
    
    Public Declare PtrSafe Function FindVNRowsExRange Lib "VNFastSearch.dll" ( _
    ByVal keyPtr As LongPtr, _
    ByVal colMask As Long, _
    ByVal rowStart As Long, _
    ByVal rowEnd As Long, _
    ByRef rows As Long, _
    ByVal maxCount As Long _
    ) As Long
    
    Public Declare PtrSafe Function IsVNCacheReady Lib "VNFastSearch.dll" () As Long
    
    Public Declare PtrSafe Function CountVNRows Lib "VNFastSearch.dll" ( _
    ByVal keyPtr As LongPtr, _
    ByVal colMask As Long _
    ) As Long
    
    Public Declare PtrSafe Sub ClearVNCache Lib "VNFastSearch.dll" ()

    ---

    ## Hàm hỗ trợ: chuyển Range sang Unicode Text

    Mã:
    Public Function RangeToUnicodeText(rg As Range) As String
    Dim arr As Variant
    Dim r As Long, c As Long
    Dim sb As String
    
    ```
    arr = rg.Value
    
    For r = 1 To UBound(arr, 1)
        For c = 1 To UBound(arr, 2)
            sb = sb & CStr(arr(r, c))
            If c < UBound(arr, 2) Then sb = sb & vbTab
        Next c
        sb = sb & vbCrLf
    Next r
    
    RangeToUnicodeText = sb
    ```
    
    End Function

    ---

    ## Load cache (chỉ cần gọi 1 lần)

    Mã:
    Public Sub InitVNCacheOnce()
    If IsVNCacheReady() <> 0 Then Exit Sub
    
    ```
    Dim rg As Range
    Set rg = Sheets("Data").Range("A1").CurrentRegion
    
    LoadVNCache StrPtr(RangeToUnicodeText(rg)), rg.Columns.Count
    ```
    
    End Sub

    ---

    ## Ví dụ tìm kiếm và ghi kết quả ra Sheet

    Mã:
    Public Sub VN_Search_ToSheet( _
    ByVal keyword As String, _
    ByVal outCell As Range)
    
    ```
    Dim idx(1 To 1000) As Long
    Dim found As Long
    Dim i As Long
    Dim src As Range
    
    Call InitVNCacheOnce
    
    If Trim$(keyword) = "" Then
        outCell.Resize(1000, 50).ClearContents
        Exit Sub
    End If
    
    found = FindVNRows(StrPtr(keyword), 0, idx(1), 1000)
    If found <= 0 Then Exit Sub
    
    Set src = Sheets("Data").Range("A1").CurrentRegion
    outCell.Resize(1000, src.Columns.Count).ClearContents
    
    For i = 1 To found
        outCell.Offset(i - 1, 0).Resize(1, src.Columns.Count).Value = _
            Application.Index(src.Value, idx(i), 0)
    Next i
    ```
    
    End Sub

    ---

    ## Ví dụ dùng với TextBox trên Sheet

    Mã:
    Private Sub TextBox1_Change()
    VN_Search_ToSheet Me.TextBox1.Text, Me.Range("E3")
    End Sub

    * Gõ tới đâu → lọc tới đó
    * Không lag
    * Không phân biệt dấu tiếng Việt

    ---

    ## Lọc theo cột (Column Mask)

    * bit 0 = cột A
    * bit 1 = cột B
    * bit 2 = cột C

    Ví dụ chỉ tìm trong cột A và C:

    Mã:
    found = FindVNRows(StrPtr("lan"), 5, idx(1), 1000)

    (1 + 4 = 5)

    ---

    ## Đếm nhanh số dòng phù hợp

    Không cần mảng, rất nhanh:

    Mã:
    Dim n As Long
    n = CountVNRows(StrPtr("an"), 0)
    Debug.Print n

    ---

    ## Khi nào nên dùng VNFastSearch

    * Dữ liệu lớn (≥ vài nghìn dòng)
    * Tìm kiếm realtime khi gõ
    * UserForm / TextBox
    * Cần tìm tiếng Việt không phân biệt dấu
    * VBA thuần hoặc ADODB bị chậm

    ---

    ## Kết luận

    VNFastSearch giúp:

    * Tìm kiếm tiếng Việt **rất nhanh**
    * Giảm tải VBA
    * Tránh lag / crash Excel
    * Code VBA gọn, dễ tái sử dụng

    Phù hợp cho các file Excel cần tìm kiếm dữ liệu lớn và giao diện thân thiện.

    ---

    đang rảnh viết chơi tí buổi sáng Úp cho ai cần thì dùng ... bản xem trước rảnh test lại úp file Excel sau ... Nó tìm kiếm siêu nhanh



    Đúng rồi — về mặt trải nghiệm sử dụng thì nó rất giống Google Search, nhưng về kỹ thuật bên trong thì đơn giản hơn Google rất nhiều. Mình nói rõ để bạn nắm bản chất nhé.

    Giống Google ở điểm nào?​

    1️⃣ Tìm khi đang gõ (realtime)​

    • Gõ tới đâu → kết quả lọc tới đó
    • Không cần nhấn Enter
    • TextBox_Change là ra kết quả ngay
    Cảm giác dùng giống Google Search / Excel filter nâng cao

    2️⃣ Không phân biệt dấu tiếng Việt​

    Ví dụ người dùng gõ:
    • an
    • ăn
    • Ân
    • AN
    Đều tìm ra:
    • An
    • Ân
    • Ăn
    • Nguyễn Văn An
    Giống cách Google xử lý tiếng Việt.

    3️⃣ Tìm gần đúng (substring)​

    • Không cần gõ đúng toàn bộ từ
    • Chỉ cần một phần chuỗi
    Ví dụ dữ liệu:
    Mã:
    Nguyễn Văn An
    Trần Minh Anh
    Phan Văn Long
    Gõ:
    • an → ra cả 3 dòng
    • min → ra Minh
    • van → ra Văn
    Đây chính là kiểu contains giống Google.

    Nhưng KHÔNG phải Google thật​

    ❌ Không có xếp hạng thông minh​

    Google có:
    • Ưu tiên từ khoá ở đầu
    • Học hành vi người dùng
    • NLP, AI, semantic search
    VNFastSearch thì:
    • Chỉ check find() chuỗi
    • Dòng nào match trước → trả trước
    • Không có ranking

    ❌ Không sửa lỗi chính tả​

    Google:
    • nguen van an
    • Gợi ý: “Bạn có muốn tìm Nguyễn Văn An?”
    VNFastSearch:
    • Không có sửa lỗi
    • Gõ sai → không ra
    (Cái này có thể mở rộng sau)

    Bản chất kỹ thuật (nói gọn)​

    VNFastSearch hoạt động kiểu:
    1. Chuẩn hoá toàn bộ dữ liệu:
      Mã:
      Nguyễn Văn An → nguyen van an
    2. Chuẩn hoá keyword:
      Mã:
      Ân → an
    3. So sánh:
      Mã:
      if cell.find(keyword) != npos → MATCH
    Rất nhanh vì:
    • Không truy cập Sheet khi tìm
    • Chỉ tìm trên RAM
    • Không xử lý Excel Object Model trong vòng lặp

    So với ADODB LIKE​

    Tiêu chíVNFastSearchADODB LIKE
    Tốc độ Rất nhanh Chậm khi lớn
    Realtime✅ Rất mượt❌ Lag
    Không dấu✅❌ Không
    VBA đơn giản✅❌
    SQL❌✅

    Nếu muốn giống Google hơn nữa thì có thể làm gì?​

    Có thể mở rộng DLL thêm:
    • ✅ Ưu tiên match đầu chuỗi
    • ✅ Ưu tiên cột chính (VD: Tên)
    • ✅ Tách từ (token search)
    • ✅ Gợi ý từ khoá
    • ✅ Highlight keyword trong kết quả
    Nền tảng hiện tại đã rất tốt để phát triển tiếp.

    Tóm lại (1 câu)​

    Về cách người dùng cảm nhận: đúng là giống Google Search.
    Về kỹ thuật: là “Google-style search đơn giản, cực nhanh, chạy trong Excel”.
     
    Đúng rồi. Nói không + mấy dòng code thì không hình dung được
    Thử xem có gì báo lại mới úp trên github

    Downloads

    Tôi không sử dụng hệ thống 32 bit mà sử dụng Windows11_x64 và Office2024_x64 nên úp lên là bản 64 bit vậy bạn nào dùng Office 32 bít thì nói tôi tạo riêng bản 32 bit úp sau

    xem hình thử hàm trong Sheet FindVNRowsSmart ... còn các hàm Sheet khác đang test và viết thêm chưa hoàn thiện có chức năng AutoComplete

    1771464683437.png


    1/ Gõ tìm kiếm ký tự bất kỳ không dấu vào TextBox nó sẽ tìm ra từ mảng dữ liệu có ký tự đó và xếp hạnh thấp dần xuống cuối dòng của Sheet ... có nghĩa ký tự đúng hàng đầu và sai số dần xuống cuối

    2/ xem có có ghi chú các hàm và cách sử dụng

    3/ thử gõ 26 ký tự bàn phín xem sao ??!!!

    Còn bài sau là do Copilot viết theo yêu cầu của tôi và nó cùng viết hàm C++ Builder


    Tìm kiếm thông minh trong Excel với SearchVNRowsSmart

    Trong Excel, hàm Find mặc định chỉ cho phép tìm từng kết quả một, không có xếp hạng mức độ phù hợp, và không hỗ trợ tiếng Việt có dấu. Để khắc phục hạn chế này, DLL VNFastSearch cung cấp hàm SearchVNRowsSmart, biến Excel thành một công cụ tìm kiếm mạnh mẽ, giống như một “Google mini” cho dữ liệu bảng tính.

    Chức năng chính​

    • Tìm kiếm thông minh: tự động chọn thuật toán phù hợp theo độ dài từ khóa.
      • <4 ký tự → tìm kiếm nhanh, đơn luồng.
      • 4–6 ký tự → tìm kiếm fuzzy (cho phép sai khác 1 ký tự).
      • ≥7 ký tự → tìm kiếm đa luồng, tối ưu cho dữ liệu lớn.
    • Chấm điểm kết quả: ưu tiên khớp chính xác, sắp xếp theo mức độ phù hợp.
    • Hỗ trợ Unicode tiếng Việt: xử lý tốt dữ liệu có dấu.
    • Trả về nhiều kết quả cùng lúc: tối đa 500 dòng, không cần lặp lại nhiều lần như Find.
    • API đơn giản: chỉ cần gọi một hàm duy nhất trong VBA.

    Khai báo trong VBA​

    Mã:
    Declare PtrSafe Function SearchVNRowsSmart Lib "VNFastSearch.dll" _
        (ByVal keyword As LongPtr, ByVal colMask As Long, _
         ByRef outRows As Long, ByVal maxCount As Long) As Long

    Ví dụ sử dụng cơ bản​

    Mã:
    Sub TestSearch()
        Dim rows(100) As Long
        Dim found As Long
       
        ' Đảm bảo cache đã load trước
        EnsureCacheLoaded "Data", "A1:D1000", 4
       
        ' Tìm kiếm từ khóa "hoa hồng"
        found = SearchVNRowsSmart(StrPtr("hoa hồng"), 0, rows(0), 100)
       
        If found > 0 Then
            Dim i As Long
            For i = 0 To found - 1
                Debug.Print "Kết quả tại dòng: "; rows(i)
            Next i
        Else
            Debug.Print "Không tìm thấy kết quả."
        End If
    End Sub

    Ứng dụng nâng cao: Search Box như Google​

    Bạn có thể kết hợp với TextBox trên UserForm để tạo ô tìm kiếm trực tiếp trong Excel:
    Mã:
    Private Sub TextBox1_Change()
        If Not FastDebounceAdaptive(Me.TextBox1.Text) Then Exit Sub
    
        FindVNRowsSmart_ToSheet _
            Me.TextBox1.Text, _
            "Data", _
            "A1:C5000", _
            "FindVNRowsSmart", _
            "A3"
    End Sub
    Khi người dùng gõ từ khóa, kết quả sẽ tự động hiển thị trên sheet “FindVNRowsSmart” từ ô A3, giống như cách Google trả về danh sách kết quả.

    Quy trình hoạt động​

    Mã:
    [Keyword người dùng]
            ↓ Chuẩn hóa (VN_NormalizeFull)
    [Tách thành danh sách từ]
            ↓ Duyệt cache
    [So khớp từng ô dữ liệu]
            ↓ Chấm điểm mức độ phù hợp
    [Sắp xếp kết quả theo điểm]
            ↓ Trả về danh sách dòng phù hợp nhất

    So sánh với Excel Find​

    Tính năngExcel FindSearchVNRowsSmart
    Tìm nhiều kết quả❌✅ (tối đa 500)
    Xếp hạng mức độ phù hợp❌✅
    Tìm kiếm fuzzy❌✅
    Hỗ trợ Unicode tiếng Việt❌✅
    Tốc độ trên dữ liệu lớnChậmNhanh (đa luồng)

    Với SearchVNRowsSmart, bạn có thể biến Excel thành công cụ tìm kiếm dữ liệu mạnh mẽ, nhanh chóng và thân thiện, đặc biệt hữu ích khi làm việc với bảng dữ liệu lớn bằng tiếng Việt.

     
    "dĩ bất biến còn ứng vạn biến" ... sáng nay đang rảnh chiều bận tết nên làm chơi một ví dụ ứng dụng nó cho ai đó cần thì sử dụng chơi

    trên Sheet vẽ ra hai Controls sau

    1/ Private Sub TextBox1_Change()

    2/ Private Sub ListBox1_Click()

    Copy Code sau vào sử dụng
    Mã:
    Option Explicit
    
    #If VBA7 Then
        Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
        Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
        Private Declare PtrSafe Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32W" ( _
            ByVal hdc As LongPtr, _
            ByVal lpString As LongPtr, _
            ByVal c As Long, _
            lpSize As SIZE) As Long
    #Else
        Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
        Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
        Private Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32W" ( _
            ByVal hdc As Long, _
            ByVal lpString As Long, _
            ByVal c As Long, _
            lpSize As SIZE) As Long
    #End If
    
    Private Type SIZE
        cx As Long
        cy As Long
    End Type
    
    
    Public Sub AutoColumnWidthsAndResize(lb As MSForms.ListBox, rng As Range)
        Dim c As Long, r As Long
        Dim maxLen As Long
        Dim colWidths() As String
        Dim totalWidth As Double
        Dim textValue As String
       
        ReDim colWidths(1 To rng.Columns.count)
       
        For c = 1 To rng.Columns.count
            maxLen = 0
           
            For r = 1 To rng.rows.count
                textValue = CStr(rng.Cells(r, c).Value)
                If Len(textValue) > maxLen Then
                    maxLen = Len(textValue)
                End If
            Next r
           
            ' ~6.5 point moi ký tu (Calibri 11 gan dúng)
            colWidths(c) = (maxLen * 6.5 + 10)
           
            totalWidth = totalWidth + CDbl(colWidths(c))
        Next c
       
        lb.ColumnCount = rng.Columns.count
        lb.ColumnWidths = Join(colWidths, ";")
       
        ' ?? Co luôn ListBox
        lb.Width = totalWidth + 10   ' padding
       
    End Sub
    
    ' Ham tien ich: nap du lieu tim kiem vao ListBox nhieu cot
    Public Sub LoadSearchResultToListBox( _
        ByVal lb As MSForms.ListBox, _
        ByVal keyword As String, _
        ByVal wsName As String, _
        ByVal srcRange As String, _
        Optional ByVal maxCount As Long = 100 _
    )
        Dim rows() As Long
        Dim found As Long
        Dim i As Long, c As Long
        Dim wsSrc As Worksheet
        Dim srcRg As Range
       
        ' Dam bao cache da load
        EnsureCacheLoaded wsName, srcRange, Range(srcRange).Columns.count
       
        ' Neu keyword rong thi xoa ListBox
        If Trim$(keyword) = "" Then
            lb.Clear
            Exit Sub
        End If
       
        ' Khoi tao mang ket qua
        ReDim rows(1 To maxCount)
       
        ' Tim kiem
        found = SearchVNRowsSmart(StrPtr(keyword), 0, rows(1), maxCount)
       
        ' Xoa ket qua cu
        lb.Clear
       
        If found > 0 Then
            Set wsSrc = ThisWorkbook.Worksheets(wsName)
            Set srcRg = wsSrc.Range(srcRange)
           
            ' Nap du lieu vao ListBox
            For i = 1 To found
                lb.AddItem srcRg.Cells(rows(i), 1).Value
                For c = 2 To srcRg.Columns.count
                    lb.List(lb.ListCount - 1, c - 1) = srcRg.Cells(rows(i), c).Value
                Next c
            Next i
           
            ' Goi AutoColumnWidths de tu dong co gian cot theo du lieu
            AutoColumnWidthsAndResize lb, srcRg
        End If
    End Sub
    
    
    'Cach goi tu TextBox
    Private Sub TextBox1_Change()
        ' Goi hàm tien ích, không can truyen colWidths nua
        LoadSearchResultToListBox _
            Me.ListBox1, _
            Me.TextBox1.Text, _
            "Data", _
            "A1:C1000", _
            200   ' so ket qua toi da
    End Sub

    Hình ảnh khi gõ các từ không dấu tìm kiếm như sau xong thử nguyen van và xoá nó sẽ xếp hạng gần đúng dòng đầu của listbox và sai dần về cuối

    ký tự nào có trong bảng dữ liệu sẽ liệt kê hết theo dòng ra listbox

    1771470561033.png
     
    trên VBA Tạo một cái Form
    Vẽ kéo 2 Controls vào Form

    1/ TextBox1_Change
    Mã:
    Private Sub TextBox1_Change()
        FormListBoxFastLoad _
            Me.ListBox1, _
            TextBox1.Text, _
            "Data", _
            "A2:C1000", _
            Array("Ho", "Tên", "Ghi chú"), _
            200
    
    End Sub

    2/ ListBox1_Click

    Mã:
    Private Sub ListBox1_Click()
        FormListBoxBlockHeader Me.ListBox1
    End Sub


    Copy Code sau vào một Module tên gì tuỳ thích ...Tôi ít quan tâm

    Mã:
    Option Explicit
    ' ==========================================================
    ' FAST SEARCH + HEADER DONG DAU (DUNG DLL CACHE)
    ' ==========================================================
    Public Sub FormListBoxFastLoad( _
            ByVal lb As MSForms.ListBox, _
            ByVal keyword As String, _
            ByVal wsName As String, _
            ByVal srcRange As String, _
            ByVal headers As Variant, _
            Optional ByVal maxCount As Long = 200)
    
        Dim rows() As Long
        Dim found As Long
        Dim i As Long, c As Long
        Dim ws As Worksheet
        Dim rg As Range
        Dim colCount As Long
      
        lb.Clear
      
        If Trim$(keyword) = "" Then Exit Sub
      
        Set ws = ThisWorkbook.Worksheets(wsName)
        Set rg = ws.Range(srcRange)
      
        colCount = rg.Columns.count
      
        ' dam bao cache da load
        EnsureCacheLoaded wsName, srcRange, colCount
      
        ReDim rows(1 To maxCount)
      
        found = SearchVNRowsSmart(StrPtr(keyword), 0, rows(1), maxCount)
      
        If found = 0 Then Exit Sub
      
        lb.ColumnCount = colCount
      
        ' ===== HEADER DONG DAU =====
        lb.AddItem
        For c = 0 To colCount - 1
            lb.List(0, c) = UCase(headers(c))
        Next c
      
        ' ===== LOAD KET QUA TU CACHE =====
        For i = 1 To found
          
            lb.AddItem rg.Cells(rows(i), 1).Value
          
            For c = 2 To colCount
                lb.List(lb.ListCount - 1, c - 1) = _
                    rg.Cells(rows(i), c).Value
            Next c
          
        Next i
      
        AutoResizeFast lb
    
    End Sub
    
    
    ' ==========================================================
    ' AUTO RESIZE NHANH
    ' ==========================================================
    Private Sub AutoResizeFast(lb As MSForms.ListBox)
    
        Dim r As Long, c As Long
        Dim maxLen As Long
        Dim totalWidth As Double
        Dim colWidths() As String
      
        If lb.ListCount = 0 Then Exit Sub
      
        ReDim colWidths(0 To lb.ColumnCount - 1)
      
        For c = 0 To lb.ColumnCount - 1
          
            maxLen = 0
          
            For r = 0 To lb.ListCount - 1
                If Len(lb.List(r, c)) > maxLen Then
                    maxLen = Len(lb.List(r, c))
                End If
            Next r
          
            colWidths(c) = maxLen * 6.2 + 18
            totalWidth = totalWidth + colWidths(c)
          
        Next c
      
        lb.ColumnWidths = Join(colWidths, ";")
        lb.Width = totalWidth + 5
        lb.IntegralHeight = False
      
    End Sub
    
    
    ' ==========================================================
    ' CHAN CHON HEADER
    ' ==========================================================
    Public Sub FormListBoxBlockHeader(lb As MSForms.ListBox)
    
        If lb.ListIndex = 0 Then
            lb.ListIndex = -1
        End If
      
    End Sub
    
    ' ==========================================================
    ' su dung tren form nhu sau
    ' ==========================================================
    
    Private Sub TextBox1_Change()
        FormListBoxFastLoad _
            Me.ListBox1, _
            TextBox1.Text, _
            "Data", _
            "A2:C1000", _
            Array("Ho", "Tên", "Ghi chú"), _
            200
    
    End Sub
    
    Private Sub ListBox1_Click()
        FormListBoxBlockHeader Me.ListBox1
    End Sub

    Thời đại AI hãy học code theo tư duy logis và ra lệnh cho AI viết vài phút là xong hãy biết vận dụng nó viết lại cho đẹp theo sở thích

    Cơ bản là vậy còn vận dụng tuỳ khả năng của ai đó vào công việc của mình cho phù hợp

    Hình ảnh tạm như sau

    1771472288453.png
    Copilot nhận xét như sau

    Excel VBA (UI)
    → gọi DLL C++
    → DLL giữ cache trong RAM
    → Search chạy trên bộ nhớ
    → VBA chỉ render kết quả

    Đó là lý do nó nhanh.

    ---

    # Vì sao nó nhanh thật sự?

    Khi bạn dùng:

    ```vba
    EnsureCacheLoaded
    SearchVNRowsSmart
    ```

    thì:

    * Sheet chỉ load 1 lần vào RAM C++
    * Không còn đọc từng ô Excel
    * Không còn Variant 2D loop chậm
    * Không còn InStr trên VBA
    * Chỉ trả về index dòng

    VBA chỉ làm việc nhẹ:

    ```vba
    rg.Cells(rows(i), c).Value
    ```

    → chi phí cực nhỏ so với search.

    ---

    # Nếu muốn đẩy hiệu năng thêm nữa

    Hiện tại bạn vẫn đang:

    ```vba
    rg.Cells(rows(i), c).Value
    ```

    Nghĩa là vẫn truy cập Worksheet.

    Nếu muốn cực hạn tốc độ:

    ### Cách Pro hơn:

    Cho DLL trả luôn dữ liệu gốc (wstring)
    → VBA không cần đụng Worksheet nữa
    → Không cần rg.Cells

    Khi đó:

    * Search + trả dữ liệu = 100% RAM
    * Excel chỉ hiển thị

    Tốc độ sẽ còn cao hơn nữa khi dataset lớn.

    ---

    # Kiến trúc bạn đang dùng là chuẩn

    | Tầng | Vai trò |
    | --------- | --------------------- |
    | VBA | UI |
    | DLL C++ | Engine |
    | RAM | Database |
    | Worksheet | Nguồn dữ liệu ban đầu |

    Đây là mô hình giống mini search engine.
     
    # VNFastSearch – DLL tìm kiếm tiếng Việt tốc độ cao cho Excel VBA

    ## Giới thiệu

    Khi làm việc với dữ liệu lớn trong Excel (vài nghìn đến hàng chục nghìn dòng), việc tìm kiếm chuỗi **tiếng Việt không phân biệt dấu** bằng VBA thuần hoặc ADODB (SQL LIKE) thường gặp các vấn đề:

    * Tốc độ chậm, lag khi gõ tìm realtime
    * Không xử lý tốt tiếng Việt có dấu
    * UserForm / TextBox dễ làm Excel bị đơ
    * Code VBA phức tạp, khó tối ưu

    **VNFastSearch.dll** được xây dựng để giải quyết các vấn đề trên bằng cách đưa phần tìm kiếm sang **DLL C++**, còn VBA chỉ đóng vai trò giao tiếp.

    ---

    ## Nguyên lý hoạt động

    1. Excel chuyển dữ liệu Range → chuỗi Unicode
    (phân tách cột bằng Tab, dòng bằng CRLF)
    2. DLL:

    * Tách dòng / cột
    * Chuẩn hoá tiếng Việt (bỏ dấu + lowercase)
    * Cache dữ liệu vào RAM
    3. Khi tìm kiếm:

    * VBA chỉ truyền keyword
    * DLL trả về index các dòng phù hợp
    4. VBA lấy lại dữ liệu gốc từ Sheet theo index

    DLL **không thay đổi dữ liệu Excel**, chỉ dùng để tìm kiếm.

    ---

    ## Khai báo API DLL trong VBA

    Tạo một **Module VBA** và khai báo:

    Mã:
    Option Explicit
    
    Public Declare PtrSafe Sub LoadVNCache Lib "VNFastSearch.dll" ( _
    ByVal txtPtr As LongPtr, _
    ByVal colCount As Long _
    )
    
    Public Declare PtrSafe Function FindVNRows Lib "VNFastSearch.dll" ( _
    ByVal keyPtr As LongPtr, _
    ByVal colMask As Long, _
    ByRef rows As Long, _
    ByVal maxCount As Long _
    ) As Long
    
    Public Declare PtrSafe Function FindVNRowsExRange Lib "VNFastSearch.dll" ( _
    ByVal keyPtr As LongPtr, _
    ByVal colMask As Long, _
    ByVal rowStart As Long, _
    ByVal rowEnd As Long, _
    ByRef rows As Long, _
    ByVal maxCount As Long _
    ) As Long
    
    Public Declare PtrSafe Function IsVNCacheReady Lib "VNFastSearch.dll" () As Long
    
    Public Declare PtrSafe Function CountVNRows Lib "VNFastSearch.dll" ( _
    ByVal keyPtr As LongPtr, _
    ByVal colMask As Long _
    ) As Long
    
    Public Declare PtrSafe Sub ClearVNCache Lib "VNFastSearch.dll" ()

    ---

    ## Hàm hỗ trợ: chuyển Range sang Unicode Text

    Mã:
    Public Function RangeToUnicodeText(rg As Range) As String
    Dim arr As Variant
    Dim r As Long, c As Long
    Dim sb As String
    
    ```
    arr = rg.Value
    
    For r = 1 To UBound(arr, 1)
        For c = 1 To UBound(arr, 2)
            sb = sb & CStr(arr(r, c))
            If c < UBound(arr, 2) Then sb = sb & vbTab
        Next c
        sb = sb & vbCrLf
    Next r
    
    RangeToUnicodeText = sb
    ```
    
    End Function

    ---

    ## Load cache (chỉ cần gọi 1 lần)

    Mã:
    Public Sub InitVNCacheOnce()
    If IsVNCacheReady() <> 0 Then Exit Sub
    
    ```
    Dim rg As Range
    Set rg = Sheets("Data").Range("A1").CurrentRegion
    
    LoadVNCache StrPtr(RangeToUnicodeText(rg)), rg.Columns.Count
    ```
    
    End Sub

    ---

    ## Ví dụ tìm kiếm và ghi kết quả ra Sheet

    Mã:
    Public Sub VN_Search_ToSheet( _
    ByVal keyword As String, _
    ByVal outCell As Range)
    
    ```
    Dim idx(1 To 1000) As Long
    Dim found As Long
    Dim i As Long
    Dim src As Range
    
    Call InitVNCacheOnce
    
    If Trim$(keyword) = "" Then
        outCell.Resize(1000, 50).ClearContents
        Exit Sub
    End If
    
    found = FindVNRows(StrPtr(keyword), 0, idx(1), 1000)
    If found <= 0 Then Exit Sub
    
    Set src = Sheets("Data").Range("A1").CurrentRegion
    outCell.Resize(1000, src.Columns.Count).ClearContents
    
    For i = 1 To found
        outCell.Offset(i - 1, 0).Resize(1, src.Columns.Count).Value = _
            Application.Index(src.Value, idx(i), 0)
    Next i
    ```
    
    End Sub

    ---

    ## Ví dụ dùng với TextBox trên Sheet

    Mã:
    Private Sub TextBox1_Change()
    VN_Search_ToSheet Me.TextBox1.Text, Me.Range("E3")
    End Sub

    * Gõ tới đâu → lọc tới đó
    * Không lag
    * Không phân biệt dấu tiếng Việt

    ---

    ## Lọc theo cột (Column Mask)

    * bit 0 = cột A
    * bit 1 = cột B
    * bit 2 = cột C

    Ví dụ chỉ tìm trong cột A và C:

    Mã:
    found = FindVNRows(StrPtr("lan"), 5, idx(1), 1000)

    (1 + 4 = 5)

    ---

    ## Đếm nhanh số dòng phù hợp

    Không cần mảng, rất nhanh:

    Mã:
    Dim n As Long
    n = CountVNRows(StrPtr("an"), 0)
    Debug.Print n

    ---

    ## Khi nào nên dùng VNFastSearch

    * Dữ liệu lớn (≥ vài nghìn dòng)
    * Tìm kiếm realtime khi gõ
    * UserForm / TextBox
    * Cần tìm tiếng Việt không phân biệt dấu
    * VBA thuần hoặc ADODB bị chậm

    ---

    ## Kết luận

    VNFastSearch giúp:

    * Tìm kiếm tiếng Việt **rất nhanh**
    * Giảm tải VBA
    * Tránh lag / crash Excel
    * Code VBA gọn, dễ tái sử dụng

    Phù hợp cho các file Excel cần tìm kiếm dữ liệu lớn và giao diện thân thiện.

    ---

    đang rảnh viết chơi tí buổi sáng Úp cho ai cần thì dùng ... bản xem trước rảnh test lại úp file Excel sau ... Nó tìm kiếm siêu nhanh



    Đúng rồi — về mặt trải nghiệm sử dụng thì nó rất giống Google Search, nhưng về kỹ thuật bên trong thì đơn giản hơn Google rất nhiều. Mình nói rõ để bạn nắm bản chất nhé.

    Giống Google ở điểm nào?​

    1️⃣ Tìm khi đang gõ (realtime)​

    • Gõ tới đâu → kết quả lọc tới đó
    • Không cần nhấn Enter
    • TextBox_Change là ra kết quả ngay
    Cảm giác dùng giống Google Search / Excel filter nâng cao

    2️⃣ Không phân biệt dấu tiếng Việt​

    Ví dụ người dùng gõ:
    • an
    • ăn
    • Ân
    • AN
    Đều tìm ra:
    • An
    • Ân
    • Ăn
    • Nguyễn Văn An
    Giống cách Google xử lý tiếng Việt.

    3️⃣ Tìm gần đúng (substring)​

    • Không cần gõ đúng toàn bộ từ
    • Chỉ cần một phần chuỗi
    Ví dụ dữ liệu:
    Mã:
    Nguyễn Văn An
    Trần Minh Anh
    Phan Văn Long
    Gõ:
    • an → ra cả 3 dòng
    • min → ra Minh
    • van → ra Văn
    Đây chính là kiểu contains giống Google.

    Nhưng KHÔNG phải Google thật​

    ❌ Không có xếp hạng thông minh​

    Google có:
    • Ưu tiên từ khoá ở đầu
    • Học hành vi người dùng
    • NLP, AI, semantic search
    VNFastSearch thì:
    • Chỉ check find() chuỗi
    • Dòng nào match trước → trả trước
    • Không có ranking

    ❌ Không sửa lỗi chính tả​

    Google:
    • nguen van an
    • Gợi ý: “Bạn có muốn tìm Nguyễn Văn An?”
    VNFastSearch:
    • Không có sửa lỗi
    • Gõ sai → không ra
    (Cái này có thể mở rộng sau)

    Bản chất kỹ thuật (nói gọn)​

    VNFastSearch hoạt động kiểu:
    1. Chuẩn hoá toàn bộ dữ liệu:
      Mã:
      Nguyễn Văn An → nguyen van an
    2. Chuẩn hoá keyword:
      Mã:
      Ân → an
    3. So sánh:
      Mã:
      if cell.find(keyword) != npos → MATCH
    Rất nhanh vì:
    • Không truy cập Sheet khi tìm
    • Chỉ tìm trên RAM
    • Không xử lý Excel Object Model trong vòng lặp

    So với ADODB LIKE​

    Tiêu chíVNFastSearchADODB LIKE
    Tốc độRất nhanhChậm khi lớn
    Realtime✅ Rất mượt❌ Lag
    Không dấu✅❌ Không
    VBA đơn giản✅❌
    SQL❌✅

    Nếu muốn giống Google hơn nữa thì có thể làm gì?​

    Có thể mở rộng DLL thêm:
    • ✅ Ưu tiên match đầu chuỗi
    • ✅ Ưu tiên cột chính (VD: Tên)
    • ✅ Tách từ (token search)
    • ✅ Gợi ý từ khoá
    • ✅ Highlight keyword trong kết quả
    Nền tảng hiện tại đã rất tốt để phát triển tiếp.

    Tóm lại (1 câu)​

    Về cách người dùng cảm nhận: đúng là giống Google Search.
    Về kỹ thuật: là “Google-style search đơn giản, cực nhanh, chạy trong Excel”.

    Cảm ơn vì một file .dll chia sẻ tìm kiếm với tốc độ rất nhanh
    Thực tế trong việc áp dụng vào VBA như làm file Nhập - Xuất - Tồn chẳng hạn
    Yêu cầu tìm kiếm là gồm có cả dấu tiếng việt
    Nếu có thể mong bác làm tiếp file .dll cho việc tìm kiếm theo cả dấu tiếng việt
    Em nghĩ việc load dữ liệu vào RAM thì khi trả kết quả hãy trả luôn dạng mãng dữ liệu đừng trả index mất công VBA làm việc lần nữa
    Kết quả có thể vẫn sắp xếp theo thứ tự độ liên quan đến keyword
    Một lần nữa xin cảm ơn và chúc bác thật nhiều sức khỏe
     
    Cái này dùng thế nào vậy tác giả, không biết dùng inbox riêng có được hướng đẫn tận giường không anh trai?
     

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

    Back
    Top Bottom