Trong bài viết này, tôi sẽ chỉ cho bạn cách thực hiện Trộn thư MS Word bằng C# hoặc VB.NET mà không cần MS Word hoặc Office Interop. Aspose.Words for .NET là một API Word mạnh mẽ và giàu tính năng, cung cấp tất cả các tính năng Hợp nhất thư MS Word cơ bản cũng như mở rộng. Nó cho phép bạn tạo thư, phong bì, báo cáo, hóa đơn và các loại tài liệu khác trong Windows Forms, ứng dụng web ASP.NET hoặc bất kỳ ứng dụng .NET/.NET Core nào.

Bao gồm các tính năng nổi bật của .NET Mail Merge API của chúng tôi, bài viết này bao gồm các phần sau:

Trộn thư là gì?

Mail Merge là cách tự động tạo báo cáo, thư, phong bì, hóa đơn và các loại tài liệu khác. Trộn thư trong MS Word cho phép bạn tạo một tài liệu mẫu có chứa các trường hợp nhất, sau đó điền các trường đó bằng cách sử dụng các bản ghi trong nguồn dữ liệu. Để hiểu về Trộn thư, giả sử bạn phải gửi thư cho mười người khác nhau và chỉ có các trường tên và địa chỉ là được cập nhật. Trong trường hợp như vậy, chỉ cần tạo một mẫu chữ cái và sau đó tự động tạo các chữ cái bằng cách điền các trường hợp nhất tên và địa chỉ bằng cách sử dụng nguồn dữ liệu.

Nguồn dữ liệu để trộn thư

Dữ liệu cho Trộn thư có thể được tìm nạp từ bất kỳ nguồn dữ liệu nào, chẳng hạn như XML, JSON hoặc cơ sở dữ liệu. Đối với Aspose.Words for .NET, bạn có thể sử dụng bất kỳ nguồn dữ liệu nào được ADO.NET hỗ trợ. Dữ liệu có thể được tải vào DataSet, DataTable, DataView hoặc một mảng giá trị.

Chuẩn bị mẫu để trộn thư

Mẫu Trộn Thư là tài liệu chứa các trường phối. Sau đó, các trường này được phổ biến với dữ liệu trong nguồn dữ liệu khi Trộn Thư được thực thi. Tài liệu mẫu không cần phải là định dạng mẫu và có thể là tài liệu DOC/DOCX. Đây là cách bạn có thể chuẩn bị mẫu cho Trộn Thư.

  • Mở tài liệu của bạn hoặc tạo một tài liệu mới trong MS Word.
  • Đặt con trỏ ở nơi bạn muốn thêm trường hợp nhất.
  • Từ menu Chèn, chọn tùy chọn Trường.
  • Từ danh sách Tên trường, chọn Hợp nhất Trường.
  • Nhập tên cho trường hợp nhất trong Tên trường và nhấn OK.
  • Lưu tài liệu.

Sau đây là ảnh chụp màn hình của tài liệu mẫu mẫu.

Mẫu trộn thư

.NET Mail Merge API - Cài đặt

Có thể tải xuống hoặc cài đặt Aspose.Words for .NET bằng các cách sau:

Thực hiện trộn thư trong tài liệu Word bằng C#

Khi bạn đã có sẵn mẫu, bạn có thể thực hiện Trộn thư để tạo tài liệu. Sau đây là các bước để thực hiện Trộn thư trên mẫu đã đề cập ở trên.

Mẫu mã sau đây cho biết cách thực hiện Hợp nhất Thư MS Word bằng cách sử dụng một mảng giá trị trong C#.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
// Đường dẫn đến thư mục tài liệu.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 
// Mở một tài liệu hiện có.
Document doc = new Document(dataDir + "MailMerge.ExecuteArray.doc");

// Cắt bỏ các giá trị trộn thư ở cuối và khoảng trắng ở đầu
doc.MailMerge.TrimWhitespaces = false;

