/** * switched to row-major, seems to have no ill effects * (not sure if there are benefits yet either) */ import type { IArea, ICellAddress } from './area'; import { Area } from './area'; import { Cell } from './cell'; import type { Table } from './table'; import { type SerializedValueType, ValueType } from './value-type'; import type { CellValue, UnionValue } from './union'; import type { CellStyle } from './style'; export interface CellSerializationOptions { preserve_type?: boolean; convert_address?: boolean; calculated_value?: boolean; expand_arrays?: boolean; subset?: Area; preserve_empty_strings?: boolean; decorated_cells?: boolean; tables?: boolean; /** * nest rows in columns, or vice-versa, depending on which is smaller. */ nested?: boolean; /** * cell style refs to pack into cells */ cell_style_refs?: number[][]; /** optionally attach an ID to the cells */ sheet_id?: number; } export interface BaseCellData { value: CellValue; style_ref?: number; calculated?: CellValue; table?: Table; area?: IArea; merge_area?: IArea; calculated_type?: SerializedValueType; note?: string; hyperlink?: string; type?: SerializedValueType; sheet_id?: number; spill?: IArea; } /** * this type is for serialized data that includes the row and column * in each cell. this was the original serialized data type, and is * still supported. current serialization will group data into rows or * columns, whichever results in a smaller overall serialized representation. */ export interface CellDataWithAddress extends BaseCellData { row: number; column: number; } export interface NestedCellData { cells: BaseCellData[]; } /** * this type is for serialized data that is grouped by row, with each * cell referencing a column in the spreadsheet. */ export interface CellDataWithColumn extends BaseCellData { column: number; } export interface NestedRowData extends NestedCellData { row: number; cells: CellDataWithColumn[]; } /** * this type is for serialized data that is grouped by column, with each * cell referencing a row in the spreadsheet. */ export interface CellDataWithRow extends BaseCellData { row: number; } export interface NestedColumnData extends NestedCellData { column: number; cells: CellDataWithRow[]; } export type SerializedCellData = CellDataWithAddress[] | NestedRowData[] | NestedColumnData[]; /** @internal */ export declare const IsFlatData: (test: CellDataWithAddress | NestedCellData) => test is CellDataWithAddress; /** @internal */ export declare const IsFlatDataArray: (test: CellDataWithAddress[] | NestedCellData[]) => test is CellDataWithAddress[]; /** @internal */ export declare const IsNestedRowArray: (test: NestedRowData[] | NestedColumnData[]) => test is NestedRowData[]; /** * collection of cells, basically a wrapper around an * array, with some accessor and control methods. */ export declare class Cells { /** switching to row-major */ data: Cell[][]; private rows_; private columns_; get rows(): number; get columns(): number; /** * the sheet wants to make sure this row exists, probably because it has * a header. so we will update our dimensions to match. we don't actually * add data. * * this is not serialized. specific headers aren't serialized either, at * the moment, so it's sort of irrelevant. if we start serializing headers, * the deserialization routine can call this function to pad out, so we * don't need to store it here. */ EnsureRow(row: number): void; /** @see EnsureRow */ EnsureColumn(column: number): void; /** * this class does none of the validation/correction * required when inserting rows/columns. that should * be done by external logic. this method only does * the mechanical work of inserting rows/columns. */ InsertColumns(before?: number, count?: number): void; DeleteColumns(index: number, count?: number): void; DeleteRows(index: number, count?: number): void; /** * this class does none of the validation/correction * required when inserting rows/columns. that should * be done by external logic. this method only does * the mechanical work of inserting rows/columns. */ InsertRows(before?: number, count?: number): void; /** * return or create cell at the given address */ GetCell(address: ICellAddress, create_new: true): Cell; /** * return the cell at the given address or undefined if it doesn't exist */ GetCell(address: ICellAddress, create_new?: false): Cell | undefined; /** * apply function to range or address. skips empty cells (for now...) * (already have this function, it's called "IterateArea". "Apply" is better.) * / public Apply(target: ICellAddress|IArea, func: (cell: Cell) => void): void { if (IsCellAddress(target)) { target = new Area(target); } const start = target.start; const end = target.end; for (let r = start.row; r <= end.row; r++) { if (this.data[r]) { const row = this.data[r]; for (let c = start.column; c < end.column; c++) { if (this.data[r][c]) { func.call(undefined, row[c]); } } } } } */ /** returns an existing cell or creates a new cell. */ EnsureCell(address: ICellAddress): Cell; /** * with the update, we assume the passed-in data is row-major. * when reading an older file, transpose. */ FromArray(data?: CellValue[][], transpose?: boolean): void; SerializedTypeToValueType(type?: SerializedValueType | ValueType): ValueType | undefined; ValueTypeToSerializedType(type?: ValueType): SerializedValueType | undefined; /** * UPDATE: adding optional style refs, for export */ FromJSON(data?: SerializedCellData, style_refs?: CellStyle[]): void; toJSON(options?: CellSerializationOptions): { data: SerializedCellData; rows: number; columns: number; }; GetAll(transpose?: boolean): CellValue | CellValue[][]; /** overload */ Normalize(from: ICellAddress, to: ICellAddress): { from: ICellAddress; to: ICellAddress; }; /** overload */ Normalize(from: ICellAddress): { from: ICellAddress; }; /** overload */ Normalize(from: ICellAddress, to: K): { from: ICellAddress; to: K; }; /** * get raw values (i.e. not calculated). anything outside of actual * range will be undefined OR not populated. * * to match GetRange, we return a single value in the case of a single cell, * or a matrix. * * NOTE that I'm not sure this is good behavior. if you're going to * return a single value for one cell, you should return a vector for * a single row OR a single column. alternatively, you should always * return a matrix. * * @param from * @param to * @param transpose */ RawValue(from: ICellAddress, to?: ICellAddress): CellValue | CellValue[][] | undefined; /** gets range as values */ GetRange(from: ICellAddress, to?: ICellAddress, transpose?: boolean): CellValue | CellValue[][]; GetRange4(from: ICellAddress, to?: ICellAddress, transpose?: boolean): UnionValue; /** * set area. shortcut to reduce overhead. consolidates single value * and array value methods, although the implementation is separate. * * watch out for typed arrays, which do not satisfy Array.isArray * * when would this function get a 1D typed array? can't figure that out. * just drop for the time being. * */ SetArea(area: Area, values: CellValue | CellValue[][]): void; /** * yet another iterator, this one returns cell and address. * iterates all cells; does not create missing cells. * * UPDATE: adding area parameter; not shrinking it (don't call w/ infinities) */ IterateRC(area?: IArea, create_missing_cells?: boolean): Generator<{ cell: Cell; row: number; column: number; }, void, unknown>; /** * replacement for old callback iterator. this is a composite * of iterating all and iterating an area. I want to remove the * other method, but there are still some calls that use the * cell address. * * Q: is it possible to use Symbol.iterator with arguments? * A: apparently it is, but how would you call it? (...) */ Iterate(area?: Area | ICellAddress, create_missing_cells?: boolean): Generator; /** moved from sheet, so we can do it non-functional style (for perf) */ FlushCellStyles(): void; /** moved from sheet, so we can do it non-functional style (for perf) */ FlushCachedValues(): void; }