在本文中,我將向您展示如何在沒有 MS Word 或 Office Interop 的情況下使用 C# 或 VB.NET 執行 MS Word 郵件合併。 Aspose.Words for .NET 是一個功能豐富且功能強大的 Word API,它提供了所有基本的以及擴展的 MS Word 郵件合併功能。它允許您在 Windows 窗體、ASP.NET Web 應用程序或任何 .NET/.NET Core 應用程序中生成信件、信封、報告、發票和其他類型的文檔。

本文涵蓋了我們的 .NET 郵件合併 API 的顯著功能,由以下部分組成:

什麼是郵件合併?

Mail Merge 是自動生成報告、信件、信封、發票和其他類型文檔的方式。 MS Word 中的郵件合併允許您創建包含合併字段的模板文檔,然後使用數據源中的記錄填充這些字段。要了解郵件合併,假設您必須向十個不同的人發送一封信,並且只有姓名和地址字段需要更新。在這種情況下,只需創建一個字母模板,然後通過使用數據源填充名稱和地址合併字段來動態生成字母。

郵件合併的數據源

郵件合併的數據可以從任何數據源(如 XML、JSON 或數據庫)中獲取。就 Aspose.Words for .NET 而言,您可以使用 ADO.NET 支持的任何數據源。數據可以加載到 DataSet、DataTable、DataView 或值數組中。

為郵件合併準備模板

郵件合併模板是包含合併字段的文檔。當執行郵件合併時,這些字段隨後會填充數據源中的數據。模板文檔不需要是模板格式,可以是DOC/DOCX文檔。這就是您可以為郵件合併準備模板的方法。

  • 打開您的文檔或在 MS Word 中創建一個新文檔。
  • 將光標置於要添加合併字段的位置。
  • 從插入菜單中選擇字段選項。
  • 從字段名稱列表中,選擇 MergeField。
  • 在字段名稱中輸入合併字段的名稱,然後按確定。
  • 保存文檔。

以下是示例模板文檔的截圖。

郵件合併模板

.NET 郵件合併 API - 安裝

Aspose.Words for .NET 可以通過以下方式下載或安裝:

使用 C# 在 Word 文檔中執行郵件合併

準備好模板後,您可以執行郵件合併以生成文檔。以下是在上述模板上執行郵件合併的步驟。

以下代碼示例顯示如何使用 C# 中的值數組執行 MS Word 郵件合併。

// 如需完整示例和數據文件,請訪問 https://github.com/aspose-words/Aspose.Words-for-.NET
// 文檔目錄的路徑。
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 
// 打開現有文檔。
Document doc = new Document(dataDir + "MailMerge.ExecuteArray.doc");

// 修剪尾隨和前導空格郵件合併值
doc.MailMerge.TrimWhitespaces = false;

// 使用用戶數據填充文檔中的字段。
doc.MailMerge.Execute(
    new string[] { "FullName", "Company", "Address", "Address2", "City" },
    new object[] { "James Bond", "MI5 Headquarters", "Milbank", "", "London" });

dataDir = dataDir + "MailMerge.ExecuteArray_out.doc";
// 將 Word 格式的文檔發送到客戶端瀏覽器,並可選擇保存到磁盤或在當前瀏覽器中打開。
doc.Save(dataDir);

郵件合併後的 Word 文檔

在 C# 中執行郵件合併

在 C# 中使用 XML 數據源執行郵件合併

XML 文件廣泛用於保存和導入/導出數據。 Aspose.Words for .NET 也支持 XML 作為郵件合併的數據源。只需將 XML 讀入 DataSet 對象並執行郵件合併。以下是我們將要使用的示例 XML 文件。

<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>

以下代碼示例從 XML 數據源獲取數據並使用 C# 執行郵件合併。

// 如需完整示例和數據文件,請訪問 https://github.com/aspose-words/Aspose.Words-for-.NET
// 文檔目錄的路徑。
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 

// 創建數據集並讀取 XML。
DataSet customersDs = new DataSet();
customersDs.ReadXml(dataDir + "Customers.xml");

string fileName = "TestFile XML.doc";
// 打開模板文檔。
Document doc = new Document(dataDir + fileName);