// Điền vào các trường trong tài liệu với dữ liệu người dùng.
doc.MailMerge.Execute(
    new string[] { "FullName", "Company", "Address", "Address2", "City" },
    new object[] { "James Bond", "MI5 Headquarters", "Milbank", "", "London" });

dataDir = dataDir + "MailMerge.ExecuteArray_out.doc";
// Gửi tài liệu ở định dạng Word tới trình duyệt máy khách với tùy chọn lưu vào đĩa hoặc mở bên trong trình duyệt hiện tại.
doc.Save(dataDir);

Tài liệu Word sau khi trộn thư

Thực hiện trộn thư trong C#

Thực hiện Hợp nhất Thư bằng Nguồn Dữ liệu XML trong C#

Các tệp XML được sử dụng rộng rãi để giữ cũng như nhập/xuất dữ liệu. Aspose.Words for .NET cũng hỗ trợ XML làm nguồn dữ liệu cho Trộn Thư. Chỉ cần đọc XML vào đối tượng DataSet và thực hiện Trộn thư. Sau đây là tệp XML mẫu mà chúng tôi sẽ sử dụng.

<customers>
<customer Name="John Ben Jan" ID="1" Domain="History" City="Boston"/>
<customer Name="Lisa Lane" ID="2" Domain="Chemistry" City="LA"/>
<customer Name="Dagomir Zits" ID="3" Domain="Heraldry" City="Milwaukee"/>
<customer Name="Sara Careira Santy" ID="4" Domain="IT" City="Miami"/>
</customers>

Mẫu mã sau tìm nạp dữ liệu từ một nguồn dữ liệu XML và thực hiện Phối thư bằng C#.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
// Đường dẫn đến thư mục tài liệu.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 

// Tạo Bộ dữ liệu và đọc XML.
DataSet customersDs = new DataSet();
customersDs.ReadXml(dataDir + "Customers.xml");

string fileName = "TestFile XML.doc";
// Mở một tài liệu mẫu.
Document doc = new Document(dataDir + fileName);

// Thực hiện trộn thư để điền vào mẫu bằng dữ liệu từ XML bằng DataTable.
doc.MailMerge.Execute(customersDs.Tables["Customer"]);

dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
// Lưu tài liệu đầu ra.
doc.Save(dataDir);

Dưới đây là Trộn thư mẫu sẽ được điền bằng dữ liệu XML.

Mẫu trộn thư cho XML

Sau đây là trang 1 của tài liệu Word kết quả mà chúng tôi nhận được sau khi thực hiện Trộn thư.

Thực thi trộn thư với XML trong C#

Định dạng tùy chỉnh của các trường hợp nhất

Aspose.Words dành cho .NET cung cấp cho bạn nhiều quyền kiểm soát hơn đối với Trộn thư trong quá trình thực thi. Thuộc tính MailMerge.FieldMergingCallback cho phép bạn tùy chỉnh Trộn thư khi gặp bất kỳ trường trộn nào. MailMerge.FieldMergingCallback chấp nhận lớp triển khai các phương thức IFieldMergingCallback.FieldMergingIFieldMergingCallback.ImageFieldMerging.

Mẫu mã sau đây cho biết cách tùy chỉnh thao tác Trộn thư và áp dụng định dạng cho các ô trong mẫu này.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
// Đường dẫn đến thư mục tài liệu.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 
Document doc = new Document(dataDir + "MailMerge.AlternatingRows.doc");

// Thêm trình xử lý cho sự kiện MergeField.
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldAlternatingRows();

// Thực hiện trộn thư với các vùng.
DataTable dataTable = GetSuppliersDataTable();
doc.MailMerge.ExecuteWithRegions(dataTable);
dataDir = dataDir + "MailMerge.AlternatingRows_out.doc";
doc.Save(dataDir);

