/* * (c) Copyright Ascensio System SIA 2010-2024 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ "use strict"; (function (window, undefined) { /* * Import * ----------------------------------------------------------------------------- */ var c_oAscInsertOptions = Asc.c_oAscInsertOptions; var c_oAscDeleteOptions = Asc.c_oAscDeleteOptions; var cElementType = AscCommonExcel.cElementType; var EDataValidationType = { None: 0, Custom: 1, Date: 2, Decimal: 3, List: 4, TextLength: 5, Time: 6, Whole: 7 }; var EDataValidationErrorStyle = { Stop: 0, Warning: 1, Information: 2 }; var EDataValidationImeMode = { NoControl: 0, Off: 1, On: 2, Disabled: 3, Hiragana: 4, FullKatakana: 5, HalfKatakana: 6, FullAlpha: 7, HalfAlpha: 8, FullHangul: 9, HalfHangul: 10 }; var EDataValidationOperator = { Between: 0, NotBetween: 1, Equal: 2, NotEqual: 3, LessThan: 4, LessThanOrEqual: 5, GreaterThan: 6, GreaterThanOrEqual: 7 }; function checkIntegerType(val) { return val && AscCommonExcel.cElementType.number === val.type; } function isNum(value) { return !isNaN(parseFloat(value)) && isFinite(value); } function CDataFormula(value) { this.text = value; this._formula = null; } CDataFormula.prototype._init = function (ws, locale, doNotBuildDependencies) { if (this._formula || this.text == null) { return; } var t = this; var formulaText = isNum(this.text) ? this.text + "" : this.text; this._formula = new AscCommonExcel.parserFormula(formulaText, this, ws); if (!locale) { AscCommonExcel.executeInR1C1Mode(false, function () { t._formula.parse(); }); } else { this._formula.parse(locale); } if (!doNotBuildDependencies) { this._formula.buildDependencies(); } }; CDataFormula.prototype.clone = function () { var res = new CDataFormula(); res.text = this.text; //this._formula = null; return res; }; CDataFormula.prototype.onFormulaEvent = function (type, eventData) { if (AscCommon.c_oNotifyParentType.ChangeFormula === type) { this.text = eventData.assemble; } }; CDataFormula.prototype.getValue = function (ws, returnRaw, local, offset) { this._init(ws, local); if (offset) { this._formula.changeOffset(offset); } var activeCell = ws.getSelection().activeCell; var res = this._formula.calculate(null, new Asc.Range(activeCell.col, activeCell.row, activeCell.col, activeCell.row)); return returnRaw ? this._formula.simplifyRefType(res) : res; }; CDataFormula.prototype.Write_ToBinary2 = function (writer) { if (null !== this.text) { writer.WriteBool(true); writer.WriteString2(this.text); } else { writer.WriteBool(false); } }; CDataFormula.prototype.Read_FromBinary2 = function (reader) { if (reader.GetBool()) { this.text = reader.GetString2(); } }; CDataFormula.prototype.asc_getValue = function () { return this.text; }; CDataFormula.prototype.asc_setValue = function (val) { this.text = val; }; CDataFormula.prototype.setOffset = function (offset) { if (this._formula) { this.text = this._formula.changeOffset(offset, null, true).assemble(true); } }; function CDataValidation() { this.ranges = null; this.allowBlank = false; this.showDropDown = false; // Excel considers this field to be a refusal to display this.showErrorMessage = false; this.showInputMessage = false; this.type = EDataValidationType.None; this.errorStyle = EDataValidationErrorStyle.Stop; this.imeMode = EDataValidationImeMode.NoControl; this.operator = EDataValidationOperator.Between; this.error = null; this.errorTitle = null; this.prompt = null; this.promptTitle = null; this.formula1 = null; this.formula2 = null; //while on open this.list = null; this.Id = AscCommon.g_oIdCounter.Get_NewId(); this._tempSelection = null; return this; } CDataValidation.prototype.Get_Id = function () { return this.Id; }; CDataValidation.prototype.getObjectType = function () { return AscDFH.historyitem_type_DataValidation; }; CDataValidation.prototype.getType = function () { return AscCommonExcel.UndoRedoDataTypes.DataValidationInner; }; CDataValidation.prototype._init = function (ws, doNotBuildDependencies) { //list convert to formula if (this.list) { if (!this.formula1 && !this.formula2) { this.formula1 = this.list; } this.list = null; } if (this.formula1) { this.formula1._init(ws, null, doNotBuildDependencies); } if (this.formula2) { this.formula2._init(ws, null, doNotBuildDependencies); } }; CDataValidation.prototype._buildDependencies = function (ws, doNotBuildDependencies) { if (this.formula1 && this.formula1._formula) { this.formula1._formula.buildDependencies(); } if (this.formula2 && this.formula2._formula) { this.formula2._formula.buildDependencies(); } }; CDataValidation.prototype.clone = function (needSaveId) { var res = new CDataValidation(); if (this.ranges) { res.ranges = []; for (var i = 0; i < this.ranges.length; ++i) { res.ranges.push(this.ranges[i].clone()); } } res.allowBlank = this.allowBlank; res.showDropDown = this.showDropDown; res.showErrorMessage = this.showErrorMessage; res.showInputMessage = this.showInputMessage; res.type = this.type; res.errorStyle = this.errorStyle; res.imeMode = this.imeMode; res.operator = this.operator; res.error = this.error; res.errorTitle = this.errorTitle; res.prompt = this.prompt; res.promptTitle = this.promptTitle; res.formula1 = this.formula1 ? this.formula1.clone() : null; res.formula2 = this.formula2 ? this.formula2.clone() : null; if (needSaveId) { res.Id = this.Id; } return res; }; CDataValidation.prototype.set = function (val, ws) { this.allowBlank = this.checkProperty(this.allowBlank, val.allowBlank, AscCH.historyitem_DataValidation_AllowBlank, ws); this.showDropDown = this.checkProperty(this.showDropDown, val.showDropDown, AscCH.historyitem_DataValidation_ShowDropDown, ws); this.showErrorMessage = this.checkProperty(this.showErrorMessage, val.showErrorMessage, AscCH.historyitem_DataValidation_ShowErrorMessage, ws); this.showInputMessage = this.checkProperty(this.showInputMessage, val.showInputMessage, AscCH.historyitem_DataValidation_ShowInputMessage, ws); this.type = this.checkProperty(this.type, val.type, AscCH.historyitem_DataValidation_Type, ws); this.errorStyle = this.checkProperty(this.errorStyle, val.errorStyle, AscCH.historyitem_DataValidation_ErrorStyle, ws); this.imeMode = this.checkProperty(this.imeMode, val.imeMode, AscCH.historyitem_DataValidation_ImeMode, ws); this.operator = this.checkProperty(this.operator, val.operator, AscCH.historyitem_DataValidation_Operator, ws); this.error = this.checkProperty(this.error, val.error, AscCH.historyitem_DataValidation_Error, ws); this.errorTitle = this.checkProperty(this.errorTitle, val.errorTitle, AscCH.historyitem_DataValidation_ErrorTitle, ws); this.prompt = this.checkProperty(this.prompt, val.prompt, AscCH.historyitem_DataValidation_Prompt, ws); this.promptTitle = this.checkProperty(this.promptTitle, val.promptTitle, AscCH.historyitem_DataValidation_PromptTotle, ws); this.formula1 = this.checkProperty(this.formula1, val.formula1, AscCH.historyitem_DataValidation_Formula1, ws); this.formula2 = this.checkProperty(this.formula2, val.formula2, AscCH.historyitem_DataValidation_Formula2, ws); }; CDataValidation.prototype.checkProperty = function (propOld, propNew, type, ws) { var isFormulaType = type === AscCH.historyitem_DataValidation_Formula1 || type === AscCH.historyitem_DataValidation_Formula12; var _propOld = isFormulaType ? propOld && propOld.text : propOld; var _propNew = isFormulaType ? propNew && propNew.text : propNew; if (_propOld !== _propNew && undefined !== _propNew) { History.Add(AscCommonExcel.g_oUndoRedoSlicer, type, ws.getId(), null, new AscCommonExcel.UndoRedoData_DataValidation(this.Id, _propOld, _propNew)); return propNew; } return propOld; }; CDataValidation.prototype.isEqual = function (obj) { var errorEqual = obj.error === this.error && this.errorStyle === obj.errorStyle && this.showErrorMessage === obj.showErrorMessage; var compareFormulas = function (_f1, _f2) { if (_f1 === _f2) { return true; } else if (_f1 && _f2 && _f1.text === _f2.text) { return true; } return false; }; if (errorEqual) { if (obj.allowBlank === this.allowBlank && obj.showDropDown === this.showDropDown && obj.showInputMessage === this.showInputMessage) { if (obj.type === this.type && obj.imeMode === this.imeMode && obj.operator === this.operator && obj.prompt === this.prompt) { if (obj.promptTitle === this.promptTitle && compareFormulas(obj.formula1, this.formula1) && compareFormulas(obj.formula2, this.formula2)) { return true; } } } } return false; }; CDataValidation.prototype.setOffset = function (offset) { if (this.formula1) { this.formula1.setOffset(offset); } if (this.formula2) { this.formula2.setOffset(offset); } }; CDataValidation.prototype.Write_ToBinary2 = function (writer) { //for wrapper //writer.WriteLong(this.getObjectType()); if (null != this.ranges) { writer.WriteBool(true); writer.WriteLong(this.ranges.length); for (var i = 0; i < this.ranges.length; i++) { writer.WriteLong(this.ranges[i].r1); writer.WriteLong(this.ranges[i].c1); writer.WriteLong(this.ranges[i].r2); writer.WriteLong(this.ranges[i].c2); } } else { writer.WriteBool(false); } writer.WriteBool(this.allowBlank); writer.WriteBool(this.showDropDown); writer.WriteBool(this.showErrorMessage); writer.WriteBool(this.showInputMessage); writer.WriteLong(this.type); writer.WriteLong(this.errorStyle); writer.WriteLong(this.imeMode); writer.WriteLong(this.operator); if (null != this.error) { writer.WriteBool(true); writer.WriteString2(this.error); } else { writer.WriteBool(false); } if (null != this.errorTitle) { writer.WriteBool(true); writer.WriteString2(this.errorTitle); } else { writer.WriteBool(false); } if (null != this.prompt) { writer.WriteBool(true); writer.WriteString2(this.prompt); } else { writer.WriteBool(false); } if (null != this.promptTitle) { writer.WriteBool(true); writer.WriteString2(this.promptTitle); } else { writer.WriteBool(false); } if (null != this.formula1) { writer.WriteBool(true); this.formula1.Write_ToBinary2(writer); } else { writer.WriteBool(false); } if (null != this.formula2) { writer.WriteBool(true); this.formula2.Write_ToBinary2(writer); } else { writer.WriteBool(false); } }; CDataValidation.prototype.Read_FromBinary2 = function (reader) { if (reader.GetBool()) { var length = reader.GetULong(); for (var i = 0; i < length; ++i) { if (!this.ranges) { this.ranges = []; } var r1 = reader.GetLong(); var c1 = reader.GetLong(); var r2 = reader.GetLong(); var c2 = reader.GetLong(); this.ranges.push(new Asc.Range(c1, r1, c2, r2)); } } this.allowBlank = reader.GetBool(); this.showDropDown = reader.GetBool(); this.showErrorMessage = reader.GetBool(); this.showInputMessage = reader.GetBool(); this.type = reader.GetLong(); this.errorStyle = reader.GetLong(); this.imeMode = reader.GetLong(); this.operator = reader.GetLong(); if (reader.GetBool()) { this.error = reader.GetString2(); } if (reader.GetBool()) { this.errorTitle = reader.GetString2(); } if (reader.GetBool()) { this.prompt = reader.GetString2(); } if (reader.GetBool()) { this.promptTitle = reader.GetString2(); } var obj; if (reader.GetBool()) { obj = new CDataFormula(); obj.Read_FromBinary2(reader); this.formula1 = obj; } if (reader.GetBool()) { obj = new CDataFormula(); obj.Read_FromBinary2(reader); this.formula2 = obj; } }; CDataValidation.prototype.setSqRef = function (sqRef) { this.ranges = AscCommonExcel.g_oRangeCache.getRangesFromSqRef(sqRef); }; CDataValidation.prototype.contains = function (c, r) { if (this.ranges) { for (var i = 0; i < this.ranges.length; ++i) { if (this.ranges[i].contains(c, r)) { return true; } } } return false; }; CDataValidation.prototype.containsRange = function (range) { if (this.ranges) { for (var i = 0; i < this.ranges.length; ++i) { if (this.ranges[i].containsRange(range)) { return true; } } } return false; }; CDataValidation.prototype.intersection = function (range) { if (this.ranges) { for (var i = 0; i < this.ranges.length; ++i) { if (this.ranges[i].intersection(range)) { return true; } } } return false; }; CDataValidation.prototype.getIntersections = function (range, offset) { var res = []; if (this.ranges) { for (var i = 0; i < this.ranges.length; ++i) { var intersection = this.ranges[i].intersection(range); if (intersection) { if (offset) { intersection.setOffset(offset); } res.push(intersection); } } } return res.length ? res : null; }; CDataValidation.prototype.checkValue = function (cell, ws) { if (!this.showErrorMessage || EDataValidationType.None === this.type) { return true; } let cleanFormulaCaches = function () { AscCommonExcel.g_oLOOKUPCache.clean(); AscCommonExcel.g_oVLOOKUPCache.clean(); AscCommonExcel.g_oHLOOKUPCache.clean(); AscCommonExcel.g_oMatchCache.clean(); AscCommonExcel.g_oSUMIFSCache.clean(); AscCommonExcel.g_oFormulaRangesCache.clean(); AscCommonExcel.g_oCountIfCache.clean(); }; let cellType = cell.getType(); let val = cell.getValueWithoutFormat(); if (EDataValidationType.List === this.type) { let list = this._getListValues(ws); let aValue = list[0]; if (!aValue) { return false; } let aData = list[1]; if (aData) { for (let i = 0; i < aData.length; ++i) { if (aData[i].isEqualCell(cell)) { return true; } } } else { return -1 !== aValue.indexOf(val); } } else if (EDataValidationType.Custom === this.type) { cleanFormulaCaches(); let v = this.formula1 && this.formula1.clone().getValue(ws, true, null, this.calculateOffset(ws)); v = v && v.tocBool(); return !!(v && AscCommonExcel.cElementType.bool === v.type && v.toBool()); } else { if (EDataValidationType.TextLength === this.type) { val = val.length; } else { if (AscCommon.CellValueType.Number !== cellType) { return false; } val = Number(val); if (isNaN(val) || (EDataValidationType.Whole === this.type && (val >> 0) !== val)) { return false; } } cleanFormulaCaches(); let v1 = this.formula1 && this.formula1.getValue(ws, true); let v2 = this.formula2 && this.formula2.getValue(ws, true); let res = false; if (v1 == null && v2 == null) { switch (this.type) { case EDataValidationType.None: case EDataValidationType.Date: case EDataValidationType.Decimal: case EDataValidationType.TextLength: case EDataValidationType.Time: case EDataValidationType.Whole: res = true; break; } return res; } if (!checkIntegerType(v1)) { return false; } v1 = v1.toNumber(); switch (this.operator) { case EDataValidationOperator.Between: res = checkIntegerType(v2) && v1 <= val && val <= v2.toNumber(); break; case EDataValidationOperator.NotBetween: res = checkIntegerType(v2) && !(v1 <= val && val <= v2.toNumber()); break; case EDataValidationOperator.Equal: res = v1 === val; break; case EDataValidationOperator.NotEqual: res = v1 !== val; break; case EDataValidationOperator.LessThan: res = v1 > val; break; case EDataValidationOperator.LessThanOrEqual: res = v1 >= val; break; case EDataValidationOperator.GreaterThan: res = v1 < val; break; case EDataValidationOperator.GreaterThanOrEqual: res = v1 <= val; break; } return res; } return false; }; CDataValidation.prototype._getListValues = function (ws) { var aValue, aData; var f = this.formula1; var offset; if (f && f._formula) { //если формула содержит ссылки на диапазоны, то в зависимости от активной области нужно их сдвинуть offset = this.calculateOffset(ws); if (offset) { f = f.clone(); } } var list = f && f.getValue(ws, false, null, offset); if (list && AscCommonExcel.cElementType.error !== list.type) { if (AscCommonExcel.cElementType.string === list.type) { aValue = list.getValue().split(AscCommon.FormulaSeparators.functionArgumentSeparatorDef); if (aValue && aValue.length) { for (var i = 0; i < aValue.length; i++) { //обрезаем только вначале строки if (aValue[i] && aValue[i].length) { var pos = 0; while ((pos < aValue[i].length) && (aValue[i][pos] == ' ')) { ++pos; } aValue[i] = pos ? aValue[i].substr(pos) : aValue[i]; } } } } else if (AscCommonExcel.cElementType.array === list.type) { let seenValues = {}; aValue = []; list.foreach(function (elem) { let _val = elem.getValue && elem.getValue(); if (_val != null && !seenValues[_val]) { aValue.push(_val); seenValues[_val] = true; } }); } else { list = list.getRange && list.getRange(); if (list) { aValue = []; aData = []; let duplicatedMap = []; list._foreachNoEmpty(function (cell) { if (!cell.isNullTextString()) { let val = cell.getValue(); if (!duplicatedMap[val]) { aValue.push(val); aData.push(new AscCommonExcel.CCellValue(cell)); duplicatedMap[val] = 1; } } }); } } } return [aValue, aData]; }; CDataValidation.prototype.isListValues = function () { return (this.type === EDataValidationType.List && !this.showDropDown); }; CDataValidation.prototype.getListValues = function (ws) { return this.isListValues() ? this._getListValues(ws) : null; }; CDataValidation.prototype.asc_checkValid = function () { var res = Asc.c_oAscError.ID.No; var _getNumber = function (_text) { var _val = null; if (!isNum(_text)) { var date = AscCommon.g_oFormatParser.parseDate(_text, AscCommon.g_oDefaultCultureInfo); if (date) { _val = date.value; } } else { _val = parseFloat(_text); } return _val; }; if (this.type !== EDataValidationType.Custom && this.type !== EDataValidationType.List) { if (this.operator === EDataValidationOperator.Between || this.operator === EDataValidationOperator.NotBetween) { if (this.formula1 && this.formula2) { var nFormula1 = _getNumber(this.formula1.text); var nFormula2 = _getNumber(this.formula2.text); if (nFormula1 !== null && nFormula2 !== null && nFormula2 < nFormula1) { return Asc.c_oAscError.ID.DataValidateMinGreaterMax; } } } } return res; }; CDataValidation.prototype.isValidDataRef = function (ws, _val, type) { var _checkValidType = function (val) { var _res = false; if (val.type === cElementType.cell || val.type === cElementType.cell3D) { _res = true; } else if (type === EDataValidationType.List) { if (val.type === cElementType.cellsRange || val.type === cElementType.cellsRange3D) { _res = true; } } else if (val.type === cElementType.number) { _res = true; } return _res; }; var checkDefNames = function (_f) { var outStack = _f._formula.outStack; if (outStack && outStack.length) { for (var i = 0; i < outStack.length; i++) { if (outStack[i].type === cElementType.name && outStack[i].Calculate().type === cElementType.error) { return false; } } } return true; }; var _checkFormulaOnError = function (fValue, _f) { //ошибка по именованному диапазону if (fValue.type === cElementType.error && fValue.errorType === AscCommonExcel.cErrorType.wrong_name && !checkDefNames(_f)) { return asc_error.NamedRangeNotFound; } //если ссылка на диапазон - в любом случае отдаём ошибку if (fValue.type === cElementType.cellsRange || fValue.type === cElementType.cellsRange3D) { //в случае списка допустимы строки/столбцы if (type === EDataValidationType.List) { var _bbox = fValue.getBBox0(); if (_bbox.c1 !== _bbox.c2 && _bbox.r1 !== _bbox.r2) { return asc_error.DataValidateInvalidList; } } else { return asc_error.DataValidateInvalid; } } if (fValue.type === cElementType.array) { //в ms другой текст ошибки, мы выдаём общий return asc_error.DataValidateInvalid; } if (type !== EDataValidationType.Custom && !_checkValidType(fValue)) { return type === EDataValidationType.List ? asc_error.DataValidateInvalidList : asc_error.DataValidateNotNumeric; } //если ощибка в подсчете формулы - выдаём предупреждение if (fValue.type === cElementType.error) { return asc_error.FormulaEvaluateError; } return null; }; var asc_error = Asc.c_oAscError.ID; var formula, fResult, isNumeric, date; if (_val[0] === "=") { formula = new CDataFormula(_val.slice(1)); fResult = formula.getValue(ws, null, true); var formulaError = _checkFormulaOnError(fResult, formula); if (formulaError !== null) { return formulaError; } } else { isNumeric = isNum(_val); if (!isNumeric) { //проверим, может быть это дата или время if (type !== EDataValidationType.List) { date = AscCommon.g_oFormatParser.parseDate(_val, AscCommon.g_oDefaultCultureInfo); } } } var res = asc_error.No; switch (type) { case EDataValidationType.Date: if (fResult) { } else { if (!isNumeric) { if (date) { _val = date.value; } else { return asc_error.DataValidateInvalid; } } //TODO не нашёл константу на максимальную дату var maxDate = 2958465; if (isNumeric && (_val < 0 || _val > maxDate)) { return asc_error.DataValidateInvalid; } } break; case EDataValidationType.Decimal: case EDataValidationType.Whole: if (fResult) { } else { if (!isNumeric) { if (date) { _val = date.value; } else { return asc_error.DataValidateInvalid; } } } break; case EDataValidationType.List: if (fResult) { } else { } break; case EDataValidationType.TextLength: if (fResult) { } else { if (!isNumeric) { if (date) { _val = date.value; } else { return asc_error.DataValidateNotNumeric; } } if (_val >= 10000000000 || _val < 0) { return asc_error.DataValidateNegativeTextLength; } } break; case EDataValidationType.Time: if (fResult) { } else { if (!isNumeric) { if (date) { _val = date.value; } else { return asc_error.DataValidateInvalid; } } if (_val < 0 || _val >= 1) { return asc_error.DataValidateInvalid; } } break; } return res; }; CDataValidation.prototype.getError = function () { return this.error; }; CDataValidation.prototype.getErrorStyle = function () { return this.errorStyle; }; CDataValidation.prototype.getErrorTitle = function () { return this.errorTitle; }; CDataValidation.prototype.getAllowBlank = function () { return this.allowBlank; }; CDataValidation.prototype.getShowDropDown = function () { return this.showDropDown; }; CDataValidation.prototype.getShowErrorMessage = function () { return this.showErrorMessage; }; CDataValidation.prototype.getShowInputMessage = function () { return this.showInputMessage; }; CDataValidation.prototype.asc_getType = function () { return this.type; }; CDataValidation.prototype.getImeMode = function () { return this.imeMode; }; CDataValidation.prototype.getOperator = function () { return this.operator; }; CDataValidation.prototype.getPrompt = function () { return this.prompt; }; CDataValidation.prototype.getPromptTitle = function () { return this.promptTitle; }; CDataValidation.prototype.getFormula1 = function () { return this.formula1; }; CDataValidation.prototype.getFormula2 = function () { return this.formula2; }; CDataValidation.prototype.setAllowBlank = function (newVal, addToHistory) { this.allowBlank = newVal; }; CDataValidation.prototype.setShowDropDown = function (newVal, addToHistory) { this.showDropDown = newVal; }; CDataValidation.prototype.setShowErrorMessage = function (newVal, addToHistory) { this.showErrorMessage = newVal; }; CDataValidation.prototype.setShowInputMessage = function (newVal, addToHistory) { this.showInputMessage = newVal; }; CDataValidation.prototype.setType = function (newVal, addToHistory) { this.type = newVal; }; CDataValidation.prototype.setErrorStyle = function (newVal, addToHistory) { this.errorStyle = newVal; }; CDataValidation.prototype.setImeMode = function (newVal, addToHistory) { this.imeMode = newVal; }; CDataValidation.prototype.setOperator = function (newVal, addToHistory) { this.operator = newVal; }; CDataValidation.prototype.setError = function (newVal, addToHistory) { this.error = newVal; }; CDataValidation.prototype.setErrorTitle = function (newVal, addToHistory) { this.errorTitle = newVal; }; CDataValidation.prototype.setPrompt = function (newVal, addToHistory) { this.prompt = newVal; }; CDataValidation.prototype.setPromptTitle = function (newVal, addToHistory) { this.promptTitle = newVal; }; CDataValidation.prototype.setFormula1 = function (newVal, addToHistory) { this.formula1 = newVal; }; CDataValidation.prototype.setFormula2 = function (newVal, addToHistory) { this.formula2 = newVal; }; CDataValidation.prototype.shift = function (bInsert, type, updateRange) { var _setDiff = function (_range) { var _newRanges, offset, tempRange, intersection, otherPart, diff; switch (type) { case c_oAscInsertOptions.InsertCellsAndShiftDown: tempRange = new Asc.Range(updateRange.c1, updateRange.r1, updateRange.c2, AscCommon.gc_nMaxRow0); intersection = tempRange.intersection(_range); if (intersection) { diff = updateRange.r2 - updateRange.r1 + 1; _newRanges = []; //добавляем сдвинутую часть диапазона _newRanges.push(intersection); offset = new AscCommon.CellBase(bInsert ? diff : -diff, 0); otherPart = _newRanges[0].difference(_range); _newRanges[0].setOffset(offset); //исключаем сдвинутую часть из диапазона _newRanges = _newRanges.concat(otherPart); } break; case c_oAscInsertOptions.InsertCellsAndShiftRight: tempRange = new Asc.Range(updateRange.c1, updateRange.r1, AscCommon.gc_nMaxCol0, updateRange.r2); intersection = tempRange.intersection(_range); if (intersection) { diff = updateRange.c2 - updateRange.c1 + 1; _newRanges = []; //добавляем сдвинутую часть диапазона _newRanges.push(intersection); offset = new AscCommon.CellBase(0, bInsert ? diff : -diff, 0); otherPart = _newRanges[0].difference(_range); _newRanges[0].setOffset(offset); //исключаем сдвинутую часть из диапазона _newRanges = _newRanges.concat(otherPart); } break; } return _newRanges; }; var _offset; if (type === c_oAscInsertOptions.InsertCellsAndShiftDown || type === c_oAscInsertOptions.InsertRows) { _offset = new AscCommon.CellBase(updateRange.r2 - updateRange.r1 + 1, 0); if (!bInsert) { _offset.row = -_offset.row; } } else { _offset = new AscCommon.CellBase(0, updateRange.c2 - updateRange.c1 + 1); if (!bInsert) { _offset.col = -_offset.col; } } var newRanges = []; var bDel, isChanged; //TODO правлю ошибку. 50521 - попытаться понять, как получился такой файл. if (!this.ranges) { return -1; } for (var i = 0; i < this.ranges.length; i++) { if (!bInsert && updateRange.containsRange(this.ranges[i])) { bDel = true; } else { if (updateRange.isIntersectForShift(this.ranges[i], _offset)) { var cloneRange = this.ranges[i].clone(); cloneRange.forShift(updateRange, _offset); newRanges.push(cloneRange); isChanged = true; } else { var changedRanges = _setDiff(this.ranges[i]); if (changedRanges) { newRanges = newRanges.concat(changedRanges); isChanged = true; } else { newRanges = newRanges.concat(this.ranges[i].clone()); } } } } if (!newRanges.length && bDel) { //удаляем return -1; } else if (newRanges.length && isChanged) { //меняем диапазон return newRanges; } }; CDataValidation.prototype.clear = function (ranges) { if (!this.ranges) { return null; } var newRanges = []; var isChanged; for (var i = 0; i < this.ranges.length; i++) { for (var j = 0; j < ranges.length; j++) { var intersection = this.ranges[i].intersection(ranges[j]); if (intersection) { isChanged = true; newRanges = newRanges.concat(intersection.difference(this.ranges[i])); } else { newRanges.push(this.ranges[i]); } } } return isChanged ? newRanges : null; }; CDataValidation.prototype.move = function (oBBoxFrom, copyRange, offset) { if (!this.ranges) { return null; } var newRanges = []; var isChanged; for (var i = 0; i < this.ranges.length; i++) { var intersection = this.ranges[i].intersection(oBBoxFrom); if (intersection) { isChanged = true; if (!copyRange) { newRanges = newRanges.concat(intersection.difference(this.ranges[i])); } else { newRanges.push(this.ranges[i]); } intersection.setOffset(offset); newRanges.push(intersection); } else { newRanges.push(this.ranges[i]); } } return isChanged ? newRanges : null; }; CDataValidation.prototype.prepeareToPaste = function (range, offset) { if (!this.ranges) { return false; } var newRanges = []; for (var j = 0; j < this.ranges.length; j++) { var intersection = range.intersection(this.ranges[j]); if (intersection) { intersection.setOffset(offset); newRanges.push(intersection); } } if (newRanges.length) { this.ranges = newRanges; return true; } return false; }; CDataValidation.prototype.applyCollaborative = function (nSheetId, collaborativeEditing) { }; CDataValidation.prototype.correctToInterface = function (ws) { var t = this; var doCorrect = function (_formula) { var _val = _formula.text; //если формула var _isNum = isNum(_val); if (_val[0] === '"' || _isNum) { if (!_isNum) { _val = _formula.text = _val.slice(1, -1); _isNum = isNum(_val); if (!_isNum) { _val = _formula.text = _val.replace(/\"\"/g, "\""); } } if (_isNum) { //переводим в дату var _format; if (t.type === EDataValidationType.Date) { _format = AscCommon.oNumFormatCache.get("m/d/yyyy"); } else if (t.type === EDataValidationType.Time) { _format = AscCommon.oNumFormatCache.get("h:mm:ss AM/PM"); } if (_format) { var dateVal = _format.format(_val); if (dateVal && dateVal[0] && dateVal[0].text) { _formula.text = dateVal[0].text; } } } } else { if (_formula && _formula._formula) { //если формула содержит ссылки на диапазоны, то в зависимости от активной области нужно их сдвинуть var offset = t.calculateOffset(ws); if (offset) { _formula._formula.changeOffset(offset); } _formula.text = "=" + _formula._formula.assembleLocale(AscCommonExcel.cFormulaFunctionToLocale); } else { _formula.text = "=" + _val; } } }; if (this.formula1) { doCorrect(this.formula1); } if (this.formula2) { doCorrect(this.formula2); } }; CDataValidation.prototype.correctFromInterface = function (ws) { var t = this; var addQuotes = function (_val) { var _res; if (_val[0] === '"') { _res = _val.replace(/\"/g, "\"\""); _res = "\"" + _res + "\""; } else { _res = "\"" + _val + "\""; } return _res; }; var doCorrect = function (_formula) { var _val = _formula.text; var isNumeric = isNum(_val); if (isNumeric) { if (t.type === EDataValidationType.List) { _formula.text = '"' + _formula.text + '"'; } } else { var isDate; var isFormula; if (!isNumeric) { if (_val[0] === "=") { _val = _val.slice(1); _formula.text = _val; if (isNum(_val)) { if (t.type === EDataValidationType.List) { _val = '"' + _val + '"'; } _formula.text = _val; return; } var _tempFormula = new CDataFormula(_val); isFormula = _tempFormula.getValue(ws, null, true); } else if (t.type !== EDataValidationType.List) { isDate = AscCommon.g_oFormatParser.parseDate(_val, AscCommon.g_oDefaultCultureInfo); } } //храним число if (isDate) { _formula.text = isDate.value; return; } if (!isFormula) { _formula.text = addQuotes(_formula.text); } else if (_tempFormula && _tempFormula._formula) { _formula.text = _tempFormula._formula.assemble(); } } }; if (this.formula1) { doCorrect(this.formula1); } if (this.formula2) { doCorrect(this.formula2); } }; CDataValidation.prototype.checkFormulaStackOnCell = function (row, col) { var stack = this.formula1 && this.formula1._formula && this.formula1._formula.outStack; if (stack && stack.length) { for (var i = 0; i < stack.length; i++) { if (stack[i]) { if (stack[i].type === AscCommonExcel.cElementType.cell || stack[i].type === AscCommonExcel.cElementType.cellsRange) { if (stack[i].range && stack[i].range.bbox && stack[i].range.bbox.contains(col, row)) { return true; } } } } } return false; }; CDataValidation.prototype.calculateOffset = function (ws) { if (!this.ranges) { return null; } var res = null; //находим левый верхний угол var _row = null, _col = null; for (var i = 0; i < this.ranges.length; i++) { if (_row === null && _col === null) { _row = this.ranges[i].r1; _col = this.ranges[i].c1; } else if (_row > this.ranges[i].r1) { _row = this.ranges[i].r1; } else if (_col > this.ranges[i].c1) { _col = this.ranges[i].c1; } } if (_row !== null && _col !== null) { var selectionRange = ws.getSelection(); var activeCell = selectionRange.activeCell; res = new AscCommon.CellBase(activeCell.row - _row, activeCell.col - _col); } return res; }; function CDataValidations() { this.disablePrompts = false; this.xWindow = null; this.yWindow = null; this.elems = []; return this; } CDataValidations.prototype.init = function (ws) { for (var i = 0; i < this.elems.length; ++i) { this.elems[i]._init(ws); } }; CDataValidations.prototype.clone = function () { var i, res = new CDataValidations(); res.disablePrompts = this.disablePrompts; res.xWindow = this.xWindow; res.yWindow = this.yWindow; for (i = 0; i < this.elems.length; ++i) { res.elems.push(this.elems[i].clone()); } return res; }; CDataValidations.prototype.shift = function (ws, bInsert, type, updateRange, addToHistory) { for (var i = 0; i < this.elems.length; i++) { var isUpdate = this.elems[i].shift(bInsert, type, updateRange); if (isUpdate === -1) { if (this.delete(ws, this.elems[i].Id, addToHistory)) { i--; } } else if (isUpdate) { var to = this.elems[i].clone(); to.ranges = isUpdate; this.change(ws, this.elems[i], to, addToHistory); } } }; CDataValidations.prototype.add = function (ws, val, addToHistory) { this.elems.push(val); if (addToHistory) { History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_DataValidationAdd, ws.getId(), null, new AscCommonExcel.UndoRedoData_DataValidation(val.Id, null, val)); } }; CDataValidations.prototype.change = function (ws, from, to, addToHistory) { if (!to || !to.ranges || !to.ranges.length) { return; } to.Id = from.Id; for (var i = 0; i < this.elems.length; i++) { if (this.elems[i].Id === to.Id) { this.elems[i] = to; } } if (addToHistory) { History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_DataValidationChange, ws.getId(), null, new AscCommonExcel.UndoRedoData_DataValidation(from.Id, from, to)); } }; CDataValidations.prototype.delete = function (ws, id, addToHistory) { var deleteElem; for (var i = 0; i < this.elems.length; i++) { if (this.elems[i].Id === id) { deleteElem = this.elems[i]; this.elems.splice(i, 1); } } if (addToHistory && deleteElem) { History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_DataValidationDelete, ws.getId(), null, new AscCommonExcel.UndoRedoData_DataValidation(deleteElem.Id, deleteElem, null)); } return deleteElem; }; CDataValidations.prototype.getById = function (id) { for (var i = 0; i < this.elems.length; i++) { if (this.elems[i].Id === id) { return {data: this.elems[i], index: i}; } } }; CDataValidations.prototype.getIntersections = function (ranges) { //выделяем несколько групп //первая - если вся активная область находится в пределах одного dataValidation //вторая - если пересекаемся с dataValidation var checkAdd = function (arr, obj) { for (var n = 0; n < arr.length; n++) { if (arr[n].isEqual(obj)) { return true; } } return false; }; var intersectionArr = []; var containArr = []; if (this.elems) { for (var i = 0; i < this.elems.length; i++) { var dataValidation = this.elems[i]; for (var j = 0; j < ranges.length; j++) { if (dataValidation.intersection(ranges[j])) { if (dataValidation.containsRange(ranges[j])) { if (!checkAdd(dataValidation, containArr)) { containArr.push(dataValidation); } } else { if (!checkAdd(dataValidation, intersectionArr)) { intersectionArr.push(dataValidation); } } } } } } return {intersection: intersectionArr, contain: containArr}; }; CDataValidations.prototype.getProps = function (ranges, doExtend, ws) { var _obj = this.getIntersections(ranges); var dataValidationIntersection = _obj.intersection; var dataValidationContain = _obj.contain; var needCheck = doExtend === undefined; if (needCheck) { //если выделено несколько диапазонов с data validation if (dataValidationIntersection.length > 1 || dataValidationContain.length > 1) { return c_oAscError.ID.MoreOneTypeDataValidate; } //если в выделение попали диапазоны как с data validation так и без if (dataValidationIntersection.length) { return c_oAscError.ID.ContainsCellsWithoutDataValidate; } } var getNewObject = function () { var _res = new window['AscCommonExcel'].CDataValidation(); _res.showErrorMessage = true; _res.showInputMessage = true; _res.allowBlank = true; return _res; }; //для передачи в интерфейс использую объект и модели - CDataValidation //если doExtend = null -> значит erase === true var res; if (doExtend === null) { res = getNewObject(); } else if (doExtend !== undefined) { res = doExtend ? dataValidationIntersection[0].clone(true) : getNewObject(); } else if (dataValidationContain.length === 1) { res = dataValidationContain[0].clone(true); } else { //возвращаем новый объект с опциями res = getNewObject(); } res._init(ws); res.correctToInterface(ws); return res; }; CDataValidations.prototype.setProps = function (ws, ranges, props) { var _obj = this.getIntersections(ranges); var instersection = _obj.intersection; var contain = _obj.contain; var prepeareAdd = function (_props, modelRanges) { var _dataValidation = _props.clone(); var _ranges = []; var needRanges = modelRanges ? modelRanges : ranges; for (var i = 0; i < needRanges.length; i++) { _ranges.push(needRanges[i].clone()); } _dataValidation.ranges = _ranges; _dataValidation._init(ws); return _dataValidation; }; props.Id = AscCommon.g_oIdCounter.Get_NewId(); props.correctFromInterface(ws); var equalRangeDataValidation; var equalDataValidation; var i; if (this.elems) { for (i = 0; i < this.elems.length; i++) { if (this._isPartOfRanges(this.elems[i].ranges, ranges)) { if (!equalRangeDataValidation) { equalRangeDataValidation = []; } equalRangeDataValidation.push(this.elems[i]); } //пока не усложняем логику и не объединяем объекты с одинаковыми настройками /*if (props.isEqual(this.dataValidations.elems[i])) { equalDataValidation = this.dataValidations.elems[i]; break; }*/ } } if (!instersection.length && !contain.length) { //самый простой вариант - просто добавляем новый обхект и привязываем его к активной области if (equalDataValidation) { //в данном случае расширяем диапазон //set } else { this.add(ws, prepeareAdd(props), true); } } else if (equalRangeDataValidation) { for (i = 0; i < equalRangeDataValidation.length; i++) { this.change(ws, equalRangeDataValidation[i], prepeareAdd(props, equalRangeDataValidation[i].ranges), true); } } else { var t = this; var _split = function (_dataValidation) { var _newRanges = []; var dataValidationRanges = _dataValidation.ranges; for (var i = 0; i < dataValidationRanges.length; i++) { var tempRanges = []; for (var j = 0; j < ranges.length; j++) { if (tempRanges.length) { var tempRanges2 = []; for (var k = 0; k < tempRanges.length; k++) { tempRanges2 = tempRanges2.concat(ranges[j].difference(tempRanges[k])); } tempRanges = tempRanges2; } else { tempRanges = ranges[j].difference(dataValidationRanges[i]); } } _newRanges = _newRanges.concat(tempRanges); } if (!_newRanges.length) { t.delete(ws, _dataValidation.Id, true) } else { var newDataValidation = _dataValidation.clone(); newDataValidation.ranges = _newRanges; t.change(ws, _dataValidation, prepeareAdd(newDataValidation, _newRanges), true); } }; var k; for (k = 0; k < instersection.length; k++) { _split(instersection[k]); } for (k = 0; k < contain.length; k++) { _split(contain[k]); } //разбиваем диапазон объектов, с которыми пересекаемся + добавляем новый this.add(ws, prepeareAdd(props), true); } }; CDataValidations.prototype._isPartOfRanges = function (_ranges1, _ranges2) { if (_ranges1 && _ranges2 && _ranges1.length <= _ranges2.length) { for (var j = 0; j < _ranges1.length; j++) { var _equal = false; for (var n = 0; n < _ranges2.length; n++) { if (_ranges1[j].isEqual(_ranges2[n])) { _equal = true; break; } } if (!_equal) { return false; } } } else { return false; } return true; }; CDataValidations.prototype._containRanges = function (_ranges1, _ranges2) { //проверка на то, что диапазон второго range входит в дипапазон первого var res = false; if (_ranges1 && _ranges2 && _ranges1.length && _ranges2.length) { for (var j = 0; j < _ranges1.length; j++) { //проверяем, вошёл ли целиком массив диапазонов второго в один из первых if (_ranges1[j].containsRanges(_ranges2)) { res = true; break; } } } else { res = false; } return res; }; CDataValidations.prototype.clear = function (ws, ranges, addToHistory) { for (var i = 0; i < this.elems.length; i++) { var isEmptyRanges = !this.elems[i].ranges || !this.elems[i].ranges.length; if (isEmptyRanges || this._containRanges(ranges, this.elems[i].ranges)) { if (this.delete(ws, this.elems[i].Id, addToHistory)) { i--; } } else { var changedRanges = this.elems[i].clear(ranges); if (changedRanges) { if (!changedRanges.length) { if (this.delete(ws, this.elems[i].Id, addToHistory)) { i--; } } else { var newDataValidation = this.elems[i].clone(); newDataValidation.ranges = changedRanges; this.change(ws, this.elems[i], newDataValidation, addToHistory); } } } } }; CDataValidations.prototype.move = function (ws, oBBoxFrom, oBBoxTo, copyRange, offset) { for (var i = 0; i < this.elems.length; i++) { var changedRanges = this.elems[i].move(oBBoxFrom, copyRange, offset); if (changedRanges) { var newDataValidation = this.elems[i].clone(); newDataValidation.ranges = changedRanges; this.change(ws, this.elems[i], newDataValidation, true); } } }; CDataValidations.prototype.getCopyByRange = function (range, offset) { var res = []; for (var i = 0; i < this.elems.length; i++) { var changedRanges = this.elems[i].getIntersections(range, offset); if (changedRanges) { var newDataValidation = this.elems[i].clone(); newDataValidation.ranges = changedRanges; res.push(newDataValidation); } } return res.length ? res : null; }; CDataValidations.prototype.getIntersectionByRange = function (range) { var res = []; for (var i = 0; i < this.elems.length; i++) { var changedRanges = this.elems[i].getIntersections(range); if (changedRanges) { res.push({ranges: changedRanges, id: this.elems[i].Id}); } } return res.length ? res : null; }; CDataValidations.prototype.expandRanges = function (ranges) { var res = []; var _notExpandRanges = []; for (var k = 0; k < ranges.length; k++) { res[k] = ranges[k]; for (var i = 0; i < this.elems.length; i++) { var _expandRange = res[k]; var isIntersection = false; var tempArr = []; for (var j = 0; j < this.elems[i].ranges.length; j++) { if (this.elems[i].ranges[j].intersection(_expandRange)) { isIntersection = true; _expandRange = _expandRange.union(this.elems[i].ranges[j]); } else { tempArr.push(this.elems[i].ranges[j]); } } if (isIntersection) { _notExpandRanges = _notExpandRanges.concat(tempArr); res[k] = _expandRange; } } } return res.concat(_notExpandRanges); }; CDataValidations.prototype.getSameSettingsElems = function (_elem) { var res = null; if (!_elem) { return res; } for (var i = 0; i < this.elems.length; i++) { if (this.elems[i].isEqual(_elem)) { if (!res) { res = []; } res.push(this.elems[i]); } } return res; }; /* * Export * ----------------------------------------------------------------------------- */ var prot; window['Asc'] = window['Asc'] || {}; window['Asc']['c_oAscEDataValidationType'] = window['Asc'].EDataValidationType = EDataValidationType; prot = EDataValidationType; prot['None'] = prot.None; prot['Custom'] = prot.Custom; prot['Date'] = prot.Date; prot['Decimal'] = prot.Decimal; prot['List'] = prot.List; prot['TextLength'] = prot.TextLength; prot['Time'] = prot.Time; prot['Whole'] = prot.Whole; window['Asc']['c_oAscEDataValidationErrorStyle'] = window['Asc'].EDataValidationErrorStyle = EDataValidationErrorStyle; prot = EDataValidationErrorStyle; prot['Stop'] = prot.Stop; prot['Warning'] = prot.Warning; prot['Information'] = prot.Information; window['Asc'].EDataValidationImeMode = EDataValidationImeMode; window['Asc']['CDataFormula'] = window['Asc'].CDataFormula = CDataFormula; prot = CDataFormula.prototype; prot['asc_getValue'] = prot.asc_getValue; prot['asc_setValue'] = prot.asc_setValue; window['AscCommonExcel'] = window['AscCommonExcel'] || {}; window['AscCommonExcel'].CDataValidation = CDataValidation; prot = CDataValidation.prototype; prot['asc_getError'] = prot.getError; prot['asc_getErrorStyle'] = prot.getErrorStyle; prot['asc_getErrorTitle'] = prot.getErrorTitle; prot['asc_getErrorTitle'] = prot.getErrorTitle; prot['asc_getAllowBlank'] = prot.getAllowBlank; prot['asc_getShowDropDown'] = prot.getShowDropDown; prot['asc_getShowErrorMessage'] = prot.getShowErrorMessage; prot['asc_getShowInputMessage'] = prot.getShowInputMessage; prot['asc_getType'] = prot.asc_getType; //prot['asc_getImeMode'] = prot.getImeMode; prot['asc_getOperator'] = prot.getOperator; prot['asc_getPrompt'] = prot.getPrompt; prot['asc_getPromptTitle'] = prot.getPromptTitle; prot['asc_getFormula1'] = prot.getFormula1; prot['asc_getFormula2'] = prot.getFormula2; prot['asc_setError'] = prot.setError; prot['asc_setErrorStyle'] = prot.setErrorStyle; prot['asc_setErrorTitle'] = prot.setErrorTitle; prot['asc_setErrorTitle'] = prot.setErrorTitle; prot['asc_setAllowBlank'] = prot.setAllowBlank; prot['asc_setShowDropDown'] = prot.setShowDropDown; prot['asc_setShowErrorMessage'] = prot.setShowErrorMessage; prot['asc_setShowInputMessage'] = prot.setShowInputMessage; prot['asc_setType'] = prot.setType; //prot['asc_setImeMode'] = prot.setImeMode; prot['asc_setOperator'] = prot.setOperator; prot['asc_setPrompt'] = prot.setPrompt; prot['asc_setPromptTitle'] = prot.setPromptTitle; prot['asc_setFormula1'] = prot.setFormula1; prot['asc_setFormula2'] = prot.setFormula2; prot['asc_checkValid'] = prot.asc_checkValid; window['Asc']['EDataValidationOperator'] = window['Asc'].EDataValidationOperator = EDataValidationOperator; prot = EDataValidationOperator; prot['Between'] = prot.Between; prot['NotBetween'] = prot.NotBetween; prot['Equal'] = prot.Equal; prot['NotEqual'] = prot.NotEqual; prot['LessThan'] = prot.LessThan; prot['LessThanOrEqual'] = prot.LessThanOrEqual; prot['GreaterThan'] = prot.GreaterThan; prot['GreaterThanOrEqual'] = prot.GreaterThanOrEqual; window['AscCommonExcel'].CDataValidations = CDataValidations; })(window);