How to Mail Merge Word Documents in C

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronWord führt in C# einen Serienbrief durch, indem es MERGEFIELD Platzhalter in einer Word-Vorlage mit Ihren Daten füllt, die aus Wörterbüchern, DataSet Objekten oder sich wiederholenden Abschnittstabellen stammen, alles ohne Microsoft Office Interop. Seriendruckfelder, die in Microsoft Word oder einem kompatiblen Tool erstellt wurden, werden automatisch erkannt.

Serienbriefe sind der Standardweg, um personalisierte Dokumente in großem Maßstab zu erstellen: Serienbriefe, Rechnungen, Zertifikate, Verträge und Berichte, die eine Vorlage teilen, sich aber je nach Empfänger unterscheiden. Anstatt jedes Dokument von Hand zu bearbeiten, erstellen Sie eine einzelne .docx Vorlage mit Seriendruckfeldern und lassen IronWord diese aus Ihrer Datenquelle ausfüllen. Jede Operation wird über den WordDocument.MailMerge Einstiegspunkt erreicht.

Schnellstart: Serienbriefe in einem Word-Dokument zusammenführen

Laden Sie eine Vorlage, die MERGEFIELD Platzhalter enthält, übergeben Sie ein Wörterbuch mit Feldnamen und Werten an Execute und speichern Sie das Ergebnis.

  1. Installieren Sie IronWord mit NuGet Package Manager

    PM > Install-Package IronWord
  2. Kopieren Sie diesen Codeausschnitt und führen Sie ihn aus.

    WordDocument doc = new WordDocument("template.docx");
    doc.MailMerge.Execute(new Dictionary<string, string> { { "FirstName", "Jane" }, { "Company", "Acme Corp" } });
    doc.SaveAs("output.docx");
  3. Bereitstellen zum Testen in Ihrer Live-Umgebung

    Beginnen Sie noch heute, IronWord in Ihrem Projekt zu verwenden, mit einer kostenlosen Testversion

    arrow pointer


Wie führe ich einen Serienbrief aus einem Wörterbuch zusammen?

Die einfachste Datenquelle ist ein IDictionary<string, string>, der nach dem Namen des Seriendruckfelds geordnet ist. Execute ersetzt jedes Feld, dessen Name mit einem Schlüssel übereinstimmt.

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")
$vbLabelText   $csharpLabel

TippsFeldnamen-Suchen sind standardmäßig nicht fallabhängig, wie in Microsoft Word. Stellen Sie MailMerge.Options.CaseInsensitiveFieldNames = false ein, um eine exakte Übereinstimmung (Groß-/Kleinschreibung) zu erfordern.)

Sie können auch zwei parallele Sequenzen von Feldnamen und Werten bereitstellen:

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" })
$vbLabelText   $csharpLabel

Execute(fieldNames, values) wirft eine(n) ArgumentException aus, wenn die beiden Sequenzen unterschiedliche Längen haben.

Wie führe ich einen Serienbrief aus einem DataTable oder DataRow zusammen?

Wenn Daten aus einer Datenbank oder einem vorhandenen DataSet stammen, übergeben Sie ein DataTable oder DataRow direkt an Execute. Seriendruckfeldnamen werden den Spaltennamen zugeordnet. Execute(DataTable) verwendet die Werte aus der ersten Zeile der Tabelle, während Execute(DataRow) die Spaltennamen der übergeordneten Tabelle der Zeile verwendet.

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")
$vbLabelText   $csharpLabel

Wie fülle ich wiederholte Tabellenbereiche aus?

Wiederholte Bereiche verwandeln eine Vorlagenzeile in viele, was ideal für Rechnungsposten oder Bestelllisten ist. In der Vorlage umschließen Sie den sich wiederholenden Inhalt zwischen zwei Markierungsfeldern mit den Namen TableStart:RegionName und TableEnd:RegionName. Rufen Sie dann ExecuteWithRegions auf, wodurch der Inhalt des Bereichs einmal pro Zeile der übereinstimmenden Tabelle wiederholt wird.

ExecuteWithRegions akzeptiert ein vollständiges DataSet (das jeden Bereich erweitert, dessen Name mit einer Tabelle übereinstimmt), ein einzelnes DataTable (das den Bereich erweitert, dessen Name mit dataTable.TableName übereinstimmt), oder einen Bereichsnamen zusammen mit einem 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")
$vbLabelText   $csharpLabel

Hinweis:ExecuteWithRegions füllt nur sich wiederholende Bereiche aus. Um auch standardmäßige Seriendruckfelder außerhalb der Bereiche zu füllen, rufen Sie nach dem Erweitern der Bereiche Execute(...) auf, wie oben gezeigt.

Wie inspiziere ich die Seriendruckfelder einer Vorlage?

Vor dem Zusammenführen können Sie herausfinden, was eine Vorlage enthält, was nützlich zum Validieren von Vorlagen oder zum dynamischen Erstellen der Datenquelle ist.

  • GetFieldNames() gibt die Namen aller wertstilbezogenen Seriendruckfelder in der Dokumentreihenfolge und ohne Duplikate zurück.
  • GetRegionNames() gibt die Namen aller TableStart Bereiche zurück, die im Dokument deklariert sind.
  • GetFields() gibt jedes Feld zurück, einschließlich TableEnd Markierungen, als MergeField Objekte.
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"]
$vbLabelText   $csharpLabel

