Khi làm Mail Merge (trộn thư) trong Word với danh sách dài hàng trăm học sinh, sinh viên, mặc định Word sẽ gộp tất cả vào một file duy nhất. Việc ngồi cắt thủ công từng trang, lưu tên theo từng người là một "cực hình".

1. Bản chất và Cơ chế hoạt động của Code

Trước khi copy code về dùng, anh em cần hiểu bản chất cách đoạn code này vận hành để khi gặp lỗi có thể tự sửa (DIY):

  1. Tự động định vị đường dẫn (Dynamic Path): Thay vì cố định đường dẫn (Hardcode), code sử dụng ThisDocument.Path để lấy vị trí của file Word hiện tại. File Excel dữ liệu (DSHS.xlsx) và thư mục lưu file (\DS\) sẽ đi theo file Word này. Bạn mang thư mục này đi máy nào cũng chạy được, không lo lỗi đường dẫn.

  2. Tự động tạo thư mục: Kiểm tra nếu thư mục \DS\ chưa tồn tại, code dùng lệnh MkDir để tự tạo mới, tránh lỗi runtime.

  3. Vòng lặp Mail Merge đơn lẻ: Thay vì chạy một lệnh trộn cho tất cả, code ép biến .ActiveRecord, .FirstRecord, .LastRecord bằng nhau và chạy vòng lặp For...Next. Bản chất là bắt Word trộn từng dòng dữ liệu một, xuất ra file tạm rồi xử lý.

  4. Cập nhật trường (Fields Update): Ép Word cập nhật lại toàn bộ các trường (như hình ảnh, mã số) trước khi lưu để tránh lỗi hiển thị dữ liệu cũ.

  5. Đổi tên và Xuất file kép: Dùng dữ liệu của cột title trong file Excel để làm tên file, sau đó lưu thành 2 bản: .docx.pdf.

2. Đoạn code VBA hoàn chỉnh (Đã sửa lỗi Font Comment)

Anh em nhấn Alt + F11 trong file Word, chèn một Module mới và dán đoạn code sau vào:

VBA
Sub Merge_ThuChaoDon_v3()
Dim MainDoc As Document, TargetDoc As Document
Dim dbPath As String
Dim recordNumber As Long, totalRecord As Long

' === ĐOẠN TỰ ĐỘNG LẤY ĐƯỜNG DẪN THAY CHO CONST ===
Dim SOURCE_FILE_PATH As String
Dim FOLDER_SAVED As String
Dim CurrentFolder As String

' Lấy thư mục hiện tại chứa file Word đang mở
CurrentFolder = ThisDocument.Path

' File Excel nằm chung thư mục với file Word
SOURCE_FILE_PATH = CurrentFolder & "\DSHS.xlsx"

' File xuất ra sẽ lưu vào thư mục "DS" nằm trong thư mục hiện tại
FOLDER_SAVED = CurrentFolder & "\DS\"

' Mẹo thực tế: Tự động tạo thư mục "DS" nếu trong máy chưa có để tránh lỗi Code
If Dir(FOLDER_SAVED, vbDirectory) = "" Then
    MkDir FOLDER_SAVED
End If
' =================================================

Set MainDoc = ActiveDocument
With MainDoc.MailMerge
    ' Kết nối nguồn dữ liệu từ file Excel, lấy dữ liệu từ Sheet có tên là DS
    .OpenDataSource Name:=SOURCE_FILE_PATH, SqlStatement:="SELECT * FROM [DS$]"

    totalRecord = .DataSource.RecordCount

    ' Vòng lặp chạy qua từng dòng dữ liệu trong file Excel
    For recordNumber = 1 To totalRecord

        With .DataSource
            .ActiveRecord = recordNumber
            .FirstRecord = recordNumber
            .LastRecord = recordNumber
        End With

        ' Trộn dữ liệu và xuất ra một file Word mới tạm thời
        .Destination = wdSendToNewDocument
        .Execute False

        Set TargetDoc = ActiveDocument

        ' Ép cập nhật ảnh/trường thông tin trước khi xuất
        TargetDoc.Fields.Update

        ' Lưu file theo đường dẫn tự động, lấy giá trị cột "title" làm tên file
        TargetDoc.SaveAs2 FOLDER_SAVED & .DataSource.DataFields("title").Value & ".docx", wdFormatDocumentDefault
        TargetDoc.ExportAsFixedFormat FOLDER_SAVED & .DataSource.DataFields("title").Value & ".pdf", exportformat:=wdExportFormatPDF

        ' Đóng file tạm thời lại và không lưu đè thay đổi
        TargetDoc.Close False
        Set TargetDoc = Nothing

    Next recordNumber
End With

Set MainDoc = Nothing
End Sub

3. Ưu điểm và Nhược điểm của giải pháp này

Để anh em cân nhắc trước khi áp dụng vào thực tế công việc:

Tiêu chí Ưu điểm Nhược điểm
Tính linh hoạt Không bị lỗi đường dẫn khi copy thư mục sang máy tính khác (máy đồng nghiệp, sếp). Tên file phụ thuộc hoàn toàn vào cột title, nếu cột này chứa ký tự đặc biệt (/, \, *,... ) code sẽ bị lỗi.
Độ tiện dụng Xuất đồng thời cả Word và PDF cùng lúc. Tự động tạo thư mục lưu trữ cực kỳ sạch sẽ. Tốc độ xử lý sẽ chậm nếu danh sách lên đến hàng ngàn dòng (do phải mở/đóng file liên tục).
Độ chuẩn xác Lệnh Fields.Update đảm bảo dữ liệu động (như hình ảnh chèn qua code) không bị lỗi. Phải đảm bảo tên Sheet trong file Excel chính xác là DS (khớp với đoạn [DS$]).

4. Các bước chuẩn bị để code chạy mượt mà

Để code chạy phát ăn ngay, anh em cấu trúc thư mục và file đúng như sau:

  • Bước 1: Tạo một thư mục bất kỳ (ví dụ: MailMerge_Project).

  • Bước 2: Lưu file Word chứa mẫu thư và đoạn code VBA này vào thư mục trên dưới định dạng .docm (Word Macro-Enabled Document).

  • Bước 3: Đặt file Excel dữ liệu vào chung thư mục đó, đổi tên file thành DSHS.xlsx.

  • Bước 4: Mở file Excel lên, đảm bảo tên Sheet chứa data tên là DS và có một cột tiêu đề tên là title (cột này dùng để đặt tên file, nên viết liền không dấu, không chứa ký tự đặc biệt).

  • Bước 5: Bấm F5 trong cửa sổ VBA và tận hưởng kết quả trong thư mục \DS\ tự động sinh ra.

Chúc anh em ứng dụng thành công! Nếu gặp lỗi trong quá trình chạy, hãy để lại bình luận phía dưới bản chất lỗi, tôi sẽ hỗ trợ giải đáp.