import { BodyElement, SectionProperties, Table } from '../core/document-model/index.js';
import { CellRange, DefinedName, ParsedWorksheet, SheetRichRun, WorksheetCell, XlsxStyles } from './index.js';
import { SheetHyperlink, SheetSlicer } from '../core/ir/sheet.js';
import { Loss } from '../core/ir/loss.js';
/**
* Excel "character width" → twips: the default font's Maximum Digit Width,
* ~7 px at 96 DPI ≈ 5.25 pt ≈ 105 twips.
*/
export declare const TWIPS_PER_EXCEL_CHAR = 105;
/**
* ECMA-376 §18.3.1.13 — a `
` measures characters of text, and the
* rendered column is that many Maximum Digit Widths PLUS a fixed 5-pixel
* padding: `px = chars × MDW + 5`. 5 px at 96 DPI = 3.75 pt = 75 twips.
*
* Omitting it made every column 75 twips narrow, which compounds: on a sheet of
* equal 12-character columns the third one landed ~37 pt left of where
* LibreOffice puts it. That {@link DEFAULT_COL_TWIPS} below is 960 is the proof
* the padding belongs — 8.43 characters only reaches Excel's documented 64 px
* default with it (8.43 × 7 + 5 = 64.01 px = 48.01 pt = 960 twips), so the
* default was derived from the full formula while the explicit path dropped it.
*/
export declare const COL_PADDING_TWIPS = 75;
/**
* §18.3.1.13 — a `` in twips.
*
* The padding above is the formula for a column at least one character wide.
* Excel documents a SEPARATE one below that: `px = Trunc(width × MDW + 0.5)`,
* with no padding at all. It matters because the padding is a constant: on a
* form drawn over a fine grid — tdf118668.xlsx rules 168 columns of 0.855
* characters — 3.75pt of padding nearly doubles a 4.5pt column, and the sheet
* came out 1384pt wide against the reference's 754, so it paginated across two
* pages where every reader prints one.
*
* @param chars The declared width in characters.
* @param charTwips The Maximum Digit Width, in twips.
* @returns The rendered column width in twips.
*/
export declare function columnTwips(chars: number, charTwips: number): number;
/**
* Excel's default column width is 8.43 "characters" ≈ 64px ≈ 960 twips. Used for
* columns without an explicit ``.
*/
export declare const DEFAULT_COL_TWIPS = 960;
/**
* The row height a sheet that declares none inherits from the workbook's
* Normal font. Sizes outside Excel's table scale from its 10pt entry and snap
* up to the 0.75pt grid row heights are stored on (one pixel at 96 dpi).
*
* @param fontPt The Normal style's font size, or undefined if unknown.
* @returns The default row height in points.
*/
export declare function defaultRowHeightPtFor(fontPt: number | undefined): number;
/**
* Excel's default row height is ~15pt = 300 twips. Used (for the `fitToHeight`
* estimate) for rows without an explicit ``.
*/
export declare const DEFAULT_ROW_TWIPS = 300;
/**
* Build the page section (paper size + margins) from a worksheet's ``
* / ``.
*
* Margins are always set, to Excel's own defaults when the worksheet declares
* none (§18.3.1.62) — the renderer's fallback is a word processor's inch, which
* is not what a spreadsheet prints. The paper size is left unset when the
* worksheet names none, because there the file genuinely holds no answer: Excel
* picks by locale and printer, and the renderer's deterministic A4 is as good
* as anything we could invent.
*/
export declare function sectionFromWorksheet(worksheet: ParsedWorksheet): SectionProperties;
/**
* ECMA-376 §18.2.5 — resolve the sheet-scoped `_xlnm.Print_Area` defined name
* (`localSheetId` = the sheet's 0-based index) into a clipping range.
*/
export declare function resolvePrintArea(definedNames: ReadonlyArray, sheetIdx: number): CellRange | undefined;
/** ECMA-376 §18.2.5 — `_xlnm.Print_Titles` → the repeated row range (0-indexed). */
export declare function resolvePrintTitleRows(definedNames: ReadonlyArray, sheetIdx: number): {
readonly startRow: number;
readonly endRow: number;
} | undefined;
/**
* The width one page has for content: the sheet's paper (declared or the A4
* default) less its left and right margins, in points. The same measure the
* column bands are packed into — a drawing layer banded on any other width
* would not line up with the grid beside it.
*/
export declare function printableWidthPt(worksheet: ParsedWorksheet): number;
/**
* The printable HEIGHT of one page of this sheet, in points — its paper height
* less its own top and bottom margins. The vertical twin of
* {@link printableWidthPt}.
*
* @param worksheet The parsed worksheet (paper + margins).
* @returns The height a page of this sheet has for content, in points.
*/
export declare function printableHeightPt(worksheet: ParsedWorksheet): number;
interface PrintModelOptions {
readonly printArea?: CellRange;
readonly gridLines: boolean;
readonly titleRows?: {
readonly startRow: number;
readonly endRow: number;
};
readonly sheetGrids?: ReadonlyMap;
readonly sheetName?: string;
readonly definedNames?: ReadonlyArray;
readonly hyperlinks?: ReadonlyArray;
readonly sharedStringRuns?: ReadonlyArray | undefined>;
readonly now?: Date;
readonly digitWidthPt?: number;
readonly defaultFontPt?: number;
readonly scaleSink?: {
value: number;
};
readonly bandSink?: {
lefts: Array;
};
readonly drawingExtentPt?: {
readonly widthPt: number;
readonly heightPt: number;
};
readonly losses?: Array;
}
/**
* Project one worksheet's grid into Flow body elements — a single {@link Table}
* (or, when the sheet is wider than the page, several column-banded tables). The
* full print model lives here: the used-range/print-area window, merge handling,
* the style cascade (fonts/fills/borders/alignment), print scaling, conditional
* formatting, sparklines, table/pivot banding, overflow and rotation. Memory- and
* text-budget-bounded against untrusted input.
*
* @param worksheet The parsed grid + per-sheet geometry.
* @param sharedStrings The workbook shared-string table (`t="s"` cells index it).
* @param styles The workbook style table (cellXfs + fonts/fills/borders).
* @param date1904 The 1904 date system flag (serial-to-date epoch).
* @param print The print-model knobs (print area, gridlines, title rows, …).
* @returns The body elements (one table block, or banded tables); empty for a
* blank or empty-print-area sheet.
*/
export declare function worksheetToBody(worksheet: ParsedWorksheet, sharedStrings: ReadonlyArray, styles: XlsxStyles, date1904: boolean, print: PrintModelOptions): Array;
/**
* Resolve a cell's displayed text from its RAW stored value: shared-string and
* inline-string lookup, boolean → `TRUE`/`FALSE`, and the number-format pass
* (§18.8) for numeric cells. Error/string/date cells pass through verbatim.
*
* @param cell The parsed cell.
* @param sharedStrings The shared-string table for `t="s"` cells.
* @param styles The style table (for the cell's number format).
* @param date1904 The 1904 date system flag.
* @returns The resolved display string.
*/
export declare function resolveCellText(cell: WorksheetCell, sharedStrings: ReadonlyArray, styles: XlsxStyles, date1904: boolean): string;
/**
* Whether an EMPTY cell still draws something of its own — a fill or a border.
*
* Such a cell cannot be swallowed by a neighbour's overflowing text: the span
* that gives the text its width would take the paint with it.
*/
/**
* Whether a cell puts anything VISIBLE on an otherwise-empty page.
*
* The difference from {@link cellPaintsSomething} is white: a solid fill in the
* paper's own colour paints nothing a reader can see, and a sheet of them is a
* blank sheet. bnc762542.xlsx is 176 such cells — `fgColor indexed="9"`, the
* legacy palette's white — with every word it prints living in a callout, and
* both references print the callout on a bare page. 48779.xlsx is one cell of
* solid red, and both print the swatch.
*
* @param cell The cell, or undefined.
* @param styles The workbook's style tables.
* @returns True when the cell draws something the eye can find.
*/
export declare function cellPaintsVisibly(cell: WorksheetCell | undefined, styles: XlsxStyles): boolean;
export declare function cellPaintsSomething(cell: WorksheetCell | undefined, styles: XlsxStyles): boolean;
/**
* Project a slicer panel (E-SHEET SV2) into a styled mini-{@link Table} emitted
* after the grid: a caption header spanning the button columns, then one button
* cell per item — the slicer accent fill + white text when selected, a light
* band when not; the last row padded so every row keeps the column count.
*/
export declare function slicerTable(slicer: SheetSlicer): Table;
export {};