Jedes MergeField gibt sein Name, den vollständigen Instruction Text, wie im Dokument gespeichert (zum Beispiel MERGEFIELD FirstName \* MERGEFORMAT), ein RegionName, das nur für Bereichsmarkierungen festgelegt ist (zum Beispiel "Orders" aus "TableStart:Orders"), und eine Kind zurück, die das Feld als Value (Text durch einen Datenwert ersetzt), TableStart oder TableEnd (die Grenzen eines sich wiederholenden Bereichs), oder NextRecord (ein NEXT Feld, das zum nächsten Datensatz innerhalb des gleichen Vorlagentextes übergeht) klassifiziert.

Wie kontrolliere ich unbeantwortete Felder und Nullwerte?

Das Seriendruckverhalten wird durch MailMerge.Options konfiguriert:

Option Default Verhalten
RemoveUnusedFields true Entfernt Zusammenführungsfelder, die keinen passenden Schlüssel in der Datenquelle haben. Auf false setzen, um sie an Ort und Stelle zu belassen.
RemoveUnusedRegions true Entfernt TableEnd Bereiche ohne übereinstimmende Tabelle in der Datenquelle.
NullValueReplacement "" Text wird ersetzt, wenn die Datenquelle einen null Wert für ein Feld liefert.
CaseInsensitiveFieldNames true Ignoriert die Groß-/Kleinschreibung bei der Namensübereinstimmung der Felder, entspricht der Microsoft Word-Verhalten.
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")
$vbLabelText   $csharpLabel

Für die einfache Wertersetzung ohne Datenquelle siehe Text in einem Word-Dokument ersetzen.

Häufig gestellte Fragen

Wie mache ich einen Serienbrief in einem Word-Dokument in C#?

Laden Sie eine Word-Vorlage mit MERGEFIELD-Platzhaltern mit dem WordDocument-Konstruktor, rufen Sie dann doc.MailMerge.Execute mit einem IDictionary, DataTable oder DataRow auf, um jedes Feld zu ersetzen, dessen Name mit einem Schlüssel oder einer Spalte übereinstimmt, und speichern Sie das Ergebnis mit SaveAs. In Microsoft Word erstellte Merge-Felder werden automatisch erkannt, und eine Microsoft Office-Installation ist nicht erforderlich.

Welche Datenquellen kann IronWord für Serienbriefe verwenden?

MailMerge.Execute akzeptiert ein IDictionary von Feldnamen und Werten, zwei parallele Sequenzen von Feldnamen und Werten, eine DataTable (unter Verwendung der ersten Zeile) oder eine DataRow (unter Verwendung ihrer übergeordneten Tabellenspalten). MailMerge.ExecuteWithRegions akzeptiert ein DataSet oder DataTable, um sich wiederholende Tabellenbereiche zu erweitern.

Wie fülle ich sich wiederholende Tabellenbereiche in einem Word Serienbrief?

Umfassen Sie die sich wiederholenden Inhalte in der Vorlage zwischen den Merge-Feldern TableStart:RegionName und TableEnd:RegionName, rufen Sie dann MailMerge.ExecuteWithRegions mit einem DataSet oder DataTable auf. Der Inhalt der Region wird einmal pro Zeile der passenden Tabelle wiederholt. Da ExecuteWithRegions nur Bereiche ausfüllt, rufen Sie anschließend Execute auf, um alle standardmäßigen Merge-Felder zu füllen.

Kann ich die Merge-Felder einer Vorlage vor dem Zusammenführen überprüfen?

Ja. MailMerge.GetFieldNames gibt die Feldnamen im Wertestil in Dokumentreihenfolge zurück, GetRegionNames gibt die TableStart-Regionennamen zurück, und GetFields gibt MergeField-Objekte zurück, die den Namen, die Anweisung, die Art (Wert, TableStart, TableEnd oder NextRecord) und den Regionenamen jedes Feldes offenlegen.

Was passiert mit Merge-Feldern, die keine passenden Daten haben?

Standardmäßig ist MailMergeOptions.RemoveUnusedFields wahr, sodass Felder ohne passenden Schlüssel in der Datenquelle aus der Ausgabe entfernt werden. Setzen Sie es auf falsch, um sie vor Ort zu belassen. Nicht übereinstimmende TableStart/TableEnd-Bereiche werden entfernt, wenn RemoveUnusedRegions wahr ist, und Nullwerte werden durch die NullValueReplacement-Zeichenfolge ersetzt.

Ist die Übereinstimmung von Serienbrieffeldnamen groß-/kleinschreibungssensitiv?

Nein. Die Suche nach Feldnamen erfolgt standardmäßig ohne Berücksichtigung der Groß-/Kleinschreibung, wie es das Verhalten von Microsoft Word entspricht. Setzen Sie MailMerge.Options.CaseInsensitiveFieldNames auf falsch, wenn Sie eine exakte Übereinstimmung der Groß-/Kleinschreibung benötigen.

Curtis Chau
Technischer Autor

Curtis Chau hat einen Bachelor-Abschluss in Informatik von der Carleton University und ist spezialisiert auf Frontend-Entwicklung mit Expertise in Node.js, TypeScript, JavaScript und React. Leidenschaftlich widmet er sich der Erstellung intuitiver und ästhetisch ansprechender Benutzerschnittstellen und arbeitet gerne mit modernen Frameworks sowie der Erstellung gut strukturierter, optisch ansprechender ...

Weiterlesen
Bereit anzufangen?
Nuget Downloads 48,355 | Version: 2026.7 gerade veröffentlicht
Still Scrolling Icon

Scrollst du immer noch?

Sie brauchen schnell einen Beweis? PM > Install-Package IronWord
Führen Sie ein Beispiel aus und sehen Sie zu, wie aus Ihren Daten ein Word-Dokument wird.