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
.BuildUpvẫ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ữUSDtrước khi quét macro. -
Xử lý tài liệu dung lượng lớn:
Lệnh
R_Equation.SelectvàApplication.ScreenUpdating = Truegiú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 sangApplication.ScreenUpdating = Falsevà bỏ dòng.Selectđể code chạy nhanh gấp nhiều lần.