Skip to main content

Workbook Settings

Settings that apply to the file as a whole rather than to any one sheet: the metadata Windows shows in a file's Properties dialog, protection, how Excel recalculates, and the options that govern loading and saving.

Document properties

workbook.Properties maps to the fields Excel exposes under File → Info:

using XLibur.Excel;

using var workbook = new XLWorkbook();

workbook.Properties.Author = "Reporting Service";
workbook.Properties.Title = "Q1 Sales Report";
workbook.Properties.Subject = "Regional performance";
workbook.Properties.Category = "Finance";
workbook.Properties.Keywords = "sales;q1;regional";
workbook.Properties.Comments = "Generated automatically — do not edit by hand.";
workbook.Properties.Status = "Final";
workbook.Properties.Company = "Example Ltd";
workbook.Properties.Manager = "A. Manager";
workbook.Properties.LastModifiedBy = "Reporting Service";
workbook.Properties.Created = new DateTime(2026, 1, 21);
workbook.Properties.Modified = DateTime.UtcNow;

workbook.Author is a shortcut that also seeds the author of new comments:

using var workbook = new XLWorkbook { Author = "Reporting Service" };

Reading them from an existing file is a cheap way to audit where a spreadsheet came from:

using var workbook = new XLWorkbook("Report.xlsx");

Console.WriteLine(workbook.Properties.Author);
Console.WriteLine(workbook.Properties.Created);
Console.WriteLine(workbook.Properties.LastModifiedBy);

Custom properties

Arbitrary typed key/value pairs stored in the file — useful for stamping a generated workbook with the version, run id, or source system that produced it:

workbook.CustomProperties.Add("GeneratorVersion", "2.4.1");
workbook.CustomProperties.Add("RunId", 48213);
workbook.CustomProperties.Add("GeneratedAt", DateTime.UtcNow);
workbook.CustomProperties.Add("IsDraft", false);

Four types are supported — Text, Number, Date, and Boolean — inferred from the value.

Reading them back:

foreach (var property in workbook.CustomProperties)
{
Console.WriteLine($"{property.Name} ({property.Type}) = {property.Value}");
}

var runId = workbook.CustomProperties.CustomProperty("RunId").GetValue<int>();

workbook.CustomProperties.Delete("IsDraft");

This is a good place for a provenance stamp, because unlike a cell it cannot be accidentally deleted while editing:

static void StampProvenance(XLWorkbook workbook, string source)
{
workbook.CustomProperties.Add("SourceSystem", source);
workbook.CustomProperties.Add("GeneratedAtUtc", DateTime.UtcNow);
workbook.CustomProperties.Add("GeneratorVersion",
typeof(Program).Assembly.GetName().Version?.ToString() ?? "unknown");
}

Calculation

workbook.CalculateMode = XLCalculateMode.Auto; // Excel recalculates on open and edit
workbook.CalculateMode = XLCalculateMode.Manual; // only on F9
workbook.CalculateMode = XLCalculateMode.AutoNoTable; // auto, except data tables

ReferenceStyle controls whether Excel shows A1 or R1C1 addresses in its UI — it does not change how you write formulas in code:

workbook.ReferenceStyle = XLReferenceStyle.A1; // or R1C1, Default

Recalculating with XLibur's own engine, rather than deferring to Excel:

workbook.RecalculateAllFormulas();
workbook.Worksheet("Data").RecalculateAllFormulas();

See Formulas for when this matters.

Date system

Excel workbooks store dates as a serial number counting from an epoch. Windows Excel uses 1900; legacy Mac files use 1904. Switching moves every date in the workbook by four years, so this is a load-time property rather than something to toggle mid-build:

workbook.Use1904DateSystem = true;
workbook.SetUse1904DateSystem();

Console.WriteLine(workbook.Use1904DateSystem);

Leave it alone unless you are reading a file that already uses the 1904 system.

Right-to-left

workbook.RightToLeft = true; // default for new sheets
workbook.Worksheet("Data").RightToLeft = true; // per sheet

Default style

workbook.Style is the style every new cell inherits. Setting it once is far cheaper than styling cells individually:

workbook.Style.Font.FontName = "Calibri";
workbook.Style.Font.FontSize = 11;
workbook.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;

It is also the starting point for building a reusable style — see Styling.

Protection

Workbook structure

Workbook protection stops the structure changing — sheets being added, deleted, renamed, or reordered. It does not protect cell contents; that is sheet protection.

workbook.Protect("s3cret");

// Allow window moves but lock the structure
workbook.Protect("s3cret", XLProtectionAlgorithm.Algorithm.SHA512,
XLWorkbookProtectionElements.Windows);

Console.WriteLine(workbook.IsProtected);
Console.WriteLine(workbook.IsPasswordProtected);

workbook.Unprotect("s3cret");

Elements: Structure, Windows, Everything, None.

