hyperformula-dc
Version:
HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas
1,451 lines (1,311 loc) • 175 kB
JavaScript
"use strict";
require("core-js/modules/es.array.slice.js");
require("core-js/modules/es.function.name.js");
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.symbol.iterator.js");
exports.__esModule = true;
exports.HyperFormula = void 0;
require("core-js/modules/es.array.concat.js");
require("core-js/modules/es.array.map.js");
require("core-js/modules/es.array.from.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/es.map.js");
var _AbsoluteCellRange = require("./AbsoluteCellRange");
var _ArgumentSanitization = require("./ArgumentSanitization");
var _BuildEngineFactory = require("./BuildEngineFactory");
var _Cell = require("./Cell");
var _CellContentParser = require("./CellContentParser");
var _DateTimeHelper = require("./DateTimeHelper");
var _Destroy = require("./Destroy");
var _Emitter = require("./Emitter");
var _errors = require("./errors");
var _i18n = require("./i18n");
var _FunctionRegistry = require("./interpreter/FunctionRegistry");
var _Operations = require("./Operations");
var _parser2 = require("./parser");
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
/**
* This is a class for creating HyperFormula instance, all the following public methods
* ale related to this class.
*
* The instance can be created only by calling one of the static methods
* `buildFromArray`, `buildFromSheets` or `buildEmpty` and should be disposed of with the
* `destroy` method when it's no longer needed to free the resources.
*
* The instance can be seen as a workbook where worksheets can be created and
* manipulated. They are organized within a widely know structure of columns and rows
* which can be manipulated as well. The smallest possible data unit are the cells, which
* may contain simple values or formulas to be calculated.
*
* All CRUD methods are called directly on HyperFormula instance and will trigger
* corresponding lifecycle events. The events are marked accordingly, as well as thrown
* errors so they can be correctly handled.
*/
var HyperFormula = /*#__PURE__*/function () {
function HyperFormula(_config, _stats, _dependencyGraph, _columnSearch, _parser, _unparser, _cellContentParser, _evaluator, _lazilyTransformingAstService, _crudOperations, _exporter, _namedExpressions, _serialization, _functionRegistry) {
_classCallCheck(this, HyperFormula);
this._config = _config;
this._stats = _stats;
this._dependencyGraph = _dependencyGraph;
this._columnSearch = _columnSearch;
this._parser = _parser;
this._unparser = _unparser;
this._cellContentParser = _cellContentParser;
this._evaluator = _evaluator;
this._lazilyTransformingAstService = _lazilyTransformingAstService;
this._crudOperations = _crudOperations;
this._exporter = _exporter;
this._namedExpressions = _namedExpressions;
this._serialization = _serialization;
this._functionRegistry = _functionRegistry;
this._emitter = new _Emitter.Emitter();
this._evaluationSuspended = false;
}
/**
* Calls the `graph` method on the dependency graph.
* Allows to execute `graph` directly without a need to refer to `dependencyGraph`.
*
* @internal
*/
_createClass(HyperFormula, [{
key: "graph",
get: function get() {
return this.dependencyGraph.graph;
}
/**
* Calls the `rangeMapping` method on the dependency graph.
* Allows to execute `rangeMapping` directly without a need to refer to `dependencyGraph`.
*
* @internal
*/
}, {
key: "rangeMapping",
get: function get() {
return this.dependencyGraph.rangeMapping;
}
/**
* Calls the `arrayMapping` method on the dependency graph.
* Allows to execute `arrayMapping` directly without a need to refer to `dependencyGraph`.
*
* @internal
*/
}, {
key: "arrayMapping",
get: function get() {
return this.dependencyGraph.arrayMapping;
}
/**
* Calls the `sheetMapping` method on the dependency graph.
* Allows to execute `sheetMapping` directly without a need to refer to `dependencyGraph`.
*
* @internal
*/
}, {
key: "sheetMapping",
get: function get() {
return this.dependencyGraph.sheetMapping;
}
/**
* Calls the `addressMapping` method on the dependency graph.
* Allows to execute `addressMapping` directly without a need to refer to `dependencyGraph`.
*
* @internal
*/
}, {
key: "addressMapping",
get: function get() {
return this.dependencyGraph.addressMapping;
}
/** @internal */
}, {
key: "dependencyGraph",
get: function get() {
return this._dependencyGraph;
}
/** @internal */
}, {
key: "evaluator",
get: function get() {
return this._evaluator;
}
/** @internal */
}, {
key: "columnSearch",
get: function get() {
return this._columnSearch;
}
/** @internal */
}, {
key: "lazilyTransformingAstService",
get: function get() {
return this._lazilyTransformingAstService;
}
/**
* Returns state of the validity of the license key.
*
* @internal
*/
}, {
key: "licenseKeyValidityState",
get: function get() {
return this._config.licenseKeyValidityState;
}
}, {
key: "getCellValue",
value:
/**
* Returns the cell value of a given address.
* Applies rounding and post-processing.
*
* @param {SimpleCellAddress} cellAddress - cell coordinates
*
* @throws [[ExpectedValueOfTypeError]] when cellAddress is of incorrect type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[EvaluationSuspendedError]] when the evaluation is suspended
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['=SUM(1,2,3)', '2'],
* ]);
*
* // get value of A1 cell, should be '6'
* const A1Value = hfInstance.getCellValue({ sheet: 0, col: 0, row: 0 });
*
* // get value of B1 cell, should be '2'
* const B1Value = hfInstance.getCellValue({ sheet: 0, col: 1, row: 0 });
* ```
*
* @category Cells
*/
function getCellValue(cellAddress) {
if (!(0, _Cell.isSimpleCellAddress)(cellAddress)) {
throw new _errors.ExpectedValueOfTypeError('SimpleCellAddress', 'cellAddress');
}
this.ensureEvaluationIsNotSuspended();
return this._serialization.getCellValue(cellAddress);
}
}, {
key: "ensureEvaluationIsNotSuspended",
value: function ensureEvaluationIsNotSuspended() {
if (this._evaluationSuspended) {
throw new _errors.EvaluationSuspendedError();
}
}
/**
* Returns a normalized formula string from the cell of a given address or `undefined` for an address that does not exist and empty values.
*
* @param {SimpleCellAddress} cellAddress - cell coordinates
*
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[ExpectedValueOfTypeError]] when cellAddress is of incorrect type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['=SUM(1,2,3)', '0'],
* ]);
*
* // should return a normalized A1 cell formula: '=SUM(1,2,3)'
* const A1Formula = hfInstance.getCellFormula({ sheet: 0, col: 0, row: 0 });
*
* // should return a normalized B1 cell formula: 'undefined'
* const B1Formula = hfInstance.getCellFormula({ sheet: 0, col: 1, row: 0 });
* ```
*
* @category Cells
*/
}, {
key: "getCellFormula",
value: function getCellFormula(cellAddress) {
if (!(0, _Cell.isSimpleCellAddress)(cellAddress)) {
throw new _errors.ExpectedValueOfTypeError('SimpleCellAddress', 'cellAddress');
}
return this._serialization.getCellFormula(cellAddress);
}
/**
* Returns [[RawCellContent]] with a serialized content of the cell of a given address: either a cell formula, an explicit value, or an error.
*
* @param {SimpleCellAddress} cellAddress - cell coordinates
*
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[EvaluationSuspendedError]] when the evaluation is suspended
* @throws [[ExpectedValueOfTypeError]] when cellAddress is of incorrect type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['=SUM(1,2,3)', '0'],
* ]);
*
* // should return serialized content of A1 cell: '=SUM(1,2,3)'
* const cellA1Serialized = hfInstance.getCellSerialized({ sheet: 0, col: 0, row: 0 });
*
* // should return serialized content of B1 cell: '0'
* const cellB1Serialized = hfInstance.getCellSerialized({ sheet: 0, col: 1, row: 0 });
* ```
*
* @category Cells
*/
}, {
key: "getCellSerialized",
value: function getCellSerialized(cellAddress) {
if (!(0, _Cell.isSimpleCellAddress)(cellAddress)) {
throw new _errors.ExpectedValueOfTypeError('SimpleCellAddress', 'cellAddress');
}
this.ensureEvaluationIsNotSuspended();
return this._serialization.getCellSerialized(cellAddress);
}
/**
* Returns an array of arrays of [[CellValue]] with values of all cells from [[Sheet]].
* Applies rounding and post-processing.
*
* @param {number} sheetId - sheet ID number
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[EvaluationSuspendedError]] when the evaluation is suspended
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['0', '=SUM(1,2,3)', '=A1'],
* ['1', '=TEXT(A2, "0.0%")', '=C1'],
* ['2', '=SUM(A1:C1)', '=C1'],
* ]);
*
* // should return all values of a sheet: [[0, 6, 0], [1, '1.0%', 0], [2, 6, 0]]
* const sheetValues = hfInstance.getSheetValues(0);
* ```
*
* @category Sheets
*/
}, {
key: "getSheetValues",
value: function getSheetValues(sheetId) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
this.ensureEvaluationIsNotSuspended();
return this._serialization.getSheetValues(sheetId);
}
/**
* Returns an array with normalized formula strings from [[Sheet]] or `undefined` for a cells that have no value.
*
* @param {SimpleCellAddress} sheetId - sheet ID number
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['0', '=SUM(1,2,3)', '=A1'],
* ['1', '=TEXT(A2, "0.0%")', '=C1'],
* ['2', '=SUM(A1:C1)', '=C1'],
* ]);
*
* // should return all formulas of a sheet:
* // [
* // [undefined, '=SUM(1,2,3)', '=A1'],
* // [undefined, '=TEXT(A2, "0.0%")', '=C1'],
* // [undefined, '=SUM(A1:C1)', '=C1'],
* // ];
* const sheetFormulas = hfInstance.getSheetFormulas(0);
* ```
*
* @category Sheets
*/
}, {
key: "getSheetFormulas",
value: function getSheetFormulas(sheetId) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
return this._serialization.getSheetFormulas(sheetId);
}
/**
* Returns an array of arrays of [[RawCellContent]] with serialized content of cells from [[Sheet]], either a cell formula or an explicit value.
*
* @param {SimpleCellAddress} sheetId - sheet ID number
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[EvaluationSuspendedError]] when the evaluation is suspended
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['0', '=SUM(1,2,3)', '=A1'],
* ['1', '=TEXT(A2, "0.0%")', '=C1'],
* ['2', '=SUM(A1:C1)', '=C1'],
* ]);
*
* // should return:
* // [
* // ['0', '=SUM(1,2,3)', '=A1'],
* // ['1', '=TEXT(A2, "0.0%")', '=C1'],
* // ['2', '=SUM(A1:C1)', '=C1'],
* // ];
* const serializedContent = hfInstance.getSheetSerialized(0);
* ```
*
* @category Sheets
*/
}, {
key: "getSheetSerialized",
value: function getSheetSerialized(sheetId) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
this.ensureEvaluationIsNotSuspended();
return this._serialization.getSheetSerialized(sheetId);
}
/**
* Returns a map containing dimensions of all sheets for the engine instance represented as a key-value pairs where keys are sheet IDs and dimensions are returned as numbers, width and height respectively.
*
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromSheets({
* Sheet1: [
* ['1', '2', '=Sheet2!$A1'],
* ],
* Sheet2: [
* ['3'],
* ['4'],
* ],
* });
*
* // should return the dimensions of all sheets:
* // { Sheet1: { width: 3, height: 1 }, Sheet2: { width: 1, height: 2 } }
* const allSheetsDimensions = hfInstance.getAllSheetsDimensions();
* ```
*
* @category Sheets
*/
}, {
key: "getAllSheetsDimensions",
value: function getAllSheetsDimensions() {
var _this = this;
return this._serialization.genericAllSheetsGetter(function (arg) {
return _this.getSheetDimensions(arg);
});
}
/**
* Returns dimensions of a specified sheet.
* The sheet dimensions is represented with numbers: width and height.
*
* @param {number} sheetId - sheet ID number
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2', '=Sheet2!$A1'],
* ]);
*
* // should return provided sheet's dimensions: { width: 3, height: 1 }
* const sheetDimensions = hfInstance.getSheetDimensions(0);
* ```
*
* @category Sheets
*/
}, {
key: "getSheetDimensions",
value: function getSheetDimensions(sheetId) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
return {
width: this.dependencyGraph.getSheetWidth(sheetId),
height: this.dependencyGraph.getSheetHeight(sheetId)
};
}
/**
* Returns values of all sheets in a form of an object which property keys are strings and values are arrays of arrays of [[CellValue]].
*
* @throws [[EvaluationSuspendedError]] when the evaluation is suspended
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '=A1+10', '3'],
* ]);
*
* // should return all sheets values: { Sheet1: [ [ 1, 11, 3 ] ] }
* const allSheetsValues = hfInstance.getAllSheetsValues();
* ```
*
* @category Sheets
*/
}, {
key: "getAllSheetsValues",
value: function getAllSheetsValues() {
this.ensureEvaluationIsNotSuspended();
return this._serialization.getAllSheetsValues();
}
/**
* Returns formulas of all sheets in a form of an object which property keys are strings and values are arrays of arrays of strings or possibly `undefined` when the call does not contain a formula.
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2', '=A1+10'],
* ]);
*
* // should return only formulas: { Sheet1: [ [ undefined, undefined, '=A1+10' ] ] }
* const allSheetsFormulas = hfInstance.getAllSheetsFormulas();
* ```
* @category Sheets
*/
}, {
key: "getAllSheetsFormulas",
value: function getAllSheetsFormulas() {
return this._serialization.getAllSheetsFormulas();
}
/**
* Returns formulas or values of all sheets in a form of an object which property keys are strings and values are arrays of arrays of [[RawCellContent]].
*
* @throws [[EvaluationSuspendedError]] when the evaluation is suspended
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2', '=A1+10'],
* ]);
*
* // should return all sheets serialized content: { Sheet1: [ [ 1, 2, '=A1+10' ] ] }
* const allSheetsSerialized = hfInstance.getAllSheetsSerialized();
* ```
*
* @category Sheets
*/
}, {
key: "getAllSheetsSerialized",
value: function getAllSheetsSerialized() {
this.ensureEvaluationIsNotSuspended();
return this._serialization.getAllSheetsSerialized();
}
/**
* Updates the config with given new metadata.
*
* @param {Partial<ConfigParams>} newParams configuration options to be updated or added
*
* @throws [[ExpectedValueOfTypeError]] when some parameters of config are of wrong type (e.g. currencySymbol)
* @throws [[ConfigValueEmpty]] when some parameters of config are of invalid value (e.g. currencySymbol)
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2'],
* ]);
*
* // add a config param, for example maxColumns,
* // you can check the configuration with getConfig method
* hfInstance.updateConfig({ maxColumns: 1000 });
* ```
*
* @category Instance
*/
}, {
key: "updateConfig",
value: function updateConfig(newParams) {
var newConfig = this._config.mergeConfig(newParams);
var configNewLanguage = this._config.mergeConfig({
language: newParams.language
});
var serializedSheets = this._serialization.withNewConfig(configNewLanguage, this._namedExpressions).getAllSheetsSerialized();
var serializedNamedExpressions = this._serialization.getAllNamedExpressionsSerialized();
var newEngine = _BuildEngineFactory.BuildEngineFactory.rebuildWithConfig(newConfig, serializedSheets, serializedNamedExpressions, this._stats);
this._config = newEngine.config;
this._stats = newEngine.stats;
this._dependencyGraph = newEngine.dependencyGraph;
this._columnSearch = newEngine.columnSearch;
this._parser = newEngine.parser;
this._unparser = newEngine.unparser;
this._cellContentParser = newEngine.cellContentParser;
this._evaluator = newEngine.evaluator;
this._lazilyTransformingAstService = newEngine.lazilyTransformingAstService;
this._crudOperations = newEngine.crudOperations;
this._exporter = newEngine.exporter;
this._namedExpressions = newEngine.namedExpressions;
this._serialization = newEngine.serialization;
this._functionRegistry = newEngine.functionRegistry;
}
/**
* Returns current configuration of the engine instance.
*
* @example
* ```js
* // should return all config metadata including default and those which were added
* const hfConfig = hfInstance.getConfig();
* ```
*
* @category Instance
*/
}, {
key: "getConfig",
value: function getConfig() {
return this._config.getConfig();
}
/**
* Serializes and deserializes whole engine, effectively reloading it.
*
* @example
* ```js
* hfInstance.rebuildAndRecalculate();
* ```
*
* @category Instance
*/
}, {
key: "rebuildAndRecalculate",
value: function rebuildAndRecalculate() {
this.updateConfig({});
}
/**
* Returns a snapshot of computation time statistics.
* It returns a map with key-value pairs where keys are enums for stat type and time (number).
*
* @internal
*
* @category Instance
*/
}, {
key: "getStats",
value: function getStats() {
return this._stats.snapshot();
}
/**
* Undo the previous operation.
*
* Note that this method may trigger dependency graph recalculation.
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[NoOperationToUndoError]] when there is no operation running that can be undone
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2'],
* ['3', ''],
* ]);
*
* // perform CRUD operation, for example remove the second row
* hfInstance.removeRows(0, [1, 1]);
*
* // do an undo, it should return the changes
* const changes = hfInstance.undo();
* ```
*
* @category Undo and Redo
*/
}, {
key: "undo",
value: function undo() {
this._crudOperations.undo();
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Re-do recently undone operation.
*
* Note that this method may trigger dependency graph recalculation.
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[NoOperationToRedoError]] when there is no operation running that can be re-done
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1'],
* ['2'],
* ['3'],
* ]);
*
* // perform CRUD operation, for example remove the second row
* hfInstance.removeRows(0, [1, 1]);
*
* // do an undo, it should return prvious values: [['1'], ['2'], ['3']]
* hfInstance.undo();
*
* // do a redo, it should return the values after removing the second row: [['1'], ['3']]
* const changes = hfInstance.redo();
* ```
*
* @category Undo and Redo
*/
}, {
key: "redo",
value: function redo() {
this._crudOperations.redo();
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Checks if there is at least one operation that can be undone.
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1'],
* ['2'],
* ['3'],
* ]);
*
* // perform CRUD operation, for example remove the second row
* hfInstance.removeRows(0, [1, 1]);
*
* // should return 'true', it is possible to undo last operation
* // which is removing rows in this example
* const isSomethingToUndo = hfInstance.isThereSomethingToUndo();
* ```
*
* @category Undo and Redo
*/
}, {
key: "isThereSomethingToUndo",
value: function isThereSomethingToUndo() {
return this._crudOperations.isThereSomethingToUndo();
}
/**
* Checks if there is at least one operation that can be re-done.
*
* @example
* ```js
* hfInstance.undo();
*
* // when there is an action to redo, this returns 'true'
* const isSomethingToRedo = hfInstance.isThereSomethingToRedo();
* ```
*
* @category Undo and Redo
*/
}, {
key: "isThereSomethingToRedo",
value: function isThereSomethingToRedo() {
return this._crudOperations.isThereSomethingToRedo();
}
/**
* Returns information whether it is possible to change the content in a rectangular area bounded by the box.
* If returns `true`, doing [[setCellContents]] operation won't throw any errors.
* Returns `false` if the address is invalid or the sheet does not exist.
*
* @param {SimpleCellAddress | SimpleCellRange} address - single cell or block of cells to check
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[SheetsNotEqual]] if range provided has distinct sheet numbers for start and end
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2'],
* ]);
*
* // top left corner
* const address1 = { col: 0, row: 0, sheet: 0 };
* // bottom right corner
* const address2 = { col: 1, row: 0, sheet: 0 };
*
* // should return 'true' for this example, it is possible to set content of
* // width 2, height 1 in the first row and column of sheet 0
* const isSettable = hfInstance.isItPossibleToSetCellContents({ start: address1, end: address2 });
* ```
*
* @category Cells
*/
}, {
key: "isItPossibleToSetCellContents",
value: function isItPossibleToSetCellContents(address) {
var range;
if ((0, _Cell.isSimpleCellAddress)(address)) {
range = new _AbsoluteCellRange.AbsoluteCellRange(address, address);
} else if ((0, _AbsoluteCellRange.isSimpleCellRange)(address)) {
range = new _AbsoluteCellRange.AbsoluteCellRange(address.start, address.end);
} else {
throw new _errors.ExpectedValueOfTypeError('SimpleCellAddress | SimpleCellRange', 'address');
}
try {
this._crudOperations.ensureRangeInSizeLimits(range);
var _iterator = _createForOfIteratorHelper(range.addresses(this._dependencyGraph)),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var it = _step.value;
this._crudOperations.ensureItIsPossibleToChangeContent(it);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
} catch (e) {
return false;
}
return true;
}
/**
* Sets the content for a block of cells of a given coordinates.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {SimpleCellAddress} topLeftCornerAddress - top left corner of block of cells
* @param {(RawCellContent[][]|RawCellContent)} cellContents - array with content
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[InvalidArgumentsError]] when the value is not an array of arrays or a raw cell value
* @throws [[SheetSizeLimitExceededError]] when performing this operation would result in sheet size limits exceeding
* @throws [[ExpectedValueOfTypeError]] if topLeftCornerAddress argument is of wrong type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2', '=A1'],
* ]);
*
* // should set the content, returns:
* // [{
* // address: { sheet: 0, col: 3, row: 0 },
* // newValue: 2,
* // }]
* const changes = hfInstance.setCellContents({ col: 3, row: 0, sheet: 0 }, [['=B1']]);
* ```
*
* @category Cells
*/
}, {
key: "setCellContents",
value: function setCellContents(topLeftCornerAddress, cellContents) {
this._crudOperations.setCellContents(topLeftCornerAddress, cellContents);
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Reorders rows of a sheet according to a source-target mapping.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {[number, number][]} rowMapping - array mapping original positions to final positions of rows
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[InvalidArgumentsError]] when rowMapping does not define correct row permutation for some subset of rows of the given sheet
* @throws [[SourceLocationHasArrayError]] when the selected position has array inside
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1],
* [2],
* [4, 5],
* ]);
*
* // should set swap rows 0 and 2 in place, returns:
* // [{
* // address: { sheet: 0, col: 0, row: 2 },
* // newValue: 1,
* // },
* // {
* // address: { sheet: 0, col: 1, row: 2 },
* // newValue: null,
* // },
* // {
* // address: { sheet: 0, col: 0, row: 0 },
* // newValue: 4,
* // },
* // {
* // address: { sheet: 0, col: 1, row: 0 },
* // newValue: 5,
* // }]
* const changes = hfInstance.swapRowIndexes(0, [[0,2],[2,0]]);
* ```
*
* @category Rows
*/
}, {
key: "swapRowIndexes",
value: function swapRowIndexes(sheetId, rowMapping) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
this._crudOperations.setRowOrder(sheetId, rowMapping);
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Checks if it is possible to reorder rows of a sheet according to a source-target mapping.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {[number, number][]} rowMapping - array mapping original positions to final positions of rows
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1],
* [2],
* [4, 5],
* ]);
*
* // returns true
* const isSwappable = hfInstance.isItPossibleToSwapRowIndexes(0, [[0,2],[2,0]]);
*
* // returns false
* const isSwappable = hfInstance.isItPossibleToSwapRowIndexes(0, [[0,1]]);
* ```
*
* @category Rows
*/
}, {
key: "isItPossibleToSwapRowIndexes",
value: function isItPossibleToSwapRowIndexes(sheetId, rowMapping) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
try {
this._crudOperations.validateSwapRowIndexes(sheetId, rowMapping);
this._crudOperations.testRowOrderForArrays(sheetId, rowMapping);
return true;
} catch (e) {
return false;
}
}
/**
* Reorders rows of a sheet according to a permutation.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {number[]} newRowOrder - permutation of rows
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[InvalidArgumentsError]] when rowMapping does not define correct row permutation for some subset of rows of the given sheet
* @throws [[SourceLocationHasArrayError]] when the selected position has array inside
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1],
* [2],
* [4, 5],
* ]);
* // rows 0 and 2 swap places
*
* // returns:
* // [{
* // address: { sheet: 0, col: 0, row: 2 },
* // newValue: 1,
* // },
* // {
* // address: { sheet: 0, col: 1, row: 2 },
* // newValue: null,
* // },
* // {
* // address: { sheet: 0, col: 0, row: 0 },
* // newValue: 4,
* // },
* // {
* // address: { sheet: 0, col: 1, row: 0 },
* // newValue: 5,
* // }]
* const changes = hfInstance.setRowOrder(0, [2, 1, 0]);
* ```
*
* @category Rows
*/
}, {
key: "setRowOrder",
value: function setRowOrder(sheetId, newRowOrder) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
var mapping = this._crudOperations.mappingFromOrder(sheetId, newRowOrder, 'row');
return this.swapRowIndexes(sheetId, mapping);
}
/**
* Checks if it is possible to reorder rows of a sheet according to a permutation.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {number[]} newRowOrder - permutation of rows
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1],
* [2],
* [4, 5],
* ]);
*
* // returns true
* hfInstance.isItPossibleToSetRowOrder(0, [2, 1, 0]);
*
* // returns false
* hfInstance.isItPossibleToSetRowOrder(0, [2]);
* ```
*
* @category Rows
*/
}, {
key: "isItPossibleToSetRowOrder",
value: function isItPossibleToSetRowOrder(sheetId, newRowOrder) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
try {
var rowMapping = this._crudOperations.mappingFromOrder(sheetId, newRowOrder, 'row');
this._crudOperations.validateSwapRowIndexes(sheetId, rowMapping);
this._crudOperations.testRowOrderForArrays(sheetId, rowMapping);
return true;
} catch (e) {
return false;
}
}
/**
* Reorders columns of a sheet according to a source-target mapping.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {[number, number][]} columnMapping - array mapping original positions to final positions of columns
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[InvalidArgumentsError]] when columnMapping does not define correct column permutation for some subset of columns of the given sheet
* @throws [[SourceLocationHasArrayError]] when the selected position has array inside
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1, 2, 4],
* [5]
* ]);
*
* // should set swap columns 0 and 2 in place, returns:
* // [{
* // address: { sheet: 0, col: 2, row: 0 },
* // newValue: 1,
* // },
* // {
* // address: { sheet: 0, col: 2, row: 1 },
* // newValue: 5,
* // },
* // {
* // address: { sheet: 0, col: 0, row: 0 },
* // newValue: 4,
* // },
* // {
* // address: { sheet: 0, col: 0, row: 1 },
* // newValue: null,
* // }]
* const changes = hfInstance.swapColumnIndexes(0, [[0,2],[2,0]]);
* ```
*
* @category Columns
*/
}, {
key: "swapColumnIndexes",
value: function swapColumnIndexes(sheetId, columnMapping) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
this._crudOperations.setColumnOrder(sheetId, columnMapping);
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Checks if it is possible to reorder columns of a sheet according to a source-target mapping.
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1, 2, 4],
* [5]
* ]);
*
* // returns true
* hfInstance.isItPossibleToSwapColumnIndexes(0, [[0,2],[2,0]]);
*
* // returns false
* hfInstance.isItPossibleToSwapColumnIndexes(0, [[0,1]]);
* ```
*
* @category Columns
*/
}, {
key: "isItPossibleToSwapColumnIndexes",
value: function isItPossibleToSwapColumnIndexes(sheetId, columnMapping) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
try {
this._crudOperations.validateSwapColumnIndexes(sheetId, columnMapping);
this._crudOperations.testColumnOrderForArrays(sheetId, columnMapping);
return true;
} catch (e) {
return false;
}
}
/**
* Reorders columns of a sheet according to a permutation.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {number[]} newColumnOrder - permutation of columns
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[InvalidArgumentsError]] when columnMapping does not define correct column permutation for some subset of columns of the given sheet
* @throws [[SourceLocationHasArrayError]] when the selected position has array inside
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1, 2, 4],
* [5]
* ]);
* // columns 0 and 2 swap places
*
* // returns:
* // [{
* // address: { sheet: 0, col: 2, row: 0 },
* // newValue: 1,
* // },
* // {
* // address: { sheet: 0, col: 2, row: 1 },
* // newValue: 5,
* // },
* // {
* // address: { sheet: 0, col: 0, row: 0 },
* // newValue: 4,
* // },
* // {
* // address: { sheet: 0, col: 0, row: 1 },
* // newValue: null,
* // }]
* const changes = hfInstance.setColumnOrder(0, [2, 1, 0]]);
* ```
*
* @category Columns
*/
}, {
key: "setColumnOrder",
value: function setColumnOrder(sheetId, newColumnOrder) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
var mapping = this._crudOperations.mappingFromOrder(sheetId, newColumnOrder, 'column');
return this.swapColumnIndexes(sheetId, mapping);
}
/**
* Checks if it possible to reorder columns of a sheet according to a permutation.
*
* @param {number} sheetId - ID of a sheet to operate on
* @param {number[]} newColumnOrder - permutation of columns
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* [1, 2, 4],
* [5]
* ]);
*
* // returns true
* hfInstance.isItPossibleToSetColumnOrder(0, [2, 1, 0]]);
*
* // returns false
* hfInstance.isItPossibleToSetColumnOrder(0, [1]]);
* ```
*
* @category Columns
*/
}, {
key: "isItPossibleToSetColumnOrder",
value: function isItPossibleToSetColumnOrder(sheetId, newColumnOrder) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
try {
var columnMapping = this._crudOperations.mappingFromOrder(sheetId, newColumnOrder, 'column');
this._crudOperations.validateSwapColumnIndexes(sheetId, columnMapping);
this._crudOperations.testColumnOrderForArrays(sheetId, columnMapping);
return true;
} catch (e) {
return false;
}
}
/**
* Returns information whether it is possible to add rows into a specified position in a given sheet.
* Checks against particular rules to ascertain that addRows can be called.
* If returns `true`, doing [[addRows]] operation won't throw any errors.
* Returns `false` if adding rows would exceed the sheet size limit or given arguments are invalid.
*
* @param {number} sheetId - sheet ID in which rows will be added
* @param {ColumnRowIndex[]} indexes - non-contiguous indexes with format [row, amount], where row is a row number above which the rows will be added
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1', '2', '3'],
* ]);
*
* // should return 'true' for this example,
* // it is possible to add one row in the second row of sheet 0
* const isAddable = hfInstance.isItPossibleToAddRows(0, [1, 1]);
* ```
*
* @category Rows
*/
}, {
key: "isItPossibleToAddRows",
value: function isItPossibleToAddRows(sheetId) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
for (var _len = arguments.length, indexes = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
indexes[_key - 1] = arguments[_key];
}
var normalizedIndexes = (0, _Operations.normalizeAddedIndexes)(indexes);
try {
var _this$_crudOperations;
(_this$_crudOperations = this._crudOperations).ensureItIsPossibleToAddRows.apply(_this$_crudOperations, [sheetId].concat(_toConsumableArray(normalizedIndexes)));
return true;
} catch (e) {
return false;
}
}
/**
* Adds multiple rows into a specified position in a given sheet.
* Does nothing if rows are outside of effective sheet size.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {number} sheetId - sheet ID in which rows will be added
* @param {ColumnRowIndex[]} indexes - non-contiguous indexes with format [row, amount], where row is a row number above which the rows will be added
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
* @throws [[SheetSizeLimitExceededError]] when performing this operation would result in sheet size limits exceeding
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1'],
* ['2'],
* ]);
*
* // should return a list of cells which values changed after the operation,
* // their absolute addresses and new values
* const changes = hfInstance.addRows(0, [0, 1]);
* ```
*
* @category Rows
*/
}, {
key: "addRows",
value: function addRows(sheetId) {
var _this$_crudOperations2;
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
for (var _len2 = arguments.length, indexes = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
indexes[_key2 - 1] = arguments[_key2];
}
(_this$_crudOperations2 = this._crudOperations).addRows.apply(_this$_crudOperations2, [sheetId].concat(indexes));
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Returns information whether it is possible to remove rows from a specified position in a given sheet.
* Checks against particular rules to ascertain that removeRows can be called.
* If returns `true`, doing [[removeRows]] operation won't throw any errors.
* Returns `false` if given arguments are invalid.
*
* @param {number} sheetId - sheet ID from which rows will be removed
* @param {ColumnRowIndex[]} indexes - non-contiguous indexes with format: [row, amount]
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1'],
* ['2'],
* ]);
*
* // should return 'true' for this example
* // it is possible to remove one row from row 1 of sheet 0
* const isRemovable = hfInstance.isItPossibleToRemoveRows(0, [1, 1]);
* ```
*
* @category Rows
*/
}, {
key: "isItPossibleToRemoveRows",
value: function isItPossibleToRemoveRows(sheetId) {
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
for (var _len3 = arguments.length, indexes = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
indexes[_key3 - 1] = arguments[_key3];
}
var normalizedIndexes = (0, _Operations.normalizeRemovedIndexes)(indexes);
try {
var _this$_crudOperations3;
(_this$_crudOperations3 = this._crudOperations).ensureItIsPossibleToRemoveRows.apply(_this$_crudOperations3, [sheetId].concat(_toConsumableArray(normalizedIndexes)));
return true;
} catch (e) {
return false;
}
}
/**
* Removes multiple rows from a specified position in a given sheet.
* Does nothing if rows are outside of the effective sheet size.
*
* Note that this method may trigger dependency graph recalculation.
*
* @param {number} sheetId - sheet ID from which rows will be removed
* @param {ColumnRowIndex[]} indexes - non-contiguous indexes with format: [row, amount]
*
* @fires [[valuesUpdated]] if recalculation was triggered by this change
*
* @throws [[ExpectedValueOfTypeError]] if any of its basic type argument is of wrong type
* @throws [[InvalidArgumentsError]] when the given arguments are invalid
* @throws [[NoSheetWithIdError]] when the given sheet ID does not exist
*
* @example
* ```js
* const hfInstance = HyperFormula.buildFromArray([
* ['1'],
* ['2'],
* ]);
*
* // should return: [{ sheet: 0, col: 1, row: 2, value: null }] for this example
* const changes = hfInstance.removeRows(0, [1, 1]);
* ```
*
* @category Rows
*/
}, {
key: "removeRows",
value: function removeRows(sheetId) {
var _this$_crudOperations4;
(0, _ArgumentSanitization.validateArgToType)(sheetId, 'number', 'sheetId');
for (var _len4 = arguments.length, indexes = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
indexes[_key4 - 1] = arguments[_key4];
}
(_this$_crudOperations4 = this._crudOperations).removeRows.apply(_this$_crudOperations4, [sheetId].concat(indexes));
return this.recomputeIfDependencyGraphNeedsIt();
}
/**
* Returns information whether it is possible to add columns into a specified position in a given sheet.
* Checks against particular rules to ascertain that addColumns can be called.
* If returns `true`, doing [[addColumns]] operation won't throw any errors.
* Returns `false` if adding columns would exceed the sheet size limit or given arguments are invali