Sau đây là cách triển khai lớp HandleMergeFieldAlternatingRows.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
private class HandleMergeFieldAlternatingRows : IFieldMergingCallback
{
    ///<summary>
    /// Được gọi cho mọi trường hợp nhất gặp phải trong tài liệu.
    /// Chúng tôi có thể trả lại một số dữ liệu cho công cụ trộn thư hoặc làm điều gì đó
    /// Khác với tài liệu. Trong trường hợp này, chúng tôi sửa đổi định dạng ô.
    ///</summary>
    void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
    {
        if (mBuilder == null)
            mBuilder = new DocumentBuilder(e.Document);

        // Bằng cách này, chúng tôi bắt đầu một hàng mới.
        if (e.FieldName.Equals("CompanyName"))
        {
            // Chọn màu tùy thuộc vào số hàng là chẵn hay lẻ.
            Color rowColor;
            if (IsOdd(mRowIdx))
                rowColor = Color.FromArgb(213, 227, 235);
            else
                rowColor = Color.FromArgb(242, 242, 242);

            // Hiện tại không có cách nào để đặt thuộc tính ô cho toàn bộ hàng,
            // Vì vậy, chúng ta phải lặp lại tất cả các ô trong hàng.
           for (int colIdx = 0; colIdx < 4; colIdx++)
            {
                mBuilder.MoveToCell(0, mRowIdx, colIdx, 0);
                mBuilder.CellFormat.Shading.BackgroundPatternColor = rowColor;
            }

            mRowIdx++;
        }
    }

    void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
    {
        // Không làm gì cả.
    }

    private DocumentBuilder mBuilder;
    private int mRowIdx;
}     
///<summary>
/// Trả về true nếu giá trị là số lẻ; sai nếu giá trị là số chẵn.
///</summary>
private static bool IsOdd(int value)
{
    // Mã này hơi phức tạp, nhưng nếu không thì chuyển đổi tự động sang VB không hoạt động.
    return ((value / 2) * 2).Equals(value);
}      
///<summary>
/// Tạo DataTable và điền dữ liệu vào.
/// Trong thực tế, DataTable này phải được điền từ cơ sở dữ liệu.
///</summary>
private static DataTable GetSuppliersDataTable()
{
    DataTable dataTable = new DataTable("Suppliers");
    dataTable.Columns.Add("CompanyName");
    dataTable.Columns.Add("ContactName");
   for (int i = 0; i < 10; i++)
    {
        DataRow datarow = dataTable.NewRow();
        dataTable.Rows.Add(datarow);
        datarow[0] = "Company " + i.ToString();
        datarow[1] = "Contact " + i.ToString();
    }
    return dataTable;
}

Trộn thư với các khu vực bằng C#

Có thể xảy ra trường hợp bạn cần điền và lặp lại một vùng cụ thể trong tài liệu Word. Đối với trường hợp như vậy, bạn có thể sử dụng Trộn thư với các vùng. Để tạo một vùng, bạn cần chỉ định điểm đầu và điểm cuối của vùng, sau đó Mail Megre sẽ lặp lại vùng đó cho từng bản ghi trong nguồn dữ liệu. Ví dụ: Mẫu sau chứa hai vùng, Đơn hàng và Chi tiết đơn hàng với các trường hợp nhất «TableStart:Orders», «TableEnd:Orders» và «TableStart:OrderDetails», «TableEnd:OrderDetails» tương ứng.

Trộn thư với các khu vực

Sau đây là mẫu mã thực hiện Mail Megre trên các vùng cho mẫu nêu trên.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
// Đường dẫn đến thư mục tài liệu.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
string fileName = "MailMerge.ExecuteWithRegions.doc";
Document doc = new Document(dataDir + fileName);
 
// Sử dụng DataTable làm nguồn dữ liệu.
int orderId = 10444;
DataTable orderTable = GetTestOrder(orderId);
doc.MailMerge.ExecuteWithRegions(orderTable);
 
