UNPKG

@syncfusion/ej2-spreadsheet

Version:

Feature-rich JavaScript Spreadsheet (Excel) control with built-in support for selection, editing, formatting, importing and exporting to Excel

1,010 lines 79.4 kB
import { getSheetName, getSheet, getSheetIndexFromId, setCell, getTypeFromFormat, isHiddenRow, isHiddenCol } from '../index'; import { getCell, getSheetIndex, checkFormulaRef, parseFormulaArgument, sheetRenameUpdate } from '../index'; import { workbookFormulaOperation, getColumnHeaderText, aggregateComputation, clearFormulaDependentCells, formulaInValidation, applyCF, getCellRefValue, commputeFormulaValue, getAutoDetectFormatParser, calculateFormula } from '../common/index'; import { Calculate, ValueChangedArgs, CommonErrors, getAlphalabel } from '../../calculate/index'; import { isNullOrUndefined, getNumericObject } from '@syncfusion/ej2-base'; import { Deferred } from '@syncfusion/ej2-data'; import { getCellAddress, getFormattedCellObject, isNumber, checkIsFormula, removeUniquecol, checkUniqueRange } from '../common/index'; import { getRangeAddress, getRangeFromAddress, isCellReference, refreshInsertDelete, getUpdatedFormulaOnInsertDelete } from '../common/index'; import { getUniqueRange, DefineName, selectionComplete, getRangeIndexes, getSwapRange } from '../common/index'; import { updateSheetFromDataSource, importModelUpdate } from '../common/index'; import { formulaBarOperation } from '../../spreadsheet/common/event'; /** * @hidden * The `WorkbookFormula` module is used to handle the formula operation in Workbook. */ var WorkbookFormula = /** @class */ (function () { /** * Constructor for formula module in Workbook. * * @param {Workbook} workbook - Specifies the workbook. * @private */ function WorkbookFormula(workbook) { this.uniqueOBracket = String.fromCharCode(129); this.uniqueCBracket = String.fromCharCode(130); this.uniqueCSeparator = String.fromCharCode(131); this.uniqueCOperator = String.fromCharCode(132); this.uniquePOperator = String.fromCharCode(133); this.uniqueSOperator = String.fromCharCode(134); this.uniqueMOperator = String.fromCharCode(135); this.uniqueDOperator = String.fromCharCode(136); this.uniqueModOperator = String.fromCharCode(137); this.uniqueConcateOperator = String.fromCharCode(138); this.uniqueEqualOperator = String.fromCharCode(139); this.uniqueExpOperator = String.fromCharCode(140); this.uniqueGTOperator = String.fromCharCode(141); this.uniqueLTOperator = String.fromCharCode(142); this.sheetInfo = []; this.parent = workbook; this.init(); } WorkbookFormula.prototype.init = function () { var _this = this; this.addEventListener(); this.initCalculate(); this.registerSheet(); this.parent.customFormulaCollection.forEach(function (value, key) { _this.addCustomFunction(value.handler, key, value.description); }); }; /** * To destroy the formula module. * * @returns {void} * @hidden */ WorkbookFormula.prototype.destroy = function () { var _this = this; this.removeEventListener(); // eslint-disable-next-line @typescript-eslint/no-explicit-any if (this.parent.refreshing) { this.clearAllUniqueFormulaValue(); var formulaCollect = this.calculateInstance.getLibraryFormulas(); formulaCollect.forEach(function (value, key) { if (value.isCustom) { _this.parent.customFormulaCollection.set(key, { handler: value.handler, description: value.description }); } }); } this.calculateInstance.dispose(); this.calculateInstance = null; if (this.sheetInfo) { this.sheetInfo = []; } this.parent = null; }; WorkbookFormula.prototype.addEventListener = function () { this.parent.on(workbookFormulaOperation, this.performFormulaOperation, this); this.parent.on(aggregateComputation, this.aggregateComputation, this); this.parent.on(getUniqueRange, this.getUniqueRange, this); this.parent.on(removeUniquecol, this.removeUniquecol, this); this.parent.on(clearFormulaDependentCells, this.clearFormulaDependentCells, this); this.parent.on(formulaInValidation, this.formulaInValidation, this); this.parent.on(refreshInsertDelete, this.refreshInsertDelete, this); this.parent.on(getUpdatedFormulaOnInsertDelete, this.getUpdatedFormulaOnInsertDelete, this); this.parent.on(checkFormulaRef, this.autoCorrectCellRef, this); this.parent.on(parseFormulaArgument, this.parseFormulaArgument, this); this.parent.on(getCellRefValue, this.getCellRefValue, this); this.parent.on(commputeFormulaValue, this.commputeFormulaValue, this); this.parent.on(sheetRenameUpdate, this.renameUpdation, this); this.parent.on(importModelUpdate, this.initFormulaOnImport, this); }; WorkbookFormula.prototype.removeEventListener = function () { if (!this.parent.isDestroyed) { this.parent.off(workbookFormulaOperation, this.performFormulaOperation); this.parent.off(aggregateComputation, this.aggregateComputation); this.parent.off(getUniqueRange, this.getUniqueRange); this.parent.off(removeUniquecol, this.removeUniquecol); this.parent.off(clearFormulaDependentCells, this.clearFormulaDependentCells); this.parent.off(formulaInValidation, this.formulaInValidation); this.parent.off(refreshInsertDelete, this.refreshInsertDelete); this.parent.off(getUpdatedFormulaOnInsertDelete, this.getUpdatedFormulaOnInsertDelete); this.parent.off(checkFormulaRef, this.autoCorrectCellRef); this.parent.off(parseFormulaArgument, this.parseFormulaArgument); this.parent.off(getCellRefValue, this.getCellRefValue); this.parent.off(commputeFormulaValue, this.commputeFormulaValue); this.parent.off(sheetRenameUpdate, this.renameUpdation); this.parent.off(importModelUpdate, this.initFormulaOnImport); } }; /** * Get the module name. * * @returns {string} - Get the module name. * @private */ WorkbookFormula.prototype.getModuleName = function () { return 'workbookFormula'; }; WorkbookFormula.prototype.initCalculate = function () { this.calculateInstance = new Calculate(this.parent); this.calcID = this.calculateInstance.createSheetFamilyID(); this.calculateInstance.setTreatEmptyStringAsZero(true); this.calculateInstance.grid = this.parent.getActiveSheet().id.toString(); this.calculateInstance.setParseArgumentSeparator(this.parent.listSeparator); var decimalSeparator = getNumericObject(this.parent.locale).decimal; if (decimalSeparator !== '.' && this.parent.listSeparator !== decimalSeparator) { this.calculateInstance.setParseDecimalSeparator(decimalSeparator); } }; WorkbookFormula.prototype.clearFormulaDependentCells = function (args) { if (args.isOpen) { this.calculateInstance.getDependentCells().clear(); this.calculateInstance.getFormulaInfoTable().clear(); this.calculateInstance.getDependentFormulaCells().clear(); return; } var cellRef = args.cellRef.split(':')[0]; var sheetId = this.parent.getActiveSheet().id.toString(); var family = this.calculateInstance.getSheetFamilyItem(sheetId); if (family.isSheetMember && !isNullOrUndefined(family.parentObjectToToken)) { cellRef = family.parentObjectToToken.get(sheetId) + cellRef; } if (args.clearFormulaInfo && this.calculateInstance.getFormulaInfoTable().has(cellRef)) { this.calculateInstance.getFormulaInfoTable().delete(cellRef); } this.calculateInstance.clearFormulaDependentCells(cellRef); }; WorkbookFormula.prototype.formulaInValidation = function (args) { var col = this.calculateInstance.getLibraryFormulas().get(args.value); args.skip = isNullOrUndefined(col); }; WorkbookFormula.prototype.performFormulaOperation = function (args) { var action = args.action; var formulas; var formulaInfo; if (action !== 'refreshCalculate') { formulas = this.calculateInstance.getLibraryFormulas(); formulaInfo = (Array.from(formulas.values())); } var collection; var family = this.calculateInstance.getSheetFamilyItem(args.sheetId); switch (action) { case 'getLibraryFormulas': args.formulaCollection = Array.from(formulas.keys()); break; case 'getFormulaCategory': collection = ['All']; for (var i = 1; i < Array.from(formulas.values()).length; i++) { if (collection.indexOf(formulaInfo[i].category) < 0) { collection.push(formulaInfo[i].category); } } args.categoryCollection = collection; break; case 'dropDownSelectFormulas': for (var i = 0; i < Array.from(formulas.values()).length; i++) { if (args.selectCategory === formulaInfo[i].category) { args.formulaCollection[i] = Array.from(formulas.keys())[i]; } } break; case 'getFormulaDescription': for (var i = 0; i < Array.from(formulas.values()).length; i++) { if (args.selectedList === Array.from(formulas.keys())[i]) { args.description = formulaInfo[i].description; args.isCustom = formulaInfo[i].isCustom; } } break; case 'registerSheet': this.registerSheet(args.sheetIndex, args.sheetCount); break; case 'unRegisterSheet': this.unRegisterSheet(args.sheetIndex, args.sheetCount, args.propertyChange, args.isNewWorkBook); break; case 'initSheetInfo': this.updateSheetInfo(); break; case 'refreshCalculate': this.refreshCalculate(args); break; case 'refreshRandomFormula': this.refreshRandomFormula(); this.calculateInstance.cell = ''; break; case 'setArgumentSeparator': this.calculateInstance.setParseArgumentSeparator(this.parent.listSeparator); break; case 'addDefinedName': args.isAdded = this.addDefinedName(args.definedName, false, args.index, args.isEventTrigger); break; case 'removeDefinedName': args.isRemoved = this.removeDefinedName(args.definedName, args.scope, args.isEventTrigger); break; case 'initiateDefinedNames': this.initiateDefinedNames(); break; case 'addSheet': this.sheetInfo.push({ visibleName: args.visibleName, sheet: args.sheetName, index: args.sheetId }); break; case 'getSheetInfo': args.sheetInfo = this.sheetInfo; break; case 'deleteSheetTab': for (var i = 0; i < this.sheetInfo.length; i++) { if (this.sheetInfo[i].index === args.sheetId) { var visibleName = this.sheetInfo[i].visibleName; var sheetName = this.sheetInfo[i].sheet; this.sheetInfo.splice(i, 1); var id = args.sheetId.toString(); this.sheetDeletion(sheetName, id); this.calculateInstance.unregisterGridAsSheet(id, id); this.definedNamesDeletion(visibleName); break; } } break; case 'getReferenceError': args.refError = this.referenceError(); break; case 'getAlpha': args.col = getAlphalabel(args.col); break; case 'addCustomFunction': this.addCustomFunction(args.functionHandler, args.functionName, args.formulaDescription); break; case 'computeExpression': args.calcValue = this.calculateInstance.computeExpression(args.formula, args.isFromComputeExpression); break; case 'registerGridInCalc': this.calculateInstance.grid = args.sheetID; break; case 'dependentCellsAvailable': case 'checkFormulaAdded': if (family.isSheetMember && !isNullOrUndefined(family.parentObjectToToken)) { args.address = family.parentObjectToToken.get(args.sheetId) + args.address; } if (action === 'checkFormulaAdded') { args.added = this.calculateInstance.getFormulaInfoTable().has(args.address); } else { args.isAvailable = this.calculateInstance.getDependentCells().has(args.address); } break; case 'calculateNow': this.calculateNow(args); break; case 'ClearDependentCellCollection': this.calculateInstance.getDependentFormulaCells().clear(); this.calculateInstance.getDependentCells().clear(); this.calculateInstance.getFormulaInfoTable().clear(); break; } }; WorkbookFormula.prototype.initFormulaOnImport = function () { this.registerSheet(); this.calculateInstance.setParseArgumentSeparator(this.parent.listSeparator); this.updateSheetInfo(); this.initiateDefinedNames(); }; WorkbookFormula.prototype.definedNamesDeletion = function (sheetName) { var definedNames = this.parent.definedNames; if (definedNames && definedNames.length > 0) { for (var i = definedNames.length - 1; i >= 0; i--) { if (definedNames[i].refersTo.substring(1, definedNames[i].refersTo.lastIndexOf('!')).split('\'').join('') === sheetName) { this.removeDefinedName(definedNames[i].name, definedNames[i].scope); } } } }; WorkbookFormula.prototype.referenceError = function () { return this.calculateInstance.getErrorStrings()[CommonErrors.Ref]; }; WorkbookFormula.prototype.getSheetInfo = function () { return this.sheetInfo; }; WorkbookFormula.prototype.addCustomFunction = function (functionHandler, functionName, formulaDescription) { this.calculateInstance.defineFunction(functionName, functionHandler, formulaDescription); }; WorkbookFormula.prototype.updateSheetInfo = function () { var _this = this; this.sheetInfo = []; this.parent.sheets.forEach(function (sheet) { _this.sheetInfo.push({ visibleName: sheet.name, sheet: 'Sheet' + sheet.id, index: sheet.id }); }); }; WorkbookFormula.prototype.getSheetRefUpdateOnDelete = function () { var _this = this; var definedNames = this.calculateInstance.namedRanges; var keyArray; var valueArray; var isDefinedNamesAvail; if (definedNames && definedNames.size) { isDefinedNamesAvail = true; keyArray = Array.from(definedNames.keys()); valueArray = Array.from(definedNames.values()); } return function (delSheetName, formula) { var isNamedRange; if (isDefinedNamesAvail && !formula.includes(delSheetName)) { formula = formula.replace(/\w+/g, function (key) { var index = keyArray.indexOf(key); if (index !== -1) { isNamedRange = true; return valueArray[index]; } return key; }); } var sheetName = delSheetName.toUpperCase(); formula = formula.toUpperCase(); var idx = formula.indexOf(sheetName); while (idx > -1) { formula = formula.split((formula[idx - 1] === '\'' && formula[idx + sheetName.length] === '\'' ? "'" + sheetName + "'" : sheetName) + _this.calculateInstance.sheetToken).join(_this.referenceError()); idx = formula.indexOf(sheetName); } return { value: formula, isNamedRange: isNamedRange }; }; }; WorkbookFormula.prototype.sheetDeletion = function (delSheetName, sheetId) { var _this = this; var dependentCell = this.calculateInstance.getDependentCells(); var fInfo; var token; var family = this.calculateInstance.getSheetFamilyItem(sheetId); var updateSheetRef = this.getSheetRefUpdateOnDelete(); var updatedInfo; dependentCell.forEach(function (dependentCellRefs, cellRef) { dependentCellRefs.forEach(function (dependentCellRef) { fInfo = _this.calculateInstance.getFormulaInfoTable().get(dependentCellRef); if (!isNullOrUndefined(fInfo)) { updatedInfo = updateSheetRef(delSheetName, fInfo.formulaText); if (updatedInfo.value !== fInfo.formulaText) { token = dependentCellRef.slice(0, dependentCellRef.lastIndexOf(_this.calculateInstance.sheetToken) + 1); updatedInfo.sheetId = family.tokenToParentObject.has(token) ? Number(family.tokenToParentObject.get(token)) : parseInt(dependentCellRef.split('!')[1], 10) + 1; _this.updateDataContainer([_this.calculateInstance.rowIndex(dependentCellRef) - 1, _this.calculateInstance.colIndex(dependentCellRef) - 1], updatedInfo); _this.calculateInstance.refresh(fInfo.getParsedFormula()); } } token = cellRef.slice(0, cellRef.lastIndexOf(_this.calculateInstance.sheetToken) + 1); if (sheetId === (family.tokenToParentObject.has(token) ? family.tokenToParentObject.get(token) : cellRef.split('!')[1])) { _this.calculateInstance.getFormulaInfoTable().delete(cellRef); _this.calculateInstance.clearFormulaDependentCells(cellRef); } }); }); }; WorkbookFormula.prototype.renameUpdation = function (args) { var _this = this; var name = args.value; var pName = args.pName; var sheet; var cell; var uPName = args.pName.toUpperCase(); var escapeRegx = new RegExp('[!@#$%^&()+=\';,.{}|\\":<>~_-]', 'g'); var exp = '(?=[\'!])(?=[^"]*(?:"[^"]*"[^"]*)*$)'; var regExp = RegExp; var regx = new regExp(pName.replace(escapeRegx, '\\$&') + exp, 'gi'); var renameValidationSheetRef = function (validation) { if (checkIsFormula(validation.value1) && validation.value1.toUpperCase().includes(uPName) && validation.value1.match(regx)) { validation.value1 = validation.value1.replace(regx, name); } if (checkIsFormula(validation.value2) && validation.value2.toUpperCase().includes(uPName) && validation.value2.match(regx)) { validation.value2 = validation.value2.replace(regx, name); } }; this.sheetInfo.forEach(function (info, index) { sheet = getSheet(_this.parent, index); if (sheet && sheet.rows && sheet.rows.length) { for (var i = 0, rowLen = sheet.rows.length; i < rowLen; i++) { if (sheet.rows[i] && sheet.rows[i].cells) { for (var j = 0, cellsLen = sheet.rows[i].cells.length; j < cellsLen; j++) { cell = getCell(i, j, sheet, false, true); if (cell.formula && checkIsFormula(cell.formula) && cell.formula.toUpperCase().includes(uPName) && cell.formula.match(regx)) { cell.formula = cell.formula.replace(regx, name); } if (cell.validation) { renameValidationSheetRef(cell.validation); } if (cell.chart && cell.chart.length) { cell.chart.forEach(function (chart) { if (chart.range.includes('!')) { var tokenIdx = chart.range.lastIndexOf('!'); var chartSheetRef = chart.range.substring(0, tokenIdx).toUpperCase(); if (chartSheetRef.startsWith('\'') && chartSheetRef.endsWith('\'')) { chartSheetRef = chartSheetRef.slice(1, -1); } if (chartSheetRef === uPName) { chart.range = name + chart.range.substring(tokenIdx); } } }); } } } } } if (sheet && sheet.columns && sheet.columns.length) { var column = void 0; for (var i = 0, colsLen = sheet.columns.length; i < colsLen; i++) { column = sheet.columns[i]; if (column && column.validation) { renameValidationSheetRef(column.validation); } } } var definedNames = _this.parent.definedNames; for (var i = 0; i < definedNames.length; i++) { if (checkIsFormula(definedNames[i].refersTo) && definedNames[i].refersTo.includes(pName) && definedNames[i].refersTo.match(regx)) { definedNames[i].refersTo = definedNames[i].refersTo.replace(regx, name); if (definedNames[i].scope.includes(pName)) { definedNames[i].scope = name; } } } _this.calculateInstance.updateNamedRange(pName, name); if (info.visibleName === pName) { info.visibleName = name; } }); }; WorkbookFormula.prototype.updateDataContainer = function (indexes, data) { var sheet; var rowData; var colObj; for (var i = 0, len = this.parent.sheets.length; i < len; i++) { sheet = getSheet(this.parent, i); if (sheet.id === data.sheetId) { if (indexes[0] in sheet.rows) { rowData = sheet.rows[indexes[0]]; if (indexes[1] in rowData.cells) { colObj = rowData.cells[indexes[1]]; colObj.formula = data.isNamedRange ? colObj.formula : data.value; if (data.visible) { if (i === this.parent.activeSheetIndex && sheet.activeCell === getCellAddress(indexes[0], indexes[1])) { this.parent.notify(selectionComplete, {}); } } else if (this.parent.calculationMode === 'Automatic') { colObj.value = this.referenceError(); } } else { rowData.cells[indexes[1]] = colObj = {}; } } else { rowData = sheet.rows[indexes[0]] = {}; rowData[indexes[1]] = colObj = {}; } break; } } }; WorkbookFormula.prototype.parseSheetRef = function (value, addSheetQuotes) { var regx; // eslint-disable-next-line no-useless-escape var escapeRegx = new RegExp('[!@#$%^&()+=\';,.{}|\":<>~_-]', 'g'); var i = 0; var sheetInfo = this.getSheetInfo(); var sheetCount = sheetInfo.length; var temp = []; temp.length = 0; var regxTemp; var searchIdx; var idx; var valSearchIdx; var regxVisible; var exp = '(?=[\'!])(?=[^"]*(?:"[^"]*"[^"]*)*$)'; var regExp = RegExp; for (i = 0; i < sheetCount; i++) { if (sheetInfo[i].sheet !== sheetInfo[i].visibleName) { regx = new regExp(sheetInfo[i].visibleName.replace(escapeRegx, '\\$&') + exp, 'gi'); idx = i; if (value.match(regx)) { for (var j = i + 1; j < sheetCount; j++) { if (sheetInfo[j].visibleName.includes(sheetInfo[i].visibleName)) { regxTemp = new regExp(sheetInfo[j].visibleName.replace(escapeRegx, '\\$&') + exp, 'gi'); searchIdx = value.search(regxTemp); valSearchIdx = value.search(regx); if (searchIdx > -1 && (searchIdx < valSearchIdx || (searchIdx === valSearchIdx && sheetInfo[j].visibleName.length > sheetInfo[i].visibleName.length))) { regxVisible = new RegExp('Sheet', 'gi'); if (sheetInfo[j].visibleName.search(regxVisible) !== 0) { regx = regxTemp; idx = j; } } } } value = value.replace(regx, idx + '/'); temp.push(idx); } } } i = 0; var sheetRef; while (i < temp.length) { regx = new regExp(temp[i] + '/' + exp, 'gi'); sheetRef = addSheetQuotes ? '`' + sheetInfo[temp[i]].sheet + '`' : sheetInfo[temp[i]].sheet; value = value.replace(regx, sheetRef); i++; } return value; }; WorkbookFormula.prototype.registerSheet = function (sheetIndex, sheetCount) { if (sheetIndex === void 0) { sheetIndex = 0; } if (sheetCount === void 0) { sheetCount = this.parent.sheets.length; } var id; while (sheetIndex < sheetCount) { id = getSheet(this.parent, sheetIndex).id + ''; this.calculateInstance.registerGridAsSheet(id, id, this.calcID); sheetIndex++; } }; WorkbookFormula.prototype.unRegisterSheet = function (sheetIndex, sheetCount, propertyChange, isNewWorkBook) { if (sheetIndex === void 0) { sheetIndex = 0; } if (sheetCount === void 0) { sheetCount = this.parent.sheets.length; } var id; this.calculateInstance.tokenCount = 0; if (propertyChange) { this.calculateInstance.unregisterGridAsSheet(id, id, propertyChange); } else { if (isNewWorkBook) { for (var i = this.sheetInfo.length - 1; i >= 0; i--) { var visibleName = this.sheetInfo[i].visibleName; id = this.sheetInfo[i].index.toString(); this.calculateInstance.unregisterGridAsSheet(id, id); this.definedNamesDeletion(visibleName); } this.clearFormulaDependentCells({ isOpen: true }); } else { while (sheetIndex < sheetCount) { id = getSheet(this.parent, sheetIndex).id + ''; this.calculateInstance.unregisterGridAsSheet(id, id); sheetIndex++; } } } }; WorkbookFormula.prototype.getUniqueRange = function (args) { args.range = this.calculateInstance.uniqueRange; }; WorkbookFormula.prototype.removeUniquecol = function (args) { if (args && args.clearAll) { this.clearAllUniqueFormulaValue(); return; } var sheet = this.parent.getActiveSheet(); for (var i = 0; i < this.calculateInstance.uniqueRange.length; i++) { var uniqRngAddress = this.calculateInstance.uniqueRange[i].split(':')[0].split('!'); if (uniqRngAddress[0] === sheet.name && uniqRngAddress[1] === sheet.activeCell) { var range = getRangeIndexes(this.calculateInstance.uniqueRange[i]); this.calculateInstance.uniqueRange.splice(i, 1); for (var j = range[0]; j <= range[2]; j++) { for (var k = range[1]; k <= range[3]; k++) { var cell = getCell(j, k, this.parent.getActiveSheet()); cell.formula = ''; this.parent.updateCellDetails({ value: '', formula: '' }, getRangeAddress([j, k]), undefined, undefined, true); } } } } }; /** * Perform the formula calculation. * * @param {FormulaCalculateArgs} args - Specifies the formula calculation options. * @param {number} args.rowIndex - The index of the row. * @param {number} args.colIndex - The index of the column. * @param {string} args.value - The value of the cell. * @param {boolean} args.isFormula - A flag indicating whether the value is a formula. * @param {number} args.sheetIdx - The index of the sheet. * @param {boolean} args.isRefreshing - A flag indicating whether the calculation is being refreshed. * @param {boolean} [args.isDependentRefresh] - An optional flag indicating whether the refresh is dependent. * @param {boolean} [args.isRandomFormula] - An optional flag indicating whether the formula is random. * @param {boolean} [args.isDelete] - An optional flag indicating whether is from delete cells. * @param {number[]} [args.deletedRange] - An optional range array indicating the deleted cells. * @returns {void} * @private */ WorkbookFormula.prototype.refreshCalculate = function (args) { args.sheet = isNullOrUndefined(args.sheetIndex) ? this.parent.getActiveSheet() : getSheet(this.parent, args.sheetIndex); var sheetId = args.sheet.id + ''; var family = this.calculateInstance.getSheetFamilyItem(sheetId); var cellRef = getColumnHeaderText(args.colIndex + 1) + (args.rowIndex + 1); if (family.isSheetMember && !isNullOrUndefined(family.parentObjectToToken)) { cellRef = family.parentObjectToToken.get(sheetId) + cellRef; } if (args.isFormula) { this.calculateFormula(args, cellRef); } else { if (this.calculateInstance.getFormulaInfoTable().has(cellRef)) { this.calculateInstance.getFormulaInfoTable().delete(cellRef); this.calculateInstance.clearFormulaDependentCells(cellRef); } this.calculateInstance.refresh(cellRef, null, null, null, args.isDelete, args.deletedRange); if (this.parent.calculationMode === 'Automatic') { this.calculateInstance.refreshRandValues(cellRef); } } this.calculateInstance.cell = ''; args.isFormulaDependent = this.calculateInstance.getDependentCells().has(cellRef); if (args.value) { args.value = args.value.toString().split('^+').join('^').split('&+').join('&'); } }; WorkbookFormula.prototype.calculateFormula = function (args, cellRef) { var _this = this; var sheet = args.sheet; this.autoCorrectFormula(args, sheet); var value = args.value; if (args.isClipboard && value.toUpperCase().includes('UNIQUE')) { setCell(args.rowIndex, args.colIndex, sheet, { value: '' }, true); } var formula = value; value = this.parseSheetRef(value); var cellArgs = new ValueChangedArgs(args.rowIndex + 1, args.colIndex + 1, value); var usedRange = [sheet.usedRange.rowIndex, sheet.usedRange.colIndex]; this.calculateInstance.valueChanged(sheet.id.toString(), cellArgs, true, usedRange, args.isRefreshing, sheet.name, args.isRandomFormula, null, args.isDelete, args.deletedRange, args.isDependentRefresh, args.action); if (this.calculateInstance.isRandomVal === true && !args.isRandomFormula && this.parent.calculationMode === 'Automatic') { this.refreshRandomFormula(); } var updatedCell = getCell(args.rowIndex, args.colIndex, sheet); if (updatedCell && formula && !args.isDependentRefresh) { formula = formula.toUpperCase(); var formulaStr = void 0; if (formula.indexOf('=SUM(') === 0) { formulaStr = '=SUM('; } else if (formula.indexOf('=AVERAGE(') === 0) { formulaStr = '=AVERAGE('; } else if (formula.indexOf('=ROUNDDOWN(') === 0) { formulaStr = '=ROUNDDOWN('; } else if (formula.indexOf('=ROUNDUP(') === 0) { formulaStr = '=ROUNDUP('; } else if (formula.indexOf('=MOD(') === 0) { formulaStr = '=MOD('; } if (formulaStr) { formula = formula.replace(formulaStr, ''); if (formula.includes(')')) { formula = formula.slice(0, formula.lastIndexOf(')')); var fStr = void 0; var idx = void 0; while (formula.includes('(') && formula.includes(')')) { idx = formula.indexOf('('); fStr = formula.slice(idx + 1); formula = formula.slice(0, idx) + (fStr.includes(')') ? fStr.slice(fStr.indexOf(')') + 1) : fStr); } } var cellRefArr = formula.split(this.calculateInstance.getParseArgumentSeparator()); var cellRef_1; var fCell = void 0; var model = void 0; var sheetIdx = void 0; var sheetName = void 0; var index = void 0; var _loop_1 = function (idx) { cellRef_1 = cellRefArr[idx].split(':')[0]; if (cellRef_1.includes('!')) { sheetName = cellRef_1.substring(0, cellRef_1.lastIndexOf('!')).split('\'').join(''); cellRef_1 = cellRef_1.substring(cellRef_1.lastIndexOf('!') + 1); } else { sheetName = ''; } if (isCellReference(cellRef_1)) { if (sheetName) { sheetIdx = getSheetIndex(this_1.parent, sheetName); model = sheetIdx !== undefined ? getSheet(this_1.parent, sheetIdx) : sheet; } else { model = sheet; } index = getRangeIndexes(cellRef_1); fCell = getCell(index[0], index[1], model); var format_1 = getTypeFromFormat(updatedCell.format); var excludedFormats = ['Number', 'Currency', 'LongDate', 'Time']; if (fCell && fCell.format && (!updatedCell.format || (!args.fillType && (excludedFormats.every(function (fmt) { return format_1 !== fmt; }) && getTypeFromFormat(fCell.format) !== 'Number')))) { updatedCell.format = fCell.format; return "break"; } } }; var this_1 = this; for (var idx = 0; idx < cellRefArr.length; idx++) { var state_1 = _loop_1(idx); if (state_1 === "break") break; } } else { var depCells = this.calculateInstance.getDependentFormulaCells().get(cellRef); if (depCells && depCells.size && this.calculateInstance.getFormulaInfoTable().has(cellRef) && this.calculateInstance.getFormulaInfoTable().get(cellRef).getParsedFormula().lastIndexOf('q') === -1 && !updatedCell.format) { var format_2; var fCell_1; var sheetRef_1; var model_1; var sheetIdx_1; var idx_1; var family_1 = this.calculateInstance.getSheetFamilyItem(null, this.calcID); depCells.forEach(function (cellRef) { if (!format_2) { sheetRef_1 = cellRef.slice(0, cellRef.lastIndexOf('!') + 1); cellRef = cellRef.replace(sheetRef_1, ''); if (isCellReference(cellRef)) { idx_1 = getRangeIndexes(cellRef); if (family_1.tokenToParentObject.has(sheetRef_1)) { sheetIdx_1 = getSheetIndexFromId(_this.parent, Number(family_1.tokenToParentObject.get(sheetRef_1))); model_1 = sheetIdx_1 !== undefined ? getSheet(_this.parent, sheetIdx_1) : sheet; } else { model_1 = sheet; } fCell_1 = getCell(idx_1[0], idx_1[1], model_1); if (fCell_1 && fCell_1.format) { format_2 = fCell_1.format; } } } }); if (format_2) { updatedCell.format = format_2; } } } } }; WorkbookFormula.prototype.refreshRandomFormula = function () { var rowId; var colId; var refValue = ''; var referenceCollection = this.calculateInstance.randCollection; if (this.calculateInstance.randomValues.size > 1 && this.calculateInstance.randomValues.size === referenceCollection.length) { for (var i = 0; i < this.calculateInstance.randomValues.size; i++) { rowId = this.calculateInstance.rowIndex(referenceCollection[i]); colId = this.calculateInstance.colIndex(referenceCollection[i]); refValue = this.calculateInstance.randomValues.get(referenceCollection[i]); var sheetId = (parseFloat(this.calculateInstance.getSheetToken(referenceCollection[i]).split(this.calculateInstance.sheetToken).join('')) + 1).toString(); var sheet = getSheet(this.parent, getSheetIndexFromId(this.parent, Number(sheetId))); if (sheet && getCell(rowId - 1, colId - 1, sheet).formula) { var tempArgs = new ValueChangedArgs(rowId, colId, refValue); this.calculateInstance.valueChanged(sheetId, tempArgs, true, undefined, undefined, undefined, false, true); } } } }; WorkbookFormula.prototype.autoCorrectFormula = function (args, sheet) { if (!isNullOrUndefined(args.value)) { var formula = args.value; formula = this.autoCorrectCellRef({ formula: args.value }); formula = formula.toString(); if (formula.split('(').length === 2 && formula.indexOf(')') < 0) { formula += ')'; } var isEqual = void 0; if (formula.indexOf('=') === 0) { formula = formula.slice(1); isEqual = true; } var lessEq = formula.match(/</g); var greaterEq = formula.match(/>/g); var equal = formula.match(/=/g); if (lessEq) { var lessOp = ''; for (var i = 0; i < lessEq.length; i++) { lessOp = lessOp + lessEq[i]; } formula = formula.replace(lessOp, '<'); } if (greaterEq) { var greaterOp = ''; for (var j = 0; j < greaterEq.length; j++) { greaterOp = greaterOp + greaterEq[j]; } formula = formula.replace(greaterOp, '>'); } if (equal) { var equalOp = ''; for (var c = 0; c < equal.length; c++) { equalOp = equalOp + equal[c]; } formula = formula.split(equalOp).join('='); } formula = isEqual ? '=' + formula : formula; if (lessEq || greaterEq || equal) { getCell(args.rowIndex, args.colIndex, sheet).formula = formula; } args.value = formula; } }; WorkbookFormula.prototype.correctCellReference = function (cellRef) { var _this = this; var cellRefArr = cellRef.split(':'); var refArr; var sheetRefArr; var oprMatchArr; var isInvalid; var updatedRef; cellRefArr.forEach(function (cellAddr, idx) { sheetRefArr = cellAddr.split('!'); cellRef = sheetRefArr[1] || cellAddr; updatedRef = null; if (cellRef.includes('&')) { refArr = cellRef.split('&'); if (_this.calculateInstance.isCellReference(refArr[1].split('$').join(''))) { refArr[1] = _this.getUpdatedCellRef(refArr[1]); updatedRef = refArr.join('&'); } } else if (_this.calculateInstance.isCellReference(cellRef.split('$').join(''))) { updatedRef = _this.getUpdatedCellRef(cellRef); if (sheetRefArr.length > 1) { updatedRef = sheetRefArr[0] + '!' + updatedRef; } } else { oprMatchArr = cellAddr.match(/[/+\-*^><>=<=<>]+/g); if (oprMatchArr) { refArr = cellAddr.split(oprMatchArr[0]); for (var refIdx = 0; refIdx < refArr.length; refIdx++) { sheetRefArr = refArr[refIdx].split('!'); cellRef = sheetRefArr[1] || sheetRefArr[0]; if (_this.calculateInstance.isCellReference(cellRef.split('$').join(''))) { refArr[refIdx] = _this.getUpdatedCellRef(cellRef); if (sheetRefArr.length > 1) { refArr[refIdx] = sheetRefArr[0] + '!' + refArr[refIdx]; } } } updatedRef = refArr.join(oprMatchArr[0]); } } if (updatedRef && updatedRef !== cellAddr) { isInvalid = true; cellRefArr[idx] = updatedRef; } }); return { isInvalid: isInvalid, ref: cellRefArr.join(':') }; }; WorkbookFormula.prototype.autoCorrectCellRef = function (args) { var rightParens = args.formula.lastIndexOf(')'); var refCorrectObj; if (rightParens > -1 && args.formula.split(')').length === 2) { var leftParens = rightParens - 1; while (leftParens > -1 && args.formula[leftParens] !== '(') { if (args.formula[leftParens] === ')') { return args.formula; } leftParens--; } if (leftParens > -1) { var formulaArgs = args.formula.substring(leftParens + 1, rightParens); var listSeparator = this.calculateInstance.getParseArgumentSeparator(); var formulaArgsArr = formulaArgs.split(listSeparator); var isInValidRef = void 0; for (var argsIdx = 0; argsIdx < formulaArgsArr.length; argsIdx++) { refCorrectObj = this.correctCellReference(formulaArgsArr[argsIdx]); if (refCorrectObj.isInvalid) { isInValidRef = true; formulaArgsArr[argsIdx] = refCorrectObj.ref; } } if (isInValidRef) { args.formula = args.formula.split(formulaArgs).join(formulaArgsArr.join(listSeparator)); args.isInvalid = true; } } } else if (args.formula.startsWith('=') && !args.formula.includes(')')) { refCorrectObj = this.correctCellReference(args.formula.substring(1, args.formula.length)); if (refCorrectObj.isInvalid) { args.formula = '=' + refCorrectObj.ref; args.isInvalid = true; } } return args.formula; }; WorkbookFormula.prototype.getUpdatedCellRef = function (cellRef) { var orgCellRef = cellRef; cellRef = cellRef.trim(); var isAbsolute = cellRef.indexOf('$') === 0; var alphabetStartIdx = cellRef.search(/[a-zA-Z]/); var digitStartIdx = cellRef.search(/\d/); alphabetStartIdx = isAbsolute ? alphabetStartIdx - 1 : alphabetStartIdx; if ((isAbsolute ? digitStartIdx > 1 : digitStartIdx > 0) && isNumber(cellRef.substring(digitStartIdx, cellRef.length))) { return orgCellRef; } else { return cellRef.substring(alphabetStartIdx, cellRef.length) + cellRef.substring(0, alphabetStartIdx); } }; WorkbookFormula.prototype.initiateDefinedNames = function () { var definedNames = this.parent.definedNames; var i = 0; while (i < definedNames.length) { var definedname = definedNames[i]; var refersTo = this.parseSheetRef(definedname.refersTo); var range = getRangeFromAddress(refersTo); var cellRef = false; var isLink = refersTo.indexOf('http:') > -1 ? true : (refersTo.indexOf('https:') > -1 ? true : false); range = range.split('$').join(''); range = range.split('=').join(''); if (range.indexOf(':') > -1) { var rangeSplit = range.split(':'); if ((isCellReference(rangeSplit[0]) && isCellReference(rangeSplit[1])) || ((rangeSplit[0].match(/[0-9]/) && rangeSplit[1].match(/[0-9]/)) || (rangeSplit[0].toUpperCase().match(/[A-Z]/) && rangeSplit[1].toUpperCase().match(/[A-Z]/)))) { cellRef = true; } } else if (range.indexOf(':') < 0) { if (isCellReference(range)) { cellRef = true; } } if (isLink) { cellRef = false; } if (cellRef) { this.addDefinedName(definedname, true, undefined, true); } else { this.removeDefinedName(definedname.name, definedname.scope, true); i--; } i++; } }; /** * @hidden * Used to add defined name to workbook. * * @param {DefineNameModel} definedName - Define named range. * @param {boolean} isValidate - Specify the boolean value. * @param {number} index - Define named index. * @param {boolean} isEventTrigger - Specify the boolean value. * @returns {boolean} - Used to add defined name to workbook. */ WorkbookFormula.prototype.addDefinedName = function (definedName, isValidate, index, isEventTrigger) { if (index === undefined || index < -1) { index = this.parent.definedNames.length; } var isAdded = true; var sheetIdx; var name = definedName.name; if (definedName.refersTo.indexOf('!') < 0) { var sheetName = getSheetName(this.parent); sheetName = sheetName.indexOf(' ') !== -1 ? '\'' + sheetName + '\'' : sheetName; definedName.refersTo = sheetName + '!' + ((definedName.refersTo.indexOf('=') < 0) ? definedName.refersTo : definedName.refersTo.split('=')[1]); } var visibleRefersTo = definedName.refersTo; var refersTo = this.parseSheetRef(definedName.refersTo); if (definedName.scope) { sheetIdx = getSheetIndex(this.parent, definedName.scope); if (sheetIdx > -1) { name = getSheetName(this.parent, sheetIdx) + '!' + name; } } else { definedName.scope = 'Workbook'; } if (!definedName.comment) { definedName.comment = ''; } //need to extend once internal sheet value changes done. if (!isValidate && this.checkIsNameExist(definedName.name, definedName.scope)) { isAdded = false; } else { this.calculat