How to Mail Merge Word Documents in C
IronWord 透過在 Word 範本中的 MERGEFIELD 替換碼填入您的資料來執行 C# 的合併郵件。這些資料從字典、DataSet 物件或重複區域表中提取,且不需 Microsoft Office Interop。在 Microsoft Word 或任何相容工具中建立的合併欄位可自動檢測。
郵件合併是大規模產生個性化文件的標準方法:如表格信件、發票、證書、合同和報告等,它們共用一個模板但因收件人不同而區別。 不需要手動編輯每個文件,您可以撰寫一個具有合併欄位的 .docx 範本,然後讓 IronWord 從資料來源中填入這些欄位。 每個操作皆可透過 WordDocument.MailMerge 進入點達成。
快速入門:郵件合併Word文件
載入包含 MERGEFIELD 替換碼的範本,將欄位名稱和值的字典傳遞給 Execute,並保存結果。
-
使用NuGet套件管理器安裝https://www.nuget.org/packages/IronWord
-
複製並運行這段程式碼片段。
WordDocument doc = new WordDocument("template.docx"); doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" }, { "Company", "Acme Corp" } }); doc.SaveAs("output.docx"); -
部署以在您的實時環境中測試
今天就開始在您的專案中使用IronWord,透過免費試用
最小工作流程(5 個步驟)
- 從NuGet下載Word郵件合併C#庫
- 建立一個含有
MERGEFIELD佔位符的Word模板 - 使用
WordDocument構造函式載入模板 - 使用您的資料來源調用
MailMerge.Execute或MailMerge.ExecuteWithRegions - 儲存填充過的文件
我如何從字典中進行郵件合併?
最簡單的資料來源是以合併欄位名稱為鍵的 IDictionary<string, string>。 Execute 會替換每個名稱與鍵匹配的欄位。
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "FirstName", "Jane" },
{ "LastName", "Smith" },
{ "Company", "Acme Corp" }
});
doc.SaveAs("output.docx");
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(new Dictionary<string, string>
{
{ "FirstName", "Jane" },
{ "LastName", "Smith" },
{ "Company", "Acme Corp" }
});
doc.SaveAs("output.docx");
Dim doc As New WordDocument("template.docx")
doc.MailMerge.Execute(New Dictionary(Of String, String) From {
{"FirstName", "Jane"},
{"LastName", "Smith"},
{"Company", "Acme Corp"}
})
doc.SaveAs("output.docx")
MailMerge.Options.CaseInsensitiveFieldNames = false 以要求精確大小寫匹配。)]}
您也可以提供兩組平行的字段名稱和值的序列:
doc.MailMerge.Execute(
new[] { "FirstName", "LastName" },
new[] { "Jane", "Smith" });
doc.MailMerge.Execute(
new[] { "FirstName", "LastName" },
new[] { "Jane", "Smith" });
doc.MailMerge.Execute(
New String() { "FirstName", "LastName" },
New String() { "Jane", "Smith" })
Execute(fieldNames, values) 當兩個序列長度不一致時會拋出 ArgumentException。
我如何從DataTable或DataRow中進行郵件合併?
當資料來自資料庫或現有 DataSet 時,將 DataTable 或 DataRow 直接傳遞給 Execute。 合併字段名稱對應於列名稱。 Execute(DataTable) 使用表的第一行的值,而 Execute(DataRow) 使用行的父表的欄名。
DataTable table = new DataTable();
table.Columns.Add("FirstName");
table.Columns.Add("LastName");
DataRow row = table.NewRow();
row["FirstName"] = "Jane";
row["LastName"] = "Smith";
table.Rows.Add(row);
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(row);
doc.SaveAs("output.docx");
DataTable table = new DataTable();
table.Columns.Add("FirstName");
table.Columns.Add("LastName");
DataRow row = table.NewRow();
row["FirstName"] = "Jane";
row["LastName"] = "Smith";
table.Rows.Add(row);
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Execute(row);
doc.SaveAs("output.docx");
Imports System.Data
Dim table As New DataTable()
table.Columns.Add("FirstName")
table.Columns.Add("LastName")
Dim row As DataRow = table.NewRow()
row("FirstName") = "Jane"
row("LastName") = "Smith"
table.Rows.Add(row)
Dim doc As New WordDocument("template.docx")
doc.MailMerge.Execute(row)
doc.SaveAs("output.docx")
我如何填充重複表格區域?
重複區域將一個模板行變成多行,非常適合使用於發票項目或訂單清單。 在範本中,將重複內容包裹在名為 TableStart:RegionName 和 TableEnd:RegionName 的兩個標記欄位之間。 然後調用 ExecuteWithRegions,每一行匹配表的內容都重複該區域內容一次。
ExecuteWithRegions 接受完整的 DataSet(擴展每個名稱與表匹配的區域)、單個 DataTable(擴展名稱與 dataTable.TableName 匹配的區域),或與 DataTable 一起的區域名稱。
DataTable orders = new DataTable("Orders");
orders.Columns.Add("Item");
orders.Columns.Add("Qty");
orders.Rows.Add("Widget A", "3");
orders.Rows.Add("Widget B", "1");
DataSet ds = new DataSet();
ds.Tables.Add(orders);
WordDocument doc = new WordDocument("invoice-template.docx");
doc.MailMerge.ExecuteWithRegions(ds);
doc.MailMerge.Execute(new Dictionary<string, string> { { "CustomerName", "Jane Smith" } });
doc.SaveAs("invoice.docx");
DataTable orders = new DataTable("Orders");
orders.Columns.Add("Item");
orders.Columns.Add("Qty");
orders.Rows.Add("Widget A", "3");
orders.Rows.Add("Widget B", "1");
DataSet ds = new DataSet();
ds.Tables.Add(orders);
WordDocument doc = new WordDocument("invoice-template.docx");
doc.MailMerge.ExecuteWithRegions(ds);
doc.MailMerge.Execute(new Dictionary<string, string> { { "CustomerName", "Jane Smith" } });
doc.SaveAs("invoice.docx");
Imports System.Data
Imports System.Collections.Generic
Dim orders As New DataTable("Orders")
orders.Columns.Add("Item")
orders.Columns.Add("Qty")
orders.Rows.Add("Widget A", "3")
orders.Rows.Add("Widget B", "1")
Dim ds As New DataSet()
ds.Tables.Add(orders)
Dim doc As New WordDocument("invoice-template.docx")
doc.MailMerge.ExecuteWithRegions(ds)
doc.MailMerge.Execute(New Dictionary(Of String, String) From {{"CustomerName", "Jane Smith"}})
doc.SaveAs("invoice.docx")
ExecuteWithRegions 僅填充重複區域。) 要填充區域外的標準合併欄位,請在展開區域後調用 Execute(...),如上述所示。我如何檢查模板的合併字段?
在合併之前,您可以發現模板中包含的內容,這對於驗證模板或動態生成資料源很有用。
GetFieldNames()返回文件順序中的所有值樣式合併欄位名稱,且去重。GetRegionNames()返回文件中宣告的所有TableStart區域的名稱。GetFields()返回每個欄位,包括TableEnd標記,作為MergeField物件。
WordDocument doc = new WordDocument("template.docx");
IReadOnlyList<string> fieldNames = doc.MailMerge.GetFieldNames();
IReadOnlyList<string> regionNames = doc.MailMerge.GetRegionNames();
// fieldNames: ["FirstName", "LastName", "Company"]
// regionNames: ["Orders", "LineItems"]
WordDocument doc = new WordDocument("template.docx");
IReadOnlyList<string> fieldNames = doc.MailMerge.GetFieldNames();
IReadOnlyList<string> regionNames = doc.MailMerge.GetRegionNames();
// fieldNames: ["FirstName", "LastName", "Company"]
// regionNames: ["Orders", "LineItems"]
Dim doc As New WordDocument("template.docx")
Dim fieldNames As IReadOnlyList(Of String) = doc.MailMerge.GetFieldNames()
Dim regionNames As IReadOnlyList(Of String) = doc.MailMerge.GetRegionNames()
' fieldNames: ["FirstName", "LastName", "Company"]
' regionNames: ["Orders", "LineItems"]
每個 MergeField 暴露其 Name,完整的 Instruction 文字如文件中儲存(例如 MERGEFIELD FirstName \* MERGEFORMAT),僅針對區域標記設置的 RegionName(例如來自 "Orders" 的 "TableStart:Orders"),以及將欄位歸類為 TableStart 或 TableEnd(重複區域的界限),或 NextRecord(在同一範本主體內推進到下一個資料記錄的 NEXT 欄位)。
我如何控制未匹配字段和空值?
合併行為透過 MailMerge.Options 配置:
| 選項 | Default | 行為 |
|---|---|---|
RemoveUnusedFields |
true |
移除在資料源中不具匹配鍵的合併字段。 設置為 false 以保持其原地不動。 |
RemoveUnusedRegions |
true |
移除資料來源中沒有匹配表的 TableEnd 區域。 |
NullValueReplacement |
"" |
當資料來源為某欄位提供 null 值時替換的文字。 |
CaseInsensitiveFieldNames |
true |
在匹配字段名稱時忽略大小寫,匹配Microsoft Word的行為。 |
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Options.RemoveUnusedFields = false;
doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" } });
doc.SaveAs("partial-output.docx");
WordDocument doc = new WordDocument("template.docx");
doc.MailMerge.Options.RemoveUnusedFields = false;
doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" } });
doc.SaveAs("partial-output.docx");
Dim doc As New WordDocument("template.docx")
doc.MailMerge.Options.RemoveUnusedFields = False
doc.MailMerge.Execute(New Dictionary(Of String, String) From {{"FirstName", "Jane"}})
doc.SaveAs("partial-output.docx")
如需不使用資料來源實現簡單數值替代,請查看如何在Word文件中替換文字。
常見問題
如何在C#中合併郵件Word文件?
使用WordDocument構造函式載入一個包含MERGEFIELD佔位符的Word模板,然後調用doc.MailMerge.Execute使用IDictionary, DataTable或DataRow替換每個名稱與鍵或列匹配的欄位,並使用SaveAs保存結果。在Microsoft Word中建立的合併欄位會自動被檢測到,無需安裝Microsoft Office。
IronWord郵件合併可以使用哪些資料來源?
MailMerge.Execute接受與欄位名稱和值匹配的IDictionary,兩個平行的欄位名稱和值序列,一個DataTable(使用第一行),或一個DataRow(使用其父表的欄)。MailMerge.ExecuteWithRegions接受DataSet或DataTable來展開重複的表格區域。
如何在Word郵件合併中填充重複的表格區域?
將模板中重複的內容包裹在TableStart:RegionName和TableEnd:RegionName合併字段之間,然後用DataSet或DataTable調用MailMerge.ExecuteWithRegions。該區域的內容會根據匹配表格的每一行重複一次。由於ExecuteWithRegions僅填充區域,請在之後調用Execute以填充任何標準合併字段。
我是否可以在合併之前檢查模板的合併欄位?
可以。MailMerge.GetFieldNames以文件順序返回值型別的欄位名稱,GetRegionNames返回TableStart區域名稱,GetFields返回Expose每個欄位的Name, Instruction, Kind (Value, TableStart, TableEnd, or NextRecord), 和RegionName的MergeField物件。
沒有匹配資料的合併字段會怎麼處理?
預設情況下MailMergeOptions.RemoveUnusedFields為true,因此輸出中沒有匹配鍵的資料源欄位會被移除。設置為false以保留它們。當RemoveUnusedRegions為true時,把沒有匹配的TableStart/TableEnd區域移除,並用NullValueReplacement字串替換空值。
郵件合併欄位匹配是否區分大小寫?
不。字段名稱查詢預設不區分大小寫,匹配Microsoft Word的行為。如果需要精確大小寫匹配,將MailMerge.Options.CaseInsensitiveFieldNames設置為false。

