Table of Contents

Write Excel files

DocWright.Formats.Xlsx writes Excel workbooks: typed cells, number formats, fonts, fills, borders, merged ranges, column widths, frozen panes, outlines, autofilter and images. It has no dependencies, and the same workbook always produces the same bytes.

dotnet add package DocWright.Formats.Xlsx

A workbook

using DocWright.Core.Primitives;
using DocWright.Formats.Xlsx;

var book = new XlsxWorkbook();
var sheet = new XlsxWorksheet("Sales");
sheet.Columns.Add(new XlsxColumn(1, 1, 24m));   // column A, width in characters
sheet.Columns.Add(new XlsxColumn(2, 3, 14m));   // columns B-C

XlsxCellStyle header = XlsxCellStyle.Default.With(
    bold: true,
    backgroundColor: ColorRgb.FromRgb(0xEE, 0xF2, 0xFF),
    bottomBorder: new XlsxBorder(XlsxBorderStyle.Thin, ColorRgb.FromRgb(0x1E, 0x3A, 0x8A)));
XlsxCellStyle money = XlsxCellStyle.Default.With(numberFormat: "#,##0.00");
XlsxCellStyle date = XlsxCellStyle.Default.With(numberFormat: "d mmm yyyy");

var heading = new XlsxRow(1);
heading.Cells.Add(new XlsxCell(1, XlsxCellValue.Text("Region"), header));
heading.Cells.Add(new XlsxCell(2, XlsxCellValue.Text("Revenue"), header));
heading.Cells.Add(new XlsxCell(3, XlsxCellValue.Text("Closed"), header));
sheet.Rows.Add(heading);

(string Region, decimal Revenue, DateTime Closed)[] data =
[
    ("Auckland", 182_000m, new DateTime(2026, 9, 30)),
    ("Wellington", 264_500m, new DateTime(2026, 9, 28)),
    ("Canterbury", 200_750m, new DateTime(2026, 9, 29)),
];

int r = 2;
foreach (var (region, revenue, closed) in data)
{
    var row = new XlsxRow(r++);
    row.Cells.Add(new XlsxCell(1, XlsxCellValue.Text(region)));
    row.Cells.Add(new XlsxCell(2, XlsxCellValue.Number(revenue), money));   // a real number: it sums
    row.Cells.Add(new XlsxCell(3, XlsxCellValue.Date(closed), date));
    sheet.Rows.Add(row);
}

sheet.FrozenRows = 1;   // keep the header visible while scrolling
book.Worksheets.Add(sheet);

using (FileStream output = File.Create("sales.xlsx"))
{
    XlsxWriter.Write(book, output);
}

Download the result: sales.xlsx.

Values, not text

XlsxCellValue is Text, Number, Boolean, Date, Error or Blank. A Number with a #,##0.00 format displays like the formatted text and sums in Excel. Text that looks like a number sums to zero.

  • Numbers are decimal. A double is rounded to 15 significant digits, the precision Excel displays, so output is identical on .NET Framework and .NET.
  • Date stores Excel's serial number, including Excel's 1900 leap-year quirk, so dates agree with Excel's own. A cell displays as a date only when its style has a date format.

Rules enforced up front

Sheet names must be 1–31 characters, without : \ / ? * [ ]. XlsxWorksheet throws for an invalid name, and XlsxSheetName.Normalize(text, fallback) and XlsxSheetName.MakeUnique(name, taken) produce valid ones from any text.

XlsxWriteSettings.MaxOutputBytes caps the output size, for workbooks whose size depends on data you don't control.

Not supported

Formulas, pivot tables, charts, conditional formatting, data validation, comments and macros. There is no XLSX reader.

Tip

To export a report to Excel, with number formats, grouping outlines and charts as pictures, use ReportXlsxExporter from DocWright.Reporting.Export, which builds on this writer. See Run an SSRS report.