C#
Word Document
Programming
.NET
Automation

How can a Word document be created in C?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To create a Word document in C#, the best approach for most scenarios is the Open XML SDK (DocumentFormat.OpenXml), which generates .docx files without requiring Microsoft Word to be installed. For simpler needs, the DocX library (Xceed.Document.NET) provides a fluent API. Microsoft Office Interop (Microsoft.Office.Interop.Word) offers the most features but requires Word to be installed and is not suitable for server-side applications. Choose Open XML SDK for server/cloud deployments and Interop for desktop automation.

csharp
1// Install: dotnet add package DocumentFormat.OpenXml
2
3using DocumentFormat.OpenXml;
4using DocumentFormat.OpenXml.Packaging;
5using DocumentFormat.OpenXml.Wordprocessing;
6
7public void CreateDocument(string filePath)
8{
9    using var doc = WordprocessingDocument.Create(filePath, WordprocessingDocumentType.Document);
10
11    // Add main document part
12    var mainPart = doc.AddMainDocumentPart();
13    mainPart.Document = new Document();
14    var body = mainPart.Document.AppendChild(new Body());
15
16    // Add a heading
17    var heading = new Paragraph(
18        new ParagraphProperties(
19            new ParagraphStyleId() { Val = "Heading1" }
20        ),
21        new Run(new Text("Monthly Report"))
22    );
23    body.AppendChild(heading);
24
25    // Add a paragraph with formatted text
26    var para = new Paragraph(
27        new Run(
28            new RunProperties(new Bold()),
29            new Text("Summary: ")
30        ),
31        new Run(new Text("All metrics are within expected ranges."))
32    );
33    body.AppendChild(para);
34
35    // Add a bulleted list
36    string[] items = { "Revenue up 12%", "Costs down 5%", "Customer satisfaction at 94%" };
37    foreach (var item in items)
38    {
39        var listItem = new Paragraph(
40            new ParagraphProperties(
41                new NumberingProperties(
42                    new NumberingLevelReference() { Val = 0 },
43                    new NumberingId() { Val = 1 }
44                )
45            ),
46            new Run(new Text(item))
47        );
48        body.AppendChild(listItem);
49    }
50
51    mainPart.Document.Save();
52}

Adding a Table with Open XML

csharp
1public void AddTable(Body body)
2{
3    var table = new Table();
4
5    // Table properties (borders)
6    var tblProperties = new TableProperties(
7        new TableBorders(
8            new TopBorder() { Val = BorderValues.Single, Size = 4 },
9            new BottomBorder() { Val = BorderValues.Single, Size = 4 },
10            new LeftBorder() { Val = BorderValues.Single, Size = 4 },
11            new RightBorder() { Val = BorderValues.Single, Size = 4 },
12            new InsideHorizontalBorder() { Val = BorderValues.Single, Size = 4 },
13            new InsideVerticalBorder() { Val = BorderValues.Single, Size = 4 }
14        )
15    );
16    table.AppendChild(tblProperties);
17
18    // Header row
19    var headerRow = new TableRow();
20    foreach (var header in new[] { "Name", "Department", "Salary" })
21    {
22        var cell = new TableCell(
23            new Paragraph(new Run(
24                new RunProperties(new Bold()),
25                new Text(header)
26            ))
27        );
28        headerRow.AppendChild(cell);
29    }
30    table.AppendChild(headerRow);
31
32    // Data rows
33    var data = new[] {
34        ("Alice", "Engineering", "$120,000"),
35        ("Bob", "Marketing", "$95,000"),
36    };
37
38    foreach (var (name, dept, salary) in data)
39    {
40        var row = new TableRow();
41        row.AppendChild(new TableCell(new Paragraph(new Run(new Text(name)))));
42        row.AppendChild(new TableCell(new Paragraph(new Run(new Text(dept)))));
43        row.AppendChild(new TableCell(new Paragraph(new Run(new Text(salary)))));
44        table.AppendChild(row);
45    }
46
47    body.AppendChild(table);
48}

DocX Library (Xceed) — Simpler API

