hyperformula
Version:
HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas
225 lines (224 loc) • 11.1 kB
TypeScript
/**
* @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;
}