Styles

Font, Fill, Border, Alignment, NumberFormat, Stylesheet.

116 exports from 12 source files

Cell style

src/styles/cell-style.ts

alignCellHorizontal function

src/styles/cell-style.ts:579

Set the horizontal alignment in isolation.

function alignCellHorizontal(wb: Workbook, c: Cell, horizontal: HorizontalAlignment): void

Parameters

NameTypeDescription
wb Workbook
c Cell
horizontal HorizontalAlignment

Returns

void

alignCellVertical function

src/styles/cell-style.ts:585

Set the vertical alignment in isolation.

function alignCellVertical(wb: Workbook, c: Cell, vertical: VerticalAlignment): void

Parameters

NameTypeDescription
wb Workbook
c Cell
vertical VerticalAlignment

Returns

void

applyBuiltinStyle function

src/styles/cell-style.ts:719

Apply a built-in Excel style ("Heading 1" / "Total" / "Good" / "Bad" / "Calculation" / etc.) to a single cell. Registers the built-in on the Stylesheet (idempotent) and points the cell's xf at it via xfId while inheriting the matching font/fill/border/ numFmt ids so the cell renders correctly on its own.

Throws when name isn't in BUILTIN_NAMED_STYLES; use applyNamedStyle for user-registered styles.

function applyBuiltinStyle(wb: Workbook, c: Cell, name: string): void

Parameters

NameTypeDescription
wb Workbook
c Cell
name string

Returns

void

applyNamedStyle function

src/styles/cell-style.ts:728

Apply a NamedStyle that's already registered on the workbook (via addNamedStyle or ensureBuiltinStyle) to a single cell, by name.

function applyNamedStyle(wb: Workbook, c: Cell, name: string): void

Parameters

NameTypeDescription
wb Workbook
c Cell
name string

Returns

void

cellStyleToCss function

src/styles/cell-style.ts:106

Aggregate fontToCss + fillToCss + borderToCss + alignmentToCss for a cell into a single CSS-property record. Resolves the cell's styleId against the workbook stylesheet, then merges the four partials. On key collision the priority is alignment > border > fill > font (alignment is most specific, font is the broad default). A fully-default cell (styleId === 0 with empty pools) returns {}.

function cellStyleToCss(wb: Workbook, c: Cell): Record<string, string>

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Record<string, string>

centerCell function

src/styles/cell-style.ts:567

Center a cell horizontally + vertically. Mirrors Excel's "Merge & Center" UI button (without the merge — see mergeCells for that). Preserves any other alignment fields already present.

function centerCell(wb: Workbook, c: Cell): void

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

void

clearCellBackground function

src/styles/cell-style.ts:359

Strip the cell's background fill, returning it to the default.

function clearCellBackground(wb: Workbook, c: Cell): void

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

void

clearCellStyle function

src/styles/cell-style.ts:207

