跳至页脚内容
USING IRONWORD

如何使用 IronWord 在 C# 中创建可填写表格模板

多年以来,.NET 团队需要大规模生成个性化的 Word 文档,只有两个真正的选择,没有一个是好的。

第一个选择是通过 COM 互操作自动化 Microsoft Word。它有效,直到它不再有效。 Word 互操作速度慢、易碎、每台机器都需要 Word 许可证,并且一旦尝试在没有安装 Word 的 Linux 容器、Azure Function 或任何服务器环境中运行就会崩溃。 大多数尝试过的团队最终都绕过去重写。

第二种是自定义查找和替换管道。以 XML 或文本方式读取 .docx,将占位符标记替换为真实值,然后保存结果。 这适用于简单的情况,但在真正的Word文档中会出错,因为这些文档使用复杂的字段结构,完全不像开发者期望找到的简单的{{FirstName}}标记。

现在,IronWord 支持原生邮件合并。 使用 Microsoft Word 设计的模板,使用与 Word 自身生成的相同的合并字段语法,直接从 .NET 代码填充,无需安装 Word。

该功能的作用

邮件合并引擎处理 Word 生产的两种合并字段格式:

  • 简单字段,格式为"FieldName",这是您直接在模板中输入 <> 时获得的
  • 复杂字段,Word 通过插入→快速部件→字段生成的多元素 XML 结构

模板可以包含单值占位符,每个文档被替换一次,以及由 "TableStart:Name" 和 "TableEnd:Name" 标记界定的重复区域,这些标记会扩展到每个数据记录的一个行。

第二部分是该特性赢得其位置的原因。 重复区域是如何将发票中的一个模板行扩展为一个 50 行的项目表,或如何将标签页中的一个联系槽位变为一个完整的 Avery 网格并从数据库填充。

来自 CRM 的个性化求职信

大多数团队首先通过销售运营接触到邮件合并。 CRM 保存着客户记录; 市场营销或销售运营需要发送个性化的求职信、欢迎包或续签通知。 模式很简单:一个模板,每个客户一行,一个个性化文档输出。

// Template: "Dear &laquo;FirstName&raquo;, thank you for your order of &laquo;Amount&raquo;..."
DataTable customers = LoadFromSalesforce();   // FirstName, LastName, Amount, ...

foreach (DataRow row in customers.Rows)
{
    var doc = new WordDocument("cover-letter-template.docx");
    doc.MailMerge.Execute(row);
    doc.SaveAs($"letters/{row["LastName"]}.docx");
}
// Template: "Dear &laquo;FirstName&raquo;, thank you for your order of &laquo;Amount&raquo;..."
DataTable customers = LoadFromSalesforce();   // FirstName, LastName, Amount, ...

foreach (DataRow row in customers.Rows)
{
    var doc = new WordDocument("cover-letter-template.docx");
    doc.MailMerge.Execute(row);
    doc.SaveAs($"letters/{row["LastName"]}.docx");
}
Imports System.Data

' Template: "Dear «FirstName», thank you for your order of «Amount»..."
Dim customers As DataTable = LoadFromSalesforce() ' FirstName, LastName, Amount, ...

For Each row As DataRow In customers.Rows
    Dim doc As New WordDocument("cover-letter-template.docx")
    doc.MailMerge.Execute(row)
    doc.SaveAs($"letters/{row("LastName")}.docx")
Next
$vbLabelText   $csharpLabel

数据源是一个 DataTable,这意味着任何加载到其中的内容(Salesforce、HubSpot、SQL Server、CSV、API 响应)无需额外的适配器代码就可成为邮件合并源。

具有重复行项目的发票

开发票是重复区域能力发挥作用的地方。发票模板带有标题(客户姓名、订单 ID、日期),一个行项目表的一行和一个页脚(总数)。 合并运行时,单个模板行扩展为每个产品的一行,无论订单是一个行项目还是五十个。

// Template:
//   Bill To: &laquo;CustomerName&raquo;  Order: &laquo;OrderId&raquo;
//   ┌──────────┬─────┬──────────┐
//   │ &laquo;TableStart:Items&raquo;&laquo;Product&raquo; │ &laquo;Qty&raquo; │ &laquo;LineTotal&raquo; &laquo;TableEnd:Items&raquo; │
//   └──────────┴─────┴──────────┘
//   Total: &laquo;Total&raquo;

var doc = new WordDocument("invoice-template.docx");

doc.MailMerge.ExecuteWithRegions(orderLineItems);  // one row per product
doc.MailMerge.Execute(new Dictionary<string, string>
{
    { "CustomerName", "Acme Industries" },
    { "OrderId",      "10444" },
    { "Total",        "$1,117.71" },
});

