Khi soạn tài liệu hay giáo án, việc sao chép công thức toán học dạng LaTeX ($...$ hoặc $$...$$) từ các chatbot AI hoặc Overleaf sang Microsoft Word là nhu cầu rất phổ biến. Tuy nhiên, nhiều người dùng macro VBA thường gặp lỗi hiển thị sai định dạng hoặc công thức không chịu render.

Bản chất vấn đề nằm ở sự khác biệt lớn về bộ phân tích cú pháp (Parser) giữa các thế hệ Word. Nắm được cơ chế này sẽ giúp bạn tối ưu hóa đoạn code VBA vừa ngắn gọn vừa chạy chính xác.

1. Cơ chế phân tích toán học giữa các phiên bản Word

Phiên bản Word Cơ chế xử lý toán học Xử lý dấu $ và $$ Cách tiếp cận tối ưu
Office 2019 / Microsoft 365 Tích hợp sẵn bộ parser LaTeX gốc bên cạnh UnicodeMath. Tự động nhận diện ranh giới. Lệnh .BuildUp tự động bóc tách cặp dấu $ hoặc $$ và chuyển đổi sang OMath. Không cần cắt chuỗi: Chỉ cần đưa cả cụm có chứa dấu $ vào Doc.OMaths.Add rồi gọi .BuildUp.
Office 2016 trở về trước (2013, 2010) Chỉ hỗ trợ thuần UnicodeMath (OMML cũ) hoặc MathType, hoàn toàn không có parser LaTeX gốc. Không hiểu cú pháp LaTeX và không nhận diện dấu đô la làm ranh giới công thức. Bắt buộc xử lý thủ công: Phải cắt bỏ dấu đô la bằng code (Mid), sau đó tự map/convert các ký hiệu toán sang UnicodeMath tương ứng.

2. Đoạn mã VBA chuẩn hóa cho Office 2019 & Microsoft 365

Vì bộ phân tích LaTeX của Word từ bản 2019 trở lên đã tự nhận diện dấu đô la làm biên giới toán học, việc dùng hàm cắt chuỗi Mid() là thao tác thừa và dễ gây lỗi lệch vị trí con trỏ Range.

Đoạn mã dưới đây được tối ưu gọn nhẹ, chỉ cần đưa nguyên khối văn bản chứa dấu $$ hoặc $ vào OMath để Word tự render. 

Bạn mở Word, bấm Alt + F11, vào menu Insert > Module rồi dán đoạn mã sau:

VBA

Sub ConvertAllInlineAndDisplayLatex_Realtime()
    Dim Doc As Document
    Dim R As Range
    Dim R_Equation As Range
    Dim Latex As String
    Dim countTotal As Long

    Set Doc = ActiveDocument
    countTotal = 0
    
    ' Bật cập nhật màn hình để theo dõi tiến trình
    Application.ScreenUpdating = True

    ' =======================================================
    ' GIAI ĐOẠN 1: TÌM VÀ CHUYỂN ĐỔI DẠNG ĐÔ LA ĐÔI $$...$$
    ' =======================================================
    Set R = Doc.Content
    With R.Find
        .ClearFormatting
        .Text = "\$$([!\$]@)\$$"
        .MatchWildcards = True
        .Forward = True
        .Wrap = wdFindStop
    End With

    Do While R.Find.Execute
        Set R_Equation = R.Duplicate
        Latex = R_Equation.Text
               
        
        ' Gán lại text thuần và dựng công thức OMath
        R_Equation.Text = Latex
        Doc.OMaths.Add R_Equation
        R_Equation.OMaths(1).BuildUp
        
        countTotal = countTotal + 1
        
        ' Cuộn màn hình và cập nhật tiến trình
        R_Equation.Select
        DoEvents
        Application.StatusBar = "Dang chuyen doi cong thuc $$: da xu ly" & countTotal & " muc..."
        
        ' Dời con trỏ tìm kiếm ra sau công thức vừa xử lý
        R.Start = R_Equation.End
    Loop

    ' =======================================================
    ' GIAI ĐOẠN 2: TÌM VÀ CHUYỂN ĐỔI DẠNG ĐÔ LA ĐƠN $...$
    ' =======================================================
    Set R = Doc.Content
    With R.Find
        .ClearFormatting
        .Text = "\$([!\$]@)\$"
        .MatchWildcards = True
        .Forward = True
        .Wrap = wdFindStop
    End With

    Do While R.Find.Execute
        Set R_Equation = R.Duplicate
        Latex = R_Equation.Text
                
        R_Equation.Text = Latex
        Doc.OMaths.Add R_Equation
        R_Equation.OMaths(1).BuildUp
        
        countTotal = countTotal + 1
        
        R_Equation.Select
        DoEvents
        Application.StatusBar = "Dang chuyen đoi cong thuc $: da xu ly " & countTotal & " muc..."
        
        R.Start = R_Equation.End
    Loop

    ' Trả lại trạng thái mặc định của Word
    Application.StatusBar = False
     MsgBox "Hoan tat! Tong cong da chuyen doi " & countTotal & " cong thuc.", vbInformation, "Thong Bao"
End Sub

3. Những lưu ý quan trọng khi triển khai

  • Thiết lập chế độ Equation sang LaTeX:

    Dù dùng Word đời mới, nếu trình biên tập công thức đang ghim mặc định ở chế độ UnicodeMath, lệnh .BuildUp vẫn không nhận mã TeX. Hãy vào thẻ Insert > Equation > tại nhóm công cụ Conversions, click chọn LaTeX.

  • Tránh xung đột ký tự tiền tệ USD:

    Pattern \$([!\$]@)\$ sẽ quét mọi đoạn text kẹp giữa 2 dấu $. Nếu văn bản có chứa đơn vị tiền tệ (ví dụ: tăng từ $20 lên $50), Word sẽ hiểu nhầm đó là công thức toán. Cần tìm và thay thế tạm thời ký hiệu $ tiền tệ thành chữ USD trước khi quét macro.

  • Xử lý tài liệu dung lượng lớn:

    Lệnh R_Equation.Select và Application.ScreenUpdating = True giúp giao diện chạy trực quan theo thời gian thực nhưng làm chậm tốc độ tổng thể. Đối với tài liệu vài chục trang, nên đổi sang Application.ScreenUpdating = False và bỏ dòng .Select để code chạy nhanh gấp nhiều lần.