Feature Guide
This guide shows practical examples for the main document features.
Document Metadata
Document.Create(doc =>
{
doc.MetadataTitle("Annual Report")
.MetadataAuthor("Contoso Finance")
.MetadataSubject("FY2026 performance")
.MetadataKeywords("annual report, finance, operations")
.MetadataCreator("TerraFluent.Docx.Reporting");
});
Headers, Footers, And Page Numbers
doc.Page(page =>
{
page.FirstPageHeader().Text("Annual Report", t => t.Bold().AlignCenter());
page.EvenPageHeader().Text("Contoso", t => t.AlignLeft().FontSize(9));
page.OddPageHeader().Text("FY2026", t => t.AlignRight().FontSize(9));
page.Footer().Text(t =>
{
t.Span("Page ");
t.CurrentPageNumber();
t.Span(" of ");
t.TotalPages();
t.AlignCenter().FontSize(9);
});
});
Page Layout
doc.Page(page =>
{
page.Size(PageSize.A4)
.Margin(Unit.Centimetre(2))
.Background("FAFAFA")
.Watermark("DRAFT", Colors.Grey.L300, 72);
page.Content().Text("The page background is document-wide in Word.");
});
doc.Page(page =>
{
page.Size(PageSize.A4).Landscape();
page.Columns(2, spacingPoints: 24, separatorLine: true);
page.Content().H1("Two Column Appendix");
page.Content().Text("Content flows from the first column to the second.");
});
Text And Rich Runs
page.Content().Text(text =>
{
text.Span("Revenue ").Bold();
text.Span("increased 12%").FontColor(Colors.Green.L700).Bold();
text.Span(" year over year.");
text.SpacingAfter(8).KeepLinesTogether();
});
page.Content().Text("Important policy note.", text => text
.Shading(Colors.Orange.L100)
.BorderLeft(4, Colors.Orange.L700)
.LeftIndent(14)
.RightIndent(14)
.SpacingBefore(6)
.SpacingAfter(6));
Links, Bookmarks, Cross References, And Notes
page.Content().Bookmark("revenue-section", "Revenue", text => text.Bold());
page.Content().Text(text =>
{
text.Span("See ");
text.CrossReference("revenue-section", "the revenue section");
text.Span(" for details.");
});
H1 through H6 don’t accept a bookmark name directly. To bookmark a heading, use Bookmark with Style instead of H1-H6:
page.Content().Bookmark("operations-section", "Operations", text => text.Style("Heading1"));
page.Content().Text(text =>
{
text.Span("External reference: ");
text.Hyperlink("company site", "https://example.com", link => link.FontColor(Colors.Blue.L700));
});
page.Content().Text(text =>
{
text.Span("Net revenue excludes discontinued products.");
text.Footnote("A discontinued product is excluded after the final shipment date.");
});
Lists
page.Content().BulletList(list =>
{
list.Marker(">");
list.Marker("-", level: 1);
list.Item("Prepare source data");
list.Item("Validate totals", level: 1, text => text.FontColor(Colors.Green.L700));
list.Item("Generate final report");
});
page.Content().NumberedList(list =>
{
list.Item("Open the generated document in Word.");
list.Item("Confirm there are no repair prompts.");
list.Item("Export to PDF if needed.");
});
Tables
page.Content().Table(table =>
{
table.WidthPercent(100)
.CellPadding(4, 6)
.HeaderBackground(Colors.Blue.L800)
.AlternateRowBackground(Colors.Grey.L100)
.Border(0.5f, Colors.Grey.L300);
table.ColumnsDefinition(cols =>
{
cols.RelativeColumn(3);
cols.ConstantColumn(90);
cols.ConstantColumn(90);
});
table.HeaderRow(row =>
{
row.KeepTogether();
row.Cell().Text("Metric", t => t.Bold().FontColor(Colors.White.Default));
row.Cell().Text("Q3", t => t.Bold().FontColor(Colors.White.Default).AlignRight());
row.Cell().Text("Q4", t => t.Bold().FontColor(Colors.White.Default).AlignRight());
});
table.Row(row =>
{
row.Cell().Text("Revenue");
row.Cell().Text("$4.1M", t => t.AlignRight());
row.Cell().Text("$4.8M", t => t.AlignRight().Bold());
});
});
Spans And Vertical Merges
page.Content().Table(table =>
{
table.ColumnsDefinition(cols =>
{
cols.RelativeColumn();
cols.RelativeColumn();
cols.RelativeColumn();
});
table.Row(row =>
{
row.Cell(3).Background(Colors.Blue.L100).Text("Regional Summary", t => t.Bold().AlignCenter());
});
table.Row(row =>
{
row.Cell().VerticalMergeStart().Text("North");
row.Cell().Text("Revenue");
row.Cell().Text("$2.3M");
});
table.Row(row =>
{
row.Cell().VerticalMergeContinue();
row.Cell().Text("Margin");
row.Cell().Text("31%");
});
});
Images
page.Content().Image("logo.png", image => image
.Width(120)
.AltText("Company logo")
.AlignCenter()
.Caption("Figure 1. Company logo"));
page.Content().Image(File.ReadAllBytes("photo.png"), "photo.png", image => image
.Width(160)
.WrapSquare(8)
.FloatRight(8)
.Border(1, Colors.Grey.L400)
.Rounded()
.Crop(4, 4, 4, 4));
Barcodes
page.Content().Barcode("SKU-00100011");
page.Content().Barcode("ACME-99887766", bc => bc
.Width(220)
.Height(50)
.BarColor(Colors.Blue.L700)
.AlignCenter()
.Caption("Figure 1. Product tracking code"));
page.Content().Barcode("Internal-Only", bc => bc.ShowText(false));
Barcodes encode text as Code 128 and render as vector bars (not raster images), so they stay crisp at any size. Only ASCII 32-126 (space through ~) can be encoded; anything else throws ArgumentException immediately.
Charts
page.Content().Chart(chart => chart
.Title("Quarterly Revenue")
.Series("Revenue", series => series
.Bar("Q1", 4.1)
.Bar("Q2", 4.3)
.Bar("Q3", 4.8)
.Bar("Q4", 5.2)
.Color(Colors.Green.L700)));
Line chart:
page.Content().Chart(chart => chart
.Title("Customer Growth")
.Series("Customers", series => series
.Line("Jan", 120)
.Line("Feb", 132)
.Line("Mar", 150)
.Color(Colors.Blue.L700)));
Pie chart:
page.Content().Chart(chart => chart
.Title("Revenue Mix")
.Series(series => series
.Pie("Consulting", 45)
.Pie("Support", 30)
.Pie("Licensing", 25)
.Color(Colors.Orange.L700)));
Legend placement, axis titles, data labels, and stacked bars:
page.Content().Chart(chart => chart
.Title("Stacked Revenue by Quarter")
.Width(430) // points; default is 432 x 252 (6 x 3.5 in)
.Height(250)
.AlignCenter()
.Legend(ChartLegendPosition.Bottom) // or .HideLegend()
.CategoryAxisTitle("Quarter")
.ValueAxisTitle("Revenue ($M)")
.DataLabels()
.Stacked() // or .PercentStacked(); bar charts only
.Series("Product", s => s.Bar("Q1", 4.1).Bar("Q2", 4.3).Color(Colors.Blue.L700))
.Series("Services", s => s.Bar("Q1", 2.2).Bar("Q2", 2.6).Color(Colors.Orange.L700)));
Rows And Columns
page.Content().Row(row =>
{
row.Spacing(12);
row.RelativeItem(2).Text("Main narrative column.");
row.RelativeItem(1).Text("Sidebar", text => text
.Shading(Colors.Grey.L100)
.Border(0.5f, Colors.Grey.L300)
.LeftIndent(8)
.RightIndent(8));
});
page.Content().Column(column =>
{
column.Spacing(6);
column.Item().H2("Stacked Content");
column.Item().Text("First block.");
column.Item().Text("Second block.");
});
Table Of Contents
page.Content().TableOfContents("Contents", minLevel: 1, maxLevel: 3);
page.Content().PageBreak();
page.Content().H1("Executive Summary");
page.Content().H2("Revenue");
page.Content().H2("Operations");
Word updates TOC fields when the document is opened or when fields are refreshed.
Auto-Numbered Captions And Table Of Figures
FigureCaption (images) and Caption (tables) insert Word SEQ fields, so Word renumbers captions automatically and can collect them into a table of figures:
page.Content().TableOfFigures(); // lists Figure captions
page.Content().TableOfFigures("List of Tables", "Table"); // lists Table captions
page.Content().Image("chart.png", img => img
.Width(200)
.FigureCaption("Revenue growth chart")); // "Figure 1. Revenue growth chart"
page.Content().Table(t =>
{
t.Caption("Quarterly results by region"); // "Table 1. Quarterly results by region", above the table
t.ColumnsDefinition(d => { d.RelativeColumn(1); d.RelativeColumn(1); });
t.Row(r => { r.Cell().Text("North"); r.Cell().Text("$4.1M"); });
});
Figure captions render below the image; table captions render above the table. The static Caption(...) image overload remains available for unnumbered captions.
Restrict Editing
RestrictEditing applies Word’s “Restrict Editing” protection, optionally guarded by a password:
Document.Create(doc =>
{
doc.RestrictEditing(DocumentProtection.ReadOnly, "secret123");
doc.Page(page => page.Content().Text("Read-only content."));
});
Modes: ReadOnly, CommentsOnly, TrackedChangesOnly, and FormsOnly. The password (first 15 characters) is stored as a salted, spun SHA-512 verifier per ISO/IEC 29500. This is a guard rail, not security: the file is not encrypted, and a malicious tool can strip the setting.
Templates
Use templates when a .docx already exists and you only need to replace placeholders or content controls.
DocxTemplate.Open("invoice-template.docx")
.Replace("", "Ada Lovelace")
.Replace("", "$1,250.00")
.ReplaceContentControl("PaymentTerms", "Net 30")
.SaveAs("invoice-output.docx");
To return bytes:
byte[] output = DocxTemplate.Open("template.docx")
.Replace("", "Grace Hopper")
.Save();