doc.SaveAs("invoice-10444.docx");
// Template:
//   Bill To: &laquo;CustomerName&raquo;  Order: &laquo;OrderId&raquo;
//   ┌──────────┬─────┬──────────┐
//   │ &laquo;TableStart:Items&raquo;&laquo;Product&raquo; │ &laquo;Qty&raquo; │ &laquo;LineTotal&raquo; &laquo;TableEnd:Items&raquo; │
//   └──────────┴─────┴──────────┘
//   Total: &laquo;Total&raquo;

var doc = new WordDocument("invoice-template.docx");

doc.MailMerge.ExecuteWithRegions(orderLineItems);  // one row per product
doc.MailMerge.Execute(new Dictionary<string, string>
{
    { "CustomerName", "Acme Industries" },
    { "OrderId",      "10444" },
    { "Total",        "$1,117.71" },
});

doc.SaveAs("invoice-10444.docx");
Imports System.Collections.Generic

' Template:
'   Bill To: «CustomerName»  Order: «OrderId»
'   ┌──────────┬─────┬──────────┐
'   │ «TableStart:Items»«Product» │ «Qty» │ «LineTotal» «TableEnd:Items» │
'   └──────────┴─────┴──────────┘
'   Total: «Total»

Dim doc As New WordDocument("invoice-template.docx")

doc.MailMerge.ExecuteWithRegions(orderLineItems)  ' one row per product
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
    {"CustomerName", "Acme Industries"},
    {"OrderId", "10444"},
    {"Total", "$1,117.71"}
})

doc.SaveAs("invoice-10444.docx")
$vbLabelText   $csharpLabel

相同的模式适用于报价单、采购订单、对帐单和任何可变长度列表位于固定形状页面内的文档。

Avery 标签页和信封

运输和运营团队从联系人名单生成标签和信封,布局(Avery 5160、5161、5163 及其国际等效模板)是已有几十年的标准化模板。 IronWord 直接填充它们:标签网格中的每个单元格都从单个 API 调用中提取适当的联系人。

// Template: a 3&times;10 Avery 5160 grid, each cell has &laquo;CONTACT_FULLNAME&raquo; / &laquo;CONTACT_ADDRESS&raquo;
var doc = new WordDocument("avery-5160.docx");

doc.MailMerge.Execute(new Dictionary<string, string>
{
    { "CONTACT_FULLNAME", "Jane Doe" },
    { "CONTACT_ADDRESS",  "100 Main Street, Boston, MA 02108" },
});

doc.SaveAs("labels-jane.docx");
// Template: a 3&times;10 Avery 5160 grid, each cell has &laquo;CONTACT_FULLNAME&raquo; / &laquo;CONTACT_ADDRESS&raquo;
var doc = new WordDocument("avery-5160.docx");

doc.MailMerge.Execute(new Dictionary<string, string>
{
    { "CONTACT_FULLNAME", "Jane Doe" },
    { "CONTACT_ADDRESS",  "100 Main Street, Boston, MA 02108" },
});

doc.SaveAs("labels-jane.docx");
Imports System.Collections.Generic

' Template: a 3×10 Avery 5160 grid, each cell has «CONTACT_FULLNAME» / «CONTACT_ADDRESS»
Dim doc As New WordDocument("avery-5160.docx")

doc.MailMerge.Execute(New Dictionary(Of String, String) From {
    {"CONTACT_FULLNAME", "Jane Doe"},
    {"CONTACT_ADDRESS", "100 Main Street, Boston, MA 02108"}
})

doc.SaveAs("labels-jane.docx")
$vbLabelText   $csharpLabel

对于可变长度的联系人列表,来自发票示例的 ExecuteWithRegions 模式适用:定义一个单元格为重复单元,其余的单元自动填充。

多区域报告

最强大的应用是多区域报告。 一个季度总结可能包含"顶级客户"和"顶级产品"部分,每个部分由自己的数据表驱动。 通过包含多个表的 DataSet,合并在单个调用中扩展了两个区域。

// Template:
//   Top Customers
//   &laquo;TableStart:Customers&raquo; &bull; &laquo;Name&raquo; | &laquo;City&raquo; | &laquo;Revenue&raquo; &laquo;TableEnd:Customers&raquo;
//   Top Products
//   &laquo;TableStart:Products&raquo;  &laquo;ProductName&raquo;: &laquo;Revenue&raquo;     &laquo;TableEnd:Products&raquo;

var ds = new DataSet();
ds.Tables.Add(topCustomers);   // TableName = "Customers"
ds.Tables.Add(topProducts);    // TableName = "Products"

