hyperformula-dc
Version:
HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas
608 lines (553 loc) • 18.6 kB
JavaScript
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
}
};