// 執行郵件合併以使用 DataTable 使用來自 XML 的數據填充模板。
doc.MailMerge.Execute(customersDs.Tables["Customer"]);

dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
// 保存輸出文檔。
doc.Save(dataDir);

下面是將用 XML 數據填充的郵件合併 模板

XML 的郵件合併模板

以下是執行郵件合併後得到的結果 Word 文檔的第 1 頁。

在 C# 中使用 XML 執行郵件合併

合併字段的自定義格式

Aspose.Words for .NET 讓您在執行期間更好地控制郵件合併。 MailMerge.FieldMergingCallback 屬性允許您在遇到任何合併字段時自定義郵件合併。 MailMerge.FieldMergingCallback 接受實現 IFieldMergingCallback.FieldMergingIFieldMergingCallback.ImageFieldMerging 方法的類。

以下代碼示例顯示如何自定義郵件合併操作並將格式應用於 此模板 中的單元格。

// 如需完整示例和數據文件,請訪問 https://github.com/aspose-words/Aspose.Words-for-.NET
// 文檔目錄的路徑。
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 
Document doc = new Document(dataDir + "MailMerge.AlternatingRows.doc");

// 為 MergeField 事件添加處理程序。
doc.MailMerge.FieldMergingCallback = new HandleMergeFieldAlternatingRows();

// 執行與區域的郵件合併。
DataTable dataTable = GetSuppliersDataTable();
doc.MailMerge.ExecuteWithRegions(dataTable);
dataDir = dataDir + "MailMerge.AlternatingRows_out.doc";
doc.Save(dataDir);

以下是 HandleMergeFieldAlternatingRows 類的實現。

// 如需完整示例和數據文件,請訪問 https://github.com/aspose-words/Aspose.Words-for-.NET
private class HandleMergeFieldAlternatingRows : IFieldMergingCallback
{
    ///<summary>
    /// 為文檔中遇到的每個合併字段調用。
    /// 我們可以將一些數據返回給郵件合併引擎或者做一些事情
    ///else 同文件。在這種情況下,我們修改單元格格式。
    ///</summary>
    void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
    {
        if (mBuilder == null)
            mBuilder = new DocumentBuilder(e.Document);

        // 這樣我們就抓住了新行的開頭。
        if (e.FieldName.Equals("CompanyName"))
        {
            // 根據行號是偶數還是奇數選擇顏色。
            Color rowColor;
            if (IsOdd(mRowIdx))
                rowColor = Color.FromArgb(213, 227, 235);
            else
                rowColor = Color.FromArgb(242, 242, 242);

            // 目前無法為整行設置單元格屬性,
            // 所以我們必須遍歷行中的所有單元格。
           for (int colIdx = 0; colIdx < 4; colIdx++)
            {
                mBuilder.MoveToCell(0, mRowIdx, colIdx, 0);
                mBuilder.CellFormat.Shading.BackgroundPatternColor = rowColor;
            }

            mRowIdx++;
        }
    }

    void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
    {
        // 沒做什麼。
    }

    private DocumentBuilder mBuilder;
    private int mRowIdx;
}     
///<summary>
/// 如果值為奇數則返回真;如果值為偶數,則為 false。
///</summary>
private static bool IsOdd(int value)
{
    // 代碼有點複雜,不過自動轉換成VB是不行的。
    return ((value / 2) * 2).Equals(value);
}      
///<summary>
/// 創建 DataTable 並用數據填充它。
/// 在現實生活中,這個 DataTable 應該從數據庫中填充。
///</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;
}

使用 C# 與區域合併郵件

當您需要填充和重複 Word 文檔中的特定區域時,可能會出現這種情況。對於這種情況,您可以使用區域郵件合併。要創建區域,您需要指定區域的開始和結束,然後 Mail Megre 將為數據源中的每條記錄重複該區域。例如,以下模板包含兩個區域,Orders 和 OrderDetails,分別具有合併字段 «TableStart:Orders»、«TableEnd:Orders» 和 «TableStart:OrderDetails»、«TableEnd:OrderDetails»。

郵件與區域合併