var doc = new WordDocument("quarterly-report.docx");
doc.MailMerge.ExecuteWithRegions(ds);          // expands both regions
doc.MailMerge.Execute(new Dictionary<string, string>
{
    { "CompanyName", "Iron Software" },
    { "ReportDate",  "Q2 2026" },
});
doc.SaveAs("Q2-2026-report.docx");
// Template:
//   Top Customers
//   &laquo;TableStart:Customers&raquo; &bull; &laquo;Name&raquo; | &laquo;City&raquo; | &laquo;Revenue&raquo; &laquo;TableEnd:Customers&raquo;
//   Top Products
//   &laquo;TableStart:Products&raquo;  &laquo;ProductName&raquo;: &laquo;Revenue&raquo;     &laquo;TableEnd:Products&raquo;

var ds = new DataSet();
ds.Tables.Add(topCustomers);   // TableName = "Customers"
ds.Tables.Add(topProducts);    // TableName = "Products"

var doc = new WordDocument("quarterly-report.docx");
doc.MailMerge.ExecuteWithRegions(ds);          // expands both regions
doc.MailMerge.Execute(new Dictionary<string, string>
{
    { "CompanyName", "Iron Software" },
    { "ReportDate",  "Q2 2026" },
});
doc.SaveAs("Q2-2026-report.docx");
Imports System.Data
Imports System.Collections.Generic

' Template:
'   Top Customers
'   «TableStart:Customers» • «Name» | «City» | «Revenue» «TableEnd:Customers»
'   Top Products
'   «TableStart:Products»  «ProductName»: «Revenue»     «TableEnd:Products»

Dim ds As New DataSet()
ds.Tables.Add(topCustomers)   ' TableName = "Customers"
ds.Tables.Add(topProducts)    ' TableName = "Products"

Dim doc As New WordDocument("quarterly-report.docx")
doc.MailMerge.ExecuteWithRegions(ds)          ' expands both regions
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
    {"CompanyName", "Iron Software"},
    {"ReportDate", "Q2 2026"}
})
doc.SaveAs("Q2-2026-report.docx")
$vbLabelText   $csharpLabel

DataSet 中的每个 DataTable 按名称匹配其相应的"TableStart:..."区域,在同一次通过中填充标量字段以完成头部值。

对于具有此类文档工作流并等待干净 .NET 实现的团队,Iron SuiteIronWord、IronPDF、IronOCR、IronXL 和 IronBarcode 捆绑在一个许可证中。

开始免费试用,无需信用卡。

为什么这个方法有效

这方面与其他替代方案的区别在于以下几点:

原生 Word 语法。模板是在 Microsoft Word 设计的,使用 Word 已经提供的合并字段工具。 保存为 .docx,将文件交给 IronWord,合并运行。 没有专有模板语言,没有翻译层,团队在设计文档时没有单独的学习曲线。

简单和复杂字段格式。Word 根据字段的插入方式产生两种不同的字段结构。 IronWord 处理这两种结构,这意味着由不同团队成员以不同方式设计的现有模板都可以在不修改的情况下工作。

没有外部依赖库。该库完全在 .NET 上运行。 没有 Word 安装,没有 COM,没有 Office 许可证,没有互操作脆弱性。 在 Windows 开发机器上运行的同一代码完全可以在 Linux 容器、Azure Function 或无服务器构建代理中运行。

摘要

邮件合并在 .NET 文档工具领域长期处于空白,解决方法不尽人意且过时。 IronWord 的原生邮件合并填补了这一空白,其模型与 Word 的合并字段语法相似,支持简单值和重复区域,无需任何历史上与 .NET 文档自动化相关的部署负担。

对于需要大规模生成发票、标签、信函、合同和报告的团队,这是从单个模板到上千份个性化文档的最简约路径。

常见问题解答

什么是IronWord邮件合并?

IronWord邮件合并是一种功能,可以从.NET应用程序生成个性化Word文档,而无需安装Microsoft Word。

IronWord邮件合并可以大规模生成文档吗?

是的,IronWord邮件合并设计用于处理大规模生成个性化Word文档,非常适合大批量处理。

使用IronWord邮件合并需要安装Microsoft Word吗?

不,IronWord邮件合并不需要安装Microsoft Word,允许在.NET应用程序中无缝生成文档。

使用IronWord邮件合并可以生成哪些类型的文档?

IronWord邮件合并可以使用Word模板生成各种文档,包括发票、信件、标签和报告。

IronWord邮件合并如何与.NET集成?

IronWord邮件合并在.NET中得到本地支持,为开发者提供了一种简便高效的方法来实现邮件合并功能。

使用IronWord邮件合并相比传统方法有哪些好处?

使用IronWord邮件合并消除了对Microsoft Word的依赖,减少了对第三方软件的依赖,并为从.NET应用程序生成文档提供了可扩展的解决方案。

IronWord邮件合并可以用于生成报告吗?

是的,IronWord邮件合并可以用于从Word模板生成详细报告,适用于各种文档需求。

IronWord邮件合并适合自动化文档生成吗?

是的,IronWord邮件合并非常适合自动化文档生成,允许开发者在他们的.NET应用程序中以编程方式创建个性化文档。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我