csharp
1// Install: dotnet add package DocX
2
3using Xceed.Document.NET;
4using Xceed.Words.NET;
5
6public void CreateWithDocX(string filePath)
7{
8    using var doc = DocX.Create(filePath);
9
10    // Title
11    doc.InsertParagraph("Monthly Report")
12       .FontSize(24)
13       .Bold()
14       .Alignment = Alignment.center;
15
16    // Body text
17    doc.InsertParagraph("All metrics are within expected ranges.")
18       .FontSize(12)
19       .SpacingAfter(10);
20
21    // Bulleted list
22    var list = doc.AddList("Revenue up 12%", 0, ListItemType.Bulleted);
23    doc.AddListItem(list, "Costs down 5%");
24    doc.AddListItem(list, "Customer satisfaction at 94%");
25    doc.InsertList(list);
26
27    // Table
28    var table = doc.AddTable(3, 3);
29    table.Rows[0].Cells[0].Paragraphs[0].Append("Name").Bold();
30    table.Rows[0].Cells[1].Paragraphs[0].Append("Department").Bold();
31    table.Rows[0].Cells[2].Paragraphs[0].Append("Salary").Bold();
32    table.Rows[1].Cells[0].Paragraphs[0].Append("Alice");
33    table.Rows[1].Cells[1].Paragraphs[0].Append("Engineering");
34    table.Rows[1].Cells[2].Paragraphs[0].Append("$120,000");
35    doc.InsertTable(table);
36
37    doc.Save();
38}

Microsoft Office Interop (Desktop Only)

csharp
1// Requires Microsoft Word installed
2// Add reference: Microsoft.Office.Interop.Word
3
4using Word = Microsoft.Office.Interop.Word;
5
6public void CreateWithInterop(string filePath)
7{
8    var app = new Word.Application();
9    var doc = app.Documents.Add();
10
11    try
12    {
13        // Add title
14        var titlePara = doc.Paragraphs.Add();
15        titlePara.Range.Text = "Monthly Report";
16        titlePara.Range.Font.Size = 24;
17        titlePara.Range.Font.Bold = 1;
18        titlePara.Range.InsertParagraphAfter();
19
20        // Add body text
21        var bodyPara = doc.Paragraphs.Add();
22        bodyPara.Range.Text = "All metrics are within expected ranges.";
23        bodyPara.Range.Font.Size = 12;
24        bodyPara.Range.Font.Bold = 0;
25        bodyPara.Range.InsertParagraphAfter();
26
27        doc.SaveAs2(filePath);
28    }
29    finally
30    {
31        doc.Close();
32        app.Quit();
33
34        // Release COM objects
35        System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
36        System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
37    }
38}

Comparison

FeatureOpen XML SDKDocX (Xceed)Office Interop
Word requiredNoNoYes
Server-safeYesYesNo
API complexityVerboseSimpleMedium
.docx supportYesYesYes
.doc supportNoNoYes
NuGet packageDocumentFormat.OpenXmlDocXN/A (COM)
LicenseMITFree (community)Office license

Common Pitfalls

  • Using Office Interop on a server: Microsoft.Office.Interop.Word requires a full Word installation and launches a Word process. It is not thread-safe, leaks memory if COM objects are not released, and Microsoft explicitly does not support server-side Interop. Use Open XML SDK or DocX for server applications.
  • Not disposing WordprocessingDocument: WordprocessingDocument implements IDisposable. Failing to call Dispose() (or use using) leaves the file locked and may produce a corrupted .docx file. Always wrap in a using statement.
  • Open XML text spaces being collapsed: By default, Open XML strips leading/trailing spaces from Text elements. To preserve spaces, set Space = SpaceProcessingModeValues.Preserve on the Text element: new Text(" indented") { Space = SpaceProcessingModeValues.Preserve }.
  • Missing numbering definitions for lists: Open XML bulleted/numbered lists require a NumberingDefinitionsPart with abstract and concrete numbering definitions. Without this, list items render as plain paragraphs. The DocX library handles this automatically.
  • Forgetting to release COM objects with Interop: Each Interop call creates COM objects that must be released with Marshal.ReleaseComObject(). Failing to release them keeps Word processes running in the background. Always release in a finally block and call GC.Collect() after releasing.

Summary

  • Use Open XML SDK for server/cloud applications — no Word installation required, full .docx control
  • Use DocX (Xceed) for a simpler API when complex Open XML structures are not needed
  • Use Office Interop only for desktop applications that need full Word feature access (track changes, macros)
  • Always dispose WordprocessingDocument with using to prevent file corruption
  • Never use Office Interop on servers — it is unsupported, not thread-safe, and leaks resources

Course illustration
Course illustration

All Rights Reserved.