UNPKG

hyperformula-dc

Version:

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

608 lines (553 loc) 18.6 kB
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } import "core-js/modules/es.object.get-prototype-of.js"; import "core-js/modules/es.reflect.construct.js"; import "core-js/modules/es.symbol.js"; import "core-js/modules/es.symbol.description.js"; import "core-js/modules/es.object.to-string.js"; import "core-js/modules/es.symbol.iterator.js"; import "core-js/modules/es.array.iterator.js"; import "core-js/modules/es.string.iterator.js"; import "core-js/modules/web.dom-collections.iterator.js"; 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; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } /** * @license * Copyright (c) 2021 Handsoncode. All rights reserved. */ import { CellError, ErrorType } from '../../Cell'; import { FormulaVertex } from '../../DependencyGraph/FormulaCellVertex'; import { ErrorMessage } from '../../error-message'; import { AstNodeType } from '../../parser'; import { EmptyValue, isExtendedNumber } from '../InterpreterValue'; import { SimpleRangeValue } from '../SimpleRangeValue'; import { ArgumentTypes, FunctionPlugin } from './FunctionPlugin'; /** * Interpreter plugin containing information functions */ export var InformationPlugin = /*#__PURE__*/function (_FunctionPlugin) { _inherits(InformationPlugin, _FunctionPlugin); var _super = _createSuper(InformationPlugin); function InformationPlugin() { _classCallCheck(this, InformationPlugin); return _super.apply(this, arguments); } _createClass(InformationPlugin, [{ key: "isbinary", value: /** * Corresponds to ISBINARY(value) * * Returns true if provided value is a valid binary number * * @param ast * @param state */ function isbinary(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISBINARY'), function (arg) { return /^[01]{1,10}$/.test(arg); }); } /** * Corresponds to ISERR(value) * * Returns true if provided value is an error except #N/A! * * @param ast * @param state */ }, { key: "iserr", value: function iserr(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISERR'), function (arg) { return arg instanceof CellError && arg.type !== ErrorType.NA; }); } /** * Corresponds to ISERROR(value) * * Checks whether provided value is an error * * @param ast * @param state */ }, { key: "iserror", value: function iserror(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISERROR'), function (arg) { return arg instanceof CellError; }); } /** * Corresponds to ISFORMULA(value) * * Checks whether referenced cell is a formula * * @param ast * @param state */ }, { key: "isformula", value: function isformula(ast, state) { var _this = this; return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('ISFORMULA'), function () { return new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber); }, function (reference) { var vertex = _this.dependencyGraph.addressMapping.getCell(reference); return vertex instanceof FormulaVertex; }); } /** * Corresponds to ISBLANK(value) * * Checks whether provided cell reference is empty * * @param ast * @param state */ }, { key: "isblank", value: function isblank(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISBLANK'), function (arg) { return arg === EmptyValue; }); } /** * Corresponds to ISNA(value) * * Returns true if provided value is #N/A! error * * @param ast * @param state */ }, { key: "isna", value: function isna(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISNA'), function (arg) { return arg instanceof CellError && arg.type == ErrorType.NA; }); } /** * Corresponds to ISNUMBER(value) * * Checks whether provided cell reference is a number * * @param ast * @param state */ }, { key: "isnumber", value: function isnumber(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISNUMBER'), isExtendedNumber); } /** * Corresponds to ISLOGICAL(value) * * Checks whether provided cell reference is of logical type * * @param ast * @param state */ }, { key: "islogical", value: function islogical(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISLOGICAL'), function (arg) { return typeof arg === 'boolean'; }); } /** * Corresponds to ISREF(value) * * Returns true if provided value is #REF! error * * @param ast * @param state */ }, { key: "isref", value: function isref(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISREF'), function (arg) { return arg instanceof CellError && (arg.type == ErrorType.REF || arg.type == ErrorType.CYCLE); }); } /** * Corresponds to ISTEXT(value) * * Checks whether provided cell reference is of logical type * * @param ast * @param state */ }, { key: "istext", value: function istext(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISTEXT'), function (arg) { return typeof arg === 'string'; }); } /** * Corresponds to ISNONTEXT(value) * * Checks whether provided cell reference is of logical type * * @param ast * @param state */ }, { key: "isnontext", value: function isnontext(ast, state) { return this.runFunction(ast.args, state, this.metadata('ISNONTEXT'), function (arg) { return !(typeof arg === 'string'); }); } /** * Corresponds to COLUMN(reference) * * Returns column number of a reference or a formula cell if reference not provided * * @param ast * @param state */ }, { key: "column", value: function column(ast, state) { return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('COLUMN'), function () { return state.formulaAddress.col + 1; }, function (reference) { return reference.col + 1; }); } /** * Corresponds to COLUMNS(range) * * Returns number of columns in provided range of cells * * @param ast * @param _state */ }, { key: "columns", value: function columns(ast, state) { if (ast.args.length !== 1) { return new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber); } if (ast.args.some(function (astIt) { return astIt.type === AstNodeType.EMPTY; })) { return new CellError(ErrorType.NUM, ErrorMessage.EmptyArg); } var argAst = ast.args[0]; while (argAst.type === AstNodeType.PARENTHESIS) { argAst = argAst.expression; } if (argAst.type === AstNodeType.CELL_RANGE || argAst.type === AstNodeType.COLUMN_RANGE) { return argAst.end.col - argAst.start.col + 1; } else if (argAst.type === AstNodeType.CELL_REFERENCE) { return 1; } else if (argAst.type === AstNodeType.ROW_RANGE) { return this.config.maxColumns; } else { var val = this.evaluateAst(argAst, state); if (val instanceof SimpleRangeValue) { return val.width(); } else if (val instanceof CellError) { return val; } else { return 1; } } } /** * Corresponds to ROW(reference) * * Returns row number of a reference or a formula cell if reference not provided * * @param ast * @param state */ }, { key: "row", value: function row(ast, state) { return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('ROW'), function () { return state.formulaAddress.row + 1; }, function (reference) { return reference.row + 1; }); } /** * Corresponds to ROWS(range) * * Returns number of rows in provided range of cells * * @param ast * @param _state */ }, { key: "rows", value: function rows(ast, state) { if (ast.args.length !== 1) { return new CellError(ErrorType.NA, ErrorMessage.WrongArgNumber); } if (ast.args.some(function (astIt) { return astIt.type === AstNodeType.EMPTY; })) { return new CellError(ErrorType.NUM, ErrorMessage.EmptyArg); } var argAst = ast.args[0]; while (argAst.type === AstNodeType.PARENTHESIS) { argAst = argAst.expression; } if (argAst.type === AstNodeType.CELL_RANGE || argAst.type === AstNodeType.ROW_RANGE) { return argAst.end.row - argAst.start.row + 1; } else if (argAst.type === AstNodeType.CELL_REFERENCE) { return 1; } else if (argAst.type === AstNodeType.COLUMN_RANGE) { return this.config.maxRows; } else { var val = this.evaluateAst(argAst, state); if (val instanceof SimpleRangeValue) { return val.height(); } else if (val instanceof CellError) { return val; } else { return 1; } } } /** * Corresponds to INDEX(range;) * * Returns specific position in 2d array. * * @param ast * @param state */ }, { key: "index", value: function index(ast, state) { var _this2 = this; return this.runFunction(ast.args, state, this.metadata('INDEX'), function (rangeValue, row, col) { var _a, _b, _c, _d, _e, _f; if (col < 1 || row < 1) { return new CellError(ErrorType.VALUE, ErrorMessage.LessThanOne); } if (col > rangeValue.width() || row > rangeValue.height()) { return new CellError(ErrorType.NUM, ErrorMessage.ValueLarge); } return (_f = (_c = (_b = (_a = rangeValue === null || rangeValue === void 0 ? void 0 : rangeValue.data) === null || _a === void 0 ? void 0 : _a[row - 1]) === null || _b === void 0 ? void 0 : _b[col - 1]) !== null && _c !== void 0 ? _c : (_e = (_d = rangeValue === null || rangeValue === void 0 ? void 0 : rangeValue.data) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e[0]) !== null && _f !== void 0 ? _f : new CellError(ErrorType.VALUE, ErrorMessage.CellRangeExpected); var address = rangeValue.range.getAddress(col - 1, row - 1); return _this2.dependencyGraph.getScalarValue(address); }); } /** * Corresponds to NA() * * Returns #N/A! * * @param _ast * @param _state */ }, { key: "na", value: function na(_ast, _state) { return new CellError(ErrorType.NA); } /** * Corresponds to SHEET(value) * * Returns sheet number of a given value or a formula sheet number if no argument is provided * * @param ast * @param state * */ }, { key: "sheet", value: function sheet(ast, state) { var _this3 = this; return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('SHEET'), function () { return state.formulaAddress.sheet + 1; }, function (reference) { return reference.sheet + 1; }, function (value) { var sheetNumber = _this3.dependencyGraph.sheetMapping.get(value); if (sheetNumber !== undefined) { return sheetNumber + 1; } else { return new CellError(ErrorType.NA, ErrorMessage.SheetRef); } }); } /** * Corresponds to SHEETS(value) * * Returns number of sheet of a given reference or number of all sheets in workbook when no argument is provided. * It returns always 1 for a valid reference as 3D references are not supported. * * @param ast * @param state * */ }, { key: "sheets", value: function sheets(ast, state) { var _this4 = this; return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata('SHEETS'), function () { return _this4.dependencyGraph.sheetMapping.numberOfSheets(); }, // return number of sheets if no argument function () { return 1; }, // return 1 for valid reference function () { return new CellError(ErrorType.VALUE, ErrorMessage.CellRefExpected); } // error otherwise ); } }]); return InformationPlugin; }(FunctionPlugin); InformationPlugin.implementedFunctions = { 'COLUMN': { method: 'column', parameters: [{ argumentType: ArgumentTypes.NOERROR, optional: true }], isDependentOnSheetStructureChange: true, doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true }, 'COLUMNS': { method: 'columns', parameters: [{ argumentType: ArgumentTypes.RANGE }], isDependentOnSheetStructureChange: true, doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true }, 'ISBINARY': { method: 'isbinary', parameters: [{ argumentType: ArgumentTypes.STRING }] }, 'ISERR': { method: 'iserr', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISFORMULA': { method: 'isformula', parameters: [{ argumentType: ArgumentTypes.NOERROR }], doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true }, 'ISNA': { method: 'isna', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISREF': { method: 'isref', parameters: [{ argumentType: ArgumentTypes.SCALAR }], vectorizationForbidden: true }, 'ISERROR': { method: 'iserror', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISBLANK': { method: 'isblank', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISNUMBER': { method: 'isnumber', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISLOGICAL': { method: 'islogical', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISTEXT': { method: 'istext', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'ISNONTEXT': { method: 'isnontext', parameters: [{ argumentType: ArgumentTypes.SCALAR }] }, 'INDEX': { method: 'index', parameters: [{ argumentType: ArgumentTypes.RANGE }, { argumentType: ArgumentTypes.NUMBER }, { argumentType: ArgumentTypes.NUMBER, defaultValue: 1 }] }, 'NA': { method: 'na', parameters: [] }, 'ROW': { method: 'row', parameters: [{ argumentType: ArgumentTypes.NOERROR, optional: true }], isDependentOnSheetStructureChange: true, doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true }, 'ROWS': { method: 'rows', parameters: [{ argumentType: ArgumentTypes.RANGE }], isDependentOnSheetStructureChange: true, doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true }, 'SHEET': { method: 'sheet', parameters: [{ argumentType: ArgumentTypes.STRING }], doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true }, 'SHEETS': { method: 'sheets', parameters: [{ argumentType: ArgumentTypes.STRING }], doesNotNeedArgumentsToBeComputed: true, vectorizationForbidden: true } };