// Thay vì sử dụng DataTable, bạn có thể tạo một DataView để sắp xếp hoặc lọc tùy chỉnh, rồi phối thư.
DataView orderDetailsView = new DataView(GetTestOrderDetails(orderId));
orderDetailsView.Sort = "ExtendedPrice DESC";
 
// Thực hiện thao tác trộn thư.
doc.MailMerge.ExecuteWithRegions(orderDetailsView);
 
// Lưu tài liệu đã hợp nhất.
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
doc.Save(dataDir);

Sau đây là các phương pháp để đọc dữ liệu từ cơ sở dữ liệu.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
private static DataTable GetTestOrder(int orderId)
{
    DataTable table = ExecuteDataTable(string.Format(
        "SELECT * FROM AsposeWordOrders WHERE OrderId = {0}", orderId));
    table.TableName = "Orders";
    return table;
}
private static DataTable GetTestOrderDetails(int orderId)
{
    DataTable table = ExecuteDataTable(string.Format(
        "SELECT * FROM AsposeWordOrderDetails WHERE OrderId = {0} ORDER BY ProductID", orderId));
    table.TableName = "OrderDetails";
    return table;
}
///<summary>
/// Chức năng tiện ích tạo kết nối, lệnh, 
/// Thực thi lệnh và trả về kết quả trong DataTable.
///</summary>
private static DataTable ExecuteDataTable(string commandText)
{
    // Mở kết nối cơ sở dữ liệu.
    string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
        RunExamples.GetDataDir_Database() + "Northwind.mdb";
    OleDbConnection conn = new OleDbConnection(connString);
    conn.Open();

    // Tạo và thực hiện một lệnh.
    OleDbCommand cmd = new OleDbCommand(commandText, conn);
    OleDbDataAdapter da = new OleDbDataAdapter(cmd);
    DataTable table = new DataTable();
    da.Fill(table);

    // Đóng cơ sở dữ liệu.
    conn.Close();

    return table;
}

Khu vực trộn thư lồng nhau

Thông thường, dữ liệu chúng ta có trong nguồn dữ liệu ở dạng các mối quan hệ. Ví dụ: bảng “Đơn hàng” sẽ có mối quan hệ một-nhiều với “Chi tiết đơn hàng” sẽ lưu giữ hồ sơ của các mặt hàng trong một đơn hàng. Để xử lý các mối quan hệ cha-con như vậy, Trộn thư lồng nhau được sử dụng. Sau đây là mẫu mẫu hóa đơn rất phù hợp với trường hợp này.

Mẫu trộn thư với các khu vực

Sau đây là nguồn dữ liệu XML mẫu mà chúng tôi sẽ sử dụng cho Phối thư lồng nhau.

<?xml version="1.0" encoding="utf-8"?>
<Orders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="OrdersSchema.xsd">
  <Order>
    <Number>23</Number>
    <Address>Nelson Street</Address>
    <Suburb>Howick</Suburb>
    <City>Auckland</City>
    <Phonenumber>543 1234</Phonenumber>
    <Date>03/01/2010</Date>
    <Total>14.00</Total>
    <Item>
      <Name>BBQ Chicken Pizza</Name>
      <Price>6.00</Price>
      <Quantity>1</Quantity>
      <ItemTotal>6.00</ItemTotal>
    </Item>
    <Item>
      <Name>1.5 Litre Coke</Name>
      <Price>4.00</Price>
      <Quantity>2</Quantity>
      <ItemTotal>8.00</ItemTotal>
    </Item>
  </Order>
  <Order>
    <Number>10</Number>
    <Address>Parkville Avenue</Address>
    <Suburb>Pakuranga</Suburb>
    <City>Auckland</City>
    <Phonenumber>548 7342</Phonenumber>
    <Date>05/03/2010</Date>
    <Total>6.00</Total>
    <Item>
      <Name>Hawaiian Pizza</Name>
      <Price>4.00</Price>
      <Quantity>1</Quantity>
      <ItemTotal>4.00</ItemTotal>
    </Item>
    <Item>
      <Name>Fries</Name>
      <Price>1.00</Price>
      <Quantity>2</Quantity>
      <ItemTotal>2.00</ItemTotal>
    </Item>
  </Order>
