使用 Word 郵件合併功能,資料來源為 Excel 工作表,透過 C# 自動化產出客製化文件(信函、標籤、合約等)。
Template.docx):插入合併欄位(插入 → 快速組件 → 欄位 → MergeField)。Data.xlsx):第一列為欄位名稱,資料從第二列開始,工作表名稱如 Sheet1。using Word = Microsoft.Office.Interop.Word;
using System.Reflection;
using System.IO;
public class MailMergeHelper
{
private readonly Word.Application _app;
public MailMergeHelper()
{
_app = new Word.Application { Visible = false };
}
public void ExecuteMerge(string templatePath, string excelPath, string outputPath,
string sheetName = "Sheet1", string[] mergeFields = null)
{
object missing = Missing.Value;
object falseVal = false;
object trueVal = true;
// 1. 複製模板與資料檔至暫存目錄(避免鎖定原檔)
string tempDoc = CopyToTemp(templatePath);
string tempXls = CopyToTemp(excelPath);
// 2. 開啟 Word 文件
Word.Document doc = _app.Documents.Open(tempDoc, ref missing, ref falseVal,
ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref trueVal, ref missing, ref missing, ref missing);
try
{
// 3. 設定郵件合併資料來源
object linkTo = tempXls;
object query = $"SELECT * FROM `{sheetName}$`"; // Excel SQL 查詢
object header = string.Join(",", mergeFields ?? new[] { "Name", "Category", "Address", "Content" });
doc.MailMerge.CreateDataSource(ref linkTo, ref missing, ref missing,
ref header, ref falseVal, ref query, ref missing, ref missing, ref trueVal);
// 4. 可選:插入合併欄位至文件(若模板未預設)
if (mergeFields != null)
{
foreach (string field in mergeFields)
doc.MailMerge.Fields.Add(_app.Selection.Range, field);
}
// 5. 執行合併並另存新檔
doc.MailMerge.Destination = Word.WdMailMergeDestination.wdSendToNewDocument;
doc.MailMerge.Execute(ref missing);
// 6. 儲存合併後文件
Word.Document mergedDoc = _app.ActiveDocument;
mergedDoc.SaveAs2(outputPath, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing);
mergedDoc.Close(ref falseVal, ref missing, ref missing);
}
finally
{
doc.Close(ref falseVal, ref missing, ref missing);
// 7. 覆寫 Excel 檔案(解決某些版本儲存後檔案損毀問題)
File.Copy(tempXls, excelPath, true);
}
}
private string CopyToTemp(string sourcePath)
{
string temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + Path.GetExtension(sourcePath));
File.Copy(sourcePath, temp, true);
return temp;
}
public void Dispose()
{
_app.Quit(ref falseVal, ref missing, ref missing);
System.Runtime.InteropServices.Marshal.ReleaseComObject(_app);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
using (var helper = new MailMergeHelper())
{
helper.ExecuteMerge(
templatePath: @"C:\Templates\Letter.docx",
excelPath: @"C:\Data\Customers.xlsx",
outputPath: @"C:\Output\MergedLetters.docx",
sheetName: "Sheet1",
mergeFields: new[] { "Name", "Category", "Address", "Content" });
}
| 問題 | 原因 | 解決 |
|---|---|---|
| Excel 連結失敗 | 工作表名稱需加 $ 且用反引號包裹 | 查詢字串:SELECT * FROM `Sheet1$` |
| 合併欄位不顯示 | 模板未插入 MergeField 或欄位名稱不符 | 確認模板欄位名稱與 header 參數完全一致 |
| 輸出檔案損毀/無法開啟 | Word 併發存取 Excel 導致鎖定 | 複製至暫存目錄操作,結束後覆寫回原檔 |
| Word 進程殘留 | COM 物件未正確釋放 | Marshal.ReleaseComObject + GC.Collect + Quit |
| 伺服器端自動化不支援 | Microsoft 不建議在 Server 端自動化 Office | 改用 Open XML SDK、Aspose.Words 或 DocX 純 .NET 庫 |