import type { Cell, FormulaResult } from "./cell.js"; import type { ChartSupport } from "./chart-host-registry.js"; import type { Chart, ChartAnchorModel } from "./chart/chart.js"; import type { AddChartExFromRowsOptions, AddChartExFromTableOptions, AddChartFromRowsOptions, AddChartFromTableOptions, SeriesFromColumnsOptions } from "./chart/chart-api.js"; import type { AddChartExOptions } from "./chart/chart-ex-types.js"; import type { ExcelChartExPreset, ExcelChartPreset } from "./chart/chart-presets.js"; import type { AddBarChartOptions, AddChartOptions, AddChartRange, AddComboChartOptions, AddPieChartOptions, AddScatterChartOptions, AddSurfaceChartOptions } from "./chart/types.js"; import { Column, type ColumnModel, type ColumnDefn } from "./column.js"; import { DataValidations } from "./data-validations.js"; import { FormCheckbox, type FormCheckboxModel, type FormCheckboxOptions, type FormControlRange } from "./form-control.js"; import { Image, type ImageModel } from "./image.js"; import { type PivotTable, type PivotTableModel } from "./pivot-table.js"; import { Range, type RangeInput } from "./range.js"; import { Row, type RowModel } from "./row.js"; import type { AddSparklineGroupOptions, SparklineGroup } from "./sparkline/index.js"; import { Table, type TableModel } from "./table.js"; import type { AddImageRange, AddShapeOptions, AutoFilter, CellValue, ColBreak, ConditionalFormattingOptions, DataValidation, IgnoredError, RowBreak, RowValues, ShapeModel, TableProperties, ThreadedComment, WatermarkOptions, WorksheetProperties, WorksheetState, WorksheetView } from "./types.js"; import { type Origin } from "./utils/address.js"; import type { Workbook } from "./workbook.js"; type DataValidationModel = { [address: string]: DataValidation | undefined; }; interface SheetProtection { sheet?: boolean; objects?: boolean; scenarios?: boolean; selectLockedCells?: boolean; selectUnlockedCells?: boolean; formatCells?: boolean; formatColumns?: boolean; formatRows?: boolean; insertColumns?: boolean; insertRows?: boolean; insertHyperlinks?: boolean; deleteColumns?: boolean; deleteRows?: boolean; sort?: boolean; autoFilter?: boolean; pivotTables?: boolean; algorithmName?: string; hashValue?: string; saltValue?: string; spinCount?: number; } interface WorksheetOptions { workbook?: Workbook; id?: number; orderNo?: number; name?: string; state?: WorksheetState; properties?: Partial; pageSetup?: Partial; headerFooter?: Partial; views?: Partial[]; autoFilter?: AutoFilter | null; } interface PageSetupMargins { left: number; right: number; top: number; bottom: number; header: number; footer: number; } interface PageSetup { margins: PageSetupMargins; orientation: string; horizontalDpi: number; verticalDpi: number; fitToPage: boolean; pageOrder: string; blackAndWhite: boolean; draft: boolean; cellComments: string; errors: string; scale: number; fitToWidth: number; fitToHeight: number; paperSize?: number; showRowColHeaders: boolean; showGridLines: boolean; firstPageNumber?: number; horizontalCentered: boolean; verticalCentered: boolean; rowBreaks: RowBreak[]; printArea?: string; printTitlesRow?: string; printTitlesColumn?: string; } interface HeaderFooter { differentFirst: boolean; differentOddEven: boolean; oddHeader: string | null; oddFooter: string | null; evenHeader: string | null; evenFooter: string | null; firstHeader: string | null; firstFooter: string | null; } interface WorksheetModel { id: number; name: string; dataValidations: DataValidationModel; properties: Partial; state: WorksheetState; pageSetup: PageSetup; headerFooter: HeaderFooter; rowBreaks: RowBreak[]; colBreaks: ColBreak[]; views: Partial[]; autoFilter: AutoFilter | null; media: ImageModel[]; shapes?: ShapeModel[]; sheetProtection: SheetProtection | null; tables: TableModel[]; pivotTables: PivotTable[]; conditionalFormattings: ConditionalFormattingOptions[]; formControls: FormCheckboxModel[]; ignoredErrors: IgnoredError[]; watermark?: WatermarkOptions | null; cols?: ColumnModel[]; rows?: RowModel[]; dimensions?: Range; mergeCells?: string[]; /** Loaded drawing data (for charts, etc.) - preserved for round-trip */ drawing?: unknown; /** Chart anchor models for worksheet charts */ charts?: ChartAnchorModel[]; /** Sparkline groups (x14:sparklineGroups) */ sparklineGroups?: SparklineGroup[]; /** * Office 365 threaded comments for this worksheet. Rendered as a * separate `xl/threadedComments/threadedComment{N}.xml` part. Empty * when the sheet has no modern comments. */ threadedComments?: Array<{ ref: string; comment: ThreadedComment; }>; } declare class Worksheet { private _workbook; id: number; orderNo: number; private _name; state: WorksheetState; private _rows; private _columns; private _keys; private _merges; rowBreaks: RowBreak[]; colBreaks: ColBreak[]; properties: Partial; pageSetup: PageSetup; headerFooter: HeaderFooter; dataValidations: DataValidations; views: Partial[]; autoFilter: AutoFilter | null; private _media; private _shapes; private _charts; private _sparklineGroups; sheetProtection: SheetProtection | null; tables: { [key: string]: Table; }; pivotTables: PivotTable[]; conditionalFormattings: ConditionalFormattingOptions[]; formControls: FormCheckbox[]; ignoredErrors: IgnoredError[]; /** * Office 365 threaded comments attached to this sheet, keyed by * cell reference. Each cell may carry a linear conversation (a * top-level comment followed by replies whose `parentId` points at * the top-level entry). Round-tripped verbatim on load; mutating * the array triggers a fresh `xl/threadedComments/threadedComment{N}.xml` * on save. * * Distinct from (and can coexist with) classic VML notes — modern * Excel shows threaded comments in the conversation pane, classic * VML in the tooltip. When both are present the threaded text is * authoritative. */ threadedComments: Array<{ ref: string; comment: ThreadedComment; }>; private _headerRowCount?; /** Loaded drawing data (for charts, etc.) - preserved for round-trip */ private _drawing; /** Watermark configuration for overlay or header mode */ private _watermark; constructor(options: WorksheetOptions); get name(): string; set name(name: string | undefined); /** * The workbook that contains this worksheet */ get workbook(): Workbook; /** * When you're done with this worksheet, call this to remove from workbook */ destroy(): void; /** * Get the bounding range of the cells in this worksheet */ get dimensions(): Range; /** * Get the current columns array */ get columns(): Column[]; /** * Add column headers and define column keys and widths. * * Note: these column structures are a workbook-building convenience only, * apart from the column width, they will not be fully persisted. */ set columns(value: ColumnDefn[]); getColumnKey(key: string): Column | undefined; setColumnKey(key: string, value: Column): void; deleteColumnKey(key: string): void; eachColumnKey(f: (column: Column, key: string) => void): void; /** * Access an individual column by key, letter and 1-based column number */ getColumn(c: string | number): Column; /** * Cut one or more columns (columns to the right are shifted left) * and optionally insert more * * If column properties have been defined, they will be cut or moved accordingly * * Known limitation: If a splice causes any merged cells to move, the results may be unpredictable * * Also: If the worksheet has more rows than values in the column inserts, * the rows will still be shifted as if the values existed */ spliceColumns(start: number, count: number, ...inserts: CellValue[][]): void; /** * Get the last column in a worksheet */ get lastColumn(): Column; /** * The total column size of the document. Equal to the maximum cell count from all of the rows */ get columnCount(): number; /** * A count of the number of columns that have values */ get actualColumnCount(): number; private get _lastRowNumber(); private get _nextRow(); /** * Get the last editable row in a worksheet (or undefined if there are none) */ get lastRow(): Row | undefined; /** * Tries to find and return row for row number, else undefined * * @param r - The 1-indexed row number */ findRow(r: number): Row | undefined; /** * Tries to find and return rows for row number start and length, else undefined * * @param start - The 1-indexed starting row number * @param length - The length of the expected array */ findRows(start: number, length: number): (Row | undefined)[]; /** * The total row size of the document. Equal to the row number of the last row that has values. */ get rowCount(): number; /** * A count of the number of rows that have values. If a mid-document row is empty, it will not be included in the count. */ get actualRowCount(): number; getRow(r: number): Row; getRows(start: number, length: number): Row[] | undefined; addRow(value: RowValues, style?: string): Row; addRows(value: RowValues[], style?: string): Row[]; insertRow(pos: number, value: RowValues, style?: string): Row; insertRows(pos: number, values: RowValues[], style?: string): Row[] | undefined; private _setStyleOption; private _copyStyle; /** * Duplicate rows and insert new rows */ duplicateRow(rowNum: number, count: number, insert?: boolean): void; /** * Cut one or more rows (rows below are shifted up) * and optionally insert more * * Known limitation: If a splice causes any merged cells to move, the results may be unpredictable */ spliceRows(start: number, count: number, ...inserts: RowValues[]): void; /** * Iterate over all rows that have values in a worksheet */ eachRow(callback: (row: Row, rowNumber: number) => void): void; /** * Iterate over all rows (including empty rows) in a worksheet */ eachRow(opt: { includeEmpty?: boolean; }, callback: (row: Row, rowNumber: number) => void): void; /** * Return all rows as sparse array */ getSheetValues(): CellValue[][]; /** * Returns the cell at [r,c] or address given by r. If not found, return undefined */ findCell(r: number | string, c?: number): Cell | undefined; /** * Get or create cell at [r,c] or address given by r */ getCell(r: number | string, c?: number): Cell; /** * Merge cells, either: * * tlbr string, e.g. `'A4:B5'` * * tl string, br string, e.g. `'G10', 'H11'` * * t, l, b, r numbers, e.g. `10,11,12,13` */ mergeCells(...cells: RangeInput[]): void; mergeCellsWithoutStyle(...cells: RangeInput[]): void; private _mergeCellsInternal; private _unMergeMaster; /** * Shift all chart anchors (drawing anchors + programmatic charts) by delta along an axis. * @param axis "row" or "col" * @param threshold 0-based index; anchors at or beyond this are shifted * @param delta number of positions to shift (positive = expand, negative = shrink) */ private _shiftChartAnchors; /** * Update _merges dictionary and cell-level merge references after a row or column splice. */ private _spliceMerges; get hasMerges(): boolean; /** * Read-only enumeration of every merged region on this sheet * (1-based, inclusive). Consumed by the formula engine's snapshot * builder to detect `#SPILL!` conflicts. See issue #162 follow-up. */ get mergedRegions(): ReadonlyArray<{ readonly top: number; readonly left: number; readonly bottom: number; readonly right: number; }>; /** * Scan the range and if any cell is part of a merge, un-merge the group. * Note this function can affect multiple merges and merge-blocks are * atomic - either they're all merged or all un-merged. */ unMergeCells(...cells: RangeInput[]): void; fillFormula(range: string, formula: string, results?: FormulaResult[][] | FormulaResult[] | ((row: number, col: number) => FormulaResult | undefined), shareType?: string): void; /** * Using the image id from `Workbook.addImage`, * embed an image within the worksheet to cover a range */ addImage(imageId: string | number, range: AddImageRange): void; /** * Add a free-form drawing shape (rectangle, ellipse, line, text box, …) to * the worksheet, anchored to a cell range. * * Unlike images, shapes need no media file — the geometry, fill, outline and * optional text label are written directly into the drawing part. * * @example * ```typescript * worksheet.addShape({ * type: "rect", * range: "B2:D5", * fillColor: "FFD966", * lineColor: "000000", * lineWidth: 1, * text: "Important" * }); * ``` */ addShape(options: AddShapeOptions): void; /** All shapes added to this worksheet. */ getShapes(): ShapeModel[]; /** * Resolve a shape's `range` into concrete two-cell anchor coordinates, * reusing the `Image` range parser so cell-address/anchor handling stays in * one place. Returns a serializable ShapeModel for the worksheet xform. */ private _resolveShapeModel; getImages(): Image[]; /** * Add a chart to the worksheet, positioned at the given range. * Returns the chart number (1-based) that identifies this chart in the workbook. */ addChart(options: AddChartOptions, range: AddChartRange): number; addColumnChart(options: Omit, range: AddChartRange): number; addBarChart(options: Omit, range: AddChartRange): number; addLineChart(options: Omit, range: AddChartRange): number; addAreaChart(options: Omit, range: AddChartRange): number; addPieChart(options: Omit, range: AddChartRange): number; addDoughnutChart(options: Omit, range: AddChartRange): number; addScatterChart(options: Omit, range: AddChartRange): number; addBubbleChart(options: Omit, range: AddChartRange): number; addRadarChart(options: Omit, range: AddChartRange): number; addStockChart(options: Omit, range: AddChartRange): number; addSurfaceChart(options: Omit, range: AddChartRange): number; addHistogramChart(options: Omit, range: AddChartRange): number; addParetoChart(options: Omit, range: AddChartRange): number; addWaterfallChart(options: Omit, range: AddChartRange): number; addFunnelChart(options: Omit, range: AddChartRange): number; addTreemapChart(options: Omit, range: AddChartRange): number; addSunburstChart(options: Omit, range: AddChartRange): number; addBoxWhiskerChart(options: Omit, range: AddChartRange): number; addRegionMapChart(options: Omit, range: AddChartRange): number; addPresetChart(preset: ExcelChartPreset, options: Omit & Partial>, range: AddChartRange): number; addPresetChartEx(preset: ExcelChartExPreset, options: Omit & Partial>, range: AddChartRange): number; seriesFromColumns(options: SeriesFromColumnsOptions): ReturnType; addChartFromTable(table: Table | string, options: AddChartFromTableOptions, range: AddChartRange): number; addChartFromRows>(rows: T[], options: AddChartFromRowsOptions, range: AddChartRange): number; addColumnChartFromRows>(rows: T[], options: Omit, "type" | "barDir">, range: AddChartRange): number; /** * Add a chartEx chart whose data references come from a worksheet Table. * Mirrors {@link addChartFromTable} for the modern `cx:` chart types * (sunburst, treemap, waterfall, funnel, histogram, pareto, boxWhisker). * `regionMap` is not supported through this helper because its data * model expects geographic labels — use {@link addChartEx} directly. */ addChartExFromTable(table: Table | string, options: AddChartExFromTableOptions & { type: Exclude; }, range: AddChartRange): number; /** * Add a chartEx chart whose rows come from a plain object-array, staged * into the worksheet before being referenced by absolute range. Mirrors * {@link addChartFromRows} for the modern `cx:` chart types. */ addChartExFromRows>(rows: T[], options: AddChartExFromRowsOptions & { type: Exclude; }, range: AddChartRange): number; /** * Add a classic pivot chart linked to an existing pivot table. * Returns the chart number (1-based) that identifies this chart in the workbook. */ addPivotChart(pivotTable: PivotTable, options: AddChartOptions, range: AddChartRange): number; /** * Add a combo pivot chart linked to an existing pivot table. * Returns the chart number (1-based) that identifies this chart in the workbook. */ addPivotComboChart(pivotTable: PivotTable, options: AddComboChartOptions, range: AddChartRange): number; /** * Add a combo chart (multiple chart type groups) to the worksheet. * Returns the chart number (1-based) that identifies this chart in the workbook. */ addComboChart(options: AddComboChartOptions, range: AddChartRange): number; /** * Add a ChartEx (Office 2016+ extended chart) to the worksheet. * * Supported types: `sunburst`, `treemap`, `waterfall`, `funnel`, `histogram`, * `pareto`, `boxWhisker`, `regionMap`. * * Returns the chartEx number (1-based) that identifies this chart in the workbook. */ addChartEx(options: AddChartExOptions, range: AddChartRange): number; private _applyChartSidecars; /** * Get all charts embedded in this worksheet. */ getCharts(): Chart[]; /** * Remove a chart from this worksheet. * * @param chart - Either the chart object or its 0-based index in the worksheet. * @returns `true` if a chart was removed, `false` otherwise. */ removeChart(chart: Chart | number): boolean; /** * Add a sparkline group to this worksheet. * * A sparkline group is a collection of small in-cell charts sharing common * styling. Sparklines are rendered via `x14:sparklineGroups` inside the * worksheet extension list. * * @returns The newly added SparklineGroup for further modification. */ addSparklineGroup(options: AddSparklineGroupOptions): SparklineGroup; /** Get all sparkline groups on this worksheet. */ getSparklineGroups(): SparklineGroup[]; /** * Remove a sparkline group. * * @param groupOrIndex - The group object or its 0-based index. * @returns `true` if removed, `false` otherwise. */ removeSparklineGroup(groupOrIndex: SparklineGroup | number): boolean; /** * Using the image id from `Workbook.addImage`, set the background to the worksheet. * * The image must be **embedded** (`buffer`/`base64`/`filename`). Worksheet * background pictures (``) do not support external (linked) * images — Excel silently drops a background whose relationship uses * `TargetMode="External"`, so this rejects linked images up front. */ addBackgroundImage(imageId: string | number): void; getBackgroundImageId(): string | undefined; /** * Add a watermark to the worksheet using an image from `workbook.addImage()`. * * The watermark can be placed in one of two modes: * * - **overlay** (default): Places the watermark image as a drawing on top of cells. * Visible on screen AND when printed. Supports transparency via DrawingML `alphaModFix`. * * - **header**: Places the watermark image in the page header using VML. * Visible in Page Layout view and when printed. Renders behind cell content. * Transparency must be baked into the image (PNG with alpha channel). * * **External (linked) images:** `mode: "overlay"` supports external images * (registered via `workbook.addImage({ link })`). `mode: "header"` does * **not** — VML header/footer images require embedded media, so passing a * linked image with `mode: "header"` throws an `ImageError`. Use an embedded * image (`buffer`/`base64`/`filename`) or switch to `mode: "overlay"`. * * @param options - Watermark configuration * @throws {ImageError} If `mode: "header"` is used with an external (linked) image. * * @example Overlay watermark with transparency: * ```typescript * const imgId = workbook.addImage({ buffer: pngData, extension: "png" }); * worksheet.addWatermark({ imageId: imgId, opacity: 0.15 }); * ``` * * @example Header watermark (behind content): * ```typescript * const imgId = workbook.addImage({ buffer: pngData, extension: "png" }); * worksheet.addWatermark({ imageId: imgId, mode: "header" }); * ``` */ addWatermark(options: WatermarkOptions): void; /** * Get the current watermark configuration, or null if none is set. */ getWatermark(): WatermarkOptions | null; /** * Remove the watermark from the worksheet. */ removeWatermark(): void; /** * Add a form control checkbox to the worksheet. * * Form control checkboxes are the legacy style that work in Office 2007+, * WPS Office, LibreOffice, and other spreadsheet applications. * * Unlike modern in-cell checkboxes (which only work in Microsoft 365), * form control checkboxes are floating controls positioned over cells. * * @param range - Cell reference (e.g., "B2") or range (e.g., "B2:D3") for positioning * @param options - Checkbox options * @returns The created FormCheckbox instance * * @example * // Simple checkbox at B2 * ws.addFormCheckbox("B2"); * * // Checkbox with label and linked cell * ws.addFormCheckbox("B2:D3", { * text: "Accept terms", * link: "A2", * checked: false * }); */ addFormCheckbox(range: FormControlRange, options?: FormCheckboxOptions): FormCheckbox; /** * Get all form control checkboxes in the worksheet */ getFormCheckboxes(): FormCheckbox[]; /** * Protect the worksheet with optional password and options */ protect(password?: string, options?: Partial): Promise; unprotect(): void; /** * Add a new table and return a reference to it */ addTable(model: TableProperties): Table; /** * Fetch table by name */ getTable(name: string): Table; /** * Delete table by name */ removeTable(name: string): void; /** * Fetch all tables in the worksheet */ getTables(): Table[]; addPivotTable(model: PivotTableModel): PivotTable; /** * Add conditional formatting rules */ addConditionalFormatting(cf: ConditionalFormattingOptions): void; /** * Delete conditional formatting rules. * * - When `filter` is a number, removes the rule at that index. * - When `filter` is a function, removes every rule for which it returns `true` * (i.e. the predicate selects the rules to delete, not the ones to keep). * - When `filter` is omitted/falsy, removes all rules. */ removeConditionalFormatting(filter?: number | ((value: ConditionalFormattingOptions, index: number, array: ConditionalFormattingOptions[]) => boolean)): void; /** * Auto-fit a single column's width to its content. * * Calculates the optimal column width by measuring the display text of every * cell in the column, considering font, number format, bold/italic, and CJK * characters. Sets `column.width` and `column.bestFit = true`. * * @param col - Column number (1-based) or column letter (e.g. "A") * @returns The worksheet (for chaining) */ autoFitColumn(col: number | string): this; /** * Auto-fit all columns (or a range of columns) to their content. * * @param startCol - Start column (1-based number or letter). Defaults to first column. * @param endCol - End column (1-based number or letter). Defaults to last column. * @returns The worksheet (for chaining) */ autoFitColumns(startCol?: number | string, endCol?: number | string): this; /** * Auto-fit a single row's height to its content. * * @param rowNumber - Row number (1-based) * @returns The worksheet (for chaining) */ autoFitRow(rowNumber: number): this; /** * Auto-fit all rows (or a range of rows) to their content. * * @param startRow - Start row (1-based). Defaults to first row. * @param endRow - End row (1-based). Defaults to last row. * @returns The worksheet (for chaining) */ autoFitRows(startRow?: number, endRow?: number): this; get model(): WorksheetModel; private _parseRows; private _parseMergeCells; set model(value: WorksheetModel); /** * Convert worksheet data to a JSON array. * * @example * // Default: first row as headers, returns array of objects * const data = ws.toJSON(); * // => [{name: "Alice", age: 30}, {name: "Bob", age: 25}] * * @example * // Array of arrays * const aoa = ws.toJSON({ header: 1 }); * // => [["name", "age"], ["Alice", 30], ["Bob", 25]] * * @example * // Column letters as keys * const cols = ws.toJSON({ header: "A" }); * // => [{A: "name", B: "age"}, {A: "Alice", B: 30}] */ toJSON(opts: SheetToJSONOptions & { header: 1; }): CellValue[][]; toJSON(opts?: SheetToJSONOptions): Record[]; /** * Add data from a JSON array to this worksheet. * Each object's keys become column headers (written in the first row unless skipHeader is set). * * @example * ws.addJSON([{name: "Alice", age: 30}, {name: "Bob", age: 25}]); * * @returns this (for chaining) */ addJSON(data: Record[], opts?: AddJSONOptions): this; /** * Convert worksheet data to an array of arrays. * * @example * const aoa = ws.toAOA(); * // => [["Name", "Age"], ["Alice", 30], ["Bob", 25]] */ toAOA(): CellValue[][]; /** * Add data from an array of arrays to this worksheet. * * @example * ws.addAOA([["Name", "Age"], ["Alice", 30], ["Bob", 25]]); * * @returns this (for chaining) */ addAOA(data: CellValue[][], opts?: AddAOAOptions): this; } export interface SheetToJSONOptions { /** * Control output format: * - `1`: Generate an array of arrays * - `"A"`: Row object keys are literal column labels (A, B, C, ...) * - `string[]`: Use specified strings as keys in row objects * - `undefined`: Read and disambiguate first row as keys */ header?: 1 | "A" | string[]; /** * Override range: * - `number`: Use worksheet range but set starting row to the value (0-indexed) * - `string`: Use specified range (A1-style bounded range string) * - `undefined`: Use worksheet range */ range?: number | string; /** Use raw values (true, default) or formatted text strings (false) */ raw?: boolean; /** Default value for empty cells */ defaultValue?: CellValue; /** Include blank rows in output (default: true for AOA, false for objects) */ blankRows?: boolean; /** Override format for date values (only applies when raw: false) */ dateFormat?: string; } export interface AddJSONOptions { /** Use specified field order (default: Object.keys from data) */ header?: string[]; /** If true, do not include header row in output */ skipHeader?: boolean; /** Starting position: cell address string, {c, r} object, row number (0-indexed), or -1 to append */ origin?: Origin; /** If true, emit #NULL! error cells for null values */ nullError?: boolean; } export interface AddAOAOptions { /** Starting position: cell address string, {c, r} object, row number (0-indexed), or -1 to append */ origin?: Origin; } export { Worksheet, type WorksheetModel };