在本文中,我将向您展示如何在没有 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 Mail Merge 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>
/// 如果值为奇数,则返回 true;如果值是偶数,则为 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 应用程序提供所有标准以及扩展的邮件合并功能。只需几行代码,您就可以从各种类型的数据源无缝地创建简单或复杂的报告。您可以从 documentation 中阅读有关 .NET Mail Merge API 的更多信息。要了解 Aspose.Words for .NET,请从 开发人员指南GitHub 代码示例开始。

免费试用 Aspose.Words for .NET

您可以获得免费的临时许可证来试用 Aspose.Words for .NET,没有任何限制。 立即获取您的临时许可证

也可以看看