Thay đổi định dạng số trang trong mục lục tự động bằng macro trong Word

Trong Microsoft Word, khi tự động tạo mục lục từ các tham chiếu, nếu tiêu đề chứa số thì không thể dễ dàng thay đổi định dạng số trang theo yêu cầu thông qua chức năng tìm kiếm và thay thế thông thường. Trong trường hợp này, ta có thể sử dụng macro VBA để xử lý các mã trường (field code).


Sub FormatTrangMucLuc()
    Dim toc As TableOfContents
    Dim fld As Field
    Dim viTriBatDau As Long, viTriKetThuc As Long
    Dim danhSachBatDau As New Collection
    Dim danhSachKetThuc As New Collection
    Dim idx As Long

    If ActiveDocument.TablesOfContents.Count = 0 Then
        MsgBox "Tài liệu hiện tại không có mục lục tự động.", vbInformation
        Exit Sub
    End If

    For Each toc In ActiveDocument.TablesOfContents
        For Each fld In toc.Range.Fields
            If InStr(1, fld.Code.Text, "PAGEREF", vbTextCompare) > 0 Then
                viTriBatDau = fld.Result.Start
                viTriKetThuc = LayViTriKetThuc(fld)
                ' Bỏ qua nếu đã được xử lý (kết thúc bằng chữ "trang")
                If ActiveDocument.Range(viTriKetThuc, viTriKetThuc + 1).Text <> "trang" Then
                    danhSachBatDau.Add viTriBatDau
                    danhSachKetThuc.Add viTriKetThuc
                End If
            End If
        Next fld
    Next toc

    ' Xử lý ngược từ cuối lên để tránh xô lệch vị trí
    For idx = danhSachBatDau.Count To 1 Step -1
        viTriKetThuc = CLng(danhSachKetThuc(idx))
        viTriBatDau = CLng(danhSachBatDau(idx))

        If ActiveDocument.Range(viTriKetThuc, viTriKetThuc + 1).Text <> "trang" Then
            ActiveDocument.Range(viTriKetThuc, viTriKetThuc).InsertAfter "trang"
        End If
        ActiveDocument.Range(viTriBatDau, viTriBatDau).InsertBefore "Trang "
    Next idx

    MsgBox "Đã cập nhật định dạng số trang trong mục lục thành ""Trang X trang"".", vbInformation
End Sub

Function LayViTriKetThuc(ByVal fld As Field) As Long
    Dim pos As Long
    For pos = fld.Result.End To fld.Result.End + 20
        If pos >= ActiveDocument.Content.End Then Exit For
        If ActiveDocument.Range(pos, pos + 1).Text = ChrW(21) Then
            LayViTriKetThuc = pos + 1
            Exit Function
        End If
    Next pos
    LayViTriKetThuc = fld.Result.End
End Function

Sau khi chạy macro, mục lục sẽ được cập nhật như sau:

  • Trước khi chạy:
    Chương 1: Giới thiệu....................15
  • Sau khi chạy:
    Chương 1: Giới thiệu....................Trang 15 trang

Lưu ý:

  • Khi nội dung tài liệu thay đổi làm ảnh hưởng đến số trang, cần chạy lại macro để cập nhật.
  • Nếu tài liệu đã hoàn tất nội dung, bạn có thể chuyển các trường trong mục lục thành văn bản bằng tổ hợp phím Ctrl+Alt+F9.

Một số đối tượng liên quan trong VBA:

  • { TOC ... }ActiveDocument.TablesOfContents
  • { INDEX ... }ActiveDocument.Indexes
  • Mục lục bảng biểu → ActiveDocument.TablesOfFigures
  • Đánh dấu (bookmark) → ActiveDocument.Bookmarks
  • Liên kết nhảy đến bookmark → ActiveDocument.Hyperlinks / Fields

Thẻ: Microsoft Word VBA macro Mục lục tự động Định dạng số trang

Đăng vào ngày 21 tháng 8 lúc 10:15