UNPKG

hyperformula

Version:

HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas

225 lines (224 loc) 11.1 kB
/** * @license * Copyright (c) 2025 Handsoncode. All rights reserved. */ import { AbsoluteCellRange, SimpleCellRange } from '../AbsoluteCellRange'; import { ArraySize } from '../ArraySize'; import { SimpleCellAddress } from '../Cell'; import { RawCellContent } from '../CellContentParser'; import { CellDependency } from '../CellDependency'; import { Config } from '../Config'; import { ContentChanges } from '../ContentChanges'; import { FunctionRegistry } from '../interpreter/FunctionRegistry'; import { InternalScalarValue, InterpreterValue, RawScalarValue } from '../interpreter/InterpreterValue'; import { LazilyTransformingAstService } from '../LazilyTransformingAstService'; import { Maybe } from '../Maybe'; import { NamedExpressions } from '../NamedExpressions'; import { Ast } from '../parser'; import { ColumnsSpan, RowsSpan } from '../Span'; import { Statistics } from '../statistics'; import { ArrayFormulaVertex, CellVertex, ParsingErrorVertex, RangeVertex, Vertex } from './'; import { AddressMapping } from './AddressMapping/AddressMapping'; import { ArrayMapping } from './ArrayMapping'; import { Graph } from './Graph'; import { RangeMapping } from './RangeMapping'; import { SheetMapping } from './SheetMapping'; import { SheetReferenceRegistrar } from './SheetReferenceRegistrar'; import { RawAndParsedValue } from './ValueCellVertex'; import { TopSortResult } from './TopSort'; export declare class DependencyGraph { readonly addressMapping: AddressMapping; readonly rangeMapping: RangeMapping; readonly sheetMapping: SheetMapping; readonly arrayMapping: ArrayMapping; readonly stats: Statistics; readonly lazilyTransformingAstService: LazilyTransformingAstService; readonly functionRegistry: FunctionRegistry; readonly namedExpressions: NamedExpressions; readonly graph: Graph<Vertex>; private changes; readonly sheetReferenceRegistrar: SheetReferenceRegistrar; constructor(addressMapping: AddressMapping, rangeMapping: RangeMapping, sheetMapping: SheetMapping, arrayMapping: ArrayMapping, stats: Statistics, lazilyTransformingAstService: LazilyTransformingAstService, functionRegistry: FunctionRegistry, namedExpressions: NamedExpressions); /** * Invariants: * - empty cell has associated EmptyCellVertex if and only if it is a dependency (possibly indirect, through range) to some formula */ static buildEmpty(lazilyTransformingAstService: LazilyTransformingAstService, config: Config, functionRegistry: FunctionRegistry, namedExpressions: NamedExpressions, stats: Statistics): DependencyGraph; setFormulaToCell(address: SimpleCellAddress, ast: Ast, dependencies: CellDependency[], size: ArraySize, hasVolatileFunction: boolean, hasStructuralChangeFunction: boolean): ContentChanges; setParsingErrorToCell(address: SimpleCellAddress, errorVertex: ParsingErrorVertex): ContentChanges; setValueToCell(address: SimpleCellAddress, value: RawAndParsedValue): ContentChanges; /** * Sets a cell empty. * - if vertex has no dependents, removes it from graph, address mapping and range mapping and cleans up its dependencies * - if vertex has dependents, exchanges it for an EmptyCellVertex and marks it as dirty */ setCellEmpty(address: SimpleCellAddress): ContentChanges; clearDirtyVertices(): void; verticesToRecompute(): Vertex[]; processCellDependencies(cellDependencies: CellDependency[], endVertex: Vertex): void; fetchNamedExpressionVertex(expressionName: string, sheetId: number): { vertex: CellVertex; id: Maybe<number>; }; exchangeNode(addressFrom: SimpleCellAddress, addressTo: SimpleCellAddress): void; fetchCellOrCreateEmpty(address: SimpleCellAddress): { vertex: CellVertex; id: Maybe<number>; }; removeRows(removedRows: RowsSpan): EagerChangesGraphChangeResult; /** * Adds a new sheet to the graph. * If the sheetId was a placeholder sheet, marks its vertices as dirty. */ addSheet(sheetId: number): void; /** * Removes all vertices without dependents in other sheets from address mapping, range mapping and array mapping. * - If nothing is left, removes the sheet from sheet mapping and address mapping. * - Otherwise, marks it as placeholder. */ removeSheet(sheetId: number): void; /** * Removes placeholderSheetToDelete and reroutes edges to the corresponding vertices in sheetToKeep * * Assumptions about placeholderSheetToDelete: * - is empty (contains only empty cell vertices and range vertices), * - empty cell vertices have no dependencies, * - range vertices have dependencies only in placeholderSheetToDelete, * - vertices may have dependents in placeholderSheetToDelete and other sheets, */ mergeSheets(sheetToKeep: number, placeholderSheetToDelete: number): void; /** * Clears the sheet content. * - removes all cell vertices without dependents * - removes all array vertices * - for vertices with dependents, exchanges them for EmptyCellVertex and marks them as dirty */ clearSheet(sheetId: number): void; removeColumns(removedColumns: ColumnsSpan): EagerChangesGraphChangeResult; addRows(addedRows: RowsSpan): ArrayAffectingGraphChangeResult; addColumns(addedColumns: ColumnsSpan): EagerChangesGraphChangeResult; isThereSpaceForArray(arrayVertex: ArrayFormulaVertex): boolean; moveCells(sourceRange: AbsoluteCellRange, toRight: number, toBottom: number, toSheet: number): void; /** * Sets an array empty. * - removes all corresponding entries from address mapping * - reroutes the edges * - removes vertex from graph and cleans up its dependencies * - removes vertex from range mapping and array mapping */ setArrayEmpty(arrayVertex: ArrayFormulaVertex): void; addVertex(address: SimpleCellAddress, vertex: CellVertex): void; addArrayVertex(address: SimpleCellAddress, vertex: ArrayFormulaVertex): void; /** * Iterator over all array formula nodes in the graph. */ arrayFormulaNodes(): IterableIterator<ArrayFormulaVertex>; entriesFromRowsSpan(rowsSpan: RowsSpan): IterableIterator<[SimpleCellAddress, CellVertex]>; entriesFromColumnsSpan(columnsSpan: ColumnsSpan): IterableIterator<[SimpleCellAddress, CellVertex]>; fetchCell(address: SimpleCellAddress): CellVertex; /** * Gets the cell vertex at the specified address. * @throws {NoSheetWithIdError} if sheet doesn't exist */ getCell(address: SimpleCellAddress): Maybe<CellVertex>; getCellValue(address: SimpleCellAddress): InterpreterValue; getRawValue(address: SimpleCellAddress): RawCellContent; getScalarValue(address: SimpleCellAddress): InternalScalarValue; existsEdge(fromNode: Vertex, toNode: Vertex): boolean; getSheetId(sheetName: string): number; getSheetHeight(sheet: number): number; getSheetWidth(sheet: number): number; getArray(range: AbsoluteCellRange): Maybe<ArrayFormulaVertex>; getRange(start: SimpleCellAddress, end: SimpleCellAddress): Maybe<RangeVertex>; topSortWithScc(): TopSortResult<Vertex>; markAsVolatile(vertex: Vertex): void; markAsDependentOnStructureChange(vertex: Vertex): void; forceApplyPostponedTransformations(): void; rawValuesFromRange(range: AbsoluteCellRange): IterableIterator<[RawScalarValue, SimpleCellAddress]>; dependencyQueryAddresses: (vertex: Vertex) => (SimpleCellAddress | SimpleCellRange)[]; computeListOfValuesInRange(range: AbsoluteCellRange): InternalScalarValue[]; shrinkArrayToCorner(array: ArrayFormulaVertex): void; isArrayInternalCell(address: SimpleCellAddress): boolean; getAndClearContentChanges(): ContentChanges; getAdjacentNodesAddresses(inputVertex: Vertex): (SimpleCellRange | SimpleCellAddress)[]; /** * Marks all cell vertices in the sheet as dirty. */ private markAllCellsAsDirtyInSheet; /** * Marks all range vertices in the sheet as dirty. */ private markAllRangesAsDirtyInSheet; /** * For each range vertex in placeholderSheetToDelete: * - reroutes dependencies and dependents of range vertex to the corresponding vertex in sheetToKeep * - removes range vertex from graph and range mapping * - cleans up dependencies of the removed vertex */ private mergeRangeVertices; /** * For each cell vertex in placeholderSheetToDelete: * - reroutes dependents of cell vertex to the corresponding vertex in sheetToKeep * - removes cell vertex from graph and address mapping * - cleans up dependencies of the removed vertex */ private mergeCellVertices; /** * Checks if the given sheet ID refers to a placeholder sheet (doesn't exist but is referenced by other sheets) */ private isPlaceholder; private exchangeGraphNode; private setArray; private correctInfiniteRangesDependency; private exchangeOrAddGraphNode; private dependencyQueryVertices; private getArrayVerticesRelatedToRanges; private correctInfiniteRangesDependenciesByRangeVertex; private cleanAddressMappingUnderArray; private formulaDirectDependenciesToArray; private rangeDirectDependenciesToArray; private adjacentArrayVertices; private rangeDependencyQuery; private formulaDependencyQuery; private addStructuralNodesToChangeSet; private fixRangesWhenAddingRows; private addAllFromRange; private fixRangesWhenAddingColumns; private exchangeOrAddFormulaVertex; private setAddressMappingForArrayVertex; private truncateRanges; private fixArraysAfterAddingRow; private fixArraysAfterRemovingRows; private fixArraysAfterAddingColumn; private fixArraysAfterRemovingColumns; private shrinkPossibleArrayAndGetCell; private setNoSpaceIfArray; /** * Removes a vertex from the graph and range mapping and cleans up its dependencies. */ private removeVertex; /** * Reroutes dependent vertices of source to target. Also removes the edge target -> source if it exists. */ private rerouteDependents; /** * Removes a vertex from graph and reroutes its dependencies to other vertex. Also removes the edge vertexToKeep -> vertexToDelete if it exists. */ private removeVertexAndRerouteDependencies; /** * Removes a vertex from graph and cleans up its dependencies. * Dependency clean up = remove all RangeVertex and EmptyCellVertex dependencies if no other vertex depends on them. * Also cleans up placeholder sheets that have no remaining vertices (not needed anymore) */ private removeVertexAndCleanupDependencies; /** * Removes placeholder sheets that have no remaining vertices. */ private cleanupPlaceholderSheets; } export interface ArrayAffectingGraphChangeResult { affectedArrays: Set<ArrayFormulaVertex>; } export interface EagerChangesGraphChangeResult extends ArrayAffectingGraphChangeResult { contentChanges: ContentChanges; }