Hướng dẫn tạo Nút bấm sắp xếp họ tên tiếng Việt trong LibreOffice Calc (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

    hng1635

    Thành viên mới
    Tham gia
    7/11/08
    Bài viết
    19
    Được thích
    8
    Bài toán sắp xếp tên tiếng Việt trên Excel đã được giải quyết từ rất lâu rồi và hiện nay có nhiều addin hỗ trợ, tuy nhiên với LibreOffice Calc thì chưa thấy có giải pháp nào làm việc tương ứng. Nay nhân tiện có con Gemini nên bắt nó viết đoạn code để dùng, thấy cũng được nên viết bài để chia sẻ cho anh em nào dùng LibreOffice Calc.
    Đây là đoạn code sắp xếp tiếng Việt:

    PHP:
    REM === MACRO SẮP XẾP HỌ TÊN TIẾNG VIỆT TRỰC TIẾP TRÊN VÙNG CHỌN ===
    
    Sub SapXepTenTiengViet_Click()
        Dim oDoc As Object, oSel As Object
        oDoc = ThisComponent
        oSel = oDoc.CurrentSelection
        
        ' 1. Kiểm tra vùng chọn
        If Not oSel.supportsService("com.sun.star.sheet.SheetCellRange") Then
            MsgBox "Vui lòng bôi đen vùng dữ liệu cần sắp xếp!", 48, "Lỗi thao tác"
            Exit Sub
        End If
        
        Dim numCols As Long
        numCols = oSel.Columns.Count
        
        Dim keyColIndex As Long
        keyColIndex = 0 ' Mặc định là cột đầu tiên (chỉ số 0)
        
        ' 2. Hỏi người dùng nếu chọn nhiều cột
        If numCols > 1 Then
            Dim userInput As String
            userInput = InputBox("Bạn đã bôi đen " & numCols & " cột." & Chr(10) & _
                                 "Nhập SỐ THỨ TỰ của cột chứa HỌ TÊN để làm chuẩn sắp xếp:" & Chr(10) & _
                                 "(Tính từ trái sang phải trong vùng đã chọn, bắt đầu từ 1)", "Chọn cột sắp xếp", "1")
                                
            ' Nếu người dùng bấm Cancel hoặc bỏ trống
            If userInput = "" Then Exit Sub
            
            ' Kiểm tra xem có nhập đúng số không
            If Not IsNumeric(userInput) Then
                MsgBox "Vui lòng nhập một số nguyên hợp lệ!", 48, "Lỗi"
                Exit Sub
            End If
            
            keyColIndex = CLng(userInput) - 1 ' Trừ 1 vì mảng bắt đầu từ 0
            
            If keyColIndex < 0 Or keyColIndex >= numCols Then
                MsgBox "Số thứ tự cột không hợp lệ! Vui lòng nhập từ 1 đến " & numCols, 48, "Lỗi"
                Exit Sub
            End If
        End If
        
        Dim mData As Variant
        mData = oSel.getDataArray() ' Lấy mảng dữ liệu (mỗi phần tử là 1 dòng chứa các cột)
        
        Dim UBR As Long
        UBR = UBound(mData)
        
        If UBR <= 0 Then
            MsgBox "Vùng chọn cần có ít nhất 2 dòng để thực hiện sắp xếp.", 48, "Thông báo"
            Exit Sub
        End If
        
        ' Khởi tạo Collator Tiếng Việt
        Dim oCollator As Object
        Dim aLocale As New com.sun.star.lang.Locale
        aLocale.Language = "vi"
        aLocale.Country = "VN"
        oCollator = CreateUnoService("com.sun.star.i18n.Collator")
        oCollator.loadDefaultCollator(aLocale, 0)
        
        ' 3. Tạo mảng phụ để lưu TOÀN BỘ DÒNG và Khóa sắp xếp
        Dim arr() As Variant
        ReDim arr(0 To UBR)
        Dim i As Long, j As Long
        
        For i = 0 To UBR
            Dim tenGoc As String
            ' Chỉ lấy chuỗi ở cột người dùng đã chỉ định để tạo khóa sắp xếp
            tenGoc = CStr(mData(i)(keyColIndex))
            Dim khoaSapXep As String
            khoaSapXep = TenHoLot(tenGoc)
            
            ' Lưu lại mảng gồm: [0] Toàn bộ dữ liệu dòng hiện tại, [1] Khóa sắp xếp
            arr(i) = Array(mData(i), khoaSapXep)
        Next i
        
        ' 4. Thuật toán sắp xếp (Hoán vị toàn bộ dòng)
        Dim temp As Variant
        For i = 0 To UBR - 1
            For j = i + 1 To UBR
                If oCollator.compareString(arr(i)(1), arr(j)(1)) = 1 Then
                    temp = arr(i)
                    arr(i) = arr(j)
                    arr(j) = temp
                End If
            Next j
        Next i
        
        ' 5. Đổ dữ liệu đã sắp xếp ngược lại mảng gốc
        For i = 0 To UBR
            mData(i) = arr(i)(0) ' Trả lại toàn bộ các cột của dòng đó
        Next i
        
        ' 6. Ghi dữ liệu đè lên Sheet
        oSel.setDataArray(mData)
        
        MsgBox "Tuyệt vời! Đã sắp xếp xong " & (UBR + 1) & " dòng dữ liệu theo đúng chuẩn tiếng Việt.", 64, "Hoàn tất"
    End Sub
    
    ' =========================================================
    ' CÁC HÀM HỖ TRỢ BÊN DƯỚI (Cần giữ lại để phục vụ Macro)
    ' =========================================================
    
    Function Del_Space(ByVal ChuoiData As String) As String
        ChuoiData = Trim(ChuoiData)
        While InStr(ChuoiData, "  ") > 0
            ChuoiData = Replace(ChuoiData, "  ", " ")
        Wend
        Del_Space = ChuoiData
    End Function
    
    Function TachHo(ByVal Str As String, Optional Kt As Variant) As String
        If IsMissing(Kt) Then Kt = True
        If Kt Then Str = Del_Space(Str)
        Dim spacePos As Integer
        spacePos = InStr(1, Str, " ")
        If Len(Str) = 0 Or spacePos = 0 Then TachHo = Str Else TachHo = Left(Str, spacePos - 1)
    End Function
    
    Function TachTen(ByVal Str As String, Optional Kt As Variant) As String
        If IsMissing(Kt) Then Kt = True
        If Kt Then Str = Del_Space(Str)
        Dim spacePos As Integer
        spacePos = InStrRev(Str, " ")
        If Len(Str) = 0 Or spacePos = 0 Then TachTen = Str Else TachTen = Right(Str, Len(Str) - spacePos)
    End Function
    
    Function TachChuLot(ByVal Str As String, Optional Kt As Variant) As String
        If IsMissing(Kt) Then Kt = True
        If Kt Then Str = Del_Space(Str)
        Dim ten As String, ho As String
        ten = TachTen(Str, False) : ho = TachHo(Str, False)
        If ho & " " & ten = Str Or ho = Str Then
            TachChuLot = ""
        Else
            TachChuLot = Mid(Str, Len(ho) + 2, Len(Str) - Len(ho) - Len(ten) - 2)
        End If
    End Function
    
    Function TenHoLot(ByVal Str As String) As String
        Str = Del_Space(Str)
        Dim ten As String, ho As String, lot As String
        ten = TachTen(Str, False) : ho = TachHo(Str, False) : lot = TachChuLot(Str, False)
        Dim Result As String
        Result = ""
        If Len(ten) > 0 Then Result = Result & ten & " "
        If Len(ho) > 0 Then Result = Result & ho & " "
        If Len(lot) > 0 Then Result = Result & lot
        TenHoLot = Trim(Result)
    End Function
    ' Hàm tự tạo thay thế cho InStrRev của VBA (Tìm kiếm từ phải sang trái)
    Function InStrRev(ByVal strCheck As String, ByVal strMatch As String) As Integer
        Dim i As Integer
        If Len(strMatch) = 0 Or Len(strCheck) = 0 Then
            InStrRev = 0
            Exit Function
        End If
        
        ' Chạy vòng lặp ngược từ cuối chuỗi lên đầu chuỗi
        For i = Len(strCheck) To 1 Step -1
            If Mid(strCheck, i, Len(strMatch)) = strMatch Then
                InStrRev = i
                Exit Function
            End If
        Next i
        
        InStrRev = 0 ' Trả về 0 nếu không tìm thấy
    End Function

    Cách thêm nút bấm vào thanh công cụ:
    1. Lưu mã lệnh: Mở LibreOffice Calc, chọn Tools > Macros > Edit Macros.
    2. Tìm đến mục My Macros > Standard > Module1. Dán toàn bộ đoạn mã trên vào khung soạn thảo rồi lưu lại (Ctrl+S). Đóng cửa sổ Macro.
    1.jpg
    1. Tạo nút trên thanh công cụ (Toolbar):
      • Trong Calc, chọn Tools > Customize...
      • Chuyển sang thẻ Toolbars.
      • Bên ô Target, chọn thanh công cụ bạn muốn hiển thị nút (ví dụ: Standard).
      • Bấm vào nút Add Command... (ở bên phải hoặc phía dưới tùy phiên bản).
      • Trong cửa sổ hiện ra, kéo xuống phần Category ở góc trái dưới cùng, chọn LibreOffice Macros > My Macros > Standard > Module1.
      • Ở cột Commands bên phải, chọn SapXepTenTiengViet_Click rồi nhấn Add.
    2. Tân trang cho nút bấm: Sau khi Add, lệnh sẽ nằm trong thanh công cụ của bạn. Bạn có thể chọn nó, bấm Modify > Rename... để đổi tên thành "Sắp Xếp Tên VN", và Modify > Change Icon... để chọn một icon đẹp mắt. Nhấn OK.

    2.jpg

    3.jpg

    Cách sử dụng: Bôi đen các cột cần sắp xếp -> Bấm cái nút bạn vừa tạo -> Xong!

    4.jpg
     

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

    Back
    Top Bottom