Reset a cell back to the default (unstyled) appearance — equivalent to Excel's "Clear Formatting" command. After the call, the cell inherits the workbook's default font / fill / border / alignment / protection / numberFormat. The underlying xf pool is **not** shrunk (Excel doesn't bother either; the orphaned xf is harmless).

function clearCellStyle(_wb: Workbook, c: Cell): void

Parameters

NameTypeDescription
_wb Workbook
c Cell

Returns

void

clearRangeStyle function

src/styles/cell-style.ts:217

Range-level shortcut for clearCellStyle. Walks every cell actually present in the range and resets its styleId to 0; cells that don't exist yet are **not** materialised (no-op for sparse regions, unlike the styled setRange* family which has to create cells to make the patch observable).

function clearRangeStyle(wb: Workbook, ws: Worksheet, range: RangeRef): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef

Returns

void

cloneCellStyle function

src/styles/cell-style.ts:234

Deep-copy the source cell's full xf (font / fill / border / alignment / protection / numberFormat) into a possibly-different workbook. Returns the new styleId in the target workbook.

function cloneCellStyle(sourceWb: Workbook, source: Cell, targetWb: Workbook, target: Cell): number

Parameters

NameTypeDescription
sourceWb Workbook
source Cell
targetWb Workbook
target Cell

Returns

number

copyCellStyle function

src/styles/cell-style.ts:196

Copy the source cell's styleId to the target cell. Both cells share the same workbook stylesheet, so the styled appearance carries over without allocating a new xf entry. Pass cells from different workbooks via cloneCellStyle if you need a deep copy across workbooks.

function copyCellStyle(_wb: Workbook, source: Cell, target: Cell): void

Parameters

NameTypeDescription
_wb Workbook
source Cell
target Cell

Returns

void

formatAsHeader function

src/styles/cell-style.ts:675

Apply Excel's stock "table header" formatting to a range: bold white text on a dark fill, plus a thick bottom border. Override any axis via opts — pass bold: false to drop the bold, or fillColor: 'FF305496' for a different shade. Defaults match Excel's "Table Style Medium 2" header row.

function formatAsHeader(wb: Workbook, ws: Worksheet, range: RangeRef, opts?: { bold?: boolean; bottomBorder?: false | SideStyle; bottomBorderColor?: string | Partial<Color>; fillColor?: string | Partial<Color>; fontColor?: string | Partial<Color> }): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
opts? = {}{ bold?: boolean; bottomBorder?: false | SideStyle; bottomBorderColor?: string | Partial<Color>; fillColor?: string | Partial<Color>; fontColor?: string | Partial<Color> }

Returns

void

getCellAlignment function

src/styles/cell-style.ts:78
function getCellAlignment(wb: Workbook, c: Cell): Alignment

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Alignment

getCellBorder function

src/styles/cell-style.ts:73
function getCellBorder(wb: Workbook, c: Cell): Border

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Border

getCellFill function

src/styles/cell-style.ts:68
function getCellFill(wb: Workbook, c: Cell): Fill

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Fill

getCellFont function

src/styles/cell-style.ts:63
function getCellFont(wb: Workbook, c: Cell): Font

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Font

getCellNumberFormat function

src/styles/cell-style.ts:91

Returns the cell's number-format **code** (e.g. "0.00", "General"). Built-in IDs resolve through builtinFormatCode; custom IDs come from the workbook's numFmts map.

function getCellNumberFormat(wb: Workbook, c: Cell): string

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

string

getCellProtection function

src/styles/cell-style.ts:82
function getCellProtection(wb: Workbook, c: Cell): Protection

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Protection

indentCell function

src/styles/cell-style.ts:601

Set or clear the indent level (0..255).

function indentCell(wb: Workbook, c: Cell, levels: number): void

Parameters

NameTypeDescription
wb Workbook
c Cell
levels number

Returns

void

patchCellFont function

src/styles/cell-style.ts:500

Merge patch over the cell's current font, so the fields left out keep the value they already had (the workbook default, on an unstyled cell). This is the way to change several font fields at once: setCellFont(wb, c, makeFont({ bold: true })) is a legal call that registers a font carrying no name and no size, and Excel, LibreOffice and Sheets each substitute a different one.

A field set to undefined is removed rather than kept, so patchCellFont(wb, c, { underline: undefined }) un-underlines a cell while leaving the rest of its font alone. Omitting the key keeps the current value.

The single-field setters below are this function with one field filled in.

function patchCellFont(wb: Workbook, c: Cell, patch: FontPatch): void

Parameters

NameTypeDescription
wb Workbook
c Cell
patch FontPatch

Returns

void

registerCellStyle function

src/styles/cell-style.ts:299

Register a style and return its styleId. setCell and setCellByCoord take it as their last argument, appendRow and appendRows take it inside { styleIds: [...] }:

``ts const INT = registerCellStyle(wb, { numberFormat: '#,##0' }); setCell(ws, 2, 3, 1234, INT); appendRow(ws, ['de', 71_579], { styleIds: [undefined, INT] }); ``

Build each distinct look once and let the write carry the formatting, instead of running a styling pass over every cell afterwards.

The id names a **complete** style, not a patch: an axis missing from spec resolves to slot 0 of that pool, so it renders as the workbook default even when the target cell previously had something there. setCellStyle is the patch-an-existing-cell counterpart.

"Workbook default" means slot 0 literally. On a workbook from createWorkbook that is the neutral font / no fill / no border. A workbook loaded from another producer may hold anything in slot 0, since nothing in ECMA-376 reserves it, so pass the axis explicitly when the look has to be neutral regardless of what the file arrived with.

function registerCellStyle(wb: Workbook, spec: CellStyleSpec): number

Parameters

NameTypeDescription
wb Workbook
spec CellStyleSpec

Returns

number

rotateCellText function

src/styles/cell-style.ts:595

Rotate the cell's text. degrees accepts 0..180 (clockwise) or 255 for Excel's "vertical stacked" mode. Mirrors the rotate icons in the alignment ribbon.

function rotateCellText(wb: Workbook, c: Cell, degrees: number): void

Parameters

NameTypeDescription
wb Workbook
c Cell
degrees number

Returns

void

setBold function

src/styles/cell-style.ts:508

Toggle bold on a cell. Preserves other font fields.

function setBold(wb: Workbook, c: Cell, on?: boolean): void

Parameters

NameTypeDescription
wb Workbook
c Cell
on? = trueboolean

Returns

void

setCellAlignment function

src/styles/cell-style.ts:173
function setCellAlignment(wb: Workbook, c: Cell, alignment: Alignment): void

Parameters

NameTypeDescription
wb Workbook
c Cell
alignment Alignment

Returns

void

setCellAsCurrency function

src/styles/cell-style.ts:620

Format a cell as currency. Produces one of: - default → "$#,##0.00" (US dollar, 2 decimals) - { symbol: "€" } → "€#,##0.00" - { symbol: "¥", decimals: 0 } → "¥#,##0" - { accounting: true } → "_-$* #,##0.00_-;-$* #,##0.00_-;_-$* \"-\"??_-;_-@_-" (Excel's "Accounting" subtype with right-aligned symbol).

function setCellAsCurrency(wb: Workbook, c: Cell, opts?: { accounting?: boolean; decimals?: number; symbol?: string }): void

Parameters

NameTypeDescription
wb Workbook
c Cell
opts? = {}{ accounting?: boolean; decimals?: number; symbol?: string }

Returns

void

setCellAsDate function

src/styles/cell-style.ts:651

Format a cell as a date. format defaults to Excel's default locale-independent ISO-style date "yyyy-mm-dd". Common alternatives: "m/d/yyyy", "dd-mmm-yy", "yyyy-mm-dd hh:mm:ss".

function setCellAsDate(wb: Workbook, c: Cell, format?: string): void

Parameters

NameTypeDescription
wb Workbook
c Cell
format? = 'yyyy-mm-dd'string

Returns

void

setCellAsNumber function

src/styles/cell-style.ts:659

Format a cell as a thousands-separated number. decimals defaults to 0 → "#,##0"; decimals: 2 → "#,##0.00".

function setCellAsNumber(wb: Workbook, c: Cell, decimals?: number): void

Parameters

NameTypeDescription
wb Workbook
c Cell
decimals? = 0number

Returns

void

setCellAsPercent function

src/styles/cell-style.ts:638

Format a cell as a percentage. decimals defaults to 0 → "0%"; decimals: 2 → "0.00%". The cell value is multiplied by 100 by Excel during display.

function setCellAsPercent(wb: Workbook, c: Cell, decimals?: number): void

Parameters

NameTypeDescription
wb Workbook
c Cell
decimals? = 0number

Returns

void

setCellBackgroundColor function

src/styles/cell-style.ts:353

Set the cell's background to a solid color. Accepts a hex string ('FFAAFFAA') or a partial Color object ({ theme: 4, tint: 0.4 }). Equivalent to setCellFill(wb, c, makePatternFill({ patternType: 'solid', fgColor: makeColor(...) })).

function setCellBackgroundColor(wb: Workbook, c: Cell, color: string | Partial<Color>): void

Parameters

NameTypeDescription
wb Workbook
c Cell
color string | Partial<Color>

Returns

void

setCellBorder function

src/styles/cell-style.ts:168
function setCellBorder(wb: Workbook, c: Cell, border: Border): void

Parameters

NameTypeDescription
wb Workbook
c Cell
border Border

Returns

void

setCellBorderAll function

src/styles/cell-style.ts:776

Apply the same SideStyle to all four edges of a single cell. Optional color via hex string or Color partial. Equivalent to setCellBorder(wb, c, makeBorder({ left, right, top, bottom: side })) with all four sides identical.

function setCellBorderAll(wb: Workbook, c: Cell, opts?: { color?: string | Partial<Color>; style: SideStyle }): void

Parameters

NameTypeDescription
wb Workbook
c Cell
opts? = ...{ color?: string | Partial<Color>; style: SideStyle }

Returns

void

setCellFill function

src/styles/cell-style.ts:163
function setCellFill(wb: Workbook, c: Cell, fill: Fill): void

Parameters

NameTypeDescription
wb Workbook
c Cell
fill Fill

Returns

void

setCellFont function

src/styles/cell-style.ts:158

Replace the cell's font outright. font has to be complete: anything it omits is omitted from the <font> record too, and each viewer then falls back to its own default rather than the workbook's. Reach for patchCellFont unless you really mean "this font and nothing inherited".

function setCellFont(wb: Workbook, c: Cell, font: Font): void

Parameters

NameTypeDescription
wb Workbook
c Cell
font Font

Returns

void

setCellNumberFormat function

src/styles/cell-style.ts:185

Set the cell's number format by its **code** string. Built-in codes resolve to their canonical id; custom codes are registered via addNumFmt.

function setCellNumberFormat(wb: Workbook, c: Cell, formatCode: string): void

Parameters

NameTypeDescription
wb Workbook
c Cell
formatCode string

Returns

void

setCellProtection function

src/styles/cell-style.ts:177
function setCellProtection(wb: Workbook, c: Cell, protection: Protection): void

Parameters

NameTypeDescription
wb Workbook
c Cell
protection Protection

Returns

void

setCellStyle function

src/styles/cell-style.ts:339

Combined cell-style setter, patching the cell's existing xf. Each axis is independent, so pass any subset and the corresponding applyXxx flags get set on the underlying CellXf. Avoids 5+ separate stylesheet round-trips when a caller wants to style a single cell across multiple axes (Excel dedupes the resulting xf record on every call).

function setCellStyle(wb: Workbook, c: Cell, spec: CellStyleSpec): void

Parameters

NameTypeDescription
wb Workbook
c Cell
spec CellStyleSpec

Returns

void

setFontColor function

src/styles/cell-style.ts:551

Set the font color. Accepts a hex string ("FFAA0033") or a partial Color object ({ theme: 4, tint: 0.4 }). Preserves other font fields.

function setFontColor(wb: Workbook, c: Cell, color: string | Partial<Color>): void

Parameters

NameTypeDescription
wb Workbook
c Cell
color string | Partial<Color>

Returns

void

setFontName function

src/styles/cell-style.ts:543

Set the font family name (e.g. "Arial"). Preserves other fields.

function setFontName(wb: Workbook, c: Cell, name: string): void

Parameters

NameTypeDescription
wb Workbook
c Cell
name string

Returns

void

setFontSize function

src/styles/cell-style.ts:538

Set the font size in points (e.g. 14). Preserves other fields.

function setFontSize(wb: Workbook, c: Cell, size: number): void

Parameters

NameTypeDescription
wb Workbook
c Cell
size number

Returns

void

setItalic function

src/styles/cell-style.ts:513

Toggle italic on a cell.

function setItalic(wb: Workbook, c: Cell, on?: boolean): void

Parameters

NameTypeDescription
wb Workbook
c Cell
on? = trueboolean

Returns

void

setRangeAlignment function

src/styles/cell-style.ts:462

Range-level Alignment setter. Two modes:

- mode: 'merge' (default) — each cell's existing alignment is preserved; the supplied partial overlays it. Use this when you want to set just horizontal or vertical without wiping the other axes. - mode: 'replace' — each cell's alignment is **wholly replaced** by the supplied value. Indent / textRotation / wrapText that weren't supplied are dropped.

Empty cells in the range are materialised so the patch is observable on round-trip.

function setRangeAlignment(wb: Workbook, ws: Worksheet, range: RangeRef, alignment: Partial<Alignment>, mode?: "replace" | "merge"): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
alignment Partial<Alignment>
mode? = 'merge'"replace" | "merge"

Returns

void

setRangeBackgroundColor function

src/styles/cell-style.ts:368

Range-level shortcut for setCellBackgroundColor. Each cell in the range gets the same solid pattern fill via setRangeStyle, so the fill pool dedups to a single entry across the whole range.

function setRangeBackgroundColor(wb: Workbook, ws: Worksheet, range: RangeRef, color: string | Partial<Color>): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
color string | Partial<Color>

Returns

void

setRangeBorderBox function

src/styles/cell-style.ts:793

Draw an outer border around a rectangular range. Cells on the perimeter receive a partial border (only the edges that face outside the range); inner cells are unaffected unless inner is provided, in which case every cell in the range receives a border combining its perimeter edges with the inner style for the inside edges.

function setRangeBorderBox(wb: Workbook, ws: Worksheet, range: RangeRef, opts?: { color?: string | Partial<Color>; inner?: SideStyle; style: SideStyle }): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
opts? = ...{ color?: string | Partial<Color>; inner?: SideStyle; style: SideStyle }

Returns

void

setRangeFont function

src/styles/cell-style.ts:386

Range-level shortcut for setCellFont. Replaces the whole Font on every cell in the range; there is no range-level merge, so build the complete font you want rather than passing makeFont({ bold: true }) and losing the workbook default.

function setRangeFont(wb: Workbook, ws: Worksheet, range: RangeRef, font: Font): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
font Font

Returns

void

setRangeNumberFormat function

src/styles/cell-style.ts:400

Range-level shortcut for setCellNumberFormat. Stamps the same format-code onto every cell in the range; the numFmt pool dedups the code so callers don't pay per-cell pool churn.

function setRangeNumberFormat(wb: Workbook, ws: Worksheet, range: RangeRef, formatCode: string): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
formatCode string

Returns

void

setRangeProtection function

src/styles/cell-style.ts:418

Range-level shortcut for setCellProtection. Stamps the same Protection (locked / hidden) onto every cell in the range. Pass a full Protection value or a partial — partials default missing fields to false per Excel's <protection> semantics.

Common usage: setRangeProtection(wb, ws, 'B2:B100', { locked: false }) to leave just an input column editable when the sheet is protected.

function setRangeProtection(wb: Workbook, ws: Worksheet, range: RangeRef, protection: Protection | Partial<Protection>): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
protection Protection | Partial<Protection>

Returns

void

setRangeStyle function

src/styles/cell-style.ts:314

Build a single CellXf from a multi-axis style spec, then merge it into every cell in range. The xf is registered once per style shape, so a 1000-cell range allocates one xf, which is much faster than looping setCellStyle per cell.

Each cell keeps the axes spec leaves out, which is what separates this from registerCellStyle: the id that returns is a whole style, this is a patch over whatever each cell already carried.

function setRangeStyle(wb: Workbook, ws: Worksheet, range: RangeRef, spec: CellStyleSpec): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
spec CellStyleSpec

Returns

void

setRangeWrapText function

src/styles/cell-style.ts:437

Range-level shortcut for wrapCellText. Toggles "Wrap Text" on every cell in the range while preserving each cell's existing alignment (horizontal / vertical / textRotation / indent are not touched). Empty cells in the range are materialised so the alignment patch is observable on round-trip.

function setRangeWrapText(wb: Workbook, ws: Worksheet, range: RangeRef, on?: boolean): void

Parameters

NameTypeDescription
wb Workbook
ws Worksheet
range RangeRef
on? = trueboolean

Returns

void

setStrikethrough function

src/styles/cell-style.ts:518

Toggle strike-through on a cell.

function setStrikethrough(wb: Workbook, c: Cell, on?: boolean): void

Parameters

NameTypeDescription
wb Workbook
c Cell
on? = trueboolean

Returns

void

setUnderline function

src/styles/cell-style.ts:528

Set the underline style. Pass false to drop underline; pass 'single' | 'double' | 'singleAccounting' | 'doubleAccounting' to apply that style; pass true for the most common single-line. Pass 'none' to preserve an explicit no-underline value in XML.

function setUnderline(wb: Workbook, c: Cell, style?: boolean | UnderlineStyle): void

Parameters

NameTypeDescription
wb Workbook
c Cell
style? = 'single'boolean | UnderlineStyle

Returns

void

wrapCellText function

src/styles/cell-style.ts:573

Toggle "Wrap Text" on a cell, preserving other alignment fields.

function wrapCellText(wb: Workbook, c: Cell, wrap?: boolean): void

Parameters

NameTypeDescription
wb Workbook
c Cell
wrap? = trueboolean

Returns

void

Numbers

src/styles/numbers.ts

builtinFormatCode function

src/styles/numbers.ts:77

Look up the format code for a given numFmtId, or undefined if unknown.

function builtinFormatCode(id: number): string | undefined

Parameters

NameTypeDescription
id number

Returns

string | undefined

builtinFormatId function

src/styles/numbers.ts:82

Look up the numFmtId for a given format code, or undefined if not built-in.

function builtinFormatId(code: string): number | undefined

Parameters

NameTypeDescription
code string

Returns

number | undefined

classifyDateFormat function

src/styles/numbers.ts:134

Categorise a date format as 'date', 'time', 'datetime' or undefined.

function classifyDateFormat(code: string | null | undefined): "date" | "time" | "datetime" | undefined

Parameters

NameTypeDescription
code string | null | undefined

Returns

"date" | "time" | "datetime" | undefined

isBuiltinFormat function

src/styles/numbers.ts:87

True iff code is one of the OOXML built-in format strings.

function isBuiltinFormat(code: string): boolean

Parameters

NameTypeDescription
code string

Returns

boolean

isDateFormat function

src/styles/numbers.ts:119

Heuristic: does the format string imply a date / time interpretation? Looks at only the first format section (positive-value branch); strips literals, colour codes and locale modifiers before scanning for date tokens (d/m/h/y/s, case-insensitive) that aren't escaped.

function isDateFormat(code: string | null | undefined): boolean

Parameters

NameTypeDescription
code string | null | undefined

Returns

boolean

isTimedeltaFormat function

src/styles/numbers.ts:127

Heuristic: does the format string indicate a duration ([h]:mm:ss etc.)?

function isTimedeltaFormat(code: string | null | undefined): boolean

Parameters

NameTypeDescription
code string | null | undefined

Returns

boolean

makeNumberFormat function

src/styles/numbers.ts:161
function makeNumberFormat(opts: { formatCode: string; numFmtId: number }): NumberFormat

Parameters

NameTypeDescription
opts { formatCode: string; numFmtId: number }

Returns

NumberFormat

BUILTIN_FORMATS const

src/styles/numbers.ts:13

Canonical OOXML built-in number formats — verbatim from openpyxl.

const BUILTIN_FORMATS: Readonly<Record<number, string>>

BUILTIN_FORMATS_MAX_SIZE const

src/styles/numbers.ts:55

First numFmtId Excel reserves for user-defined formats.

const BUILTIN_FORMATS_MAX_SIZE: 164

FORMAT_DATE_DATETIME const

src/styles/numbers.ts:70
const FORMAT_DATE_DATETIME: "yyyy-mm-dd h:mm:ss"

FORMAT_DATE_TIMEDELTA const

src/styles/numbers.ts:71
const FORMAT_DATE_TIMEDELTA: "[hh]:mm:ss"

FORMAT_DATE_YYYYMMDD2 const

src/styles/numbers.ts:72
const FORMAT_DATE_YYYYMMDD2: "yyyy-mm-dd"

FORMAT_GENERAL const

src/styles/numbers.ts:64
const FORMAT_GENERAL: "General"

FORMAT_NUMBER const

src/styles/numbers.ts:66
const FORMAT_NUMBER: "0"

FORMAT_NUMBER_00 const

src/styles/numbers.ts:67
const FORMAT_NUMBER_00: "0.00"

FORMAT_PERCENTAGE const

src/styles/numbers.ts:68
const FORMAT_PERCENTAGE: "0%"

FORMAT_PERCENTAGE_00 const

src/styles/numbers.ts:69
const FORMAT_PERCENTAGE_00: "0.00%"

FORMAT_TEXT const

src/styles/numbers.ts:65
const FORMAT_TEXT: "@"

Colors

src/styles/colors.ts

adjustLightness function

src/styles/colors.ts:325

Adjust the lightness of a color by delta (added directly to the [0, 1] lightness channel and clamped). Positive = lighter, negative = darker. Distinct from lighten / darken which mix toward white/black in RGB space.

function adjustLightness(hex: string, delta: number): string

Parameters

NameTypeDescription
hex string
delta number

Returns

string

adjustSaturation function

src/styles/colors.ts:314

Adjust the saturation of a color by delta (added directly to the [0, 1] saturation channel and clamped). Positive = more vivid, negative = closer to gray. Hue, lightness, and alpha are preserved.

function adjustSaturation(hex: string, delta: number): string

Parameters

NameTypeDescription
hex string
delta number

Returns

string

colorToHex function

src/styles/colors.ts:177

Read a Color value-object back to a normalised ARGB hex. Resolution order: explicit rgb → indexed palette lookup. Returns undefined for theme / auto / empty inputs (unresolvable without a theme), so callers can fall back to a default.

function colorToHex(color: Color | undefined): string | undefined

Parameters

NameTypeDescription
color Color | undefined

Returns

string | undefined

contrastRatio function

src/styles/colors.ts:206

WCAG contrast ratio between two ARGB hex colors. Returns a value in [1, 21]; 1 = identical luminance, 21 = pure black on pure white. The order of arguments doesn't matter.

function contrastRatio(hexA: string, hexB: string): number

Parameters

NameTypeDescription
hexA string
hexB string

Returns

number

darken function

src/styles/colors.ts:256

Darken a color by mixing it with black. amount is in [0, 1]: 0 returns the input unchanged, 1 returns pure black (preserving the alpha channel).

function darken(hex: string, amount: number): string

Parameters

NameTypeDescription
hex string
amount number

Returns

string

hexToHsl function

src/styles/colors.ts:279

Convert an ARGB / RGB hex to its HSL representation. Returns { h, s, l, a } with h ∈ [0, 360), s ∈ [0, 1], l ∈ [0, 1], a ∈ [0, 255] (alpha as the original byte). Useful for theme tweaking (rotate hue, desaturate, etc.) before round-tripping through hslToHex.

function hexToHsl(hex: string): { a: number; h: number; l: number; s: number }

Parameters

NameTypeDescription
hex string

Returns

{ a: number; h: number; l: number; s: number }

hslToHex function

src/styles/colors.ts:335

Convert HSL components back to an ARGB hex string. h wraps mod-360, s and l clamp to [0, 1]. alpha is the byte (default 255 = opaque), placed in the high byte of the result.

function hslToHex(h: number, s: number, l: number, alpha?: number): string

Parameters

NameTypeDescription
h number
s number
l number
alpha? = 255number

Returns

string

lighten function

src/styles/colors.ts:246

Lighten a color by mixing it with white. amount is in [0, 1]: 0 returns the input unchanged, 1 returns pure white. Alpha channel is preserved. Equivalent to mixColors(hex, 'FFFFFFFF', amount).

function lighten(hex: string, amount: number): string

Parameters

NameTypeDescription
hex string
amount number

Returns

string

luminance function

src/styles/colors.ts:192

Compute the relative luminance of an ARGB / RGB hex string per the WCAG 2.x formula. Returns a value in [0, 1] where 0 is black and 1 is white. The alpha channel (if present) is ignored.

function luminance(hex: string): number

Parameters

NameTypeDescription
hex string

Returns

number

mixColors function

src/styles/colors.ts:266

Linearly interpolate between two ARGB colors. t = 0 returns hexA; t = 1 returns hexB; intermediate values mix per channel (including alpha).

function mixColors(hexA: string, hexB: string, t: number): string

Parameters

NameTypeDescription
hexA string
hexB string
t number

Returns

string

normaliseRgb function

src/styles/colors.ts:122

Normalise an aRGB hex string. Accepts either 6 or 8 hex digits; 6-digit input is padded to 8 by prefixing 00 (alpha=0 = fully opaque per Excel convention). Returns the canonical uppercase form.

function normaliseRgb(value: string): string

Parameters

NameTypeDescription
value string

Returns

string

pickReadableTextColor function

src/styles/colors.ts:218

Pick the higher-contrast text color ('FF000000' black or 'FFFFFFFF' white) for a background hex. Useful when applying a solid fill and wanting the cell text to stay readable.

function pickReadableTextColor(backgroundHex: string): "FF000000" | "FFFFFFFF"

Parameters

NameTypeDescription
backgroundHex string

Returns

"FF000000" | "FFFFFFFF"

resolveIndexedColor function

src/styles/colors.ts:162

Resolve indexed references against COLOR_INDEX. Returns undefined for 64/65 (system fg/bg, not in the palette) or out-of-range.

function resolveIndexedColor(idx: number): string | undefined

Parameters

NameTypeDescription
idx number

Returns

string | undefined

rgbColor function

src/styles/colors.ts:167

Shortcut for the common opaque solid colour.

function rgbColor(hex: string): Color

Parameters

NameTypeDescription
hex string

Returns

Color

rotateHue function

src/styles/colors.ts:304

Rotate the hue of a color by degrees (positive = clockwise). Saturation and lightness are preserved; alpha is preserved. Equivalent to hexToHsl → adjust h → hslToHex.

function rotateHue(hex: string, degrees: number): string

Parameters

NameTypeDescription
hex string
degrees number

Returns

string

Stylesheet

src/styles/stylesheet.ts

addBorder function

src/styles/stylesheet.ts:124

Add a Border to the pool, returning its 0-based index. Idempotent.

function addBorder(ss: Stylesheet, border: Border): number

Parameters

NameTypeDescription
ss Stylesheet
border Border

Returns

number

addCellStyleXf function

src/styles/stylesheet.ts:152

Add a CellXf to the cellStyleXfs pool. Idempotent.

function addCellStyleXf(ss: Stylesheet, xf: CellXf): number

Parameters

NameTypeDescription
ss Stylesheet
xf CellXf

Returns

number

addCellXf function

src/styles/stylesheet.ts:146

Add a CellXf to the cellXfs pool, returning its 0-based index. Idempotent.

function addCellXf(ss: Stylesheet, xf: CellXf): number

Parameters

NameTypeDescription
ss Stylesheet
xf CellXf

Returns

number

addFill function

src/styles/stylesheet.ts:119

Add a Fill to the pool, returning its 0-based index. Idempotent.

function addFill(ss: Stylesheet, fill: Fill): number

Parameters

NameTypeDescription
ss Stylesheet
fill Fill

Returns

number

addFont function

src/styles/stylesheet.ts:114

Add a Font to the pool, returning its 0-based index. Idempotent.

function addFont(ss: Stylesheet, font: Font): number

Parameters

NameTypeDescription
ss Stylesheet
font Font

Returns

number

addNumFmt function

src/styles/stylesheet.ts:134

Resolve a number-format string to its numFmtId. - Built-in codes return their canonical OOXML ID. - Otherwise the custom code is registered (and allocated an ID ≥ BUILTIN_FORMATS_MAX_SIZE). Idempotent.

function addNumFmt(ss: Stylesheet, formatCode: string): number

Parameters

NameTypeDescription
ss Stylesheet
formatCode string

Returns

number

defaultCellXf function

src/styles/stylesheet.ts:232

Convenience: build the default cellXfs[0] Excel emits — points at the workbook's font 0 / fill 0 / border 0 / numFmtId 0 (General).

function defaultCellXf(): CellXf

Returns

CellXf

listBorders function

src/styles/stylesheet.ts:214

Every Border entry in the pool, indexed by id. Live, as listFonts.

function listBorders(ss: Stylesheet): readonly Border[]

Parameters

NameTypeDescription
ss Stylesheet

Returns

readonly Border[]

listCellStyleXfs function

src/styles/stylesheet.ts:224

Every CellStyleXf entry (named-style xfs). Live, as listFonts.

function listCellStyleXfs(ss: Stylesheet): readonly CellXf[]

Parameters

NameTypeDescription
ss Stylesheet

Returns

readonly CellXf[]

listCellXfs function

src/styles/stylesheet.ts:219

Every CellXf entry in the cellXfs pool. Live, as listFonts.

function listCellXfs(ss: Stylesheet): readonly CellXf[]

Parameters

NameTypeDescription
ss Stylesheet

Returns

readonly CellXf[]

listFills function

src/styles/stylesheet.ts:209

Every Fill entry in the pool, indexed by id. Live, as listFonts.

function listFills(ss: Stylesheet): readonly Fill[]

Parameters

NameTypeDescription
ss Stylesheet

Returns

readonly Fill[]

listFonts function

src/styles/stylesheet.ts:204

Every Font entry in the pool, indexed by id, as a read-only view of the live array, not a copy: a later addFont is visible through it. The same holds for the other pool accessors below.

function listFonts(ss: Stylesheet): readonly Font[]

Parameters

NameTypeDescription
ss Stylesheet

Returns

readonly Font[]

makeStylesheet function

src/styles/stylesheet.ts:86

Build a fresh Stylesheet pre-populated with Excel's required default entries. Mirrors openpyxl's empty Stylesheet: fonts: [DEFAULT_FONT] (index 0) fills: [DEFAULT_EMPTY_FILL, DEFAULT_GRAY_FILL] (indices 0, 1 — required) borders: [DEFAULT_BORDER] (index 0) cellXfs: empty (indices allocated on demand)

function makeStylesheet(): Stylesheet

Returns

Stylesheet

Borders

src/styles/borders.ts

borderToCss function

src/styles/borders.ts:150

Translate a Border to a CSS-property record suitable for HTML preview. Each present side becomes border-<edge>: <width> <style> <#color>. Theme/auto/missing colours fall back to currentColor. Diagonal / vertical / horizontal sides are skipped (CSS has no native equivalent for in-cell strokes). Empty Border returns {}.

function borderToCss(border: Border | undefined): Record<string, string>

Parameters

NameTypeDescription
border Border | undefined

Returns

Record<string, string>

makeBorder function

src/styles/borders.ts:89

Build an immutable Border.

function makeBorder(opts?: Partial<Border>): Border

Parameters

NameTypeDescription
opts? = {}Partial<Border>

Returns

Border

makeSide function

src/styles/borders.ts:55

Build an immutable Side.

function makeSide(opts?: Partial<Side>): Side

Parameters

NameTypeDescription
opts? = {}Partial<Side>

Returns

Side

Fills

src/styles/fills.ts

fillToCss function

src/styles/fills.ts:174

Translate a Fill to a CSS-property record suitable for HTML preview. 'solid' PatternFill renders as background-color, other pattern types collapse to bgColor (CSS has no built-in equivalent of Excel hatch patterns). GradientFill emits a CSS background-image with linear-gradient(<angle>, …) for type='linear' or radial-gradient(circle, …) for type='path'.

theme/auto colours and unresolvable inputs are skipped (returns {}) so callers can spread without overwriting upstream defaults.

function fillToCss(fill: Fill | undefined): Record<string, string>

Parameters

NameTypeDescription
fill Fill | undefined

Returns

Record<string, string>

makeFill function

src/styles/fills.ts:144

Single-arg constructor that defers to the variant-specific maker based on kind. Useful when the caller has a plain object in hand and wants the freeze invariant applied uniformly.

function makeFill(opts: Partial<PatternFill> | Partial<GradientFill>): Fill

Parameters

NameTypeDescription
opts Partial<PatternFill> | Partial<GradientFill>

Returns

Fill

makeGradientStop function

src/styles/fills.ts:110
function makeGradientStop(position: number, color: Color | Partial<Color>): GradientStop

Parameters

NameTypeDescription
position number
color Color | Partial<Color>

Returns

GradientStop

Fonts

src/styles/fonts.ts

fontToCss function

src/styles/fonts.ts:144

Translate a Font to a CSS-property record suitable for HTML rendering / preview. Boolean toggles map to weight/style/decoration, size becomes font-size: <n>pt, and an explicit rgb/indexed color is rendered as #RRGGBB (alpha dropped). theme/auto colours are skipped — callers without a theme can't resolve them.

vertAlign='superscript'|'subscript' lowers font-size to 0.83em (W3C convention) and sets vertical-align.

Returns {} for an empty Font so callers can spread it without overwriting upstream defaults.

function fontToCss(font: Font | undefined): Record<string, string>

Parameters

NameTypeDescription
font Font | undefined

Returns

Record<string, string>

makeFont function

src/styles/fonts.ts:61
function makeFont(opts?: FontPatch): Font

Parameters

NameTypeDescription
opts? = {}FontPatch

Returns

Font

DEFAULT_FONT const

src/styles/fonts.ts:123

Excel's default cell font: Calibri 11, minor scheme, theme=1 colour.

const DEFAULT_FONT: Font

Named styles

src/styles/named-styles.ts

addNamedStyle function

src/styles/named-styles.ts:69

Register a NamedStyle on the Stylesheet: 1. add Font / Fill / Border / NumberFormat to their pools 2. push a CellXf with apply* flags into cellStyleXfs 3. append a {name, xfId, builtinId} entry into the workbook's namedStyles list (caller-managed; this function returns the xfId so callers can connect the dots) Idempotent on (name): re-registering by the same name returns the cached xfId.

function addNamedStyle(ss: Stylesheet, style: NamedStyle): number

Parameters

NameTypeDescription
ss Stylesheet
style NamedStyle

Returns

number

ensureBuiltinStyle function

src/styles/named-styles.ts:255

Register a built-in style with the supplied Stylesheet (idempotent). Returns the cellStyleXfs index. Throws OpenXmlSchemaError when the name is unknown.

function ensureBuiltinStyle(ss: Stylesheet, name: string): number

Parameters

NameTypeDescription
ss Stylesheet
name string

Returns

number

BUILTIN_NAMED_STYLES const

src/styles/named-styles.ts:127

Curated subset of openpyxl's styles dict. Keys match the user-visible names.

const BUILTIN_NAMED_STYLES: Readonly<Record<string, NamedStyle>>

Alignment

src/styles/alignment.ts

alignmentToCss function

src/styles/alignment.ts:136

Translate an Alignment to a CSS-property record suitable for HTML preview. horizontal → text-align, vertical → vertical-align (table-cell semantics), wrapText → white-space: pre-wrap, textRotation → transform: rotate(<-deg>) (Excel rotates counter-clockwise relative to CSS) plus transform-origin to keep the text anchored, and indent → padding-left: <n>em. 255 stacked-text rotation maps to a 180° flip with writing-mode.

Empty / undefined Alignment returns {}.

function alignmentToCss(alignment: Alignment | undefined): Record<string, string>

Parameters

NameTypeDescription
alignment Alignment | undefined

Returns

Record<string, string>

makeAlignment function

src/styles/alignment.ts:54
function makeAlignment(opts?: Partial<Alignment>): Alignment

Parameters

NameTypeDescription
opts? = {}Partial<Alignment>

Returns

Alignment

Differential

src/styles/differential.ts

addDxf function

src/styles/differential.ts:62

Add a DifferentialStyle to the stylesheet's dxfs pool. Returns the 0-based index. Idempotent on structural equality (via stableStringify).

function addDxf(ss: Stylesheet, dxf: DifferentialStyle): number

Parameters

NameTypeDescription
ss Stylesheet
dxf DifferentialStyle

Returns

number

makeDifferentialStyle function

src/styles/differential.ts:37
function makeDifferentialStyle(opts?: Partial<DifferentialStyle>): DifferentialStyle

Parameters

NameTypeDescription
opts? = {}Partial<DifferentialStyle>

Returns

DifferentialStyle

Display text

src/styles/display-text.ts

getCellDate function

src/styles/display-text.ts:151

The Date a date-formatted cell stands for, or undefined when the cell has no date reading.

Excel stores a date as a plain number of days since the workbook epoch, so nothing in a loaded cell's value distinguishes 45365 the date from 45365 the count: the cell's number format is the only evidence, and cellValueAsDate deliberately does not consult it. This composes the three steps that reading one otherwise takes, getCellNumberFormat then the format's own reading then excelToDate with the epoch from wb.date1904, into the call that reading a foreign workbook actually needs.

- A Date value passes through, formatted or not. - A number needs a format that names a day: a year, month or day part. Without one it is a count, and the answer is undefined. - A formula cell is read from the value Excel cached for it. - A time-of-day format (h:mm) names a moment inside a day but not which day, and an elapsed-time format ([h]:mm) measures a span rather than naming a moment, so neither has a date reading. Neither does a duration value: its ms is already the span. - The format is read by the parser getCellDisplayText renders with, so the two agree on what any one cell is. A code outside the subset that one documents has no date reading here either.

The returned Date is built in UTC, which is how excelToDate and dateToExcel read every serial in this library. Use getUTCFullYear and friends, or the local-time accessors will shift the day for anybody east or west of UTC.

function getCellDate(wb: Workbook, c: Cell): Date | undefined

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

Date | undefined

getCellDisplayText function

src/styles/display-text.ts:118

The text Excel prints in c: the cell's value put through the number format its style points at.

This is not a shorter cellValueAsString. That one takes a CellValue and answers "what is this value in JavaScript terms", so it never sees the stylesheet and cannot know that 0.5 is a percentage or that 45365 is a date. This one takes the workbook and the cell, resolves the cell's numFmt, and answers "what would somebody looking at this file in Excel read". Pick cellValueAsString when you want the value and this when you want the text: writing a sheet out as CSV, rendering it as HTML, diffing two workbooks by what they show, or logging a cell for a human. Choosing wrong fails quietly, which is why both say so.

Covered:

- General, at the 15 significant digits Excel stores. This is what turns =1.1+2.2 into 3.3 rather than 3.3000000000000003. - Every code in BUILTIN_FORMATS, including the accounting codes, scientific notation and the two fraction codes. The one exception is that catalogue's entry for numFmtId 44, whose stored form is missing the ; section separators Excel's own accounting code carries, so it reads as a text layout. - Custom numeric codes: 0 # ? digit placeholders, thousands grouping, trailing commas that divide by a thousand, %, E+/E- (including the engineering step ##0.0E+0), ?/? fractions with a placeholder or a spelled-out denominator, quoted and \-escaped literals, _x width reservations, currency symbols, and colour codes (which change nothing about the text). - The positive / negative / zero / text sections of a multi-section code. A lone section takes the minus sign in front of it; a value that rounds to zero prints without one. - Dates and times: y m d h s runs, mmm / mmmm month names, ddd / dddd weekday names, AM/PM and A/P, fractional seconds, and the elapsed forms [h] [mm] [ss]. - Comparison sections ([<1000]0;[<1000000]0.0,"K";0.0,,"M"), picked the way Excel does; a value no section takes has no reading. - The 1900 system's phantom days: serial 0 prints as 1/0/1900 and 60 as 2/29/1900, as in Excel. - Booleans as TRUE / FALSE, error cells as their token, rich text as its runs joined, a formula cell from the value Excel cached for it, and an empty cell as ''.

Not covered, and the cell falls back to cellValueAsString so the reading is a plain coercion rather than a guess:

- A section splicing two numeric layouts together (0.00" ("0.00")"). - Calendar and numbering modifiers: era tokens (g, e, b) and bracket groups such as [DBNum1] that replace the digits themselves. - More than four sections, or an unterminated " or [.

Three more places where the text is a judgement call, because Excel's own answer is not recoverable from the cell:

- *x repeats x until the column is full, so nothing is printed for it. - Month and weekday names come out in English; a [$-409]-style locale tag is read for its currency symbol and otherwise ignored. - How wide the column is decides how many digits General shows and when it gives up and switches to scientific notation. Every stored digit is kept.

A Date cell value is converted to its serial and run through the format, so it reads as a date only if the cell carries a date format. That is the same rule the file itself follows: the worksheet stores a serial and the style decides what it means. Use setCellAsDate on the write side.

function getCellDisplayText(wb: Workbook, c: Cell): string

Parameters

NameTypeDescription
wb Workbook
c Cell

Returns

string

Protection

src/styles/protection.ts

makeProtection function

src/styles/protection.ts:13
function makeProtection(opts?: Partial<Protection>): Protection

Parameters

NameTypeDescription
opts? = {}Partial<Protection>

Returns

Protection