Two hashing algorithms are available: SimpleHash (the default, matching Excel's legacy scheme) and SHA512. Pass SHA512 explicitly for new files unless you need the old format:

workbook.Protect("s3cret", XLProtectionAlgorithm.Algorithm.SHA512);
warning

Neither workbook nor sheet protection encrypts anything. The data is stored in plain text inside the .xlsx and any tool — including XLibur — can read it without the password. Treat it as a guard against accidental edits, not as security. To genuinely protect contents, see Encryption — or restrict access to the file.

Read-only recommendation

A softer signal: Excel prompts the user to open the file read-only.

workbook.FileSharing.ReadOnlyRecommended = true;
workbook.FileSharing.UserName = "Reporting Service";

Load options

LoadOptions configures a workbook as it is constructed — for both new and loaded files:

var options = new LoadOptions
{
RecalculateAllFormulas = true, // recalculate during load; default false
Dpi = new Point(120, 120), // affects text measurement and image sizing
FontEngine = new SkiaSharpFontEngine("Arial"),
};

using var workbook = new XLWorkbook("Report.xlsx", options);
using var fresh = new XLWorkbook(options);
OptionEffect
RecalculateAllFormulasRe-evaluate every formula on load rather than trusting cached values
DpiResolution assumed for text measurement and images; default 96×96
FontEnginePer-workbook font engine — see Fonts
GraphicEnginePer-workbook image handling engine
PasswordDecrypts a password-protected workbook — see Encryption

Two static members set global defaults for every workbook that does not specify its own:

LoadOptions.DefaultFontEngine = new SkiaSharpFontEngine("Arial");
LoadOptions.DefaultGraphicEngine = customEngine;

Save options

SaveOptions controls what happens on the way out:

var options = new SaveOptions
{
EvaluateFormulasBeforeSaving = true,
ValidatePackage = true,
ConsolidateConditionalFormatRanges = true,
ConsolidateDataValidationRanges = true,
GenerateCalculationChain = true,
FilterPrivacy = true,
CompressionLevel = CompressionLevel.Optimal,
};

workbook.SaveAs("Report.xlsx", options);
OptionDefaultEffect
EvaluateFormulasBeforeSavingfalseCompute formula results and store them alongside the formulas
ValidatePackagefalseRun OpenXML schema validation before writing — slow, but catches malformed output
ConsolidateConditionalFormatRangestrueMerge adjacent conditional-format ranges to shrink the file
ConsolidateDataValidationRangestrueSame, for data validation
GenerateCalculationChaintrueWrite the calc chain part Excel uses to order recalculation
FilterPrivacynullSet the privacy flag; null leaves it unchanged
CompressionLevelOptimalHow hard to compress the package — Fastest trades size for speed
PasswordnullEncrypt the saved file — see Encryption
CompressionLevel applies to new parts

It is honoured for parts the save creates. Re-saving a workbook that was loaded from an existing file leaves that file's existing parts at whatever level they were originally written with, because those parts are updated rather than recreated. A workbook built from scratch is unaffected.

XLStreamingOptions.CompressionLevel is the equivalent for a streaming write, where it applies to everything.

The shorthand overloads cover the two common cases:

workbook.SaveAs("Report.xlsx"); // fast path
workbook.SaveAs("Report.xlsx", validate: true, evaluateFormulae: true);
workbook.Save(); // back to where it was loaded from
workbook.Save(validate: false, evaluateFormulae: true);
note

ValidatePackage is worth switching on in tests and leaving off in production — it walks the whole package against the OpenXML schema, which is expensive on large files.

Disposal

XLWorkbook implements IDisposable. Always dispose it, and prefer a using declaration:

using var workbook = new XLWorkbook("Report.xlsx");
// ...

Long-lived workbooks held in a field or a cache keep their whole cell model in memory. For a service generating files per request, construct, save, and dispose within the request.

A worked example

using System.Drawing;
using XLibur.Excel;

var loadOptions = new LoadOptions
{
RecalculateAllFormulas = false,
Dpi = new Point(96, 96),
};

using var workbook = new XLWorkbook(loadOptions)
{
Author = "Reporting Service",
};

// Document metadata
workbook.Properties.Title = "Q1 Sales Report";
workbook.Properties.Subject = "Regional performance";
workbook.Properties.Company = "Example Ltd";
workbook.Properties.Category = "Finance";
workbook.Properties.Status = "Final";
workbook.Properties.Created = DateTime.UtcNow;

// Provenance, so support can tell where a file came from
workbook.CustomProperties.Add("SourceSystem", "sales-api");
workbook.CustomProperties.Add("GeneratedAtUtc", DateTime.UtcNow);
workbook.CustomProperties.Add("RunId", 48213);

// House style
workbook.Style.Font.FontName = "Calibri";
workbook.Style.Font.FontSize = 11;

var ws = workbook.Worksheets.Add("Summary");
ws.Cell("A1").Value = "Q1 Sales Report";
ws.Cell("A1").Style.Font.SetBold().Font.SetFontSize(16);
ws.Cell("A3").FormulaA1 = "=TODAY()";
ws.Cell("A3").Style.DateFormat.Format = "yyyy-MM-dd";

// Recalculate automatically when opened
workbook.CalculateMode = XLCalculateMode.Auto;

// Lock the structure so the sheet layout survives contact with users,
// and hint that the file is not meant to be edited
workbook.Protect("s3cret", XLProtectionAlgorithm.Algorithm.SHA512,
XLWorkbookProtectionElements.Structure);
workbook.FileSharing.ReadOnlyRecommended = true;

workbook.SaveAs("Q1Sales.xlsx", new SaveOptions
{
EvaluateFormulasBeforeSaving = true,
ValidatePackage = false,
});

Where to next

  • Worksheets — sheet-level protection and view settings
  • Formulas — calculation mode and evaluation in detail
  • Fonts — the font engine LoadOptions selects