</Orders>

Trong khi đó, OrderSchema.xsd cho XML này là:

<?xml version="1.0" encoding ="utf-8"?>
<xs:schema id="OrdersSchema"  xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="Orders">
 <xs:complexType>
 <xs:sequence>
  <xs:element name="Order">
  <xs:complexType>
  <xs:sequence>
  <xs:element name="Number"/>
  <xs:element name="Address"/>
  <xs:element name="Suburb"/>
  <xs:element name="City"/>
  <xs:element name="Phonenumber">
  <xs:element name="Date"/>
  <xs:element name="Total"/>
  <xs:element name="Item">
   <xs:complexType>
   <xs:sequence>
   <xs:element name="Name"/>
   <xs:element name="Price"/>
   <xs:element name="Quantity"/>
   <xs:element name="ItemTotal"/>
   </xs:sequence>
  </xs:complexType>
  </xs:element>
  </xs:sequence>
  </xs:complexType>
 </xs:element>
 </xs:sequence>
 </xs:complexType>
 </xs:element>
</xs:schema>

Mẫu mã sau đây được sử dụng để thực hiện Phối thư lồng nhau bằng C#.

// Để biết các ví dụ và tệp dữ liệu đầy đủ, vui lòng truy cập https://github.com/aspose-words/Aspose.Words-for-.NET
// Đường dẫn đến thư mục tài liệu.
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 
	 
// Tạo Bộ dữ liệu và đọc XML.
DataSet pizzaDs = new DataSet();
	 
// Datatable.TableNames và DataSet.Relations được định nghĩa hoàn toàn bởi .NET thông qua ReadXml.
pizzaDs.ReadXml(dataDir + "CustomerData.xml");
string fileName = "Invoice Template.doc";

// Mở tài liệu mẫu.
Document doc = new Document(dataDir + fileName);
	 
// Cắt bỏ các giá trị trộn thư ở cuối và khoảng trắng ở đầu.
doc.MailMerge.TrimWhitespaces = false;
	 
// Thực hiện trộn thư lồng nhau với các vùng.
doc.MailMerge.ExecuteWithRegions(pizzaDs);
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);

// Lưu đầu ra vào tập tin.
doc.Save(dataDir);

Debug.Assert(doc.MailMerge.GetFieldNames().Length == 0, "There was a problem with mail merge");
Console.WriteLine("\nMail merge performed with nested data successfully.\nFile saved at " + dataDir);

Tài liệu Word sau khi trộn thư

Dưới đây là trang đầu tiên của tài liệu Word thu được sau khi thực hiện Trộn thư.

Tài liệu Word sau khi trộn thư

Sự kết luận

Aspose.Words for .NET là một API trộn thư giàu tính năng cung cấp tất cả các tính năng trộn thư tiêu chuẩn cũng như mở rộng cho các ứng dụng .NET. Trong một vài dòng mã, bạn có thể tạo các báo cáo đơn giản hoặc phức tạp từ nhiều loại nguồn dữ liệu khác nhau một cách liền mạch. Bạn có thể đọc thêm về .NET Mail Merge API từ tài liệu. Để tìm hiểu về Aspose.Words for .NET, hãy bắt đầu với hướng dẫn dành cho nhà phát triển và mẫu mã GitHub.

Dùng thử miễn phí Aspose.Words for .NET

Bạn có thể nhận giấy phép tạm thời miễn phí để dùng thử Aspose.Words for .NET mà không có bất kỳ giới hạn nào. Nhận giấy phép tạm thời của bạn ngay bây giờ.

Xem thêm