以下是針對上述模板在區域上執行Mail Megre的代碼示例。

// 如需完整示例和數據文件,請訪問 https://github.com/aspose-words/Aspose.Words-for-.NET
// 文檔目錄的路徑。
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting();
string fileName = "MailMerge.ExecuteWithRegions.doc";
Document doc = new Document(dataDir + fileName);
 
// 使用 DataTable 作為數據源。
int orderId = 10444;
DataTable orderTable = GetTestOrder(orderId);
doc.MailMerge.ExecuteWithRegions(orderTable);
 
// 您可以創建一個 DataView 來進行自定義排序或篩選,然後進行郵件合併,而不是使用 DataTable。
DataView orderDetailsView = new DataView(GetTestOrderDetails(orderId));
orderDetailsView.Sort = "ExtendedPrice DESC";
 
// 執行郵件合併操作。
doc.MailMerge.ExecuteWithRegions(orderDetailsView);
 
// 保存合併的文檔。
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);
doc.Save(dataDir);

下面是從數據庫中讀取數據的方法。

// 如需完整示例和數據文件,請訪問 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>
/// 創建連接、命令的實用函數, 
/// 執行命令並將結果返回到 DataTable 中。
///</summary>
private static DataTable ExecuteDataTable(string commandText)
{
    // 打開數據庫連接。
    string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
        RunExamples.GetDataDir_Database() + "Northwind.mdb";
    OleDbConnection conn = new OleDbConnection(connString);
    conn.Open();

    // 創建並執行命令。
    OleDbCommand cmd = new OleDbCommand(commandText, conn);
    OleDbDataAdapter da = new OleDbDataAdapter(cmd);
    DataTable table = new DataTable();
    da.Fill(table);

    // 關閉數據庫。
    conn.Close();

    return table;
}

嵌套郵件合併區域

大多數情況下,我們在數據源中擁有的數據以關係的形式出現。例如,表“Order”將與“OrderDetails”建立一對多關係,後者將保存訂單中的項目記錄。為了處理這種父子關係,使用了嵌套的郵件合併。以下是一個非常適合這種情況的示例發票模板

帶區域的郵件合併模板

以下是我們將用於嵌套郵件合併的示例 XML 數據源。

<?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>

而此 XML 的 OrderSchema.xsd 是:

<?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>

以下代碼示例用於使用 C# 執行嵌套郵件合併。

// 如需完整示例和數據文件,請訪問 https://github.com/aspose-words/Aspose.Words-for-.NET
// 文檔目錄的路徑。
string dataDir = RunExamples.GetDataDir_MailMergeAndReporting(); 
	 
// 創建數據集並讀取 XML。
DataSet pizzaDs = new DataSet();
	 
// Datatable.TableNames 和 DataSet.Relations 由 .NET 通過 ReadXml 隱式定義。
pizzaDs.ReadXml(dataDir + "CustomerData.xml");
string fileName = "Invoice Template.doc";

// 打開模板文檔。
Document doc = new Document(dataDir + fileName);
	 
// 修剪尾隨和前導空格郵件合併值。
doc.MailMerge.TrimWhitespaces = false;
	 
// 執行與區域的嵌套郵件合併。
doc.MailMerge.ExecuteWithRegions(pizzaDs);
dataDir = dataDir + RunExamples.GetOutputFilePath(fileName);

// 將輸出保存到文件。
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);

郵件合併後的 Word 文檔

下面是執行郵件合併後生成的 Word 文檔的第一頁。

郵件合併後的 Word 文檔

結論

Aspose.Words for .NET 是一個功能豐富的郵件合併 API,它為 .NET 應用程序提供所有標準以及擴展的郵件合併功能。只需幾行代碼,您就可以從各種類型的數據源無縫創建簡單或複雜的報告。您可以從 文檔 中閱讀有關 .NET 郵件合併 API 的更多信息。要了解 Aspose.Words for .NET,請從 開發人員指南GitHub 代碼示例開始。

免費試用 Aspose.Words for .NET

您可以獲得一個免費的臨時許可證,可以不受任何限制地試用 Aspose.Words for .NET。 立即獲取臨時許可證

也可以看看