24632 lines
839 KiB
JavaScript
24632 lines
839 KiB
JavaScript
/*
|
|
* (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 g_memory = AscFonts.g_memory;
|
|
|
|
var CellValueType = AscCommon.CellValueType;
|
|
var c_oAscBorderStyles = Asc.c_oAscBorderStyles;
|
|
var fSortAscending = AscCommon.fSortAscending;
|
|
var parserHelp = AscCommon.parserHelp;
|
|
var oNumFormatCache = AscCommon.oNumFormatCache;
|
|
var gc_nMaxRow0 = AscCommon.gc_nMaxRow0;
|
|
var gc_nMaxCol0 = AscCommon.gc_nMaxCol0;
|
|
var g_oCellAddressUtils = AscCommon.g_oCellAddressUtils;
|
|
var CellAddress = AscCommon.CellAddress;
|
|
var isRealObject = AscCommon.isRealObject;
|
|
var cBoolLocal = AscCommon.cBoolLocal;
|
|
var cErrorLocal = AscCommon.cErrorLocal;
|
|
var cErrorOrigin = AscCommon.cErrorOrigin;
|
|
var c_oAscNumFormatType = Asc.c_oAscNumFormatType;
|
|
var oSeriesInType = Asc.c_oAscSeriesInType;
|
|
var oSeriesType = Asc.c_oAscSeriesType;
|
|
var oSeriesDateUnitType = Asc.c_oAscDateUnitType;
|
|
var oFillType = Asc.c_oAscFillType;
|
|
|
|
|
|
var UndoRedoItemSerializable = AscCommonExcel.UndoRedoItemSerializable;
|
|
var UndoRedoData_CellSimpleData = AscCommonExcel.UndoRedoData_CellSimpleData;
|
|
var UndoRedoData_CellValueData = AscCommonExcel.UndoRedoData_CellValueData;
|
|
var UndoRedoData_FromToRowCol = AscCommonExcel.UndoRedoData_FromToRowCol;
|
|
var UndoRedoData_FromTo = AscCommonExcel.UndoRedoData_FromTo;
|
|
var UndoRedoData_IndexSimpleProp = AscCommonExcel.UndoRedoData_IndexSimpleProp;
|
|
var UndoRedoData_BBox = AscCommonExcel.UndoRedoData_BBox;
|
|
var UndoRedoData_SheetAdd = AscCommonExcel.UndoRedoData_SheetAdd;
|
|
var UndoRedoData_DefinedNames = AscCommonExcel.UndoRedoData_DefinedNames;
|
|
var g_oDefaultFormat = AscCommonExcel.g_oDefaultFormat;
|
|
var g_StyleCache = AscCommonExcel.g_StyleCache;
|
|
var Border = AscCommonExcel.Border;
|
|
var RangeDataManager = AscCommonExcel.RangeDataManager;
|
|
|
|
var cElementType = AscCommonExcel.cElementType;
|
|
|
|
var parserFormula = AscCommonExcel.parserFormula;
|
|
|
|
var c_oAscError = Asc.c_oAscError;
|
|
var c_oAscInsertOptions = Asc.c_oAscInsertOptions;
|
|
var c_oAscDeleteOptions = Asc.c_oAscDeleteOptions;
|
|
var c_oAscGetDefinedNamesList = Asc.c_oAscGetDefinedNamesList;
|
|
var c_oAscDefinedNameReason = Asc.c_oAscDefinedNameReason;
|
|
var c_oNotifyType = AscCommon.c_oNotifyType;
|
|
var g_cCalcRecursion = AscCommonExcel.g_cCalcRecursion;
|
|
|
|
var cError = AscCommonExcel.cError;
|
|
var cErrorType = AscCommonExcel.cErrorType;
|
|
|
|
var g_nVerticalTextAngle = 255;
|
|
//определяется в WorksheetView.js
|
|
var oDefaultMetrics = {
|
|
ColWidthChars: 0,
|
|
RowHeight: 0
|
|
};
|
|
var g_sNewSheetNamePattern = "Sheet";
|
|
var g_nSheetNameMaxLength = 31;
|
|
var g_nDefNameMaxLength = 255;
|
|
var g_nAllColIndex = -1;
|
|
var g_nAllRowIndex = -1;
|
|
var aStandartNumFormats = [];
|
|
var aStandartNumFormatsId = {};
|
|
var oFormulaLocaleInfo = {
|
|
Parse: true,
|
|
DigitSep: true
|
|
};
|
|
|
|
(function(){
|
|
aStandartNumFormats[0] = "General";
|
|
aStandartNumFormats[1] = "0";
|
|
aStandartNumFormats[2] = "0.00";
|
|
aStandartNumFormats[3] = "#,##0";
|
|
aStandartNumFormats[4] = "#,##0.00";
|
|
aStandartNumFormats[9] = "0%";
|
|
aStandartNumFormats[10] = "0.00%";
|
|
aStandartNumFormats[11] = "0.00E+00";
|
|
aStandartNumFormats[12] = "# ?/?";
|
|
aStandartNumFormats[13] = "# ??/??";
|
|
aStandartNumFormats[14] = "m/d/yyyy";
|
|
aStandartNumFormats[15] = "d-mmm-yy";
|
|
aStandartNumFormats[16] = "d-mmm";
|
|
aStandartNumFormats[17] = "mmm-yy";
|
|
aStandartNumFormats[18] = "h:mm AM/PM";
|
|
aStandartNumFormats[19] = "h:mm:ss AM/PM";
|
|
aStandartNumFormats[20] = "h:mm";
|
|
aStandartNumFormats[21] = "h:mm:ss";
|
|
aStandartNumFormats[22] = "m/d/yyyy h:mm";
|
|
aStandartNumFormats[37] = "#,##0_);(#,##0)";
|
|
aStandartNumFormats[38] = "#,##0_);[Red](#,##0)";
|
|
aStandartNumFormats[39] = "#,##0.00_);(#,##0.00)";
|
|
aStandartNumFormats[40] = "#,##0.00_);[Red](#,##0.00)";
|
|
aStandartNumFormats[45] = "mm:ss";
|
|
aStandartNumFormats[46] = "[h]:mm:ss";
|
|
aStandartNumFormats[47] = "mm:ss.0";
|
|
aStandartNumFormats[48] = "##0.0E+0";
|
|
aStandartNumFormats[49] = "@";
|
|
for(var i in aStandartNumFormats)
|
|
{
|
|
aStandartNumFormatsId[aStandartNumFormats[i]] = i - 0;
|
|
}
|
|
})();
|
|
|
|
var c_oRangeType =
|
|
{
|
|
Range:0,
|
|
Col:1,
|
|
Row:2,
|
|
All:3
|
|
};
|
|
var c_oSharedShiftType = {
|
|
Processed: 1,
|
|
NeedTransform: 2,
|
|
PreProcessed: 3
|
|
};
|
|
|
|
|
|
|
|
var emptyStyleComponents = {table: [], conditional: []};
|
|
function getRangeType(oBBox){
|
|
if(null == oBBox)
|
|
oBBox = this.bbox;
|
|
if(oBBox.c1 == 0 && gc_nMaxCol0 == oBBox.c2 && oBBox.r1 == 0 && gc_nMaxRow0 == oBBox.r2)
|
|
return c_oRangeType.All;
|
|
if(oBBox.c1 == 0 && gc_nMaxCol0 == oBBox.c2)
|
|
return c_oRangeType.Row;
|
|
else if(oBBox.r1 == 0 && gc_nMaxRow0 == oBBox.r2)
|
|
return c_oRangeType.Col;
|
|
else
|
|
return c_oRangeType.Range;
|
|
}
|
|
|
|
function getCompiledStyleFromArray(xf, xfs, isTableBorders) {
|
|
for (var i = 0; i < xfs.length; ++i) {
|
|
if (null == xf) {
|
|
xf = xfs[i];
|
|
} else {
|
|
xf = xf.merge(xfs[i], undefined, isTableBorders);
|
|
}
|
|
}
|
|
return xf;
|
|
}
|
|
function getCompiledStyle(sheetMergedStyles, hiddenManager, nRow, nCol, opt_cell, opt_ws, opt_styleComponents, opt_AffectingText) {
|
|
var styleComponents = opt_styleComponents ? opt_styleComponents : sheetMergedStyles.getStyle(hiddenManager, nRow, nCol, opt_ws, opt_AffectingText);
|
|
var xf = getCompiledStyleFromArray(null, styleComponents.table, true);
|
|
if (opt_cell) {
|
|
if (null === xf) {
|
|
xf = opt_cell.xfs;
|
|
} else if (opt_cell.xfs) {
|
|
xf = xf.merge(opt_cell.xfs, true);
|
|
}
|
|
} else if (opt_ws) {
|
|
opt_ws._getRowNoEmpty(nRow, function(row){
|
|
if(row && null != row.xfs){
|
|
xf = null === xf ? row.xfs : xf.merge(row.xfs, true);
|
|
} else {
|
|
var col = opt_ws._getColNoEmptyWithAll(nCol);
|
|
if(null != col && null != col.xfs){
|
|
xf = null === xf ? col.xfs : xf.merge(col.xfs, true);
|
|
}
|
|
}
|
|
});
|
|
|
|
}
|
|
xf = getCompiledStyleFromArray(xf, styleComponents.conditional);
|
|
return xf;
|
|
}
|
|
|
|
function getDefNameIndex(name) {
|
|
//uniqueness is checked without capitalization
|
|
return name ? name.toLowerCase() : name;
|
|
}
|
|
|
|
function getDefNameId(sheetId, name) {
|
|
if (sheetId) {
|
|
return sheetId + AscCommon.g_cCharDelimiter + getDefNameIndex(name);
|
|
} else {
|
|
return getDefNameIndex(name);
|
|
}
|
|
}
|
|
|
|
var g_FDNI = {sheetId: null, name: null};
|
|
|
|
function getFromDefNameId(nodeId) {
|
|
var index = nodeId ? nodeId.indexOf(AscCommon.g_cCharDelimiter) : -1;
|
|
if (-1 != index) {
|
|
g_FDNI.sheetId = nodeId.substring(0, index);
|
|
g_FDNI.name = nodeId.substring(index + 1);
|
|
} else {
|
|
g_FDNI.sheetId = null;
|
|
g_FDNI.name = nodeId;
|
|
}
|
|
}
|
|
|
|
function changeTextCase(fragments, type, opt_start, opt_end) {
|
|
if (!fragments) {
|
|
return;
|
|
}
|
|
|
|
let isChange = false;
|
|
let newText = "", fragmentsMap;
|
|
let c_oType = Asc.c_oAscChangeTextCaseType;
|
|
|
|
let getChangedTextSimpleCase = function (_text, _text_pos) {
|
|
if (!_text) {
|
|
return _text;
|
|
}
|
|
|
|
let _newText = "";
|
|
let _textBefore = "";
|
|
let _textAfter = "";
|
|
if (opt_start || opt_end) {
|
|
if (_text_pos + _text.length < opt_start || _text_pos > opt_end) {
|
|
return _text;
|
|
}
|
|
let _start = null, _end = null;
|
|
if (_text_pos < opt_start) {
|
|
_textBefore = _text.substring(0, opt_start - _text_pos);
|
|
_start = opt_start - _text_pos;
|
|
}
|
|
if (_text_pos + _text.length > opt_end) {
|
|
_textAfter = _text.substring(opt_end - _text_pos, _text.length);
|
|
_end = opt_end - _text_pos;
|
|
}
|
|
if (_start || _end) {
|
|
_text = _text.substring(_start ? _start : 0, _end ? _end : _text.length);
|
|
}
|
|
|
|
}
|
|
switch (type) {
|
|
case c_oType.LowerCase: {
|
|
_newText = _text.toLowerCase();
|
|
break;
|
|
}
|
|
case c_oType.UpperCase: {
|
|
_newText = _text.toUpperCase();
|
|
break;
|
|
}
|
|
case c_oType.ToggleCase: {
|
|
for (let i = 0, length = _text.length; i < length; ++i) {
|
|
if (_text[i].toUpperCase() === _text[i]) {
|
|
_newText += _text[i].toLowerCase();
|
|
} else {
|
|
_newText += _text[i].toUpperCase();
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
return _textBefore + _newText + _textAfter;
|
|
};
|
|
|
|
if (type === c_oType.LowerCase || type === c_oType.UpperCase || type === c_oType.ToggleCase) {
|
|
let curTextLength = 0;
|
|
for (let m = 0; m < fragments.length; m++) {
|
|
let newFragmentText = getChangedTextSimpleCase(fragments[m].text, curTextLength);
|
|
if (newFragmentText !== fragments[m].text) {
|
|
isChange = true;
|
|
if (fragments[m].setText) {
|
|
fragments[m].setText(newFragmentText);
|
|
} else if (fragments[m].setFragmentText) {
|
|
if (!fragmentsMap) {
|
|
fragmentsMap = {};
|
|
}
|
|
fragmentsMap[m] = fragments[m].clone();
|
|
fragmentsMap[m].setFragmentText(newFragmentText);
|
|
}
|
|
}
|
|
newText += newFragmentText;
|
|
curTextLength += fragments[m].text.length;
|
|
}
|
|
} else {
|
|
|
|
let getParagraphs = function (_fragments) {
|
|
let res = [];
|
|
|
|
AscFormat.ExecuteNoHistory(function () {
|
|
let oCurPar = null;
|
|
let oCurRun = null;
|
|
|
|
let _setSelection = function (_run, pos) {
|
|
if (!_run || !_run.Content) {
|
|
return;
|
|
}
|
|
let startRun = pos;
|
|
let run_length = _run.Content.length;
|
|
let endRun = pos + run_length;
|
|
if (opt_start <= startRun && endRun <= opt_end) {
|
|
//select all
|
|
_run.State.Selection.StartPos = 0;
|
|
_run.State.Selection.EndPos = run_length;
|
|
_run.State.Selection.Use = true;
|
|
} else if (endRun > opt_start && startRun < opt_end) {
|
|
_run.State.Selection.StartPos = opt_start > startRun ? (opt_start - startRun) : 0;
|
|
_run.State.Selection.EndPos = (endRun > opt_end) ? (opt_end - curTextLength) : run_length;
|
|
_run.State.Selection.Use = true;
|
|
}
|
|
};
|
|
|
|
let pushParagraph = function () {
|
|
if (!oCurPar || !oCurRun) {
|
|
return;
|
|
}
|
|
|
|
oCurPar.Internal_Content_Add(0, oCurRun, false);
|
|
|
|
if (opt_start || opt_end) {
|
|
_setSelection(oCurRun, curTextLength);
|
|
} else {
|
|
oCurPar.SelectAll();
|
|
}
|
|
|
|
curTextLength += oCurRun.Content.length;
|
|
|
|
res.push(oCurPar);
|
|
oCurPar = null;
|
|
oCurRun = null;
|
|
};
|
|
|
|
let curTextLength = 0;
|
|
for (let m = 0; m < _fragments.length; m++) {
|
|
let curMultiText = _fragments[m].text;
|
|
for (let k = 0, length = curMultiText.length; k < length; k++) {
|
|
if (oCurPar === null) {
|
|
oCurPar = new AscWord.Paragraph();
|
|
oCurRun = new ParaRun(oCurPar);
|
|
}
|
|
|
|
let nCharCode = curMultiText.charCodeAt(k);
|
|
if (curMultiText[k] === "\n") {
|
|
pushParagraph();
|
|
curTextLength++;
|
|
continue;
|
|
}
|
|
|
|
let nUnicode = null;
|
|
if (AscCommon.isLeadingSurrogateChar(nCharCode)) {
|
|
if (k + 1 < length) {
|
|
k++;
|
|
let nTrailingChar = curMultiText.charCodeAt(k);
|
|
nUnicode = AscCommon.decodeSurrogateChar(nCharCode, nTrailingChar);
|
|
}
|
|
} else {
|
|
nUnicode = nCharCode;
|
|
}
|
|
|
|
if (null != nUnicode) {
|
|
let Item;
|
|
if (0x20 !== nUnicode && 0xA0 !== nUnicode && 0x2009 !== nUnicode) {
|
|
Item = new AscWord.CRunText(nUnicode);
|
|
} else {
|
|
Item = new AscWord.CRunSpace();
|
|
}
|
|
//add text
|
|
oCurRun.Add_ToContent(-1, Item, false);
|
|
}
|
|
}
|
|
}
|
|
if (oCurPar) {
|
|
pushParagraph();
|
|
}
|
|
|
|
}, this, []);
|
|
|
|
return res;
|
|
};
|
|
|
|
let aParagraphs = getParagraphs(fragments);
|
|
if (aParagraphs && aParagraphs.length) {
|
|
let oChangeEngine = new AscCommonWord.CChangeTextCaseEngine(type);
|
|
oChangeEngine.ProcessParagraphs(aParagraphs);
|
|
|
|
for (let i = 0; i < aParagraphs.length; i++) {
|
|
newText += aParagraphs[i].GetText({ParaSeparator : ""});
|
|
if (i !== aParagraphs.length - 1) {
|
|
newText += "\n";
|
|
}
|
|
}
|
|
|
|
if (newText) {
|
|
let counter = 0;
|
|
for (let m = 0; m < fragments.length; m++) {
|
|
let curMultiText = fragments[m].text;
|
|
let isChangeFragment = false;
|
|
let newFragmentText = "";
|
|
for (let k = 0, length = curMultiText.length; k < length; k++) {
|
|
if (curMultiText[k] !== newText[counter]) {
|
|
isChange = true;
|
|
isChangeFragment = true;
|
|
}
|
|
newFragmentText += newText[counter];
|
|
counter++;
|
|
}
|
|
if (isChangeFragment) {
|
|
if (fragments[m].setText) {
|
|
//cell value
|
|
fragments[m].setText(newFragmentText);
|
|
} else if (fragments[m].setFragmentText) {
|
|
//cell editor
|
|
if (!fragmentsMap) {
|
|
fragmentsMap = {};
|
|
}
|
|
fragmentsMap[m] = fragments[m].clone();
|
|
fragmentsMap[m].setFragmentText(newFragmentText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return isChange ? {text: newText, fragmentsMap: fragmentsMap} : null;
|
|
}
|
|
|
|
function DefName(wb, name, ref, sheetId, hidden, type, isXLNM) {
|
|
this.wb = wb;
|
|
this.name = name;
|
|
this.ref = ref;
|
|
this.sheetId = sheetId;
|
|
this.hidden = hidden;
|
|
this.type = type;
|
|
|
|
this.isXLNM = isXLNM;
|
|
|
|
this.isLock = null;
|
|
this.parsedRef = null;
|
|
}
|
|
|
|
DefName.prototype = {
|
|
clone: function(wb){
|
|
return new DefName(wb, this.name, this.ref, this.sheetId, this.hidden, this.type, this.isXLNM);
|
|
},
|
|
removeDependencies: function() {
|
|
if (this.parsedRef) {
|
|
this.parsedRef.removeDependencies();
|
|
this.parsedRef = null;
|
|
}
|
|
},
|
|
setRef: function(ref, opt_noRemoveDependencies, opt_forceBuild, opt_open) {
|
|
if(!opt_noRemoveDependencies){
|
|
this.removeDependencies();
|
|
}
|
|
//для R1C1: ref - всегда строка в виде A1B1
|
|
//флаг opt_open - на открытие, undo/redo, принятие изменений - строка приходит в виде A1B1 - преобразовывать не нужно
|
|
//во всех остальных случаях парсим ref и заменяем на формат A1B1
|
|
opt_open = opt_open || this.wb.bRedoChanges || this.wb.bUndoChanges;
|
|
|
|
this.ref = ref;
|
|
//all ref should be 3d, so worksheet can be anyone
|
|
this.parsedRef = new AscCommonExcel.parserFormula(ref, this, AscCommonExcel.g_DefNameWorksheet);
|
|
this.parsedRef.setIsTable(this.type);
|
|
var t = this;
|
|
if (opt_forceBuild) {
|
|
if(opt_open) {
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
t.parsedRef.parse();
|
|
});
|
|
} else {
|
|
this.parsedRef.parse();
|
|
}
|
|
this.parsedRef.buildDependencies();
|
|
} else {
|
|
if(!opt_open) {
|
|
this.parsedRef.parse();
|
|
this.ref = this.parsedRef.assemble();
|
|
}
|
|
this.wb.dependencyFormulas.addToBuildDependencyDefName(this);
|
|
}
|
|
},
|
|
getRef: function(bLocale) {
|
|
//R1C1 - отдаём в зависимости от флага bLocale(для меню в виде R1C1)
|
|
var res, t = this;
|
|
if(!this.parsedRef.isParsed) {
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
t.parsedRef.parse();
|
|
});
|
|
}
|
|
if(bLocale) {
|
|
res = this.parsedRef.assembleLocale(AscCommonExcel.cFormulaFunctionToLocale, true);
|
|
} else {
|
|
res = this.parsedRef.assemble();
|
|
}
|
|
return res;
|
|
},
|
|
getNodeId: function() {
|
|
return getDefNameId(this.sheetId, this.name);
|
|
},
|
|
getAscCDefName: function(bLocale) {
|
|
var index = null;
|
|
if (this.sheetId) {
|
|
var sheet = this.wb.getWorksheetById(this.sheetId);
|
|
index = sheet.getIndex();
|
|
}
|
|
//теперь тип используется ещё и при получении результата вычисления именованного диапазона
|
|
//так же заполняю при отркытии
|
|
//TODO - проверить, возможно необходимо убрать
|
|
if (!this.type && this.wb && this.wb.getSlicerCacheByName(this.name)) {
|
|
this.type = Asc.c_oAscDefNameType.slicer;
|
|
}
|
|
return new Asc.asc_CDefName(this.name, this.getRef(bLocale), index, this.type, this.hidden, this.isLock, this.isXLNM);
|
|
},
|
|
getUndoDefName: function() {
|
|
return new UndoRedoData_DefinedNames(this.name, this.ref, this.sheetId, this.type, this.isXLNM, this.hidden);
|
|
},
|
|
setUndoDefName: function(newUndoName, doNotChangeRef) {
|
|
this.name = newUndoName.name;
|
|
this.sheetId = newUndoName.sheetId;
|
|
this.hidden = newUndoName.hidden;
|
|
this.type = newUndoName.type;
|
|
if (!doNotChangeRef && this.ref != newUndoName.ref) {
|
|
this.setRef(newUndoName.ref);
|
|
}
|
|
this.isXLNM = newUndoName.isXLNM;
|
|
},
|
|
onFormulaEvent: function (type, eventData) {
|
|
if (AscCommon.c_oNotifyParentType.IsDefName === type) {
|
|
return null;
|
|
} else if (AscCommon.c_oNotifyParentType.Change === type) {
|
|
this.wb.dependencyFormulas.addToChangedDefName(this);
|
|
} else if (AscCommon.c_oNotifyParentType.ChangeFormula === type) {
|
|
var notifyType = eventData.notifyData.type;
|
|
if (!(this.type === Asc.c_oAscDefNameType.table && (c_oNotifyType.Shift === notifyType || c_oNotifyType.Move === notifyType || c_oNotifyType.Delete === notifyType))) {
|
|
var oldUndoName = this.getUndoDefName();
|
|
this.parsedRef.setFormulaString(this.ref = eventData.assemble);
|
|
this.wb.dependencyFormulas.addToChangedDefName(this);
|
|
var newUndoName = this.getUndoDefName();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_DefinedNamesChangeUndo,
|
|
null, null, new UndoRedoData_FromTo(oldUndoName, newUndoName), true);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
function getCellIndex(row, col) {
|
|
return row * AscCommon.gc_nMaxCol + col;
|
|
}
|
|
|
|
var g_FCI = {row: null, col: null};
|
|
|
|
function getFromCellIndex(cellIndex, returnDuplicate) {
|
|
g_FCI.row = Math.floor(cellIndex / AscCommon.gc_nMaxCol);
|
|
g_FCI.col = cellIndex % AscCommon.gc_nMaxCol;
|
|
return returnDuplicate ? {row: g_FCI.row, col: g_FCI.col} : null;
|
|
}
|
|
|
|
function getVertexIndex(bbox) {
|
|
//without $
|
|
//значения в areaMap хранятся в виде A1B1
|
|
//данная функция используется только для получения данных из areaMap
|
|
var res;
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
res = bbox.getName(AscCommonExcel.referenceType.R);
|
|
});
|
|
return res;
|
|
}
|
|
|
|
function DependencyGraph(wb) {
|
|
this.wb = wb;
|
|
//listening
|
|
this.sheetListeners = {};
|
|
this.volatileListeners = {};
|
|
this.defNameListeners = {};
|
|
this.tempGetByCells = [];
|
|
this.volatileArrays = {}; // contains all daf formulas on the sheet that could not be expanded (vm="1")
|
|
//set dirty
|
|
this.isInCalc = false;
|
|
this.changedCell = null;
|
|
this.changedCellRepeated = null;
|
|
this.changedRange = null;
|
|
this.changedRangeRepeated = null;
|
|
this.changedDefName = null;
|
|
this.changedDefNameRepeated = null;
|
|
this.changedShared = {};
|
|
this.buildCell = {};
|
|
this.buildDefName = {};
|
|
this.buildShared = {};
|
|
this.buildArrayFormula = [];
|
|
this.buildPivot = [];
|
|
this.cleanCellCache = {};
|
|
//lock
|
|
this.lockCounter = 0;
|
|
//defined name
|
|
this.defNames = {wb: {}, sheet: {}, xlchartIndex: null};
|
|
this.tableNamePattern = "Table";
|
|
this.tableNameIndex = 0;
|
|
this.pivotNamePattern = "PivotTable";
|
|
this.pivotNameIndex = 0;
|
|
}
|
|
|
|
DependencyGraph.prototype = {
|
|
maxSharedRecursion: 50,
|
|
maxBroadcastRecursion: 1000,
|
|
//listening
|
|
startListeningRange: function(sheetId, bbox, listener) {
|
|
//todo bbox clone or bbox immutable
|
|
var listenerId = listener.getListenerId();
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (!sheetContainer) {
|
|
sheetContainer = {cellMap: {}, areaMap: {}, defName3d: {}, rangesTopFrom: null, rangesTopTo: null, rangesBottomFrom: null, rangesBottomTo: null, cells: null };
|
|
this.sheetListeners[sheetId] = sheetContainer;
|
|
}
|
|
if (bbox.isOneCell()) {
|
|
var cellIndex = getCellIndex(bbox.r1, bbox.c1);
|
|
var cellMapElem = sheetContainer.cellMap[cellIndex];
|
|
if (!cellMapElem) {
|
|
cellMapElem = {cellIndex: cellIndex, count: 0, listeners: {}};
|
|
sheetContainer.cellMap[cellIndex] = cellMapElem;
|
|
sheetContainer.cells = null;
|
|
}
|
|
if (!cellMapElem.listeners[listenerId]) {
|
|
cellMapElem.listeners[listenerId] = listener;
|
|
cellMapElem.count++;
|
|
}
|
|
} else {
|
|
var vertexIndex = getVertexIndex(bbox);
|
|
var areaSheetElem = sheetContainer.areaMap[vertexIndex];
|
|
if (!areaSheetElem) {
|
|
//todo clone inside or outside startListeningRange?
|
|
bbox = bbox.clone();
|
|
areaSheetElem = {index: 0, bbox: bbox, count: 0, listeners: {}, isActive: true};
|
|
if (true) {
|
|
areaSheetElem.sharedBroadcast = {changedBBox: null, prevChangedBBox: null, recursion: 0};
|
|
}
|
|
sheetContainer.areaMap[vertexIndex] = areaSheetElem;
|
|
sheetContainer.rangesTopFrom = null;
|
|
sheetContainer.rangesTopTo = null;
|
|
sheetContainer.rangesBottomFrom = null;
|
|
sheetContainer.rangesBottomTo = null;
|
|
}
|
|
if (!areaSheetElem.listeners[listenerId]) {
|
|
areaSheetElem.listeners[listenerId] = listener;
|
|
areaSheetElem.count++;
|
|
}
|
|
}
|
|
},
|
|
endListeningRange: function(sheetId, bbox, listener) {
|
|
var listenerId = listener.getListenerId();
|
|
if (null != listenerId) {
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
if (bbox.isOneCell()) {
|
|
var cellIndex = getCellIndex(bbox.r1, bbox.c1);
|
|
var cellMapElem = sheetContainer.cellMap[cellIndex];
|
|
if (cellMapElem && cellMapElem.listeners[listenerId]) {
|
|
delete cellMapElem.listeners[listenerId];
|
|
cellMapElem.count--;
|
|
if (cellMapElem.count <= 0) {
|
|
delete sheetContainer.cellMap[cellIndex];
|
|
sheetContainer.cells = null;
|
|
}
|
|
}
|
|
} else {
|
|
var vertexIndex = getVertexIndex(bbox);
|
|
var areaSheetElem = sheetContainer.areaMap[vertexIndex];
|
|
if (areaSheetElem && areaSheetElem.listeners[listenerId]) {
|
|
delete areaSheetElem.listeners[listenerId];
|
|
areaSheetElem.count--;
|
|
if (areaSheetElem.count <= 0) {
|
|
delete sheetContainer.areaMap[vertexIndex];
|
|
sheetContainer.rangesTopFrom = null;
|
|
sheetContainer.rangesTopTo = null;
|
|
sheetContainer.rangesBottomFrom = null;
|
|
sheetContainer.rangesBottomTo = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
startListeningVolatile: function(listener) {
|
|
var listenerId = listener.getListenerId();
|
|
this.volatileListeners[listenerId] = listener;
|
|
},
|
|
endListeningVolatile: function(listener) {
|
|
var listenerId = listener.getListenerId();
|
|
if (null != listenerId) {
|
|
delete this.volatileListeners[listenerId];
|
|
}
|
|
},
|
|
forEachSheetListeners: function(sheetId, callback) {
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
var i, j;
|
|
for (i in sheetContainer.cellMap) {
|
|
if (sheetContainer.cellMap[i]) {
|
|
for (j in sheetContainer.cellMap[i].listeners) {
|
|
callback(sheetContainer.cellMap[i].listeners[j]);
|
|
}
|
|
}
|
|
}
|
|
for (i in sheetContainer.areaMap) {
|
|
if (sheetContainer.areaMap[i]) {
|
|
for (j in sheetContainer.areaMap[i].listeners) {
|
|
callback(sheetContainer.areaMap[i].listeners[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
startListeningDefName: function(name, listener, opt_sheetId) {
|
|
var listenerId = listener.getListenerId();
|
|
var nameIndex = getDefNameIndex(name);
|
|
var container = this.defNameListeners[nameIndex];
|
|
if (!container) {
|
|
container = {count: 0, listeners: {}};
|
|
this.defNameListeners[nameIndex] = container;
|
|
}
|
|
if (!container.listeners[listenerId]) {
|
|
container.listeners[listenerId] = listener;
|
|
container.count++;
|
|
}
|
|
if(opt_sheetId){
|
|
var sheetContainer = this.sheetListeners[opt_sheetId];
|
|
if (!sheetContainer) {
|
|
sheetContainer = {cellMap: {}, areaMap: {}, defName3d: {}, rangesTopFrom: null, rangesTopTo: null, rangesBottomFrom: null, rangesBottomTo: null, cells: null };
|
|
this.sheetListeners[opt_sheetId] = sheetContainer;
|
|
}
|
|
sheetContainer.defName3d[listenerId] = listener;
|
|
}
|
|
},
|
|
isListeningDefName: function(name) {
|
|
return null != this.defNameListeners[getDefNameIndex(name)];
|
|
},
|
|
endListeningDefName: function(name, listener, opt_sheetId) {
|
|
var listenerId = listener.getListenerId();
|
|
if (null != listenerId) {
|
|
var nameIndex = getDefNameIndex(name);
|
|
var container = this.defNameListeners[nameIndex];
|
|
if (container && container.listeners[listenerId]) {
|
|
delete container.listeners[listenerId];
|
|
container.count--;
|
|
if (container.count <= 0) {
|
|
delete this.defNameListeners[nameIndex];
|
|
}
|
|
}
|
|
if(opt_sheetId){
|
|
var sheetContainer = this.sheetListeners[opt_sheetId];
|
|
if (sheetContainer) {
|
|
delete sheetContainer.defName3d[listenerId];
|
|
}
|
|
}
|
|
}
|
|
},
|
|
//shift, move
|
|
deleteNodes: function(sheetId, bbox) {
|
|
this.buildDependency();
|
|
this._shiftMoveDelete(c_oNotifyType.Delete, sheetId, bbox, null);
|
|
this.addToChangedRange(sheetId, bbox);
|
|
},
|
|
shift: function(sheetId, bbox, offset) {
|
|
this.buildDependency();
|
|
return this._shiftMoveDelete(c_oNotifyType.Shift, sheetId, bbox, offset);
|
|
},
|
|
move: function(sheetId, bboxFrom, offset, sheetIdTo, isTableCreated) {
|
|
this.buildDependency();
|
|
this._shiftMoveDelete(c_oNotifyType.Move, sheetId, bboxFrom, offset, sheetIdTo, isTableCreated);
|
|
this.addToChangedRange(sheetId, bboxFrom);
|
|
},
|
|
prepareChangeSheet: function(sheetId, data, tableNamesMap) {
|
|
this.buildDependency();
|
|
var listeners = {};
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
for (var cellIndex in sheetContainer.cellMap) {
|
|
var cellMapElem = sheetContainer.cellMap[cellIndex];
|
|
for (var listenerId in cellMapElem.listeners) {
|
|
listeners[listenerId] = cellMapElem.listeners[listenerId];
|
|
}
|
|
}
|
|
for (var vertexIndex in sheetContainer.areaMap) {
|
|
var areaSheetElem = sheetContainer.areaMap[vertexIndex];
|
|
for (var listenerId in areaSheetElem.listeners) {
|
|
listeners[listenerId] = areaSheetElem.listeners[listenerId];
|
|
}
|
|
}
|
|
for (var listenerId in sheetContainer.defName3d) {
|
|
listeners[listenerId] = sheetContainer.defName3d[listenerId];
|
|
}
|
|
}
|
|
if (this.volatileListeners) {
|
|
for (var listenerId in this.volatileListeners) {
|
|
listeners[listenerId] = this.volatileListeners[listenerId];
|
|
}
|
|
}
|
|
if(tableNamesMap){
|
|
for (var tableName in tableNamesMap) {
|
|
var nameIndex = getDefNameIndex(tableName);
|
|
var container = this.defNameListeners[nameIndex];
|
|
if (container) {
|
|
for (var listenerId in container.listeners) {
|
|
listeners[listenerId] = container.listeners[listenerId];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var notifyData = {
|
|
type: c_oNotifyType.Prepare, actionType: c_oNotifyType.ChangeSheet, data: data, transformed: {},
|
|
preparedData: {}
|
|
};
|
|
for (var listenerId in listeners) {
|
|
listeners[listenerId].notify(notifyData);
|
|
}
|
|
for (var listenerId in notifyData.transformed) {
|
|
if (notifyData.transformed.hasOwnProperty(listenerId)) {
|
|
delete listeners[listenerId];
|
|
var elems = notifyData.transformed[listenerId];
|
|
for (var i = 0; i < elems.length; ++i) {
|
|
var elem = elems[i];
|
|
listeners[elem.getListenerId()] = elem;
|
|
elem.notify(notifyData);
|
|
}
|
|
}
|
|
}
|
|
return {listeners: listeners, data: data, preparedData: notifyData.preparedData};
|
|
},
|
|
changeSheet: function(prepared) {
|
|
var notifyData = {type: c_oNotifyType.ChangeSheet, data: prepared.data, preparedData: prepared.preparedData};
|
|
for (var listenerId in prepared.listeners) {
|
|
prepared.listeners[listenerId].notify(notifyData);
|
|
}
|
|
},
|
|
changeExternalLink: function(prepared) {
|
|
var notifyData = {type: c_oNotifyType.ChangeExternalLink, data: prepared.data, preparedData: prepared.preparedData, existedWs: prepared.existedWs};
|
|
for (var listenerId in prepared.listeners) {
|
|
prepared.listeners[listenerId].notify(notifyData);
|
|
}
|
|
},
|
|
prepareRemoveSheet: function(sheetId, tableNames) {
|
|
var t = this;
|
|
//cells
|
|
var ws = this.wb.getWorksheetById(sheetId);
|
|
var formulas = [];
|
|
ws.getAllFormulas(formulas);
|
|
for (var i = 0; i < formulas.length; ++i) {
|
|
formulas[i].removeDependencies();
|
|
}
|
|
//defnames
|
|
this._foreachDefNameSheet(sheetId, function(defName){
|
|
if (!defName.type !== Asc.c_oAscDefNameType.table) {
|
|
t._removeDefName(sheetId, defName.name, AscCH.historyitem_Workbook_DefinedNamesChangeUndo);
|
|
}
|
|
});
|
|
//tables
|
|
var tableNamesMap = {};
|
|
var i;
|
|
for (i = 0; i < tableNames.length; ++i) {
|
|
var tableName = tableNames[i];
|
|
this._removeDefName(null, tableName, null);
|
|
tableNamesMap[tableName] = 1;
|
|
this.wb.deleteSlicersByTable(tableName, true);
|
|
}
|
|
//удаляю срезы, которые остались на данном листе, но привязаны к таблицам других листов
|
|
if (ws.aSlicers) {
|
|
for (i = 0; i < ws.aSlicers.length; i++) {
|
|
ws.deleteSlicer(ws.aSlicers[i].name, true);
|
|
}
|
|
}
|
|
|
|
//dependence
|
|
return this.prepareChangeSheet(sheetId, {remove: sheetId, tableNamesMap: tableNamesMap}, tableNamesMap);
|
|
},
|
|
removeSheet: function(prepared) {
|
|
this.changeSheet(prepared);
|
|
},
|
|
//lock
|
|
lockRecal: function() {
|
|
++this.lockCounter;
|
|
},
|
|
isLockRecal: function() {
|
|
return this.lockCounter > 0;
|
|
},
|
|
unlockRecal: function(notCalc, callback) {
|
|
if (0 < this.lockCounter) {
|
|
--this.lockCounter;
|
|
}
|
|
if (!notCalc && 0 >= this.lockCounter) {
|
|
this.calcTree(callback);
|
|
} else {
|
|
callback && callback();
|
|
}
|
|
},
|
|
lockRecalExecute: function(callback) {
|
|
this.lockRecal();
|
|
callback();
|
|
this.unlockRecal();
|
|
},
|
|
//defined name
|
|
getDefNameByName: function(name, sheetId, opt_exact) {
|
|
var res = null;
|
|
let nameIndex = getDefNameIndex(name);
|
|
if (sheetId) {
|
|
var sheetContainer = this.defNames.sheet[sheetId];
|
|
if (sheetContainer) {
|
|
res = sheetContainer[nameIndex];
|
|
}
|
|
}
|
|
if (!res && !(opt_exact && sheetId)) {
|
|
res = this.defNames.wb[nameIndex];
|
|
}
|
|
return res;
|
|
},
|
|
getDefNameByNodeId: function(nodeId) {
|
|
getFromDefNameId(nodeId);
|
|
return this.getDefNameByName(g_FDNI.name, g_FDNI.sheetId, true);
|
|
},
|
|
getDefNameByRef: function(ref, sheetId, bLocale) {
|
|
var getByRef = function(defName) {
|
|
if (!defName.hidden && defName.ref == ref) {
|
|
return defName.name;
|
|
}
|
|
};
|
|
var res = this._foreachDefNameSheet(sheetId, getByRef);
|
|
if(res && bLocale) {
|
|
res = AscCommon.translateManager.getValue(res);
|
|
}
|
|
if (!res) {
|
|
res = this._foreachDefNameBook(getByRef);
|
|
}
|
|
return res;
|
|
},
|
|
getDefNameByCellInside: function(col, row, sheetId, bLocale) {
|
|
var cellSheet = this.wb.getWorksheetById(sheetId);
|
|
var getByRef = function(defName) {
|
|
if (!defName.hidden) {
|
|
var defNameParseRef = defName.ref.split('!');
|
|
if (defNameParseRef) {
|
|
var sheetDefName = defNameParseRef[0];
|
|
var sRefDefName = defNameParseRef[1];
|
|
|
|
if (cellSheet && cellSheet.sName === sheetDefName) {
|
|
var refDefName = AscCommonExcel.g_oRangeCache.getAscRange(sRefDefName);
|
|
if (refDefName && refDefName.contains(col, row)) {
|
|
return defName.name;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var res = this._foreachDefNameSheet(sheetId, getByRef);
|
|
if(res && bLocale) {
|
|
res = AscCommon.translateManager.getValue(res);
|
|
}
|
|
if (!res) {
|
|
res = this._foreachDefNameBook(getByRef);
|
|
}
|
|
return res;
|
|
},
|
|
getDefinedNamesWB: function(type, bLocale, excludeErrorRefNames) {
|
|
var names = [], activeWS;
|
|
|
|
function getNames(defName) {
|
|
if (defName.ref && !defName.hidden && (defName.name.indexOf("_xlnm") < 0)) {
|
|
if (excludeErrorRefNames && defName.parsedRef && defName.parsedRef.outStack) {
|
|
var _stack = defName.parsedRef.outStack;
|
|
for (var i = 0; i < _stack.length; i++) {
|
|
if (_stack[i] && cElementType.error === _stack[i].type) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
names.push(defName.getAscCDefName(bLocale));
|
|
}
|
|
}
|
|
|
|
function sort(a, b) {
|
|
if (a.name > b.name) {
|
|
return 1;
|
|
} else if (a.name < b.name) {
|
|
return -1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
switch (type) {
|
|
case c_oAscGetDefinedNamesList.Worksheet:
|
|
case c_oAscGetDefinedNamesList.WorksheetWorkbook:
|
|
activeWS = this.wb.getActiveWs();
|
|
this._foreachDefNameSheet(activeWS.getId(), getNames);
|
|
if (c_oAscGetDefinedNamesList.WorksheetWorkbook) {
|
|
this._foreachDefNameBook(getNames);
|
|
}
|
|
break;
|
|
case c_oAscGetDefinedNamesList.All:
|
|
default:
|
|
this._foreachDefName(getNames);
|
|
break;
|
|
}
|
|
return names.sort(sort);
|
|
},
|
|
getDefinedNamesWS: function(sheetId) {
|
|
var names = [];
|
|
|
|
function getNames(defName) {
|
|
if (defName.ref) {
|
|
names.push(defName);
|
|
}
|
|
}
|
|
|
|
this._foreachDefNameSheet(sheetId, getNames);
|
|
return names;
|
|
},
|
|
addDefNameOpen: function(name, ref, sheetIndex, hidden, type) {
|
|
var sheetId = this.wb.getSheetIdByIndex(sheetIndex);
|
|
var isXLNM = null;
|
|
var XLNMName = this._checkXlnmName(name);
|
|
if(null !== XLNMName) {
|
|
name = XLNMName;
|
|
isXLNM = true;
|
|
}
|
|
|
|
var defName = new DefName(this.wb, name, ref, sheetId, hidden, type, isXLNM);
|
|
this._addDefName(defName);
|
|
return defName;
|
|
},
|
|
_checkXlnmName: function(name) {
|
|
var supportName = {"Print_Area": 1, "Print_Titles": 1};
|
|
|
|
var prefix = "_xlnm.";
|
|
var parseName = name.split(prefix)[1];
|
|
if(supportName[parseName]) {
|
|
return parseName;
|
|
}
|
|
|
|
return null;
|
|
},
|
|
addDefName: function(name, ref, sheetId, hidden, type, isXLNM) {
|
|
var defName = new DefName(this.wb, name, ref, sheetId, hidden, type, isXLNM);
|
|
defName.setRef(defName.ref, true);
|
|
this._addDefName(defName);
|
|
return defName;
|
|
},
|
|
removeDefName: function(sheetId, name) {
|
|
this._removeDefName(sheetId, name, AscCH.historyitem_Workbook_DefinedNamesChange);
|
|
if (!this.wb.bUndoChanges && !this.wb.bRedoChanges) {
|
|
this.wb.handlers && this.wb.handlers.trigger("updateCellWatches", sheetId);
|
|
}
|
|
this.wb.handlers && this.wb.handlers.trigger("onChangePageSetupProps", sheetId);
|
|
},
|
|
editDefinesNames: function(oldUndoName, newUndoName, isFromHistory) {
|
|
var res = null;
|
|
var isSlicer = oldUndoName && this.wb.getSlicerCacheByCacheName(oldUndoName.name);
|
|
|
|
if (!isFromHistory && (!AscCommon.rx_defName.test(getDefNameIndex(newUndoName.name)) || (!newUndoName.ref && !isSlicer) ||
|
|
(newUndoName.ref.length === 0 && !isSlicer) || newUndoName.name.length > g_nDefNameMaxLength)) {
|
|
return res;
|
|
}
|
|
if (oldUndoName) {
|
|
res = this.getDefNameByName(oldUndoName.name, oldUndoName.sheetId);
|
|
} else {
|
|
res = this.addDefName(newUndoName.name, newUndoName.ref, newUndoName.sheetId, newUndoName.hidden, newUndoName.type, newUndoName.isXLNM);
|
|
}
|
|
AscCommon.History.Create_NewPoint();
|
|
if (res && oldUndoName) {
|
|
if (oldUndoName.name != newUndoName.name) {
|
|
this.buildDependency();
|
|
|
|
res = this._delDefName(res.name, res.sheetId);
|
|
res.setUndoDefName(newUndoName, isSlicer);
|
|
this._addDefName(res);
|
|
|
|
var notifyData = {type: c_oNotifyType.ChangeDefName, from: oldUndoName, to: newUndoName};
|
|
this._broadcastDefName(oldUndoName.name, notifyData);
|
|
|
|
this.addToChangedDefName(res);
|
|
} else {
|
|
res.setUndoDefName(newUndoName);
|
|
}
|
|
}
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_DefinedNamesChange, null, null,
|
|
new UndoRedoData_FromTo(oldUndoName, newUndoName));
|
|
|
|
if (!this.wb.bUndoChanges && !this.wb.bRedoChanges) {
|
|
this.wb.handlers && this.wb.handlers.trigger("updateCellWatches");
|
|
}
|
|
this.wb.handlers && this.wb.handlers.trigger("onChangePageSetupProps", newUndoName.sheetId);
|
|
return res;
|
|
},
|
|
checkDefName: function (name, sheetIndex) {
|
|
var res = new Asc.asc_CCheckDefName();
|
|
var range = AscCommonExcel.g_oRangeCache.getRange3D(name) ||
|
|
AscCommonExcel.g_oRangeCache.getAscRange(name);
|
|
if(!range) {
|
|
//проверяем на совпадение с именем диапазона в другом формате
|
|
AscCommonExcel.executeInR1C1Mode(!AscCommonExcel.g_R1C1Mode, function () {
|
|
range = AscCommonExcel.g_oRangeCache.getRange3D(name) ||
|
|
AscCommonExcel.g_oRangeCache.getAscRange(name);
|
|
});
|
|
}
|
|
if (range || !AscCommon.rx_defName.test(name.toLowerCase()) || name.length > g_nDefNameMaxLength) {
|
|
res.status = false;
|
|
res.reason = c_oAscDefinedNameReason.WrongName;
|
|
return res;
|
|
}
|
|
|
|
var sheetId = this.wb.getSheetIdByIndex(sheetIndex);
|
|
var defName = this.getDefNameByName(name, sheetId, true);
|
|
if (defName) {
|
|
res.status = false;
|
|
if (defName.isLock) {
|
|
res.reason = c_oAscDefinedNameReason.IsLocked;
|
|
} else {
|
|
res.reason = c_oAscDefinedNameReason.Existed;
|
|
}
|
|
} else {
|
|
if (this.isListeningDefName(name)) {
|
|
res.status = false;
|
|
res.reason = c_oAscDefinedNameReason.NameReserved;
|
|
} else {
|
|
res.status = true;
|
|
res.reason = c_oAscDefinedNameReason.OK;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
},
|
|
copyDefNameByWorksheet: function(wsFrom, wsTo, renameParams, opt_sheet) {
|
|
var sheetContainerFrom;
|
|
var opt_df = opt_sheet && opt_sheet.workbook && opt_sheet.workbook.dependencyFormulas ? opt_sheet.workbook.dependencyFormulas : null;
|
|
if(opt_df && opt_df.defNames && opt_df.defNames.sheet && opt_df.defNames.sheet[wsFrom.getId()]) {
|
|
//TODO пересмотреть!
|
|
//пока делаю только для им. диапазонов листа. в случае книгой - необходимо хранить map преообразований для redo
|
|
sheetContainerFrom = opt_df.defNames.sheet[wsFrom.getId()];
|
|
} else {
|
|
sheetContainerFrom = this.defNames.sheet[wsFrom.getId()];
|
|
}
|
|
if (sheetContainerFrom) {
|
|
for (var name in sheetContainerFrom) {
|
|
var defNameOld = sheetContainerFrom[name];
|
|
if (defNameOld.type !== Asc.c_oAscDefNameType.table && defNameOld.parsedRef) {
|
|
var parsedRefNew = defNameOld.parsedRef.clone();
|
|
parsedRefNew.renameSheetCopy(renameParams);
|
|
var refNew = parsedRefNew.assemble(true);
|
|
this.addDefName(defNameOld.name, refNew, wsTo.getId(), defNameOld.hidden, defNameOld.type);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
copyDefNameByWorkbook: function(wsFrom, wsTo, renameParams, opt_sheet) {
|
|
var t = this;
|
|
var opt_wb = opt_sheet && opt_sheet.workbook;
|
|
var opt_df = opt_wb && opt_wb.dependencyFormulas;
|
|
|
|
var doCopy = function (_sheetContainerFrom) {
|
|
if (_sheetContainerFrom) {
|
|
for (var name in _sheetContainerFrom) {
|
|
var defNameOld = _sheetContainerFrom[name];
|
|
|
|
if (defNameOld.type !== Asc.c_oAscDefNameType.table && defNameOld.parsedRef) {
|
|
var parsedRefNew = defNameOld.parsedRef.clone();
|
|
parsedRefNew.renameSheetCopy(renameParams);
|
|
var refNew = parsedRefNew.assemble(true);
|
|
var _newDefName = new Asc.asc_CDefName(defNameOld.name, refNew, null, defNameOld.type, defNameOld.hidden);
|
|
t.wb.editDefinesNames(null, _newDefName);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
if (opt_df) {
|
|
doCopy(opt_df.defNames.wb);
|
|
}
|
|
},
|
|
saveDefName: function(isCopySheet) {
|
|
var list = [];
|
|
var t = this;
|
|
this._foreachDefName(function(defName) {
|
|
if (defName.type !== Asc.c_oAscDefNameType.table && defName.ref) {
|
|
if (!isCopySheet || t._checkDefNamesCopySheet(defName)) {
|
|
list.push(defName.getAscCDefName());
|
|
}
|
|
}
|
|
});
|
|
return list;
|
|
},
|
|
_checkDefNamesCopySheet: function (defName) {
|
|
var res = true;
|
|
|
|
var ws = this.wb.getActiveWs();
|
|
if (defName.sheetId && defName.sheetId !== ws.Id) {
|
|
return false;
|
|
}
|
|
if (defName.type === Asc.c_oAscDefNameType.slicer) {
|
|
return false;
|
|
}
|
|
|
|
//временная правка - не пишем именованный диапазоны, которые ссылаются на другие листы
|
|
var parsedRef = defName.parsedRef;
|
|
if (parsedRef) {
|
|
for (var i = 0; i < parsedRef.outStack.length; i++) {
|
|
var elem = parsedRef.outStack[i];
|
|
if (cElementType.cell === elem.type || cElementType.cellsRange === elem.type ||
|
|
cElementType.cell3D === elem.type || cElementType.cellsRange3D === elem.type ) {
|
|
if (elem.getWS().getName() !== ws.getName()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
},
|
|
unlockDefName: function() {
|
|
this._foreachDefName(function(defName) {
|
|
defName.isLock = null;
|
|
});
|
|
},
|
|
unlockCurrentDefName: function(name, sheetId) {
|
|
var defName = this.getDefNameByName(name, sheetId);
|
|
if(defName) {
|
|
defName.isLock = null;
|
|
}
|
|
},
|
|
checkDefNameLock: function() {
|
|
return this._foreachDefName(function(defName) {
|
|
return defName.isLock;
|
|
});
|
|
},
|
|
getNewXlChartIndex: function() {
|
|
if (this.defNames.xlchartIndex === null) {
|
|
let startIndex = -1;
|
|
this._foreachDefNameBook(function(defName) {
|
|
const name = defName.name;
|
|
if (name.startsWith("_xlchart")) {
|
|
const splitName = name.split(".");
|
|
const index = parseInt(splitName[splitName.length - 1], 10);
|
|
if (AscFormat.isRealNumber(index) && index > startIndex) {
|
|
startIndex = index;
|
|
}
|
|
}
|
|
});
|
|
this.defNames.xlchartIndex = startIndex;
|
|
}
|
|
return ++this.defNames.xlchartIndex;
|
|
},
|
|
getNewXlChartId: function() {
|
|
return "_xlchart.v1." + this.getNewXlChartIndex();
|
|
},
|
|
//defined name table
|
|
getNextTableName: function() {
|
|
var sNewName;
|
|
var collaborativeIndexUser = "";
|
|
var api = window["Asc"]["editor"];
|
|
if (api && api.collaborativeEditing && api.collaborativeEditing.getCollaborativeEditing()) {
|
|
collaborativeIndexUser = "_" + this.wb.oApi.CoAuthoringApi.get_indexUser();
|
|
}
|
|
do {
|
|
this.tableNameIndex++;
|
|
var tableName = AscCommon.translateManager.getValue(this.tableNamePattern);
|
|
sNewName = tableName + this.tableNameIndex + collaborativeIndexUser;
|
|
} while (this.getDefNameByName(sNewName, null) || this.isListeningDefName(sNewName));
|
|
return sNewName;
|
|
},
|
|
getNextPivotName: function() {
|
|
var sNewName;
|
|
do {
|
|
this.pivotNameIndex++;
|
|
var tableName = AscCommon.translateManager.getValue(this.pivotNamePattern);
|
|
sNewName = tableName + this.pivotNameIndex;
|
|
} while (this.wb.getPivotTableByName(sNewName));
|
|
return sNewName;
|
|
},
|
|
addTableName: function(ws, table, opt_isOpen) {
|
|
var ref = table.getRangeWithoutHeaderFooter();
|
|
|
|
var defNameRef = parserHelp.get3DRef(ws.getName(), ref.getAbsName());
|
|
var defName = this.getDefNameByName(table.DisplayName, null);
|
|
if (!defName) {
|
|
if(opt_isOpen){
|
|
this.addDefNameOpen(table.DisplayName, defNameRef, null, null, Asc.c_oAscDefNameType.table);
|
|
} else {
|
|
this.addDefName(table.DisplayName, defNameRef, null, null, Asc.c_oAscDefNameType.table);
|
|
}
|
|
} else {
|
|
defName.setRef(defNameRef);
|
|
}
|
|
},
|
|
changeTableRef: function(table) {
|
|
var defName = this.getDefNameByName(table.DisplayName, null);
|
|
if (defName) {
|
|
this.buildDependency();
|
|
var oldUndoName = defName.getUndoDefName();
|
|
var newUndoName = defName.getUndoDefName();
|
|
var ref = table.getRangeWithoutHeaderFooter();
|
|
newUndoName.ref = defName.ref.split('!')[0] + '!' + ref.getAbsName();
|
|
AscCommon.History.TurnOff();
|
|
this.editDefinesNames(oldUndoName, newUndoName);
|
|
var notifyData = {type: c_oNotifyType.ChangeDefName, from: oldUndoName, to: newUndoName};
|
|
this._broadcastDefName(defName.name, notifyData);
|
|
AscCommon.History.TurnOn();
|
|
this.addToChangedDefName(defName);
|
|
this.calcTree();
|
|
}
|
|
},
|
|
changeTableName: function(tableName, newName) {
|
|
var defName = this.getDefNameByName(tableName, null);
|
|
if (defName) {
|
|
var oldUndoName = defName.getUndoDefName();
|
|
var newUndoName = defName.getUndoDefName();
|
|
newUndoName.name = newName;
|
|
AscCommon.History.TurnOff();
|
|
this.editDefinesNames(oldUndoName, newUndoName);
|
|
AscCommon.History.TurnOn();
|
|
}
|
|
},
|
|
delTableName: function(tableName, bConvertTableFormulaToRef) {
|
|
this.buildDependency();
|
|
var defName = this.getDefNameByName(tableName);
|
|
|
|
this.addToChangedDefName(defName);
|
|
var notifyData = {type: c_oNotifyType.ChangeDefName, from: defName.getUndoDefName(), to: null, bConvertTableFormulaToRef: bConvertTableFormulaToRef};
|
|
this._broadcastDefName(tableName, notifyData);
|
|
|
|
this._delDefName(tableName, null);
|
|
if (defName) {
|
|
defName.removeDependencies();
|
|
}
|
|
},
|
|
delColumnTable: function(tableName, deleted) {
|
|
this.buildDependency();
|
|
var notifyData = {type: c_oNotifyType.DelColumnTable, tableName: tableName, deleted: deleted};
|
|
this._broadcastDefName(tableName, notifyData);
|
|
},
|
|
renameTableColumn: function(tableName) {
|
|
var defName = this.getDefNameByName(tableName, null);
|
|
if (defName) {
|
|
this.buildDependency();
|
|
var notifyData = {type: c_oNotifyType.RenameTableColumn, tableName: tableName};
|
|
this._broadcastDefName(defName.name, notifyData);
|
|
}
|
|
this.calcTree();
|
|
},
|
|
addToVolatileArrays: function(formula) {
|
|
if (!this.volatileArrays) {
|
|
this.volatileArrays = {};
|
|
}
|
|
let listenerId = formula.getListenerId();
|
|
this.volatileArrays[listenerId] = formula;
|
|
},
|
|
getVolatileArrays: function() {
|
|
if (!this.volatileArrays) {
|
|
return
|
|
}
|
|
|
|
return this.volatileArrays
|
|
},
|
|
endListeningVolatileArray: function(listenerId) {
|
|
if (listenerId) {
|
|
delete this.volatileArrays[listenerId];
|
|
}
|
|
},
|
|
//set dirty
|
|
addToChangedRange2: function(sheetId, bbox) {
|
|
if (bbox.isOneCell()) {
|
|
this.addToChangedCell2(sheetId, bbox.r1, bbox.c1);
|
|
return;
|
|
}
|
|
if (!this.changedRange) {
|
|
this.changedRange = {};
|
|
}
|
|
var changedSheet = this.changedRange[sheetId];
|
|
if (!changedSheet) {
|
|
//{}, а не [], потому что при сборке может придти сразу много одинаковых ячеек
|
|
changedSheet = {};
|
|
this.changedRange[sheetId] = changedSheet;
|
|
}
|
|
var name = getVertexIndex(bbox);
|
|
if (this.isInCalc && !changedSheet[name]) {
|
|
//todo change cell
|
|
if (!this.changedRangeRepeated) {
|
|
this.changedRangeRepeated = {};
|
|
}
|
|
var changedSheetRepeated = this.changedRangeRepeated[sheetId];
|
|
if (!changedSheetRepeated) {
|
|
changedSheetRepeated = {};
|
|
this.changedRangeRepeated[sheetId] = changedSheetRepeated;
|
|
}
|
|
changedSheetRepeated[name] = bbox;
|
|
}
|
|
changedSheet[name] = bbox;
|
|
},
|
|
addToChangedCell2: function(sheetId, row, col) {
|
|
var t = this;
|
|
if (!this.changedCell) {
|
|
this.changedCell = {};
|
|
}
|
|
var changedSheet = this.changedCell[sheetId];
|
|
if (!changedSheet) {
|
|
//{}, а не [], потому что при сборке может придти сразу много одинаковых ячеек
|
|
changedSheet = {};
|
|
this.changedCell[sheetId] = changedSheet;
|
|
}
|
|
|
|
var addChangedSheet = function(row, col) {
|
|
var cellIndex = getCellIndex(row, col);
|
|
if (t.isInCalc && undefined === changedSheet[cellIndex]) {
|
|
if (!t.changedCellRepeated) {
|
|
t.changedCellRepeated = {};
|
|
}
|
|
var changedSheetRepeated = t.changedCellRepeated[sheetId];
|
|
if (!changedSheetRepeated) {
|
|
changedSheetRepeated = {};
|
|
t.changedCellRepeated[sheetId] = changedSheetRepeated;
|
|
}
|
|
changedSheetRepeated[cellIndex] = cellIndex;
|
|
}
|
|
changedSheet[cellIndex] = cellIndex;
|
|
};
|
|
|
|
addChangedSheet(row, col);
|
|
},
|
|
addToChangedCell: function(cell) {
|
|
this.addToChangedCell2(cell.ws.getId(), cell.nRow, cell.nCol);
|
|
},
|
|
addToChangedDefName: function(defName) {
|
|
if (!this.changedDefName) {
|
|
this.changedDefName = {};
|
|
}
|
|
var nodeId = defName.getNodeId();
|
|
if (this.isInCalc && !this.changedDefName[nodeId]) {
|
|
if (!this.changedDefNameRepeated) {
|
|
this.changedDefNameRepeated = {};
|
|
}
|
|
this.changedDefNameRepeated[nodeId] = 1;
|
|
}
|
|
this.changedDefName[nodeId] = 1;
|
|
},
|
|
addToChangedRange: function(sheetId, bbox) {
|
|
var notifyData = {type: c_oNotifyType.Dirty};
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
for (var cellIndex in sheetContainer.cellMap) {
|
|
getFromCellIndex(cellIndex);
|
|
if (bbox.contains(g_FCI.col, g_FCI.row)) {
|
|
var cellMapElem = sheetContainer.cellMap[cellIndex];
|
|
for (var listenerId in cellMapElem.listeners) {
|
|
cellMapElem.listeners[listenerId].notify(notifyData);
|
|
}
|
|
}
|
|
}
|
|
for (var areaIndex in sheetContainer.areaMap) {
|
|
var areaMapElem = sheetContainer.areaMap[areaIndex];
|
|
var isIntersect = bbox.isIntersect(areaMapElem.bbox);
|
|
if (isIntersect) {
|
|
for (var listenerId in areaMapElem.listeners) {
|
|
areaMapElem.listeners[listenerId].notify(notifyData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
addToChangedHiddenRows: function() {
|
|
//notify hidden rows
|
|
var tmpRange = new Asc.Range(0, 0, gc_nMaxCol0, 0);
|
|
for (var i = 0; i < this.wb.aWorksheets.length; ++i) {
|
|
var ws = this.wb.aWorksheets[i];
|
|
var hiddenRange = ws.hiddenManager.getHiddenRowsRange();
|
|
if (hiddenRange) {
|
|
tmpRange.r1 = hiddenRange.r1;
|
|
tmpRange.r2 = hiddenRange.r2;
|
|
this.addToChangedRange(ws.getId(), tmpRange);
|
|
}
|
|
}
|
|
},
|
|
addToBuildDependencyCell: function(cell) {
|
|
var sheetId = cell.ws.getId();
|
|
var unparsedSheet = this.buildCell[sheetId];
|
|
if (!unparsedSheet) {
|
|
//{}, а не [], потому что при сборке может придти сразу много одинаковых ячеек
|
|
unparsedSheet = {};
|
|
this.buildCell[sheetId] = unparsedSheet;
|
|
}
|
|
unparsedSheet[getCellIndex(cell.nRow, cell.nCol)] = 1;
|
|
},
|
|
addToBuildDependencyDefName: function(defName) {
|
|
this.buildDefName[defName.getNodeId()] = 1;
|
|
},
|
|
addToBuildDependencyShared: function(shared) {
|
|
this.buildShared[shared.getIndexNumber()] = shared;
|
|
},
|
|
addToBuildDependencyArray: function(f) {
|
|
//TODO переммотреть! добавлять по индексу!
|
|
//добавляю не по индексу потому на момент вызова(setValue) ещё не проставились индексы формулам
|
|
//происходит это позже - в Cell.prototype.saveContent
|
|
this.buildArrayFormula.push(f);
|
|
},
|
|
addToBuildDependencyPivot: function(f) {
|
|
this.buildPivot.push(f);
|
|
},
|
|
addToCleanCellCache: function(sheetId, row, col) {
|
|
var sheetArea = this.cleanCellCache[sheetId];
|
|
if (sheetArea) {
|
|
sheetArea.union3(col, row);
|
|
} else {
|
|
this.cleanCellCache[sheetId] = new Asc.Range(col, row, col, row);
|
|
}
|
|
},
|
|
addToChangedShared: function(parsed) {
|
|
this.changedShared[parsed.getIndexNumber()] = parsed;
|
|
},
|
|
notifyChanged: function(changedFormulas) {
|
|
var notifyData = {type: c_oNotifyType.Dirty};
|
|
for (var listenerId in changedFormulas) {
|
|
changedFormulas[listenerId].notify(notifyData);
|
|
}
|
|
},
|
|
//build, calc
|
|
buildDependency: function() {
|
|
for (var sheetId in this.buildCell) {
|
|
var ws = this.wb.getWorksheetById(sheetId);
|
|
if (ws) {
|
|
var unparsedSheet = this.buildCell[sheetId];
|
|
for (var cellIndex in unparsedSheet) {
|
|
getFromCellIndex(cellIndex);
|
|
ws._getCellNoEmpty(g_FCI.row, g_FCI.col, function(cell) {
|
|
if (cell) {
|
|
cell._BuildDependencies(true, true);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
for (var defNameId in this.buildDefName) {
|
|
var defName = this.getDefNameByNodeId(defNameId);
|
|
if (defName && defName.parsedRef) {
|
|
defName.parsedRef.parse();
|
|
defName.parsedRef.buildDependencies();
|
|
this.addToChangedDefName(defName);
|
|
}
|
|
}
|
|
for (var index in this.buildShared) {
|
|
if (this.buildShared.hasOwnProperty(index)) {
|
|
var parsed = this.wb.workbookFormulas.get(index - 0);
|
|
if (parsed) {
|
|
parsed.parse();
|
|
parsed.buildDependencies();
|
|
var shared = parsed.getShared();
|
|
this.wb.dependencyFormulas.addToChangedRange2(parsed.getWs().getId(), shared.ref);
|
|
}
|
|
}
|
|
}
|
|
for (var index = 0; index < this.buildArrayFormula.length; ++index) {
|
|
var parsed = this.buildArrayFormula[index];
|
|
if (parsed) {
|
|
parsed.parse();
|
|
parsed.buildDependencies();
|
|
var array = parsed.getArrayFormulaRef();
|
|
this.wb.dependencyFormulas.addToChangedRange2(parsed.getWs().getId(), array);
|
|
}
|
|
}
|
|
for (var index = 0; index < this.buildPivot.length; ++index) {
|
|
var parsed = this.buildPivot[index];
|
|
if (parsed) {
|
|
parsed.parse();
|
|
parsed.buildDependencies();
|
|
}
|
|
}
|
|
this.buildCell = {};
|
|
this.buildDefName = {};
|
|
this.buildShared = {};
|
|
this.buildArrayFormula = [];
|
|
this.buildPivot = [];
|
|
},
|
|
calcTree: function(callback, forceRecal) {
|
|
if (this.lockCounter > 0) {
|
|
callback && callback();
|
|
return;
|
|
}
|
|
this.buildDependency();
|
|
this.addToChangedHiddenRows();
|
|
if (!(this.changedCell || this.changedRange || this.changedDefName) && !forceRecal) {
|
|
callback && callback();
|
|
return;
|
|
}
|
|
var notifyData = {type: c_oNotifyType.Dirty, areaData: undefined};
|
|
if (!g_cCalcRecursion.getIsSheetCreating()) {
|
|
this._broadscastVolatile(notifyData);
|
|
}
|
|
this._broadcastCellsStart();
|
|
let repeatCount = 0;
|
|
while (this.changedCellRepeated || this.changedRangeRepeated || this.changedDefNameRepeated) {
|
|
if (++repeatCount > this.maxBroadcastRecursion) {
|
|
this.notifyAllFormulasInChangedWs();
|
|
}
|
|
|
|
this._broadcastDefNames(notifyData);
|
|
this._broadcastCells(notifyData);
|
|
this._broadcastRanges(notifyData);
|
|
}
|
|
this._broadcastCellsEnd();
|
|
do {
|
|
this._calculateDirty();
|
|
if (g_cCalcRecursion.getIsEnabledRecursion()) {
|
|
g_cCalcRecursion.incIterStep();
|
|
}
|
|
} while (g_cCalcRecursion.needRecursiveCall());
|
|
|
|
if (!this.wb.asyncFormulasManager.isRecalculating() && this.wb.asyncFormulasManager.getPromises() && !AscCommonExcel.g_LockCustomFunctionRecalculate) {
|
|
this.wb.asyncFormulasManager.calculatePromises(callback);
|
|
} else if (!g_cCalcRecursion.needRecursiveCall() && !this.wb.asyncFormulasManager.isRecalculating()) {
|
|
callback && callback();
|
|
}
|
|
|
|
if (/*!this.wb.asyncFormulasManager.isRecalculating() &&*/ this.wb.asyncFormulasManager.getReplacedFormulas() && !AscCommonExcel.g_LockCustomFunctionRecalculate) {
|
|
this.wb.asyncFormulasManager.calculateReplacedFormulas(callback);
|
|
} else if (!g_cCalcRecursion.needRecursiveCall() && !this.wb.asyncFormulasManager.isRecalculating()) {
|
|
callback && callback();
|
|
}
|
|
|
|
g_cCalcRecursion.resetIterStep();
|
|
g_cCalcRecursion.setStartCellIndex(null);
|
|
g_cCalcRecursion.setGroupChangedCells(null);
|
|
g_cCalcRecursion.clearPrevIterResult();
|
|
g_cCalcRecursion.clearDiffBetweenIter();
|
|
g_cCalcRecursion.clearCycleCells();
|
|
g_cCalcRecursion.clearCheckedCells();
|
|
this.changedCell = null;
|
|
this.changedRange = null;
|
|
this.updateSharedFormulas();
|
|
//copy cleanCellCache to prevent recursion in trigger("cleanCellCache")
|
|
var tmpCellCache = this.cleanCellCache;
|
|
this.cleanCellCache = {};
|
|
for (var i in tmpCellCache) {
|
|
this.wb.handlers && this.wb.handlers.trigger("cleanCellCache", i, [tmpCellCache[i]], true);
|
|
}
|
|
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();
|
|
},
|
|
notifyAllFormulasInChangedWs: function() {
|
|
let sheetIds = {};
|
|
for (let sheetId in this.changedCell) {
|
|
sheetIds[sheetId] = 1;
|
|
}
|
|
for (let sheetId in this.changedRangeRepeated) {
|
|
sheetIds[sheetId] = 1;
|
|
}
|
|
let formulas = [];
|
|
for (let sheetId in sheetIds) {
|
|
let ws = this.wb.getWorksheetById(sheetId);
|
|
if (ws) {
|
|
ws.getAllFormulas(formulas);
|
|
}
|
|
}
|
|
this.notifyChanged(formulas);
|
|
},
|
|
initOpen: function() {
|
|
this._foreachDefName(function(defName) {
|
|
defName.setRef(defName.ref, true, true, true);
|
|
});
|
|
},
|
|
getSnapshot: function(wb) {
|
|
var res = new DependencyGraph(wb);
|
|
this._foreachDefName(function(defName){
|
|
//_addDefName because we don't need dependency
|
|
//include table defNames too.
|
|
res._addDefName(defName.clone(wb));
|
|
});
|
|
res.tableNameIndex = this.tableNameIndex;
|
|
return res;
|
|
},
|
|
getAllFormulas: function(formulas) {
|
|
this._foreachDefName(function(defName) {
|
|
if (defName.parsedRef) {
|
|
formulas.push(defName.parsedRef);
|
|
}
|
|
});
|
|
},
|
|
forEachFormula: function(callback) {
|
|
this._foreachDefName(function(defName) {
|
|
if (defName.parsedRef) {
|
|
callback(defName.parsedRef);
|
|
}
|
|
});
|
|
},
|
|
updateSharedFormulas: function() {
|
|
var newRef;
|
|
for (var indexNumber in this.changedShared) {
|
|
var parsed = this.changedShared[indexNumber];
|
|
var shared = parsed.getShared();
|
|
if (shared) {
|
|
var ws = parsed.getWs();
|
|
var ref = shared.ref;
|
|
var r1 = gc_nMaxRow0;
|
|
var c1 = gc_nMaxCol0;
|
|
var r2 = 0;
|
|
var c2 = 0;
|
|
ws.getRange3(ref.r1, ref.c1, ref.r2, ref.c2)._foreachNoEmpty(function(cell) {
|
|
if (parsed === cell.getFormulaParsed()) {
|
|
r1 = Math.min(r1, cell.nRow);
|
|
c1 = Math.min(c1, cell.nCol);
|
|
r2 = Math.max(r2, cell.nRow);
|
|
c2 = Math.max(c2, cell.nCol);
|
|
}
|
|
});
|
|
newRef = undefined;
|
|
if (r1 <= r2 && c1 <= c2) {
|
|
newRef = new Asc.Range(c1, r1, c2, r2);
|
|
}
|
|
parsed.setSharedRef(newRef);
|
|
}
|
|
}
|
|
this.changedShared = {};
|
|
},
|
|
//internal
|
|
_addDefName: function(defName) {
|
|
var nameIndex = getDefNameIndex(defName.name);
|
|
var container;
|
|
var sheetId = defName.sheetId;
|
|
if (sheetId) {
|
|
container = this.defNames.sheet[sheetId];
|
|
if (!container) {
|
|
container = {};
|
|
this.defNames.sheet[sheetId] = container;
|
|
}
|
|
} else {
|
|
container = this.defNames.wb;
|
|
}
|
|
var cur = container[nameIndex];
|
|
if (cur) {
|
|
cur.removeDependencies();
|
|
}
|
|
container[nameIndex] = defName;
|
|
},
|
|
_removeDefName: function(sheetId, name, historyType) {
|
|
var defName = this._delDefName(name, sheetId);
|
|
if (defName) {
|
|
if (null != historyType) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, historyType, null, null,
|
|
new UndoRedoData_FromTo(defName.getUndoDefName(), null));
|
|
}
|
|
|
|
defName.removeDependencies();
|
|
this.addToChangedDefName(defName);
|
|
}
|
|
},
|
|
_delDefName: function(name, sheetId) {
|
|
var res = null;
|
|
var nameIndex = getDefNameIndex(name);
|
|
var sheetContainer;
|
|
if (sheetId) {
|
|
sheetContainer = this.defNames.sheet[sheetId];
|
|
}
|
|
else {
|
|
sheetContainer = this.defNames.wb;
|
|
}
|
|
if (sheetContainer) {
|
|
res = sheetContainer[nameIndex];
|
|
delete sheetContainer[nameIndex];
|
|
}
|
|
return res;
|
|
},
|
|
_foreachDefName: function(action) {
|
|
var containerSheet;
|
|
var sheetId;
|
|
var name;
|
|
var res;
|
|
for (sheetId in this.defNames.sheet) {
|
|
containerSheet = this.defNames.sheet[sheetId];
|
|
for (name in containerSheet) {
|
|
res = action(containerSheet[name], containerSheet);
|
|
if (res) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!res) {
|
|
res = this._foreachDefNameBook(action);
|
|
}
|
|
return res;
|
|
},
|
|
_foreachDefNameSheet: function(sheetId, action) {
|
|
var name;
|
|
var res;
|
|
var containerSheet = this.defNames.sheet[sheetId];
|
|
if (containerSheet) {
|
|
for (name in containerSheet) {
|
|
res = action(containerSheet[name], containerSheet);
|
|
if (res) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
},
|
|
_foreachDefNameBook: function(action) {
|
|
var containerSheet;
|
|
var name;
|
|
var res;
|
|
for (name in this.defNames.wb) {
|
|
res = action(this.defNames.wb[name], this.defNames.wb);
|
|
if (res) {
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
},
|
|
_broadscastVolatile: function(notifyData) {
|
|
if (this.wb.asyncFormulasManager.isRecalculating()) {
|
|
return;
|
|
}
|
|
for (var i in this.volatileListeners) {
|
|
this.volatileListeners[i].notify(notifyData);
|
|
}
|
|
},
|
|
_broadcastDefName: function(name, notifyData) {
|
|
var nameIndex = getDefNameIndex(name);
|
|
var container = this.defNameListeners[nameIndex];
|
|
if (container) {
|
|
for (var listenerId in container.listeners) {
|
|
container.listeners[listenerId].notify(notifyData);
|
|
}
|
|
}
|
|
},
|
|
_broadcastDefNames: function(notifyData) {
|
|
if (this.changedDefNameRepeated) {
|
|
var changedDefName = this.changedDefNameRepeated;
|
|
this.changedDefNameRepeated = null;
|
|
for (var nodeId in changedDefName) {
|
|
getFromDefNameId(nodeId);
|
|
this._broadcastDefName(g_FDNI.name, notifyData);
|
|
}
|
|
}
|
|
},
|
|
_broadcastCells: function(notifyData) {
|
|
if (this.changedCellRepeated) {
|
|
var changedCell = this.changedCellRepeated;
|
|
this.changedCellRepeated = null;
|
|
for (var sheetId in changedCell) {
|
|
var changedSheet = changedCell[sheetId];
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
var cells = [];
|
|
for (var cellIndex in changedSheet) {
|
|
cells.push(changedSheet[cellIndex]);
|
|
}
|
|
cells.sort(AscCommon.fSortAscending);
|
|
this._broadcastCellsByCells(sheetContainer, cells, notifyData);
|
|
//todo add changedCellRepeated after _broadcastCellsByCells
|
|
this._broadcastRangesByCells(sheetContainer, cells, notifyData);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_broadcastRanges: function(notifyData) {
|
|
if (this.changedRangeRepeated) {
|
|
var changedRange = this.changedRangeRepeated;
|
|
this.changedRangeRepeated = null;
|
|
for (var sheetId in changedRange) {
|
|
var changedSheet = changedRange[sheetId];
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
if (sheetContainer) {
|
|
let rangesTopFrom = [];
|
|
let counter = 1;
|
|
for (let name in changedSheet) {
|
|
rangesTopFrom.push({index: 0, bbox: changedSheet[name]});
|
|
}
|
|
let rangesTopTo = rangesTopFrom.concat();
|
|
let rangesBottomFrom = rangesTopFrom.concat();
|
|
let rangesBottomTo = rangesTopFrom.concat();
|
|
|
|
rangesTopFrom.sort(AscCommonExcel.BroadcastHelper.prototype.cmpInsertFrom);
|
|
rangesTopTo.sort(AscCommonExcel.BroadcastHelper.prototype.cmpInsertTo);
|
|
rangesBottomFrom.sort(AscCommonExcel.BroadcastHelper.prototype.cmpDeleteFrom);
|
|
rangesBottomTo.sort(AscCommonExcel.BroadcastHelper.prototype.cmpDeleteTo);
|
|
this._broadcastCellsByRanges(sheetContainer, rangesTopFrom, rangesTopTo, rangesBottomFrom, rangesBottomTo, notifyData);
|
|
this._broadcastRangesByRanges(sheetContainer, rangesTopFrom, rangesTopTo, rangesBottomFrom, rangesBottomTo, notifyData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_broadcastCellsStart: function() {
|
|
this.isInCalc = true;
|
|
this.changedCellRepeated = this.changedCell;
|
|
this.changedRangeRepeated = this.changedRange;
|
|
this.changedDefNameRepeated = this.changedDefName;
|
|
for (var sheetId in this.sheetListeners) {
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (!sheetContainer.cells) {
|
|
sheetContainer.cells = [];
|
|
for (var cellIndex in sheetContainer.cellMap) {
|
|
sheetContainer.cells.push(sheetContainer.cellMap[cellIndex]);
|
|
}
|
|
sheetContainer.cells.sort(function(a, b) {
|
|
return a.cellIndex - b.cellIndex
|
|
});
|
|
}
|
|
if (!sheetContainer.rangesTopFrom || !sheetContainer.rangesTopTo || !sheetContainer.rangesBottomFrom || !sheetContainer.rangesBottomTo) {
|
|
sheetContainer.rangesTopFrom = [];
|
|
for (let name in sheetContainer.areaMap) {
|
|
sheetContainer.rangesTopFrom.push(sheetContainer.areaMap[name]);
|
|
}
|
|
sheetContainer.rangesTopTo = sheetContainer.rangesTopFrom.concat();
|
|
sheetContainer.rangesBottomFrom = sheetContainer.rangesTopFrom.concat();
|
|
sheetContainer.rangesBottomTo = sheetContainer.rangesTopFrom.concat();
|
|
|
|
sheetContainer.rangesTopFrom.sort(AscCommonExcel.BroadcastHelper.prototype.cmpInsertFrom);
|
|
sheetContainer.rangesTopTo.sort(AscCommonExcel.BroadcastHelper.prototype.cmpInsertTo);
|
|
sheetContainer.rangesBottomFrom.sort(AscCommonExcel.BroadcastHelper.prototype.cmpDeleteFrom);
|
|
sheetContainer.rangesBottomTo.sort(AscCommonExcel.BroadcastHelper.prototype.cmpDeleteTo);
|
|
}
|
|
}
|
|
},
|
|
_broadcastCellsEnd: function() {
|
|
this.isInCalc = false;
|
|
this.changedDefName = null;
|
|
for (var i = 0; i < this.tempGetByCells.length; ++i) {
|
|
for (var j = 0; j < this.tempGetByCells[i].length; ++j) {
|
|
var temp = this.tempGetByCells[i][j];
|
|
|
|
temp.isActive = true;
|
|
if (temp.sharedBroadcast) {
|
|
temp.sharedBroadcast.changedBBox = null;
|
|
temp.sharedBroadcast.prevChangedBBox = null;
|
|
temp.sharedBroadcast.recursion = 0;
|
|
}
|
|
}
|
|
}
|
|
this.tempGetByCells = [];
|
|
},
|
|
|
|
/**
|
|
* Method starts preparing for calculate cells with formula. Recognizes what cells need to calculate.
|
|
* @memberof DependencyGraph
|
|
* @private
|
|
*/
|
|
_calculateDirty: function() {
|
|
const t = this;
|
|
let needUpdateCells = [];
|
|
this._foreachChanged(function (oCell) {
|
|
if (oCell && oCell.isFormula()) {
|
|
const oFormulaParsed = oCell.getFormulaParsed();
|
|
// Logic for iterative calculation
|
|
if (g_cCalcRecursion.getIsEnabledRecursion()) {
|
|
const nThisCellIndex = getCellIndex(oCell.nRow, oCell.nCol);
|
|
const sCellWsName = oCell.ws.getName().toLowerCase();
|
|
const aRecursiveCells = g_cCalcRecursion.getRecursiveCells(oCell);
|
|
|
|
// Fills 0 value for empty cells for potentially recursive formula.
|
|
if (oCell.getNumberValue() == null && (oCell.getValueText() == null || oCell.getValueText() === '#NUM!')) {
|
|
if (oCell.getType() !== CellValueType.Number) {
|
|
oCell.setTypeInternal(CellValueType.Number);
|
|
}
|
|
oCell.setValueNumberInternal(0);
|
|
}
|
|
g_cCalcRecursion.updateStartCellIndex(aRecursiveCells);
|
|
if (!g_cCalcRecursion.getStartCellIndex()) {
|
|
oCell.initStartCellForIterCalc();
|
|
}
|
|
let oStartCellIndex = g_cCalcRecursion.getStartCellIndex();
|
|
if (oStartCellIndex) {
|
|
/** Checks static formulas with ca flag - false. For iterative calc static formulas that
|
|
participate in recursive formulas must be calculated before calculating dependent cells.**/
|
|
if (!oFormulaParsed.ca) {
|
|
oCell.changeLinkedCell(function (oLinkedCell) {
|
|
const oFormulaParsed = oLinkedCell.getFormulaParsed();
|
|
if (!oFormulaParsed.ca) {
|
|
oLinkedCell.setIsDirty(true);
|
|
oLinkedCell._checkDirty();
|
|
}
|
|
}, true);
|
|
oCell.setIsDirty(true);
|
|
oCell._checkDirty();
|
|
}
|
|
// Check result of the formula is convergent
|
|
let nDiffBetweenIter = g_cCalcRecursion.getDiffBetweenIter(oCell);
|
|
if (!isNaN(nDiffBetweenIter) && nDiffBetweenIter < g_cCalcRecursion.getRelativeError()) {
|
|
g_cCalcRecursion.removeRecursionCell(oCell);
|
|
if (g_cCalcRecursion.getPrevIterResult(oCell) !== 0 && g_cCalcRecursion.getIterStep() === 2) {
|
|
oCell.setValueNumberInternal(g_cCalcRecursion.getPrevIterResult(oCell));
|
|
}
|
|
return;
|
|
} else {
|
|
// Check diff of linked cell
|
|
let bLinkCellConvergent = false;
|
|
oCell.changeLinkedCell(function (oLinkedCell) {
|
|
const nLinkedDiff = g_cCalcRecursion.getDiffBetweenIter(oLinkedCell);
|
|
if (!isNaN(nLinkedDiff) && nLinkedDiff < g_cCalcRecursion.getRelativeError()) {
|
|
bLinkCellConvergent = true;
|
|
}
|
|
}, false);
|
|
if (bLinkCellConvergent) {
|
|
g_cCalcRecursion.removeRecursionCell(oCell);
|
|
return;
|
|
}
|
|
}
|
|
// Save current value of cell as result of previous iteration
|
|
g_cCalcRecursion.setPrevIterResult(oCell);
|
|
// Fill the array with linked cells from the recursive formula
|
|
if (!aRecursiveCells.length && oStartCellIndex.cellId === nThisCellIndex && oStartCellIndex.wsName === sCellWsName) {
|
|
oCell.fillRecursiveCells(aRecursiveCells, oStartCellIndex);
|
|
}
|
|
// Disable calculating formula for linked cells
|
|
let bRecursiveCell = aRecursiveCells.some(function(oCellIndex) {
|
|
return oCellIndex.cellId === nThisCellIndex && oCellIndex.wsName === sCellWsName;
|
|
});
|
|
if ((nThisCellIndex !== oStartCellIndex.cellId || oStartCellIndex.wsName !== sCellWsName) && bRecursiveCell) {
|
|
oCell.setIsDirty(false);
|
|
return;
|
|
}
|
|
} else if (g_cCalcRecursion.getIterStep() > 1 && oCell.getValueWithoutFormat() && !g_cCalcRecursion.hasInRecursiveCells(oCell)) {
|
|
oCell.setIsDirty(false);
|
|
return;
|
|
}
|
|
} else if (oFormulaParsed.ca === true) {
|
|
oCell.initStartCellForIterCalc();
|
|
if (g_cCalcRecursion.getStartCellIndex()) {
|
|
g_cCalcRecursion.addCycleCell(oCell);
|
|
const oRefRange = oCell.getFormulaParsed().ref;
|
|
let bEmptyCell = oCell.getNumberValue() == null && (oCell.getValueText() == null || oCell.getValueText() === '#NUM!');
|
|
let bRefEmptyCell = !!oRefRange && oRefRange.r1 === oCell.nRow && oRefRange.c1 === oCell.nCol && bEmptyCell;
|
|
if ((!oRefRange && bEmptyCell) || bRefEmptyCell) {
|
|
if (oCell.getType() !== CellValueType.Number) {
|
|
oCell.setTypeInternal(CellValueType.Number);
|
|
}
|
|
oCell.setValueNumberInternal(0);
|
|
}
|
|
oCell.setIsDirty(false);
|
|
g_cCalcRecursion.setStartCellIndex(null);
|
|
return;
|
|
}
|
|
}
|
|
oCell.setIsDirty(true);
|
|
}
|
|
});
|
|
|
|
AscCommonExcel.importRangeLinksState.startBuildImportRangeLinks = false;
|
|
|
|
this._foreachChanged(function (oCell) {
|
|
if (oCell) {
|
|
oCell._checkDirty();
|
|
if (oCell.formulaParsed && AscCommonExcel.bIsSupportDynamicArrays && (oCell.formulaParsed.getDynamicRef() || oCell.formulaParsed.getArrayFormulaRef()) && oCell.formulaParsed.aca && oCell.formulaParsed.ca) {
|
|
t.addToVolatileArrays(oCell.formulaParsed);
|
|
}
|
|
// Enable calculating formula for next cell in chain
|
|
const oFormulaParsed = oCell.getFormulaParsed();
|
|
if (g_cCalcRecursion.getIsEnabledRecursion() && oCell.isFormula() && oFormulaParsed.ca === true) {
|
|
const nThisCellIndex = getCellIndex(oCell.nRow, oCell.nCol);
|
|
const sCellWsName = oCell.ws.getName().toLowerCase();
|
|
const aRecursiveCells = g_cCalcRecursion.getRecursiveCells(oCell);
|
|
let bLinkedCell = aRecursiveCells.some(function (oCellIndex) {
|
|
return oCellIndex.cellId === nThisCellIndex && oCellIndex.wsName === sCellWsName;
|
|
});
|
|
if (aRecursiveCells.length && bLinkedCell) {
|
|
oCell.changeLinkedCell(function (oCell) {
|
|
const oFormulaParsed = oCell.getFormulaParsed();
|
|
const nCellIndex = getCellIndex(oCell.nRow, oCell.nCol);
|
|
const sCellWsName = oCell.ws.getName().toLowerCase();
|
|
let bLinkedCell = aRecursiveCells.some(function (oCellIndex) {
|
|
return oCellIndex.cellId === nCellIndex && oCellIndex.wsName === sCellWsName;
|
|
});
|
|
if (bLinkedCell && oFormulaParsed.ca === true && !oCell.getIsDirty()) {
|
|
oCell.setIsDirty(true);
|
|
}
|
|
}, false);
|
|
g_cCalcRecursion.calcDiffBetweenIter(oCell);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (g_cCalcRecursion.getCycleCells().length && g_cCalcRecursion.getShowCycleWarn()) {
|
|
const oApi = Asc.editor;
|
|
oApi.sendEvent("asc_onError", c_oAscError.ID.CircularReference, c_oAscError.Level.NoCritical);
|
|
g_cCalcRecursion.setShowCycleWarn(false);
|
|
}
|
|
if (!g_cCalcRecursion.getCycleCells().length && !g_cCalcRecursion.getShowCycleWarn()) {
|
|
g_cCalcRecursion.setShowCycleWarn(true);
|
|
}
|
|
|
|
if (AscCommonExcel.importRangeLinksState.importRangeLinks) {
|
|
//need update
|
|
|
|
let needUpdateExternalReference = [];
|
|
let newExternalReferences = [];
|
|
for (let i in AscCommonExcel.importRangeLinksState.importRangeLinks) {
|
|
let newExternalReference = new AscCommonExcel.ExternalReference();
|
|
//newExternalReference.referenceData = referenceData;
|
|
newExternalReference.Id = i;
|
|
|
|
for (var j = 0; j < AscCommonExcel.importRangeLinksState.importRangeLinks[i].length; j++) {
|
|
let newSheet = AscCommonExcel.importRangeLinksState.importRangeLinks[i][j].sheet;
|
|
newExternalReference.addSheetName(newSheet, true);
|
|
newExternalReference.initWorksheetFromSheetDataSet(newSheet);
|
|
|
|
let ws = newExternalReference.worksheets[newSheet];
|
|
|
|
newExternalReference.initRows(ws.getRange2(AscCommonExcel.importRangeLinksState.importRangeLinks[i][j].range));
|
|
}
|
|
|
|
newExternalReference.notUpdateId = true;
|
|
|
|
newExternalReferences.push(newExternalReference);
|
|
needUpdateExternalReference.push(newExternalReference.getAscLink())
|
|
}
|
|
|
|
AscCommonExcel.importRangeLinksState.importRangeLinks = null;
|
|
|
|
this.wb.addExternalReferences(newExternalReferences);
|
|
|
|
|
|
this.wb.dependencyFormulas.lockRecal();
|
|
let t = this;
|
|
this.wb.oApi.asc_updateExternalReferences(needUpdateExternalReference, function () {
|
|
t.wb.dependencyFormulas.unlockRecal(true);
|
|
|
|
//needUpdateCells
|
|
for (let i = 0; i < needUpdateCells.length; i++) {
|
|
t.wb.dependencyFormulas.addToChangedCell(needUpdateCells[i]);
|
|
}
|
|
t.wb.sortDependency();
|
|
AscCommonExcel.importRangeLinksState.startBuildImportRangeLinks = null;
|
|
|
|
|
|
t.wb.drawWorksheet();
|
|
});
|
|
} else {
|
|
AscCommonExcel.importRangeLinksState.startBuildImportRangeLinks = null;
|
|
}
|
|
},
|
|
_foreachChanged: function(callback) {
|
|
var sheetId, changedSheet, ws, bbox;
|
|
for (sheetId in this.changedCell) {
|
|
if (this.changedCell.hasOwnProperty(sheetId)) {
|
|
changedSheet = this.changedCell[sheetId];
|
|
ws = this.wb.getWorksheetById(sheetId);
|
|
if (changedSheet && ws) {
|
|
for (var cellIndex in changedSheet) {
|
|
if (changedSheet.hasOwnProperty(cellIndex)) {
|
|
getFromCellIndex(cellIndex);
|
|
ws._getCell(g_FCI.row, g_FCI.col, callback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (sheetId in this.changedRange) {
|
|
if (this.changedRange.hasOwnProperty(sheetId)) {
|
|
changedSheet = this.changedRange[sheetId];
|
|
ws = this.wb.getWorksheetById(sheetId);
|
|
if (changedSheet && ws) {
|
|
for (var name in changedSheet) {
|
|
if (changedSheet.hasOwnProperty(name)) {
|
|
bbox = changedSheet[name];
|
|
ws.getRange3(bbox.r1, bbox.c1, bbox.r2, bbox.c2)._foreachNoEmpty(callback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_shiftMoveDelete: function(notifyType, sheetId, bbox, offset, sheetIdTo, isTableCreated) {
|
|
var listeners = {};
|
|
var res = {changed: listeners, shiftedShared: {}};
|
|
var sheetContainer = this.sheetListeners[sheetId];
|
|
if (sheetContainer) {
|
|
var bboxShift;
|
|
if (c_oNotifyType.Shift === notifyType) {
|
|
var bHor = 0 !== offset.col;
|
|
bboxShift = AscCommonExcel.shiftGetBBox(bbox, bHor);
|
|
}
|
|
var isIntersect;
|
|
for (var cellIndex in sheetContainer.cellMap) {
|
|
getFromCellIndex(cellIndex);
|
|
if (c_oNotifyType.Shift === notifyType) {
|
|
isIntersect = bboxShift.contains(g_FCI.col, g_FCI.row);
|
|
} else {
|
|
isIntersect = bbox.contains(g_FCI.col, g_FCI.row);
|
|
}
|
|
if (isIntersect) {
|
|
var cellMapElem = sheetContainer.cellMap[cellIndex];
|
|
for (var listenerId in cellMapElem.listeners) {
|
|
listeners[listenerId] = cellMapElem.listeners[listenerId];
|
|
}
|
|
}
|
|
}
|
|
for (var areaIndex in sheetContainer.areaMap) {
|
|
var areaMapElem = sheetContainer.areaMap[areaIndex];
|
|
if (c_oNotifyType.Shift === notifyType) {
|
|
isIntersect = bboxShift.isIntersect(areaMapElem.bbox);
|
|
} else if (c_oNotifyType.Move === notifyType || c_oNotifyType.Delete === notifyType) {
|
|
isIntersect = bbox.isIntersect(areaMapElem.bbox);
|
|
}
|
|
if (isIntersect) {
|
|
for (var listenerId in areaMapElem.listeners) {
|
|
listeners[listenerId] = areaMapElem.listeners[listenerId];
|
|
}
|
|
}
|
|
}
|
|
var notifyData = {
|
|
type: notifyType, sheetId: sheetId, sheetIdTo: sheetIdTo, bbox: bbox, offset: offset, shiftedShared: res.shiftedShared, isTableCreated: isTableCreated
|
|
};
|
|
for (var listenerId in listeners) {
|
|
listeners[listenerId].notify(notifyData);
|
|
}
|
|
}
|
|
return res;
|
|
},
|
|
_broadcastCellsByCells: function(sheetContainer, cellsChanged, notifyData) {
|
|
var cells = sheetContainer.cells;
|
|
var indexCell = 0;
|
|
var indexCellChanged = 0;
|
|
var row, col, rowChanged, colChanged;
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell].cellIndex);
|
|
row = g_FCI.row;
|
|
col = g_FCI.col;
|
|
}
|
|
if (indexCellChanged < cellsChanged.length) {
|
|
getFromCellIndex(cellsChanged[indexCellChanged]);
|
|
rowChanged = g_FCI.row;
|
|
colChanged = g_FCI.col;
|
|
}
|
|
while (indexCell < cells.length && indexCellChanged < cellsChanged.length) {
|
|
var cmp = Asc.Range.prototype.compareCell(col, row, colChanged, rowChanged);
|
|
if (cmp > 0) {
|
|
indexCellChanged++;
|
|
if (indexCellChanged < cellsChanged.length) {
|
|
getFromCellIndex(cellsChanged[indexCellChanged]);
|
|
rowChanged = g_FCI.row;
|
|
colChanged = g_FCI.col;
|
|
}
|
|
} else {
|
|
if (0 === cmp) {
|
|
this._broadcastNotifyListeners(cells[indexCell].listeners, notifyData);
|
|
}
|
|
indexCell++;
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell].cellIndex);
|
|
row = g_FCI.row;
|
|
col = g_FCI.col;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_broadcastRangesByCells: function(sheetContainer, cells, notifyData) {
|
|
if (0 === sheetContainer.rangesTopFrom.length || 0 === cells.length) {
|
|
return;
|
|
}
|
|
let t = this;
|
|
let rangesTopFrom = sheetContainer.rangesTopFrom;
|
|
let rangesTopFromIndex = 0;
|
|
let rangesTopTo = sheetContainer.rangesTopTo;
|
|
let rangesTopToIndex = 0;
|
|
let rangesBottomFrom = sheetContainer.rangesBottomFrom;
|
|
let rangesBottomFromIndex = 0;
|
|
let rangesBottomTo = sheetContainer.rangesBottomTo;
|
|
let rangesBottomToIndex = 0;
|
|
|
|
var indexCell = 0;
|
|
let helper = new BroadcastHelper();
|
|
var affected = [];
|
|
var curY, curYCell = -1, elem;
|
|
function skipRowHead(col) {
|
|
while (curYCell === g_FCI.row && g_FCI.col < col) {
|
|
indexCell++;
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell]);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
function skipRowTail() {
|
|
while (curYCell === g_FCI.row) {
|
|
indexCell++;
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell]);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let processCellsBeforeCurY = function (_curY) {
|
|
while (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell]);
|
|
if (g_FCI.row <= _curY) {
|
|
if (g_FCI.row > curYCell) {
|
|
helper.nextRow();
|
|
curYCell = g_FCI.row;
|
|
if (g_FCI.col < helper.from) {
|
|
skipRowHead(helper.from);
|
|
continue;
|
|
} else if (helper.to < g_FCI.col) {
|
|
skipRowTail();
|
|
continue;
|
|
}
|
|
}
|
|
if (g_FCI.col < helper.curFrom) {
|
|
indexCell++;
|
|
} else if (helper.curFrom <= g_FCI.col && g_FCI.col <= helper.curTo) {
|
|
for (let i = 0; i < helper.curElemsLen; ++i) {
|
|
let elem = helper.curElems[i];
|
|
if (elem) {
|
|
t._broadcastShared(elem, helper, affected, null, g_FCI.row, g_FCI.col);
|
|
}
|
|
}
|
|
indexCell++;
|
|
} else {
|
|
//todo bin search?
|
|
if (!helper.next()) {
|
|
skipRowTail();
|
|
}
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
helper.finishDelete();
|
|
}
|
|
//scanline by Y
|
|
while (rangesBottomFromIndex < rangesBottomFrom.length && indexCell < cells.length) {
|
|
//next curY
|
|
if (rangesTopFromIndex < rangesTopFrom.length) {
|
|
curY = Math.min(rangesTopFrom[rangesTopFromIndex].bbox.r1, rangesBottomFrom[rangesBottomFromIndex].bbox.r2);
|
|
} else {
|
|
curY = rangesBottomFrom[rangesBottomFromIndex].bbox.r2;
|
|
}
|
|
//process cells before curY
|
|
processCellsBeforeCurY(curY-1);
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell]);
|
|
}
|
|
//insert new ranges
|
|
rangesTopFromIndex = helper.addInsertByRow(curY, g_FCI.row, rangesTopFrom, rangesTopFromIndex, helper.addInsertFrom);
|
|
rangesTopToIndex = helper.addInsertByRow(curY, g_FCI.row, rangesTopTo, rangesTopToIndex, helper.addInsertTo);
|
|
helper.finishInsert();
|
|
//process cells curY
|
|
processCellsBeforeCurY(curY);
|
|
//delete ranges before move to new curY
|
|
rangesBottomFromIndex = helper.addDeleteByRow(curY, rangesBottomFrom, rangesBottomFromIndex, helper.addDeleteFrom);
|
|
rangesBottomToIndex = helper.addDeleteByRow(curY, rangesBottomTo, rangesBottomToIndex, helper.addDeleteTo);
|
|
helper.finishDelete();
|
|
}
|
|
this._broadcastNotifyRanges(affected, notifyData);
|
|
},
|
|
_broadcastCellsByRanges: function(sheetContainer, rangesTopFrom, rangesTopTo, rangesBottomFrom, rangesBottomTo, notifyData) {
|
|
if (0 === sheetContainer.cells.length || 0 === rangesTopFrom.length) {
|
|
return;
|
|
}
|
|
let t = this;
|
|
var cells = sheetContainer.cells;
|
|
let rangesTopFromIndex = 0;
|
|
let rangesTopToIndex = 0;
|
|
let rangesBottomFromIndex = 0;
|
|
let rangesBottomToIndex = 0;
|
|
var indexCell = 0;
|
|
let helper = new BroadcastHelper();
|
|
var curY, curYCell = -1, elem, bbox;
|
|
let skipRowHead = function(col) {
|
|
while (curYCell === g_FCI.row && g_FCI.col < col) {
|
|
indexCell++;
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell]);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let skipRowTail = function() {
|
|
while (curYCell === g_FCI.row) {
|
|
indexCell++;
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell]);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let processCellsBeforeCurY = function (_curY) {
|
|
while (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell].cellIndex);
|
|
if (g_FCI.row <= _curY) {
|
|
if (g_FCI.row > curYCell) {
|
|
helper.nextRow();
|
|
curYCell = g_FCI.row;
|
|
if (g_FCI.col < helper.from) {
|
|
skipRowHead(helper.from);
|
|
continue;
|
|
} else if (helper.to < g_FCI.col) {
|
|
skipRowTail();
|
|
continue;
|
|
}
|
|
}
|
|
if (g_FCI.col < helper.curFrom) {
|
|
indexCell++;
|
|
} else if (helper.curFrom <= g_FCI.col && g_FCI.col <= helper.curTo) {
|
|
t._broadcastNotifyListeners(cells[indexCell].listeners, notifyData);
|
|
indexCell++;
|
|
} else {
|
|
//todo bin search?
|
|
if (!helper.next()) {
|
|
skipRowTail();
|
|
}
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//scanline by Y
|
|
while (rangesBottomFromIndex < rangesBottomFrom.length && indexCell < cells.length) {
|
|
//next curY
|
|
if (rangesTopFromIndex < rangesTopFrom.length) {
|
|
curY = Math.min(rangesTopFrom[rangesTopFromIndex].bbox.r1, rangesBottomFrom[rangesBottomFromIndex].bbox.r2);
|
|
} else {
|
|
curY = rangesBottomFrom[rangesBottomFromIndex].bbox.r2;
|
|
}
|
|
//process cells before curY
|
|
processCellsBeforeCurY(curY - 1);
|
|
if (indexCell < cells.length) {
|
|
getFromCellIndex(cells[indexCell].cellIndex);
|
|
}
|
|
//insert new ranges
|
|
rangesTopFromIndex = helper.addInsertByRow(curY, g_FCI.row, rangesTopFrom, rangesTopFromIndex, helper.addInsertFrom);
|
|
rangesTopToIndex = helper.addInsertByRow(curY, g_FCI.row, rangesTopTo, rangesTopToIndex, helper.addInsertTo);
|
|
helper.finishInsert();
|
|
//process cells curY
|
|
processCellsBeforeCurY(curY);
|
|
//delete ranges before move to new curY
|
|
rangesBottomFromIndex = helper.addDeleteByRow(curY, rangesBottomFrom, rangesBottomFromIndex, helper.addDeleteFrom);
|
|
rangesBottomToIndex = helper.addDeleteByRow(curY, rangesBottomTo, rangesBottomToIndex, helper.addDeleteTo);
|
|
helper.finishDelete();
|
|
}
|
|
},
|
|
_broadcastRangesByRanges: function(sheetContainer, rangesTopFromChanged, rangesTopToChanged, rangesBottomFromChanged, rangesBottomToChanged, notifyData) {
|
|
if (0 === sheetContainer.rangesTopFrom.length || 0 === rangesTopFromChanged.length) {
|
|
return;
|
|
}
|
|
let t = this;
|
|
let rangesTopFrom = sheetContainer.rangesTopFrom;
|
|
let rangesTopFromIndex = 0;
|
|
let rangesTopTo = sheetContainer.rangesTopTo;
|
|
let rangesTopToIndex = 0;
|
|
let rangesBottomFrom = sheetContainer.rangesBottomFrom;
|
|
let rangesBottomFromIndex = 0;
|
|
let rangesBottomTo = sheetContainer.rangesBottomTo;
|
|
let rangesBottomToIndex = 0;
|
|
let rangesTopFromChangedIndex = 0;
|
|
let rangesTopToChangedIndex = 0;
|
|
let rangesBottomFromChangedIndex = 0;
|
|
let rangesBottomToChangedIndex = 0;
|
|
let helper = new BroadcastHelper();
|
|
let helperChanged = new BroadcastHelper();
|
|
var affected = [];
|
|
var curY;
|
|
|
|
//scanline by Y
|
|
while (rangesBottomFromIndex < rangesBottomFrom.length && rangesBottomFromChangedIndex < rangesBottomFromChanged.length) {
|
|
//next curY
|
|
curY = Math.min(rangesBottomFromChanged[rangesBottomFromChangedIndex].bbox.r2, rangesBottomFrom[rangesBottomFromIndex].bbox.r2);
|
|
let curYTop = -1;
|
|
if (rangesTopFromIndex < rangesTopFrom.length) {
|
|
curYTop = rangesTopFrom[rangesTopFromIndex].bbox.r1;
|
|
curY = Math.min(curY, curYTop);
|
|
}
|
|
let curYTopChanged = -1;
|
|
if (rangesTopFromChangedIndex < rangesTopFromChanged.length) {
|
|
curYTopChanged = rangesTopFromChanged[rangesTopFromChangedIndex].bbox.r1;
|
|
curY = Math.min(curY, curYTopChanged);
|
|
}
|
|
let eventsCountOld = helper.getRowEventsCount();
|
|
let eventsCountOldChanged = helperChanged.getRowEventsCount();
|
|
//insert new ranges
|
|
rangesTopFromIndex = helper.addInsertByRow(curY, eventsCountOldChanged ? curY : curYTopChanged, rangesTopFrom, rangesTopFromIndex, helper.addInsertFrom);
|
|
rangesTopToIndex = helper.addInsertByRow(curY, eventsCountOldChanged ? curY : curYTopChanged, rangesTopTo, rangesTopToIndex, helper.addInsertTo);
|
|
helper.finishInsert();
|
|
rangesTopFromChangedIndex = helperChanged.addInsertByRow(curY, eventsCountOld ? curY : curYTop, rangesTopFromChanged, rangesTopFromChangedIndex, helper.addInsertFrom);
|
|
rangesTopToChangedIndex = helperChanged.addInsertByRow(curY, eventsCountOld ? curY : curYTop, rangesTopToChanged, rangesTopToChangedIndex, helper.addInsertTo);
|
|
helperChanged.finishInsert();
|
|
//intersect
|
|
if ((eventsCountOld !== helper.getRowEventsCount() || eventsCountOldChanged !== helperChanged.getRowEventsCount()) &&
|
|
!(helper.to < helperChanged.from || helperChanged.to < helper.from))
|
|
{
|
|
helper.nextRow();
|
|
helper.next();
|
|
helperChanged.nextRow();
|
|
helperChanged.next();
|
|
while (true) {
|
|
if (!(helperChanged.curTo < helper.curFrom || helper.curTo < helperChanged.curFrom)) {
|
|
for (let i = 0; i < helper.curElemsLen; ++i) {
|
|
let elem = helper.curElems[i];
|
|
if (elem) {
|
|
for (let j = 0; j < helperChanged.curElemsLen; ++j) {
|
|
let elemChanged = helperChanged.curElems[j];
|
|
if (elemChanged) {
|
|
var intersect = elem.bbox.intersectionSimple(elemChanged.bbox);
|
|
t._broadcastShared(elem, helper, affected, intersect, null, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (helper.curTo < helperChanged.curTo) {
|
|
if (!helper.next()) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (!helperChanged.next()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
helper.finishDelete();
|
|
}
|
|
//delete ranges before move to new curY
|
|
rangesBottomFromIndex = helper.addDeleteByRow(curY, rangesBottomFrom, rangesBottomFromIndex, helper.addDeleteFrom);
|
|
rangesBottomToIndex = helper.addDeleteByRow(curY, rangesBottomTo, rangesBottomToIndex, helper.addDeleteTo);
|
|
helper.finishDelete();
|
|
rangesBottomFromChangedIndex = helperChanged.addDeleteByRow(curY, rangesBottomFromChanged, rangesBottomFromChangedIndex, helper.addDeleteFrom);
|
|
rangesBottomToChangedIndex = helperChanged.addDeleteByRow(curY, rangesBottomToChanged, rangesBottomToChangedIndex, helper.addDeleteTo);
|
|
helperChanged.finishDelete();
|
|
}
|
|
this._broadcastNotifyRanges(affected, notifyData);
|
|
},
|
|
_broadcastShared: function(elem, helper, affected, intersect, row, col) {
|
|
var sharedBroadcast = elem.sharedBroadcast;
|
|
if (!sharedBroadcast) {
|
|
if (elem.isActive) {
|
|
affected.push(elem);
|
|
elem.isActive = false;
|
|
helper.addDeleteFrom(elem);
|
|
helper.addDeleteToUnsorted(elem);
|
|
}
|
|
} else if (!sharedBroadcast.changedBBox ||
|
|
!(intersect && sharedBroadcast.changedBBox.containsRange(intersect)) ||
|
|
!(!intersect && sharedBroadcast.changedBBox.contains(col, row)))
|
|
{
|
|
if (!sharedBroadcast.changedBBox ||
|
|
sharedBroadcast.changedBBox.isEqual(sharedBroadcast.prevChangedBBox)) {
|
|
sharedBroadcast.recursion++;
|
|
if (sharedBroadcast.recursion >= this.maxSharedRecursion) {
|
|
sharedBroadcast.changedBBox = elem.bbox.clone();
|
|
}
|
|
affected.push(elem);
|
|
}
|
|
if (intersect) {
|
|
if (sharedBroadcast.changedBBox) {
|
|
sharedBroadcast.changedBBox.union2(intersect);
|
|
} else {
|
|
sharedBroadcast.changedBBox = intersect.clone();
|
|
}
|
|
} else {
|
|
if (sharedBroadcast.changedBBox) {
|
|
sharedBroadcast.changedBBox.union3(col, row);
|
|
} else {
|
|
sharedBroadcast.changedBBox = new Asc.Range(col, row, col, row);
|
|
}
|
|
}
|
|
if (sharedBroadcast.changedBBox.isEqual(elem.bbox)) {
|
|
if (elem.isActive) {
|
|
elem.isActive = false;
|
|
helper.addDeleteFrom(elem);
|
|
helper.addDeleteToUnsorted(elem);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_broadcastRangesByRangesIntersect: function(bbox, tree, output) {
|
|
var intervals = tree.searchNodes(bbox.c1, bbox.c2);
|
|
for(var i = 0; i < intervals.length; ++i){
|
|
var interval = intervals[i];
|
|
var elem = interval.data;
|
|
if (elem) {
|
|
var intersect = elem.bbox.intersectionSimple(bbox);
|
|
var sharedBroadcast = elem.sharedBroadcast;
|
|
if (!sharedBroadcast) {
|
|
output.push(elem);
|
|
elem.isActive = false;
|
|
tree.remove(elem.bbox.c1, elem.bbox.c2, elem);
|
|
} else if (!(sharedBroadcast.changedBBox && sharedBroadcast.changedBBox.containsRange(intersect))) {
|
|
if (!sharedBroadcast.changedBBox ||
|
|
sharedBroadcast.changedBBox.isEqual(sharedBroadcast.prevChangedBBox)) {
|
|
sharedBroadcast.recursion++;
|
|
if (sharedBroadcast.recursion >= this.maxSharedRecursion) {
|
|
sharedBroadcast.changedBBox = elem.bbox.clone();
|
|
}
|
|
output.push(elem);
|
|
}
|
|
if (sharedBroadcast.changedBBox) {
|
|
sharedBroadcast.changedBBox.union2(intersect);
|
|
} else {
|
|
sharedBroadcast.changedBBox = intersect;
|
|
}
|
|
if (sharedBroadcast.changedBBox.isEqual(elem.bbox)) {
|
|
elem.isActive = false;
|
|
tree.remove(elem.bbox.c1, elem.bbox.c2, elem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_broadcastNotifyRanges: function(affected, notifyData) {
|
|
var areaData = {bbox: null, changedBBox: null};
|
|
for (var i = 0; i < affected.length; ++i) {
|
|
var elem = affected[i];
|
|
var shared = elem.sharedBroadcast;
|
|
if (shared && shared.changedBBox) {
|
|
areaData.bbox = elem.bbox;
|
|
notifyData.areaData = areaData;
|
|
if (!shared.prevChangedBBox) {
|
|
areaData.changedBBox = shared.changedBBox;
|
|
this._broadcastNotifyListeners(elem.listeners, notifyData);
|
|
} else {
|
|
var ranges = shared.prevChangedBBox.difference(shared.changedBBox);
|
|
for (var j = 0; j < ranges.length; ++j) {
|
|
areaData.changedBBox = ranges[j];
|
|
this._broadcastNotifyListeners(elem.listeners, notifyData);
|
|
}
|
|
}
|
|
notifyData.areaData = undefined;
|
|
shared.prevChangedBBox = shared.changedBBox.clone();
|
|
} else {
|
|
this._broadcastNotifyListeners(elem.listeners, notifyData);
|
|
}
|
|
}
|
|
this.tempGetByCells.push(affected);
|
|
},
|
|
_broadcastNotifyListeners: function(listeners, notifyData) {
|
|
for (var listenerId in listeners) {
|
|
listeners[listenerId].notify(notifyData);
|
|
}
|
|
}
|
|
};
|
|
|
|
function BroadcastHelper() {
|
|
this.curElems = [];
|
|
this.curElemsLen = 0;
|
|
this.curElemsCount = 0;
|
|
this.curFrom = -1;
|
|
this.curTo = -1;
|
|
this.from = -1;
|
|
this.to = -1;
|
|
|
|
//many arrays to avoid temp objects
|
|
this.eventsFrom = [];
|
|
this.eventsFromIndex = 0;
|
|
this.eventsFromLen = 0;
|
|
this.eventsTo = [];
|
|
this.eventsToIndex = 0;
|
|
this.eventsToLen = 0;
|
|
|
|
this.insertFrom = [];
|
|
this.insertFromLen = 0;
|
|
this.insertTo = [];
|
|
this.insertToLen = 0;
|
|
|
|
this.deleteFrom = [];
|
|
this.deleteFromLen = 0;
|
|
this.deleteTo = [];
|
|
this.deleteToLen = 0;
|
|
this.deleteToUnsorted = [];
|
|
this.deleteToUnsortedLen = 0;
|
|
}
|
|
BroadcastHelper.prototype.getRowEventsCount = function () {
|
|
return this.eventsFromLen;
|
|
};
|
|
BroadcastHelper.prototype.nextRow = function () {
|
|
this.curElemsLen = 0;
|
|
this.curElemsCount = 0;
|
|
this.curFrom = -1;
|
|
this.curTo = -1;
|
|
this.from = this.eventsFromLen > 0 ? this.eventsFrom[0].bbox.c1 : -1;
|
|
this.to = this.eventsToLen > 0 ? this.eventsTo[this.eventsToLen - 1].bbox.c2 : -1;
|
|
this.eventsFromIndex = 0;
|
|
this.eventsToIndex = 0;
|
|
};
|
|
BroadcastHelper.prototype._getNextTo = function () {
|
|
if (this.eventsToIndex < this.eventsToLen) {
|
|
let elem = this.eventsTo[this.eventsToIndex];
|
|
if (this.eventsFromIndex < this.eventsFromLen && this.eventsFrom[this.eventsFromIndex].bbox.c1 <= elem.bbox.c2) {
|
|
elem = this.eventsFrom[this.eventsFromIndex];
|
|
return elem.bbox.c1 - 1;
|
|
} else {
|
|
return elem.bbox.c2;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
BroadcastHelper.prototype.next = function () {
|
|
if (this.eventsToIndex < this.eventsToLen) {
|
|
let elem = this.eventsTo[this.eventsToIndex];
|
|
if (this.eventsFromIndex < this.eventsFromLen && this.eventsFrom[this.eventsFromIndex].bbox.c1 <= elem.bbox.c2) {
|
|
elem = this.eventsFrom[this.eventsFromIndex];
|
|
this.curFrom = elem.bbox.c1;
|
|
while (this.eventsFromIndex < this.eventsFromLen && this.eventsFrom[this.eventsFromIndex].bbox.c1 === elem.bbox.c1) {
|
|
elem = this.eventsFrom[this.eventsFromIndex];
|
|
elem.index = this.curElemsLen;
|
|
this.curElems[this.curElemsLen] = elem;
|
|
this.curElemsCount++;
|
|
this.curElemsLen++;
|
|
this.eventsFromIndex++;
|
|
}
|
|
this.curTo = this._getNextTo();
|
|
return true;
|
|
} else {
|
|
while (this.eventsToIndex < this.eventsToLen && this.eventsTo[this.eventsToIndex].bbox.c2 === elem.bbox.c2) {
|
|
elem = this.eventsTo[this.eventsToIndex];
|
|
//todo decrement this.curElemsLen too
|
|
this.curElems[elem.index] = undefined;
|
|
this.curElemsCount--;
|
|
this.eventsToIndex++;
|
|
}
|
|
if (this.eventsToIndex < this.eventsToLen) {
|
|
//skip empty space
|
|
if (0 === this.curElemsCount) {
|
|
return this.next();
|
|
}
|
|
this.curFrom = elem.bbox.c2 + 1;
|
|
this.curTo = this._getNextTo();
|
|
return true;
|
|
} else {
|
|
this.curFrom = this.curTo = -1;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
BroadcastHelper.prototype.cmpInsertFrom = function (a, b) {
|
|
return Asc.Range.prototype.compareByLeftTop(a.bbox, b.bbox);
|
|
};
|
|
BroadcastHelper.prototype.cmpInsertTo = function (a, b) {
|
|
return Asc.Range.prototype.compareByRightTop(a.bbox, b.bbox);
|
|
};
|
|
BroadcastHelper.prototype.cmpDeleteFrom = function (a, b) {
|
|
return Asc.Range.prototype.compareByLeftBottom(a.bbox, b.bbox) || Asc.Range.prototype.compareByLeftTop(a.bbox, b.bbox);
|
|
};
|
|
BroadcastHelper.prototype.cmpDeleteTo = function (a, b) {
|
|
return Asc.Range.prototype.compareByRightBottom(a.bbox, b.bbox) || Asc.Range.prototype.compareByRightTop(a.bbox, b.bbox);
|
|
};
|
|
BroadcastHelper.prototype._cmpC1 = function (a, b) {
|
|
return a.bbox.c1 <= b.bbox.c1;
|
|
};
|
|
BroadcastHelper.prototype._cmpC2 = function (a, b) {
|
|
return a.bbox.c2 <= b.bbox.c2;
|
|
};
|
|
BroadcastHelper.prototype.addInsertFrom = function (elem) {
|
|
//elem.bbox & elem.id & elem.isActive
|
|
this.insertFrom[this.insertFromLen] = elem;
|
|
this.insertFromLen++;
|
|
};
|
|
BroadcastHelper.prototype.addInsertTo = function (elem) {
|
|
//elem.bbox & elem.id
|
|
this.insertTo[this.insertToLen] = elem;
|
|
this.insertToLen++;
|
|
};
|
|
BroadcastHelper.prototype.addInsertByRow = function (row, minRow, sorted, sortedIndex, fInsert) {
|
|
while (sortedIndex < sorted.length && row === sorted[sortedIndex].bbox.r1) {
|
|
let elem = sorted[sortedIndex];
|
|
sortedIndex++;
|
|
if (false !== elem.isActive && minRow <= elem.bbox.r2) {
|
|
fInsert.call(this, elem);
|
|
}
|
|
}
|
|
return sortedIndex;
|
|
}
|
|
BroadcastHelper.prototype._mergeInsertSorted = function (events, eventsLen, ins, insLen, fCmp) {
|
|
let eventsIndex = eventsLen - 1;
|
|
let insIndex = insLen - 1;
|
|
let eventsInsertIndex = eventsIndex + insLen;
|
|
while (insIndex >= 0) {
|
|
if (eventsIndex < 0 || fCmp(events[eventsIndex], ins[insIndex])) {
|
|
events[eventsInsertIndex] = ins[insIndex];
|
|
insIndex--;
|
|
} else {
|
|
events[eventsInsertIndex] = events[eventsIndex];
|
|
eventsIndex--;
|
|
}
|
|
eventsInsertIndex--;
|
|
}
|
|
return eventsLen + insLen;
|
|
};
|
|
BroadcastHelper.prototype.finishInsert = function () {
|
|
if (0 === this.insertFromLen && 0 === this.insertToLen) {
|
|
this.nextRow();
|
|
return;
|
|
}
|
|
this.eventsFromLen = this._mergeInsertSorted(this.eventsFrom, this.eventsFromLen, this.insertFrom, this.insertFromLen, this._cmpC1);
|
|
this.insertFromLen = 0;
|
|
this.eventsToLen = this._mergeInsertSorted(this.eventsTo, this.eventsToLen, this.insertTo, this.insertToLen, this._cmpC2);
|
|
this.insertToLen = 0;
|
|
|
|
this.nextRow();
|
|
};
|
|
BroadcastHelper.prototype.addDeleteFrom = function (elem) {
|
|
//elem.bbox & elem.id
|
|
this.deleteFrom[this.deleteFromLen] = elem;
|
|
this.deleteFromLen++;
|
|
};
|
|
BroadcastHelper.prototype.addDeleteTo = function (elem) {
|
|
this.deleteTo[this.deleteToLen] = elem;
|
|
this.deleteToLen++;
|
|
};
|
|
BroadcastHelper.prototype.addDeleteToUnsorted = function (elem) {
|
|
this.deleteToUnsorted[this.deleteToUnsortedLen] = elem;
|
|
this.deleteToUnsortedLen++;
|
|
};
|
|
BroadcastHelper.prototype.addDeleteByRow = function (row, sorted, sortedIndex, fDelete) {
|
|
while (sortedIndex < sorted.length && row === sorted[sortedIndex].bbox.r2) {
|
|
let elem = sorted[sortedIndex];
|
|
sortedIndex++;
|
|
if (false !== elem.isActive) {
|
|
fDelete.call(this, elem);
|
|
}
|
|
}
|
|
return sortedIndex;
|
|
}
|
|
BroadcastHelper.prototype._mergeDeleteSorted = function (events, eventsLen, del, delLen) {
|
|
//todo нельзя рассчитывать, что в addDelete будут приходить элементы из curElems и в порядке forEach(есть другие вызовы addDelete)
|
|
//The forEach() method executes per each pair in insertion order.
|
|
let eventsIndex = 0;
|
|
let delIndex = 0;
|
|
let eventsCurIndex = 0;
|
|
while (eventsIndex < eventsLen && delIndex < delLen) {
|
|
if (events[eventsIndex] !== del[delIndex]) {
|
|
events[eventsCurIndex] = events[eventsIndex];
|
|
eventsCurIndex++;
|
|
} else {
|
|
delIndex++;
|
|
}
|
|
eventsIndex++;
|
|
}
|
|
while (eventsIndex < eventsLen) {
|
|
events[eventsCurIndex] = events[eventsIndex];
|
|
eventsIndex++;
|
|
eventsCurIndex++;
|
|
}
|
|
return eventsCurIndex;
|
|
};
|
|
BroadcastHelper.prototype.finishDelete = function () {
|
|
if (0 === this.deleteFromLen && 0 === this.deleteToLen && 0 === this.deleteToUnsortedLen) {
|
|
this.nextRow();
|
|
return;
|
|
}
|
|
//deleteFrom,deleteTo - presorted; need sort deleteToUnsorted;
|
|
this.deleteToUnsorted.sort(this.cmpDeleteTo);
|
|
this.eventsFromLen = this._mergeDeleteSorted(this.eventsFrom, this.eventsFromLen, this.deleteFrom, this.deleteFromLen);
|
|
this.deleteFromLen = 0;
|
|
this.eventsToLen = this._mergeDeleteSorted(this.eventsTo, this.eventsToLen, this.deleteTo, this.deleteToLen);
|
|
this.deleteToLen = 0;
|
|
this.eventsToLen = this._mergeDeleteSorted(this.eventsTo, this.eventsToLen, this.deleteToUnsorted, this.deleteToUnsortedLen);
|
|
this.deleteToUnsortedLen = 0;
|
|
this.nextRow();
|
|
};
|
|
|
|
function AsyncFormulasManager(wb) {
|
|
this.wb = wb;
|
|
this.promises = null;
|
|
this.promiseMap = null;
|
|
this.calcProcess = null;
|
|
this.aParserFormulas = null;
|
|
|
|
this.replacedFormulas = null;
|
|
|
|
this.endCallback = null;
|
|
}
|
|
|
|
AsyncFormulasManager.prototype.addPromise = function (val, reWrite) {
|
|
if (!this.promises) {
|
|
this.promises = [];
|
|
}
|
|
let isAdded = false;
|
|
if (this.getPromiseByIndex(val.parserFormula._index, val.index)) {
|
|
isAdded = true;
|
|
}
|
|
if (!isAdded) {
|
|
this.promises.push(val);
|
|
if (!this.promiseMap) {
|
|
this.promiseMap = {};
|
|
}
|
|
if (!this.promiseMap[val.parserFormula._index]) {
|
|
this.promiseMap[val.parserFormula._index] = {};
|
|
}
|
|
this.promiseMap[val.parserFormula._index][val.index] = this.promises.length - 1;
|
|
} else if (reWrite) {
|
|
this.promises[this.promiseMap[val.parserFormula._index][val.index]] = val;
|
|
}
|
|
};
|
|
AsyncFormulasManager.prototype.getPromiseByIndex = function (indexParserFormula, stackIndex) {
|
|
let indexArray = this.promiseMap && this.promiseMap[indexParserFormula] && this.promiseMap[indexParserFormula][stackIndex];
|
|
if (indexArray != null && this.promises) {
|
|
return this.promises[indexArray];
|
|
}
|
|
return null;
|
|
};
|
|
AsyncFormulasManager.prototype.getPromise = function (index) {
|
|
return this.promises && this.promises[index];
|
|
};
|
|
AsyncFormulasManager.prototype.getPromises = function () {
|
|
return this.promises;
|
|
};
|
|
AsyncFormulasManager.prototype.isPromises = function () {
|
|
return this.promises && this.promises.length;
|
|
};
|
|
AsyncFormulasManager.prototype.clearPromises = function () {
|
|
this.promises = null;
|
|
this.promiseMap = null;
|
|
};
|
|
AsyncFormulasManager.prototype.getReplacedFormulas = function () {
|
|
return this.replacedFormulas;
|
|
};
|
|
AsyncFormulasManager.prototype.clearReplacedFormulas = function () {
|
|
this.replacedFormulas = null;
|
|
};
|
|
AsyncFormulasManager.prototype.isReplacedFormulas = function () {
|
|
return this.replacedFormulas && this.replacedFormulas.length;
|
|
};
|
|
AsyncFormulasManager.prototype.addReplacedFormula = function (val) {
|
|
if (!this.replacedFormulas) {
|
|
this.replacedFormulas = [];
|
|
}
|
|
this.replacedFormulas.push(val);
|
|
};
|
|
AsyncFormulasManager.prototype.setRecalculating = function (val) {
|
|
this.calcProcess = val;
|
|
};
|
|
AsyncFormulasManager.prototype.isRecalculating = function () {
|
|
return this.calcProcess;
|
|
};
|
|
AsyncFormulasManager.prototype.addPromiseParserFormula = function (elem) {
|
|
if (!this.aParserFormulas) {
|
|
this.aParserFormulas = [];
|
|
}
|
|
this.aParserFormulas.push(elem);
|
|
};
|
|
AsyncFormulasManager.prototype.cleanPromiseParserFormula = function () {
|
|
if (this.aParserFormulas) {
|
|
for (let i = 0; i < this.aParserFormulas.length; i++) {
|
|
this.aParserFormulas[i].promiseResult = null;
|
|
}
|
|
this.aParserFormulas = null;
|
|
}
|
|
};
|
|
AsyncFormulasManager.prototype.calculatePromises = function (callback) {
|
|
let t = this;
|
|
let promises = !this.isRecalculating() && this.getPromises();
|
|
if (promises) {
|
|
let doPromises = function (_promises) {
|
|
let streamInfos = [];
|
|
let fPromises = [];
|
|
for (let i = 0; i < _promises.length; i++) {
|
|
const fPromise = function () {
|
|
return _promises[i].promise;
|
|
};
|
|
fPromises.push(fPromise);
|
|
}
|
|
const promiseIterator = new AscCommon.CPromiseGetterIterator(fPromises);
|
|
promiseIterator.forEachValue(function (streamInfo) {
|
|
streamInfos.push(streamInfo);
|
|
}, function (rejectInfo) {
|
|
streamInfos.push(null);
|
|
}, function () {
|
|
for (let i = 0; i < streamInfos.length; i++) {
|
|
if (!_promises[i].parserFormula.promiseResult) {
|
|
_promises[i].parserFormula.promiseResult = [];
|
|
}
|
|
let resStreamInfo;
|
|
if (streamInfos[i] == null) {
|
|
resStreamInfo = new cError(cErrorType.wrong_value_type);
|
|
} else {
|
|
resStreamInfo = _promises[i].callback(streamInfos[i]);
|
|
}
|
|
_promises[i].parserFormula.promiseResult[_promises[i].index] = resStreamInfo;
|
|
if (_promises[i].parserFormula.parent) {
|
|
t.wb.dependencyFormulas.addToChangedCell(_promises[i].parserFormula.parent);
|
|
}
|
|
t.addPromiseParserFormula(_promises[i].parserFormula);
|
|
}
|
|
//t.wb.buildDependency();
|
|
//t.wb.sortDependency();
|
|
/*t._foreachChanged(function (oCell) {
|
|
oCell.setIsDirty(true);
|
|
oCell && oCell._checkDirty();
|
|
});*/
|
|
|
|
t.clearPromises();
|
|
t.setRecalculating(true);
|
|
t.wb.dependencyFormulas.calcTree();
|
|
t.wb.handlers && t.wb.handlers.trigger("drawWS");
|
|
/*for (let i = 0; i < streamInfos.length; i++) {
|
|
_promises[i].parserFormula.promiseResult = null;
|
|
}*/
|
|
t.setRecalculating(false);
|
|
|
|
promises = !t.isRecalculating() && t.getPromises();
|
|
if (promises) {
|
|
doPromises(promises);
|
|
} else {
|
|
t.cleanPromiseParserFormula();
|
|
t.endCallback && t.endCallback();
|
|
callback && callback();
|
|
}
|
|
});
|
|
};
|
|
doPromises(promises);
|
|
} else {
|
|
//t.endCallback && t.endCallback()
|
|
}
|
|
};
|
|
|
|
AsyncFormulasManager.prototype.calculateReplacedFormulas = function (callback) {
|
|
let t = this;
|
|
let replacedFormulas = /*!this.isRecalculating() &&*/ this.getReplacedFormulas();
|
|
if (replacedFormulas) {
|
|
let doReplacedFormulas = function (_replacedFormulas) {
|
|
for (let i = 0; i < _replacedFormulas.length; i++) {
|
|
t.wb.dependencyFormulas.addToChangedCell(_replacedFormulas[i].parent);
|
|
}
|
|
|
|
t.clearReplacedFormulas();
|
|
t.setRecalculating(true);
|
|
t.wb.dependencyFormulas.calcTree();
|
|
t.wb.handlers && t.wb.handlers.trigger("drawWS");
|
|
t.setRecalculating(false);
|
|
};
|
|
doReplacedFormulas(replacedFormulas);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {string} s1
|
|
* @param {string} s2
|
|
* @return {number}
|
|
*/
|
|
function stringCompare(s1, s2) {
|
|
if (s1 === s2) {
|
|
return 0;
|
|
}
|
|
return s1.localeCompare(s2, "en");
|
|
}
|
|
function ForwardTransformationFormula(elem, formula, parsed) {
|
|
this.elem = elem;
|
|
this.formula = formula;
|
|
this.parsed = parsed;
|
|
}
|
|
ForwardTransformationFormula.prototype = {
|
|
onFormulaEvent: function(type, eventData) {
|
|
if (AscCommon.c_oNotifyParentType.ChangeFormula === type) {
|
|
this.formula = eventData.assemble;
|
|
}
|
|
}
|
|
};
|
|
function angleFormatToInterface(val)
|
|
{
|
|
var nRes = 0;
|
|
if(0 <= val && val <= 180)
|
|
nRes = val <= 90 ? val : 90 - val;
|
|
return nRes;
|
|
}
|
|
function angleFormatToInterface2(val)
|
|
{
|
|
if(g_nVerticalTextAngle == val)
|
|
return val;
|
|
else
|
|
return angleFormatToInterface(val);
|
|
}
|
|
function angleInterfaceToFormat(val)
|
|
{
|
|
var nRes = val;
|
|
if(-90 <= val && val <= 90)
|
|
{
|
|
if(val < 0)
|
|
nRes = 90 - val;
|
|
}
|
|
else if(g_nVerticalTextAngle != val)
|
|
nRes = 0;
|
|
return nRes;
|
|
}
|
|
function getUniqueKeys(array) {
|
|
var i, o = {};
|
|
for (i = 0; i < array.length; ++i) {
|
|
o[array[i].v] = o.hasOwnProperty(array[i].v);
|
|
}
|
|
return o;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function Workbook(eventsHandlers, oApi, isMainLogicDocument){
|
|
this.oApi = oApi;
|
|
this.History = History;
|
|
if (false !== isMainLogicDocument)
|
|
{
|
|
if (this.History)
|
|
this.History.Set_LogicDocument(this);
|
|
}
|
|
this.MainDocument = false !== isMainLogicDocument;
|
|
this.handlers = eventsHandlers;
|
|
this.dependencyFormulas = new DependencyGraph(this);
|
|
this.asyncFormulasManager = new AsyncFormulasManager(this);
|
|
this.nActive = 0;
|
|
this.showVerticalScroll = null;
|
|
this.showHorizontalScroll = null;
|
|
this.App = null;
|
|
this.Core = null;
|
|
|
|
AscFormat.ExecuteNoHistory(function () {
|
|
this.CustomProperties = new AscCommon.CCustomProperties();
|
|
}, this, [], true);
|
|
|
|
this.theme = null;
|
|
this.clrSchemeMap = null;
|
|
|
|
this.CellStyles = new AscCommonExcel.CCellStyles();
|
|
this.TableStyles = new Asc.CTableStyles();
|
|
this.SlicerStyles = new Asc.CSlicerStyles();
|
|
this.oStyleManager = new AscCommonExcel.StyleManager();
|
|
this.sharedStrings = new AscCommonExcel.CSharedStrings();
|
|
this.workbookFormulas = new AscCommonExcel.CWorkbookFormulas();
|
|
this.loadCells = [];//to return one object when nested _getCell calls
|
|
this.DrawingDocument = new AscCommon.CDrawingDocument();
|
|
this.mathTrackHandler = new AscWord.CMathTrackHandler(this.DrawingDocument, oApi);
|
|
|
|
this.aComments = []; // Комментарии к документу
|
|
this.aWorksheets = [];
|
|
this.aWorksheetsById = {};
|
|
this.aCollaborativeActions = [];
|
|
this.bCollaborativeChanges = false;
|
|
this.bUndoChanges = false;
|
|
this.bRedoChanges = false;
|
|
this.aCollaborativeChangeElements = [];
|
|
this.externalReferences = [];
|
|
this.calcPr = new AscCommonExcel.CCalcPr();
|
|
this.workbookPr = new AscCommonExcel.CWorkbookPr();
|
|
|
|
this.connections = null;
|
|
|
|
this.wsHandlers = null;
|
|
|
|
this.openErrors = [];
|
|
|
|
this.maxDigitWidth = 0;
|
|
this.paddingPlusBorder = 0;
|
|
|
|
this.lastFindOptions = null;
|
|
this.lastFindCells = {};
|
|
this.oleSize = null;
|
|
if (oApi && oApi.frameManager.isOleEditor()) {
|
|
this.oleSize = new AscCommonExcel.OleSizeSelectionRange(null, new Asc.Range(0, 0, 6, 9));
|
|
}
|
|
|
|
//при копировании листа с одного wb на другой необходимо менять в стеке
|
|
// формул лист и книгу(на которые ссылаемся) - например у элементов cStrucTable
|
|
//временно добавляю новый вставляемый лист, чтобы не передавать параметры через большое количество функций
|
|
this.addingWorksheet = null;
|
|
|
|
this.workbookProtection = null;
|
|
this.fileSharing = null;
|
|
|
|
if (isMainLogicDocument) {
|
|
this.customXmlManager = new AscWord.CustomXmlManager(this);
|
|
} else {
|
|
AscFormat.ExecuteNoHistory(function () {
|
|
this.customXmlManager = new AscWord.CustomXmlManager(this);
|
|
}, this, [], true);
|
|
}
|
|
|
|
this.oGoalSeek = null;
|
|
this.oSolver = null;
|
|
|
|
this.timelineCaches = [];
|
|
this.TimelineStyles = null;
|
|
|
|
this.metadata = null;
|
|
//true - rightToLeft, false/null - leftToRight
|
|
this.defaultDirection = null;
|
|
|
|
this.externalReferenceHelper = new CExternalReferenceHelper(this);
|
|
|
|
this.fileCustomFunctions = null;
|
|
}
|
|
Workbook.prototype.init=function(oReadResult, bNoBuildDep, bSnapshot){
|
|
let tableCustomFunc = oReadResult.tableCustomFunc || {};
|
|
let tableIds = oReadResult.tableIds || {};
|
|
let sheetIds = oReadResult.sheetIds || {};
|
|
let pivotCaches = oReadResult.pivotCacheDefinitions || {};
|
|
if(this.nActive < 0)
|
|
this.nActive = 0;
|
|
if(this.nActive >= this.aWorksheets.length)
|
|
this.nActive = this.aWorksheets.length - 1;
|
|
|
|
var self = this;
|
|
|
|
this.wsHandlers = new AscCommonExcel.asc_CHandlersList( /*handlers*/{
|
|
"changeRefTablePart" : function (table) {
|
|
self.dependencyFormulas.changeTableRef(table);
|
|
},
|
|
"changeColumnTablePart": function ( tableName ) {
|
|
self.dependencyFormulas.renameTableColumn( tableName );
|
|
},
|
|
"deleteColumnTablePart": function(tableName, deleted) {
|
|
self.dependencyFormulas.delColumnTable(tableName, deleted);
|
|
var wsActive = self.getActiveWs();
|
|
if (wsActive) {
|
|
wsActive.deleteSlicersByTableCol(tableName, deleted);
|
|
}
|
|
}, 'onFilterInfo' : function () {
|
|
self.handlers && self.handlers.trigger("asc_onFilterInfo");
|
|
}
|
|
} );
|
|
for(var i = 0, length = tableCustomFunc.length; i < length; ++i) {
|
|
var elem = tableCustomFunc[i];
|
|
elem.column.applyTotalRowFormula(elem.formula, elem.ws, !bNoBuildDep);
|
|
}
|
|
//ws
|
|
this.forEach(function (ws) {
|
|
ws.initPostOpen(self.wsHandlers, tableIds, sheetIds, pivotCaches, self.oNumFmtsOpen, self.dxfsOpen);
|
|
});
|
|
//timelinecache
|
|
this.timelineCaches.forEach(function(elem){
|
|
elem.initPostOpen(tableIds, sheetIds);
|
|
});
|
|
//show active if it hidden
|
|
var wsActive = this.getActiveWs();
|
|
if (wsActive && wsActive.getHidden()) {
|
|
wsActive.setHidden(false);
|
|
}
|
|
|
|
if(!bNoBuildDep){
|
|
this.dependencyFormulas.initOpen();
|
|
}
|
|
//external references
|
|
this.externalReferences.forEach(function(elem){
|
|
elem && elem.initPostOpen && elem.initPostOpen();
|
|
});
|
|
if (bSnapshot) {
|
|
this.snapshot = this._getSnapshot();
|
|
}
|
|
|
|
if (this.MainDocument) {
|
|
g_cCalcRecursion.initCalcProperties(this.calcPr);
|
|
}
|
|
|
|
};
|
|
Workbook.prototype.Get_Api = function() {
|
|
return this.oApi;
|
|
};
|
|
Workbook.prototype.Get_CollaborativeEditing = function() {
|
|
return this.oApi.collaborativeEditing
|
|
};
|
|
Workbook.prototype.addImages = function (aImages, obj) {
|
|
const oApi = Asc.editor;
|
|
if (obj && undefined !== obj.id && aImages.length === 1 && aImages[0].Image) {
|
|
const oController = oApi.getGraphicController();
|
|
const oDrawingObjects = oApi.getDrawingObjects();
|
|
const oPlaceholderTarget = AscCommon.g_oTableId.Get_ById(obj.id);
|
|
if (oPlaceholderTarget) {
|
|
if (oPlaceholderTarget.isObjectInSmartArt && oPlaceholderTarget.isObjectInSmartArt()) {
|
|
const oSmartArtGroup = oPlaceholderTarget.group.getMainGroup();
|
|
const oSmartArtId = oSmartArtGroup && oSmartArtGroup.Id;
|
|
this.checkObjectsLock([oSmartArtId], function (bLock) {
|
|
if (bLock) {
|
|
AscCommon.History.Create_NewPoint();
|
|
oController.resetSelection();
|
|
oPlaceholderTarget.applyImagePlaceholderCallback && oPlaceholderTarget.applyImagePlaceholderCallback(aImages, obj);
|
|
oController.selectObject(oSmartArtGroup, 0);
|
|
oController.selection.groupSelection = oSmartArtGroup;
|
|
oSmartArtGroup.selectObject(oPlaceholderTarget, 0);
|
|
const oWS = oApi.wb.getWorksheet();
|
|
if (oWS) {
|
|
oWS.setSelectionShape(true);
|
|
}
|
|
oSmartArtGroup.addToRecalculate();
|
|
oController.startRecalculate();
|
|
if (oDrawingObjects) {
|
|
oDrawingObjects.sendGraphicObjectProps();
|
|
}
|
|
oController.clearPreTrackObjects();
|
|
oController.clearTrackObjects();
|
|
oController.updateOverlay();
|
|
oController.changeCurrentState(new AscFormat.NullState(oController));
|
|
oController.updateSelectionState();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} else if (obj && obj.callback && aImages.length === 1 && aImages[0].Image) {
|
|
obj.callback(aImages[0]);
|
|
}
|
|
};
|
|
Workbook.prototype.getOleSize = function () {
|
|
return this.oleSize;
|
|
};
|
|
Workbook.prototype.setOleSize = function (oPr) {
|
|
this.oleSize = oPr;
|
|
};
|
|
Workbook.prototype.RemoveDrawingObjectById = function (drawingId) {
|
|
AscCommon.History.Create_NewPoint();
|
|
const drawing = AscCommon.g_oTableId.Get_ById(drawingId);
|
|
const controller = drawing.getDrawingObjectsController();
|
|
drawing.deselect(controller);
|
|
drawing.deleteDrawingBase();
|
|
controller.startRecalculate();
|
|
};
|
|
Workbook.prototype.preparePivotForSerialization=function(pivotCaches, isCopyPaste){
|
|
var pivotCacheIndex = 0;
|
|
this.forEach(function(ws) {
|
|
for (var i = 0; i < ws.pivotTables.length; ++i) {
|
|
var pivotTable = ws.pivotTables[i];
|
|
if (isCopyPaste && !pivotTable.isInRange(isCopyPaste)) {
|
|
continue;
|
|
}
|
|
if (pivotTable.cacheDefinition) {
|
|
var pivotCache = pivotCaches[pivotTable.cacheDefinition.Get_Id()];
|
|
if (!pivotCache) {
|
|
pivotCache = {id: pivotCacheIndex++, cache: pivotTable.cacheDefinition};
|
|
pivotCaches[pivotTable.cacheDefinition.Get_Id()] = pivotCache;
|
|
}
|
|
pivotTable.cacheId = pivotCache.id;
|
|
}
|
|
}
|
|
for (var i = 0; i < ws.aSlicers.length; ++i) {
|
|
var slicer = ws.aSlicers[i];
|
|
if (isCopyPaste) {
|
|
continue;
|
|
}
|
|
var cacheDefinition = slicer.getPivotCache();
|
|
if (cacheDefinition) {
|
|
var pivotCache = pivotCaches[cacheDefinition.Get_Id()];
|
|
if (!pivotCache) {
|
|
pivotCache = {id: pivotCacheIndex++, cache: cacheDefinition};
|
|
pivotCaches[cacheDefinition.Get_Id()] = pivotCache;
|
|
}
|
|
}
|
|
}
|
|
}, isCopyPaste);
|
|
return pivotCacheIndex;
|
|
};
|
|
Workbook.prototype.isChartOleObject = function () {
|
|
return this.aWorksheets.length === 2;
|
|
};
|
|
Workbook.prototype.setCommonIndexObjectsFrom = function(wb) {
|
|
this.oStyleManager = wb.oStyleManager;
|
|
this.sharedStrings = wb.sharedStrings;
|
|
this.workbookFormulas = wb.workbookFormulas;
|
|
};
|
|
Workbook.prototype.forEach = function (callback, isCopyPaste, writeTabSelected) {
|
|
//if copy/paste - use only actve ws
|
|
if ((isCopyPaste || isCopyPaste === false) && !writeTabSelected) {
|
|
callback(this.getActiveWs(), this.getActive());
|
|
} else {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
if (!writeTabSelected || (writeTabSelected && this.aWorksheets[i].isSelectedTab())) {
|
|
callback(this.aWorksheets[i], i);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype.rebuildColors=function(){
|
|
AscCommonExcel.g_oColorManager.rebuildColors();
|
|
this.forEach(function (ws) {
|
|
ws.rebuildColors();
|
|
});
|
|
};
|
|
Workbook.prototype.getDefaultFont=function(){
|
|
return g_oDefaultFormat.Font.getName();
|
|
};
|
|
Workbook.prototype.getDefaultSize=function(){
|
|
return g_oDefaultFormat.Font.getSize();
|
|
};
|
|
Workbook.prototype.getActive=function(){
|
|
return this.nActive;
|
|
};
|
|
Workbook.prototype.getActiveWs = function () {
|
|
return this.getWorksheet(this.nActive);
|
|
};
|
|
Workbook.prototype.setActive=function(index){
|
|
if(index >= 0 && index < this.aWorksheets.length){
|
|
this.nActive = index;
|
|
// Must clean find
|
|
this.cleanFindResults();
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
Workbook.prototype.setActiveById=function(sheetId){
|
|
var ws = this.getWorksheetById(sheetId);
|
|
if (ws) {
|
|
this.setActive(ws.getIndex());
|
|
}
|
|
return false;
|
|
};
|
|
Workbook.prototype.getSheetIdByIndex = function(index) {
|
|
var ws = this.getWorksheet(index);
|
|
return ws ? ws.getId() : null;
|
|
};
|
|
Workbook.prototype.getWorksheet=function(index){
|
|
//index 0-based
|
|
if(index >= 0 && index < this.aWorksheets.length){
|
|
return this.aWorksheets[index];
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getWorksheetById=function(id){
|
|
return this.aWorksheetsById[id];
|
|
};
|
|
Workbook.prototype.getWorksheetByName=function(name, ignoreCaseSensitive){
|
|
for(var i = 0; i < this.aWorksheets.length; i++) {
|
|
if (ignoreCaseSensitive) {
|
|
if(name && this.aWorksheets[i].getName().toLowerCase() == name.toLowerCase()){
|
|
return this.aWorksheets[i];
|
|
}
|
|
} else if(this.aWorksheets[i].getName() == name){
|
|
return this.aWorksheets[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
Workbook.prototype.getWorksheetIndexByName=function(name){
|
|
for(var i = 0; i < this.aWorksheets.length; i++)
|
|
if(this.aWorksheets[i].getName() == name){
|
|
return i;
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getWorksheetCount=function(){
|
|
return this.aWorksheets.length;
|
|
};
|
|
Workbook.prototype.createWorksheet=function(indexBefore, sName, sId){
|
|
this.dependencyFormulas.lockRecal();
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.TurnOff();
|
|
var wsActive = this.getActiveWs();
|
|
var oNewWorksheet = new Worksheet(this, this.aWorksheets.length, sId);
|
|
if (this.checkValidSheetName(sName))
|
|
oNewWorksheet.sName = sName;
|
|
oNewWorksheet.initPostOpen(this.wsHandlers, {});
|
|
if(null != indexBefore && indexBefore >= 0 && indexBefore < this.aWorksheets.length)
|
|
this.aWorksheets.splice(indexBefore, 0, oNewWorksheet);
|
|
else
|
|
{
|
|
indexBefore = this.aWorksheets.length;
|
|
this.aWorksheets.push(oNewWorksheet);
|
|
}
|
|
this.aWorksheetsById[oNewWorksheet.getId()] = oNewWorksheet;
|
|
this._updateWorksheetIndexes(wsActive);
|
|
AscCommon.History.TurnOn();
|
|
this._insertWorksheetFormula(oNewWorksheet.index);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_SheetAdd, null, null, new UndoRedoData_SheetAdd(indexBefore, oNewWorksheet.getName(), null, oNewWorksheet.getId()));
|
|
AscCommon.History.SetSheetUndo(wsActive.getId());
|
|
AscCommon.History.SetSheetRedo(oNewWorksheet.getId());
|
|
this.dependencyFormulas.unlockRecal();
|
|
return oNewWorksheet;
|
|
};
|
|
Workbook.prototype.copyWorksheet=function(index, insertBefore, sName, sId, bFromRedo, tableNames, opt_sheet, opt_base64){
|
|
//insertBefore - optional
|
|
var renameParams;
|
|
if(index >= 0 && index < this.aWorksheets.length){
|
|
//buildRecalc вызываем чтобы пересчиталося cwf(может быть пустым если сделать сдвиг формул и скопировать лист)
|
|
this.dependencyFormulas.buildDependency();
|
|
AscCommon.History.TurnOff();
|
|
var wsActive = this.getActiveWs();
|
|
var wsFrom = opt_sheet ? opt_sheet : this.aWorksheets[index];
|
|
var newSheet = new Worksheet(this, -1, sId);
|
|
if(null != insertBefore && insertBefore >= 0 && insertBefore < this.aWorksheets.length){
|
|
//помещаем новый sheet перед insertBefore
|
|
this.aWorksheets.splice(insertBefore, 0, newSheet);
|
|
}
|
|
else{
|
|
//помещаем новый sheet в конец
|
|
this.aWorksheets.push(newSheet);
|
|
}
|
|
|
|
if(opt_sheet) {
|
|
this.addingWorksheet = newSheet;
|
|
}
|
|
|
|
this.aWorksheetsById[newSheet.getId()] = newSheet;
|
|
this._updateWorksheetIndexes(wsActive);
|
|
if (this.handlers) {
|
|
this.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.markModifiedSearch);
|
|
}
|
|
|
|
//copyFrom after sheet add because formula assemble dependce on sheet structure
|
|
renameParams = newSheet.copyFrom(wsFrom, sName, tableNames);
|
|
|
|
newSheet.copyFromFormulas(renameParams);
|
|
|
|
newSheet.initPostOpen(this.wsHandlers, {}, {});
|
|
AscCommon.History.TurnOn();
|
|
|
|
this.dependencyFormulas.copyDefNameByWorksheet(wsFrom, newSheet, renameParams, opt_sheet);
|
|
if (opt_sheet /*&& !bFromRedo*/) {
|
|
this.dependencyFormulas.copyDefNameByWorkbook(wsFrom, newSheet, renameParams, opt_sheet);
|
|
}
|
|
//для формул. создаем копию this.cwf[this.Id] для нового листа.
|
|
//newSheet._BuildDependencies(wsFrom.getCwf());
|
|
|
|
//now insertBefore is index of inserted sheet
|
|
this._insertWorksheetFormula(insertBefore);
|
|
|
|
if (!tableNames) {
|
|
tableNames = newSheet.getTableNames();
|
|
}
|
|
|
|
/*var opt_sheet_binary = null;
|
|
if(!bFromRedo && opt_sheet) {
|
|
opt_sheet_binary = AscCommonExcel.g_clipboardExcel.copyProcessor.getBinaryForCopy(wsFrom, null, null, true);
|
|
}
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_SheetAdd, null, null, new UndoRedoData_SheetAdd(insertBefore, newSheet.getName(), wsFrom.getId(), newSheet.getId(), tableNames, opt_sheet_binary));*/
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_SheetAdd, null, null, new UndoRedoData_SheetAdd(insertBefore, newSheet.getName(), wsFrom.getId(), newSheet.getId(), tableNames, opt_base64));
|
|
AscCommon.History.SetSheetUndo(wsActive.getId());
|
|
AscCommon.History.SetSheetRedo(newSheet.getId());
|
|
newSheet.copyFromAfterInsert(wsFrom);
|
|
if(!(bFromRedo === true))
|
|
{
|
|
wsFrom.copyObjects(newSheet, renameParams);
|
|
var i;
|
|
if (wsFrom.aNamedSheetViews) {
|
|
for (i = 0; i < wsFrom.aNamedSheetViews.length; ++i) {
|
|
newSheet.addNamedSheetView(wsFrom.aNamedSheetViews[i].clone(renameParams.tableNameMap));
|
|
}
|
|
}
|
|
if (wsFrom.dataValidations && wsFrom.dataValidations.elems) {
|
|
for (i = 0; i < wsFrom.dataValidations.elems.length; ++i) {
|
|
newSheet.addDataValidation(wsFrom.dataValidations.elems[i].clone(), true);
|
|
}
|
|
}
|
|
}
|
|
this.sortDependency();
|
|
|
|
if(opt_sheet) {
|
|
this.addingWorksheet = null;
|
|
}
|
|
}
|
|
return renameParams;
|
|
};
|
|
Workbook.prototype.insertWorksheet = function (index, sheet) {
|
|
var wsActive = this.getActiveWs();
|
|
if(null != index && index >= 0 && index < this.aWorksheets.length){
|
|
//помещаем новый sheet перед insertBefore
|
|
this.aWorksheets.splice(index, 0, sheet);
|
|
}
|
|
else{
|
|
//помещаем новый sheet в конец
|
|
this.aWorksheets.push(sheet);
|
|
}
|
|
this.aWorksheetsById[sheet.getId()] = sheet;
|
|
this._updateWorksheetIndexes(wsActive);
|
|
this._insertWorksheetFormula(index);
|
|
this._insertTablePartsName(sheet);
|
|
//восстанавливаем список ячеек с формулами для sheet
|
|
sheet._BuildDependencies(sheet.getCwf());
|
|
this.sortDependency();
|
|
};
|
|
Workbook.prototype._insertTablePartsName = function (sheet) {
|
|
if(sheet && sheet.TableParts && sheet.TableParts.length)
|
|
{
|
|
for(var i = 0; i < sheet.TableParts.length; i++)
|
|
{
|
|
var tablePart = sheet.TableParts[i];
|
|
this.dependencyFormulas.addTableName(sheet, tablePart);
|
|
tablePart.buildDependencies();
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype._insertWorksheetFormula=function(index){
|
|
if( index > 0 && index < this.aWorksheets.length ) {
|
|
var oWsBefore = this.aWorksheets[index - 1];
|
|
this.dependencyFormulas.changeSheet(this.dependencyFormulas.prepareChangeSheet(oWsBefore.getId(), {insert: index}));
|
|
}
|
|
};
|
|
Workbook.prototype.replaceWorksheet=function(indexFrom, indexTo){
|
|
if(indexFrom >= 0 && indexFrom < this.aWorksheets.length &&
|
|
indexTo >= 0 && indexTo < this.aWorksheets.length){
|
|
var wsActive = this.getActiveWs();
|
|
var oWsFrom = this.aWorksheets[indexFrom];
|
|
var tempW = {
|
|
wF: oWsFrom,
|
|
wFI: indexFrom,
|
|
wTI: indexTo
|
|
};
|
|
//wTI index insert before
|
|
if(tempW.wFI < tempW.wTI)
|
|
tempW.wTI++;
|
|
this.dependencyFormulas.lockRecal();
|
|
var prepared = this.dependencyFormulas.prepareChangeSheet(oWsFrom.getId(), {replace: tempW}, null);
|
|
//move sheets
|
|
var movedSheet = this.aWorksheets.splice(indexFrom, 1);
|
|
this.aWorksheets.splice(indexTo, 0, movedSheet[0]);
|
|
this._updateWorksheetIndexes(wsActive);
|
|
this.dependencyFormulas.changeSheet(prepared);
|
|
|
|
this._insertWorksheetFormula(indexTo);
|
|
|
|
if (!AscCommon.g_oTableId.Get_ById(oWsFrom.getId())) {
|
|
//todo add in constructor with history
|
|
AscFormat.ExecuteNoHistory(function () {
|
|
AscCommon.g_oTableId.Add(oWsFrom, oWsFrom.getId())
|
|
}, this, [], true);
|
|
}
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_SheetRemove, null, null, new AscCommonExcel.UndoRedoData_SheetRemove(indexFrom, oWsFrom.getId(), oWsFrom));
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_SheetAdd, null, null, new UndoRedoData_SheetAdd(indexTo, oWsFrom.getName(), null, oWsFrom.getId(), null, null, oWsFrom.getId()));
|
|
this.dependencyFormulas.unlockRecal();
|
|
|
|
if (!this.bUndoChanges && !this.bRedoChanges) {
|
|
this.handlers && this.handlers.trigger("updateCellWatches", true);
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype.findSheetNoHidden = function (nIndex) {
|
|
var i, ws, oRes = null, bFound = false, countWorksheets = this.getWorksheetCount();
|
|
for (i = nIndex; i < countWorksheets; ++i) {
|
|
ws = this.getWorksheet(i);
|
|
if (false === ws.getHidden()) {
|
|
oRes = ws;
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
// Не нашли справа, ищем слева от текущего
|
|
if (!bFound) {
|
|
for (i = nIndex - 1; i >= 0; --i) {
|
|
ws = this.getWorksheet(i);
|
|
if (false === ws.getHidden()) {
|
|
oRes = ws;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return oRes;
|
|
};
|
|
Workbook.prototype.removeWorksheet=function(nIndex, outputParams){
|
|
//проверяем останется ли хоть один нескрытый sheet
|
|
var bEmpty = true;
|
|
for(var i = 0, length = this.aWorksheets.length; i < length; ++i)
|
|
{
|
|
var worksheet = this.aWorksheets[i];
|
|
if(false == worksheet.getHidden() && i != nIndex)
|
|
{
|
|
bEmpty = false;
|
|
break;
|
|
}
|
|
}
|
|
if(bEmpty)
|
|
return -1;
|
|
|
|
var removedSheet = this.getWorksheet(nIndex);
|
|
if(removedSheet)
|
|
{
|
|
var removedSheetId = removedSheet.getId();
|
|
this.dependencyFormulas.lockRecal();
|
|
var prepared = this.dependencyFormulas.prepareRemoveSheet(removedSheetId, removedSheet.getTableNames());
|
|
|
|
//remove timeline
|
|
if (removedSheet.timelines) {
|
|
for (let i = 0; i < removedSheet.timelines.length; i++) {
|
|
this.onTimeSlicerDelete(removedSheet.timelines[i].name);
|
|
this.onTimelineCacheDelete(removedSheet.timelines[i].name, true);
|
|
}
|
|
}
|
|
|
|
//delete sheet
|
|
var wsActive = this.getActiveWs();
|
|
var oVisibleWs = null;
|
|
this.aWorksheets.splice(nIndex, 1);
|
|
delete this.aWorksheetsById[removedSheetId];
|
|
|
|
if (nIndex == this.getActive()) {
|
|
oVisibleWs = this.findSheetNoHidden(nIndex);
|
|
if (null != oVisibleWs)
|
|
wsActive = oVisibleWs;
|
|
}
|
|
if (!AscCommon.g_oTableId.Get_ById(removedSheet.getId())) {
|
|
//todo add in constructor with history
|
|
AscFormat.ExecuteNoHistory(function () {
|
|
AscCommon.g_oTableId.Add(removedSheet, removedSheet.getId())
|
|
}, this, [], true);
|
|
}
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_SheetRemove, null, null, new AscCommonExcel.UndoRedoData_SheetRemove(nIndex, removedSheetId, removedSheet));
|
|
if (null != oVisibleWs) {
|
|
AscCommon.History.SetSheetUndo(removedSheetId);
|
|
AscCommon.History.SetSheetRedo(wsActive.getId());
|
|
}
|
|
if(null != outputParams)
|
|
{
|
|
outputParams.sheet = removedSheet;
|
|
}
|
|
this._updateWorksheetIndexes(wsActive);
|
|
this.dependencyFormulas.removeSheet(prepared);
|
|
this.dependencyFormulas.unlockRecal();
|
|
this.handlers && this.handlers.trigger("asc_onSheetDeleted", nIndex);
|
|
this.handlers && this.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetRemove, nIndex);
|
|
return wsActive.getIndex();
|
|
}
|
|
return -1;
|
|
};
|
|
Workbook.prototype._updateWorksheetIndexes = function (wsActive) {
|
|
this.forEach(function (ws, index) {
|
|
ws._setIndex(index);
|
|
});
|
|
if (null != wsActive) {
|
|
this.setActive(wsActive.getIndex());
|
|
}
|
|
};
|
|
Workbook.prototype.checkUniqueSheetName=function(name){
|
|
var workbookSheetCount = this.getWorksheetCount();
|
|
for (var i = 0; i < workbookSheetCount; i++){
|
|
if (this.getWorksheet(i).getName() == name)
|
|
return i;
|
|
}
|
|
return -1;
|
|
};
|
|
Workbook.prototype.checkValidSheetName=function(name){
|
|
return (name && name.length <= g_nSheetNameMaxLength);
|
|
};
|
|
Workbook.prototype.getUniqueSheetNameFrom=function(name, bCopy){
|
|
var nIndex = 1;
|
|
var sNewName = "";
|
|
var fGetPostfix = null;
|
|
if(bCopy)
|
|
{
|
|
|
|
var result = /^(.*)\((\d)\)$/.exec(name);
|
|
if(result)
|
|
{
|
|
fGetPostfix = function(nIndex){return "(" + nIndex +")";};
|
|
name = result[1];
|
|
}
|
|
else
|
|
{
|
|
fGetPostfix = function(nIndex){return " (" + nIndex +")";};
|
|
name = name;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fGetPostfix = function(nIndex){return nIndex.toString();};
|
|
}
|
|
var workbookSheetCount = this.getWorksheetCount();
|
|
while(nIndex < 10000)
|
|
{
|
|
var sPosfix = fGetPostfix(nIndex);
|
|
sNewName = name + sPosfix;
|
|
if(sNewName.length > g_nSheetNameMaxLength)
|
|
{
|
|
name = name.substring(0, g_nSheetNameMaxLength - sPosfix.length);
|
|
sNewName = name + sPosfix;
|
|
}
|
|
var bUniqueName = true;
|
|
for (var i = 0; i < workbookSheetCount; i++){
|
|
if (this.getWorksheet(i).getName() == sNewName)
|
|
{
|
|
bUniqueName = false;
|
|
break;
|
|
}
|
|
}
|
|
if(bUniqueName)
|
|
break;
|
|
nIndex++;
|
|
}
|
|
return sNewName;
|
|
};
|
|
Workbook.prototype._generateFontMap=function(){
|
|
var oFontMap = {
|
|
"Arial" : 1
|
|
};
|
|
var i;
|
|
|
|
oFontMap[g_oDefaultFormat.Font.getName()] = 1;
|
|
|
|
//theme
|
|
if(null != this.theme)
|
|
AscFormat.checkThemeFonts(oFontMap, this.theme.themeElements.fontScheme);
|
|
//xfs
|
|
for (i = 1; i <= g_StyleCache.getXfCount(); ++i) {
|
|
var xf = g_StyleCache.getXf(i);
|
|
if (xf.font) {
|
|
oFontMap[xf.font.getName()] = 1;
|
|
}
|
|
}
|
|
//sharedStrings
|
|
this.sharedStrings.generateFontMap(oFontMap);
|
|
|
|
this.forEach(function (ws) {
|
|
ws.generateFontMap(oFontMap);
|
|
});
|
|
this.CellStyles.generateFontMap(oFontMap);
|
|
|
|
return oFontMap;
|
|
};
|
|
Workbook.prototype.generateFontMap=function(){
|
|
var oFontMap = this._generateFontMap();
|
|
|
|
var aRes = [];
|
|
for(var i in oFontMap)
|
|
aRes.push(i);
|
|
return aRes;
|
|
};
|
|
Workbook.prototype.generateFontMap2=function(){
|
|
var oFontMap = this._generateFontMap();
|
|
|
|
var aRes = [];
|
|
for(var i in oFontMap)
|
|
aRes.push(new AscFonts.CFont(i));
|
|
AscFonts.FontPickerByCharacter.extendFonts(aRes);
|
|
return aRes;
|
|
};
|
|
Workbook.prototype.getAllImageUrls = function(){
|
|
var aImageUrls = [];
|
|
this.forEach(function (ws) {
|
|
ws.getAllImageUrls(aImageUrls);
|
|
});
|
|
return aImageUrls;
|
|
};
|
|
Workbook.prototype.reassignImageUrls = function(oImages){
|
|
this.forEach(function (ws) {
|
|
ws.reassignImageUrls(oImages);
|
|
});
|
|
};
|
|
Workbook.prototype.calculate = function (type, sheetId) {
|
|
let formulas;
|
|
if (type === Asc.c_oAscCalculateType.All) {
|
|
formulas = this.getAllFormulas();
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
for (let i = 0; i < formulas.length; ++i) {
|
|
let formula = formulas[i];
|
|
let caTemp = formula.ca;
|
|
formula.removeDependencies();
|
|
formula.setFormula(formula.getFormula());
|
|
formula.parse();
|
|
formula.ca = caTemp;
|
|
formula.buildDependencies();
|
|
}
|
|
});
|
|
} else if (type === Asc.c_oAscCalculateType.ActiveSheet) {
|
|
formulas = [];
|
|
let ws = sheetId !== undefined ? this.getWorksheetById(sheetId) : this.getActiveWs();
|
|
ws.getAllFormulas(formulas);
|
|
sheetId = ws.getId();
|
|
} else {
|
|
formulas = this.getAllFormulas();
|
|
}
|
|
this.dependencyFormulas.notifyChanged(formulas);
|
|
this.dependencyFormulas.calcTree();
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_Calculate, sheetId,
|
|
null, new AscCommonExcel.UndoRedoData_SingleProperty(type));
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Workbook.prototype.checkDefName = function (checkName, scope) {
|
|
return this.dependencyFormulas.checkDefName(checkName, scope);
|
|
};
|
|
Workbook.prototype.getDefinedNamesWB = function (defNameListId, bLocale, excludeErrorRefNames) {
|
|
return this.dependencyFormulas.getDefinedNamesWB(defNameListId, bLocale, excludeErrorRefNames);
|
|
};
|
|
Workbook.prototype.getDefinedNamesWS = function (sheetId) {
|
|
return this.dependencyFormulas.getDefinedNamesWS(sheetId);
|
|
};
|
|
Workbook.prototype.addDefName = function (name, ref, sheetId, hidden, isTable) {
|
|
return this.dependencyFormulas.addDefName(name, ref, sheetId, hidden, isTable);
|
|
};
|
|
Workbook.prototype.getDefinesNames = function ( name, sheetId ) {
|
|
return this.dependencyFormulas.getDefNameByName( name, sheetId );
|
|
};
|
|
Workbook.prototype.getDefinedName = function(name) {
|
|
var sheetId = this.getSheetIdByIndex(name.LocalSheetId);
|
|
return this.dependencyFormulas.getDefNameByName(name.Name, sheetId);
|
|
};
|
|
Workbook.prototype.delDefinesNames = function ( defName ) {
|
|
this.delDefinesNamesUndoRedo(this.getUndoDefName(defName));
|
|
};
|
|
Workbook.prototype.delDefinesNamesUndoRedo = function ( defName ) {
|
|
this.dependencyFormulas.removeDefName( defName.sheetId, defName.name );
|
|
this.dependencyFormulas.calcTree();
|
|
};
|
|
Workbook.prototype.editDefinesNames = function (oldName, newName) {
|
|
return this.editDefinesNamesUndoRedo(this.getUndoDefName(oldName), this.getUndoDefName(newName));
|
|
};
|
|
Workbook.prototype.editDefinesNamesUndoRedo = function (oldName, newName, isFromHistory) {
|
|
var res = this.dependencyFormulas.editDefinesNames(oldName, newName, isFromHistory);
|
|
this.dependencyFormulas.calcTree();
|
|
return res;
|
|
};
|
|
Workbook.prototype.findDefinesNames = function ( ref, sheetId, bLocale ) {
|
|
return this.dependencyFormulas.getDefNameByRef( ref, sheetId, bLocale );
|
|
};
|
|
Workbook.prototype.definesNamesContains = function ( col, row, sheetId, bLocale ) {
|
|
return this.dependencyFormulas.getDefNameByCellInside( col, row, sheetId, bLocale );
|
|
};
|
|
Workbook.prototype.unlockDefName = function(){
|
|
this.dependencyFormulas.unlockDefName();
|
|
};
|
|
Workbook.prototype.unlockCurrentDefName = function(name, sheetId){
|
|
this.dependencyFormulas.unlockCurrentDefName(name, sheetId);
|
|
};
|
|
Workbook.prototype.checkDefNameLock = function(){
|
|
return this.dependencyFormulas.checkDefNameLock();
|
|
};
|
|
Workbook.prototype.getNewXlChartId = function () {
|
|
return this.dependencyFormulas.getNewXlChartId();
|
|
};
|
|
Workbook.prototype._SerializeHistoryItem = function (oMemory, item) {
|
|
if (this.oApi.binaryChanges) {
|
|
if (!item.LocalChange) {
|
|
let nLen = oMemory.WriteWithLen(this, function(){
|
|
item.Serialize(oMemory, this.oApi.collaborativeEditing);
|
|
});
|
|
return oMemory.GetDataUint8(0, nLen);
|
|
}
|
|
return;
|
|
} else {
|
|
if (!item.LocalChange) {
|
|
oMemory.Seek(0);
|
|
item.Serialize(oMemory, this.oApi.collaborativeEditing);
|
|
var nLen = oMemory.GetCurPosition();
|
|
if (nLen > 0)
|
|
return nLen + ";" + oMemory.GetBase64Memory2(0, nLen);
|
|
}
|
|
return;
|
|
}
|
|
};
|
|
Workbook.prototype._SerializeHistoryItem2 = function (oMemory, item) {
|
|
if (!item.LocalChange) {
|
|
item.Serialize(oMemory, this.oApi.collaborativeEditing);
|
|
}
|
|
};
|
|
Workbook.prototype._SerializeHistory = function(oMemory, item, aPointChanges) {
|
|
let data = this._SerializeHistoryItem(oMemory, item);
|
|
if (data) {
|
|
aPointChanges.push(data);
|
|
}
|
|
};
|
|
Workbook.prototype.SerializeHistory = function(){
|
|
var aResData = [];
|
|
var aResSerializable = [];
|
|
//соединяем изменения, которые были до приема данных с теми, что получились после.
|
|
|
|
var t, j, length2;
|
|
|
|
// Пересчитываем позиции
|
|
AscCommon.CollaborativeEditing.Refresh_DCChanges();
|
|
|
|
var aActions = this.aCollaborativeActions.concat(AscCommon.History.GetSerializeArray());
|
|
if(aActions.length > 0)
|
|
{
|
|
var oMemory = new AscCommon.CMemory();
|
|
for(var i = 0, length = aActions.length; i < length; ++i)
|
|
{
|
|
let items = aActions[i];
|
|
for (j = 0, length2 = items.length; j < length2; ++j) {
|
|
var item = items[j];
|
|
// Пересчитываем позиции
|
|
if (item.Data && item.Data.applyCollaborative) {
|
|
//не делаем копию oData, а сдвигаем в ней, потому что все равно после сериализации изменения потруться
|
|
if (item.Data.applyCollaborative(item.SheetId, this.oApi.collaborativeEditing)) {
|
|
AscCommon.History.Refresh_SpreadsheetChanges(item);
|
|
}
|
|
}
|
|
if (!item.LocalChange) {
|
|
let data = AscCommon.CCollaborativeChanges.ToBase64(item.Binary.Pos, item.Binary.Len);
|
|
aResData.push(data);
|
|
aResSerializable.push(AscCommon.History.Item_ToSerializable(item));
|
|
}
|
|
}
|
|
}
|
|
this.aCollaborativeActions = [];
|
|
this.snapshot = this._getSnapshot();
|
|
}
|
|
return [aResData, aResSerializable];
|
|
};
|
|
Workbook.prototype._getSnapshot = function() {
|
|
var wb = new Workbook(new AscCommonExcel.asc_CHandlersList(), this.oApi, false);
|
|
wb.dependencyFormulas = this.dependencyFormulas.getSnapshot(wb);
|
|
this.forEach(function (ws) {
|
|
ws = ws.getSnapshot(wb);
|
|
wb.aWorksheets.push(ws);
|
|
wb.aWorksheetsById[ws.getId()] = ws;
|
|
});
|
|
//init trigger
|
|
wb.init({}, true, false);
|
|
return wb;
|
|
};
|
|
Workbook.prototype.getAllFormulas = function(needReturnCellProps) {
|
|
var res = [];
|
|
this.dependencyFormulas.getAllFormulas(res);
|
|
this.forEach(function (ws) {
|
|
ws.getAllFormulas(res, needReturnCellProps);
|
|
});
|
|
return res;
|
|
};
|
|
Workbook.prototype.addCustomFunctionToChanged = function(isNotUpdate) {
|
|
var res = null;
|
|
let t = this;
|
|
this.dependencyFormulas.forEachFormula(function (fP) {
|
|
if (fP && fP.unknownOrCustomFunction && ((fP.ca && isNotUpdate) || !isNotUpdate)) {
|
|
fP.isParsed = false;
|
|
fP.outStack = [];
|
|
fP.parse();
|
|
if (/*DefName*/fP.parent.getNodeId) {
|
|
t.dependencyFormulas.addToChangedDefName(fP.parent);
|
|
}
|
|
res = true;
|
|
}
|
|
});
|
|
this.forEach(function (ws) {
|
|
ws.forEachFormula(function (fP) {
|
|
if (fP && fP.unknownOrCustomFunction && ((fP.ca && isNotUpdate) || !isNotUpdate)) {
|
|
fP.isParsed = false;
|
|
fP.outStack = [];
|
|
fP.parse();
|
|
if (/*CCellWithFormula*/fP.parent.nCol != null) {
|
|
t.dependencyFormulas.addToChangedCell(fP.parent);
|
|
}
|
|
res = true;
|
|
}
|
|
});
|
|
});
|
|
return res;
|
|
};
|
|
Workbook.prototype._forwardTransformation = function(wbSnapshot, changesMine, changesTheir) {
|
|
AscCommon.History.TurnOff();
|
|
//first mine changes to resolve conflict sheet names
|
|
var res1 = this._forwardTransformationGetTransform(wbSnapshot, changesTheir, changesMine);
|
|
var res2 = this._forwardTransformationGetTransform(wbSnapshot, changesMine, changesTheir);
|
|
//modify formulas at the end - to prevent negative effect during tranformation
|
|
var i, elem, elemWrap;
|
|
for (i = 0; i < res1.modify.length; ++i) {
|
|
elemWrap = res1.modify[i];
|
|
elem = elemWrap.elem;
|
|
elem.oClass.forwardTransformationSet(elem.nActionType, elem.oData, elem.nSheetId, elemWrap);
|
|
}
|
|
for (i = 0; i < res2.modify.length; ++i) {
|
|
elemWrap = res2.modify[i];
|
|
elem = elemWrap.elem;
|
|
elem.oClass.forwardTransformationSet(elem.nActionType, elem.oData, elem.nSheetId, elemWrap);
|
|
}
|
|
//rename current wb
|
|
for (var oldName in res1.renameSheet) {
|
|
var ws = this.getWorksheetByName(oldName);
|
|
if (ws) {
|
|
ws.setName(res1.renameSheet[oldName]);
|
|
}
|
|
}
|
|
AscCommon.History.TurnOn();
|
|
};
|
|
Workbook.prototype._forwardTransformationGetTransform = function(wbSnapshot, changesMaster, changesModify) {
|
|
var res = {modify: [], renameSheet: {}};
|
|
var changesMasterSelected = [];
|
|
var i, elem;
|
|
if (changesModify.length > 0) {
|
|
//select useful master changes
|
|
for ( i = 0; i < changesMaster.length; ++i) {
|
|
elem = changesMaster[i];
|
|
if (elem.oClass && elem.oClass.forwardTransformationIsAffect &&
|
|
elem.oClass.forwardTransformationIsAffect(elem.nActionType)) {
|
|
changesMasterSelected.push(elem);
|
|
}
|
|
}
|
|
}
|
|
if (changesMasterSelected.length > 0 && changesModify.length > 0) {
|
|
var wbSnapshotCur = wbSnapshot._getSnapshot();
|
|
var formulas = [];
|
|
for (i = 0; i < changesModify.length; ++i) {
|
|
elem = changesModify[i];
|
|
var renameRes = null;
|
|
if (elem.oClass && elem.oClass.forwardTransformationGet) {
|
|
var getRes = elem.oClass.forwardTransformationGet(elem.nActionType, elem.oData, elem.nSheetId);
|
|
if (getRes && getRes.formula) {
|
|
//inserted formulas
|
|
formulas.push(new ForwardTransformationFormula(elem, getRes.formula, null));
|
|
}
|
|
if (getRes && getRes.name) {
|
|
//add/rename sheet
|
|
//get getUniqueSheetNameFrom if need
|
|
renameRes = this._forwardTransformationRenameStart(wbSnapshotCur._getSnapshot(),
|
|
changesMasterSelected, getRes);
|
|
}
|
|
}
|
|
if (elem.oClass && elem.oClass.forwardTransformationIsAffect &&
|
|
elem.oClass.forwardTransformationIsAffect(elem.nActionType)) {
|
|
if (formulas.length > 0) {
|
|
//modify all formulas before apply next change
|
|
this._forwardTransformationFormula(wbSnapshotCur._getSnapshot(), formulas,
|
|
changesMasterSelected, res);
|
|
formulas = [];
|
|
}
|
|
//apply useful mine change
|
|
elem.oClass.Redo(elem.nActionType, elem.oData, elem.nSheetId, wbSnapshotCur);
|
|
}
|
|
if (renameRes) {
|
|
this._forwardTransformationRenameEnd(renameRes, res.renameSheet, getRes, elem);
|
|
}
|
|
}
|
|
this._forwardTransformationFormula(wbSnapshotCur, formulas, changesMasterSelected, res);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype._forwardTransformationRenameStart = function(wbSnapshot, changes, getRes) {
|
|
var res = {newName: null};
|
|
for (var i = 0; i < changes.length; ++i) {
|
|
var elem = changes[i];
|
|
elem.oClass.Redo(elem.nActionType, elem.oData, elem.nSheetId, wbSnapshot);
|
|
}
|
|
if (-1 != wbSnapshot.checkUniqueSheetName(getRes.name)) {
|
|
res.newName = wbSnapshot.getUniqueSheetNameFrom(getRes.name, true);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype._forwardTransformationRenameEnd = function(renameRes, renameSheet, getRes, elemCur) {
|
|
var isChange = false;
|
|
if (getRes.from) {
|
|
var renameCur = renameSheet[getRes.from];
|
|
if (renameCur) {
|
|
//no need rename next formulas
|
|
delete renameSheet[getRes.from];
|
|
getRes.from = renameCur;
|
|
isChange = true;
|
|
}
|
|
}
|
|
if (renameRes && renameRes.newName) {
|
|
renameSheet[getRes.name] = renameRes.newName;
|
|
getRes.name = renameRes.newName;
|
|
isChange = true;
|
|
}
|
|
//apply immediately cause it is conflict
|
|
if (isChange && elemCur.oClass.forwardTransformationSet) {
|
|
elemCur.oClass.forwardTransformationSet(elemCur.nActionType, elemCur.oData, elemCur.nSheetId, getRes);
|
|
}
|
|
};
|
|
Workbook.prototype._forwardTransformationFormula = function(wbSnapshot, formulas, changes, res) {
|
|
if (formulas.length > 0) {
|
|
var i, elem, ftFormula, ws;
|
|
//parse formulas
|
|
for (i = 0; i < formulas.length; ++i) {
|
|
ftFormula = formulas[i];
|
|
ws = wbSnapshot.getWorksheetById(ftFormula.elem.nSheetId);
|
|
if(!ws) {
|
|
ws = new AscCommonExcel.Worksheet(wbSnapshot, -1);
|
|
}
|
|
if (ws) {
|
|
ftFormula.parsed = new parserFormula(ftFormula.formula, ftFormula, ws);
|
|
ftFormula.parsed.parse();
|
|
ftFormula.parsed.buildDependencies();
|
|
}
|
|
}
|
|
//rename sheet first to prevent name conflict
|
|
for (var oldName in res.renameSheet) {
|
|
ws = wbSnapshot.getWorksheetByName(oldName);
|
|
if (ws) {
|
|
ws.setName(res.renameSheet[oldName]);
|
|
}
|
|
}
|
|
//apply useful theirs changes
|
|
for (i = 0; i < changes.length; ++i) {
|
|
elem = changes[i];
|
|
elem.oClass.Redo(elem.nActionType, elem.oData, elem.nSheetId, wbSnapshot);
|
|
}
|
|
//assemble
|
|
for (i = 0; i < formulas.length; ++i) {
|
|
ftFormula = formulas[i];
|
|
if (ftFormula.parsed) {
|
|
ftFormula.parsed.removeDependencies();
|
|
res.modify.push(ftFormula);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype._DeserializeUndoRedoElems = function(aChanges){
|
|
var oThis = this;
|
|
var aUndoRedoElems = [];
|
|
if (this.oApi.binaryChanges) {
|
|
for (let i = 0; i < aChanges.length; ++i) {
|
|
let sChange = aChanges[i];
|
|
var stream = new AscCommon.FT_Stream2(sChange, sChange.length);
|
|
stream.Seek(4);
|
|
stream.Seek2(4);
|
|
var item = new UndoRedoItemSerializable();
|
|
item.Deserialize(stream);
|
|
if (!oThis.needSkipChange(item)) {
|
|
aUndoRedoElems.push(item);
|
|
}
|
|
}
|
|
} else {
|
|
var dstLen = 0;
|
|
var aIndexes = [], i, length = aChanges.length, sChange;
|
|
for(i = 0; i < length; ++i)
|
|
{
|
|
sChange = aChanges[i];
|
|
var nIndex = sChange.indexOf(";");
|
|
if (-1 != nIndex) {
|
|
dstLen += parseInt(sChange.substring(0, nIndex));
|
|
nIndex++;
|
|
}
|
|
aIndexes.push(nIndex);
|
|
}
|
|
var pointer = g_memory.Alloc(dstLen);
|
|
var stream = new AscCommon.FT_Stream2(pointer.data, dstLen);
|
|
stream.obj = pointer.obj;
|
|
var nCurOffset = 0;
|
|
for (i = 0; i < length; ++i) {
|
|
sChange = aChanges[i];
|
|
if (sChange.startsWith("0;")) {
|
|
continue;
|
|
}
|
|
var oBinaryFileReader = new AscCommonExcel.BinaryFileReader();
|
|
nCurOffset = oBinaryFileReader.getbase64DecodedData2(sChange, aIndexes[i], stream, nCurOffset);
|
|
var item = new UndoRedoItemSerializable();
|
|
item.Deserialize(stream);
|
|
if (!oThis.needSkipChange(item)) {
|
|
aUndoRedoElems.push(item);
|
|
}
|
|
}
|
|
}
|
|
return aUndoRedoElems;
|
|
}
|
|
Workbook.prototype.DeserializeHistory = function(aChanges, fCallback, oColor){
|
|
var oThis = this;
|
|
//сохраняем те изменения, которые были до приема данных, потому что дальше undo/redo будет очищено
|
|
this.aCollaborativeActions = this.aCollaborativeActions.concat(AscCommon.History.GetSerializeArray());
|
|
if(aChanges.length > 0)
|
|
{
|
|
this.bCollaborativeChanges = true;
|
|
//собираем общую длину
|
|
var i, length = aChanges.length;
|
|
|
|
var aUndoRedoElems = this._DeserializeUndoRedoElems(aChanges);
|
|
var wsViews = window["Asc"]["editor"].wb && window["Asc"]["editor"].wb.wsViews;
|
|
if(oThis.oApi.collaborativeEditing.getFast()){
|
|
AscCommon.CollaborativeEditing.Clear_DocumentPositions();
|
|
}
|
|
if(wsViews) {
|
|
for (var i in wsViews) {
|
|
if (isRealObject(wsViews[i]) && isRealObject(wsViews[i].objectRender) &&
|
|
isRealObject(wsViews[i].objectRender.controller)) {
|
|
wsViews[i].endEditChart();
|
|
if (oThis.oApi.collaborativeEditing.getFast()) {
|
|
var oState = wsViews[i].objectRender.saveStateBeforeLoadChanges();
|
|
if (oState) {
|
|
if (oState.Pos) {
|
|
AscCommon.CollaborativeEditing.Add_DocumentPosition(oState.Pos);
|
|
}
|
|
if (oState.StartPos) {
|
|
AscCommon.CollaborativeEditing.Add_DocumentPosition(oState.StartPos);
|
|
}
|
|
if (oState.EndPos) {
|
|
AscCommon.CollaborativeEditing.Add_DocumentPosition(oState.EndPos);
|
|
}
|
|
}
|
|
}
|
|
wsViews[i].objectRender.controller.resetSelection();
|
|
}
|
|
}
|
|
}
|
|
oFormulaLocaleInfo.Parse = false;
|
|
oFormulaLocaleInfo.DigitSep = false;
|
|
AscFonts.IsCheckSymbols = true;
|
|
AscCommon.History.Clear();
|
|
AscCommon.History.TurnOff();
|
|
var history = new AscCommon.CHistory();
|
|
history.Set_LogicDocument(this);
|
|
history.Create_NewPoint();
|
|
|
|
history.SetSelection(null);
|
|
history.SetSelectionRedo(null);
|
|
var oRedoObjectParam = new AscCommonExcel.RedoObjectParam();
|
|
history.UndoRedoPrepare(oRedoObjectParam, false);
|
|
var changesMine = [].concat.apply([], oThis.aCollaborativeActions);
|
|
oThis._forwardTransformation(oThis.snapshot, changesMine, aUndoRedoElems);
|
|
oThis.cleanCollaborativeFilterObj();
|
|
for (var i = 0, length = aUndoRedoElems.length; i < length; ++i)
|
|
{
|
|
var item = aUndoRedoElems[i];
|
|
if ((null != item.oClass || (item.oData && typeof item.oData.sChangedObjectId === "string")) && null != item.nActionType) {
|
|
if (window["NATIVE_EDITOR_ENJINE"] === true && window["native"]["CheckNextChange"]) {
|
|
if (!window["native"]["CheckNextChange"]())
|
|
break;
|
|
}
|
|
if (true === oThis.oApi.collaborativeEditing.private_AddOverallChange(item))
|
|
{
|
|
// TODO if(g_oUndoRedoGraphicObjects == item.oClass && item.oData.drawingData)
|
|
// item.oData.drawingData.bCollaborativeChanges = true;
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
history.RedoAdd(oRedoObjectParam, item.oClass, item.nActionType, item.nSheetId, item.oRange, item.oData, false, item);
|
|
});
|
|
if (oThis.oApi.VersionHistory && item.nSheetId && item.GetChangedRange) {
|
|
let changedRange = item.nSheetId && item.GetChangedRange();
|
|
if (changedRange) {
|
|
oThis.oApi.wb.addToHistoryChangedRanges(item.nSheetId, changedRange, oColor);
|
|
}
|
|
}
|
|
|
|
if (item.GetClass() && item.GetClass().SetIsRecalculated && item.IsNeedRecalculate())
|
|
item.GetClass().SetIsRecalculated(false);
|
|
|
|
}
|
|
}
|
|
}
|
|
AscFonts.IsCheckSymbols = false;
|
|
|
|
var oFontMap = this._generateFontMap();
|
|
window["Asc"]["editor"]._loadFonts(oFontMap, function(){
|
|
if(oThis.oApi.collaborativeEditing.getFast()){
|
|
if(wsViews) {
|
|
for(var i in wsViews){
|
|
if(isRealObject(wsViews[i]) && isRealObject(wsViews[i].objectRender) && isRealObject(wsViews[i].objectRender.controller)){
|
|
var oState = wsViews[i].objectRender.getStateBeforeLoadChanges();
|
|
if(oState){
|
|
if (oState.Pos)
|
|
AscCommon.CollaborativeEditing.Update_DocumentPosition(oState.Pos);
|
|
if (oState.StartPos)
|
|
AscCommon.CollaborativeEditing.Update_DocumentPosition(oState.StartPos);
|
|
if (oState.EndPos)
|
|
AscCommon.CollaborativeEditing.Update_DocumentPosition(oState.EndPos);
|
|
}
|
|
wsViews[i].objectRender.loadStateAfterLoadChanges();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
oFormulaLocaleInfo.Parse = true;
|
|
oFormulaLocaleInfo.DigitSep = true;
|
|
history.UndoRedoEnd(null, oRedoObjectParam, false);
|
|
AscCommon.History.TurnOn();
|
|
oThis.bCollaborativeChanges = false;
|
|
//make snapshot for faormulas
|
|
oThis.snapshot = oThis._getSnapshot();
|
|
if(null != fCallback)
|
|
fCallback();
|
|
});
|
|
} else if(null != fCallback) {
|
|
fCallback();
|
|
}
|
|
};
|
|
Workbook.prototype.DeserializeHistoryNative = function(oRedoObjectParam, data, isFull){
|
|
if(null != data)
|
|
{
|
|
this.bCollaborativeChanges = true;
|
|
|
|
if(null == oRedoObjectParam)
|
|
{
|
|
if(window["Asc"]["editor"].wb) {
|
|
var wsViews = window["Asc"]["editor"].wb.wsViews;
|
|
for (var i in wsViews) {
|
|
if (isRealObject(wsViews[i]) && isRealObject(wsViews[i].objectRender) &&
|
|
isRealObject(wsViews[i].objectRender.controller)) {
|
|
wsViews[i].endEditChart();
|
|
wsViews[i].objectRender.controller.resetSelection();
|
|
}
|
|
}
|
|
}
|
|
|
|
AscCommon.History.Clear();
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.SetSelection(null);
|
|
AscCommon.History.SetSelectionRedo(null);
|
|
oRedoObjectParam = new AscCommonExcel.RedoObjectParam();
|
|
AscCommon.History.UndoRedoPrepare(oRedoObjectParam, false);
|
|
}
|
|
|
|
var stream = new AscCommon.FT_Stream2(data, data.length);
|
|
stream.obj = null;
|
|
// Применяем изменения, пока они есть
|
|
var _count = stream.GetLong();
|
|
var _pos = 4;
|
|
for (var i = 0; i < _count; i++)
|
|
{
|
|
if (window["NATIVE_EDITOR_ENJINE"] === true && window["native"]["CheckNextChange"])
|
|
{
|
|
if (!window["native"]["CheckNextChange"]())
|
|
break;
|
|
}
|
|
|
|
var _len = stream.GetLong();
|
|
|
|
_pos += 4;
|
|
stream.size = _pos + _len;
|
|
stream.Seek(_pos);
|
|
stream.Seek2(_pos);
|
|
|
|
var item = new UndoRedoItemSerializable();
|
|
item.Deserialize(stream);
|
|
if ((null != item.oClass || (item.oData && typeof item.oData.sChangedObjectId === "string")) && null != item.nActionType){
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
AscCommon.History.RedoAdd(oRedoObjectParam, item.oClass, item.nActionType, item.nSheetId, item.oRange, item.oData, false, item);
|
|
});
|
|
}
|
|
|
|
_pos += _len;
|
|
stream.Seek2(_pos);
|
|
stream.size = data.length;
|
|
}
|
|
|
|
if(isFull){
|
|
AscCommon.History.UndoRedoEnd(null, oRedoObjectParam, false);
|
|
AscCommon.History.Clear();
|
|
oRedoObjectParam = null;
|
|
}
|
|
this.bCollaborativeChanges = false;
|
|
}
|
|
return oRedoObjectParam;
|
|
};
|
|
Workbook.prototype.needSkipChange = function(change){
|
|
var res = false;
|
|
var aSkipChanges = [[AscCommonExcel.g_oUndoRedoWorkbook.getClassType(), AscCH.historyitem_Workbook_Date1904]];
|
|
|
|
//при десериализации пропускаем изменение, если такое же есть в списке текущих у данного юзера
|
|
var isNeededChange = function (_change, _actionType, _classType) {
|
|
if (_change && _change.oClass) {
|
|
if (_actionType === undefined || _classType === undefined) {
|
|
for (var j = 0; j < aSkipChanges.length; j++) {
|
|
if (aSkipChanges[j][0] === _change.oClass.getClassType() && aSkipChanges[j][1] === _change.nActionType) {
|
|
return true;
|
|
}
|
|
}
|
|
} else {
|
|
if (_change && _change.oClass && _change.oClass.getClassType() === _classType && _change.nActionType === _actionType) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
if (this.aCollaborativeActions && this.aCollaborativeActions.length) {
|
|
if (isNeededChange(change)) {
|
|
var actionType = change.nActionType;
|
|
var classType = change.oClass && change.oClass.getClassType();
|
|
for (var i = 0, length = this.aCollaborativeActions.length; i < length; ++i) {
|
|
if (isNeededChange(change, actionType, classType)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
Workbook.prototype.getTableRangeForFormula = function(name, objectParam){
|
|
var res = null;
|
|
for(var i = 0, length = this.aWorksheets.length; i < length; ++i)
|
|
{
|
|
var ws = this.aWorksheets[i];
|
|
res = ws.getTableRangeForFormula(name, objectParam);
|
|
if(res !== null){
|
|
res = {wsID:ws.getId(),range:res};
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getTableIndexColumnByName = function(tableName, columnName){
|
|
var res = null;
|
|
for(var i = 0, length = this.aWorksheets.length; i < length; ++i)
|
|
{
|
|
var ws = this.aWorksheets[i];
|
|
res = ws.getTableIndexColumnByName(tableName, columnName);
|
|
//получаем имя через getTableNameColumnByIndex поскольку tableName приходит в том виде
|
|
//в котором набрал пользователь, те регистр может быть произвольным
|
|
//todo для того, чтобы два раза не бежать по колонкам можно сделать функцию которая возвращает полную информацию о колонке
|
|
//
|
|
if(res !== null){
|
|
res = {wsID:ws.getId(), index: res, name: ws.getTableNameColumnByIndex(tableName, res)};
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getTableNameColumnByIndex = function(tableName, columnIndex){
|
|
var res = null;
|
|
for(var i = 0, length = this.aWorksheets.length; i < length; ++i)
|
|
{
|
|
var ws = this.aWorksheets[i];
|
|
res = ws.getTableNameColumnByIndex(tableName, columnIndex);
|
|
if(res !== null){
|
|
res = {wsID:ws.getId(), columnName: res};
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getTableByName = function(tableName, getSheetIndex){
|
|
var res = null;
|
|
for (var i = 0, length = this.aWorksheets.length; i < length; ++i) {
|
|
var ws = this.aWorksheets[i];
|
|
res = ws.getTableByName(tableName);
|
|
if (res !== null) {
|
|
return getSheetIndex ? {index: i, table: res} : res;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getTableByNameAndSheet = function(tableName, wsID){
|
|
var res = null;
|
|
var ws = this.getWorksheetById(wsID);
|
|
return ws.getTableByName(tableName);
|
|
};
|
|
Workbook.prototype.updateSparklineCache = function (sheet, ranges) {
|
|
this.forEach(function (ws) {
|
|
ws.updateSparklineCache(sheet, ranges);
|
|
});
|
|
};
|
|
Workbook.prototype.sortDependency = function () {
|
|
this.dependencyFormulas.calcTree();
|
|
};
|
|
/**
|
|
* Вычисляет ширину столбца для заданного количества символов
|
|
* @param {Number} count Количество символов
|
|
* @returns {Number} Ширина столбца в символах
|
|
*/
|
|
Workbook.prototype.charCountToModelColWidth = function (count) {
|
|
if (count <= 0) {
|
|
return 0;
|
|
}
|
|
return Asc.floor((count * this.maxDigitWidth + this.paddingPlusBorder) / this.maxDigitWidth * 256) / 256;
|
|
};
|
|
/**
|
|
* Вычисляет ширину столбца в px
|
|
* @param {Number} mcw Количество символов
|
|
* @returns {Number} Ширина столбца в px
|
|
*/
|
|
Workbook.prototype.modelColWidthToColWidth = function (mcw) {
|
|
return Asc.floor(((256 * mcw + Asc.floor(128 / this.maxDigitWidth)) / 256) * this.maxDigitWidth);
|
|
};
|
|
/**
|
|
* Вычисляет количество символов по ширине столбца
|
|
* @param {Number} w Ширина столбца в px
|
|
* @returns {Number} Количество символов
|
|
*/
|
|
Workbook.prototype.colWidthToCharCount = function (w) {
|
|
var pxInOneCharacter = this.maxDigitWidth + this.paddingPlusBorder;
|
|
// Когда меньше 1 символа, то просто считаем по пропорции относительно размера 1-го символа
|
|
return w < pxInOneCharacter ?
|
|
(1 - Asc.floor(100 * (pxInOneCharacter - w) / pxInOneCharacter + 0.49999) / 100) :
|
|
Asc.floor((w - this.paddingPlusBorder) / this.maxDigitWidth * 100 + 0.5) / 100;
|
|
};
|
|
Workbook.prototype.getUndoDefName = function(ascName) {
|
|
if (!ascName) {
|
|
return ascName;
|
|
}
|
|
var sheetId = this.getSheetIdByIndex(ascName.LocalSheetId);
|
|
return new UndoRedoData_DefinedNames(ascName.Name, ascName.Ref, sheetId, ascName.type, ascName.isXLNM, ascName.Hidden);
|
|
};
|
|
Workbook.prototype.changeColorScheme = function (sSchemeName) {
|
|
var scheme = AscCommon.getColorSchemeByName(sSchemeName);
|
|
if (!scheme) {
|
|
scheme = this.theme.getExtraClrScheme(sSchemeName);
|
|
}
|
|
if(!scheme)
|
|
{
|
|
return;
|
|
}
|
|
AscCommon.History.Create_NewPoint();
|
|
//не делаем Duplicate потому что предполагаем что схема не будет менять частями, а только обьектом целиком.
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ChangeColorScheme, null,
|
|
null, new AscCommonExcel.UndoRedoData_ClrScheme(this.theme.themeElements.clrScheme, scheme));
|
|
this.theme.changeColorScheme(scheme);
|
|
this.rebuildColors();
|
|
return true;
|
|
};
|
|
Workbook.prototype.changeColorSchemeByIdx = function (nIdx) {
|
|
|
|
var scheme = this.oApi.getColorSchemeByIdx(nIdx);
|
|
if(!scheme) {
|
|
return;
|
|
}
|
|
AscCommon.History.Create_NewPoint();
|
|
//не делаем Duplicate потому что предполагаем что схема не будет менять частями, а только обьектом целиком.
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ChangeColorScheme, null,
|
|
null, new AscCommonExcel.UndoRedoData_ClrScheme(this.theme.themeElements.clrScheme, scheme));
|
|
this.theme.changeColorScheme(scheme);
|
|
this.rebuildColors();
|
|
return true;
|
|
};
|
|
// ----- Search -----
|
|
Workbook.prototype.cleanFindResults = function () {
|
|
this.lastFindOptions = null;
|
|
this.lastFindCells = {};
|
|
};
|
|
Workbook.prototype.findCellText = function (options, searchEngine) {
|
|
var ws = this.getActiveWs();
|
|
var result = ws.findCellText(options, searchEngine), result2 = null;
|
|
if (Asc.c_oAscSearchBy.Workbook === options.scanOnOnlySheet) {
|
|
// Search on workbook
|
|
var key = result && (result.col + "-" + result.row);
|
|
if (!key || (options.isEqual(this.lastFindOptions) && this.lastFindCells[key])) {
|
|
// Мы уже находили данную ячейку, попробуем на другом листе
|
|
var i, active = this.getActive(), start = 0, end = this.getWorksheetCount();
|
|
var inc = options.scanForward ? +1 : -1;
|
|
for (i = active + inc; i < end && i >= start; i += inc) {
|
|
ws = this.getWorksheet(i);
|
|
if (ws.getHidden()) {
|
|
continue;
|
|
}
|
|
result2 = ws.findCellText(options, searchEngine);
|
|
if (result2) {
|
|
break;
|
|
}
|
|
}
|
|
if (!result2 || searchEngine) {
|
|
// Мы дошли до конца или начала (в зависимости от направления, теперь пойдем до активного)
|
|
if (options.scanForward) {
|
|
i = 0;
|
|
end = active;
|
|
} else {
|
|
i = end - 1;
|
|
start = active + 1;
|
|
inc *= -1;
|
|
}
|
|
|
|
for (; i < end && i >= start; i += inc) {
|
|
ws = this.getWorksheet(i);
|
|
if (ws.getHidden()) {
|
|
continue;
|
|
}
|
|
result2 = ws.findCellText(options, searchEngine);
|
|
if (result2 && !searchEngine) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result2 && !searchEngine) {
|
|
this.handlers && this.handlers.trigger('undoRedoHideSheet', i);
|
|
key = result2.col + "-" + result2.row;
|
|
}
|
|
}
|
|
|
|
if (key && !searchEngine) {
|
|
this.lastFindOptions = options.clone();
|
|
this.lastFindCells[key] = true;
|
|
}
|
|
}
|
|
if (searchEngine) {
|
|
return;
|
|
}
|
|
|
|
if (!result2 && !result) {
|
|
this.cleanFindResults();
|
|
}
|
|
return result2 || result;
|
|
};
|
|
//Comments
|
|
Workbook.prototype.getComment = function (id) {
|
|
if (id) {
|
|
var sheet;
|
|
for (var i = 0; i < this.aWorksheets.length; ++i) {
|
|
sheet = this.aWorksheets[i];
|
|
for (var j = 0; j < sheet.aComments.length; ++j) {
|
|
if (id === sheet.aComments[j].asc_getGuid()) {
|
|
return sheet.aComments[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getPivotTableByName = function(name) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var pivot = this.aWorksheets[i].getPivotTableByName(name);
|
|
if (pivot) {
|
|
return pivot;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getPivotTableById = function(id) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var pivot = this.aWorksheets[i].getPivotTableById(id);
|
|
if (pivot) {
|
|
return pivot;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getPivotTablesByCacheId = function(pivotCacheId) {
|
|
var res = [];
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var pivotTables = this.aWorksheets[i].getPivotTablesByCacheId(pivotCacheId);
|
|
res = res.concat(pivotTables);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getPivotTablesByCache = function(cache) {
|
|
var res = [];
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var caches = this.aWorksheets[i].getPivotTablesByCache(cache);
|
|
res = res.concat(caches);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getPivotCacheByDataLocation = function(dataLocation) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var cache = this.aWorksheets[i].getPivotCacheByDataLocation(dataLocation);
|
|
if (cache) {
|
|
return cache;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getPivotCacheById = function(pivotCacheId, pivotCachesOpen) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var cache = this.aWorksheets[i].getPivotCacheById(pivotCacheId, pivotCachesOpen);
|
|
if (cache) {
|
|
return cache;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicerCacheByName = function (name) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var cache = this.aWorksheets[i].getSlicerCacheByName(name);
|
|
if (cache) {
|
|
return cache;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicerCacheByCacheName = function (name) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var cache = this.aWorksheets[i].getSlicerCacheByCacheName(name);
|
|
if (cache) {
|
|
return cache;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicerCacheByPivotTableFld = function (sheetId, pivotName, fld) {
|
|
var slicerCaches = this.getSlicerCachesByPivotTable(sheetId, pivotName);
|
|
for (var i = 0; i < slicerCaches.length; ++i) {
|
|
if (slicerCaches[i].getPivotFieldIndex() === fld) {
|
|
return slicerCaches[i];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicerCachesByPivotTable = function (sheetId, pivotName) {
|
|
var res = [];
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var caches = this.aWorksheets[i].getSlicerCachesByPivotTable(sheetId, pivotName);
|
|
res = res.concat(caches);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getSlicerCachesByPivotCacheId = function (pivotCacheId) {
|
|
var res = [];
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var caches = this.aWorksheets[i].getSlicerCachesByPivotCacheId(pivotCacheId);
|
|
res = res.concat(caches);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getSlicerStyle = function (name) {
|
|
var slicer = this.getSlicerByName(name);
|
|
if (slicer) {
|
|
return slicer.style;
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicerByName = function (name) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var slicer = this.aWorksheets[i].getSlicerByName(name);
|
|
if (slicer) {
|
|
return slicer;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicerViewByName = function (name) {
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var slicer = this.aWorksheets[i].getSlicerViewByName(name);
|
|
if (slicer) {
|
|
return slicer;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Workbook.prototype.getSlicersByCacheName = function (name) {
|
|
var res = [];
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
var slicers = this.aWorksheets[i].getSlicersByCacheName(name);
|
|
if (slicers) {
|
|
res = res.concat(slicers);
|
|
}
|
|
}
|
|
return res.length ? res : null;
|
|
};
|
|
Workbook.prototype.getTimelineCachesByPivotTable = function (sheetId, pivotName) {
|
|
var res = [];
|
|
if (this.timelineCaches) {
|
|
for (var i = 0, l = this.timelineCaches.length; i < l; ++i) {
|
|
if (this.timelineCaches[i].isCachePivotTable(sheetId, pivotName)) {
|
|
res.push(this.timelineCaches[i]);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.getDrawingDocument = function() {
|
|
return this.DrawingDocument;
|
|
};
|
|
Workbook.prototype.onSlicerUpdate = function(sName) {
|
|
if(AscCommon.isFileBuild()) {
|
|
return false;
|
|
}
|
|
var bRet = false;
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
bRet = bRet || this.aWorksheets[i].onSlicerUpdate(sName);
|
|
}
|
|
return bRet;
|
|
};
|
|
Workbook.prototype.onSlicerDelete = function(sName) {
|
|
if(AscCommon.isFileBuild()) {
|
|
return false;
|
|
}
|
|
var bRet = false;
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
bRet = bRet || this.aWorksheets[i].onSlicerDelete(sName);
|
|
}
|
|
return bRet;
|
|
};
|
|
Workbook.prototype.onSlicerLock = function(sName, bLock) {
|
|
if(AscCommon.isFileBuild()) {
|
|
return;
|
|
}
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
this.aWorksheets[i].onSlicerLock(sName, bLock);
|
|
}
|
|
};
|
|
Workbook.prototype.onSlicerChangeName = function(sName, sNewName) {
|
|
if(AscCommon.isFileBuild()) {
|
|
return;
|
|
}
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
this.aWorksheets[i].onSlicerChangeName(sName, sNewName);
|
|
}
|
|
};
|
|
Workbook.prototype.deleteSlicer = function(sName) {
|
|
var bRet = false;
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
bRet = bRet || this.aWorksheets[i].deleteSlicer(sName);
|
|
}
|
|
return bRet;
|
|
};
|
|
Workbook.prototype.getSlicersByTableName = function (val) {
|
|
var res = null;
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
var wsSlicers = this.aWorksheets[i].getSlicersByTableName(val);
|
|
if (wsSlicers) {
|
|
if (!res) {
|
|
res = [];
|
|
}
|
|
res = res.concat(wsSlicers);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.slicersUpdateAfterChangeTable = function (name) {
|
|
var slicers = this.getSlicersByTableName(name);
|
|
if (slicers) {
|
|
for (var j = 0; j < slicers.length; j++) {
|
|
this.onSlicerUpdate(slicers[j].name);
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype.getSlicersByPivotTable = function (sheetId, pivotName) {
|
|
var res = [];
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
var slicers = this.aWorksheets[i].getSlicersByPivotTable(sheetId, pivotName);
|
|
res = res.concat(slicers);
|
|
}
|
|
return res;
|
|
};
|
|
Workbook.prototype.slicersUpdateAfterChangePivotTable = function (sheetId, pivotName) {
|
|
var slicers = this.getSlicersByPivotTable(sheetId, pivotName);
|
|
for (var j = 0; j < slicers.length; j++) {
|
|
this.onSlicerUpdate(slicers[j].name);
|
|
}
|
|
};
|
|
Workbook.prototype.deleteSlicersByPivotTable = function (sheetId, pivotName) {
|
|
var wb = this;
|
|
var slicerCaches = wb.getSlicerCachesByPivotTable(sheetId, pivotName);
|
|
slicerCaches.forEach(function (slicerCache) {
|
|
slicerCache.deletePivotTable(sheetId, pivotName);
|
|
if (0 === slicerCache.getPivotTablesCount()) {
|
|
var slicers = wb.getSlicersByCacheName(slicerCache.name);
|
|
if (slicers) {
|
|
slicers.forEach(function (slicer) {
|
|
wb.deleteSlicer(slicer.name);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Workbook.prototype.deleteSlicersByPivotTableAndFields = function (sheetId, pivotName, cacheFieldsToDelete) {
|
|
var wb = this;
|
|
var slicerCaches = wb.getSlicerCachesByPivotTable(sheetId, pivotName);
|
|
slicerCaches.forEach(function (slicerCache) {
|
|
if (cacheFieldsToDelete[slicerCache.getSourceName()]) {
|
|
slicerCache.deletePivotTable(sheetId, pivotName);
|
|
var slicers = wb.getSlicersByCacheName(slicerCache.name);
|
|
if (slicers) {
|
|
slicers.forEach(function (slicer) {
|
|
wb.deleteSlicer(slicer.name);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
Workbook.prototype.deleteSlicersByTable = function (tableName, doDelDefName) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
var wsSlicers = this.aWorksheets[i].getSlicersByTableName(tableName);
|
|
if (wsSlicers) {
|
|
for (var j = 0; j < wsSlicers.length; j++) {
|
|
this.aWorksheets[i].deleteSlicer(wsSlicers[j].name, doDelDefName);
|
|
}
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
|
|
Workbook.prototype.deleteTimelinesByPivotTable = function (sheetId, pivotName) {
|
|
var wb = this;
|
|
var timelineCaches = wb.getTimelineCachesByPivotTable(sheetId, pivotName);
|
|
timelineCaches.forEach(function (timelineCache) {
|
|
wb.onTimeSlicerDelete(timelineCache.sourceName);
|
|
wb.onTimelineCacheDelete(timelineCache.sourceName, true);
|
|
wb.onTimelinesDelete(timelineCache.sourceName, true);
|
|
});
|
|
};
|
|
|
|
Workbook.prototype.deleteTimelinesByCacheSourceName = function (name) {
|
|
this.forEach(function (ws) {
|
|
ws.deleteTimelinesByCacheSourceName(name);
|
|
});
|
|
};
|
|
|
|
Workbook.prototype.onTimeSlicerDelete = function(sName) {
|
|
if(AscCommon.isFileBuild()) {
|
|
return false;
|
|
}
|
|
var bRet = false;
|
|
for(let i = 0; i < this.aWorksheets.length; ++i) {
|
|
bRet = bRet || this.aWorksheets[i].onTimeSlicerDelete(sName);
|
|
}
|
|
|
|
return bRet;
|
|
};
|
|
Workbook.prototype.onTimelineCacheDelete = function (sName, addToHistory) {
|
|
if (this.timelineCaches) {
|
|
for(let i = 0; i < this.timelineCaches.length; ++i) {
|
|
if (this.timelineCaches[i].sourceName === sName) {
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_TimelineCacheDelete,
|
|
null, null, new UndoRedoData_FromTo(this.timelineCaches[i], null));
|
|
}
|
|
this.timelineCaches.splice(i, 1);
|
|
i--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype.onTimelinesDelete = function(sName, addToHistory) {
|
|
if(AscCommon.isFileBuild()) {
|
|
return false;
|
|
}
|
|
var bRet = false;
|
|
for(let i = 0; i < this.aWorksheets.length; ++i) {
|
|
bRet = bRet || this.aWorksheets[i].onTimelinesDelete(sName, addToHistory);
|
|
}
|
|
|
|
return bRet;
|
|
};
|
|
Workbook.prototype.handleDrawings = function (fCallback) {
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
this.aWorksheets[i].handleDrawings(fCallback);
|
|
}
|
|
};
|
|
Workbook.prototype.checkObjectsLock = function (aId, fCallback) {
|
|
if(aId.length > 0) {
|
|
if(Asc && Asc.editor) {
|
|
Asc.editor.checkObjectsLock(aId, fCallback);
|
|
}
|
|
else {
|
|
fCallback(true, true);
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype.handleChartsOnWorksheetsRemove = function (aWorksheets) {
|
|
if(!AscCommon.History.CanAddChanges()) {
|
|
return;
|
|
}
|
|
var aRefsToChange = [];
|
|
var aId = [];
|
|
var aRanges = [];
|
|
var aNames = [];
|
|
var oWorksheet;
|
|
for(var nWS = 0; nWS < aWorksheets.length; ++nWS) {
|
|
oWorksheet = aWorksheets[nWS];
|
|
aRanges.push(new AscCommonExcel.Range(oWorksheet, 0, 0, gc_nMaxRow0, gc_nMaxCol0));
|
|
aNames.push(parserHelp.getEscapeSheetName(oWorksheet.sName));
|
|
}
|
|
this.handleDrawings(function(oDrawing) {
|
|
if(oDrawing.getObjectType() === AscDFH.historyitem_type_ChartSpace) {
|
|
var nPrevLength = aRefsToChange.length;
|
|
oDrawing.collectIntersectionRefs(aRanges, aRefsToChange);
|
|
if(aRefsToChange.length > nPrevLength) {
|
|
aId.push(oDrawing.Get_Id());
|
|
}
|
|
}
|
|
});
|
|
this.checkObjectsLock(aId, function(bNoLock) {
|
|
if(bNoLock) {
|
|
for(var nRef = 0; nRef < aRefsToChange.length; ++nRef) {
|
|
aRefsToChange[nRef].handleRemoveWorksheets(aNames);
|
|
}
|
|
if(Asc.editor && Asc.editor.wb) {
|
|
Asc.editor.wb.recalculateDrawingObjects(null, false);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Workbook.prototype.getChartsWithSheetData = function(oWorksheet) {
|
|
var aRefsToChange = [];
|
|
var aId = [];
|
|
var aCharts = [];
|
|
var aRanges = [new AscCommonExcel.Range(oWorksheet, 0, 0, gc_nMaxRow0, gc_nMaxCol0)];
|
|
this.handleDrawings(function(oDrawing) {
|
|
if(oDrawing.getObjectType() === AscDFH.historyitem_type_ChartSpace) {
|
|
var nPrevLength = aRefsToChange.length;
|
|
oDrawing.clearDataRefs();
|
|
oDrawing.collectIntersectionRefs(aRanges, aRefsToChange);
|
|
oDrawing.clearDataRefs();
|
|
if(aRefsToChange.length > nPrevLength) {
|
|
aCharts.push(oDrawing);
|
|
aId.push(oDrawing.Get_Id());
|
|
}
|
|
}
|
|
});
|
|
return {refs: aRefsToChange, ids: aId, charts: aCharts};
|
|
|
|
};
|
|
Workbook.prototype.getChartSheetRenameData = function (oWorksheet, sOldName) {
|
|
var sOldSheetName = oWorksheet.sName;
|
|
oWorksheet.sName = sOldName;
|
|
var oData = this.getChartsWithSheetData(oWorksheet);
|
|
oWorksheet.sName = sOldSheetName;
|
|
return oData;
|
|
};
|
|
Workbook.prototype.changeSheetNameInRefs = function (aRefsToChange, sOldName, sNewName) {
|
|
if(aRefsToChange.length > 0) {
|
|
var sNewNameEscaped = parserHelp.getEscapeSheetName(sNewName);
|
|
var sOldNameEscaped = parserHelp.getEscapeSheetName(sOldName);
|
|
for(var nRef = 0; nRef < aRefsToChange.length; ++nRef) {
|
|
aRefsToChange[nRef].handleOnChangeSheetName(sOldNameEscaped, sNewNameEscaped);
|
|
}
|
|
}
|
|
};
|
|
Workbook.prototype.handleChartsOnChangeSheetName = function (oWorksheet, sOldName, sNewName) {
|
|
var oData = this.getChartSheetRenameData(oWorksheet, sOldName);
|
|
this.changeSheetNameInRefs(oData.refs, sOldName, sNewName);
|
|
};
|
|
Workbook.prototype.handleChartsOnMoveRange = function (oRangeFrom, oRangeTo, isInsertCol) {
|
|
if(!AscCommon.History.CanAddChanges()) {
|
|
return;
|
|
}
|
|
var aRefsToResize = [];
|
|
var aRefsToReplace = [];
|
|
var aId = [];
|
|
this.handleDrawings(function(oDrawing) {
|
|
if(oDrawing.getObjectType() === AscDFH.historyitem_type_ChartSpace) {
|
|
var nPrevLength = aRefsToReplace.length;
|
|
let delta;
|
|
let range;
|
|
if (isInsertCol) {
|
|
delta = oRangeTo.bbox.c2 - oRangeTo.bbox.c1 - 1;
|
|
range = oRangeFrom.clone()
|
|
range.bbox.c2 = oRangeFrom.bbox.c1 + delta;
|
|
} else {
|
|
delta = oRangeTo.bbox.r2 - oRangeTo.bbox.r1 - 1;
|
|
range = oRangeFrom.clone()
|
|
range.bbox.r2 = oRangeFrom.bbox.r1 + delta;
|
|
}
|
|
oDrawing.collectRefsInsideRange(oRangeFrom, aRefsToReplace);
|
|
if (typeof isInsertCol != "undefined") {
|
|
oDrawing.collectRefsInsideRangeForInsertColRow(range, aRefsToResize, isInsertCol);
|
|
}
|
|
for(var nRef = 0; nRef < aRefsToResize.length; ++nRef) {
|
|
if (aRefsToReplace.filter(function(val){return val.Id === aRefsToResize[nRef].Id}).length === 0)
|
|
aRefsToReplace.push({ ref: aRefsToResize[nRef], resize: true, Id: aRefsToResize[nRef].Id })
|
|
}
|
|
|
|
if(aRefsToReplace.length > nPrevLength) {
|
|
aId.push(oDrawing.Get_Id());
|
|
}
|
|
}
|
|
});
|
|
this.checkObjectsLock(aId, function(bNoLock) {
|
|
if(bNoLock) {
|
|
for(var nRef = 0; nRef < aRefsToReplace.length; ++nRef) {
|
|
if (aRefsToReplace[nRef].resize)
|
|
aRefsToReplace[nRef].ref.handleOnMoveRange(oRangeFrom, oRangeTo, true);
|
|
else
|
|
aRefsToReplace[nRef].handleOnMoveRange(oRangeFrom, oRangeTo, false);
|
|
}
|
|
if(Asc.editor && Asc.editor.wb) {
|
|
Asc.editor.wb.recalculateDrawingObjects(null, false);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Workbook.prototype.convertEquationToMath = function (oEquation, isAll) {
|
|
var aId = [];
|
|
var aEquations = [];
|
|
if(isAll) {
|
|
this.handleDrawings(function(oDrawing) {
|
|
oDrawing.collectEquations3(aEquations);
|
|
});
|
|
|
|
}
|
|
else {
|
|
aEquations.push(oEquation);
|
|
}
|
|
if(aEquations.length > 0) {
|
|
var nEquation;
|
|
var oObjectForCheck;
|
|
for(nEquation = 0; nEquation < aEquations.length; ++nEquation) {
|
|
oObjectForCheck = (aEquations[nEquation].getMainGroup() || aEquations[nEquation]);
|
|
aId.push(oObjectForCheck.Get_Id());
|
|
}
|
|
this.checkObjectsLock(aId, function(bNoLock) {
|
|
if(bNoLock) {
|
|
AscCommon.History.Create_NewPoint(0);
|
|
for(nEquation = 0; nEquation < aEquations.length; ++nEquation) {
|
|
aEquations[nEquation].replaceToMath();
|
|
}
|
|
if(Asc.editor && Asc.editor.wb) {
|
|
Asc.editor.wb.recalculateDrawingObjects(null, false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.cleanCollaborativeFilterObj = function () {
|
|
if (!Asc.CT_NamedSheetView.prototype.asc_getName) {
|
|
return;
|
|
}
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
this.aWorksheets[i].autoFilters.cleanCollaborativeObj();
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.checkCorrectTables = function () {
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
this.aWorksheets[i].checkCorrectTables();
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.getRulesByType = function(type, id, needClone, opt_sheet, opt_range) {
|
|
var range, sheet;
|
|
var rules = null;
|
|
switch (type) {
|
|
case Asc.c_oAscSelectionForCFType.selection:
|
|
sheet = opt_sheet ? opt_sheet : this.getActiveWs();
|
|
// ToDo multiselect
|
|
range = opt_range ? opt_range : sheet.selectionRange.getLast();
|
|
break;
|
|
case Asc.c_oAscSelectionForCFType.worksheet:
|
|
sheet = id ? this.getWorksheet(id) : this.getActiveWs();
|
|
break;
|
|
case Asc.c_oAscSelectionForCFType.table:
|
|
var oTable;
|
|
if (id) {
|
|
oTable = this.getTableByName(id, true);
|
|
if (oTable) {
|
|
sheet = this.aWorksheets[oTable.index];
|
|
range = oTable.table.Ref;
|
|
}
|
|
} else {
|
|
//this table
|
|
sheet = this.getActiveWs();
|
|
var thisTableIndex = sheet.autoFilters.searchRangeInTableParts(sheet.selectionRange.getLast());
|
|
if (thisTableIndex >= 0) {
|
|
range = sheet.TableParts[thisTableIndex].Ref;
|
|
} else {
|
|
sheet = null;
|
|
}
|
|
}
|
|
break;
|
|
case Asc.c_oAscSelectionForCFType.pivot:
|
|
sheet = this.getActiveWs();
|
|
var _activeCell = sheet.selectionRange.activeCell;
|
|
var _pivot = sheet.getPivotTable(_activeCell.col, _activeCell.row);
|
|
if (_pivot) {
|
|
range = _pivot.location && _pivot.location.ref;
|
|
}
|
|
|
|
if (!range) {
|
|
sheet = null;
|
|
}
|
|
|
|
break;
|
|
}
|
|
if (sheet) {
|
|
let _aRules = [];
|
|
sheet.forEachConditionalFormattingRules(function (elem) {
|
|
_aRules.push(elem);
|
|
});
|
|
var aRules = _aRules.sort(function(v1, v2) {
|
|
return v1.priority - v2.priority;
|
|
});
|
|
|
|
rules = [];
|
|
if (range) {
|
|
var putRange = function (_range, _rule) {
|
|
multiplyRange = new AscCommonExcel.MultiplyRange(_range);
|
|
if (multiplyRange.isIntersect(range)) {
|
|
if (needClone) {
|
|
var _id = _rule.id;
|
|
var isLocked = _rule.isLock;
|
|
_rule = _rule.clone();
|
|
_rule.id = _id;
|
|
_rule.isLock = isLocked;
|
|
_rule.recalcInterfaceFormula(sheet, true);
|
|
}
|
|
rules.push(_rule);
|
|
}
|
|
};
|
|
var oRule, ranges, multiplyRange, i, mapChangedRules = [];
|
|
for (i = 0; i < aRules.length; ++i) {
|
|
oRule = aRules[i];
|
|
ranges = oRule.ranges;
|
|
putRange(ranges, oRule);
|
|
}
|
|
} else {
|
|
for (i = 0; i < aRules.length; ++i) {
|
|
var _rule = aRules[i];
|
|
if (needClone) {
|
|
var _id = aRules[i].id;
|
|
var isLocked = _rule.isLock;
|
|
_rule = _rule.clone();
|
|
_rule.id = _id;
|
|
_rule.isLock = isLocked;
|
|
_rule.recalcInterfaceFormula(sheet, true);
|
|
}
|
|
rules.push(_rule);
|
|
}
|
|
}
|
|
}
|
|
return rules;
|
|
};
|
|
|
|
Workbook.prototype.setProtectedWorkbook = function (props, addToHistory) {
|
|
if (!this.workbookProtection) {
|
|
this.workbookProtection = new window["Asc"].CWorkbookProtection();
|
|
}
|
|
this.workbookProtection.set(props, addToHistory, this);
|
|
return true;
|
|
};
|
|
|
|
Workbook.prototype.getWorkbookProtection = function (type) {
|
|
var res = false;
|
|
|
|
if (this.workbookProtection) {
|
|
switch (type) {
|
|
case Asc.c_oAscWorkbookProtectType.lockWindows:
|
|
res = this.workbookProtection.asc_getLockWindows();
|
|
break;
|
|
case Asc.c_oAscWorkbookProtectType.lockRevisions:
|
|
res = this.workbookProtection.asc_getLockRevision();
|
|
break;
|
|
case Asc.c_oAscWorkbookProtectType.lockStructure:
|
|
default:
|
|
res = this.workbookProtection.asc_getLockStructure();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Workbook.prototype.getPrintOptionsJson = function () {
|
|
var res = [];
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
res[i] = this.aWorksheets[i].getPrintOptionsJson();
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Workbook.prototype.setDate1904 = function (val, addToHistory) {
|
|
var oldVal = AscCommon.bDate1904;
|
|
|
|
AscCommon.bDate1904 = val;
|
|
AscCommonExcel.c_DateCorrectConst = AscCommon.bDate1904 ? AscCommonExcel.c_Date1904Const : AscCommonExcel.c_Date1900Const;
|
|
|
|
this.workbookPr.setDate1904(val);
|
|
|
|
if (addToHistory) {
|
|
var updateSheet = this.getActiveWs();
|
|
var updateRange = new Asc.Range(0, 0, updateSheet.getColsCount(), updateSheet.getRowsCount());
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_Date1904,
|
|
updateSheet.getId(), updateRange, new UndoRedoData_FromTo(oldVal, val));
|
|
}
|
|
};
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
Workbook.prototype.getRangeAndSheetFromStr = function (sRange) {
|
|
var ws;
|
|
var range;
|
|
if (sRange) {
|
|
if (-1 !== sRange.indexOf("!")) {
|
|
var is3DRef = AscCommon.parserHelp.parse3DRef(sRange);
|
|
if (is3DRef) {
|
|
ws = this.getWorksheetByName(is3DRef.sheet);
|
|
range = AscCommonExcel.g_oRangeCache.getAscRange(is3DRef.range);
|
|
}
|
|
} else {
|
|
ws = this.getActiveWs();
|
|
range = AscCommonExcel.g_oRangeCache.getAscRange(sRange);
|
|
//может быть именованный диапазон
|
|
if (!range) {
|
|
var dN = this.dependencyFormulas.getDefNameByName(sRange, ws.getId());
|
|
if (dN && dN.parsedRef) {
|
|
range = dN.parsedRef.getFirstRange();
|
|
if (range) {
|
|
range = range.bbox;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return {sheet: ws, range: range}
|
|
};
|
|
|
|
Workbook.prototype.addCellWatches = function (ws, range) {
|
|
if (ws && range) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
//TODO protection!
|
|
var maxCellWatchesCount = Asc.c_nAscMaxAddCellWatchesCount;
|
|
var counter = 0;
|
|
for (var i = range.r1; i <= range.r2; i++) {
|
|
for (var j = range.c1; j <= range.c2; j++) {
|
|
var _ref = new Asc.Range(j, i, j, i);
|
|
ws.addCellWatch(_ref, true);
|
|
counter++;
|
|
if (counter === maxCellWatchesCount) {
|
|
break;
|
|
}
|
|
}
|
|
if (counter === maxCellWatchesCount) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
|
|
/*if (!this.bUndoChanges && !this.bRedoChanges) {
|
|
this.handlers.trigger("asc_onUpdateCellWatches");
|
|
}*/
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.delCellWatches = function (aCellWatches, addToHistory, opt_remove_all) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
//TODO protection!
|
|
var i;
|
|
if (opt_remove_all) {
|
|
for(i = 0; i < this.aWorksheets.length; ++i) {
|
|
this.aWorksheets[i].deleteCellWatches(addToHistory);
|
|
}
|
|
} else {
|
|
for (i = 0; i < aCellWatches.length; i++) {
|
|
var ws = aCellWatches[i]._ws;
|
|
ws.deleteCellWatch(aCellWatches[i].r, addToHistory);
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
|
|
/*if (!this.bUndoChanges && !this.bRedoChanges) {
|
|
this.handlers.trigger("asc_onUpdateCellWatches");
|
|
}*/
|
|
};
|
|
|
|
Workbook.prototype.recalculateCellWatches = function (fullRecalc) {
|
|
var count = 0;
|
|
var changedMap = null;
|
|
for(var i = 0; i < this.aWorksheets.length; ++i) {
|
|
for (var j = 0; j < this.aWorksheets[i].aCellWatches.length; j++) {
|
|
if (this.aWorksheets[i].aCellWatches[j].recalculate(fullRecalc)) {
|
|
if (!changedMap) {
|
|
changedMap = {};
|
|
}
|
|
changedMap[count] = this.aWorksheets[i].aCellWatches[j];
|
|
}
|
|
count++;
|
|
}
|
|
}
|
|
return changedMap;
|
|
};
|
|
|
|
//*****external links*****
|
|
//при открытии ждём ссылок в виде [1]Sheet1!A1:A2, но если пользователь введёт такую ссылку, то текст самой ссылки будет уже "1", а индекс самой ссылки увеличится length + 1
|
|
//далее отображаем в таком виде в зависимости от самой ссылки 'https://s3.amazonaws.com/xlsx/[ExternalLinksDestination.xlsx]Sheet1'!A1:A2
|
|
//при вводе с клавиатуры сложнее - мс пропускает ссылки в достаточно странном виде 'abracadabra1://abracadabra2:[file.abracadabra3]Sheet1'!A1:A2
|
|
Workbook.prototype.getExternalLinkByIndex = function (index, needSplit) {
|
|
var res = this.externalReferences && this.externalReferences[index];
|
|
if (needSplit && res) {
|
|
//разбиваем на имя и путь
|
|
//ms обрабатывает http:/https:/ftp: и любая конструкция до : - ..test..:
|
|
//предполагаем, что здесь уже лежит ссылка в грамотном виде
|
|
//ищем последний слэш или двоеточие и разделяем на части
|
|
res = res.Id;
|
|
var lastSlash = "/";
|
|
var checkPrefix = "file:///";
|
|
var prefixFile = "";
|
|
if (0 === res.indexOf(checkPrefix)) {
|
|
res = res.substring(8);
|
|
prefixFile = checkPrefix;
|
|
lastSlash = "\\";
|
|
}
|
|
|
|
for (let i = res.length - 1; i >= 0; i--) {
|
|
if (res[i] === lastSlash || res[i] === ":" || (res[i] === "\\" && res.indexOf(":") !== -1)) {
|
|
return {path: prefixFile + res.substring(0, i + 1), name: res.substring(i + 1, res.length)};
|
|
}
|
|
}
|
|
if (res) {
|
|
res = {path: prefixFile + "", name: res};
|
|
}
|
|
}
|
|
return res ? res : null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalLinkByName = function (name) {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].Id === name) {
|
|
return this.externalReferences[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.getExternalLinkIndexByName = function (name) {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].Id === name) {
|
|
return i + 1;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalLinkIndexById = function (id) {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i]._id === id) {
|
|
return i + 1;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalLinkIndexBySheetId = function (sheetId) {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
for (var j in this.externalReferences[i].worksheets) {
|
|
if (this.externalReferences[i].worksheets[j].Id === sheetId) {
|
|
return i + 1;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalWorksheet = function (val, sheet, getFirstSheet) {
|
|
let extarnalLink = this.getExternalLink(val);
|
|
if (extarnalLink) {
|
|
if (getFirstSheet && extarnalLink.SheetNames) {
|
|
sheet = extarnalLink.SheetNames[0];
|
|
}
|
|
|
|
if (null == sheet) {
|
|
return null;
|
|
}
|
|
if (extarnalLink.worksheets && extarnalLink.worksheets[sheet]) {
|
|
return extarnalLink.worksheets[sheet];
|
|
}
|
|
if (extarnalLink.SheetNames) {
|
|
for (var i = 0; i < extarnalLink.SheetNames.length; i++) {
|
|
if (extarnalLink.SheetNames[i] === sheet) {
|
|
return extarnalLink.initWorksheet(sheet);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalLink = function (val) {
|
|
return window['AscCommon'].isNumber(val) ? this.getExternalLinkByIndex(val - 1) : this.getExternalLinkByName(val);
|
|
};
|
|
|
|
Workbook.prototype.getExternalWorksheetByIndex = function (index, sheet) {
|
|
var extarnalLink = this.getExternalLinkByIndex(index);
|
|
if (extarnalLink) {
|
|
if (extarnalLink.worksheets && extarnalLink.worksheets[sheet]) {
|
|
return extarnalLink.worksheets[sheet];
|
|
}
|
|
if (extarnalLink.SheetNames) {
|
|
for (var i = 0; i < extarnalLink.SheetNames.length; i++) {
|
|
if (extarnalLink.SheetNames[i] === sheet) {
|
|
var wb = this.getTemporaryExternalWb();
|
|
extarnalLink.worksheets[sheet] = new Worksheet(wb);
|
|
return extarnalLink.worksheets[sheet];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalWorksheetByName = function (name, sheet) {
|
|
var extarnalLink = this.getExternalLinkByName(name);
|
|
if (extarnalLink) {
|
|
if (extarnalLink.worksheets && extarnalLink.worksheets[sheet]) {
|
|
return extarnalLink.worksheets[sheet];
|
|
}
|
|
if (extarnalLink.SheetNames) {
|
|
for (var i = 0; i < extarnalLink.SheetNames.length; i++) {
|
|
if (extarnalLink.SheetNames[i] === sheet) {
|
|
var wb = this.getTemporaryExternalWb();
|
|
extarnalLink.worksheets[sheet] = new Worksheet(wb);
|
|
return extarnalLink.worksheets[sheet];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getTemporaryExternalWb = function () {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].worksheets) {
|
|
for (var j in this.externalReferences[i].worksheets) {
|
|
if (this.externalReferences[i].worksheets[j]) {
|
|
return this.externalReferences[i].worksheets[j].workbook;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return new Workbook(undefined, undefined, false);
|
|
};
|
|
|
|
Workbook.prototype.getExternalIndexByWorksheet = function (ws) {
|
|
let checkedWb = ws && ws.workbook;
|
|
for (let i = 0; i < this.externalReferences.length; i++) {
|
|
let externalWb = this.externalReferences[i] && this.externalReferences[i].getWb && this.externalReferences[i].getWb();
|
|
if (checkedWb === externalWb) {
|
|
if (this.externalReferences[i].worksheets) {
|
|
for (let j in this.externalReferences[i].worksheets) {
|
|
if (this.externalReferences[i].worksheets[j] === ws) {
|
|
return i + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.removeExternalReferences = function (arr) {
|
|
//пока предполагаю, что здесь будет массив asc_CExternalReference
|
|
if (arr) {
|
|
var isChanged = false;
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
for (var i = 0; i < arr.length; i++) {
|
|
var eRIndex = this.getExternalLinkIndexByName(arr[i].externalReference.Id);
|
|
if (eRIndex != null) {
|
|
|
|
//TODO при undo кладутся в массив в обратном порядке - нужно всегда в одном порядке добавлять
|
|
this.removeExternalReference(eRIndex, true);
|
|
isChanged = true;
|
|
|
|
//TODO нужно заменить все ячейки просто значениями, где есть формулы, которые ссылаются на эту книгу
|
|
for (var j in arr[i].externalReference.worksheets) {
|
|
var removedSheet = arr[i].externalReference.worksheets[j];
|
|
if (removedSheet) {
|
|
|
|
var removedSheetId = removedSheet.getId();
|
|
this.dependencyFormulas.forEachSheetListeners(removedSheetId, function (parsed) {
|
|
if (parsed) {
|
|
var cell = parsed.parent;
|
|
if (cell && cell.nCol != null && cell.nRow != null) {
|
|
//нужно удалить формулу из этой ячейки
|
|
parsed.ws._getCellNoEmpty(cell.nRow, cell.nCol, function(cell) {
|
|
var valueData = cell.getValueData();
|
|
valueData.formula = null;
|
|
cell.setValueData(valueData);
|
|
//cell.setFormulaInternal(null);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
var prepared = this.dependencyFormulas.prepareChangeSheet(removedSheetId, {remove: removedSheetId});
|
|
this.dependencyFormulas.removeSheet(prepared);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
AscCommon.History.EndTransaction();
|
|
|
|
if (isChanged) {
|
|
this.handlers && this.handlers.trigger("asc_onUpdateExternalReferenceList");
|
|
}
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.removeExternalReference = function (index, addToHistory) {
|
|
if (index != null) {
|
|
var from = this.externalReferences[index - 1];
|
|
//this.reIndexExternalReferencesLinks(index - 1);
|
|
this._removeExternalReference(index - 1);
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ChangeExternalReference,
|
|
null, null, new UndoRedoData_FromTo(from, null));
|
|
}
|
|
}
|
|
};
|
|
|
|
Workbook.prototype._removeExternalReference = function (index) {
|
|
if (index != null) {
|
|
//need offset last references
|
|
for (let i = index + 1; i < this.externalReferences.length; i++) {
|
|
for (let j in this.externalReferences[i].worksheets) {
|
|
var prepared = this.dependencyFormulas.prepareChangeSheet(this.externalReferences[i].worksheets[j].getId(), {from: i + 1, to: i});
|
|
this.dependencyFormulas.changeExternalLink(prepared);
|
|
}
|
|
}
|
|
|
|
this.externalReferences.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.changeExternalReference = function (index, to) {
|
|
if (index != null) {
|
|
let from = this.externalReferences[index - 1].clone(true);
|
|
// var from = this.externalReferences[index - 1].clone();
|
|
|
|
// change formulas with importRange
|
|
this.changeImportRangeLinks(index, from, to);
|
|
|
|
this.externalReferences[index - 1] = to;
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ChangeExternalReference,
|
|
null, null, new UndoRedoData_FromTo(from, to));
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.changeImportRangeLinks = function (index, fromER, toER) {
|
|
if (index != null && fromER && toER) {
|
|
let fromLinkStr = fromER.Id;
|
|
let toLinkStr = toER.Id;
|
|
|
|
for (let ws in toER.worksheets) {
|
|
let changedSheet = toER.worksheets[ws];
|
|
if (changedSheet) {
|
|
let changedSheetId = changedSheet.getId();
|
|
|
|
this.dependencyFormulas.forEachSheetListeners(changedSheetId, function (parsed) {
|
|
// we go through the external sheet listeners and change each importRange
|
|
let cell = parsed && parsed.parent;
|
|
if (cell && cell && cell.nCol != null && cell.nRow != null && parsed.Formula) {
|
|
let newFormulaStr = "";
|
|
let formula = parsed.getFormula();
|
|
if (formula) {
|
|
newFormulaStr = formula.split(fromLinkStr).join(toLinkStr);
|
|
}
|
|
|
|
if (newFormulaStr) {
|
|
let newFP = new AscCommonExcel.parserFormula(newFormulaStr, cell, parsed.ws);
|
|
let parseResult = new AscCommonExcel.ParseResult();;
|
|
if (newFP.parse(AscCommonExcel.oFormulaLocaleInfo.Parse, AscCommonExcel.oFormulaLocaleInfo.DigitSep, parseResult)) {
|
|
parsed.ws._getCellNoEmpty(cell.nRow, cell.nCol, function(cell) {
|
|
if (cell) {
|
|
cell.setValue("=" + newFormulaStr, null, null, parsed.ref, null, null, true);
|
|
}
|
|
});
|
|
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.addExternalReferences = function (arr) {
|
|
if (arr && arr.length) {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
this.externalReferences.push(arr[i]);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ChangeExternalReference,
|
|
null, null, new UndoRedoData_FromTo(null, arr[i]));
|
|
}
|
|
this.handlers && this.handlers.trigger("asc_onUpdateExternalReferenceList");
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.getExternalLinkByReferenceData = function (referenceData) {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].referenceData) {
|
|
if (this.externalReferences[i].referenceData["fileKey"] === referenceData["fileKey"] && this.externalReferences[i].referenceData["instanceId"] === referenceData["instanceId"]) {
|
|
return {index: i + 1, val: this.externalReferences};
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalReferenceByReferenceData = function (referenceData, returnIndex) {
|
|
if (!referenceData) {
|
|
return null;
|
|
}
|
|
|
|
for (let i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].referenceData) {
|
|
if (this.externalReferences[i].referenceData["fileKey"] === referenceData["fileKey"] && this.externalReferences[i].referenceData["instanceId"] === referenceData["instanceId"]) {
|
|
return returnIndex ? i + 1 : this.externalReferences[i];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalReferenceWithoutRefData = function (id, returnIndex) {
|
|
/* Receive an external link only by name(id) and without reference data */
|
|
for (let i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].Id === id && !this.externalReferences[i].referenceData) {
|
|
return returnIndex ? i + 1 : this.externalReferences[i];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.getExternalReferences = function () {
|
|
var res = null;
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].getAscLink) {
|
|
if (!res) {
|
|
res = [];
|
|
}
|
|
res.push(this.externalReferences[i].getAscLink());
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Workbook.prototype.getExternalReferenceSheetsFromZip = function (stream) {
|
|
//TODO зачитать sharedStrings
|
|
const wb = this;
|
|
const oApi = Asc.editor;
|
|
if (!stream || !(oApi && oApi["asc_isSupportFeature"]("ooxml"))) {
|
|
return null;
|
|
}
|
|
|
|
var openXml = AscCommon.openXml;
|
|
var StaxParser = AscCommon.StaxParser;
|
|
var res = [];
|
|
|
|
AscFormat.ExecuteNoHistory(function() {
|
|
var xmlParserContext = new AscCommon.XmlParserContext();
|
|
xmlParserContext.DrawingDocument = oApi.getDrawingDocument();
|
|
xmlParserContext.InitOpenManager = AscCommonExcel.InitOpenManager ? new AscCommonExcel.InitOpenManager(null, wb) : null;
|
|
if (!xmlParserContext.InitOpenManager) {
|
|
xmlParserContext.InitOpenManager = {};
|
|
}
|
|
xmlParserContext.InitOpenManager.aCellXfs = [];
|
|
xmlParserContext.InitOpenManager.Dxfs = [];
|
|
|
|
var wbPart = null;
|
|
var wbXml = null;
|
|
if (!window.nativeZlibEngine || !window.nativeZlibEngine.open(stream)) {
|
|
return false;
|
|
}
|
|
xmlParserContext.zip = window.nativeZlibEngine;
|
|
|
|
var doc = new openXml.OpenXmlPackage(window.nativeZlibEngine, null);
|
|
|
|
//workbook
|
|
wbPart = doc.getPartByRelationshipType(openXml.Types.workbook.relationType);
|
|
if (wbPart) {
|
|
var contentWorkbook = wbPart.getDocumentContent();
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
wbXml = new AscCommonExcel.CT_Workbook(wb);
|
|
var reader = new StaxParser(contentWorkbook, wbPart, xmlParserContext);
|
|
wbXml.fromXml(reader, {"sheets" : 1});
|
|
});
|
|
}
|
|
|
|
if (wbXml && wbPart) {
|
|
wbXml.readExternalReferences(this, wbPart, xmlParserContext);
|
|
}
|
|
|
|
//sharedString
|
|
var sharedStringPart = wbPart.getPartByRelationshipType(openXml.Types.sharedStringTable.relationType);
|
|
if (sharedStringPart) {
|
|
var contentSharedStrings = sharedStringPart.getDocumentContent();
|
|
if (contentSharedStrings) {
|
|
var sharedStrings = new AscCommonExcel.CT_SharedStrings();
|
|
var reader = new StaxParser(contentSharedStrings, sharedStringPart, xmlParserContext);
|
|
sharedStrings.fromXml(reader);
|
|
}
|
|
}
|
|
|
|
//sheets
|
|
if (wbXml && wbXml.sheets) {
|
|
var wsParts = [];
|
|
|
|
wbXml.sheets.forEach(function (wbSheetXml) {
|
|
//TODO нужно отсеять только необходимые листы
|
|
if (null !== wbSheetXml.id && wbSheetXml.name) {
|
|
var wsPart = wbPart.getPartById(wbSheetXml.id);
|
|
wsParts.push({wsPart: wsPart, id: wbSheetXml.id, name: wbSheetXml.name, bHidden: wbSheetXml.bHidden, sheetId: wbSheetXml.sheetId});
|
|
}
|
|
});
|
|
|
|
wsParts.forEach(function (wbSheetXml) {
|
|
//TODO нужно отсеять только необходимые дипапазоны
|
|
if (null !== wbSheetXml.id && wbSheetXml.name) {
|
|
var wsPart = wbSheetXml.wsPart;
|
|
var contentSheetXml = wsPart && wsPart.getDocumentContent();
|
|
if (contentSheetXml) {
|
|
var ws = new AscCommonExcel.Worksheet(wb, wb.aWorksheets.length);
|
|
ws.sName = wbSheetXml.name;
|
|
if (null !== wbSheetXml.bHidden) {
|
|
ws.bHidden = wbSheetXml.bHidden;
|
|
}
|
|
//var wsView = new AscCommonExcel.asc_CSheetViewSettings();
|
|
//wsView.pane = new AscCommonExcel.asc_CPane();
|
|
//ws.sheetViews.push(wsView);
|
|
if (contentSheetXml) {
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
var reader = new StaxParser(contentSheetXml, wsPart, xmlParserContext);
|
|
ws.fromXml(reader);
|
|
});
|
|
}
|
|
xmlParserContext.InitOpenManager.putSheetAfterRead(wb, ws);
|
|
res.push(ws);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
if (wbXml && wbXml.newDefinedNames) {
|
|
xmlParserContext.InitOpenManager.oReadResult.defNames = wbXml.newDefinedNames;
|
|
xmlParserContext.InitOpenManager.PostLoadPrepareDefNames(wb);
|
|
}
|
|
|
|
var readSheetDataExternal = function (bNoBuildDep) {
|
|
for (var i = 0; i < xmlParserContext.InitOpenManager.oReadResult.sheetData.length; ++i) {
|
|
var sheetDataElem = xmlParserContext.InitOpenManager.oReadResult.sheetData[i];
|
|
var ws = sheetDataElem.ws;
|
|
|
|
var tmp = {
|
|
pos: null,
|
|
len: null,
|
|
bNoBuildDep: bNoBuildDep,
|
|
ws: ws,
|
|
row: new AscCommonExcel.Row(ws),
|
|
cell: new AscCommonExcel.Cell(ws),
|
|
formula: new AscCommonExcel.OpenFormula(),
|
|
sharedFormulas: {},
|
|
prevFormulas: {},
|
|
siFormulas: {},
|
|
prevRow: -1,
|
|
prevCol: -1,
|
|
formulaArray: []
|
|
};
|
|
|
|
|
|
var sheetData = new AscCommonExcel.CT_SheetData();
|
|
xmlParserContext.InitOpenManager.tmp = tmp;
|
|
|
|
sheetDataElem.reader.setState(sheetDataElem.state);
|
|
//TODO пересмотреть фунцию fromXml
|
|
sheetData.fromXml2(sheetDataElem.reader);
|
|
|
|
if (!bNoBuildDep) {
|
|
//TODO возможно стоит делать это в worksheet после полного чтения
|
|
//***array-formula***
|
|
//добавление ко всем ячейкам массива головной формулы
|
|
for (var j = 0; j < tmp.formulaArray.length; j++) {
|
|
var curFormula = tmp.formulaArray[j];
|
|
var ref = curFormula.ref;
|
|
if (ref) {
|
|
var rangeFormulaArray = tmp.ws.getRange3(ref.r1, ref.c1, ref.r2, ref.c2);
|
|
rangeFormulaArray._foreach(function (cell) {
|
|
cell.setFormulaInternal(curFormula);
|
|
if (curFormula.ca || cell.isNullTextString()) {
|
|
tmp.ws.workbook.dependencyFormulas.addToChangedCell(cell);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
for (var nCol in tmp.prevFormulas) {
|
|
if (tmp.prevFormulas.hasOwnProperty(nCol)) {
|
|
var prevFormula = tmp.prevFormulas[nCol];
|
|
if (!tmp.siFormulas[prevFormula.parsed.getListenerId()]) {
|
|
prevFormula.parsed.buildDependencies();
|
|
}
|
|
}
|
|
}
|
|
for (var listenerId in tmp.siFormulas) {
|
|
if (tmp.siFormulas.hasOwnProperty(listenerId)) {
|
|
tmp.siFormulas[listenerId].buildDependencies();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
xmlParserContext.InitOpenManager.aCellXfs = [];
|
|
xmlParserContext.InitOpenManager.Dxfs = [];
|
|
|
|
readSheetDataExternal(true);
|
|
}, this, []);
|
|
|
|
return res;
|
|
};
|
|
|
|
Workbook.prototype.removeExternalReferenceBySheet = function (sheetId) {
|
|
//пока предполагаю, что здесь будет массив asc_CExternalReference
|
|
let index = this.getExternalLinkIndexBySheetId(sheetId);
|
|
if (index !== null) {
|
|
let eR = this.externalReferences[index - 1];
|
|
// If there are no more listeners for the external document, delete the external link
|
|
this.removeExternalReference(index, true);
|
|
|
|
// if (eR.SheetNames.length === 1) {
|
|
// //удаляем ссылку
|
|
// this.removeExternalReference(index, true);
|
|
// } else {
|
|
// let to = eR.clone();
|
|
// eR.removeSheetById(sheetId);
|
|
// this.changeExternalReference(index, eR);
|
|
// }
|
|
this.handlers && this.handlers.trigger("asc_onUpdateExternalReferenceList");
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.getExternalReferenceById = function (id, returnIndex) {
|
|
for (var i = 0; i < this.externalReferences.length; i++) {
|
|
if (this.externalReferences[i].Id === id) {
|
|
return returnIndex ? i : this.externalReferences[i];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Workbook.prototype.addExternalReferencesAfterParseFormulas = function (externalReferenesNeedAdd) {
|
|
let newExternalReferences = [];
|
|
for (let i in externalReferenesNeedAdd) {
|
|
let needAdd = false;
|
|
let newExternalReference = this.getExternalReferenceById(i);
|
|
if (!newExternalReference) {
|
|
newExternalReference = new AscCommonExcel.ExternalReference();
|
|
newExternalReference.Id = i;
|
|
needAdd = true;
|
|
}
|
|
|
|
for (let j = 0; j < externalReferenesNeedAdd[i].length; j++) {
|
|
let oNewSheet = externalReferenesNeedAdd[i][j];
|
|
if (null === newExternalReference.getSheetByName(oNewSheet.sheet)) {
|
|
let newSheet = oNewSheet.sheet;
|
|
newExternalReference.addSheetName(newSheet, true);
|
|
newExternalReference.initWorksheetFromSheetDataSet(newSheet);
|
|
}
|
|
if (oNewSheet.notUpdateId) {
|
|
newExternalReference.notUpdateId = true;
|
|
}
|
|
}
|
|
|
|
if (needAdd) {
|
|
newExternalReferences.push(newExternalReference);
|
|
} else {
|
|
//this.changeExternalReference();
|
|
}
|
|
}
|
|
|
|
this.addExternalReferences(newExternalReferences);
|
|
};
|
|
|
|
Workbook.prototype.setUpdateLinks = function (val, addToHistory, bFirstStart, bNotStartTimer) {
|
|
var from = !!(this.workbookPr.getUpdateLinks());
|
|
if (val !== from) {
|
|
this.workbookPr.setUpdateLinks(val);
|
|
if (addToHistory) {
|
|
History.Create_NewPoint();
|
|
History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_UpdateLinks,
|
|
null, null, new UndoRedoData_FromTo(from, val));
|
|
}
|
|
!bNotStartTimer && this.handlers && this.handlers.trigger("changeUpdateLinks");
|
|
} else if (bFirstStart) {
|
|
!bNotStartTimer && this.handlers && this.handlers.trigger("changeUpdateLinks");
|
|
}
|
|
};
|
|
|
|
Workbook.prototype.getUpdateLinks = function () {
|
|
return this.workbookPr && this.workbookPr.getUpdateLinks();
|
|
};
|
|
|
|
Workbook.prototype.unlockUserProtectedRanges = function(){
|
|
this.forEach(function (ws) {
|
|
ws.unlockUserProtectedRanges();
|
|
});
|
|
};
|
|
|
|
Workbook.prototype.isUserProtectedRangesIntersection = function(range, userId){
|
|
let res = false;
|
|
for (var i = 0, l = this.aWorksheets.length; i < l; ++i) {
|
|
if (this.aWorksheets[i].isUserProtectedRangesIntersection(range, userId)) {
|
|
return true;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Workbook.prototype.checkUserProtectedRangeName = function (name) {
|
|
var res = c_oAscDefinedNameReason.OK;
|
|
//TODO пересмотреть проверку на rx_defName
|
|
if (!AscCommon.rx_protectedRangeName.test(name.toLowerCase()) || name.length > g_nDefNameMaxLength) {
|
|
return c_oAscDefinedNameReason.WrongName;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Workbook.prototype.clearFileCustomFunctions = function (name) {
|
|
this.fileCustomFunctions = null;
|
|
};
|
|
|
|
/******GOAL SEEK******
|
|
/**
|
|
* Initializes and starts goal seek calculation.
|
|
* @param {string} sFormulaCell
|
|
* @param {string} sExpectedValue
|
|
* @param {string} sChangingCell
|
|
* @param {Worksheet} wsFormula
|
|
* @param {Worksheet} wsChangingCell
|
|
*/
|
|
Workbook.prototype.startGoalSeek = function(sFormulaCell, sExpectedValue, sChangingCell, wsFormula, wsChangingCell) {
|
|
let oParserFormula;
|
|
let oFormulaCell = wsFormula.getCell2(sFormulaCell);
|
|
wsFormula._getCell(oFormulaCell.bbox.r1, oFormulaCell.bbox.c1, function (cell) {
|
|
oParserFormula = cell.getFormulaParsed();
|
|
});
|
|
|
|
this.setGoalSeek(new AscCommonExcel.CGoalSeek(oParserFormula, Number(sExpectedValue), wsChangingCell.getRange2(sChangingCell)));
|
|
let oGoalSeek = this.getGoalSeek();
|
|
// Run goal seek
|
|
oGoalSeek.init();
|
|
oGoalSeek.setIntervalId(setInterval(function () {
|
|
let bIsFinish = oGoalSeek.calculate();
|
|
if (bIsFinish) {
|
|
clearInterval(oGoalSeek.getIntervalId());
|
|
}
|
|
}, oGoalSeek.getDelay()));
|
|
};
|
|
/**
|
|
* Returns object with goal seek result
|
|
* @returns {CGoalSeek}
|
|
*/
|
|
Workbook.prototype.getGoalSeek = function() {
|
|
return this.oGoalSeek;
|
|
};
|
|
/**
|
|
* Sets object with goal seek result
|
|
* @param {CGoalSeek} oGoalSeek
|
|
*/
|
|
Workbook.prototype.setGoalSeek = function(oGoalSeek) {
|
|
this.oGoalSeek = oGoalSeek;
|
|
};
|
|
/**
|
|
* Discards goal seek result for "Changing cell" to original
|
|
*/
|
|
Workbook.prototype.closeGoalSeek = function () {
|
|
let oGoalSeek = this.getGoalSeek();
|
|
if (!oGoalSeek) {
|
|
return;
|
|
}
|
|
let oChangedCell = oGoalSeek.getChangingCell();
|
|
let nFirstChangingVal = oGoalSeek.getFirstChangingValue();
|
|
oChangedCell.setValue(nFirstChangingVal == null ? "" : nFirstChangingVal + "");
|
|
this.setGoalSeek(null);
|
|
};
|
|
/**
|
|
* Saves goal seek result for "Changing cell"
|
|
*/
|
|
Workbook.prototype.saveGoalSeek = function() {
|
|
this.setGoalSeek(null);
|
|
};
|
|
|
|
Workbook.prototype.pauseGoalSeek = function() {
|
|
this.oGoalSeek && this.oGoalSeek.pause();
|
|
};
|
|
|
|
Workbook.prototype.continueGoalSeek = function() {
|
|
this.oGoalSeek && this.oGoalSeek.resume();
|
|
};
|
|
|
|
Workbook.prototype.stepGoalSeek = function() {
|
|
this.oGoalSeek && this.oGoalSeek.step();
|
|
};
|
|
|
|
/**
|
|
* Sets Solver object
|
|
* @memberof Workbook
|
|
* @param {CSolver} oSolver
|
|
*/
|
|
Workbook.prototype.setSolver = function(oSolver) {
|
|
this.oSolver = oSolver;
|
|
};
|
|
|
|
/**
|
|
* Returns Solver object
|
|
* @memberof Workbook
|
|
* @returns {CSolver}
|
|
*/
|
|
Workbook.prototype.getSolver = function() {
|
|
return this.oSolver;
|
|
};
|
|
|
|
Workbook.prototype.setDefaultDirection = function(val) {
|
|
this.defaultDirection = val;
|
|
};
|
|
Workbook.prototype.getDefaultDirection = function() {
|
|
return this.defaultDirection;
|
|
};
|
|
Workbook.prototype.setShowVerticalScroll = function(val, addToHistory) {
|
|
var from = this.showVerticalScroll;
|
|
if (from !== val) {
|
|
if (addToHistory) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ShowVerticalScroll, null, null, new UndoRedoData_FromTo(from, val));
|
|
}
|
|
this.showVerticalScroll = val;
|
|
this.handlers && this.handlers.trigger("updateScrollVisibility");
|
|
}
|
|
};
|
|
Workbook.prototype.getShowVerticalScroll = function() {
|
|
return this.showVerticalScroll;
|
|
};
|
|
Workbook.prototype.setShowHorizontalScroll = function(val, addToHistory) {
|
|
var from = this.showHorizontalScroll;
|
|
if (from !== val) {
|
|
if (addToHistory) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorkbook, AscCH.historyitem_Workbook_ShowHorizontalScroll, null, null, new UndoRedoData_FromTo(from, val));
|
|
}
|
|
this.showHorizontalScroll = val;
|
|
this.handlers && this.handlers.trigger("updateScrollVisibility");
|
|
}
|
|
};
|
|
Workbook.prototype.getShowHorizontalScroll = function() {
|
|
return this.showHorizontalScroll;
|
|
};
|
|
Workbook.prototype.getAllInks = function(arrInks) {
|
|
arrInks = arrInks || [];
|
|
for (let i = 0; i < this.aWorksheets.length; i += 1) {
|
|
const oWorksheet = this.aWorksheets[i];
|
|
oWorksheet.getAllInks(arrInks);
|
|
}
|
|
return arrInks;
|
|
};
|
|
|
|
/**
|
|
* @returns {AscWord.CustomXmlManager}
|
|
*/
|
|
Workbook.prototype.getCustomXmlManager = function()
|
|
{
|
|
return this.customXmlManager;
|
|
};
|
|
Workbook.prototype.addExternalReferenceFromWorksheets = function(oWorksheets, oPastedWb, oWorksheetWb) {
|
|
const oApi = Asc.editor;
|
|
const oWs = oApi.wb.getWorksheet();
|
|
if (!oWs)
|
|
return;
|
|
|
|
for (let i in oWorksheets) {
|
|
oWorksheetWb.aWorksheets.push(oWorksheets[i].ws);
|
|
}
|
|
|
|
let nChangeExternalReferenceIndex = null;
|
|
let oMainExternalReference;
|
|
const allDefNames = [];
|
|
for (let sSheetName in oWorksheets) {
|
|
const oWorksheetInfo = oWorksheets[sSheetName];
|
|
const arrRanges = [new Asc.Range(oWorksheetInfo.minC, oWorksheetInfo.minR, oWorksheetInfo.maxC, oWorksheetInfo.maxR)];
|
|
const oPastedWS = oWorksheetInfo.ws;
|
|
const defNames = oWorksheetInfo.defNames;
|
|
|
|
const oCellPasteHelper = oWs.cellPasteHelper;
|
|
const oPastedLinkInfo = oCellPasteHelper.getPastedLinkInfo(oPastedWb, oPastedWS);
|
|
|
|
if (oPastedLinkInfo) {
|
|
if (oPastedLinkInfo.type === -1) {
|
|
const pasteSheetLinkName = oPastedLinkInfo.sheet;
|
|
//необходимо положить нужные данные в SheetDataSet
|
|
oMainExternalReference = this.externalReferences[oPastedLinkInfo.index - 1];
|
|
if (oMainExternalReference) {
|
|
oMainExternalReference.updateSheetData(pasteSheetLinkName, oPastedWS, arrRanges);
|
|
nChangeExternalReferenceIndex = oPastedLinkInfo.index;
|
|
}
|
|
allDefNames.push.apply(allDefNames, defNames);
|
|
} else if (oPastedLinkInfo.type === -2) {
|
|
if (!oMainExternalReference) {
|
|
var referenceData;
|
|
var name = oPastedWb.Core.title;
|
|
if (window["AscDesktopEditor"] && window["AscDesktopEditor"]["IsLocalFile"]()) {
|
|
name = oPastedLinkInfo.path;
|
|
} else if (oPastedWb && oPastedWb.Core) {
|
|
referenceData = {};
|
|
referenceData["fileKey"] = oPastedWb.Core.contentStatus;
|
|
referenceData["instanceId"] = oPastedWb.Core.category;
|
|
}
|
|
|
|
oMainExternalReference = new AscCommonExcel.ExternalReference();
|
|
oMainExternalReference.referenceData = referenceData;
|
|
oMainExternalReference.Id = name;
|
|
}
|
|
|
|
allDefNames.push.apply(allDefNames, defNames);
|
|
oMainExternalReference.addSheet(oPastedWS, arrRanges);
|
|
}
|
|
}
|
|
}
|
|
if (oMainExternalReference) {
|
|
oMainExternalReference.initDefinedNamesOnCopyPaste(allDefNames);
|
|
if (nChangeExternalReferenceIndex === null) {
|
|
this.addExternalReferences([oMainExternalReference]);
|
|
} else {
|
|
this.changeExternalReference(nChangeExternalReferenceIndex, oMainExternalReference);
|
|
}
|
|
}
|
|
return oMainExternalReference;
|
|
};
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function Worksheet(wb, _index, sId){
|
|
this.workbook = wb;
|
|
this.sName = this.workbook.getUniqueSheetNameFrom(g_sNewSheetNamePattern, false);
|
|
this.bHidden = false;
|
|
this.oSheetFormatPr = new AscCommonExcel.SheetFormatPr();
|
|
this.index = _index;
|
|
this.Id = null != sId ? sId : AscCommon.g_oIdCounter.Get_NewId();//todo AscCommon.g_oTableId.Add
|
|
this.nRowsCount = 0;
|
|
this.nColsCount = 0;
|
|
this.rowsData = new AscCommonExcel.SheetMemory(AscCommonExcel.g_nRowStructSize, gc_nMaxRow0);
|
|
this.cellsByCol = [];
|
|
this.cellsByColRowsCount = 0;//maximum rows count in cellsByCol
|
|
this.aCols = [];// 0 based
|
|
this.hiddenManager = new HiddenManager(this);
|
|
this.Drawings = [];
|
|
this.TableParts = [];
|
|
this.AutoFilter = null;
|
|
this.oAllCol = null;
|
|
this.aComments = [];
|
|
var oThis = this;
|
|
this.bExcludeHiddenRows = false;
|
|
this.bIgnoreWriteFormulas = false;
|
|
this.mergeManager = new RangeDataManager(function(data, from, to){
|
|
if(AscCommon.History.Is_On() && (null != from || null != to))
|
|
{
|
|
if(null != from)
|
|
from = from.clone();
|
|
if(null != to)
|
|
to = to.clone();
|
|
var oHistoryRange = from;
|
|
if(null == oHistoryRange)
|
|
oHistoryRange = to;
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ChangeMerge, oThis.getId(), oHistoryRange, new UndoRedoData_FromTo(new UndoRedoData_BBox(from), new UndoRedoData_BBox(to)));
|
|
}
|
|
//расширяем границы
|
|
if(null != to){
|
|
var maxRow = gc_nMaxRow0 !== to.r2 ? to.r2 : to.r1;
|
|
var maxCol = gc_nMaxCol0 !== to.c2 ? to.c2 : to.c1;
|
|
if(maxRow >= oThis.nRowsCount)
|
|
oThis.nRowsCount = maxRow + 1;
|
|
if(maxCol >= oThis.nColsCount)
|
|
oThis.setColsCount(maxCol + 1);
|
|
}
|
|
});
|
|
this.mergeManager.worksheet = this;
|
|
this.hyperlinkManager = new RangeDataManager(function(data, from, to, oChangeParam){
|
|
if(AscCommon.History.Is_On() && (null != from || null != to))
|
|
{
|
|
if(null != from)
|
|
from = from.clone();
|
|
if(null != to)
|
|
to = to.clone();
|
|
var oHistoryRange = from;
|
|
if(null == oHistoryRange)
|
|
oHistoryRange = to;
|
|
var oHistoryData = null;
|
|
if(null == from || null == to)
|
|
oHistoryData = data.clone();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ChangeHyperlink, oThis.getId(), oHistoryRange, new AscCommonExcel.UndoRedoData_FromToHyperlink(from, to, oHistoryData));
|
|
}
|
|
if (null != to)
|
|
data.Ref = oThis.getRange3(to.r1, to.c1, to.r2, to.c2);
|
|
else if (oChangeParam && oChangeParam.removeStyle && null != data.Ref)
|
|
data.Ref.cleanFormat();
|
|
//расширяем границы
|
|
if(null != to){
|
|
var maxRow = gc_nMaxRow0 !== to.r2 ? to.r2 : to.r1;
|
|
var maxCol = gc_nMaxCol0 !== to.c2 ? to.c2 : to.c1;
|
|
if(maxRow >= oThis.nRowsCount)
|
|
oThis.nRowsCount = maxRow + 1;
|
|
if(maxCol >= oThis.nColsCount)
|
|
oThis.setColsCount(maxCol + 1);
|
|
}
|
|
});
|
|
this.hyperlinkManager.setDependenceManager(this.mergeManager);
|
|
this.sheetViews = [];
|
|
this.aConditionalFormattingRules = null;
|
|
|
|
this.conditionalFormattingRangeIterator = null;
|
|
this.updateConditionalFormattingRange = null;
|
|
this.dataValidations = null;
|
|
this.sheetPr = null;
|
|
this.aFormulaExt = null;
|
|
|
|
this.autoFilters = AscCommonExcel.AutoFilters !== undefined ? new AscCommonExcel.AutoFilters(this) : null;
|
|
this.sortState = null;
|
|
|
|
this.contentChanges = new AscCommon.CContentChanges();
|
|
|
|
this.aSparklineGroups = [];
|
|
|
|
this.selectionRange = new AscCommonExcel.SelectionRange(this);
|
|
this.copySelection = null;
|
|
|
|
this.sheetMergedStyles = new AscCommonExcel.SheetMergedStyles();
|
|
this.pivotTables = [];
|
|
this.headerFooter = new Asc.CHeaderFooter(this);
|
|
this.rowBreaks = null;
|
|
this.colBreaks = null;
|
|
this.legacyDrawingHF = null;
|
|
this.picture = null;
|
|
|
|
this.PagePrintOptions = new Asc.asc_CPageOptions(this);
|
|
//***array-formula***
|
|
//TODO пересмотреть. нужно для того, чтобы хранить ссылку на parserFormula главной ячейки при проходе по range массива
|
|
this.formulaArrayLink = null;
|
|
|
|
this.lastFindOptions = null;
|
|
|
|
//чтобы разделять ситуации, когда группы скрываются/открываются из меню(в данном случае не скрываются внутренние группы)
|
|
//и ситуацию, когда группы скрываются/открываются при скрытии строк/столбцов(все внутренние группы скрываются)
|
|
//этот флаг проставляются в true при скрытии групп из меню группировки(нажатие на +/- и скрытие целиком всего уровня)
|
|
//в данном случае не нужно при скрытии строк делать setCollapsed(из-за внутренних групп) и заносить данные в историю
|
|
//во всех остальных ситуациях это делать необходимо
|
|
this.bExcludeCollapsed = false;
|
|
|
|
this.oNumFmtsOpen = {};
|
|
this.dxfsOpen = [];//todo move to InitOpenManager
|
|
|
|
/*handlers*/
|
|
this.handlers = null;
|
|
|
|
this.aSlicers = [];
|
|
|
|
this.aNamedSheetViews = [];
|
|
this.activeNamedSheetViewId = null;
|
|
this.defaultViewHiddenRows = null;
|
|
|
|
this.sheetProtection = null;
|
|
this.aProtectedRanges = [];
|
|
this.aCellWatches = [];
|
|
|
|
this.userProtectedRanges = [];
|
|
|
|
this.bFillHandleRightClick = false;
|
|
this.nFillMenuChosenProp = null;
|
|
this.activeFillType = null;
|
|
this.timelines = [];
|
|
this.changedArrays = null;
|
|
}
|
|
|
|
Worksheet.prototype.getCompiledStyle = function (row, col, opt_cell, opt_styleComponents, opt_AffectingText) {
|
|
return getCompiledStyle(this.sheetMergedStyles, this.hiddenManager, row, col, opt_cell, this, opt_styleComponents, opt_AffectingText);
|
|
};
|
|
Worksheet.prototype.getCompiledStyleCustom = function(row, col, needTable, needCell, needConditional, opt_cell) {
|
|
var res;
|
|
var styleComponents = this.sheetMergedStyles.getStyle(this.hiddenManager, row, col, this);
|
|
var ws = this;
|
|
if (!needTable) {
|
|
styleComponents.table = [];
|
|
}
|
|
if (!needConditional) {
|
|
styleComponents.conditional = [];
|
|
}
|
|
if (!needCell) {
|
|
res = getCompiledStyle(undefined, undefined, row, col, undefined, undefined, styleComponents);
|
|
} else if (opt_cell) {
|
|
res = getCompiledStyle(undefined, undefined, row, col, opt_cell, ws, styleComponents);
|
|
} else {
|
|
this._getCellNoEmpty(row, col, function(cell) {
|
|
res = getCompiledStyle(undefined, undefined, row, col, cell, ws, styleComponents);
|
|
});
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getColData = function(index) {
|
|
var sheetMemory = this.cellsByCol[index];
|
|
if(!sheetMemory){
|
|
sheetMemory = new AscCommonExcel.SheetMemory(g_nCellStructSize, gc_nMaxRow0);
|
|
this.cellsByCol[index] = sheetMemory;
|
|
}
|
|
return sheetMemory;
|
|
};
|
|
Worksheet.prototype.getColDataNoEmpty = function(index) {
|
|
return this.cellsByCol[index];
|
|
};
|
|
Worksheet.prototype.getColDataLength = function() {
|
|
return this.cellsByCol.length;
|
|
};
|
|
//returns minimal range containing all no empty cells
|
|
Worksheet.prototype.getMinimalRange = function() {
|
|
var oRange = null;
|
|
this._forEachCell(function(oCell) {
|
|
if(!oCell.isEmpty()) {
|
|
if(oRange === null) {
|
|
oRange = new Asc.Range(oCell.nCol, oCell.nRow, oCell.nCol, oCell.nRow)
|
|
} else {
|
|
oRange.union3(oCell.nCol, oCell.nRow)
|
|
}
|
|
}
|
|
});
|
|
return oRange;
|
|
};
|
|
Worksheet.prototype.getSnapshot = function(wb) {
|
|
var ws = new Worksheet(wb, this.index, this.Id);
|
|
ws.sName = this.sName;
|
|
for (var i = 0; i < this.TableParts.length; ++i) {
|
|
var table = this.TableParts[i];
|
|
ws.addTablePart(table.clone(null), false);
|
|
}
|
|
for (i = 0; i < this.sheetViews.length; ++i) {
|
|
ws.sheetViews.push(this.sheetViews[i].clone());
|
|
}
|
|
return ws;
|
|
};
|
|
Worksheet.prototype.addContentChanges = function (changes) {
|
|
this.contentChanges.Add(changes);
|
|
};
|
|
Worksheet.prototype.refreshContentChanges = function () {
|
|
this.contentChanges.Refresh();
|
|
this.contentChanges.Clear();
|
|
};
|
|
Worksheet.prototype.rebuildColors=function(){
|
|
this.rebuildTabColor();
|
|
|
|
for (var i = 0; i < this.aSparklineGroups.length; ++i) {
|
|
this.aSparklineGroups[i].cleanCache();
|
|
}
|
|
};
|
|
Worksheet.prototype.generateFontMap=function(oFontMap){
|
|
//пробегаемся по Drawing
|
|
for(var i = 0, length = this.Drawings.length; i < length; ++i)
|
|
{
|
|
var drawing = this.Drawings[i];
|
|
if(drawing)
|
|
drawing.getAllFonts(oFontMap);
|
|
}
|
|
|
|
//пробегаемся по header/footer
|
|
if(this.headerFooter){
|
|
this.headerFooter.getAllFonts(oFontMap);
|
|
}
|
|
};
|
|
Worksheet.prototype.getAllImageUrls = function(aImages){
|
|
for(var i = 0; i < this.Drawings.length; ++i){
|
|
this.Drawings[i].graphicObject.getAllRasterImages(aImages);
|
|
}
|
|
};
|
|
Worksheet.prototype.reassignImageUrls = function(oImages){
|
|
for(var i = 0; i < this.Drawings.length; ++i){
|
|
this.Drawings[i].graphicObject.Reassign_ImageUrls(oImages);
|
|
}
|
|
};
|
|
Worksheet.prototype.copyFrom=function(wsFrom, sName, tableNames){
|
|
var i, elem, range, _newSlicer;
|
|
var t = this;
|
|
this.sName = this.workbook.checkValidSheetName(sName) ? sName : this.workbook.getUniqueSheetNameFrom(wsFrom.sName, true);
|
|
this.bHidden = wsFrom.bHidden;
|
|
this.oSheetFormatPr = wsFrom.oSheetFormatPr.clone();
|
|
//this.index = wsFrom.index;
|
|
this.nRowsCount = wsFrom.nRowsCount;
|
|
this.setColsCount(wsFrom.nColsCount);
|
|
var renameParams = {lastName: wsFrom.getName(), newName: this.getName(), tableNameMap: {}, slicerNameMap: {}, copySlicerError: false};
|
|
for (i = 0; i < wsFrom.TableParts.length; ++i)
|
|
{
|
|
var tableFrom = wsFrom.TableParts[i];
|
|
var tableTo = tableFrom.clone(null);
|
|
if(tableNames && tableNames.length) {
|
|
tableTo.changeDisplayName(tableNames[i]);
|
|
} else {
|
|
tableTo.changeDisplayName(this.workbook.dependencyFormulas.getNextTableName());
|
|
}
|
|
this.addTablePart(tableTo, true);
|
|
renameParams.tableNameMap[tableFrom.DisplayName] = tableTo.DisplayName;
|
|
}
|
|
for (i = 0; i < this.TableParts.length; ++i) {
|
|
this.TableParts[i].renameSheetCopy(this, renameParams);
|
|
}
|
|
if(wsFrom.AutoFilter)
|
|
this.AutoFilter = wsFrom.AutoFilter.clone();
|
|
for (i in wsFrom.aCols) {
|
|
var col = wsFrom.aCols[i];
|
|
if(null != col)
|
|
this.aCols[i] = col.clone(this);
|
|
}
|
|
if(null != wsFrom.oAllCol)
|
|
this.oAllCol = wsFrom.oAllCol.clone(this);
|
|
|
|
//copy row/cell data
|
|
this.rowsData = wsFrom.rowsData.clone();
|
|
wsFrom._forEachColData(function(sheetMemory, index){
|
|
t.cellsByCol[index] = sheetMemory.clone();
|
|
});
|
|
this.cellsByColRowsCount = wsFrom.cellsByColRowsCount;
|
|
|
|
var aMerged = wsFrom.mergeManager.getAll();
|
|
for(i in aMerged)
|
|
{
|
|
elem = aMerged[i];
|
|
range = this.getRange3(elem.bbox.r1, elem.bbox.c1, elem.bbox.r2, elem.bbox.c2);
|
|
range.mergeOpen();
|
|
}
|
|
var aHyperlinks = wsFrom.hyperlinkManager.getAll();
|
|
for(i in aHyperlinks)
|
|
{
|
|
elem = aHyperlinks[i];
|
|
range = this.getRange3(elem.bbox.r1, elem.bbox.c1, elem.bbox.r2, elem.bbox.c2);
|
|
range.setHyperlinkOpen(elem.data);
|
|
}
|
|
if(null != wsFrom.aComments) {
|
|
for (i = 0; i < wsFrom.aComments.length; i++) {
|
|
var comment = wsFrom.aComments[i].clone(true);
|
|
comment.wsId = this.getId();
|
|
comment.nId = "sheet" + comment.wsId + "_" + (i + 1);
|
|
this.aComments.push(comment);
|
|
}
|
|
}
|
|
for (i = 0; i < wsFrom.sheetViews.length; ++i) {
|
|
this.sheetViews.push(wsFrom.sheetViews[i].clone());
|
|
}
|
|
if (wsFrom.isConditionalFormattingRules()) {
|
|
let t = this;
|
|
wsFrom.forEachConditionalFormattingRules(function (val) {
|
|
t.addConditionalFormattingRule(val);
|
|
})
|
|
}
|
|
if (wsFrom.sheetPr)
|
|
this.sheetPr = wsFrom.sheetPr.clone();
|
|
|
|
this.selectionRange = wsFrom.selectionRange.clone(this);
|
|
|
|
if(wsFrom.PagePrintOptions) {
|
|
this.PagePrintOptions = wsFrom.PagePrintOptions.clone(this);
|
|
}
|
|
|
|
//copy headers/footers
|
|
if(wsFrom.headerFooter) {
|
|
this.headerFooter = wsFrom.headerFooter.clone(this);
|
|
}
|
|
|
|
for (i = 0; i < wsFrom.aSlicers.length; ++i) {
|
|
//пока только для таблиц
|
|
var _slicer = wsFrom.aSlicers[i];
|
|
var _table = _slicer.getTableSlicerCache();
|
|
var pivotCache = _slicer.getPivotCache();
|
|
if (_table) {
|
|
var tableIdNew = renameParams.tableNameMap[_table.tableId];
|
|
if (tableIdNew) {
|
|
_newSlicer = this.insertSlicer(_table.column, tableIdNew, window['AscCommonExcel'].insertSlicerType.table);
|
|
_newSlicer.set(_slicer.clone(), true);
|
|
}
|
|
|
|
if (_newSlicer) {
|
|
renameParams.slicerNameMap[_slicer.name] = _newSlicer.name;
|
|
}
|
|
} else if (pivotCache) {
|
|
var _newCacheDefinition = _slicer.getCacheDefinition().clone(this.workbook);
|
|
_newCacheDefinition.name = _newCacheDefinition.generateSlicerCacheName(_newCacheDefinition.name);
|
|
_newSlicer = this.insertSlicer(_slicer.name, undefined, window['AscCommonExcel'].insertSlicerType.pivotTable, undefined, _newCacheDefinition);
|
|
_newCacheDefinition.forCopySheet(wsFrom.getId(), this.getId());
|
|
_newSlicer.set(_slicer.clone(), true);
|
|
renameParams.slicerNameMap[_slicer.name] = _newSlicer.name;
|
|
}
|
|
}
|
|
|
|
if(wsFrom.headerFooter) {
|
|
this.headerFooter = wsFrom.headerFooter.clone(this);
|
|
}
|
|
|
|
if(wsFrom.sheetProtection) {
|
|
this.sheetProtection = wsFrom.sheetProtection.clone(this);
|
|
}
|
|
if(wsFrom.aProtectedRanges) {
|
|
for (i = 0; i < wsFrom.aProtectedRanges.length; i++) {
|
|
if (!this.aProtectedRanges) {
|
|
this.aProtectedRanges = [];
|
|
}
|
|
this.aProtectedRanges.push(wsFrom.aProtectedRanges[i].clone(this));
|
|
}
|
|
}
|
|
|
|
if(wsFrom.colBreaks) {
|
|
this.colBreaks = wsFrom.colBreaks.clone(this);
|
|
}
|
|
if(wsFrom.rowBreaks) {
|
|
this.rowBreaks = wsFrom.rowBreaks.clone(this);
|
|
}
|
|
|
|
return renameParams;
|
|
};
|
|
|
|
Worksheet.prototype.copyFromAfterInsert=function(wsFrom){
|
|
if (!this.workbook.bUndoChanges && !this.workbook.bRedoChanges) {
|
|
for (var i = 0; i < wsFrom.pivotTables.length; ++i) {
|
|
this.insertPivotTable(wsFrom.pivotTables[i].cloneShallow(), true);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.copyFromFormulas=function(renameParams, renameSheetMap) {
|
|
//change cell formulas
|
|
var t = this;
|
|
var oldNewArrayFormulaMap = [];
|
|
this._forEachCell(function(cell) {
|
|
if (cell.isFormula()) {
|
|
var parsed, notMainArrayCell;
|
|
if (cell.transformSharedFormula()) {
|
|
parsed = cell.getFormulaParsed();
|
|
} else {
|
|
parsed = cell.getFormulaParsed();
|
|
if(parsed.getArrayFormulaRef()) {//***array-formula***
|
|
var listenerId = parsed.getListenerId();
|
|
//formula-array: parsed object one of all array cells
|
|
if(oldNewArrayFormulaMap[listenerId]) {
|
|
parsed = oldNewArrayFormulaMap[listenerId];
|
|
notMainArrayCell = true;
|
|
} else {
|
|
parsed = parsed.clone(null, new CCellWithFormula(t, cell.nRow, cell.nCol), t);
|
|
oldNewArrayFormulaMap[listenerId] = parsed;
|
|
}
|
|
} else {
|
|
parsed = parsed.clone(null, new CCellWithFormula(t, cell.nRow, cell.nCol), t);
|
|
}
|
|
}
|
|
|
|
if(renameSheetMap && AscCommon.History.Is_On()) {
|
|
//пишем в историю для того, чтобы для случая redo не делать отложенное действия для всех листов
|
|
var _oldF = parsed.Formula;
|
|
parsed.parse(null, null, null, null, renameSheetMap);
|
|
var _newF = parsed.Formula;
|
|
if(_oldF !== _newF) {
|
|
var DataOld = cell.getValueData();
|
|
var DataNew = cell.getValueData();
|
|
DataNew.formula = _newF;
|
|
if (false == DataOld.isEqual(DataNew)) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue,
|
|
cell.ws.getId(), new Asc.Range(cell.nCol, cell.nRow, cell.nCol, cell.nRow),
|
|
new UndoRedoData_CellSimpleData(cell.nRow, cell.nCol, DataOld, DataNew));
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!notMainArrayCell) {
|
|
parsed.renameSheetCopy(renameParams);
|
|
parsed.setFormulaString(parsed.assemble(true));
|
|
}
|
|
cell.setFormulaInternal(parsed, true);
|
|
t.workbook.dependencyFormulas.addToBuildDependencyCell(cell);
|
|
}
|
|
});
|
|
};
|
|
Worksheet.prototype.cloneSelection = function (start, selectRange) {
|
|
if (start) {
|
|
this.copySelection = this.selectionRange.clone();
|
|
if (selectRange) {
|
|
this.selectionRange.assign2(selectRange);
|
|
} else {
|
|
this.selectionRange = null;
|
|
}
|
|
|
|
} else {
|
|
if (this.copySelection) {
|
|
this.selectionRange = this.copySelection;
|
|
}
|
|
this.copySelection = null;
|
|
}
|
|
};
|
|
Worksheet.prototype.getSelection = function () {
|
|
return this.copySelection || this.selectionRange;
|
|
};
|
|
|
|
Worksheet.prototype.copyObjects = function (oNewWs, renameParams) {
|
|
var i;
|
|
if (null != this.Drawings && this.Drawings.length > 0) {
|
|
var drawingObjects = new AscFormat.DrawingObjects();
|
|
oNewWs.Drawings = [];
|
|
for (i = 0; i < this.Drawings.length; ++i) {
|
|
var _isSlicer = this.Drawings[i].graphicObject.getObjectType() === AscDFH.historyitem_type_SlicerView;
|
|
if (_isSlicer && renameParams && !renameParams.slicerNameMap[this.Drawings[i].graphicObject.name]) {
|
|
renameParams.copySlicerError = true;
|
|
continue;
|
|
}
|
|
|
|
var drawingObject = drawingObjects.cloneDrawingObject(this.Drawings[i]);
|
|
drawingObject.graphicObject = this.Drawings[i].graphicObject.copy(undefined);
|
|
if (_isSlicer && renameParams) {
|
|
drawingObject.graphicObject.setName(renameParams.slicerNameMap[drawingObject.graphicObject.name]);
|
|
}
|
|
|
|
drawingObject.graphicObject.setWorksheet(oNewWs);
|
|
drawingObject.graphicObject.addToDrawingObjects();
|
|
var drawingBase = this.Drawings[i];
|
|
drawingObject.graphicObject.setDrawingBaseCoords(drawingBase.from.col, drawingBase.from.colOff,
|
|
drawingBase.from.row, drawingBase.from.rowOff, drawingBase.to.col, drawingBase.to.colOff,
|
|
drawingBase.to.row, drawingBase.to.rowOff, drawingBase.Pos.X, drawingBase.Pos.Y, drawingBase.ext.cx,
|
|
drawingBase.ext.cy);
|
|
if(drawingObject.graphicObject.setDrawingBaseType){
|
|
drawingObject.graphicObject.setDrawingBaseType(drawingBase.Type);
|
|
if(drawingBase.Type === AscCommon.c_oAscCellAnchorType.cellanchorTwoCell) {
|
|
drawingObject.graphicObject.setDrawingBaseEditAs(drawingObject.editAs);
|
|
}
|
|
}
|
|
oNewWs.Drawings[oNewWs.Drawings.length - 1] = drawingObject;
|
|
}
|
|
var aRefsToChange = [];
|
|
var sNewName = parserHelp.getEscapeSheetName(oNewWs.sName);
|
|
var aRanges = [new AscCommonExcel.Range(this, 0, 0, gc_nMaxRow0, gc_nMaxCol0)];
|
|
oNewWs.handleDrawings(function(oDrawing) {
|
|
if(oDrawing.getObjectType() === AscDFH.historyitem_type_ChartSpace) {
|
|
oDrawing.collectIntersectionRefs(aRanges, aRefsToChange);
|
|
}
|
|
});
|
|
var sOldName = parserHelp.getEscapeSheetName(this.sName);
|
|
for(var nRef = 0; nRef < aRefsToChange.length; ++nRef) {
|
|
aRefsToChange[nRef].handleOnChangeSheetName(sOldName, sNewName);
|
|
}
|
|
drawingObjects.pushToAObjects(oNewWs.Drawings);
|
|
}
|
|
|
|
var newSparkline;
|
|
for (i = 0; i < this.aSparklineGroups.length; ++i) {
|
|
newSparkline = this.aSparklineGroups[i].clone();
|
|
newSparkline.setWorksheet(oNewWs, this);
|
|
oNewWs.addSparklineGroups(newSparkline);
|
|
}
|
|
};
|
|
Worksheet.prototype.initColumn = function (column) {
|
|
if (column) {
|
|
if (null !== column.width && 0 !== column.width) {
|
|
column.widthPx = this.modelColWidthToColWidth(column.width);
|
|
column.charCount = this.colWidthToCharCount(column.widthPx);
|
|
} else {
|
|
column.widthPx = column.charCount = null;
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.initColumns = function () {
|
|
this.initColumn(this.oAllCol);
|
|
this.aCols.forEach(this.initColumn, this);
|
|
};
|
|
Worksheet.prototype.initPostOpen = function (handlers, tableIds, sheetIds, pivotCaches, oNumFmts, dxfsOpen) {
|
|
var t = this;
|
|
this.PagePrintOptions.init();
|
|
this.headerFooter.init();
|
|
if (this.dataValidations) {
|
|
this.dataValidations.init(this);
|
|
}
|
|
|
|
// Sheet Views
|
|
if (0 === this.sheetViews.length) {
|
|
// Даже если не было, создадим
|
|
this.sheetViews.push(new AscCommonExcel.asc_CSheetViewSettings());
|
|
}
|
|
//this.setTableFormulaAfterOpen();
|
|
this.hiddenManager.initPostOpen();
|
|
this.oSheetFormatPr.correction();
|
|
|
|
this.handlers = handlers;
|
|
this._setHandlersTablePart();
|
|
this.aSlicers.forEach(function(elem){
|
|
elem && elem.initPostOpen(tableIds, sheetIds);
|
|
});
|
|
this.aNamedSheetViews.forEach(function(elem){
|
|
elem.initPostOpen(tableIds, t);
|
|
});
|
|
this.aCellWatches.forEach(function(elem){
|
|
elem.initPostOpen(t);
|
|
});
|
|
this.userProtectedRanges.forEach(function(elem){
|
|
elem.initPostOpen(t);
|
|
});
|
|
this.pivotTables.forEach(function(pivotTable){
|
|
pivotTable.initPostOpenZip(oNumFmts, dxfsOpen);
|
|
});
|
|
this.aSlicers.forEach(function(slicer){
|
|
slicer && slicer.initPostOpenZip(pivotCaches);
|
|
});
|
|
};
|
|
Worksheet.prototype._getValuesForConditionalFormatting = function(ranges, numbers) {
|
|
var res = [];
|
|
for (var i = 0; i < ranges.length; ++i) {
|
|
var elem = ranges[i];
|
|
var range = this.getRange3(elem.r1, elem.c1, elem.r2, elem.c2);
|
|
res = res.concat(range._getValues(numbers));
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype._isConditionalFormattingIntersect = function(range, ranges) {
|
|
for (var i = 0; i < ranges.length; ++i) {
|
|
if (range.isIntersect(ranges[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
Worksheet.prototype.setDirtyConditionalFormatting = function(range) {
|
|
if (!range) {
|
|
range = new AscCommonExcel.MultiplyRange([new Asc.Range(0, 0, gc_nMaxCol0, gc_nMaxRow0)]);
|
|
} else if (range && range.isNull && range.isNull()) {
|
|
return;
|
|
} else if (range.ranges && range.getUnionRange) {
|
|
//объединяю в один
|
|
range = new AscCommonExcel.MultiplyRange([range.getUnionRange()]);
|
|
}
|
|
if (this.updateConditionalFormattingRange) {
|
|
this.updateConditionalFormattingRange.union2(range);
|
|
this.updateConditionalFormattingRange = new AscCommonExcel.MultiplyRange([this.updateConditionalFormattingRange.getUnionRange()]);
|
|
} else {
|
|
this.updateConditionalFormattingRange = range.clone();
|
|
}
|
|
};
|
|
Worksheet.prototype._updateConditionalFormatting = function() {
|
|
if (!this.updateConditionalFormattingRange) {
|
|
return;
|
|
}
|
|
var range = this.updateConditionalFormattingRange;
|
|
this.updateConditionalFormattingRange = null;
|
|
var t = this;
|
|
let _aRules = [];
|
|
this.forEachConditionalFormattingRules(function (val) {
|
|
_aRules.push(val);
|
|
});
|
|
var aRules = _aRules.sort(function(v1, v2) {
|
|
return v2.priority - v1.priority;
|
|
});
|
|
var oGradient1, oGradient2, aWeights, oRule, oRuleElement, bboxCf, formulaParent, parsed1, parsed2;
|
|
var o, l, cell, ranges, values, value, tmp, dxf, compareFunction, nc, sum;
|
|
this.sheetMergedStyles.clearConditionalStyle(range);
|
|
var getCacheFunction = function(rule, setFunc) {
|
|
var cache = {
|
|
cache: {},
|
|
get: function(row, col) {
|
|
var cacheVal;
|
|
var cacheRow = this.cache[row];
|
|
if (!cacheRow) {
|
|
cacheRow = {};
|
|
this.cache[row] = cacheRow;
|
|
} else {
|
|
cacheVal = cacheRow[col];
|
|
}
|
|
if(undefined ===cacheVal){
|
|
cacheVal = this.set(row, col);
|
|
cacheRow[col] = cacheVal;
|
|
}
|
|
return cacheVal;
|
|
},
|
|
set: function(row, col) {
|
|
if(rule){
|
|
return setFunc(row, col) ? rule.dxf : null;
|
|
} else {
|
|
return setFunc(row, col);
|
|
}
|
|
}
|
|
};
|
|
return function(row, col) {
|
|
return cache.get(row, col);
|
|
};
|
|
};
|
|
for (var i = 0; i < aRules.length; ++i) {
|
|
oRule = aRules[i];
|
|
ranges = oRule.ranges;
|
|
if (this._isConditionalFormattingIntersect(range, ranges)) {
|
|
oRuleElement = oRule.asc_getColorScaleOrDataBarOrIconSetRule();
|
|
if (oRuleElement) {
|
|
if (Asc.ECfType.colorScale !== oRuleElement.type) {
|
|
continue;
|
|
}
|
|
values = this._getValuesForConditionalFormatting(ranges, true);
|
|
|
|
// ToDo CFVO Type formula (page 2681)
|
|
l = oRuleElement.aColors.length;
|
|
if (0 < values.length && 2 <= l) {
|
|
aWeights = [];
|
|
oGradient1 = new AscCommonExcel.CGradient(oRuleElement.aColors[0], oRuleElement.aColors[1]);
|
|
aWeights.push(oRule.getMin(values, t), oRule.getMax(values, t));
|
|
if (2 < l) {
|
|
oGradient2 = new AscCommonExcel.CGradient(oRuleElement.aColors[1], oRuleElement.aColors[2]);
|
|
aWeights.push(oRule.getMid(values, t));
|
|
|
|
aWeights.sort(AscCommon.fSortAscending);
|
|
oGradient1.init(aWeights[0], aWeights[1]);
|
|
oGradient2.init(aWeights[1], aWeights[2]);
|
|
} else {
|
|
oGradient2 = null;
|
|
aWeights.sort(AscCommon.fSortAscending);
|
|
oGradient1.init(aWeights[0], aWeights[1]);
|
|
}
|
|
|
|
compareFunction = (function (oGradient1, oGradient2) {
|
|
return function (row, col) {
|
|
var val, color, gradient;
|
|
t._getCellNoEmpty(row, col, function (cell) {
|
|
val = cell && cell.getNumberValue();
|
|
});
|
|
dxf = null;
|
|
if (null !== val) {
|
|
dxf = new AscCommonExcel.CellXfs();
|
|
gradient = oGradient2 ? oGradient2 : oGradient1;
|
|
if (val >= gradient.max) {
|
|
color = gradient.getMaxColor();
|
|
} else if (val <= oGradient1.min) {
|
|
color = oGradient1.getMinColor();
|
|
} else {
|
|
gradient = (oGradient2 && val > oGradient1.max) ? oGradient2 : oGradient1;
|
|
color = gradient.calculateColor(val);
|
|
}
|
|
dxf.fill = new AscCommonExcel.Fill();
|
|
dxf.fill.fromColor(color);
|
|
dxf = g_StyleCache.addXf(dxf, true);
|
|
}
|
|
return dxf;
|
|
};
|
|
})(oGradient1, oGradient2);
|
|
}
|
|
} else if (Asc.ECfType.dataBar === oRule.type) {
|
|
continue;
|
|
} else if (Asc.ECfType.top10 === oRule.type) {
|
|
if (oRule.rank > 0 && oRule.dxf) {
|
|
nc = 0;
|
|
values = this._getValuesForConditionalFormatting(ranges, false);
|
|
o = oRule.bottom ? Number.MAX_VALUE : -Number.MAX_VALUE;
|
|
for (cell = 0; cell < values.length; ++cell) {
|
|
value = values[cell];
|
|
if (CellValueType.Number === value.type && !isNaN(tmp = parseFloat(value.v))) {
|
|
++nc;
|
|
value.v = tmp;
|
|
} else {
|
|
value.v = o;
|
|
}
|
|
}
|
|
values.sort((function(condition) {
|
|
return function(v1, v2) {
|
|
return condition * (v2.v - v1.v);
|
|
}
|
|
})(oRule.bottom ? -1 : 1));
|
|
|
|
nc = Math.max(1, oRule.percent ? Math.floor(nc * oRule.rank / 100) : oRule.rank);
|
|
var threshold = values.length >= nc ? values[nc - 1].v : o;
|
|
compareFunction = (function(rule, threshold) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
val = cell ? cell.getNumberValue() : null;
|
|
});
|
|
return (null !== val && (rule.bottom ? val <= threshold : val >= threshold)) ? rule.dxf : null;
|
|
};
|
|
})(oRule, threshold);
|
|
}
|
|
} else if (Asc.ECfType.aboveAverage === oRule.type) {
|
|
if (!oRule.dxf) {
|
|
continue;
|
|
}
|
|
values = this._getValuesForConditionalFormatting(ranges, false);
|
|
sum = 0;
|
|
nc = 0;
|
|
for (cell = 0; cell < values.length; ++cell) {
|
|
value = values[cell];
|
|
if (CellValueType.Number === value.type && !isNaN(tmp = parseFloat(value.v))) {
|
|
++nc;
|
|
value.v = tmp;
|
|
sum += tmp;
|
|
} else {
|
|
value.v = null;
|
|
}
|
|
}
|
|
|
|
tmp = sum / nc;
|
|
|
|
var stdDev;
|
|
if (oRule.hasStdDev()) {
|
|
var sum2 = 0;
|
|
for (cell = 0; cell < values.length; ++cell) {
|
|
value = values[cell];
|
|
if (null !== value.v) {
|
|
sum2 += (value.v - tmp) * (value.v - tmp);
|
|
}
|
|
}
|
|
stdDev = Math.sqrt(sum2 / nc);
|
|
}
|
|
|
|
compareFunction = (function(rule, average, stdDev) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
val = cell ? cell.getNumberValue() : null;
|
|
});
|
|
return (null !== val && rule.getAverage(val, average, stdDev)) ? rule.dxf : null;
|
|
};
|
|
})(oRule, tmp, stdDev);
|
|
} else {
|
|
if (!oRule.dxf) {
|
|
continue;
|
|
}
|
|
switch (oRule.type) {
|
|
case Asc.ECfType.duplicateValues:
|
|
case Asc.ECfType.uniqueValues:
|
|
o = getUniqueKeys(this._getValuesForConditionalFormatting(ranges, false));
|
|
compareFunction = (function(rule, obj, condition) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
val = cell ? cell.getValueWithoutFormat() : "";
|
|
});
|
|
return (val.length > 0 ? condition === obj[val] : false) ? rule.dxf : null;
|
|
};
|
|
})(oRule, o, oRule.type === Asc.ECfType.duplicateValues);
|
|
break;
|
|
case Asc.ECfType.containsText:
|
|
case Asc.ECfType.notContainsText:
|
|
case Asc.ECfType.beginsWith:
|
|
case Asc.ECfType.endsWith:
|
|
var operator;
|
|
switch (oRule.type) {
|
|
case Asc.ECfType.containsText:
|
|
operator = AscCommonExcel.ECfOperator.Operator_containsText;
|
|
break;
|
|
case Asc.ECfType.notContainsText:
|
|
operator = AscCommonExcel.ECfOperator.Operator_notContains;
|
|
break;
|
|
case Asc.ECfType.beginsWith:
|
|
operator = AscCommonExcel.ECfOperator.Operator_beginsWith;
|
|
break;
|
|
case Asc.ECfType.endsWith:
|
|
operator = AscCommonExcel.ECfOperator.Operator_endsWith;
|
|
break;
|
|
}
|
|
formulaParent = new AscCommonExcel.CConditionalFormattingFormulaParent(this, oRule, true);
|
|
oRuleElement = oRule.getFormulaCellIs(Asc.ECfType.notContainsText === oRule.type || Asc.ECfType.containsText === oRule.type);
|
|
parsed1 = oRuleElement && oRuleElement.getFormula && oRuleElement.getFormula(this, formulaParent);
|
|
if (parsed1 && parsed1.hasRelativeRefs()) {
|
|
bboxCf = oRule.getBBox();
|
|
compareFunction = getCacheFunction(oRule, (function(rule, operator, formulaParent, rowLT, colLT) {
|
|
return function(row, col) {
|
|
var offset = new AscCommon.CellBase(row - rowLT, col - colLT);
|
|
var bboxCell = new Asc.Range(col, row, col, row);
|
|
var v1 = rule.getValueCellIs(t, formulaParent, bboxCell, offset, false);
|
|
var res;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
res = rule.cellIs(operator, cell, v1) ? rule.dxf : null;
|
|
});
|
|
return res;
|
|
};
|
|
})(oRule, operator,
|
|
new AscCommonExcel.CConditionalFormattingFormulaParent(this, oRule, true),
|
|
bboxCf ? bboxCf.r1 : 0, bboxCf ? bboxCf.c1 : 0));
|
|
} else {
|
|
compareFunction = (function(rule, operator, v1) {
|
|
return function(row, col) {
|
|
var res;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
res = rule.cellIs(operator, cell, v1) ? rule.dxf : null;
|
|
});
|
|
return res;
|
|
};
|
|
})(oRule, operator, oRule.getValueCellIs(this));
|
|
}
|
|
break;
|
|
case Asc.ECfType.containsErrors:
|
|
compareFunction = (function(rule) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
val = (cell ? CellValueType.Error === cell.getType() : false);
|
|
});
|
|
return val ? rule.dxf : null;
|
|
};
|
|
})(oRule);
|
|
break;
|
|
case Asc.ECfType.notContainsErrors:
|
|
compareFunction = (function(rule) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
val = (cell ? CellValueType.Error !== cell.getType() : true);
|
|
});
|
|
return val ? rule.dxf : null;
|
|
};
|
|
})(oRule);
|
|
break;
|
|
case Asc.ECfType.containsBlanks:
|
|
compareFunction = (function(rule) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
if (cell) {
|
|
//todo LEN(TRIM(A1))=0
|
|
val = "" === cell.getValueWithoutFormat().replace(/^ +| +$/g, '');
|
|
} else {
|
|
val = true;
|
|
}
|
|
});
|
|
return val ? rule.dxf : null;
|
|
};
|
|
})(oRule);
|
|
break;
|
|
case Asc.ECfType.notContainsBlanks:
|
|
compareFunction = (function(rule) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
if (cell) {
|
|
//todo LEN(TRIM(A1))=0
|
|
val = "" !== cell.getValueWithoutFormat().replace(/^ +| +$/g, '');
|
|
} else {
|
|
val = false;
|
|
}
|
|
});
|
|
return val ? rule.dxf : null;
|
|
};
|
|
})(oRule);
|
|
break;
|
|
case Asc.ECfType.timePeriod:
|
|
if (oRule.timePeriod) {
|
|
compareFunction = (function(rule, period) {
|
|
return function(row, col) {
|
|
var val;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
val = cell ? cell.getValueWithoutFormat() : "";
|
|
});
|
|
var n = parseFloat(val);
|
|
return (period.start <= n && n < period.end) ? rule.dxf : null;
|
|
};
|
|
})(oRule, oRule.getTimePeriod());
|
|
} else {
|
|
continue;
|
|
}
|
|
break;
|
|
case Asc.ECfType.cellIs:
|
|
formulaParent = new AscCommonExcel.CConditionalFormattingFormulaParent(this, oRule, true);
|
|
oRuleElement = oRule.aRuleElements[0];
|
|
parsed1 = oRuleElement && oRuleElement.getFormula && oRuleElement.getFormula(this, formulaParent);
|
|
oRuleElement = oRule.aRuleElements[1];
|
|
parsed2 = oRuleElement && oRuleElement.getFormula && oRuleElement.getFormula(this, formulaParent);
|
|
if ((parsed1 && parsed1.hasRelativeRefs()) || (parsed2 && parsed2.hasRelativeRefs())) {
|
|
bboxCf = oRule.getBBox();
|
|
compareFunction = getCacheFunction(oRule, (function(rule, ruleElem1, ruleElem2, formulaParent, rowLT, colLT) {
|
|
return function(row, col) {
|
|
var offset = new AscCommon.CellBase(row - rowLT, col - colLT);
|
|
var bboxCell = new Asc.Range(col, row, col, row);
|
|
var v1 = ruleElem1 && ruleElem1.getValue(t, formulaParent, bboxCell, offset, false);
|
|
var v2 = ruleElem2 && ruleElem2.getValue(t, formulaParent, bboxCell, offset, false);
|
|
var res;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
res = rule.cellIs(rule.operator, cell, v1, v2) ? rule.dxf : null;
|
|
});
|
|
return res;
|
|
};
|
|
})(oRule, oRule.aRuleElements[0], oRule.aRuleElements[1],
|
|
new AscCommonExcel.CConditionalFormattingFormulaParent(this, oRule, true),
|
|
bboxCf ? bboxCf.r1 : 0, bboxCf ? bboxCf.c1 : 0));
|
|
} else {
|
|
compareFunction = (function(rule, v1, v2) {
|
|
return function(row, col) {
|
|
var res;
|
|
t._getCellNoEmpty(row, col, function(cell) {
|
|
res = rule.cellIs(rule.operator, cell, v1, v2) ? rule.dxf : null;
|
|
});
|
|
return res;
|
|
};
|
|
})(oRule, oRule.aRuleElements[0] && oRule.aRuleElements[0].getValue(this),
|
|
oRule.aRuleElements[1] && oRule.aRuleElements[1].getValue(this));
|
|
}
|
|
break;
|
|
case Asc.ECfType.expression:
|
|
bboxCf = oRule.getBBox();
|
|
compareFunction = getCacheFunction(oRule, (function(rule, formulaCF, formulaParent, rowLT, colLT) {
|
|
return function(row, col) {
|
|
var offset = new AscCommon.CellBase(row - rowLT, col - colLT);
|
|
var bboxCell = new Asc.Range(col, row, col, row);
|
|
var res = formulaCF && formulaCF.getValue(t, formulaParent, bboxCell, offset, true);
|
|
if (res && res.tocBool) {
|
|
res = res.tocBool();
|
|
if (res && res.toBool) {
|
|
return res.toBool();
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
})(oRule, oRule.aRuleElements[0],
|
|
new AscCommonExcel.CConditionalFormattingFormulaParent(this, oRule, true),
|
|
bboxCf ? bboxCf.r1 : 0, bboxCf ? bboxCf.c1 : 0));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (compareFunction) {
|
|
this.sheetMergedStyles.setConditionalStyle(oRule, ranges, compareFunction);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._forEachRow = function(fAction) {
|
|
this.getRange3(0, 0, gc_nMaxRow0, 0)._foreachRowNoEmpty(fAction);
|
|
};
|
|
Worksheet.prototype._forEachCol = function(fAction) {
|
|
this.getRange3(0, 0, 0, gc_nMaxCol0)._foreachColNoEmpty(fAction);
|
|
};
|
|
Worksheet.prototype._forEachColData = function(fAction) {
|
|
for (var i = 0; i < this.cellsByCol.length; ++i) {
|
|
var sheetMemory = this.cellsByCol[i];
|
|
if (sheetMemory) {
|
|
fAction(sheetMemory, i);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._forEachCell = function(fAction) {
|
|
this.getRange3(0, 0, gc_nMaxRow0, gc_nMaxCol0)._foreachNoEmpty(fAction);
|
|
};
|
|
Worksheet.prototype.Get_Id = Worksheet.prototype.getId=function(){
|
|
return this.Id;
|
|
};
|
|
Worksheet.prototype.getIndex=function(){
|
|
return this.index;
|
|
};
|
|
Worksheet.prototype.getName=function(){
|
|
return this.sName != null && this.sName.length > 0 ? this.sName : "";
|
|
};
|
|
Worksheet.prototype.setName=function(name){
|
|
if(name.length <= g_nSheetNameMaxLength)
|
|
{
|
|
var lastName = this.sName;
|
|
AscCommon.History.Create_NewPoint();
|
|
var prepared = this.workbook.dependencyFormulas.prepareChangeSheet(this.getId(), {rename: {from: lastName, to: name}});
|
|
this.sName = name;
|
|
this.workbook.dependencyFormulas.changeSheet(prepared);
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_Rename, this.getId(), null, new UndoRedoData_FromTo(lastName, name));
|
|
|
|
this.workbook.dependencyFormulas.calcTree();
|
|
if (!this.workbook.bUndoChanges && !this.workbook.bRedoChanges) {
|
|
this.workbook.handlers && this.workbook.handlers.trigger("updateCellWatches");
|
|
}
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetRename, this.index, name, this.getId());
|
|
}
|
|
} else {
|
|
console.log(new Error('The sheet name must be less than 31 characters.'));
|
|
}
|
|
};
|
|
Worksheet.prototype.getTabColor=function(){
|
|
return this.sheetPr && this.sheetPr.TabColor ? Asc.colorObjToAscColor(this.sheetPr.TabColor) : null;
|
|
};
|
|
Worksheet.prototype.setTabColor=function(color){
|
|
if (!this.sheetPr)
|
|
this.sheetPr = new AscCommonExcel.asc_CSheetPr();
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetTabColor, this.getId(), null,
|
|
new UndoRedoData_FromTo(this.sheetPr.TabColor ? this.sheetPr.TabColor.clone() : null, color ? color.clone() : null));
|
|
|
|
this.sheetPr.TabColor = color;
|
|
if (!this.workbook.bUndoChanges && !this.workbook.bRedoChanges)
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_onUpdateTabColor", this.getIndex());
|
|
};
|
|
Worksheet.prototype.rebuildTabColor = function() {
|
|
if (this.sheetPr && this.sheetPr.TabColor) {
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_onUpdateTabColor", this.getIndex());
|
|
}
|
|
};
|
|
Worksheet.prototype.getHidden=function(){
|
|
return true === this.bHidden;
|
|
};
|
|
Worksheet.prototype.setHidden = function (hidden) {
|
|
var bOldHidden = this.bHidden, wb = this.workbook, wsActive = wb.getActiveWs(), oVisibleWs = null;
|
|
this.bHidden = hidden;
|
|
if (bOldHidden != hidden) {
|
|
if (true == this.bHidden && this.getIndex() == wsActive.getIndex()) {
|
|
oVisibleWs = wb.findSheetNoHidden(this.getIndex());
|
|
} else if (false == this.bHidden && this.getIndex() !== wsActive.getIndex()) {
|
|
oVisibleWs = this;
|
|
}
|
|
if (null != oVisibleWs) {
|
|
var nNewIndex = oVisibleWs.getIndex();
|
|
wb.setActive(nNewIndex);
|
|
if (!wb.bUndoChanges && !wb.bRedoChanges) {
|
|
wb.handlers && wb.handlers.trigger("undoRedoHideSheet", nNewIndex);
|
|
}
|
|
}
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_Hide, this.getId(), null, new UndoRedoData_FromTo(bOldHidden, hidden));
|
|
if (null != oVisibleWs) {
|
|
AscCommon.History.SetSheetUndo(wsActive.getId());
|
|
AscCommon.History.SetSheetRedo(oVisibleWs.getId());
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.getSheetView = function () {
|
|
return this.sheetViews[0];
|
|
};
|
|
Worksheet.prototype.getSheetViewSettings = function (bNotClone) {
|
|
return bNotClone ? this.sheetViews[0] : this.sheetViews[0].clone();
|
|
};
|
|
Worksheet.prototype.setDisplayGridlines = function (value) {
|
|
var view = this.sheetViews[0];
|
|
if (value !== view.showGridLines) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetDisplayGridlines,
|
|
this.getId(), null, new UndoRedoData_FromTo(view.showGridLines, value));
|
|
view.showGridLines = value;
|
|
|
|
this.workbook.handlers && this.workbook.handlers.trigger("changeSheetViewSettings", this.getId(), AscCH.historyitem_Worksheet_SetDisplayGridlines);
|
|
if (!this.workbook.bUndoChanges && !this.workbook.bRedoChanges) {
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_onUpdateSheetViewSettings");
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.setDisplayHeadings = function (value) {
|
|
var view = this.sheetViews[0];
|
|
if (value !== view.showRowColHeaders) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetDisplayHeadings,
|
|
this.getId(), null, new UndoRedoData_FromTo(view.showRowColHeaders, value));
|
|
view.showRowColHeaders = value;
|
|
|
|
this.workbook.handlers && this.workbook.handlers.trigger("changeSheetViewSettings", this.getId(), AscCH.historyitem_Worksheet_SetDisplayHeadings);
|
|
if (!this.workbook.bUndoChanges && !this.workbook.bRedoChanges) {
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_onUpdateSheetViewSettings");
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.setShowZeros = function (value) {
|
|
var view = this.sheetViews[0];
|
|
if (value !== view.showZeros) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetShowZeros,
|
|
this.getId(), null, new UndoRedoData_FromTo(view.showZeros, value));
|
|
view.showZeros = value;
|
|
|
|
//TODO
|
|
this.workbook.handlers && this.workbook.handlers.trigger("changeSheetViewSettings", this.getId(), AscCH.historyitem_Worksheet_SetDisplayHeadings);
|
|
if (!this.workbook.bUndoChanges && !this.workbook.bRedoChanges) {
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_onUpdateSheetViewSettings");
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.setShowFormulas = function (value) {
|
|
var view = this.sheetViews[0];
|
|
if (value !== view.showFormulas) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetShowFormulas,
|
|
this.getId(), new Asc.Range(0, 0, gc_nMaxCol0, gc_nMaxRow0), new UndoRedoData_FromTo(view.showFormulas, value));
|
|
view.showFormulas = value;
|
|
|
|
this.workbook.handlers.trigger("changeSheetViewSettings", this.getId(), AscCH.historyitem_Worksheet_SetShowFormulas);
|
|
if (!this.workbook.bCollaborativeChanges) {
|
|
this.workbook.handlers.trigger("asc_onUpdateFormulasViewSettings");
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.setRightToLeft = function (value, addToHistory) {
|
|
var view = this.sheetViews[0];
|
|
if (value !== view.rightToLeft) {
|
|
if (addToHistory) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetRightToLeft,
|
|
this.getId(), new Asc.Range(0, 0, gc_nMaxCol0, gc_nMaxRow0), new UndoRedoData_FromTo(view.rightToLeft, value));
|
|
}
|
|
view.rightToLeft = value;
|
|
|
|
this.workbook.handlers.trigger("changeSheetViewSettings", this.getId(), AscCH.historyitem_Worksheet_SetRightToLeft);
|
|
if (!this.workbook.bCollaborativeChanges) {
|
|
this.workbook.handlers.trigger("asc_onUpdateSheetViewSettings");
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.getShowFormulas = function () {
|
|
var view = this.sheetViews[0];
|
|
return view && view.showFormulas;
|
|
};
|
|
Worksheet.prototype.getRowsCount=function(){
|
|
var result = this.nRowsCount;
|
|
var pane = this.sheetViews.length && this.sheetViews[0].pane;
|
|
if (pane && pane.topLeftFrozenCell)
|
|
result = Math.max(result, pane.topLeftFrozenCell.getRow0());
|
|
return result;
|
|
};
|
|
Worksheet.prototype.getSheetViewType=function(){
|
|
return this.sheetViews && this.sheetViews.length && this.sheetViews[0].view;
|
|
};
|
|
Worksheet.prototype.removeRows=function(start, stop, bExcludeHiddenRows){
|
|
var removeRowsArr = bExcludeHiddenRows ? this._getNoHiddenRowsArr(start, stop) : [{start: start, stop: stop}];
|
|
for(var i = removeRowsArr.length - 1; i >= 0; i--) {
|
|
var oRange = this.getRange(new CellAddress(removeRowsArr[i].start, 0, 0), new CellAddress(removeRowsArr[i].stop, gc_nMaxCol0, 0));
|
|
oRange.deleteCellsShiftUp();
|
|
}
|
|
};
|
|
Worksheet.prototype._getNoHiddenRowsArr=function(start, stop){
|
|
var res = [];
|
|
var elem = null;
|
|
for (var i = start; i <= stop; i++) {
|
|
if (this.getRowHidden(i)) {
|
|
if (elem) {
|
|
res.push(elem);
|
|
elem = null;
|
|
}
|
|
} else {
|
|
if (!elem) {
|
|
elem = {};
|
|
elem.start = i;
|
|
elem.stop = i;
|
|
} else {
|
|
elem.stop++;
|
|
}
|
|
if (i === stop) {
|
|
res.push(elem);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype._updateFormulasParents = function(r1, c1, r2, c2, bbox, offset, shiftedShared) {
|
|
var t = this;
|
|
var cellWithFormula;
|
|
var shiftedArrayFormula = {};
|
|
this.getRange3(r1, c1, r2, c2)._foreachNoEmpty(function(cell){
|
|
var newNRow = cell.nRow + offset.row;
|
|
var newNCol = cell.nCol + offset.col;
|
|
var bHor = 0 !== offset.col;
|
|
var toDelete = offset.col < 0 || offset.row < 0;
|
|
|
|
if (cell.isFormula()) {
|
|
var processed = c_oSharedShiftType.NeedTransform;
|
|
var parsed = cell.getFormulaParsed();
|
|
var shared = parsed.getShared();
|
|
var arrayFormula = parsed.getArrayFormulaRef();
|
|
var formulaRefObj = null;
|
|
if (shared) {
|
|
processed = shiftedShared[parsed.getListenerId()];
|
|
var isPreProcessed = c_oSharedShiftType.PreProcessed === processed;
|
|
if (!processed || isPreProcessed) {
|
|
if (!processed) {
|
|
var bboxShift = AscCommonExcel.shiftGetBBox(bbox, bHor);
|
|
//if shared not completly in shift range - transform
|
|
//if shared intersect delete range - transform
|
|
if (bboxShift.containsRange(shared.ref) && (!toDelete || !bbox.isIntersect(shared.ref))) {
|
|
processed = c_oSharedShiftType.Processed;
|
|
} else {
|
|
processed = c_oSharedShiftType.NeedTransform;
|
|
}
|
|
} else if(isPreProcessed) {
|
|
//At PreProcessed stage all required formula was transformed. here we need to shift shared
|
|
processed = c_oSharedShiftType.Processed;
|
|
}
|
|
if (c_oSharedShiftType.Processed === processed) {
|
|
var newRef = shared.ref.clone();
|
|
newRef.forShift(bbox, offset, t.workbook.bUndoChanges);
|
|
parsed.setSharedRef(newRef, !isPreProcessed);
|
|
t.workbook.dependencyFormulas.addToChangedRange2(t.getId(), newRef);
|
|
}
|
|
shiftedShared[parsed.getListenerId()] = processed;
|
|
}
|
|
} else if(arrayFormula) {
|
|
//***array-formula***
|
|
if(!shiftedArrayFormula[parsed.getListenerId()] && parsed.checkFirstCellArray(cell)) {
|
|
shiftedArrayFormula[parsed.getListenerId()] = 1;
|
|
var newArrayRef = arrayFormula.clone();
|
|
newArrayRef.setOffset(offset);
|
|
parsed.setArrayFormulaRef(newArrayRef);
|
|
} else {
|
|
processed = c_oSharedShiftType.Processed;
|
|
}
|
|
}
|
|
|
|
if (c_oSharedShiftType.NeedTransform === processed) {
|
|
var isTransform = cell.transformSharedFormula();
|
|
parsed = cell.getFormulaParsed();
|
|
if (isTransform) {
|
|
parsed.buildDependencies();
|
|
}
|
|
|
|
cellWithFormula = parsed.getParent();
|
|
cellWithFormula.nRow = newNRow;
|
|
cellWithFormula.nCol = newNCol;
|
|
t.workbook.dependencyFormulas.addToChangedCell(cellWithFormula);
|
|
}
|
|
}
|
|
t.cellsByColRowsCount = Math.max(t.cellsByColRowsCount, newNRow + 1);
|
|
t.nRowsCount = Math.max(t.nRowsCount, t.cellsByColRowsCount);
|
|
t.setColsCount(Math.max(t.nColsCount, newNCol + 1));
|
|
});
|
|
};
|
|
Worksheet.prototype._removeRows=function(start, stop){
|
|
var t = this;
|
|
this.workbook.dependencyFormulas.lockRecal();
|
|
AscCommon.History.Create_NewPoint();
|
|
//start, stop 0 based
|
|
var nDif = -(stop - start + 1);
|
|
var oActualRange = new Asc.Range(0, start, gc_nMaxCol0, stop);
|
|
var offset = new AscCommon.CellBase(nDif, 0);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oActualRange);
|
|
var redrawTablesArr = this.autoFilters.insertRows("delCell", oActualRange, c_oAscDeleteOptions.DeleteRows);
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oActualRange, offset);
|
|
this.updateUserProtectedRangesOffset(oActualRange, offset);
|
|
}
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oActualRange, offset);
|
|
this.updateSparklineGroupOffset(oActualRange, offset);
|
|
this.updateConditionalFormattingOffset(oActualRange, offset);
|
|
this.updateProtectedRangeOffset(oActualRange, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
|
|
var collapsedInfo = null, lastRowIndex;
|
|
var oDefRowPr = new AscCommonExcel.UndoRedoData_RowProp();
|
|
this.getRange3(start,0,stop,gc_nMaxCol0)._foreachRowNoEmpty(function(row){
|
|
var oOldProps = row.getHeightProp();
|
|
lastRowIndex = row.index;
|
|
if (false === oOldProps.isEqual(oDefRowPr))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RowProp, t.getId(), row._getUpdateRange(), new UndoRedoData_IndexSimpleProp(row.getIndex(), true, oOldProps, oDefRowPr));
|
|
row.setStyle(null);
|
|
|
|
if(!t.workbook.bRedoChanges) {
|
|
if(collapsedInfo !== null && collapsedInfo < row.getOutlineLevel()) {
|
|
collapsedInfo = null;
|
|
}
|
|
if(row.getCollapsed()) {
|
|
collapsedInfo = row.getOutlineLevel();
|
|
t.setCollapsedRow(false, null, row);
|
|
}
|
|
}
|
|
|
|
}, function(cell){
|
|
t._removeCell(null, null, cell);
|
|
});
|
|
|
|
//ms не удаляет collapsed с удаляемой строки, он наследует это свойство следующей
|
|
if(collapsedInfo !== null && lastRowIndex === stop) {
|
|
this._getRow(stop + 1, function(row) {
|
|
//TODO проверить!!!
|
|
//if(collapsedInfo >= row.getOutlineLevel()) {
|
|
//row.setCollapsed(true);
|
|
t.setCollapsedRow(true, null, row);
|
|
//}
|
|
});
|
|
}
|
|
|
|
this._updateFormulasParents(start, 0, gc_nMaxRow0, gc_nMaxCol0, oActualRange, offset, renameRes && renameRes.shiftedShared);
|
|
this.rowsData.deleteRange(start, (-nDif));
|
|
this._forEachColData(function(sheetMemory) {
|
|
sheetMemory.deleteRange(start, (-nDif));
|
|
});
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes && renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RemoveRows, this.getId(), new Asc.Range(0, start, gc_nMaxCol0, gc_nMaxRow0), new UndoRedoData_FromToRowCol(true, start, stop));
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, new Asc.Range(0, start, gc_nMaxCol0, stop), this.getId());
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.removeRows, this, new Asc.Range(0, start, gc_nMaxCol0, stop), this.getId());
|
|
}
|
|
|
|
this.workbook.dependencyFormulas.unlockRecal();
|
|
|
|
return true;
|
|
};
|
|
Worksheet.prototype.insertRowsBefore=function(index, count){
|
|
var oRange = this.getRange(new CellAddress(index, 0, 0), new CellAddress(index + count - 1, gc_nMaxCol0, 0));
|
|
oRange.addCellsShiftBottom();
|
|
};
|
|
Worksheet.prototype._getBordersForInsert = function(bbox, bRow) {
|
|
var t = this;
|
|
var borders = {};
|
|
var offsetRow = (bRow && bbox.r1 > 0) ? -1 : 0;
|
|
var offsetCol = (!bRow && bbox.c1 > 0) ? -1 : 0;
|
|
var r2 = bRow ? bbox.r1 : bbox.r2;
|
|
var c2 = !bRow ? bbox.c1 : bbox.c2;
|
|
if(0 !== offsetRow || 0 !== offsetCol){
|
|
this.getRange3(bbox.r1, bbox.c1, r2, c2)._foreachNoEmpty(function(cell) {
|
|
if (cell.xfs && cell.xfs.border) {
|
|
t._getCellNoEmpty(cell.nRow + offsetRow, cell.nCol + offsetCol, function(neighbor) {
|
|
if (neighbor && neighbor.xfs && neighbor.xfs.border) {
|
|
var newBorder = neighbor.xfs.border.clone();
|
|
newBorder.intersect(cell.xfs.border, true);
|
|
borders[bRow ? cell.nCol : cell.nRow] = newBorder;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
return borders;
|
|
};
|
|
Worksheet.prototype._insertRowsBefore=function(index, count){
|
|
var t = this;
|
|
this.workbook.dependencyFormulas.lockRecal();
|
|
var oActualRange = new Asc.Range(0, index, gc_nMaxCol0, index + count - 1);
|
|
AscCommon.History.Create_NewPoint();
|
|
var offset = new AscCommon.CellBase(count, 0);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oActualRange);
|
|
var redrawTablesArr = this.autoFilters.insertRows("insCell", oActualRange, c_oAscInsertOptions.InsertColumns);
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oActualRange, offset);
|
|
this.updateUserProtectedRangesOffset(oActualRange, offset);
|
|
}
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oActualRange, offset);
|
|
this.updateSparklineGroupOffset(oActualRange, offset);
|
|
this.updateConditionalFormattingOffset(oActualRange, offset);
|
|
this.updateProtectedRangeOffset(oActualRange, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
|
|
this._updateFormulasParents(index, 0, gc_nMaxRow0, gc_nMaxCol0, oActualRange, offset, renameRes.shiftedShared);
|
|
var borders;
|
|
if (index > 0 && !this.workbook.bUndoChanges) {
|
|
borders = this._getBordersForInsert(oActualRange, true);
|
|
}
|
|
//insert new row/cell
|
|
this.rowsData.insertRange(index, count);
|
|
this.nRowsCount = Math.max(this.nRowsCount, this.rowsData.getMaxIndex() + 1);
|
|
this._forEachColData(function(sheetMemory) {
|
|
sheetMemory.insertRange(index, count);
|
|
t.cellsByColRowsCount = Math.max(t.cellsByColRowsCount, sheetMemory.getMaxIndex() + 1);
|
|
});
|
|
this.nRowsCount = Math.max(this.nRowsCount, this.cellsByColRowsCount);
|
|
//copy property from row/cell above
|
|
if (index > 0 && !this.workbook.bUndoChanges)
|
|
{
|
|
this.rowsData.copyRangeByChunk((index - 1), 1, index, count);
|
|
this.nRowsCount = Math.max(this.nRowsCount, this.rowsData.getMaxIndex() + 1);
|
|
this._forEachColData(function(sheetMemory) {
|
|
sheetMemory.copyRangeByChunk((index - 1), 1, index, count);
|
|
t.cellsByColRowsCount = Math.max(t.cellsByColRowsCount, sheetMemory.getMaxIndex() + 1);
|
|
});
|
|
this.nRowsCount = Math.max(this.nRowsCount, this.cellsByColRowsCount);
|
|
//show rows and remain only cell xf property
|
|
this.getRange3(index, 0, index + count - 1, gc_nMaxCol0)._foreachRowNoEmpty(function(row) {
|
|
row.setHidden(false);
|
|
},function(cell) {
|
|
cell.clearDataKeepXf(borders[cell.nCol]);
|
|
});
|
|
}
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_AddRows, this.getId(), new Asc.Range(0, index, gc_nMaxCol0, gc_nMaxRow0), new UndoRedoData_FromToRowCol(true, index, index + count - 1));
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, null, this.getId());
|
|
}
|
|
|
|
this.workbook.dependencyFormulas.unlockRecal();
|
|
return true;
|
|
};
|
|
Worksheet.prototype.insertRowsAfter=function(index, count){
|
|
//index 0 based
|
|
return this.insertRowsBefore(index + 1, count);
|
|
};
|
|
Worksheet.prototype.getColsCount=function(){
|
|
var result = this.nColsCount;
|
|
var pane = this.sheetViews.length && this.sheetViews[0].pane;
|
|
if (pane && pane.topLeftFrozenCell)
|
|
result = Math.max(result, pane.topLeftFrozenCell.getCol0());
|
|
return result;
|
|
};
|
|
Worksheet.prototype.removeCols=function(start, stop){
|
|
var oRange = this.getRange(new CellAddress(0, start, 0), new CellAddress(gc_nMaxRow0, stop, 0));
|
|
oRange.deleteCellsShiftLeft();
|
|
};
|
|
Worksheet.prototype._removeCols=function(start, stop){
|
|
var t = this;
|
|
this.workbook.dependencyFormulas.lockRecal();
|
|
AscCommon.History.Create_NewPoint();
|
|
//start, stop 0 based
|
|
var nDif = -(stop - start + 1), i, j, length;
|
|
var oActualRange = new Asc.Range(start, 0, stop, gc_nMaxRow0);
|
|
var offset = new AscCommon.CellBase(0, nDif);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oActualRange);
|
|
var redrawTablesArr = this.autoFilters.insertColumn(oActualRange, nDif);
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oActualRange, offset);
|
|
this.updateUserProtectedRangesOffset(oActualRange, offset);
|
|
}
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oActualRange, offset);
|
|
this.updateSparklineGroupOffset(oActualRange, offset);
|
|
this.updateConditionalFormattingOffset(oActualRange, offset);
|
|
this.updateProtectedRangeOffset(oActualRange, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
|
|
var collapsedInfo = null, lastRowIndex;
|
|
var oDefColPr = new AscCommonExcel.UndoRedoData_ColProp();
|
|
this.getRange3(0, start, gc_nMaxRow0,stop)._foreachColNoEmpty(function(col){
|
|
var nIndex = col.getIndex();
|
|
var oOldProps = col.getWidthProp();
|
|
if(false === oOldProps.isEqual(oDefColPr))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ColProp, t.getId(), new Asc.Range(nIndex, 0, nIndex, gc_nMaxRow0), new UndoRedoData_IndexSimpleProp(nIndex, false, oOldProps, oDefColPr));
|
|
col.setStyle(null);
|
|
|
|
lastRowIndex = col.index;
|
|
if(!t.workbook.bRedoChanges) {
|
|
if(collapsedInfo !== null && collapsedInfo < col.getOutlineLevel()) {
|
|
collapsedInfo = null;
|
|
}
|
|
if(col.getCollapsed()) {
|
|
collapsedInfo = col.getOutlineLevel();
|
|
t.setCollapsedCol(false, null, col);
|
|
}
|
|
}
|
|
}, function(cell){
|
|
t._removeCell(null, null, cell);
|
|
});
|
|
|
|
if(collapsedInfo !== null && lastRowIndex === stop) {
|
|
var curCol = this._getCol(stop + 1);
|
|
//TODO проверить!!!
|
|
if(curCol /*&& collapsedInfo >= curCol.getOutlineLevel()*/) {
|
|
t.setCollapsedCol(true, null, curCol);
|
|
}
|
|
}
|
|
|
|
this._updateFormulasParents(0, start, gc_nMaxRow0, gc_nMaxCol0, oActualRange, offset, renameRes.shiftedShared);
|
|
this.cellsByCol.splice(start, stop - start + 1);
|
|
this.aCols.splice(start, stop - start + 1);
|
|
for(i = start, length = this.aCols.length; i < length; ++i)
|
|
{
|
|
var elem = this.aCols[i];
|
|
if(null != elem)
|
|
elem.moveHor(nDif);
|
|
}
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RemoveCols, this.getId(), new Asc.Range(start, 0, gc_nMaxCol0, gc_nMaxRow0), new UndoRedoData_FromToRowCol(false, start, stop));
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, new Asc.Range(start, 0, stop, gc_nMaxRow0), this.getId());
|
|
}
|
|
|
|
this.workbook.dependencyFormulas.unlockRecal();
|
|
|
|
return true;
|
|
};
|
|
Worksheet.prototype.insertColsBefore=function(index, count){
|
|
var oRange = this.getRange3(0, index, gc_nMaxRow0, index + count - 1);
|
|
oRange.addCellsShiftRight();
|
|
};
|
|
Worksheet.prototype._insertColsBefore=function(index, count){
|
|
this.workbook.dependencyFormulas.lockRecal();
|
|
var oActualRange = new Asc.Range(index, 0, index + count - 1, gc_nMaxRow0);
|
|
AscCommon.History.Create_NewPoint();
|
|
var offset = new AscCommon.CellBase(0, count);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oActualRange);
|
|
var redrawTablesArr = this.autoFilters.insertColumn(oActualRange, count);
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oActualRange, offset);
|
|
this.updateUserProtectedRangesOffset(oActualRange, offset);
|
|
}
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oActualRange, offset);
|
|
this.updateSparklineGroupOffset(oActualRange, offset);
|
|
this.updateConditionalFormattingOffset(oActualRange, offset);
|
|
this.updateProtectedRangeOffset(oActualRange, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
|
|
this._updateFormulasParents(0, index, gc_nMaxRow0, gc_nMaxCol0, oActualRange, offset, renameRes.shiftedShared);
|
|
var borders;
|
|
if (index > 0 && !this.workbook.bUndoChanges) {
|
|
borders = this._getBordersForInsert(oActualRange, false);
|
|
}
|
|
//remove tail
|
|
this.cellsByCol.splice(gc_nMaxCol0 - count + 1, count);
|
|
for(var i = this.cellsByCol.length - 1; i >= index; --i) {
|
|
this.cellsByCol[i + count] = this.cellsByCol[i];
|
|
this.cellsByCol[i] = undefined;
|
|
}
|
|
this.setColsCount(Math.max(this.nColsCount, this.getColDataLength()));
|
|
this.aCols.splice(gc_nMaxCol0 - count + 1, count);
|
|
for(var i = this.aCols.length - 1; i >= index; --i) {
|
|
this.aCols[i + count] = this.aCols[i];
|
|
this.aCols[i] = undefined;
|
|
if (this.aCols[i + count]) {
|
|
this.aCols[i + count].moveHor(count);
|
|
}
|
|
}
|
|
this.setColsCount(Math.max(this.nColsCount, this.aCols.length));
|
|
if (!this.workbook.bUndoChanges) {
|
|
//copy property from col/cell above
|
|
var oPrevCol = null;
|
|
if (index > 0)
|
|
oPrevCol = this.aCols[index - 1];
|
|
if (null == oPrevCol && null != this.oAllCol)
|
|
oPrevCol = this.oAllCol;
|
|
if (null != oPrevCol) {
|
|
AscCommon.History.LocalChange = true;
|
|
for (var i = index; i < index + count; ++i) {
|
|
var oNewCol = oPrevCol.clone();
|
|
oNewCol.setHidden(null);
|
|
oNewCol.BestFit = null;
|
|
oNewCol.index = i;
|
|
this.aCols[i] = oNewCol;
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
var prevCellsByCol = index > 0 ? this.cellsByCol[index - 1] : null;
|
|
if (prevCellsByCol) {
|
|
for(var i = index; i < index + count; ++i) {
|
|
this.cellsByCol[i] = prevCellsByCol.clone();
|
|
}
|
|
this.setColsCount(Math.max(this.nColsCount, this.getColDataLength()));
|
|
//show rows and remain only cell xf property
|
|
this.getRange3(0, index, gc_nMaxRow0, index + count - 1)._foreachNoEmpty(function(cell) {
|
|
cell.clearDataKeepXf(borders[cell.nRow]);
|
|
});
|
|
}
|
|
}
|
|
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_AddCols, this.getId(), new Asc.Range(index, 0, gc_nMaxCol0, gc_nMaxRow0), new UndoRedoData_FromToRowCol(false, index, index + count - 1));
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, null, this.getId());
|
|
}
|
|
|
|
this.workbook.dependencyFormulas.unlockRecal();
|
|
return true;
|
|
};
|
|
Worksheet.prototype.insertColsAfter=function(index, count){
|
|
//index 0 based
|
|
return this.insertColsBefore(index + 1, count);
|
|
};
|
|
Worksheet.prototype.getDefaultWidth=function(){
|
|
var dRes = null;
|
|
if (this.oSheetFormatPr.dDefaultColWidth != null) {
|
|
dRes = this.oSheetFormatPr.dDefaultColWidth;
|
|
} else if(null != this.oAllCol && this.oAllCol.CustomWidth) {
|
|
dRes = this.oAllCol.width;
|
|
}
|
|
return dRes;
|
|
};
|
|
Worksheet.prototype.getDefaultFontName=function(){
|
|
return this.workbook.getDefaultFont();
|
|
};
|
|
Worksheet.prototype.getDefaultFontSize=function(){
|
|
return this.workbook.getDefaultSize();
|
|
};
|
|
Worksheet.prototype.getBaseColWidth = function () {
|
|
return this.oSheetFormatPr.nBaseColWidth || 8; // Число символов для дефалтовой ширины (по умолчинию 8)
|
|
};
|
|
Worksheet.prototype.charCountToModelColWidth = function (count) {
|
|
return this.workbook.charCountToModelColWidth(count);
|
|
};
|
|
Worksheet.prototype.modelColWidthToColWidth = function (mcw) {
|
|
return this.workbook.modelColWidthToColWidth(mcw);
|
|
};
|
|
Worksheet.prototype.colWidthToCharCount = function (w) {
|
|
return this.workbook.colWidthToCharCount(w);
|
|
};
|
|
Worksheet.prototype.getColWidth=function(index){
|
|
//index 0 based
|
|
//Результат в пунктах
|
|
var col = this._getColNoEmptyWithAll(index);
|
|
if(null != col && null != col.width)
|
|
return col.width;
|
|
var dResult = this.oSheetFormatPr.dDefaultColWidth;
|
|
if(dResult === undefined || dResult === null || dResult == 0)
|
|
//dResult = (8) + 5;//(EMCA-376.page 1857.)defaultColWidth = baseColumnWidth + {margin padding (2 pixels on each side, totalling 4 pixels)} + {gridline (1pixel)}
|
|
dResult = -1; // calc default width at presentation level
|
|
return dResult;
|
|
};
|
|
Worksheet.prototype.setColWidth=function(width, start, stop){
|
|
width = this.charCountToModelColWidth(width);
|
|
if(0 == width)
|
|
return this.setColHidden(true, start, stop);
|
|
|
|
//start, stop 0 based
|
|
if(null == start)
|
|
return;
|
|
if(null == stop)
|
|
stop = start;
|
|
AscCommon.History.Create_NewPoint();
|
|
/*var oSelection = AscCommon.History.GetSelection();
|
|
if(null != oSelection)
|
|
{
|
|
oSelection = oSelection.clone();
|
|
oSelection.assign(start, 0, stop, gc_nMaxRow0);
|
|
AscCommon.History.SetSelection(oSelection);
|
|
AscCommon.History.SetSelectionRedo(oSelection);
|
|
}*/
|
|
|
|
var bNotAddCollapsed = true == this.workbook.bUndoChanges || true == this.workbook.bRedoChanges || this.bExcludeCollapsed;
|
|
var _summaryRight = this.sheetPr ? this.sheetPr.SummaryRight : true;
|
|
var oThis = this, prevCol;
|
|
var fProcessCol = function(col){
|
|
if(col.width != width)
|
|
{
|
|
if(_summaryRight && !bNotAddCollapsed && col.getCollapsed()) {
|
|
oThis.setCollapsedCol(false, null, col);
|
|
} else if(!_summaryRight && !bNotAddCollapsed && prevCol && prevCol.getCollapsed()) {
|
|
oThis.setCollapsedCol(false, null, prevCol);
|
|
}
|
|
prevCol = col;
|
|
|
|
var oOldProps = col.getWidthProp();
|
|
col.width = width;
|
|
col.CustomWidth = true;
|
|
col.BestFit = null;
|
|
col.setHidden(null);
|
|
oThis.initColumn(col);
|
|
var oNewProps = col.getWidthProp();
|
|
if(false == oOldProps.isEqual(oNewProps))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ColProp, oThis.getId(),
|
|
col._getUpdateRange(),
|
|
new UndoRedoData_IndexSimpleProp(col.index, false, oOldProps, oNewProps));
|
|
}
|
|
};
|
|
if(0 === start && gc_nMaxCol0 === stop)
|
|
{
|
|
var col = this.getAllCol();
|
|
fProcessCol(col);
|
|
for(var i in this.aCols){
|
|
var col = this.aCols[i];
|
|
if (null != col)
|
|
fProcessCol(col);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!_summaryRight) {
|
|
if(!bNotAddCollapsed && start > 0) {
|
|
prevCol = this._getCol(start - 1);
|
|
}
|
|
}
|
|
|
|
for(var i = start; i <= stop; i++){
|
|
var col = this._getCol(i);
|
|
fProcessCol(col);
|
|
}
|
|
|
|
if(_summaryRight && !bNotAddCollapsed && prevCol) {
|
|
col = this._getCol(stop + 1);
|
|
if(col.getCollapsed()) {
|
|
this.setCollapsedCol(false, null, col);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.getColHidden=function(index){
|
|
var col = this._getColNoEmptyWithAll(index);
|
|
return col ? col.getHidden() : false;
|
|
};
|
|
Worksheet.prototype.setColHidden=function(bHidden, start, stop){
|
|
//start, stop 0 based
|
|
if(null == start)
|
|
return;
|
|
if(null == stop)
|
|
stop = start;
|
|
AscCommon.History.Create_NewPoint();
|
|
var oThis = this, outlineLevel;
|
|
var bNotAddCollapsed = true == this.workbook.bUndoChanges || true == this.workbook.bRedoChanges || this.bExcludeCollapsed;
|
|
var _summaryRight = this.sheetPr ? this.sheetPr.SummaryRight : true;
|
|
var fProcessCol = function(col){
|
|
|
|
if(col && !bNotAddCollapsed && outlineLevel !== undefined && outlineLevel !== col.getOutlineLevel()) {
|
|
if(!_summaryRight) {
|
|
oThis.setCollapsedCol(bHidden, col.index - 1);
|
|
} else {
|
|
oThis.setCollapsedCol(bHidden, null, col);
|
|
}
|
|
}
|
|
outlineLevel = col ? col.getOutlineLevel() : null;
|
|
|
|
if(col.getHidden() != bHidden)
|
|
{
|
|
var oOldProps = col.getWidthProp();
|
|
if(bHidden)
|
|
{
|
|
col.setHidden(bHidden);
|
|
if(null == col.width || true != col.CustomWidth)
|
|
col.width = 0;
|
|
col.CustomWidth = true;
|
|
col.BestFit = null;
|
|
}
|
|
else
|
|
{
|
|
col.setHidden(null);
|
|
if(0 >= col.width)
|
|
col.width = null;
|
|
}
|
|
var oNewProps = col.getWidthProp();
|
|
if(false == oOldProps.isEqual(oNewProps))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ColProp, oThis.getId(),
|
|
col._getUpdateRange(),
|
|
new UndoRedoData_IndexSimpleProp(col.index, false, oOldProps, oNewProps));
|
|
}
|
|
};
|
|
|
|
if(!bNotAddCollapsed && !_summaryRight && start > 0) {
|
|
col = this._getCol(start - 1);
|
|
outlineLevel = col.getOutlineLevel();
|
|
}
|
|
|
|
if(0 === start && gc_nMaxCol0 === stop)
|
|
{
|
|
var col = null;
|
|
if(false == bHidden)
|
|
col = this.oAllCol;
|
|
else
|
|
col = this.getAllCol();
|
|
if(null != col)
|
|
fProcessCol(col);
|
|
for(var i in this.aCols){
|
|
var col = this.aCols[i];
|
|
if (null != col)
|
|
fProcessCol(col);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(var i = start; i <= stop; i++){
|
|
var col = null;
|
|
if(false == bHidden)
|
|
col = this._getColNoEmpty(i);
|
|
else
|
|
col = this._getCol(i);
|
|
if(null != col)
|
|
fProcessCol(col);
|
|
}
|
|
}
|
|
|
|
if(!bNotAddCollapsed && outlineLevel && _summaryRight) {
|
|
col = this._getCol(stop + 1);
|
|
if(col && outlineLevel !== col.getOutlineLevel()) {
|
|
oThis.setCollapsedCol(bHidden, null, col);
|
|
}
|
|
}
|
|
};
|
|
//TODO если collapsed не будет выставляться и заносится, удалить
|
|
Worksheet.prototype.setCollapsedCol = function (bCollapse, colIndex, curCol) {
|
|
var oThis = this;
|
|
var fProcessCol = function(col){
|
|
var oOldProps = col.getCollapsed();
|
|
col.setCollapsed(bCollapse);
|
|
var oNewProps = col.getCollapsed();
|
|
|
|
if(oOldProps !== oNewProps) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_CollapsedCol, oThis.getId(), col._getUpdateRange(), new UndoRedoData_IndexSimpleProp(col.index, true, oOldProps, oNewProps));
|
|
}
|
|
};
|
|
|
|
if(curCol) {
|
|
fProcessCol(curCol);
|
|
} else {
|
|
this.getRange3(0, colIndex,0, colIndex)._foreachCol(fProcessCol);
|
|
}
|
|
};
|
|
Worksheet.prototype.setSummaryRight = function (val) {
|
|
if (!this.sheetPr){
|
|
this.sheetPr = new AscCommonExcel.asc_CSheetPr();
|
|
}
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetSummaryRight, this.getId(), null,
|
|
new UndoRedoData_FromTo(this.sheetPr.SummaryRight, val));
|
|
|
|
this.sheetPr.SummaryRight = val;
|
|
};
|
|
Worksheet.prototype.setSummaryBelow = function (val) {
|
|
if (!this.sheetPr){
|
|
this.sheetPr = new AscCommonExcel.asc_CSheetPr();
|
|
}
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetSummaryBelow, this.getId(), null,
|
|
new UndoRedoData_FromTo(this.sheetPr.SummaryBelow, val));
|
|
|
|
this.sheetPr.SummaryBelow = val;
|
|
};
|
|
Worksheet.prototype.setFitToPage = function (val) {
|
|
if((this.sheetPr && val !== this.sheetPr.FitToPage) || (!this.sheetPr && val)) {
|
|
if (!this.sheetPr){
|
|
this.sheetPr = new AscCommonExcel.asc_CSheetPr();
|
|
}
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetFitToPage, this.getId(), null,
|
|
new UndoRedoData_FromTo(this.sheetPr.FitToPage, val));
|
|
|
|
this.sheetPr.FitToPage = val;
|
|
}
|
|
};
|
|
Worksheet.prototype.setGroupCol = function (bDel, start, stop) {
|
|
var oThis = this;
|
|
var fProcessCol = function(col){
|
|
col.setOutlineLevel(null, bDel);
|
|
};
|
|
|
|
this.getRange3(0, start, 0, stop)._foreachCol(fProcessCol);
|
|
};
|
|
Worksheet.prototype.setOutlineCol = function (val, start, stop) {
|
|
var oThis = this;
|
|
|
|
var fProcessCol = function(col){
|
|
col.setOutlineLevel(val);
|
|
};
|
|
|
|
this.getRange3(0, start, 0, stop)._foreachCol(fProcessCol);
|
|
};
|
|
Worksheet.prototype.getColCustomWidth = function (index) {
|
|
var isBestFit;
|
|
var column = this._getColNoEmptyWithAll(index);
|
|
if (!column) {
|
|
isBestFit = true;
|
|
} else if (column.getHidden()) {
|
|
isBestFit = false;
|
|
} else {
|
|
isBestFit = !!(column.BestFit || (null === column.BestFit && null === column.CustomWidth));
|
|
}
|
|
return !isBestFit;
|
|
};
|
|
Worksheet.prototype.setColBestFit=function(bBestFit, width, start, stop){
|
|
//start, stop 0 based
|
|
if(null == start)
|
|
return;
|
|
if(null == stop)
|
|
stop = start;
|
|
AscCommon.History.Create_NewPoint();
|
|
var oThis = this;
|
|
var fProcessCol = function(col){
|
|
var oOldProps = col.getWidthProp();
|
|
if(bBestFit)
|
|
{
|
|
col.BestFit = bBestFit;
|
|
col.setHidden(null);
|
|
}
|
|
else
|
|
col.BestFit = null;
|
|
col.width = width;
|
|
oThis.initColumn(col);
|
|
var oNewProps = col.getWidthProp();
|
|
if(false == oOldProps.isEqual(oNewProps))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ColProp, oThis.getId(),
|
|
col._getUpdateRange(),
|
|
new UndoRedoData_IndexSimpleProp(col.index, false, oOldProps, oNewProps));
|
|
};
|
|
if(0 === start && gc_nMaxCol0 === stop)
|
|
{
|
|
var col = null;
|
|
if(bBestFit && oDefaultMetrics.ColWidthChars == width)
|
|
col = this.oAllCol;
|
|
else
|
|
col = this.getAllCol();
|
|
if(null != col)
|
|
fProcessCol(col);
|
|
for(var i in this.aCols){
|
|
var col = this.aCols[i];
|
|
if (null != col)
|
|
fProcessCol(col);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(var i = start; i <= stop; i++){
|
|
var col = null;
|
|
if(bBestFit && oDefaultMetrics.ColWidthChars == width)
|
|
col = this._getColNoEmpty(i);
|
|
else
|
|
col = this._getCol(i);
|
|
if(null != col)
|
|
fProcessCol(col);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.isDefaultHeightHidden=function(){
|
|
return null != this.oSheetFormatPr.oAllRow && this.oSheetFormatPr.oAllRow.getHidden();
|
|
};
|
|
Worksheet.prototype.isDefaultWidthHidden=function(){
|
|
return null != this.oAllCol && this.oAllCol.getHidden();
|
|
};
|
|
Worksheet.prototype.setDefaultHeight = function (h){
|
|
// ToDo refactoring this
|
|
if (this.oSheetFormatPr.oAllRow && !this.oSheetFormatPr.oAllRow.getCustomHeight()) {
|
|
this.oSheetFormatPr.oAllRow.h = h;
|
|
}
|
|
};
|
|
Worksheet.prototype.getDefaultHeight=function(){
|
|
// ToDo http://bugzilla.onlyoffice.com/show_bug.cgi?id=19666 (флага CustomHeight нет)
|
|
var dRes = null;
|
|
// Нужно возвращать выставленную, только если флаг CustomHeight = true
|
|
if(null != this.oSheetFormatPr.oAllRow && this.oSheetFormatPr.oAllRow.getCustomHeight())
|
|
dRes = this.oSheetFormatPr.oAllRow.h;
|
|
return dRes;
|
|
};
|
|
Worksheet.prototype.getRowHeight = function(index) {
|
|
var res;
|
|
this._getRowNoEmptyWithAll(index, function(row){
|
|
res = row ? row.getHeight() : -1;
|
|
});
|
|
return res;
|
|
};
|
|
Worksheet.prototype.setRowHeight=function(height, start, stop, isCustom){
|
|
if(0 == height)
|
|
return this.setRowHidden(true, start, stop);
|
|
//start, stop 0 based
|
|
if(null == start)
|
|
return;
|
|
if(null == stop)
|
|
stop = start;
|
|
AscCommon.History.Create_NewPoint();
|
|
var oThis = this, i;
|
|
/*var oSelection = AscCommon.History.GetSelection();
|
|
if(null != oSelection)
|
|
{
|
|
oSelection = oSelection.clone();
|
|
oSelection.assign(0, start, gc_nMaxCol0, stop);
|
|
AscCommon.History.SetSelection(oSelection);
|
|
AscCommon.History.SetSelectionRedo(oSelection);
|
|
}*/
|
|
var prevRow;
|
|
var bNotAddCollapsed = true == this.workbook.bUndoChanges || true == this.workbook.bRedoChanges || this.bExcludeCollapsed;
|
|
var _summaryBelow = this.sheetPr ? this.sheetPr.SummaryBelow : true;
|
|
var fProcessRow = function(row){
|
|
if(row)
|
|
{
|
|
if(_summaryBelow && !bNotAddCollapsed && row.getCollapsed()) {
|
|
oThis.setCollapsedRow(false, null, row);
|
|
} else if(!_summaryBelow && !bNotAddCollapsed && prevRow && prevRow.getCollapsed()) {
|
|
oThis.setCollapsedRow(false, null, prevRow);
|
|
}
|
|
prevRow = row;
|
|
|
|
var oOldProps = row.getHeightProp();
|
|
let bOldCalcHeight = row.getCalcHeight();
|
|
row.setHeight(height);
|
|
if (isCustom) {
|
|
row.setCustomHeight(true);
|
|
}
|
|
row.setCalcHeight(true);
|
|
row.setHidden(false);
|
|
var oNewProps = row.getHeightProp();
|
|
if (oOldProps.isEqual(oNewProps)) {
|
|
bOldCalcHeight === row.getCalcHeight() && row.setChanged(false);
|
|
} else {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RowProp, oThis.getId(), row._getUpdateRange(), new UndoRedoData_IndexSimpleProp(row.index, true, oOldProps, oNewProps));
|
|
}
|
|
}
|
|
};
|
|
if(0 == start && gc_nMaxRow0 == stop)
|
|
{
|
|
fProcessRow(this.getAllRow());
|
|
this._forEachRow(fProcessRow);
|
|
}
|
|
else
|
|
{
|
|
if(!_summaryBelow) {
|
|
if(!bNotAddCollapsed && start > 0) {
|
|
this._getRow(start - 1, function(row) {
|
|
prevRow = row;
|
|
});
|
|
}
|
|
}
|
|
|
|
this.getRange3(start,0,stop, 0)._foreachRow(fProcessRow);
|
|
|
|
if(_summaryBelow) {
|
|
if(!bNotAddCollapsed && prevRow) {
|
|
this._getRow(stop + 1, function(row) {
|
|
if(row.getCollapsed()) {
|
|
oThis.setCollapsedRow(false, null, row);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
if(this.needRecalFormulas(start, stop)) {
|
|
this.workbook.dependencyFormulas.calcTree();
|
|
}
|
|
};
|
|
Worksheet.prototype.getRowHidden=function(index){
|
|
var res;
|
|
this._getRowNoEmptyWithAll(index, function(row){
|
|
res = row ? row.getHidden() : false;
|
|
});
|
|
return res;
|
|
};
|
|
Worksheet.prototype.setRowHidden=function(bHidden, start, stop){
|
|
//start, stop 0 based
|
|
if(null == start)
|
|
return;
|
|
if(null == stop)
|
|
stop = start;
|
|
|
|
var oThis = this;
|
|
|
|
var doHide = function (_start, _stop, localChange) {
|
|
var i;
|
|
var startIndex = null, endIndex = null, updateRange, outlineLevel;
|
|
var bNotAddCollapsed = true == oThis.workbook.bUndoChanges || true == oThis.workbook.bRedoChanges || oThis.bExcludeCollapsed;
|
|
var _summaryBelow = oThis.sheetPr ? oThis.sheetPr.SummaryBelow : true;
|
|
var fProcessRow = function(row){
|
|
if(row && !bNotAddCollapsed && outlineLevel !== undefined && outlineLevel !== row.getOutlineLevel()) {
|
|
if(!_summaryBelow) {
|
|
oThis.setCollapsedRow(bHidden, row.index - 1);
|
|
} else {
|
|
oThis.setCollapsedRow(bHidden, null, row);
|
|
}
|
|
}
|
|
outlineLevel = row ? row.getOutlineLevel() : null;
|
|
|
|
if(row && bHidden != row.getHidden())
|
|
{
|
|
row.setHidden(bHidden, localChange);
|
|
|
|
if(row.index === endIndex + 1 && startIndex !== null)
|
|
endIndex++;
|
|
else
|
|
{
|
|
if(startIndex !== null)
|
|
{
|
|
updateRange = new Asc.Range(0, startIndex, gc_nMaxCol0, endIndex);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RowHide, oThis.getId(), updateRange, new UndoRedoData_FromToRowCol(bHidden, startIndex, endIndex));
|
|
}
|
|
|
|
startIndex = row.index;
|
|
endIndex = row.index;
|
|
}
|
|
}
|
|
};
|
|
if(0 == _start && gc_nMaxRow0 == _stop)
|
|
{
|
|
// ToDo реализовать скрытие всех строк!
|
|
}
|
|
else
|
|
{
|
|
if(!_summaryBelow && _start > 0 && !bNotAddCollapsed) {
|
|
oThis._getRow(_start - 1, function(row) {
|
|
if(row) {
|
|
outlineLevel = row.getOutlineLevel();
|
|
}
|
|
});
|
|
}
|
|
|
|
for (i = _start; i <= _stop; ++i) {
|
|
false == bHidden ? oThis._getRowNoEmpty(i, fProcessRow) : oThis._getRow(i, fProcessRow);
|
|
}
|
|
|
|
if(_summaryBelow && outlineLevel && !bNotAddCollapsed) {
|
|
oThis._getRow(_stop + 1, function(row) {
|
|
if(row && outlineLevel !== row.getOutlineLevel()) {
|
|
oThis.setCollapsedRow(bHidden, null, row);
|
|
}
|
|
});
|
|
}
|
|
|
|
if(startIndex !== null)//заносим последние строки
|
|
{
|
|
updateRange = new Asc.Range(0, startIndex, gc_nMaxCol0, endIndex);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RowHide, oThis.getId(),updateRange, new UndoRedoData_FromToRowCol(bHidden, startIndex, endIndex));
|
|
}
|
|
}
|
|
};
|
|
|
|
var bCollaborativeChanges = !this.autoFilters.useViewLocalChange && this.workbook.bCollaborativeChanges
|
|
if (!bCollaborativeChanges && null !== this.getActiveNamedSheetViewId()) {
|
|
var rowsArr = this.autoFilters.splitRangeByFilters(start, stop);
|
|
if (rowsArr) {
|
|
var j;
|
|
AscCommon.History.Create_NewPoint();
|
|
if (rowsArr[0] && rowsArr[0].length) {
|
|
var oldLocalChange = AscCommon.History.LocalChange;
|
|
AscCommon.History.LocalChange = true;
|
|
for (j = 0; j < rowsArr[0].length; j++) {
|
|
doHide(rowsArr[0][j].start, rowsArr[0][j].stop, true)
|
|
}
|
|
AscCommon.History.LocalChange = oldLocalChange;
|
|
}
|
|
if (rowsArr[1] && rowsArr[1].length) {
|
|
for (j = 0; j < rowsArr[1].length; j++) {
|
|
doHide(rowsArr[1][j].start, rowsArr[1][j].stop)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
AscCommon.History.Create_NewPoint();
|
|
doHide(start, stop)
|
|
}
|
|
|
|
if(this.needRecalFormulas(start, stop)) {
|
|
this.workbook.dependencyFormulas.calcTree();
|
|
}
|
|
};
|
|
//TODO
|
|
Worksheet.prototype.setCollapsedRow = function (bCollapse, rowIndex, curRow) {
|
|
var oThis = this;
|
|
var fProcessRow = function(row, bSave){
|
|
var oOldProps = row.getCollapsed();
|
|
row.setCollapsed(bCollapse);
|
|
var oNewProps = row.getCollapsed();
|
|
|
|
if(oOldProps !== oNewProps) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_CollapsedRow, oThis.getId(), row._getUpdateRange(), new UndoRedoData_IndexSimpleProp(row.index, true, oOldProps, oNewProps));
|
|
}
|
|
if(bSave) {
|
|
row.saveContent(true);
|
|
}
|
|
};
|
|
|
|
if(curRow) {
|
|
fProcessRow(curRow, true);
|
|
} else {
|
|
this.getRange3(rowIndex,0,rowIndex, 0)._foreachRow(fProcessRow);
|
|
}
|
|
};
|
|
Worksheet.prototype.setGroupRow = function (bDel, start, stop) {
|
|
var oThis = this;
|
|
var fProcessRow = function(row){
|
|
row.setOutlineLevel(null, bDel);
|
|
};
|
|
|
|
this.getRange3(start,0,stop, 0)._foreachRow(fProcessRow);
|
|
};
|
|
Worksheet.prototype.setOutlineRow = function (val, start, stop) {
|
|
var oThis = this;
|
|
var fProcessRow = function(row){
|
|
row.setOutlineLevel(val);
|
|
};
|
|
|
|
this.getRange3(start,0,stop, 0)._foreachRow(fProcessRow);
|
|
};
|
|
Worksheet.prototype.getRowCustomHeight = function (index) {
|
|
var isCustomHeight = false;
|
|
this._getRowNoEmptyWithAll(index, function (row) {
|
|
if (!row) {
|
|
isCustomHeight = false;
|
|
} else if (row.getHidden()) {
|
|
isCustomHeight = true;
|
|
} else {
|
|
isCustomHeight = row.getCustomHeight();
|
|
}
|
|
});
|
|
return isCustomHeight;
|
|
};
|
|
Worksheet.prototype.setRowBestFit=function(bBestFit, height, start, stop){
|
|
//start, stop 0 based
|
|
if(null == start)
|
|
return;
|
|
if(null == stop)
|
|
stop = start;
|
|
AscCommon.History.Create_NewPoint();
|
|
var oThis = this, i;
|
|
var isDefaultProp = (true == bBestFit && oDefaultMetrics.RowHeight == height);
|
|
var fProcessRow = function(row){
|
|
if(row)
|
|
{
|
|
var oOldProps = row.getHeightProp();
|
|
row.setCustomHeight(!bBestFit);
|
|
row.setCalcHeight(true);
|
|
row.setHeight(height);
|
|
var oNewProps = row.getHeightProp();
|
|
if(false == oOldProps.isEqual(oNewProps))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RowProp, oThis.getId(), row._getUpdateRange(), new UndoRedoData_IndexSimpleProp(row.index, true, oOldProps, oNewProps));
|
|
}
|
|
};
|
|
if(0 == start && gc_nMaxRow0 == stop) {
|
|
fProcessRow(isDefaultProp ? this.oSheetFormatPr.oAllRow : this.getAllRow());
|
|
this._forEachRow(fProcessRow);
|
|
} else {
|
|
var range = this.getRange3(start,0,stop, 0);
|
|
if (isDefaultProp) {
|
|
range._foreachRowNoEmpty(fProcessRow);
|
|
} else {
|
|
range._foreachRow(fProcessRow);
|
|
}
|
|
}
|
|
this.workbook.dependencyFormulas.calcTree();
|
|
};
|
|
Worksheet.prototype.getCell=function(oCellAdd){
|
|
return this.getRange(oCellAdd, oCellAdd);
|
|
};
|
|
Worksheet.prototype.getCell2=function(sCellAdd){
|
|
if( sCellAdd.indexOf("$") > -1)
|
|
sCellAdd = sCellAdd.replace(/\$/g,"");
|
|
return this.getRange2(sCellAdd);
|
|
};
|
|
Worksheet.prototype.getCell3=function(r1, c1){
|
|
return this.getRange3(r1, c1, r1, c1);
|
|
};
|
|
Worksheet.prototype.getRange=function(cellAdd1, cellAdd2){
|
|
//Если range находится за границами ячеек расширяем их
|
|
var nRow1 = cellAdd1.getRow0();
|
|
var nCol1 = cellAdd1.getCol0();
|
|
var nRow2 = cellAdd2.getRow0();
|
|
var nCol2 = cellAdd2.getCol0();
|
|
return this.getRange3(nRow1, nCol1, nRow2, nCol2);
|
|
};
|
|
Worksheet.prototype.getRange2=function(sRange){
|
|
var bbox = AscCommonExcel.g_oRangeCache.getAscRange(sRange);
|
|
if(null != bbox)
|
|
return Range.prototype.createFromBBox(this, bbox);
|
|
return null;
|
|
};
|
|
Worksheet.prototype.getRange3=function(r1, c1, r2, c2){
|
|
var nRowMin = r1;
|
|
var nRowMax = r2;
|
|
var nColMin = c1;
|
|
var nColMax = c2;
|
|
if(r1 > r2){
|
|
nRowMax = r1;
|
|
nRowMin = r2;
|
|
}
|
|
if(c1 > c2){
|
|
nColMax = c1;
|
|
nColMin = c2;
|
|
}
|
|
return new Range(this, nRowMin, nColMin, nRowMax, nColMax);
|
|
};
|
|
Worksheet.prototype.getRange4=function(r, c){
|
|
return new Range(this, r, c, r, c);
|
|
};
|
|
Worksheet.prototype.getRowIterator=function(r1, c1, c2, callback){
|
|
var it = new RowIterator();
|
|
it.init(this, r1, c1, c2);
|
|
callback(it);
|
|
it.release();
|
|
};
|
|
Worksheet.prototype.getCellForValidation=function(row, col, array, formula, callback, isCopyPaste, byRef){
|
|
let cell;
|
|
this._getCell(row, col, function (_cell) {
|
|
cell = _cell.clone();
|
|
});
|
|
cell.setValueForValidation(array, formula, callback, isCopyPaste, byRef);
|
|
return cell;
|
|
};
|
|
Worksheet.prototype._removeCell=function(nRow, nCol, cell, ignoreNoEmpty){
|
|
var t = this;
|
|
var processCell = function(cell) {
|
|
if(null != cell)
|
|
{
|
|
var sheetId = t.getId();
|
|
if (false == cell.isEmpty()) {
|
|
var oUndoRedoData_CellData = new AscCommonExcel.UndoRedoData_CellData(cell.getValueData(), null);
|
|
if (null != cell.xfs)
|
|
oUndoRedoData_CellData.style = cell.xfs.clone();
|
|
if (cell.formulaParsed) {
|
|
cell.checkRemoveExternalReferences(null, cell.formulaParsed);
|
|
}
|
|
cell.setFormulaInternal(null);
|
|
let oUndoRedoData_CellData_New = ignoreNoEmpty ? new AscCommonExcel.UndoRedoData_CellData(cell.getValueData(), null) : null;
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RemoveCell, sheetId, new Asc.Range(nCol, nRow, nCol, nRow), new UndoRedoData_CellSimpleData(nRow, nCol, oUndoRedoData_CellData, oUndoRedoData_CellData_New));
|
|
}
|
|
t.workbook.dependencyFormulas.addToChangedCell(cell);
|
|
|
|
cell.clearData();
|
|
cell.saveContent(true);
|
|
}
|
|
};
|
|
if(null != cell)
|
|
{
|
|
nRow = cell.nRow;
|
|
nCol = cell.nCol;
|
|
processCell(cell);
|
|
} else {
|
|
this._getCellNoEmpty(nRow, nCol, processCell);
|
|
}
|
|
};
|
|
Worksheet.prototype._getCell=function(row, col, fAction){
|
|
var wb = this.workbook;
|
|
var targetCell = null;
|
|
for (var k = 0; k < wb.loadCells.length; ++k) {
|
|
var elem = wb.loadCells[k];
|
|
if (elem.nRow == row && elem.nCol == col && this === elem.ws) {
|
|
targetCell = elem;
|
|
break;
|
|
}
|
|
}
|
|
if(null === targetCell){
|
|
var cell = new Cell(this);
|
|
wb.loadCells.push(cell);
|
|
if (!cell.loadContent(row, col)) {
|
|
this._initCell(cell, row, col);
|
|
}
|
|
fAction(cell);
|
|
cell.saveContent(true);
|
|
wb.loadCells.pop();
|
|
} else {
|
|
fAction(targetCell);
|
|
}
|
|
};
|
|
Worksheet.prototype._initRow=function(row, index){
|
|
var t = this;
|
|
row.setChanged(true);
|
|
if (null != this.oSheetFormatPr.oAllRow) {
|
|
row.copyFrom(this.oSheetFormatPr.oAllRow);
|
|
row.setIndex(index);
|
|
}
|
|
this.nRowsCount = index >= this.nRowsCount ? index + 1 : this.nRowsCount;
|
|
};
|
|
Worksheet.prototype._initCell=function(cell, nRow, nCol){
|
|
var t = this;
|
|
cell.setChanged(true);
|
|
this._getRowNoEmpty(nRow, function(row) {
|
|
var oCol = t._getColNoEmptyWithAll(nCol);
|
|
var xfs = null;
|
|
if (row && null != row.xfs)
|
|
xfs = row.xfs.clone();
|
|
else if (null != oCol && null != oCol.xfs)
|
|
xfs = oCol.xfs.clone();
|
|
cell.setStyleInternal(xfs);
|
|
t.cellsByColRowsCount = Math.max(t.cellsByColRowsCount, nRow + 1);
|
|
t.nRowsCount = Math.max(t.nRowsCount, t.cellsByColRowsCount);
|
|
if (nCol >= t.nColsCount)
|
|
t.setColsCount(nCol + 1);
|
|
});
|
|
//init ColData otherwise all 'foreach' will not return this cell until saveContent(loadCells)
|
|
var sheetMemory = this.getColData(nCol);
|
|
sheetMemory.checkIndex(nRow);
|
|
};
|
|
Worksheet.prototype._getCellNoEmpty=function(row, col, fAction){
|
|
var wb = this.workbook;
|
|
var targetCell = null;
|
|
for (var k = 0; k < wb.loadCells.length; ++k) {
|
|
var elem = wb.loadCells[k];
|
|
if (elem.nRow == row && elem.nCol == col && this === elem.ws) {
|
|
targetCell = elem;
|
|
break;
|
|
}
|
|
}
|
|
if (null === targetCell) {
|
|
var cell = new Cell(this);
|
|
var res = cell.loadContent(row, col) ? cell : null;
|
|
if (res && fAction) {
|
|
wb.loadCells.push(cell);
|
|
}
|
|
if (res && this.workbook.checkProtectedValue && this.isUserProtectedRangesIntersectionCell(res, null, null, Asc.c_oSerUserProtectedRangeType.View)) {
|
|
res.cleanText();
|
|
res._hasChanged = false;
|
|
}
|
|
fAction(res);
|
|
cell.saveContent(true);
|
|
if (res) {
|
|
wb.loadCells.pop();
|
|
}
|
|
} else {
|
|
fAction(targetCell);
|
|
}
|
|
};
|
|
Worksheet.prototype._getRowNoEmpty=function(nRow, fAction){
|
|
//0-based
|
|
var row = new AscCommonExcel.Row(this);
|
|
if(row.loadContent(nRow)){
|
|
fAction(row);
|
|
row.saveContent(true);
|
|
} else {
|
|
fAction(null);
|
|
}
|
|
};
|
|
Worksheet.prototype._getRowNoEmptyWithAll=function(nRow, fAction){
|
|
var t = this;
|
|
this._getRowNoEmpty(nRow, function(row){
|
|
if(!row)
|
|
row = t.oSheetFormatPr.oAllRow;
|
|
fAction(row);
|
|
});
|
|
|
|
};
|
|
Worksheet.prototype._getColNoEmpty = function (col) {
|
|
//0-based
|
|
return this.aCols[col] || null;
|
|
};
|
|
Worksheet.prototype._getColNoEmptyWithAll = function (col) {
|
|
return this._getColNoEmpty(col) || this.oAllCol;
|
|
};
|
|
Worksheet.prototype._getRow = function(index, fAction) {
|
|
//0-based
|
|
var row = null;
|
|
if (g_nAllRowIndex == index)
|
|
row = this.getAllRow();
|
|
else {
|
|
row = new AscCommonExcel.Row(this);
|
|
if (!row.loadContent(index)) {
|
|
this._initRow(row, index);
|
|
}
|
|
}
|
|
fAction(row);
|
|
row.saveContent(true);
|
|
};
|
|
Worksheet.prototype._getCol=function(index){
|
|
//0-based
|
|
var oCurCol;
|
|
if (g_nAllColIndex == index)
|
|
oCurCol = this.getAllCol();
|
|
else
|
|
{
|
|
oCurCol = this.aCols[index];
|
|
if(null == oCurCol)
|
|
{
|
|
if(null != this.oAllCol)
|
|
{
|
|
oCurCol = this.oAllCol.clone();
|
|
oCurCol.index = index;
|
|
}
|
|
else
|
|
oCurCol = new AscCommonExcel.Col(this, index);
|
|
this.aCols[index] = oCurCol;
|
|
this.setColsCount(index >= this.nColsCount ? index + 1 : this.nColsCount)
|
|
}
|
|
}
|
|
return oCurCol;
|
|
};
|
|
Worksheet.prototype._prepareMoveRangeGetCleanRanges=function(oBBoxFrom, oBBoxTo, wsTo){
|
|
var intersection = oBBoxFrom.intersectionSimple(oBBoxTo);
|
|
var aRangesToCheck = [];
|
|
if(null != intersection && this === wsTo)
|
|
{
|
|
var oThis = this;
|
|
var fAddToRangesToCheck = function(aRangesToCheck, r1, c1, r2, c2)
|
|
{
|
|
if(r1 <= r2 && c1 <= c2)
|
|
aRangesToCheck.push(oThis.getRange3(r1, c1, r2, c2));
|
|
};
|
|
if(intersection.r1 == oBBoxTo.r1 && intersection.c1 == oBBoxTo.c1)
|
|
{
|
|
fAddToRangesToCheck(aRangesToCheck, oBBoxTo.r1, intersection.c2 + 1, intersection.r2, oBBoxTo.c2);
|
|
fAddToRangesToCheck(aRangesToCheck, intersection.r2 + 1, oBBoxTo.c1, oBBoxTo.r2, oBBoxTo.c2);
|
|
}
|
|
else if(intersection.r2 == oBBoxTo.r2 && intersection.c1 == oBBoxTo.c1)
|
|
{
|
|
fAddToRangesToCheck(aRangesToCheck, oBBoxTo.r1, oBBoxTo.c1, intersection.r1 - 1, oBBoxTo.c2);
|
|
fAddToRangesToCheck(aRangesToCheck, intersection.r1, intersection.c2 + 1, oBBoxTo.r2, oBBoxTo.c2);
|
|
}
|
|
else if(intersection.r1 == oBBoxTo.r1 && intersection.c2 == oBBoxTo.c2)
|
|
{
|
|
fAddToRangesToCheck(aRangesToCheck, oBBoxTo.r1, oBBoxTo.c1, intersection.r2, intersection.c1 - 1);
|
|
fAddToRangesToCheck(aRangesToCheck, intersection.r2 + 1, oBBoxTo.c1, oBBoxTo.r2, oBBoxTo.c2);
|
|
}
|
|
else if(intersection.r2 == oBBoxTo.r2 && intersection.c2 == oBBoxTo.c2)
|
|
{
|
|
fAddToRangesToCheck(aRangesToCheck, oBBoxTo.r1, oBBoxTo.c1, intersection.r1 - 1, oBBoxTo.c2);
|
|
fAddToRangesToCheck(aRangesToCheck, intersection.r1, oBBoxTo.c1, oBBoxTo.r2, intersection.c1 - 1);
|
|
}
|
|
}
|
|
else
|
|
aRangesToCheck.push(wsTo.getRange3(oBBoxTo.r1, oBBoxTo.c1, oBBoxTo.r2, oBBoxTo.c2));
|
|
return aRangesToCheck;
|
|
};
|
|
Worksheet.prototype._prepareMoveRange=function(oBBoxFrom, oBBoxTo, wsTo){
|
|
var res = 0;
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (oBBoxFrom.isEqual(oBBoxTo) && this === wsTo)
|
|
return res;
|
|
var range = wsTo.getRange3(oBBoxTo.r1, oBBoxTo.c1, oBBoxTo.r2, oBBoxTo.c2);
|
|
var aMerged = wsTo.mergeManager.get(range.getBBox0());
|
|
if(aMerged.outer.length > 0)
|
|
return -2;
|
|
var aRangesToCheck = this._prepareMoveRangeGetCleanRanges(oBBoxFrom, oBBoxTo, wsTo);
|
|
for(var i = 0, length = aRangesToCheck.length; i < length; i++)
|
|
{
|
|
range = aRangesToCheck[i];
|
|
range._foreachNoEmpty(
|
|
function(cell){
|
|
if(!cell.isNullTextString())
|
|
{
|
|
res = -1;
|
|
return res;
|
|
}
|
|
});
|
|
if(0 != res)
|
|
return res;
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype._movePivots = function (oBBoxFrom, oBBoxTo, copyRange, offset, wsTo) {
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
if (copyRange) {
|
|
wsTo.deletePivotTables(oBBoxTo);
|
|
this.copyPivotTable(oBBoxFrom, offset, wsTo);
|
|
} else {
|
|
if (this === wsTo) {
|
|
this.deletePivotTablesOnMove(oBBoxFrom, oBBoxTo);
|
|
this.movePivotOffset(oBBoxFrom, offset);
|
|
} else {
|
|
this.copyPivotTable(oBBoxFrom, offset, wsTo);
|
|
this._movePivotSlicerWsRefs(oBBoxTo, this, wsTo);
|
|
this.deletePivotTables(oBBoxFrom, true);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._movePivotSlicerWsRefs = function (range, wsFrom, wsTo) {
|
|
var wb = this.workbook;
|
|
var pivotTable;
|
|
for (var i = 0; i < wsTo.pivotTables.length; ++i) {
|
|
pivotTable = wsTo.pivotTables[i];
|
|
if (pivotTable.isInRange(range)) {
|
|
var slicerCaches = wb.getSlicerCachesByPivotTable(wsFrom.getId(), pivotTable.asc_getName());
|
|
slicerCaches.forEach(function (slicerCache) {
|
|
slicerCache.movePivotTable(wsFrom.getId(), pivotTable.asc_getName(), wsTo.getId(), pivotTable.asc_getName());
|
|
});
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._moveMergedAndHyperlinksPrepare = function(oBBoxFrom, oBBoxTo, copyRange, wsTo, offset) {
|
|
var res = {merged: [], hyperlinks: []};
|
|
if (!(false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges))) {
|
|
return res;
|
|
}
|
|
var i, elem, bbox, data, wsFrom = this;
|
|
var intersection = oBBoxFrom.intersectionSimple(oBBoxTo);
|
|
AscCommon.History.LocalChange = true;
|
|
//merged
|
|
var merged = wsFrom.mergeManager.get(oBBoxFrom).inner;
|
|
var mergedToRemove;
|
|
if (!copyRange) {
|
|
mergedToRemove = merged;
|
|
} else if (null !== intersection) {
|
|
mergedToRemove = wsFrom.mergeManager.get(intersection).all;
|
|
}
|
|
if(mergedToRemove){
|
|
for (i = 0; i < mergedToRemove.length; i++) {
|
|
wsFrom.mergeManager.removeElement(mergedToRemove[i]);
|
|
}
|
|
}
|
|
|
|
//hyperlinks
|
|
var hyperlinks = wsFrom.hyperlinkManager.get(oBBoxFrom).inner;
|
|
if (!copyRange) {
|
|
for (i = 0; i < hyperlinks.length; i++) {
|
|
wsFrom.hyperlinkManager.removeElement(hyperlinks[i]);
|
|
}
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
res.merged = merged;
|
|
res.hyperlinks = hyperlinks;
|
|
return res;
|
|
};
|
|
Worksheet.prototype._moveMergedAndHyperlinks = function(prepared, oBBoxFrom, oBBoxTo, copyRange, wsTo, offset) {
|
|
var i, elem, bbox, data;
|
|
var intersection = oBBoxFrom.intersectionSimple(oBBoxTo);
|
|
AscCommon.History.LocalChange = true;
|
|
for (i = 0; i < prepared.merged.length; i++) {
|
|
elem = prepared.merged[i];
|
|
bbox = copyRange ? elem.bbox.clone() : elem.bbox;
|
|
bbox.setOffset(offset);
|
|
wsTo.mergeManager.add(bbox, elem.data);
|
|
}
|
|
//todo сделать для пересечения
|
|
if (!copyRange || null === intersection) {
|
|
for (i = 0; i < prepared.hyperlinks.length; i++) {
|
|
elem = prepared.hyperlinks[i];
|
|
if (copyRange) {
|
|
bbox = elem.bbox.clone();
|
|
data = elem.data.clone();
|
|
}
|
|
else {
|
|
bbox = elem.bbox;
|
|
data = elem.data;
|
|
}
|
|
bbox.setOffset(offset);
|
|
wsTo.hyperlinkManager.add(bbox, data);
|
|
}
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
};
|
|
Worksheet.prototype._moveCleanRanges = function(oBBoxFrom, oBBoxTo, copyRange, wsTo) {
|
|
//удаляем to через историю, для undo
|
|
var cleanRanges = this._prepareMoveRangeGetCleanRanges(oBBoxFrom, oBBoxTo, wsTo);
|
|
for (var i = 0; i < cleanRanges.length; i++) {
|
|
var range = cleanRanges[i];
|
|
range.cleanAll();
|
|
//выставляем для slave refError
|
|
if (!copyRange)
|
|
this.workbook.dependencyFormulas.deleteNodes(wsTo.getId(), range.getBBox0());
|
|
}
|
|
};
|
|
Worksheet.prototype._moveFormulas = function(oBBoxFrom, oBBoxTo, copyRange, wsTo, offset, isTableCreated) {
|
|
if(!copyRange){
|
|
this.workbook.dependencyFormulas.move(this.Id, oBBoxFrom, offset, wsTo.getId(), isTableCreated);
|
|
}
|
|
//todo avoid double getRange3
|
|
this.getRange3(oBBoxFrom.r1, oBBoxFrom.c1, oBBoxFrom.r2, oBBoxFrom.c2)._foreachNoEmpty(function(cell) {
|
|
if (cell.transformSharedFormula()) {
|
|
var parsed = cell.getFormulaParsed();
|
|
parsed.buildDependencies();
|
|
}
|
|
});
|
|
};
|
|
Worksheet.prototype._moveCells = function(oBBoxFrom, oBBoxTo, copyRange, wsTo, offset) {
|
|
var oThis = this;
|
|
var nRowsCountNew = 0;
|
|
var nColsCountNew = 0;
|
|
var dependencyFormulas = oThis.workbook.dependencyFormulas;
|
|
var moveToOtherSheet = this !== wsTo;
|
|
var isClearFromArea = !copyRange || (copyRange && oThis.workbook.bUndoChanges);
|
|
var moveCells = function(copyRange, from, to, r1From, r1To, count){
|
|
var fromData = oThis.getColDataNoEmpty(from);
|
|
var toData;
|
|
if(fromData){
|
|
toData = wsTo.getColData(to);
|
|
toData.copyRange(fromData, r1From, r1To, count);
|
|
if (isClearFromArea) {
|
|
if(from !== to || moveToOtherSheet) {
|
|
fromData.clear(r1From, r1From + count);
|
|
} else {
|
|
if (r1From < r1To) {
|
|
fromData.clear(r1From, Math.min(r1From + count, r1To));
|
|
} else {
|
|
fromData.clear(Math.max(r1From, r1To + count), r1From + count);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
toData = wsTo.getColDataNoEmpty(to);
|
|
if(toData) {
|
|
toData.clear(r1To, r1To + count);
|
|
}
|
|
}
|
|
if (toData) {
|
|
nRowsCountNew = Math.max(nRowsCountNew, toData.getMaxIndex() + 1);
|
|
nColsCountNew = Math.max(nColsCountNew, to + 1);
|
|
}
|
|
};
|
|
if(oBBoxFrom.c1 < oBBoxTo.c1){
|
|
for(var i = 0 ; i < oBBoxFrom.c2 - oBBoxFrom.c1 + 1; ++i){
|
|
moveCells(copyRange, oBBoxFrom. c2 - i, oBBoxTo.c2 - i, oBBoxFrom.r1, oBBoxTo.r1, oBBoxFrom.r2 - oBBoxFrom.r1 + 1);
|
|
}
|
|
} else {
|
|
for(var i = 0 ; i < oBBoxFrom.c2 - oBBoxFrom.c1 + 1; ++i){
|
|
moveCells(copyRange, oBBoxFrom.c1 + i, oBBoxTo.c1 + i, oBBoxFrom.r1, oBBoxTo.r1, oBBoxFrom.r2 - oBBoxFrom.r1 + 1);
|
|
}
|
|
}
|
|
// ToDo возможно нужно уменьшить диапазон обновления
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_MoveRange,
|
|
this.getId(), new Asc.Range(0, 0, gc_nMaxCol0, gc_nMaxRow0),
|
|
new UndoRedoData_FromTo(new UndoRedoData_BBox(oBBoxFrom), new UndoRedoData_BBox(oBBoxTo), copyRange, wsTo.getId()));
|
|
if(moveToOtherSheet) {
|
|
//сделано для того, чтобы происходил пересчет/обновление данных на другом листе
|
|
//таким образом заносим диапазон обновления в UpdateRigions
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_Null, wsTo.getId(), oBBoxTo, new UndoRedoData_FromTo(null, null));
|
|
}
|
|
|
|
var shiftedArrayFormula = {};
|
|
var oldNewArrayFormulaMap = {};
|
|
//modify nRowsCount/nColsCount for correct foreach functions
|
|
wsTo.cellsByColRowsCount = Math.max(wsTo.cellsByColRowsCount, nRowsCountNew);
|
|
wsTo.nRowsCount = Math.max(wsTo.nRowsCount, wsTo.cellsByColRowsCount);
|
|
wsTo.setColsCount(Math.max(wsTo.nColsCount, nColsCountNew));
|
|
wsTo.getRange3(oBBoxTo.r1, oBBoxTo.c1, oBBoxTo.r2, oBBoxTo.c2)._foreachNoEmpty(function(cell){
|
|
var formula = cell.getFormulaParsed();
|
|
if (formula) {
|
|
var cellWithFormula = formula.getParent();
|
|
var arrayFormula = formula.getArrayFormulaRef();
|
|
var newArrayRef, newFormula;
|
|
var preMoveCell = {nRow: cell.nRow - offset.row, nCol: cell.nCol - offset.col};
|
|
var isFirstCellArray = formula.checkFirstCellArray(preMoveCell) && !shiftedArrayFormula[formula.getListenerId()];
|
|
if (copyRange) {
|
|
AscCommon.History.TurnOff();
|
|
//***array-formula***
|
|
if(!arrayFormula || (arrayFormula && isFirstCellArray)) {
|
|
newFormula = oThis._moveCellsFormula(cell, formula, cellWithFormula, copyRange, oBBoxFrom, wsTo);
|
|
cellWithFormula = newFormula.getParent();
|
|
cellWithFormula = new CCellWithFormula(wsTo, cell.nRow, cell.nCol);
|
|
newFormula = newFormula.clone(null, cellWithFormula, wsTo);
|
|
newFormula.changeOffset(offset, false, true);
|
|
newFormula.setFormulaString(newFormula.assemble(true));
|
|
cell.setFormulaInternal(newFormula, !isClearFromArea);
|
|
|
|
if(isFirstCellArray) {
|
|
newArrayRef = arrayFormula.clone();
|
|
newArrayRef.setOffset(offset);
|
|
newFormula.setArrayFormulaRef(newArrayRef);
|
|
shiftedArrayFormula[newFormula.getListenerId()] = 1;
|
|
oldNewArrayFormulaMap[formula.getListenerId()] = newFormula;
|
|
}
|
|
} else if(arrayFormula && oldNewArrayFormulaMap[formula.getListenerId()]) {
|
|
cell.setFormulaInternal(oldNewArrayFormulaMap[formula.getListenerId()], !isClearFromArea);
|
|
}
|
|
AscCommon.History.TurnOn();
|
|
} else {
|
|
//***array-formula***
|
|
//TODO возможно стоит это делать в dependencyFormulas.move
|
|
if(arrayFormula) {
|
|
if(isFirstCellArray) {
|
|
newFormula = oThis._moveCellsFormula(cell, formula, cellWithFormula, copyRange, oBBoxFrom, wsTo);
|
|
cellWithFormula = newFormula.getParent();
|
|
shiftedArrayFormula[formula.getListenerId()] = 1;
|
|
newArrayRef = arrayFormula.clone();
|
|
newArrayRef.setOffset(offset);
|
|
newFormula.setArrayFormulaRef(newArrayRef);
|
|
|
|
cellWithFormula.ws = wsTo;
|
|
cellWithFormula.nRow = cell.nRow;
|
|
cellWithFormula.nCol = cell.nCol;
|
|
}
|
|
} else {
|
|
newFormula = oThis._moveCellsFormula(cell, formula, cellWithFormula, copyRange, oBBoxFrom, wsTo);
|
|
cellWithFormula = newFormula.getParent();
|
|
cellWithFormula.ws = wsTo;
|
|
cellWithFormula.nRow = cell.nRow;
|
|
cellWithFormula.nCol = cell.nCol;
|
|
}
|
|
}
|
|
if(arrayFormula) {
|
|
if(isFirstCellArray) {
|
|
dependencyFormulas.addToBuildDependencyArray(formula);
|
|
if(newFormula) {
|
|
dependencyFormulas.addToBuildDependencyArray(newFormula);
|
|
}
|
|
}
|
|
} else {
|
|
dependencyFormulas.addToBuildDependencyCell(cell);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Worksheet.prototype._moveCellsFormula = function(cell, formula, cellWithFormula, copyRange, oBBoxFrom, wsTo) {
|
|
if (this !== wsTo) {
|
|
if (copyRange || !this.workbook.bUndoChanges) {
|
|
cellWithFormula = new CCellWithFormula(wsTo, cell.nRow, cell.nCol);
|
|
formula = formula.clone(null, cellWithFormula, wsTo);
|
|
if (!copyRange) {
|
|
formula.convertTo3DRefs(oBBoxFrom);
|
|
}
|
|
formula.moveToSheet(this, wsTo);
|
|
formula.setFormulaString(formula.assemble(true));
|
|
cell.setFormulaParsed(formula);
|
|
} else {
|
|
formula.moveToSheet(this, wsTo);
|
|
formula.setFormulaString(formula.assemble(true));
|
|
}
|
|
}
|
|
return formula;
|
|
};
|
|
Worksheet.prototype._moveRange=function(oBBoxFrom, oBBoxTo, copyRange, wsTo, isTableCreated){
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (oBBoxFrom.isEqual(oBBoxTo) && this === wsTo)
|
|
return;
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
this.workbook.dependencyFormulas.lockRecal();
|
|
|
|
var offset = new AscCommon.CellBase(oBBoxTo.r1 - oBBoxFrom.r1, oBBoxTo.c1 - oBBoxFrom.c1);
|
|
var prepared = this._moveMergedAndHyperlinksPrepare(oBBoxFrom, oBBoxTo, copyRange, wsTo, offset);
|
|
this._movePivots(oBBoxFrom, oBBoxTo, copyRange, offset, wsTo);
|
|
this._moveCleanRanges(oBBoxFrom, oBBoxTo, copyRange, wsTo);
|
|
this._moveFormulas(oBBoxFrom, oBBoxTo, copyRange, wsTo, offset, isTableCreated);
|
|
this._moveCells(oBBoxFrom, oBBoxTo, copyRange, wsTo, offset, isTableCreated);
|
|
this._moveMergedAndHyperlinks(prepared, oBBoxFrom, oBBoxTo, copyRange, wsTo, offset);
|
|
this._moveDataValidation(oBBoxFrom, oBBoxTo, copyRange, offset, wsTo);
|
|
this.moveConditionalFormatting(oBBoxFrom, oBBoxTo, copyRange, offset, wsTo);
|
|
this.moveSparklineGroup(oBBoxFrom, oBBoxTo, copyRange, offset, wsTo);
|
|
this.moveProtectedRange(oBBoxFrom, oBBoxTo, copyRange, offset, wsTo);
|
|
this._moveUserProtectedRange(oBBoxFrom, oBBoxTo, copyRange, offset, wsTo);
|
|
|
|
|
|
if(true == this.workbook.bUndoChanges || true == this.workbook.bRedoChanges) {
|
|
wsTo.autoFilters.unmergeTablesAfterMove(oBBoxTo);
|
|
}
|
|
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.autoFilters._moveAutoFilters(oBBoxTo, oBBoxFrom, null, copyRange, true, oBBoxFrom, wsTo);
|
|
}
|
|
|
|
this.workbook.dependencyFormulas.unlockRecal();
|
|
AscCommon.History.EndTransaction();
|
|
return true;
|
|
};
|
|
Worksheet.prototype._shiftCellsLeft=function(oBBox){
|
|
//todo удаление когда есть замерженые ячейки
|
|
var t = this;
|
|
var nLeft = oBBox.c1;
|
|
var nRight = oBBox.c2;
|
|
var dif = nLeft - nRight - 1;
|
|
var oActualRange = new Asc.Range(nLeft, oBBox.r1, gc_nMaxCol0, oBBox.r2);
|
|
var offset = new AscCommon.CellBase(0, dif);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oBBox);
|
|
var redrawTablesArr = this.autoFilters.insertColumn( oBBox, dif );
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oBBox, offset);
|
|
this.updateSparklineGroupOffset(oBBox, offset);
|
|
this.updateConditionalFormattingOffset(oBBox, offset);
|
|
this.updateProtectedRangeOffset(oBBox, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oBBox, offset);
|
|
this.updateUserProtectedRangesOffset(oBBox, offset);
|
|
}
|
|
|
|
this.getRange3(oBBox.r1, oBBox.c1, oBBox.r2, oBBox.c2)._foreachNoEmpty(function(cell){
|
|
t._removeCell(null, null, cell);
|
|
});
|
|
|
|
this._updateFormulasParents(oActualRange.r1, oActualRange.c1, oActualRange.r2, oActualRange.c2, oBBox, offset, renameRes.shiftedShared);
|
|
var cellsByColLength = this.getColDataLength();
|
|
for (var i = nRight + 1; i < cellsByColLength; ++i) {
|
|
var sheetMemoryFrom = this.getColDataNoEmpty(i);
|
|
if (sheetMemoryFrom) {
|
|
this.getColData(i + dif).copyRange(sheetMemoryFrom, oBBox.r1, oBBox.r1, oBBox.r2 - oBBox.r1 + 1);
|
|
sheetMemoryFrom.clear(oBBox.r1, oBBox.r2 + 1);
|
|
}
|
|
}
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ShiftCellsLeft, this.getId(), oActualRange, new UndoRedoData_BBox(oBBox));
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, null, this.getId());
|
|
}
|
|
//todo проверить не уменьшились ли границы таблицы
|
|
};
|
|
Worksheet.prototype._shiftCellsUp=function(oBBox){
|
|
var t = this;
|
|
var nTop = oBBox.r1;
|
|
var nBottom = oBBox.r2;
|
|
var dif = nTop - nBottom - 1;
|
|
var oActualRange = new Asc.Range(oBBox.c1, oBBox.r1, oBBox.c2, gc_nMaxRow0);
|
|
var offset = new AscCommon.CellBase(dif, 0);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oBBox);
|
|
var redrawTablesArr = this.autoFilters.insertRows("delCell", oBBox, c_oAscDeleteOptions.DeleteCellsAndShiftTop);
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oBBox, offset);
|
|
this.updateSparklineGroupOffset(oBBox, offset);
|
|
this.updateConditionalFormattingOffset(oBBox, offset);
|
|
this.updateProtectedRangeOffset(oBBox, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oBBox, offset);
|
|
this.updateUserProtectedRangesOffset(oBBox, offset);
|
|
}
|
|
|
|
this.getRange3(oBBox.r1, oBBox.c1, oBBox.r2, oBBox.c2)._foreachNoEmpty(function(cell){
|
|
t._removeCell(null, null, cell);
|
|
});
|
|
this._updateFormulasParents(oActualRange.r1, oActualRange.c1, oActualRange.r2, oActualRange.c2, oBBox, offset, renameRes.shiftedShared);
|
|
for (var i = oBBox.c1; i <= oBBox.c2; ++i) {
|
|
var sheetMemory = this.getColDataNoEmpty(i);
|
|
if (sheetMemory) {
|
|
sheetMemory.deleteRange(nTop, -dif);
|
|
}
|
|
}
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ShiftCellsTop, this.getId(), oActualRange, new UndoRedoData_BBox(oBBox));
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, null, this.getId());
|
|
}
|
|
//todo проверить не уменьшились ли границы таблицы
|
|
};
|
|
Worksheet.prototype._shiftCellsRight=function(oBBox, displayNameFormatTable){
|
|
var nLeft = oBBox.c1;
|
|
var nRight = oBBox.c2;
|
|
var dif = nRight - nLeft + 1;
|
|
var oActualRange = new Asc.Range(oBBox.c1, oBBox.r1, gc_nMaxCol0, oBBox.r2);
|
|
var offset = new AscCommon.CellBase(0, dif);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oBBox);
|
|
var redrawTablesArr = this.autoFilters.insertColumn( oBBox, dif, displayNameFormatTable );
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oBBox, offset);
|
|
this.updateSparklineGroupOffset(oBBox, offset);
|
|
this.updateConditionalFormattingOffset(oBBox, offset);
|
|
this.updateProtectedRangeOffset(oBBox, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oBBox, offset);
|
|
this.updateUserProtectedRangesOffset(oBBox, offset);
|
|
}
|
|
|
|
this._updateFormulasParents(oActualRange.r1, oActualRange.c1, oActualRange.r2, oActualRange.c2, oBBox, offset, renameRes.shiftedShared);
|
|
var borders;
|
|
if (nLeft > 0 && !this.workbook.bUndoChanges) {
|
|
borders = this._getBordersForInsert(oBBox, false);
|
|
}
|
|
var cellsByColLength = this.getColDataLength();
|
|
for (var i = cellsByColLength - 1; i >= nLeft; --i) {
|
|
var sheetMemoryFrom = this.getColDataNoEmpty(i);
|
|
if (sheetMemoryFrom) {
|
|
if (i + dif <= gc_nMaxCol0) {
|
|
this.getColData(i + dif).copyRange(sheetMemoryFrom, oBBox.r1, oBBox.r1, oBBox.r2 - oBBox.r1 + 1);
|
|
}
|
|
sheetMemoryFrom.clear(oBBox.r1, oBBox.r2 + 1);
|
|
}
|
|
}
|
|
this.setColsCount(Math.max(this.nColsCount, this.getColDataLength()));
|
|
//copy property from row/cell above
|
|
if (nLeft > 0 && !this.workbook.bUndoChanges)
|
|
{
|
|
var prevSheetMemory = this.getColDataNoEmpty(nLeft - 1);
|
|
if (prevSheetMemory) {
|
|
//todo hidden, keep only style
|
|
for (var i = nLeft; i <= nRight; ++i) {
|
|
this.getColData(i).copyRange(prevSheetMemory, oBBox.r1, oBBox.r1, oBBox.r2 - oBBox.r1 + 1);
|
|
}
|
|
this.setColsCount(Math.max(this.nColsCount, this.getColDataLength()));
|
|
//show rows and remain only cell xf property
|
|
this.getRange3(oBBox.r1, oBBox.c1, oBBox.r2, oBBox.c2)._foreachNoEmpty(function(cell) {
|
|
cell.clearDataKeepXf(borders[cell.nRow]);
|
|
});
|
|
}
|
|
}
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ShiftCellsRight, this.getId(), oActualRange, new UndoRedoData_BBox(oBBox));
|
|
|
|
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, null, this.getId());
|
|
}
|
|
};
|
|
Worksheet.prototype._shiftCellsBottom=function(oBBox, displayNameFormatTable){
|
|
var t = this;
|
|
var nTop = oBBox.r1;
|
|
var nBottom = oBBox.r2;
|
|
var dif = nBottom - nTop + 1;
|
|
var oActualRange = new Asc.Range(oBBox.c1, oBBox.r1, oBBox.c2, gc_nMaxRow0);
|
|
var offset = new AscCommon.CellBase(dif, 0);
|
|
//renameDependencyNodes before move cells to store current location in history
|
|
var renameRes = this.renameDependencyNodes(offset, oBBox);
|
|
var redrawTablesArr;
|
|
if (!this.workbook.bUndoChanges && undefined === displayNameFormatTable) {
|
|
redrawTablesArr = this.autoFilters.insertRows("insCell", oBBox, c_oAscInsertOptions.InsertCellsAndShiftDown,
|
|
displayNameFormatTable);
|
|
}
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
this.updatePivotOffset(oBBox, offset);
|
|
this.updateUserProtectedRangesOffset(oBBox, offset);
|
|
}
|
|
|
|
this._updateFormulasParents(oActualRange.r1, oActualRange.c1, oActualRange.r2, oActualRange.c2, oBBox, offset, renameRes.shiftedShared);
|
|
if (false == this.workbook.bUndoChanges && (false == this.workbook.bRedoChanges || this.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
this.updateSortStateOffset(oBBox, offset);
|
|
this.updateSparklineGroupOffset(oBBox, offset);
|
|
this.updateConditionalFormattingOffset(oBBox, offset);
|
|
this.updateProtectedRangeOffset(oBBox, offset);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
|
|
var borders;
|
|
if (nTop > 0 && !this.workbook.bUndoChanges) {
|
|
borders = this._getBordersForInsert(oBBox, true);
|
|
}
|
|
//rowcount
|
|
for (var i = oBBox.c1; i <= oBBox.c2; ++i) {
|
|
var sheetMemory = this.getColDataNoEmpty(i);
|
|
if (sheetMemory) {
|
|
sheetMemory.insertRange(nTop, dif);
|
|
t.cellsByColRowsCount = Math.max(t.cellsByColRowsCount, sheetMemory.getMaxIndex() + 1);
|
|
}
|
|
}
|
|
this.nRowsCount = Math.max(this.nRowsCount, this.cellsByColRowsCount);
|
|
if (nTop > 0 && !this.workbook.bUndoChanges)
|
|
{
|
|
for (var i = oBBox.c1; i <= oBBox.c2; ++i) {
|
|
var sheetMemory = this.getColDataNoEmpty(i);
|
|
if (sheetMemory) {
|
|
sheetMemory.copyRangeByChunk((nTop - 1), 1, nTop, dif);
|
|
t.cellsByColRowsCount = Math.max(t.cellsByColRowsCount, sheetMemory.getMaxIndex() + 1);
|
|
}
|
|
}
|
|
this.nRowsCount = Math.max(this.nRowsCount, this.cellsByColRowsCount);
|
|
//show rows and remain only cell xf property
|
|
this.getRange3(oBBox.r1, oBBox.c1, oBBox.r2, oBBox.c2)._foreachNoEmpty(function(cell) {
|
|
cell.clearDataKeepXf(borders[cell.nCol]);
|
|
});
|
|
}
|
|
//notifyChanged after move cells to get new locations(for intersect ranges)
|
|
this.workbook.dependencyFormulas.notifyChanged(renameRes.changed);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ShiftCellsBottom, this.getId(), oActualRange, new UndoRedoData_BBox(oBBox));
|
|
|
|
//пока перенес добавление только последней строки(в данном случае порядок занесения в истрию должен быть именно в таком порядке)
|
|
//TODO возможно стоит полностью перенести сюда обработку для ф/т и а/ф
|
|
if (!this.workbook.bUndoChanges && undefined !== displayNameFormatTable) {
|
|
redrawTablesArr = this.autoFilters.insertRows("insCell", oBBox, c_oAscInsertOptions.InsertCellsAndShiftDown,
|
|
displayNameFormatTable);
|
|
}
|
|
|
|
if(!this.workbook.bUndoChanges)
|
|
{
|
|
this.autoFilters.redrawStylesTables(redrawTablesArr);
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this, null, this.getId());
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._setIndex=function(ind){
|
|
if (this.workbook.handlers) {
|
|
this.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetChangeIndex, this.index, ind, this.getId());
|
|
}
|
|
this.index = ind;
|
|
};
|
|
Worksheet.prototype._BuildDependencies=function(cellRange){
|
|
/*
|
|
Построение графа зависимостей.
|
|
*/
|
|
var ca;
|
|
for (var i in cellRange) {
|
|
if (null === cellRange[i]) {
|
|
cellRange[i] = i;
|
|
continue;
|
|
}
|
|
|
|
ca = g_oCellAddressUtils.getCellAddress(i);
|
|
this._getCellNoEmpty(ca.getRow0(), ca.getCol0(), function(c) {
|
|
if (c) {
|
|
c._BuildDependencies(true);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
Worksheet.prototype._setHandlersTablePart = function(){
|
|
if(!this.TableParts)
|
|
return;
|
|
|
|
for(var i = 0; i < this.TableParts.length; i++)
|
|
{
|
|
this.TableParts[i].setHandlers(this.handlers);
|
|
}
|
|
};
|
|
Worksheet.prototype.getTableRangeForFormula = function(name, objectParam){
|
|
var res = null;
|
|
if(!this.TableParts || !name)
|
|
return res;
|
|
|
|
let _name = name.toLowerCase();
|
|
for(var i = 0; i < this.TableParts.length; i++)
|
|
{
|
|
if(this.TableParts[i].DisplayName.length === _name.length && this.TableParts[i].DisplayName.toLowerCase() === _name)
|
|
{
|
|
return this.TableParts[i].getTableRangeForFormula(objectParam);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getTableIndexColumnByName = function(tableName, columnName){
|
|
var res = null;
|
|
if(!this.TableParts || !tableName)
|
|
return res;
|
|
|
|
let _tableName = tableName.toLowerCase();
|
|
for(var i = 0; i < this.TableParts.length; i++)
|
|
{
|
|
if(this.TableParts[i].DisplayName.length === tableName.length && this.TableParts[i].DisplayName.toLowerCase() === _tableName)
|
|
{
|
|
/* if there is a quote before a special character (i.e. escaping was used), remove it, while the quote itself is also a special character */
|
|
columnName = parserHelp.escapeTableCharacters(columnName, false);
|
|
|
|
return this.TableParts[i].getTableIndexColumnByName(columnName);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getTableNameColumnByIndex = function(tableName, columnIndex){
|
|
var res = null;
|
|
if(!this.TableParts || !tableName)
|
|
return res;
|
|
|
|
let _tableName = tableName.toLowerCase();
|
|
for(var i = 0; i < this.TableParts.length; i++)
|
|
{
|
|
if(this.TableParts[i].DisplayName.length === _tableName.length && this.TableParts[i].DisplayName.toLowerCase() === _tableName)
|
|
{
|
|
res = this.TableParts[i].getTableNameColumnByIndex(columnIndex);
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getTableByName = function(tableName){
|
|
var res = null;
|
|
if(!this.TableParts || !tableName)
|
|
return res;
|
|
|
|
let _tableName = tableName.toLowerCase();
|
|
for(var i = 0; i < this.TableParts.length; i++)
|
|
{
|
|
if(this.TableParts[i].DisplayName.length === _tableName.length && this.TableParts[i].DisplayName.toLowerCase() === _tableName)
|
|
{
|
|
res = this.TableParts[i];
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getTableRangeColumnByName = function(tableName, columnName){
|
|
var res = null;
|
|
if(!this.TableParts || !tableName)
|
|
return res;
|
|
|
|
let _tableName = tableName.toLowerCase();
|
|
for(var i = 0; i < this.TableParts.length; i++)
|
|
{
|
|
if(this.TableParts[i].DisplayName.length === _tableName.length && this.TableParts[i].DisplayName.toLowerCase() === _tableName)
|
|
{
|
|
res = this.TableParts[i].getTableRangeColumnByName(columnName);
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.isTableTotal = function (col, row) {
|
|
if (this.TableParts && this.TableParts.length > 0) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
if (this.TableParts[i].isTotalsRow()) {
|
|
var ref = this.TableParts[i].Ref;
|
|
if (ref.r2 === row && col >= ref.c1 && col <= ref.c2) {
|
|
return {index: i, colIndex: col - ref.c1};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Worksheet.prototype.isApplyFilterBySheet = function () {
|
|
var res = false;
|
|
|
|
if (this.AutoFilter && this.AutoFilter.isApplyAutoFilter()) {
|
|
res = true;
|
|
}
|
|
|
|
if (false === res && this.TableParts) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
if (true === this.TableParts[i].isApplyAutoFilter()) {
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getTableNames = function() {
|
|
var res = [];
|
|
if (this.TableParts) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
res.push(this.TableParts[i].DisplayName);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.renameDependencyNodes = function(offset, oBBox){
|
|
return this.workbook.dependencyFormulas.shift(this.Id, oBBox, offset);
|
|
};
|
|
Worksheet.prototype.getAllCol = function(){
|
|
if(null == this.oAllCol)
|
|
this.oAllCol = new AscCommonExcel.Col(this, g_nAllColIndex);
|
|
return this.oAllCol;
|
|
};
|
|
Worksheet.prototype.getAllRow = function(){
|
|
if (null == this.oSheetFormatPr.oAllRow) {
|
|
this.oSheetFormatPr.oAllRow = new AscCommonExcel.Row(this);
|
|
this.oSheetFormatPr.oAllRow.setIndex(g_nAllRowIndex);
|
|
}
|
|
return this.oSheetFormatPr.oAllRow;
|
|
};
|
|
Worksheet.prototype.getAllRowNoEmpty = function(){
|
|
return this.oSheetFormatPr.oAllRow;
|
|
};
|
|
Worksheet.prototype.getHyperlinkByCell = function(row, col){
|
|
var oHyperlink = this.hyperlinkManager.getByCell(row, col);
|
|
return oHyperlink ? oHyperlink.data : null;
|
|
};
|
|
Worksheet.prototype.getMergedByCell = function(row, col){
|
|
var oMergeInfo = this.mergeManager.getByCell(row, col);
|
|
return oMergeInfo ? oMergeInfo.bbox : null;
|
|
};
|
|
Worksheet.prototype.getMergedByRange = function(bbox){
|
|
return this.mergeManager.get(bbox);
|
|
};
|
|
Worksheet.prototype._expandRangeByMergedAddToOuter = function(aOuter, range, aMerged){
|
|
for(var i = 0, length = aMerged.all.length; i < length; i++)
|
|
{
|
|
var elem = aMerged.all[i];
|
|
if(!range.containsRange(elem.bbox))
|
|
aOuter.push(elem);
|
|
}
|
|
};
|
|
Worksheet.prototype._expandRangeByMergedGetOuter = function(range){
|
|
var aOuter = [];
|
|
//смотрим только границы
|
|
this._expandRangeByMergedAddToOuter(aOuter, range, this.mergeManager.get(new Asc.Range(range.c1, range.r1, range.c1, range.r2)));
|
|
if(range.c1 != range.c2)
|
|
{
|
|
this._expandRangeByMergedAddToOuter(aOuter, range, this.mergeManager.get(new Asc.Range(range.c2, range.r1, range.c2, range.r2)));
|
|
if(range.c2 - range.c1 > 1)
|
|
{
|
|
this._expandRangeByMergedAddToOuter(aOuter, range, this.mergeManager.get(new Asc.Range(range.c1 + 1, range.r1, range.c2 - 1, range.r1)));
|
|
if(range.r1 != range.r2)
|
|
this._expandRangeByMergedAddToOuter(aOuter, range, this.mergeManager.get(new Asc.Range(range.c1 + 1, range.r2, range.c2 - 1, range.r2)));
|
|
}
|
|
}
|
|
return aOuter;
|
|
};
|
|
Worksheet.prototype.expandRangeByMerged = function(range){
|
|
if(null != range)
|
|
{
|
|
var aOuter = this._expandRangeByMergedGetOuter(range);
|
|
if(aOuter.length > 0)
|
|
{
|
|
range = range.clone();
|
|
while(aOuter.length > 0)
|
|
{
|
|
for(var i = 0, length = aOuter.length; i < length; i++)
|
|
range.union2(aOuter[i].bbox);
|
|
aOuter = this._expandRangeByMergedGetOuter(range);
|
|
}
|
|
}
|
|
}
|
|
return range;
|
|
};
|
|
Worksheet.prototype.createTablePart = function(){
|
|
|
|
return new AscCommonExcel.TablePart(this.handlers);
|
|
};
|
|
Worksheet.prototype.onUpdateRanges = function(ranges) {
|
|
this.workbook.updateSparklineCache(this.sName, ranges);
|
|
// ToDo do not update conditional formatting on hidden sheet
|
|
if (ranges && ranges.length) {
|
|
this.setDirtyConditionalFormatting(new AscCommonExcel.MultiplyRange(ranges));
|
|
}
|
|
//this.workbook.handlers.trigger("toggleAutoCorrectOptions", null,true);
|
|
};
|
|
Worksheet.prototype.updateSparklineCache = function (sheet, ranges) {
|
|
for (var i = 0; i < this.aSparklineGroups.length; ++i) {
|
|
this.aSparklineGroups[i].updateCache(sheet, ranges);
|
|
}
|
|
};
|
|
Worksheet.prototype.getSparklineGroup = function (c, r) {
|
|
for (var i = 0; i < this.aSparklineGroups.length; ++i) {
|
|
if (-1 !== this.aSparklineGroups[i].contains(c, r)) {
|
|
return this.aSparklineGroups[i];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Worksheet.prototype.removeSparklines = function (range) {
|
|
for (var i = this.aSparklineGroups.length - 1; i > -1; --i) {
|
|
if (this.aSparklineGroups[i].remove(range)) {
|
|
AscCommon.History.Add(new AscDFH.CChangesDrawingsSparklinesRemove(this.aSparklineGroups[i]));
|
|
this.aSparklineGroups.splice(i, 1);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.removeSparklineGroups = function (range) {
|
|
for (var i = this.aSparklineGroups.length - 1; i > -1; --i) {
|
|
if (-1 !== this.aSparklineGroups[i].intersectionSimple(range)) {
|
|
AscCommon.History.Add(new AscDFH.CChangesDrawingsSparklinesRemove(this.aSparklineGroups[i]));
|
|
this.aSparklineGroups.splice(i, 1);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.addSparklineGroups = function (sparklineGroups) {
|
|
if (sparklineGroups) {
|
|
AscCommon.History.Add(new AscDFH.CChangesDrawingsSparklinesRemove(sparklineGroups, true));
|
|
this.insertSparklineGroup(sparklineGroups);
|
|
}
|
|
};
|
|
Worksheet.prototype.insertSparklineGroup = function (sparklineGroup) {
|
|
this.aSparklineGroups.push(sparklineGroup);
|
|
};
|
|
Worksheet.prototype.removeSparklineGroup = function (id) {
|
|
for (var i = 0; i < this.aSparklineGroups.length; ++i) {
|
|
if (id === this.aSparklineGroups[i].Get_Id()) {
|
|
this.aSparklineGroups.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.updateSparklineGroupOffset = function (range, offset) {
|
|
if ((offset.row < 0 || offset.col < 0)) {
|
|
this.removeSparklines(range);
|
|
}
|
|
this.setSparklinesOffset(range, offset);
|
|
};
|
|
Worksheet.prototype.setSparklinesOffset = function (range, offset) {
|
|
this.aSparklineGroups.forEach(function (val) {
|
|
if (val) {
|
|
var aSparklines = [];
|
|
var isChange = false;
|
|
for (var i = 0; i < val.arrSparklines.length; i++) {
|
|
var _elem = val.arrSparklines[i];
|
|
|
|
var cloneElem = _elem.clone();
|
|
var _isChange = false;
|
|
if (range.isIntersectForShift(cloneElem.sqRef, offset)) {
|
|
_isChange = cloneElem.sqRef.forShift(range, offset);
|
|
}
|
|
if (_isChange) {
|
|
isChange = true;
|
|
}
|
|
|
|
//необходимо ещё сдвинуть _f
|
|
if ((offset.row < 0 || offset.col < 0) && _elem && _elem._f && range.containsRange(_elem._f)) {
|
|
_elem.f = null;
|
|
_elem._f = null;
|
|
} else {
|
|
_isChange = false;
|
|
if (cloneElem._f) {
|
|
if (range.isIntersectForShift(cloneElem._f, offset)) {
|
|
_isChange = cloneElem._f.forShift(range, offset);
|
|
}
|
|
if (_isChange) {
|
|
isChange = true;
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
cloneElem.f = cloneElem._f.getName();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
aSparklines.push(cloneElem);
|
|
}
|
|
if (isChange) {
|
|
val.setSparklines(aSparklines, true, true);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Worksheet.prototype.moveSparklineGroup = function (oBBoxFrom, oBBoxTo, copyRange, offset, wsTo, wsFrom) {
|
|
var t = this;
|
|
var isMove = !wsFrom;
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (false === this.workbook.bUndoChanges && false === this.workbook.bRedoChanges && !copyRange) {
|
|
if (!wsFrom) {
|
|
wsFrom = this;
|
|
}
|
|
|
|
//TODO проверить, необходимо ли чистить?
|
|
//чистим ту область, куда переносим
|
|
//wsTo.removeSparklineGroup
|
|
|
|
wsFrom.aSparklineGroups.forEach(function (val) {
|
|
if (val) {
|
|
var aSparklines = [];
|
|
var aSparkLinesToSheet = [];
|
|
var isChange = false;
|
|
for (var i = 0; i < val.arrSparklines.length; i++) {
|
|
var _elem = val.arrSparklines[i];
|
|
|
|
var cloneElem = _elem.clone();
|
|
var _isChange = false;
|
|
var moveOnNewSheet = false;
|
|
|
|
if (wsTo === wsFrom) {
|
|
if (oBBoxFrom.containsRange(cloneElem.sqRef)) {
|
|
cloneElem.sqRef.setOffset(offset);
|
|
_isChange = true;
|
|
}
|
|
if (_isChange) {
|
|
isChange = true;
|
|
}
|
|
} else {
|
|
if (oBBoxFrom.containsRange(cloneElem.sqRef)) {
|
|
//тут необходимо добавить новый спакрлайн на новом листе
|
|
moveOnNewSheet = true;
|
|
cloneElem.sqRef.setOffset(offset);
|
|
aSparkLinesToSheet.push(cloneElem);
|
|
isChange = true;
|
|
}
|
|
}
|
|
|
|
//необходимо ещё сдвинуть _f
|
|
if (_elem && _elem._f && cloneElem._f) {
|
|
if (wsTo === wsFrom) {
|
|
if (cloneElem._f.intersection(oBBoxFrom)) {
|
|
var _isChangeF = false;
|
|
var isContainsFormula = oBBoxFrom.containsRange(cloneElem._f);
|
|
if (isContainsFormula) {
|
|
cloneElem._f.setOffset(offset);
|
|
_isChangeF = true;
|
|
} else {
|
|
|
|
//при перемещении есть такой нюанс - если перемещаем последнюю ячейку формулы вниз(вверх аналогично для первой строки) + не затрагиваем весь диапазон формулы
|
|
//то формулу растягиваем до перемещаемой ячейки
|
|
|
|
var bColF = cloneElem._f.c1 === cloneElem._f.c2;
|
|
if (bColF) {
|
|
if (oBBoxFrom.contains(cloneElem._f.c1, cloneElem._f.r2) && !offset.col) {
|
|
cloneElem._f.setOffsetLast(offset);
|
|
_isChangeF = true;
|
|
} else if (oBBoxFrom.contains(cloneElem._f.c1, cloneElem._f.r1)&& !offset.col) {
|
|
cloneElem._f.setOffsetFirst(offset);
|
|
_isChangeF = true;
|
|
}
|
|
} else {
|
|
if (oBBoxFrom.contains(cloneElem._f.c2, cloneElem._f.r1) && !offset.row) {
|
|
cloneElem._f.setOffsetLast(offset);
|
|
_isChangeF = true;
|
|
} else if (oBBoxFrom.contains(cloneElem._f.c1, cloneElem._f.r1)&& !offset.row) {
|
|
cloneElem._f.setOffsetFirst(offset);
|
|
_isChangeF = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_isChangeF) {
|
|
if (wsTo.sName !== cloneElem._f.sheet) {
|
|
cloneElem._f.setSheet(wsTo.sName);
|
|
}
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
cloneElem.f = cloneElem._f.getName();
|
|
});
|
|
isChange = true;
|
|
}
|
|
}
|
|
} else {
|
|
if (isMove) {
|
|
//если реальный перенос внутри книги, а не копирование/вставка
|
|
if (oBBoxFrom.containsRange(cloneElem._f)) {
|
|
cloneElem._f.setOffset(offset);
|
|
if (wsTo.sName !== cloneElem._f.sheet) {
|
|
cloneElem._f.setSheet(wsTo.sName);
|
|
}
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
cloneElem.f = cloneElem._f.getName();
|
|
});
|
|
isChange = true;
|
|
}
|
|
} else {
|
|
cloneElem._f.setOffset(offset);
|
|
if (wsTo.sName !== cloneElem._f.sheet) {
|
|
cloneElem._f.setSheet(wsTo.sName);
|
|
}
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
cloneElem.f = cloneElem._f.getName();
|
|
});
|
|
isChange = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!moveOnNewSheet) {
|
|
aSparklines.push(cloneElem);
|
|
}
|
|
}
|
|
if (isChange) {
|
|
if (wsTo !== wsFrom && !copyRange) {
|
|
wsFrom.removeSparklines(oBBoxFrom);
|
|
}
|
|
|
|
//если, допустим, перенесли все спарклайны на другой лист, то необходимо удалить группы здесь и добавить новую группы
|
|
if (aSparklines.length !== 0) {
|
|
val.setSparklines(aSparklines, true, true);
|
|
}
|
|
if (aSparkLinesToSheet.length !== 0) {
|
|
var modelSparkline = new AscCommonExcel.sparklineGroup(true);
|
|
modelSparkline.worksheet = wsTo;
|
|
modelSparkline.set(val);
|
|
modelSparkline.setSparklines(aSparkLinesToSheet, true);
|
|
wsTo.addSparklineGroups(modelSparkline);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
Worksheet.prototype.getSparkLinesMaxColRow = function() {
|
|
var sparkLinesGroup = this.aSparklineGroups;
|
|
var r = -1, c = -1;
|
|
|
|
if (sparkLinesGroup) {
|
|
sparkLinesGroup.forEach(function (item) {
|
|
if (item.arrSparklines) {
|
|
for (var j = 0; j < item.arrSparklines.length; ++j) {
|
|
var range = item.arrSparklines[j].sqRef;
|
|
if (range) {
|
|
r = Math.max(r, range.r2);
|
|
c = Math.max(c, range.c2);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
return new AscCommon.CellBase(r, c);
|
|
};
|
|
Worksheet.prototype.getCwf = function() {
|
|
var cwf = {};
|
|
var range = this.getRange3(0,0, gc_nMaxRow0, gc_nMaxCol0);
|
|
range._setPropertyNoEmpty(null, null, function(cell){
|
|
if(cell.isFormula()){
|
|
var name = cell.getName();
|
|
cwf[name] = name;
|
|
}
|
|
});
|
|
return cwf;
|
|
};
|
|
Worksheet.prototype.getAllFormulas = function(formulas, needReturnCellProps) {
|
|
var range = this.getRange3(0, 0, gc_nMaxRow0, gc_nMaxCol0);
|
|
range._setPropertyNoEmpty(null, null, function(cell) {
|
|
if (cell.isFormula()) {
|
|
if (!cell.formulaParsed.ref || (cell.formulaParsed.ref && cell.formulaParsed.checkFirstCellArray(cell))) {
|
|
formulas.push(needReturnCellProps ? {f: cell.getFormulaParsed(), c: cell.nCol, r: cell.nRow} : cell.getFormulaParsed());
|
|
}
|
|
}
|
|
});
|
|
for (var i = 0; i < this.TableParts.length; ++i) {
|
|
var table = this.TableParts[i];
|
|
table.getAllFormulas(formulas);
|
|
}
|
|
};
|
|
Worksheet.prototype.forEachFormula = function(callback) {
|
|
var range = this.getRange3(0, 0, gc_nMaxRow0, gc_nMaxCol0);
|
|
range._setPropertyNoEmpty(null, null, function(cell) {
|
|
if (cell.isFormula()) {
|
|
callback(cell.getFormulaParsed());
|
|
}
|
|
});
|
|
for (var i = 0; i < this.TableParts.length; ++i) {
|
|
var table = this.TableParts[i];
|
|
table.forEachFormula(callback);
|
|
}
|
|
};
|
|
Worksheet.prototype.setTableStyleAfterOpen = function () {
|
|
if (this.TableParts && this.TableParts.length) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
var table = this.TableParts[i];
|
|
this.autoFilters._setColorStyleTable(table.Ref, table);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.setTableFormulaAfterOpen = function () {
|
|
if (this.TableParts && this.TableParts.length) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
var table = this.TableParts[i];
|
|
//TODO пока заменяем при открытии на TotalsRowFormula
|
|
table.checkTotalRowFormula(this);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.isTableTotalRow = function (range) {
|
|
var res = false;
|
|
if (this.TableParts && this.TableParts.length) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
var table = this.TableParts[i];
|
|
var totalRowRange = table.getTotalsRowRange();
|
|
if(totalRowRange && totalRowRange.containsRange(range)) {
|
|
res = true;
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.addTablePart = function (tablePart, bAddToDependencies) {
|
|
this.TableParts.push(tablePart);
|
|
if (bAddToDependencies) {
|
|
this.workbook.dependencyFormulas.addTableName(this, tablePart);
|
|
tablePart.buildDependencies();
|
|
}
|
|
};
|
|
Worksheet.prototype.changeTablePart = function (index, tablePart, bChangeName) {
|
|
var oldTablePart = this.TableParts[index];
|
|
if (oldTablePart) {
|
|
oldTablePart.removeDependencies();
|
|
}
|
|
this.TableParts[index] = tablePart;
|
|
tablePart.buildDependencies();
|
|
if (bChangeName && oldTablePart) {
|
|
this.workbook.dependencyFormulas.changeTableName(oldTablePart.DisplayName, tablePart.DisplayName);
|
|
}
|
|
};
|
|
Worksheet.prototype.deleteTablePart = function (index, bConvertTableFormulaToRef) {
|
|
var tablePart = this.TableParts[index];
|
|
this.workbook.dependencyFormulas.delTableName(tablePart.DisplayName, bConvertTableFormulaToRef);
|
|
tablePart.removeDependencies();
|
|
|
|
//delete table
|
|
this.TableParts.splice(index, 1);
|
|
};
|
|
Worksheet.prototype.checkPivotReportLocationForError = function(ranges, exceptPivot) {
|
|
for (var i = 0; i < ranges.length; ++i) {
|
|
var range = ranges[i];
|
|
if (this.autoFilters.isIntersectionTable(range)) {
|
|
return c_oAscError.ID.PivotOverlap;
|
|
}
|
|
if (this.inPivotTable(range, exceptPivot)) {
|
|
return c_oAscError.ID.PivotOverlap;
|
|
}
|
|
var merged = this.mergeManager.get(range);
|
|
if (merged.outer.length > 0) {
|
|
return c_oAscError.ID.PastInMergeAreaError;
|
|
}
|
|
}
|
|
return c_oAscError.ID.No;
|
|
};
|
|
Worksheet.prototype.checkPivotReportLocationForConfirm = function(ranges, changed) {
|
|
var t = this;
|
|
if (changed && changed.oldRanges && changed.data) {
|
|
changed.oldRanges.forEach(function(range) {
|
|
t.getRange3(range.r1, range.c1, range.r2, range.c2).cleanAll();
|
|
});
|
|
}
|
|
for (var i = 0; i < ranges.length; ++i) {
|
|
var range = ranges[i];
|
|
var merged = this.mergeManager.get(range);
|
|
if (merged.inner.length > 0) {
|
|
return c_oAscError.ID.PivotOverlap;
|
|
}
|
|
var warning = c_oAscError.ID.No;
|
|
this.getRange3(range.r1, range.c1, range.r2, range.c2)._foreachNoEmptyByCol(function(cell) {
|
|
if (!cell.isNullTextString()) {
|
|
warning = c_oAscError.ID.PivotOverlap;
|
|
}
|
|
});
|
|
if (c_oAscError.ID.No !== warning) {
|
|
return warning;
|
|
}
|
|
}
|
|
return c_oAscError.ID.No;
|
|
};
|
|
Worksheet.prototype.getSlicerCachesByPivotTable = function(sheetId, pivotName) {
|
|
var res = [];
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i].getSlicerCache();
|
|
if (cache && cache.indexOfPivotTable(sheetId, pivotName) >= 0) {
|
|
res.push(cache);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getSlicerCachesByPivotCacheId = function(pivotCacheId) {
|
|
var res = [];
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i].getSlicerCache();
|
|
if (cache && pivotCacheId === cache.getPivotCacheId()) {
|
|
res.push(cache);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getSlicersByPivotTable = function(sheetId, pivotName) {
|
|
var res = [];
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i].getSlicerCache();
|
|
if (cache && cache.indexOfPivotTable(sheetId, pivotName) >= 0) {
|
|
res.push(this.aSlicers[i]);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.updatePivotTable = function(pivotTable, changed, dataRow, canModifyDocument) {
|
|
if (!changed.data && !changed.style) {
|
|
return;
|
|
}
|
|
var t = this;
|
|
var multiplyRange = new AscCommonExcel.MultiplyRange([]);
|
|
if (changed.oldRanges) {
|
|
multiplyRange.union2(new AscCommonExcel.MultiplyRange(changed.oldRanges));
|
|
}
|
|
pivotTable.init();
|
|
if (changed.data && dataRow) {
|
|
var newRanges = pivotTable.getReportRanges();
|
|
newRanges.forEach(function(range) {
|
|
t.getRange3(range.r1, range.c1, range.r2, range.c2).cleanAll();
|
|
});
|
|
this._updatePivotTableCells(pivotTable, dataRow);
|
|
}
|
|
var res = pivotTable.getReportRanges();
|
|
multiplyRange.union2(new AscCommonExcel.MultiplyRange(res));
|
|
this.updatePivotTablesStyle(multiplyRange.getUnionRange(), canModifyDocument);
|
|
return res;
|
|
};
|
|
Worksheet.prototype.clearPivotTableCell = function (pivotTable) {
|
|
var ranges = pivotTable.getReportRanges();
|
|
ranges.forEach(function(range) {
|
|
pivotTable.GetWS().getRange3(range.r1, range.c1, range.r2, range.c2).cleanAll();
|
|
});
|
|
};
|
|
Worksheet.prototype.clearPivotTableStyle = function (pivotTable) {
|
|
var ranges = pivotTable.getReportRanges();
|
|
ranges.forEach(function(range){
|
|
pivotTable.GetWS().getRange3(range.r1, range.c1, range.r2, range.c2).clearTableStyle();
|
|
});
|
|
};
|
|
Worksheet.prototype._updatePivotTableSetCellValue = function (cell, text) {
|
|
var oCellValue = new AscCommonExcel.CCellValue();
|
|
oCellValue.type = AscCommon.CellValueType.String;
|
|
oCellValue.text = text.toString();
|
|
cell.setValueData(new AscCommonExcel.UndoRedoData_CellValueData(null, oCellValue));
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
*/
|
|
Worksheet.prototype._updatePivotTableCellsPage = function (pivotTable) {
|
|
//CT_pivotTableDefinition.prototype.getLayoutByCellPage
|
|
if (pivotTable.pageFieldsPositions) {
|
|
const fieldValuesCache = [];
|
|
for (let i = 0; i < pivotTable.pageFieldsPositions.length; ++i) {
|
|
const pos = pivotTable.pageFieldsPositions[i];
|
|
let cells = this.getRange4(pos.row, pos.col);
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.getPageFieldName(i));
|
|
const pageField = pivotTable.asc_getPageFields()[i];
|
|
const index = pageField.asc_getIndex();
|
|
cells.setStyle(pivotTable.getFormatting({
|
|
axis: Asc.c_oAscAxis.AxisPage,
|
|
type: Asc.c_oAscPivotAreaType.Button,
|
|
isData: false,
|
|
field: index
|
|
}));
|
|
cells = this.getRange4(pos.row, pos.col + 1);
|
|
const num = pivotTable.getPivotFieldNum(pos.pageField.fld);
|
|
if (num) {
|
|
cells.setNum(num);
|
|
}
|
|
const oCellValue = pivotTable.getPageFieldCellValue(i);
|
|
if (oCellValue.type !== AscCommon.CellValueType.String) {
|
|
cells.setAlignHorizontal(AscCommon.align_Left);
|
|
}
|
|
const fieldValues = {
|
|
fieldIndex: index,
|
|
value: pageField.item,
|
|
type: Asc.c_oAscItemType.Data
|
|
};
|
|
let valuesInfo;
|
|
if (pageField.item !== null) {
|
|
fieldValuesCache.push(fieldValues);
|
|
valuesInfo = fieldValuesCache;
|
|
} else {
|
|
valuesInfo = fieldValuesCache.concat([fieldValues]);
|
|
}
|
|
cells.setStyle(pivotTable.getFormatting({
|
|
axis: Asc.c_oAscAxis.AxisPage,
|
|
type: Asc.c_oAscPivotAreaType.Normal,
|
|
isData: false,
|
|
field: index,
|
|
valuesInfo: valuesInfo
|
|
}));
|
|
cells.setValueData(new AscCommonExcel.UndoRedoData_CellValueData(null, oCellValue));
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
*/
|
|
Worksheet.prototype._updatePivotTableCellsHeader = function (pivotTable) {
|
|
//CT_pivotTableDefinition.prototype.getLayoutByCellHeader
|
|
var location = pivotTable.location;
|
|
if (0 === location.firstHeaderRow) {
|
|
return;
|
|
}
|
|
var cells;
|
|
var pivotRange = pivotTable.getRange();
|
|
var rowFields = pivotTable.asc_getRowFields();
|
|
var colFields = pivotTable.asc_getColumnFields();
|
|
var dataFields = pivotTable.asc_getDataFields();
|
|
var cacheFields = pivotTable.asc_getCacheFields();
|
|
var pivotFields = pivotTable.asc_getPivotFields();
|
|
if (dataFields && 1 === dataFields.length) {
|
|
if (pivotTable.gridDropZones) {
|
|
cells = this.getRange4(pivotRange.r1, pivotRange.c1);
|
|
} else {
|
|
if (rowFields && !colFields) {
|
|
cells = this.getRange4(pivotRange.r1, pivotRange.c1 + location.firstDataCol);
|
|
} else if (!rowFields && colFields) {
|
|
cells = this.getRange4(pivotRange.r1 + location.firstDataRow, pivotRange.c1);
|
|
} else {
|
|
cells = this.getRange4(pivotRange.r1, pivotRange.c1);
|
|
}
|
|
}
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.getDataFieldName(0));
|
|
const formatting = pivotTable.getFormatting({
|
|
type: Asc.c_oAscPivotAreaType.Normal,
|
|
axis: Asc.c_oAscAxis.AxisValues,
|
|
isData: false,
|
|
field: null
|
|
});
|
|
cells.setStyle(formatting);
|
|
}
|
|
if (pivotTable.showHeaders && colFields) {
|
|
cells = this.getRange4(pivotRange.r1, pivotRange.c1 + location.firstDataCol);
|
|
if (pivotTable.compact) {
|
|
let caption;
|
|
if (1 === colFields.length && AscCommonExcel.st_VALUES === colFields[0].asc_getIndex()) {
|
|
caption = pivotTable.dataCaption || AscCommon.translateManager.getValue(AscCommonExcel.DATA_CAPTION)
|
|
} else {
|
|
caption = pivotTable.colHeaderCaption || AscCommon.translateManager.getValue(AscCommonExcel.COL_HEADER_CAPTION);
|
|
}
|
|
this._updatePivotTableSetCellValue(cells, caption);
|
|
} else {
|
|
var offset = new AscCommon.CellBase(0, 1);
|
|
for (var i = 0; i < colFields.length; ++i) {
|
|
var index = colFields[i].asc_getIndex();
|
|
if (AscCommonExcel.st_VALUES !== index) {
|
|
this._updatePivotTableSetCellValue(cells, pivotFields[index].asc_getName() || cacheFields[index].asc_getName());
|
|
} else {
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.dataCaption || AscCommon.translateManager.getValue(AscCommonExcel.DATA_CAPTION));
|
|
}
|
|
cells.setOffset(offset);
|
|
}
|
|
}
|
|
// update all col buttons area formats
|
|
for(let i = 0; i < colFields.length; i += 1) {
|
|
const cells = this.getRange4(pivotRange.r1, pivotRange.c1 + location.firstDataCol + i);
|
|
const index = colFields[i].asc_getIndex();
|
|
const formatting = pivotTable.getFormatting({
|
|
type: Asc.c_oAscPivotAreaType.Button,
|
|
axis: Asc.c_oAscAxis.AxisCol,
|
|
isData: false,
|
|
field: index
|
|
});
|
|
cells.setStyle(formatting);
|
|
}
|
|
// update topRight pivot area formats
|
|
const pivotTableLenC = pivotRange.c2 - pivotRange.c1;
|
|
const lenC = pivotTableLenC - location.firstDataCol - colFields.length + 1;
|
|
this.updatePivotTableCellsLablesOriginOffsets(pivotTable, {
|
|
isData: false,
|
|
type: Asc.c_oAscPivotAreaType.TopRight,
|
|
field: null
|
|
}, pivotRange.r1, pivotRange.c1 + location.firstDataCol + colFields.length, 1, lenC);
|
|
}
|
|
// update origin pivot area formats
|
|
this.updatePivotTableCellsLablesOriginOffsets(pivotTable, {
|
|
isData: false,
|
|
type: Asc.c_oAscPivotAreaType.Origin,
|
|
field: null
|
|
}, pivotRange.r1, pivotRange.c1, location.firstDataRow - 1, location.firstDataCol);
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {PivotFormatsManagerQuery} query
|
|
* @param {number} startR
|
|
* @param {number} startC
|
|
* @param {number} endR
|
|
* @param {number} endC
|
|
*/
|
|
Worksheet.prototype.updatePivotTableCellsLablesOriginOffsets = function(pivotTable, query, startR, startC, lenR, lenC) {
|
|
for (let i = 0; i < lenR; i += 1) {
|
|
for (let j = 0; j < lenC; j += 1) {
|
|
const offset = new Asc.Range(j, i, j, i);
|
|
const cell = this.getRange4(startR + i, startC + j);
|
|
query.offset = offset;
|
|
const formatting = pivotTable.getFormatting(query);
|
|
cell.setStyle(formatting);
|
|
}
|
|
}
|
|
query.offset = null;
|
|
return;
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {number[]} rowFieldsOffset
|
|
* @param {boolean} isRowItem
|
|
* @param {number} itemIndex
|
|
* @param {PivotFormatsManagerQuery} query
|
|
*/
|
|
Worksheet.prototype.updatePivotTableCellsRowColLablesSubtotalsOffsets = function(pivotTable, rowFieldsOffset, isRowItem, itemIndex, itemXIndex, query) {
|
|
const pivotRange = pivotTable.getRange();
|
|
const location = pivotTable.location;
|
|
const items = isRowItem ? pivotTable.getRowItems() : pivotTable.getColItems();
|
|
if (!items) {
|
|
return;
|
|
}
|
|
const itemR = items[itemIndex].getR();
|
|
const r1 = isRowItem ? pivotRange.r1 + location.firstDataRow : pivotRange.r1 + location.firstHeaderRow;
|
|
const c1 = isRowItem ? pivotRange.c1 : pivotRange.c1 + location.firstDataCol;
|
|
const startRow = isRowItem ? r1 + itemIndex : r1 + itemR;
|
|
const startCol = isRowItem ? c1 + rowFieldsOffset[itemXIndex] : c1 + itemIndex;
|
|
// using for colItems Labels
|
|
const endRow = r1 + location.firstDataRow - 1;
|
|
// using for rowItems Labels
|
|
const endCol = c1 + location.firstDataCol;
|
|
const startIndex = isRowItem ? startCol : startRow;
|
|
const endIndex = isRowItem ? endCol : endRow;
|
|
for (let i = startIndex; i < endIndex; i += 1) {
|
|
const r = isRowItem ? startRow : i;
|
|
const c = isRowItem ? i : startCol;
|
|
const offsetR = isRowItem ? Asc.st_PIVOT_AREA_OFFSET_END : (i === endIndex - 1 ? Asc.st_PIVOT_AREA_OFFSET_END : i - startIndex);
|
|
const offsetC = isRowItem ? (i === endIndex - 1 ? Asc.st_PIVOT_AREA_OFFSET_END : i - startIndex) : Asc.st_PIVOT_AREA_OFFSET_END;
|
|
|
|
const offset = new Asc.Range(offsetC, offsetR, offsetC, offsetR);
|
|
const cell = this.getRange4(r, c);
|
|
|
|
query.offset = offset;
|
|
const formatting = pivotTable.getFormatting(query);
|
|
cell.setStyle(formatting);
|
|
}
|
|
query.offset = null;
|
|
return;
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {number[]} rowFieldsOffset
|
|
* @param {boolean} isRowItem
|
|
* @param {number} itemIndex
|
|
* @param {PivotFormatsManagerQuery} query
|
|
*/
|
|
Worksheet.prototype.updatePivotTableCellsRowColLablesDataOffsets = function(pivotTable, rowFieldsOffset, isRowItem, itemIndex, itemXIndex, query) {
|
|
const pivotRange = pivotTable.getRange();
|
|
const location = pivotTable.location;
|
|
const items = isRowItem ? pivotTable.getRowItems() : pivotTable.getColItems();
|
|
if (!items) {
|
|
return;
|
|
}
|
|
const itemR = items[itemIndex].getR();
|
|
const itemSummaryR = itemR + itemXIndex;
|
|
|
|
const r1 = isRowItem ? pivotRange.r1 + location.firstDataRow : pivotRange.r1 + location.firstHeaderRow;
|
|
const c1 = isRowItem ? pivotRange.c1 : pivotRange.c1 + location.firstDataCol;
|
|
const startRow = isRowItem ? r1 + itemIndex: r1 + itemSummaryR;
|
|
const startCol = isRowItem ? c1 + rowFieldsOffset[itemSummaryR] : c1 + itemIndex;
|
|
for (let i = itemIndex; i < items.length; i += 1) {
|
|
const item = items[i];
|
|
const nextItem = items[i + 1];
|
|
const r = isRowItem ? r1 + i : startRow;
|
|
const c = isRowItem ? startCol : c1 + i;
|
|
if (isRowItem && c1 + rowFieldsOffset[item.getR()] <= startCol && i !== itemIndex) {
|
|
break;
|
|
}
|
|
if (!isRowItem && r1 + item.getR() <= startRow && i !== itemIndex) {
|
|
break;
|
|
}
|
|
const offsetR = isRowItem ? ((!nextItem || (c1 + rowFieldsOffset[nextItem.getR()] <= startCol)) ? Asc.st_PIVOT_AREA_OFFSET_END : r - startRow) : Asc.st_PIVOT_AREA_OFFSET_END;
|
|
const offsetC = isRowItem ? Asc.st_PIVOT_AREA_OFFSET_END : ((!nextItem || (r1 + nextItem.getR() <= startRow)) ? Asc.st_PIVOT_AREA_OFFSET_END : c - startCol);
|
|
|
|
const offset = new Asc.Range(offsetC, offsetR, offsetC, offsetR);
|
|
const cell = this.getRange4(r, c);
|
|
|
|
query.offset = offset;
|
|
const formatting = pivotTable.getFormatting(query);
|
|
cell.setStyle(formatting);
|
|
}
|
|
query.offset = null;
|
|
return;
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {number[]} rowFieldsOffset
|
|
* @param {boolean} isRowItem
|
|
* @param {number} itemIndex
|
|
* @param {PivotFormatsManagerQuery} query
|
|
*/
|
|
Worksheet.prototype._updatePivotTableCellsRowColLablesOffsets = function(pivotTable, rowFieldsOffset, isRowItem, itemIndex, itemXIndex, query) {
|
|
const items = isRowItem ? pivotTable.getRowItems() : pivotTable.getColItems();
|
|
if (!items) {
|
|
return;
|
|
}
|
|
query.axis = isRowItem ? Asc.c_oAscAxis.AxisRow : Asc.c_oAscAxis.AxisCol;
|
|
const item = items[itemIndex];
|
|
if (item.t === Asc.c_oAscItemType.Data) {
|
|
this.updatePivotTableCellsRowColLablesDataOffsets(pivotTable, rowFieldsOffset, isRowItem, itemIndex, itemXIndex, query);
|
|
} else {
|
|
this.updatePivotTableCellsRowColLablesSubtotalsOffsets(pivotTable, rowFieldsOffset, isRowItem, itemIndex, itemXIndex, query);
|
|
}
|
|
return;
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {number[]} rowFieldsOffset
|
|
*/
|
|
Worksheet.prototype._updatePivotTableCellsRowColLables = function(pivotTable, rowFieldsOffset) {
|
|
//CT_pivotTableDefinition.prototype.getLayoutByCellHeaderRowColLables
|
|
var items, fields, field, oCellValue, fieldIndex, cells, r1, c1, i, j, valuesIndex, isRowItems = false;
|
|
var pivotRange = pivotTable.getRange();
|
|
var location = pivotTable.location;
|
|
var hasLeftAlignInRowLables = false;
|
|
var outlines = [0];
|
|
if (rowFieldsOffset) {
|
|
items = pivotTable.getRowItems();
|
|
isRowItems = true;
|
|
fields = pivotTable.asc_getRowFields();
|
|
r1 = pivotRange.r1 + location.firstDataRow;
|
|
c1 = pivotRange.c1;
|
|
valuesIndex = pivotTable.getRowFieldsValuesIndex();
|
|
hasLeftAlignInRowLables = pivotTable.hasLeftAlignInRowLables();
|
|
for (i = 1; i < rowFieldsOffset.length; ++i) {
|
|
outlines[i] = outlines[i - 1] + 1;
|
|
if (rowFieldsOffset[i] !== rowFieldsOffset[i - 1]) {
|
|
outlines[i] = 0;
|
|
}
|
|
}
|
|
} else {
|
|
items = pivotTable.getColItems();
|
|
fields = pivotTable.asc_getColumnFields();
|
|
r1 = pivotRange.r1 + location.firstHeaderRow;
|
|
c1 = pivotRange.c1 + location.firstDataCol;
|
|
valuesIndex = pivotTable.getColumnFieldsValuesIndex();
|
|
}
|
|
if (!items || !fields) {
|
|
if (pivotTable.gridDropZones && !fields && pivotTable.getDataFieldsCount() > 0) {
|
|
if (rowFieldsOffset) {
|
|
cells = this.getRange4(pivotRange.r1 + location.firstDataRow, pivotRange.c1 + location.firstDataCol - 1);
|
|
} else {
|
|
cells = this.getRange4(pivotRange.r1 + location.firstDataRow - 1, pivotRange.c1 + location.firstDataCol);
|
|
}
|
|
oCellValue = new AscCommonExcel.CCellValue();
|
|
oCellValue.type = AscCommon.CellValueType.String;
|
|
oCellValue.text = AscCommon.translateManager.getValue(AscCommonExcel.ToName_ST_ItemType(Asc.c_oAscItemType.Default));
|
|
cells.setValueData(new AscCommonExcel.UndoRedoData_CellValueData(null, oCellValue));
|
|
}
|
|
if (rowFieldsOffset && false === pivotTable.showHeaders && false === pivotTable.gridDropZones && pivotTable.getDataFieldsCount() > 0) {
|
|
cells = this.getRange4(pivotRange.r1 + location.firstDataRow, pivotRange.c1 + location.firstDataCol - 1);
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.getDataFieldName(0));
|
|
}
|
|
return;
|
|
}
|
|
var pivotFields = pivotTable.asc_getPivotFields();
|
|
|
|
var totalTitleRange = [];
|
|
var valuesCache = [];
|
|
for (i = 0; i < items.length; ++i) {
|
|
var item = items[i];
|
|
/** @type {PivotItemFieldsInfo[]} */
|
|
var fieldValues = [];
|
|
var r = item.getR();
|
|
for (j = 0; j < r; ++j) {
|
|
fieldIndex = fields[j].asc_getIndex();
|
|
field = pivotFields[fieldIndex];
|
|
fieldValues.push(valuesCache[j]);
|
|
if (AscCommonExcel.st_VALUES !== fieldIndex && field.asc_getFillDownLabelsDefault() && totalTitleRange[j]) {
|
|
if (rowFieldsOffset) {
|
|
cells = this.getRange4(r1 + i, c1 + rowFieldsOffset[j]);
|
|
} else {
|
|
cells = this.getRange4(r1 + j, c1 + i);
|
|
}
|
|
cells.setStyle(totalTitleRange[j].getStyle());
|
|
cells.setValueData(totalTitleRange[j].getValueData());
|
|
}
|
|
}
|
|
for (j = 0; j < item.x.length; ++j) {
|
|
/** @type {PivotFormatsManagerQuery} */
|
|
const query = {
|
|
valuesInfo: fieldValues,
|
|
isData: false,
|
|
isGrandRow: isRowItems && item.t === Asc.c_oAscItemType.Grand,
|
|
isGrandCol: !isRowItems && item.t === Asc.c_oAscItemType.Grand,
|
|
type: Asc.c_oAscPivotAreaType.Normal,
|
|
field: null
|
|
};
|
|
fieldIndex = null;
|
|
var outline = 0;
|
|
if (rowFieldsOffset) {
|
|
cells = this.getRange4(r1 + i, c1 + rowFieldsOffset[r + j]);
|
|
} else {
|
|
cells = this.getRange4(r1 + r + j, c1 + i);
|
|
}
|
|
if (Asc.c_oAscItemType.Data === item.t) {
|
|
if (rowFieldsOffset) {
|
|
outline = outlines[r + j];
|
|
}
|
|
fieldIndex = fields[r + j].asc_getIndex();
|
|
if (AscCommonExcel.st_VALUES !== fieldIndex) {
|
|
oCellValue = pivotTable.getPivotFieldCellValue(fieldIndex, item.x[j].getV());
|
|
fieldValues.push({
|
|
fieldIndex: fieldIndex,
|
|
value: item.x[j].getV(),
|
|
type: Asc.c_oAscItemType.Data
|
|
});
|
|
query.field = fieldIndex;
|
|
this._updatePivotTableCellsRowColLablesOffsets(pivotTable, rowFieldsOffset, isRowItems, i, j, query);
|
|
} else {
|
|
fieldValues.push({
|
|
fieldIndex: AscCommonExcel.st_DATAFIELD_REFERENCE_FIELD,
|
|
value: item.i,
|
|
type: Asc.c_oAscItemType.Data
|
|
});
|
|
query.field = AscCommonExcel.st_DATAFIELD_REFERENCE_FIELD;
|
|
const formatting = pivotTable.getFormatting(query);
|
|
cells.setStyle(formatting);
|
|
oCellValue = new AscCommonExcel.CCellValue();
|
|
oCellValue.type = AscCommon.CellValueType.String;
|
|
oCellValue.text = pivotTable.getDataFieldName(item.i);
|
|
}
|
|
totalTitleRange[r + j] = cells;
|
|
} else if (Asc.c_oAscItemType.Grand === item.t) {
|
|
oCellValue = new AscCommonExcel.CCellValue();
|
|
oCellValue.type = AscCommon.CellValueType.String;
|
|
if (-1 === valuesIndex) {
|
|
oCellValue.text = pivotTable.grandTotalCaption || AscCommon.translateManager.getValue(AscCommonExcel.GRAND_TOTAL_CAPTION);
|
|
this._updatePivotTableCellsRowColLablesOffsets(pivotTable, rowFieldsOffset, isRowItems, i, j, query);
|
|
} else {
|
|
oCellValue.text = AscCommon.translateManager.getValue(AscCommonExcel.ToName_ST_ItemType(item.t));
|
|
oCellValue.text += ' ' + pivotTable.getDataFieldName(item.i);
|
|
fieldValues.push({
|
|
fieldIndex: AscCommonExcel.st_DATAFIELD_REFERENCE_FIELD,
|
|
value: item.i,
|
|
type: Asc.c_oAscItemType.Data
|
|
});
|
|
this._updatePivotTableCellsRowColLablesOffsets(pivotTable, rowFieldsOffset, isRowItems, i, j, query);
|
|
}
|
|
if (fields && fields[0]) {
|
|
if (pivotFields[fields[0].asc_getIndex()] && pivotFields[fields[0].asc_getIndex()].num) {
|
|
cells.setNum(pivotFields[fields[0].asc_getIndex()].num);
|
|
}
|
|
}
|
|
} else if (Asc.c_oAscItemType.Blank === item.t) {
|
|
break;
|
|
} else {
|
|
if (rowFieldsOffset) {
|
|
outline = outlines[r + j];
|
|
}
|
|
oCellValue = new AscCommonExcel.CCellValue();
|
|
oCellValue.type = AscCommon.CellValueType.String;
|
|
const titleRangeValue = totalTitleRange[r + j].getValueWithFormatSkipToSpace();
|
|
if (r + j > valuesIndex) {
|
|
fieldIndex = fields[r + j].asc_getIndex();
|
|
field = pivotFields[fieldIndex];
|
|
fieldValues.push({
|
|
fieldIndex: fieldIndex,
|
|
value: item.x[j].getV(),
|
|
type: item.t
|
|
});
|
|
if (AscCommonExcel.st_VALUES !== fieldIndex) {
|
|
if (field.subtotalCaption) {
|
|
oCellValue.text = field.subtotalCaption.replace(/\?/g, titleRangeValue);
|
|
} else {
|
|
oCellValue.text = titleRangeValue;
|
|
oCellValue.text += ' ' + AscCommon.translateManager.getValue(AscCommonExcel.ToName_ST_ItemType(item.t));
|
|
query.field = fieldIndex;
|
|
this._updatePivotTableCellsRowColLablesOffsets(pivotTable, rowFieldsOffset, isRowItems, i, j, query);
|
|
}
|
|
}
|
|
} else {
|
|
fieldIndex = fields[r + j].asc_getIndex();
|
|
field = pivotFields[fieldIndex];
|
|
fieldValues.push({
|
|
fieldIndex: fieldIndex,
|
|
value: item.x[j].getV(),
|
|
type: item.t
|
|
}, {
|
|
fieldIndex: AscCommonExcel.st_DATAFIELD_REFERENCE_FIELD,
|
|
value: item.i,
|
|
type: Asc.c_oAscItemType.Data
|
|
});
|
|
query.field = fieldIndex;
|
|
oCellValue.text = titleRangeValue;
|
|
oCellValue.text += ' ' + pivotTable.getDataFieldName(item.i);
|
|
this._updatePivotTableCellsRowColLablesOffsets(pivotTable, rowFieldsOffset, isRowItems, i, j, query);
|
|
}
|
|
}
|
|
if (null !== fieldIndex) {
|
|
var num = pivotTable.getPivotFieldNum(fieldIndex);
|
|
if (num) {
|
|
cells.setNum(num);
|
|
}
|
|
}
|
|
if (hasLeftAlignInRowLables) {
|
|
cells.setAlignHorizontal(AscCommon.align_Left);
|
|
}
|
|
if (outline > 0) {
|
|
cells.setIndent(outline);
|
|
}
|
|
cells.setValueData(new AscCommonExcel.UndoRedoData_CellValueData(null, oCellValue));
|
|
valuesCache = fieldValues;
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._updatePivotTableCellsRowHeaderLabels = function(pivotTable) {
|
|
//CT_pivotTableDefinition.prototype.getLayoutByCellHeaderRowColLables
|
|
var rowFieldsOffset = [0];
|
|
var rowFields = pivotTable.asc_getRowFields();
|
|
if (!rowFields) {
|
|
return rowFieldsOffset;
|
|
}
|
|
var cells, index, field;
|
|
var pivotFields = pivotTable.asc_getPivotFields();
|
|
var pivotRange = pivotTable.getRange();
|
|
var location = pivotTable.location;
|
|
var c1 = pivotRange.c1;
|
|
var r1 = pivotRange.r1 + location.firstDataRow - 1;
|
|
cells = this.getRange4(r1, c1);
|
|
if (pivotTable.showHeaders) {
|
|
if (pivotTable.compact || location.firstDataCol !== rowFields.length) {
|
|
if(1 === rowFields.length && AscCommonExcel.st_VALUES === rowFields[0].asc_getIndex()){
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.dataCaption || AscCommon.translateManager.getValue(AscCommonExcel.DATA_CAPTION));
|
|
} else {
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.rowHeaderCaption || AscCommon.translateManager.getValue(AscCommonExcel.ROW_HEADER_CAPTION));
|
|
}
|
|
} else {
|
|
index = rowFields[0].asc_getIndex();
|
|
if (AscCommonExcel.st_VALUES !== index) {
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.getPivotFieldName(index));
|
|
} else {
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.dataCaption || AscCommon.translateManager.getValue(AscCommonExcel.DATA_CAPTION));
|
|
}
|
|
}
|
|
}
|
|
for (var i = 1; i < rowFields.length; ++i) {
|
|
index = rowFields[i - 1].asc_getIndex();
|
|
var isTabular;
|
|
if (AscCommonExcel.st_VALUES !== index) {
|
|
field = pivotFields[index];
|
|
isTabular = field && !(field.compact && field.outline);
|
|
} else {
|
|
isTabular = !(pivotTable.compact && pivotTable.outline);
|
|
}
|
|
if (isTabular) {
|
|
index = rowFields[i].asc_getIndex();
|
|
++c1;
|
|
if (pivotTable.showHeaders) {
|
|
cells = this.getRange4(r1, c1);
|
|
if (AscCommonExcel.st_VALUES !== index) {
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.getPivotFieldName(index));
|
|
} else {
|
|
this._updatePivotTableSetCellValue(cells, pivotTable.dataCaption || AscCommon.translateManager.getValue(AscCommonExcel.DATA_CAPTION));
|
|
}
|
|
}
|
|
}
|
|
rowFieldsOffset[i] = c1 - pivotRange.c1;
|
|
}
|
|
r1 = pivotRange.r1 + location.firstDataRow - 1;
|
|
c1 = pivotRange.c1;
|
|
if (pivotTable.compact) {
|
|
const cells = this.getRange4(r1, c1);
|
|
const index = rowFields[0].asc_getIndex();
|
|
const formatting = pivotTable.getFormatting({
|
|
type: Asc.c_oAscPivotAreaType.Button,
|
|
axis: Asc.c_oAscAxis.AxisRow,
|
|
isData: false,
|
|
field: index
|
|
});
|
|
cells.setStyle(formatting);
|
|
} else {
|
|
for (let i = 0; i < rowFields.length; i += 1) {
|
|
const cells = this.getRange4(r1, c1 + i);
|
|
const index = rowFields[i].asc_getIndex();
|
|
const formatting = pivotTable.getFormatting({
|
|
type: Asc.c_oAscPivotAreaType.Button,
|
|
axis: Asc.c_oAscAxis.AxisRow,
|
|
isData: false,
|
|
field: index
|
|
});
|
|
cells.setStyle(formatting);
|
|
}
|
|
}
|
|
return rowFieldsOffset;
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
*/
|
|
Worksheet.prototype.setFormatsCellsDataNoDataField = function(pivotTable) {
|
|
const pivotRange = pivotTable.getRange();
|
|
const location = pivotTable.location;
|
|
const r1 = pivotRange.r1 + location.firstDataRow;
|
|
const c1 = pivotRange.c1 + location.firstDataCol;
|
|
const r2 = pivotRange.r2;
|
|
const c2 = pivotRange.c2;
|
|
for(let i = r1; i <= r2; i += 1) {
|
|
for(let j = c1; j <= c2; j += 1) {
|
|
const cell = this.getRange4(i, j);
|
|
cell.setStyle(pivotTable.getFormatting({
|
|
type: Asc.c_oAscPivotAreaType.All,
|
|
}));
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* A function that updates the data in the cells of a pivot table.
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {PivotDataElem} dataRow
|
|
*/
|
|
Worksheet.prototype._updatePivotTableCellsData = function(pivotTable, dataRow) {
|
|
const rowItems = pivotTable.getRowItems();
|
|
const colItems = pivotTable.getColItems();
|
|
const dataFields = pivotTable.asc_getDataFields();
|
|
if (!rowItems || !colItems || !dataFields) {
|
|
this.setFormatsCellsDataNoDataField(pivotTable);
|
|
return;
|
|
}
|
|
pivotTable.dataManager.update(dataRow);
|
|
};
|
|
/**
|
|
* @param {CT_pivotTableDefinition} pivotTable
|
|
* @param {PivotDataElem} dataRow
|
|
*/
|
|
Worksheet.prototype._updatePivotTableCells = function (pivotTable, dataRow) {
|
|
pivotTable.formatsManager.updateCollection();
|
|
this._updatePivotTableCellsPage(pivotTable);
|
|
this._updatePivotTableCellsHeader(pivotTable);
|
|
this._updatePivotTableCellsRowColLables(pivotTable);
|
|
var rowFieldsOffset = this._updatePivotTableCellsRowHeaderLabels(pivotTable);
|
|
this._updatePivotTableCellsRowColLables(pivotTable, rowFieldsOffset);
|
|
this._updatePivotTableCellsData(pivotTable, dataRow);
|
|
};
|
|
Worksheet.prototype.updatePivotTablesStyle = function (range, canModifyDocument) {
|
|
var t = this;
|
|
var pivotTable, pivotRange, pivotFields, rowFields, styleInfo, style, wholeStyle, cells, j, r, x, pos,
|
|
firstHeaderRow0, firstDataCol0, countC, countCWValues, countR, countD, stripe1, stripe2, items, l, item,
|
|
start, end, isOutline, arrSubheading, emptyStripe = new Asc.CTableStyleElement();
|
|
var dxf, dxfLabels, dxfValues, grandColumn, index;
|
|
var checkRowSubheading = function (_i, _r, _v, _dxf) {
|
|
var sub, bSet = true;
|
|
if ((sub = arrSubheading[_i])) {
|
|
if (sub.v === _v) {
|
|
bSet = false;
|
|
} else {
|
|
cells = t.getRange3(sub.r, pivotRange.c1 + _i, _r - 1, pivotRange.c1 + _i);
|
|
cells.setTableStyle(sub.dxf);
|
|
}
|
|
}
|
|
if (bSet) {
|
|
arrSubheading[_i] = (null === _v) ? null : {r: _r, dxf: _dxf, v: _v};
|
|
}
|
|
};
|
|
var endRowSubheadings = function (_i, _r) {
|
|
for (;_i < arrSubheading.length; ++_i) {
|
|
checkRowSubheading(_i, _r, null, null);
|
|
}
|
|
};
|
|
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
grandColumn = 0;
|
|
pivotTable = this.pivotTables[i];
|
|
pivotRange = pivotTable.getRange();
|
|
pivotFields = pivotTable.asc_getPivotFields();
|
|
rowFields = pivotTable.asc_getRowFields();
|
|
styleInfo = pivotTable.asc_getStyleInfo();
|
|
if (!pivotTable.isInit || !styleInfo || (range && !pivotTable.intersection(range))) {
|
|
continue;
|
|
}
|
|
style = this.workbook.TableStyles.AllStyles[styleInfo.asc_getName()];
|
|
|
|
wholeStyle = style && style.wholeTable && style.wholeTable.dxf;
|
|
|
|
// Page Field Labels, Page Field Values
|
|
dxfLabels = style && style.pageFieldLabels && style.pageFieldLabels.dxf;
|
|
dxfValues = style && style.pageFieldValues && style.pageFieldValues.dxf;
|
|
for (j = 0; j < pivotTable.pageFieldsPositions.length; ++j) {
|
|
pos = pivotTable.pageFieldsPositions[j];
|
|
cells = this.getRange4(pos.row, pos.col);
|
|
cells.clearTableStyle();
|
|
cells.setTableStyle(wholeStyle);
|
|
cells.setTableStyle(dxfLabels);
|
|
cells = this.getRange4(pos.row, pos.col + 1);
|
|
cells.clearTableStyle();
|
|
cells.setTableStyle(wholeStyle);
|
|
cells.setTableStyle(dxfValues);
|
|
}
|
|
|
|
cells = this.getRange3(pivotRange.r1, pivotRange.c1, pivotRange.r2, pivotRange.c2);
|
|
cells.clearTableStyle();
|
|
|
|
if (!style) {
|
|
continue;
|
|
}
|
|
|
|
countC = pivotTable.getColumnFieldsCount();
|
|
countR = pivotTable.getRowFieldsCount(true);
|
|
|
|
if (pivotTable.isEmptyReport()) {
|
|
if (canModifyDocument && 0 === pivotTable.pageFieldsPositions.length) {
|
|
//todo transparent ih, iv
|
|
var border;
|
|
border = new AscCommonExcel.Border();
|
|
border.initDefault();
|
|
border.l = new AscCommonExcel.BorderProp();
|
|
border.l.setStyle(c_oAscBorderStyles.Thin);
|
|
border.l.c = AscCommonExcel.createRgbColor(0, 0, 0);
|
|
border.t = new AscCommonExcel.BorderProp();
|
|
border.t.setStyle(c_oAscBorderStyles.Thin);
|
|
border.t.c = AscCommonExcel.createRgbColor(0, 0, 0);
|
|
border.r = new AscCommonExcel.BorderProp();
|
|
border.r.setStyle(c_oAscBorderStyles.Thin);
|
|
border.r.c = AscCommonExcel.createRgbColor(0, 0, 0);
|
|
border.b = new AscCommonExcel.BorderProp();
|
|
border.b.setStyle(c_oAscBorderStyles.Thin);
|
|
border.b.c = AscCommonExcel.createRgbColor(0, 0, 0);
|
|
border.ih = new AscCommonExcel.BorderProp();
|
|
border.ih.setStyle(c_oAscBorderStyles.Thin);
|
|
border.ih.c = AscCommonExcel.createRgbColor(255, 255, 255);
|
|
border.iv = new AscCommonExcel.BorderProp();
|
|
border.iv.setStyle(c_oAscBorderStyles.Thin);
|
|
border.iv.c = AscCommonExcel.createRgbColor(255, 255, 255);
|
|
cells.setBorder(border);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
firstHeaderRow0 = pivotTable.getFirstHeaderRow0();
|
|
firstDataCol0 = pivotTable.getFirstDataCol();
|
|
countD = pivotTable.getDataFieldsCount();
|
|
countCWValues = pivotTable.getColumnFieldsCount(true);
|
|
|
|
// Whole Table
|
|
cells.setTableStyle(wholeStyle);
|
|
|
|
// First Column Stripe, Second Column Stripe
|
|
if (styleInfo.showColStripes) {
|
|
stripe1 = style.firstColumnStripe || emptyStripe;
|
|
stripe2 = style.secondColumnStripe || emptyStripe;
|
|
start = pivotRange.c1 + firstDataCol0;
|
|
if (stripe1.dxf) {
|
|
cells = this.getRange3(pivotRange.r1 + firstHeaderRow0 + 1, start, pivotRange.r2, pivotRange.c2);
|
|
cells.setTableStyle(stripe1.dxf, new Asc.CTableStyleStripe(stripe1.size, stripe2.size));
|
|
}
|
|
if (stripe2.dxf && start + stripe1.size <= pivotRange.c2) {
|
|
cells = this.getRange3(pivotRange.r1 + firstHeaderRow0 + 1, start + stripe1.size, pivotRange.r2,
|
|
pivotRange.c2);
|
|
cells.setTableStyle(stripe2.dxf, new Asc.CTableStyleStripe(stripe2.size, stripe1.size));
|
|
}
|
|
}
|
|
// First Row Stripe, Second Row Stripe
|
|
if (styleInfo.showRowStripes && countR && (pivotRange.c1 + countR - 1 !== pivotRange.c2)) {
|
|
stripe1 = style.firstRowStripe || emptyStripe;
|
|
stripe2 = style.secondRowStripe || emptyStripe;
|
|
start = pivotRange.r1 + firstHeaderRow0 + 1;
|
|
if (stripe1.dxf) {
|
|
cells = this.getRange3(start, pivotRange.c1, pivotRange.r2, pivotRange.c2);
|
|
cells.setTableStyle(stripe1.dxf, new Asc.CTableStyleStripe(stripe1.size, stripe2.size, true));
|
|
}
|
|
if (stripe2.dxf && start + stripe1.size <= pivotRange.r2) {
|
|
cells = this.getRange3(start + stripe1.size, pivotRange.c1, pivotRange.r2, pivotRange.c2);
|
|
cells.setTableStyle(stripe1.dxf, new Asc.CTableStyleStripe(stripe2.size, stripe1.size, true));
|
|
}
|
|
}
|
|
|
|
// First Column
|
|
dxf = style.firstColumn && style.firstColumn.dxf;
|
|
if (styleInfo.showRowHeaders && countR && dxf) {
|
|
cells = this.getRange3(pivotRange.r1, pivotRange.c1, pivotRange.r2, pivotRange.c1 +
|
|
Math.max(0, firstDataCol0 - 1));
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
|
|
// Header Row
|
|
dxf = style.headerRow && style.headerRow.dxf;
|
|
if (styleInfo.showColHeaders && dxf) {
|
|
cells = this.getRange3(pivotRange.r1, pivotRange.c1, pivotRange.r1 + firstHeaderRow0, pivotRange.c2);
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
|
|
// First Header Cell
|
|
dxf = style.firstHeaderCell && style.firstHeaderCell.dxf;
|
|
if (styleInfo.showColHeaders && styleInfo.showRowHeaders && countCWValues && (countR + countD) && dxf) {
|
|
cells = this.getRange3(pivotRange.r1, pivotRange.c1, pivotRange.r1 + firstHeaderRow0 - (countR ? 1 : 0),
|
|
pivotRange.c1 + Math.max(0, firstDataCol0 - 1));
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
|
|
// Subtotal Column + Grand Total Column
|
|
items = pivotTable.getColItems();
|
|
if (items) {
|
|
start = pivotRange.c1 + firstDataCol0;
|
|
for (j = 0; j < items.length; ++j) {
|
|
dxf = null;
|
|
item = items[j];
|
|
r = item.getR();
|
|
if (Asc.c_oAscItemType.Grand === item.t || 0 === countCWValues) {
|
|
// Grand Total Column
|
|
dxf = style.lastColumn;
|
|
grandColumn = 1;
|
|
} else {
|
|
// Subtotal Column
|
|
if (r + 1 !== countC) {
|
|
if (countD && Asc.c_oAscItemType.Data !== item.t) {
|
|
if (0 === r) {
|
|
dxf = style.firstSubtotalColumn;
|
|
} else if (1 === r % 2) {
|
|
dxf = style.secondSubtotalColumn;
|
|
} else {
|
|
dxf = style.thirdSubtotalColumn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dxf = dxf && dxf.dxf;
|
|
if (dxf) {
|
|
cells = this.getRange3(pivotRange.r1 + 1, start + j, pivotRange.r2, start + j);
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Subtotal Row + Row Subheading + Grand Total Row
|
|
items = pivotTable.getRowItems();
|
|
if (items && countR) {
|
|
arrSubheading = [];
|
|
countR = pivotTable.getRowFieldsCount();
|
|
start = pivotRange.r1 + firstHeaderRow0 + 1;
|
|
for (j = 0; j < items.length; ++j) {
|
|
dxf = null;
|
|
item = items[j];
|
|
if (Asc.c_oAscItemType.Data !== item.t) {
|
|
if (Asc.c_oAscItemType.Grand === item.t) {
|
|
// Grand Total Row
|
|
dxf = style.totalRow;
|
|
pos = 0;
|
|
} else if (Asc.c_oAscItemType.Blank === item.t) {
|
|
// Blank Row
|
|
dxf = style.blankRow;
|
|
pos = 0;
|
|
} else if (styleInfo.showRowHeaders) {
|
|
// Subtotal Row
|
|
r = item.getR();
|
|
if (r + 1 !== countR) {
|
|
if (0 === r) {
|
|
dxf = style.firstSubtotalRow;
|
|
} else if (1 === r % 2) {
|
|
dxf = style.secondSubtotalRow;
|
|
} else {
|
|
dxf = style.thirdSubtotalRow;
|
|
}
|
|
pos = pivotTable.getRowFieldPos(r);
|
|
}
|
|
}
|
|
dxf = dxf && dxf.dxf;
|
|
if (dxf) {
|
|
cells = this.getRange3(start + j, pivotRange.c1 + pos, start + j, pivotRange.c2);
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
endRowSubheadings(pos, start + j);
|
|
} else if (styleInfo.showRowHeaders) {
|
|
// Row Subheading
|
|
r = item.getR();
|
|
index = rowFields[r].asc_getIndex();
|
|
isOutline = (AscCommonExcel.st_VALUES !== index && false !== pivotFields[index].outline);
|
|
for (x = 0, l = item.x.length; x < l; ++x, ++r) {
|
|
dxf = null;
|
|
if (r + 1 !== countR) {
|
|
if (0 === r) {
|
|
dxf = style.firstRowSubheading;
|
|
} else if (1 === r % 2) {
|
|
dxf = style.secondRowSubheading;
|
|
} else {
|
|
dxf = style.thirdRowSubheading;
|
|
}
|
|
dxf = dxf && dxf.dxf;
|
|
if (dxf) {
|
|
pos = pivotTable.getRowFieldPos(r);
|
|
if (1 === l && isOutline) {
|
|
endRowSubheadings(pos, start + j);
|
|
cells = this.getRange3(start + j, pivotRange.c1 + pos, start + j, pivotRange.c2);
|
|
cells.setTableStyle(dxf);
|
|
} else {
|
|
checkRowSubheading(pos, start + j, item.x[x].getV(), dxf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
endRowSubheadings(0, pivotRange.r2 + 1);
|
|
}
|
|
|
|
// Column Subheading
|
|
items = pivotTable.getColItems();
|
|
if (items && styleInfo.showColHeaders) {
|
|
start = pivotRange.c1 + firstDataCol0;
|
|
end = pivotRange.c2 - grandColumn;
|
|
for (j = 0; j < countCWValues; ++j) {
|
|
if (0 === j) {
|
|
dxf = style.firstColumnSubheading;
|
|
} else if (1 === j % 2) {
|
|
dxf = style.secondColumnSubheading;
|
|
} else {
|
|
dxf = style.thirdColumnSubheading;
|
|
}
|
|
dxf = dxf && dxf.dxf;
|
|
if (dxf) {
|
|
cells = this.getRange3(pivotRange.r1 + 1 + j, start, pivotRange.r1 + 1 + j, end);
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
}
|
|
pos = pivotRange.r1 + 1 + firstHeaderRow0 - (countR ? 1 : 0);
|
|
for (j = 0; j < items.length; ++j) {
|
|
item = items[j];
|
|
if (Asc.c_oAscItemType.Data !== item.t && Asc.c_oAscItemType.Grand !== item.t) {
|
|
r = item.getR();
|
|
if (0 === r) {
|
|
dxf = style.firstColumnSubheading;
|
|
} else if (1 === r % 2) {
|
|
dxf = style.secondColumnSubheading;
|
|
} else {
|
|
dxf = style.thirdColumnSubheading;
|
|
}
|
|
dxf = dxf && dxf.dxf;
|
|
if (dxf) {
|
|
cells =
|
|
this.getRange3(pivotRange.r1 + 1 + r, start + j, pos, start + j);
|
|
cells.setTableStyle(dxf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.updatePivotOffset = function (range, offset) {
|
|
if (offset.row < 0 || offset.col < 0) {
|
|
this.deletePivotTables(range);
|
|
}
|
|
var bboxShift = AscCommonExcel.shiftGetBBox(range, 0 !== offset.col);
|
|
this.movePivotOffset(bboxShift, offset);
|
|
};
|
|
Worksheet.prototype.movePivotOffset = function (range, offset) {
|
|
var pivotTable;
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
pivotTable = this.pivotTables[i];
|
|
if (pivotTable.isInRange(range)) {
|
|
this.workbook.oApi._changePivotSimple(pivotTable, false, false, function() {
|
|
pivotTable.setOffset(offset, true);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.copyPivotTable = function (range, offset, wsTo) {
|
|
var t = this;
|
|
var pivotTable;
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
pivotTable = this.pivotTables[i];
|
|
if (pivotTable.isInRange(range)) {
|
|
var newPivot = pivotTable.cloneShallow();
|
|
newPivot.prepareToPaste(wsTo, offset, wsTo === pivotTable.GetWS());
|
|
this.workbook.oApi._changePivotSimple(newPivot, true, false, function() {
|
|
wsTo.insertPivotTable(newPivot, true, false);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.inTopAutoFilter = function (range) {
|
|
var _filterRange = this.AutoFilter && this.AutoFilter.Ref && new Asc.Range(this.AutoFilter.Ref.c1, this.AutoFilter.Ref.r1, this.AutoFilter.Ref.c2, this.AutoFilter.Ref.r1);
|
|
return _filterRange && range.intersection(_filterRange);
|
|
};
|
|
Worksheet.prototype.inPivotTable = function (range, exceptPivot) {
|
|
return this.pivotTables.find(function (element) {
|
|
return exceptPivot !== element && element.intersection(range);
|
|
});
|
|
};
|
|
Worksheet.prototype.checkShiftPivotTable = function (range, offset) {
|
|
if ((offset.row < 0 || offset.col < 0) && this._isPivotsIntersectRangeButNotInIt(range)) {
|
|
return true;
|
|
}
|
|
return this._isPivotsIntersectRangeButNotInIt(AscCommonExcel.shiftGetBBox(range, 0 !== offset.col));
|
|
};
|
|
Worksheet.prototype.checkMovePivotTable = function(arnFrom, arnTo, ctrlKey, opt_wsTo) {
|
|
var t = this;
|
|
if (!opt_wsTo) {
|
|
opt_wsTo = this;
|
|
}
|
|
if (this.inPivotTable(arnFrom)) {
|
|
var intersectionTableParts = opt_wsTo.autoFilters.getTablesIntersectionRange(arnTo);
|
|
for (var i = 0; i < intersectionTableParts.length; i++) {
|
|
if(intersectionTableParts[i] && intersectionTableParts[i].Ref && !arnTo.containsRange(intersectionTableParts[i].Ref)) {
|
|
return c_oAscError.ID.PivotOverlap;
|
|
}
|
|
}
|
|
}
|
|
var res = false;
|
|
if (ctrlKey) {
|
|
res = this._isPivotsIntersectRangeButNotInIt(arnFrom) || opt_wsTo._isPivotsIntersectRangeButNotInIt(arnTo);
|
|
} else {
|
|
res = this._isPivotsIntersectRangeButNotInIt(arnFrom) || opt_wsTo.pivotTables.some(function(element) {
|
|
return element.intersection(arnTo) && !element.isInRange(arnTo) && (opt_wsTo !== t || !element.isInRange(arnFrom));
|
|
});
|
|
}
|
|
return res ? c_oAscError.ID.LockedCellPivot : c_oAscError.ID.No;
|
|
};
|
|
Worksheet.prototype._isPivotsIntersectRangeButNotInIt = function (bbox) {
|
|
return this.pivotTables.some(function (element) {
|
|
return element.intersection(bbox) && !element.isInRange(bbox);
|
|
});
|
|
};
|
|
Worksheet.prototype.checkDeletePivotTables = function (range) {
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].intersection(range) && !this.pivotTables[i].getAllRange(this).inContains(range)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
Worksheet.prototype.deletePivotTable = function (id) {
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
var pivotTable = this.pivotTables[i];
|
|
if (id === pivotTable.Get_Id()) {
|
|
this.clearPivotTableStyle(pivotTable);
|
|
this.pivotTables.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype._deletePivotTable = function (pivotTables, pivotTable, index, withoutCells) {
|
|
this.workbook.deleteSlicersByPivotTable(this.getId(), pivotTable.asc_getName());
|
|
this.workbook.deleteTimelinesByPivotTable(this.getId(), pivotTable.asc_getName());
|
|
|
|
if (!withoutCells) {
|
|
this.clearPivotTableCell(pivotTable);
|
|
}
|
|
this.clearPivotTableStyle(pivotTable);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_PivotDelete, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_PivotTableRedo(pivotTable.Get_Id(), pivotTable, null));
|
|
this.pivotTables.splice(index, 1);
|
|
};
|
|
Worksheet.prototype.deletePivotTables = function (range, withoutCells) {
|
|
for (var i = this.pivotTables.length - 1; i >= 0; --i) {
|
|
var pivotTable = this.pivotTables[i];
|
|
if (pivotTable.intersection(range)) {
|
|
this._deletePivotTable(this.pivotTables, pivotTable, i, withoutCells);
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
Worksheet.prototype.deletePivotTablesOnMove = function (from, to) {
|
|
for (var i = this.pivotTables.length - 1; i >= 0; --i) {
|
|
var pivotTable = this.pivotTables[i];
|
|
if (pivotTable.isInRange(to) && !pivotTable.isInRange(from)) {
|
|
this._deletePivotTable(this.pivotTables, pivotTable, i);
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
Worksheet.prototype.getPivotTable = function (col, row) {
|
|
var res = null;
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].contains(col, row)) {
|
|
res = this.pivotTables[i];
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotTablesIntersectingRange = function (bbox) {
|
|
var res = [];
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].intersection(bbox)) {
|
|
res.push(this.pivotTables[i]);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotTableByName = function (name) {
|
|
var res = null;
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].asc_getName() === name) {
|
|
res = this.pivotTables[i];
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotTableById = function (id) {
|
|
var res = null;
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].Get_Id() === id) {
|
|
res = this.pivotTables[i];
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotTablesByCacheId = function (pivotCacheId) {
|
|
var res = [];
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].getPivotCacheId() === pivotCacheId) {
|
|
res.push(this.pivotTables[i]);
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotTablesByCache = function (cache) {
|
|
var res = [];
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
if (this.pivotTables[i].cacheDefinition === cache) {
|
|
res.push(this.pivotTables[i]);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotCacheByDataLocation = function(dataLocation) {
|
|
return this.forEachPivotCache(undefined, function(cacheDefinition){
|
|
if (dataLocation && dataLocation.isEqual(cacheDefinition.getDataLocation())) {
|
|
return cacheDefinition;
|
|
}
|
|
});
|
|
};
|
|
|
|
Worksheet.prototype.getPivotCacheById = function(pivotCacheId, pivotCachesOpen) {
|
|
return this.forEachPivotCache(pivotCachesOpen, function(cacheDefinition){
|
|
if (pivotCacheId === cacheDefinition.getPivotCacheId()) {
|
|
return cacheDefinition;
|
|
}
|
|
});
|
|
};
|
|
Worksheet.prototype.forEachPivotCache = function(pivotCachesOpen, callback) {
|
|
var res, i;
|
|
for (i = 0; i < this.pivotTables.length; ++i) {
|
|
res = callback(this.pivotTables[i].cacheDefinition);
|
|
if(res){
|
|
return res;
|
|
}
|
|
}
|
|
for (i = 0; i < this.aSlicers.length; ++i) {
|
|
var cacheDefinition = this.aSlicers[i].getPivotCache();
|
|
if (cacheDefinition) {
|
|
res = callback(cacheDefinition);
|
|
if(res){
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
//for slicer with zero pivot connection
|
|
if (pivotCachesOpen) {
|
|
for (var cacheId in pivotCachesOpen) {
|
|
var cacheDefinition = pivotCachesOpen[cacheId];
|
|
if (cacheDefinition) {
|
|
res = callback(cacheDefinition);
|
|
if(res){
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
Worksheet.prototype.insertPivotTable = function (pivotTable, addToHistory, checkCacheDefinition) {
|
|
pivotTable.worksheet = this;
|
|
pivotTable.setChanged(false, true);
|
|
if (checkCacheDefinition) {
|
|
var cacheDefinition = this.workbook.getPivotCacheByDataLocation(pivotTable.getDataLocation());
|
|
if (cacheDefinition) {
|
|
pivotTable.setCacheDefinition(cacheDefinition);
|
|
}
|
|
}
|
|
this.pivotTables.push(pivotTable);
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_PivotAdd, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_BinaryWrapper(pivotTable));
|
|
}
|
|
};
|
|
Worksheet.prototype.getPivotTableButtons = function (range) {
|
|
var res = [];
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
this.pivotTables[i].getPivotTableButtons(range, res);
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getPivotTablesClearRanges = function (range) {
|
|
// For outline and compact pivot tables layout we need clear the grid
|
|
var pivotTable, pivotRange, intersection, res = [];
|
|
for (var i = 0; i < this.pivotTables.length; ++i) {
|
|
pivotTable = this.pivotTables[i];
|
|
if (pivotTable.clearGrid) {
|
|
pivotRange = pivotTable.getRange();
|
|
if (intersection = pivotRange.intersectionSimple(range)) {
|
|
res.push(intersection);
|
|
res.push(pivotRange);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.getDisablePrompts = function () {
|
|
return this.dataValidations && this.dataValidations.disablePrompts;
|
|
};
|
|
Worksheet.prototype.getDataValidation = function (c, r) {
|
|
if (!this.dataValidations) {
|
|
return null;
|
|
}
|
|
var merged = this.getMergedByCell(r, c);
|
|
if (merged) {
|
|
r = merged.r1;
|
|
c = merged.c1;
|
|
}
|
|
for (var i = 0; i < this.dataValidations.elems.length; ++i) {
|
|
if (this.dataValidations.elems[i].contains(c, r)) {
|
|
return this.dataValidations.elems[i];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
// ----- Search -----
|
|
Worksheet.prototype.clearFindResults = function () {
|
|
this.lastFindOptions = null;
|
|
this.workbook.handlers && this.workbook.handlers.trigger("clearFindResults", this.index);
|
|
};
|
|
Worksheet.prototype._findAllCells = function (options, searchEngine) {
|
|
//***searchEngine
|
|
if (options.findWhat == null) {
|
|
options.findWhat = "";
|
|
}
|
|
if (true !== options.isMatchCase) {
|
|
options.findWhat = options.findWhat.toLowerCase();
|
|
}
|
|
|
|
var findEmptyStr = options.findWhat === "";
|
|
if (findEmptyStr) {
|
|
options.findWhat = new RegExp("^$", "g");
|
|
} else if(options.isWholeWord) {
|
|
var length = options.findWhat.length;
|
|
options.findWhat = '\\b' + options.findWhat + '\\b';
|
|
options.findWhat = new RegExp(options.findWhat, "g");
|
|
options.findWhat.length = length;
|
|
}
|
|
var isWholeWordTrue = null;
|
|
if (findEmptyStr) {
|
|
isWholeWordTrue = options.isWholeWord;
|
|
options.isWholeWord = true;
|
|
}
|
|
|
|
var selectionRange = options.selectionRange || this.selectionRange || this.copySelection;
|
|
var lastRange = selectionRange.getLast();
|
|
var activeCell = selectionRange.activeCell;
|
|
var merge = this.getMergedByCell(activeCell.row, activeCell.col);
|
|
if (!searchEngine) {
|
|
options.findInSelection = Asc.c_oAscSearchBy.Sheet === options.scanOnOnlySheet &&
|
|
!(selectionRange.isSingleRange() && (lastRange.isOneCell() || lastRange.isEqual(merge)));
|
|
}
|
|
|
|
if (options.specificRange) {
|
|
lastRange = AscCommonExcel.g_oRangeCache.getAscRange(options.specificRange);
|
|
if (lastRange) {
|
|
options.findInSelection = true;
|
|
}
|
|
}
|
|
|
|
var findRange;
|
|
var maxRowsCount = this.getRowsCount();
|
|
var maxColsCount = this.getColsCount();
|
|
var func;
|
|
if (findEmptyStr) {
|
|
if (maxRowsCount === 0 || maxColsCount === 0) {
|
|
findRange = this.getRange3(0, 0, maxRowsCount, maxColsCount);
|
|
func = findRange._foreachNoEmpty;
|
|
} else if (options.findInSelection) {
|
|
if (lastRange.r1 <= maxRowsCount - 1 && lastRange.c1 <= maxColsCount - 1) {
|
|
findRange = this.getRange3(lastRange.r1, lastRange.c1, Math.min(lastRange.r2, maxRowsCount - 1), Math.min(lastRange.c2, maxColsCount - 1));
|
|
func = findRange._foreach2;
|
|
} else {
|
|
findRange = this.getRange3(lastRange.r1, lastRange.c1, lastRange.r2, lastRange.c2);
|
|
func = findRange._foreachNoEmpty;
|
|
}
|
|
} else {
|
|
findRange = this.getRange3(0, 0, maxRowsCount - 1, maxColsCount - 1);
|
|
func = findRange._foreach2;
|
|
}
|
|
} else {
|
|
findRange = options.findInSelection ? this.getRange3(lastRange.r1, lastRange.c1, lastRange.r2, lastRange.c2) :
|
|
this.getRange3(0, 0, maxRowsCount, maxColsCount);
|
|
func = findRange._foreachNoEmpty;
|
|
}
|
|
|
|
if (!searchEngine && this.lastFindOptions && this.lastFindOptions.findResults && options.isEqual2(this.lastFindOptions) &&
|
|
findRange.getBBox0().isEqual(this.lastFindOptions.findRange)) {
|
|
return;
|
|
}
|
|
|
|
var oldResults = this.lastFindOptions && this.lastFindOptions.findResults.isNotEmpty();
|
|
var result = new AscCommonExcel.findResults(), tmp;
|
|
var emptyCell, t = this;
|
|
func.apply(findRange, [function (cell, r, c) {
|
|
if (cell === null) {
|
|
if (!emptyCell) {
|
|
emptyCell = new Cell(t);
|
|
}
|
|
cell = emptyCell;
|
|
}
|
|
if (cell && cell.isEqual(options)) {
|
|
if (!options.scanByRows) {
|
|
tmp = r;
|
|
r = c;
|
|
c = tmp;
|
|
}
|
|
searchEngine ? searchEngine.Add(r, c, cell, !options.scanByRows ? result : null, options) : result.add(r, c, cell);
|
|
}
|
|
}]);
|
|
!options.scanByRows && searchEngine && searchEngine.endAdd(result);
|
|
|
|
if (isWholeWordTrue !== null) {
|
|
options.isWholeWord = isWholeWordTrue;
|
|
}
|
|
if (findEmptyStr) {
|
|
options.findWhat = "";
|
|
}
|
|
this.lastFindOptions = options.clone();
|
|
// ToDo support multiselect
|
|
this.lastFindOptions.findRange = findRange.getBBox0().clone();
|
|
this.lastFindOptions.findResults = result;
|
|
|
|
if (!options.isReplaceAll && this.workbook.oApi.selectSearchingResults && (oldResults || result.isNotEmpty() || (searchEngine && (searchEngine._lastNotEmpty || searchEngine.isNotEmpty()))) &&
|
|
this === this.workbook.getActiveWs()) {
|
|
this.workbook.handlers && this.workbook.handlers.trigger("drawWS");
|
|
if (searchEngine) {
|
|
searchEngine._lastNotEmpty = null;
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.findCellText = function (options, searchEngine) {
|
|
this._findAllCells(options, searchEngine);
|
|
if (searchEngine) {
|
|
return;
|
|
}
|
|
//CDocumentSearchExcel.prototype.SetCurrent
|
|
|
|
var selectionRange = options.selectionRange || this.selectionRange;
|
|
var activeCell = selectionRange.activeCell;
|
|
|
|
var tmp, key1 = activeCell.row, key2 = activeCell.col;
|
|
if (!options.scanByRows) {
|
|
tmp = key1;
|
|
key1 = key2;
|
|
key2 = tmp;
|
|
}
|
|
|
|
var result = null;
|
|
var findResults = this.lastFindOptions.findResults;
|
|
if (findResults.find(key1, key2, options.scanForward)) {
|
|
key1 = findResults.currentKey1;
|
|
key2 = findResults.currentKey2;
|
|
if (!options.scanByRows) {
|
|
tmp = key1;
|
|
key1 = key2;
|
|
key2 = tmp;
|
|
}
|
|
result = new AscCommon.CellBase(key1, key2);
|
|
}
|
|
return result;
|
|
};
|
|
Worksheet.prototype.inFindResults = function (row, col) {
|
|
var tmp, res = false;
|
|
var findResults = this.lastFindOptions && this.lastFindOptions.findResults;
|
|
if (findResults) {
|
|
if (!this.lastFindOptions.scanByRows) {
|
|
tmp = col;
|
|
col = row;
|
|
row = tmp;
|
|
}
|
|
res = findResults.contains(row, col);
|
|
}
|
|
return res;
|
|
};
|
|
Worksheet.prototype.excludeHiddenRows = function (bExclude) {
|
|
this.bExcludeHiddenRows = bExclude;
|
|
};
|
|
Worksheet.prototype.ignoreWriteFormulas = function (val) {
|
|
this.bIgnoreWriteFormulas = val;
|
|
};
|
|
Worksheet.prototype.checkShiftArrayFormulas = function (range, offset) {
|
|
//проверка на частичный сдвиг формулы массива
|
|
//проверка на внутренний сдвиг
|
|
var res = true;
|
|
|
|
var isHor = offset && offset.col;
|
|
var isDelete = offset && (offset.col < 0 || offset.row < 0);
|
|
|
|
var checkRange = function(formulaRange) {
|
|
//частичное выделение при удалении столбца/строки
|
|
if(isDelete && formulaRange.intersection(range) && !range.containsRange(formulaRange)) {
|
|
return false;
|
|
}
|
|
|
|
if (isHor) {
|
|
if(range.r1 > formulaRange.r1 && range.r1 <= formulaRange.r2) {
|
|
return false;
|
|
}
|
|
if(range.r2 >= formulaRange.r1 && range.r2 < formulaRange.r2) {
|
|
return false;
|
|
}
|
|
if(range.c1 > formulaRange.c1 && range.c1 <= formulaRange.c2) {
|
|
return false;
|
|
}
|
|
/*if(range.c1 < formulaRange.c1 && range.c2 >= formulaRange.c1 && range.c2 < formulaRange.c2) {
|
|
return false;
|
|
}*/
|
|
} else {
|
|
if(range.c1 > formulaRange.c1 && range.c1 <= formulaRange.c2) {
|
|
return false;
|
|
}
|
|
if(range.c2 >= formulaRange.c1 && range.c2 < formulaRange.c2) {
|
|
return false;
|
|
}
|
|
if(range.r1 > formulaRange.r1 && range.r1 <= formulaRange.r2) {
|
|
return false;
|
|
}
|
|
/*if(range.r1 < formulaRange.r1 && range.r2 >= formulaRange.r1 && range.r2 < formulaRange.r2) {
|
|
return false;
|
|
}*/
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
//if intersection with range
|
|
var alreadyCheckFormulas = [];
|
|
var r2 = range.r2, c2 = range.c2;
|
|
if(isHor) {
|
|
c2 = gc_nMaxCol0;
|
|
} else {
|
|
r2 = gc_nMaxRow0;
|
|
}
|
|
|
|
this.getRange3(range.r1, range.c1, r2, c2)._foreachNoEmpty(function(cell) {
|
|
if(res && cell.isFormula()) {
|
|
var formulaParsed = cell.getFormulaParsed();
|
|
var arrayFormulaRef = formulaParsed.getArrayFormulaRef();
|
|
if(arrayFormulaRef && !alreadyCheckFormulas[formulaParsed._index]) {
|
|
if(!checkRange(arrayFormulaRef)) {
|
|
res = false;
|
|
}
|
|
alreadyCheckFormulas[formulaParsed._index] = 1;
|
|
}
|
|
}
|
|
});
|
|
|
|
return res;
|
|
};
|
|
Worksheet.prototype.setRowsCount = function (val) {
|
|
if(val > gc_nMaxRow0 || val < 0) {
|
|
return;
|
|
}
|
|
this.nRowsCount = val;
|
|
};
|
|
Worksheet.prototype.reinitRowsCount = function () {
|
|
let maxTableRow = 0;
|
|
if (this.TableParts) {
|
|
for (let i = 0; i < this.TableParts.length; i++) {
|
|
if (this.TableParts[i] && this.TableParts[i].Ref && this.TableParts[i].Ref.r2 > maxTableRow) {
|
|
maxTableRow = this.TableParts[i].Ref.r2;
|
|
}
|
|
}
|
|
}
|
|
//TODO не учитываются настройки для всей строки
|
|
//по this.rowsData.indexB ориентироваться не могу, поскольку при undo в большинстве случаев он остаётся неизменным
|
|
this.nRowsCount = Math.max(maxTableRow, this.cellsByColRowsCount/*, this.rowsData && this.rowsData.indexB ? this.rowsData.indexB : 0*/);
|
|
};
|
|
Worksheet.prototype.fromXLSB = function(stream, type, tmp, aCellXfs, fInitCellAfterRead) {
|
|
stream.XlsbSkipRecord();//XLSB::rt_BEGIN_SHEET_DATA
|
|
|
|
var oldPos = -1;
|
|
while (oldPos !== stream.GetCurPos()) {
|
|
oldPos = stream.GetCurPos();
|
|
type = stream.XlsbReadRecordType();
|
|
if (AscCommonExcel.XLSB.rt_CELL_BLANK <= type && type <= AscCommonExcel.XLSB.rt_FMLA_ERROR) {
|
|
tmp.cell.clear();
|
|
tmp.formula.clean();
|
|
tmp.cell.fromXLSB(stream, type, tmp.row.index, aCellXfs, tmp);
|
|
fInitCellAfterRead(tmp);
|
|
}
|
|
else if (AscCommonExcel.XLSB.rt_ROW_HDR === type) {
|
|
tmp.row.clear();
|
|
tmp.row.fromXLSB(stream, aCellXfs);
|
|
tmp.row.saveContent();
|
|
tmp.ws.cellsByColRowsCount = Math.max(tmp.ws.cellsByColRowsCount, tmp.row.index + 1);
|
|
tmp.ws.nRowsCount = Math.max(tmp.ws.nRowsCount, tmp.ws.cellsByColRowsCount);
|
|
}
|
|
else if (AscCommonExcel.XLSB.rt_END_SHEET_DATA === type) {
|
|
stream.XlsbSkipRecord();
|
|
break;
|
|
}
|
|
else {
|
|
stream.XlsbSkipRecord();
|
|
}
|
|
}
|
|
};
|
|
|
|
//need recalculate formulas after change rows
|
|
Worksheet.prototype.needRecalFormulas = function(start, stop) {
|
|
//TODO в данном случае необходим пересчёт только тез формул, которые зависят от данных строк + те, которые
|
|
// меняют своё значение в зависимости от скрытия/раскрыватия строк
|
|
var res = false;
|
|
|
|
if(this.AutoFilter && this.AutoFilter.isApplyAutoFilter()) {
|
|
return true;
|
|
}
|
|
|
|
var tableParts = this.TableParts;
|
|
var tablePart;
|
|
for (var i = 0; i < tableParts.length; i++) {
|
|
tablePart = tableParts[i];
|
|
if (tablePart && tablePart.Ref && start >= tablePart.Ref.r1 && stop <= tablePart.Ref.r2) {
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getRowColColors = function (columnRange, byRow, notCheckOneColor) {
|
|
var ws = this;
|
|
var res = {text: true, colors: [], fontColors: [], date: false};
|
|
var alreadyAddColors = {}, alreadyAddFontColors = {};
|
|
|
|
var getAscColor = function (color) {
|
|
var ascColor = new Asc.asc_CColor();
|
|
ascColor.asc_putR(color.getR());
|
|
ascColor.asc_putG(color.getG());
|
|
ascColor.asc_putB(color.getB());
|
|
ascColor.asc_putA(color.getA());
|
|
|
|
return ascColor;
|
|
};
|
|
|
|
var addFontColorsToArray = function (fontColor) {
|
|
var rgb = fontColor && null !== fontColor ? fontColor.getRgb() : null;
|
|
if(rgb === 0) {
|
|
rgb = null;
|
|
}
|
|
var isDefaultFontColor = null === rgb;
|
|
|
|
if (true !== alreadyAddFontColors[rgb]) {
|
|
if (isDefaultFontColor) {
|
|
res.fontColors.push(null);
|
|
alreadyAddFontColors[null] = true;
|
|
} else {
|
|
var ascFontColor = getAscColor(fontColor);
|
|
res.fontColors.push(ascFontColor);
|
|
alreadyAddFontColors[rgb] = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
var addCellColorsToArray = function (color) {
|
|
var rgb = null !== color && color.fill && color.fill.bg() ? color.fill.bg().getRgb() : null;
|
|
var isDefaultCellColor = null === rgb;
|
|
|
|
if (true !== alreadyAddColors[rgb]) {
|
|
if (isDefaultCellColor) {
|
|
res.colors.push(null);
|
|
alreadyAddColors[null] = true;
|
|
} else {
|
|
var ascColor = getAscColor(color.fill.bg());
|
|
res.colors.push(ascColor);
|
|
alreadyAddColors[rgb] = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
//TODO automaticRange ?
|
|
var tempText = 0, tempDigit = 0, tempDate = 0;
|
|
var r1 = byRow ? columnRange.r1 : columnRange.r1;
|
|
var r2 = byRow ? columnRange.r1 : columnRange.r2;
|
|
var c1 = byRow ? columnRange.c1 : columnRange.c1;
|
|
var c2 = byRow ? columnRange.c2 : columnRange.c1;
|
|
ws.getRange3(r1, c1, r2, c2)._foreachNoEmpty(function(cell) {
|
|
//добавляем без цвета ячейку
|
|
if (!cell) {
|
|
if (true !== alreadyAddColors[null]) {
|
|
alreadyAddColors[null] = true;
|
|
res.colors.push(null);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (false === cell.isNullText()) {
|
|
var type = cell.getType();
|
|
|
|
if (type === window["AscCommon"].CellValueType.Number) {
|
|
if (cell.getNumFormat().isDateTimeFormat()) {
|
|
tempDate++;
|
|
} else {
|
|
tempDigit++;
|
|
}
|
|
} else {
|
|
tempText++;
|
|
}
|
|
}
|
|
|
|
//font colors
|
|
var multiText = cell.getValueMultiText();
|
|
var fontColor = null;
|
|
var xfs = cell.getCompiledStyleCustom(false, true, true);
|
|
if (null !== multiText) {
|
|
for (var j = 0; j < multiText.length; j++) {
|
|
fontColor = multiText[j].format ? multiText[j].format.getColor() : null;
|
|
if(null !== fontColor) {
|
|
addFontColorsToArray(fontColor);
|
|
} else {
|
|
fontColor = xfs && xfs.font ? xfs.font.getColor() : null;
|
|
addFontColorsToArray(fontColor);
|
|
}
|
|
}
|
|
} else {
|
|
fontColor = xfs && xfs.font ? xfs.font.getColor() : null;
|
|
addFontColorsToArray(fontColor);
|
|
}
|
|
|
|
//cell colors
|
|
addCellColorsToArray(xfs);
|
|
});
|
|
|
|
//если один элемент в массиве, не отправляем его в меню
|
|
if (res.colors.length === 1 && !notCheckOneColor) {
|
|
res.colors = [];
|
|
}
|
|
if (res.fontColors.length === 1 && !notCheckOneColor) {
|
|
res.fontColors = [];
|
|
}
|
|
|
|
if (tempDate > tempDigit && tempDate > tempText) {
|
|
res.date = true;
|
|
res.text = false;
|
|
} else {
|
|
res.text = tempDigit <= tempText;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.updateSortStateOffset = function (range, offset) {
|
|
if(!this.sortState) {
|
|
return;
|
|
}
|
|
var bAlreadyDel = false;
|
|
if (offset.row < 0 || offset.col < 0) {
|
|
//смотрим, не попал ли в выделение целиком
|
|
bAlreadyDel = this.deleteSortState(range);
|
|
}
|
|
if(!bAlreadyDel) {
|
|
var bboxShift = AscCommonExcel.shiftGetBBox(range, 0 !== offset.col);
|
|
this.sortState.shift(range, offset, this, true);
|
|
this.moveSortState(bboxShift, offset);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.deleteSortState = function (range) {
|
|
if(this.sortState && range.containsRange(this.sortState.Ref)) {
|
|
this._deleteSortState();
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Worksheet.prototype._deleteSortState = function () {
|
|
var oldSortState = this.sortState.clone();
|
|
this.sortState = null;
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoSortState, AscCH.historyitem_SortState_Add, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_SortState(oldSortState, null));
|
|
return true;
|
|
};
|
|
|
|
Worksheet.prototype.moveSortState = function (range, offset) {
|
|
if(this.sortState && range.containsRange(this.sortState.Ref)) {
|
|
this.sortState.setOffset(offset, this, true);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Worksheet.prototype.getDrawingDocument = function() {
|
|
if(this.workbook) {
|
|
return this.workbook.getDrawingDocument();
|
|
}
|
|
return null;
|
|
};
|
|
Worksheet.prototype.getActiveFunctionInfo = function (parser, parserResult, argNum, type, doNotCalcArgs) {
|
|
var t = this;
|
|
var calculateFormula = function (str) {
|
|
var _res = null;
|
|
if (str !== "") {
|
|
var _formulaParsedArg = new AscCommonExcel.parserFormula(str, /*formulaParsed.parent*/null, t);
|
|
var _parseResultArg = new AscCommonExcel.ParseResult([], []);
|
|
_formulaParsedArg.parse(true, true, _parseResultArg, true);
|
|
if (!_parseResultArg.error) {
|
|
_res = _formulaParsedArg.calculate();
|
|
}
|
|
}
|
|
return _res;
|
|
};
|
|
|
|
var convertFormulaResultByType = function (_res) {
|
|
if (type === undefined || type === null) {
|
|
return _res.toLocaleString();
|
|
}
|
|
|
|
//TODO если полная проверка, то выводим ошибки - если нет, то вовзращаем пустую строку
|
|
var result = "";
|
|
if (type === Asc.c_oAscFormulaArgumentType.number) {
|
|
_res = _res.tocNumber();
|
|
if (_res) {
|
|
result = _res.toLocaleString();
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
var _formulaParsed, _parseResult, valueForEdit;
|
|
if (!parser) {
|
|
var activeCell = this.selectionRange.activeCell;
|
|
var formulaParsed;
|
|
this.getCell3(activeCell.row, activeCell.col)._foreachNoEmpty(function (cell) {
|
|
if (cell.isFormula()) {
|
|
formulaParsed = cell.getFormulaParsed();
|
|
if (formulaParsed) {
|
|
valueForEdit = cell.getValueForEdit();
|
|
}
|
|
}
|
|
});
|
|
_formulaParsed = new AscCommonExcel.parserFormula(valueForEdit.substr(1), /*formulaParsed.parent*/null, this);
|
|
_parseResult = new AscCommonExcel.ParseResult([], []);
|
|
_formulaParsed.parse(true, true, _parseResult, true);
|
|
} else {
|
|
_formulaParsed = parser;
|
|
_parseResult = parserResult;
|
|
valueForEdit = "=" + parser.Formula;
|
|
}
|
|
|
|
var res, str, calcRes;
|
|
if (_formulaParsed && _parseResult.activeFunction && _parseResult.activeFunction.func) {
|
|
res = new AscCommonExcel.CFunctionInfo(_parseResult.activeFunction.func.name);
|
|
if (!_parseResult.error) {
|
|
var _parent = _formulaParsed.parent;
|
|
_formulaParsed.parent = null;
|
|
res.formulaResult = _formulaParsed.calculate().toLocaleString();
|
|
_formulaParsed.parent = _parent;
|
|
}
|
|
|
|
//asc_getFunctionResult
|
|
str = valueForEdit.substring(_parseResult.activeFunction.start + 1, _parseResult.activeFunction.end + 1);
|
|
calcRes = calculateFormula(str);
|
|
if (calcRes) {
|
|
res.functionResult = calcRes.toLocaleString();
|
|
}
|
|
|
|
res._cursorPos = _parseResult.cursorPos + 1;
|
|
var argPosArr = _parseResult.argPosArr;
|
|
if (argPosArr && argPosArr.length && true !== doNotCalcArgs){
|
|
for (var i = 0; i < argPosArr.length; i++) {
|
|
if (!res.argumentsValue) {
|
|
res.argumentsValue = [];
|
|
}
|
|
str = valueForEdit.substring(argPosArr[i].start, argPosArr[i].end);
|
|
res.argumentsValue.push(str);
|
|
if (str !== "") {
|
|
if (!res.argumentsResult) {
|
|
res.argumentsResult = [];
|
|
}
|
|
calcRes = calculateFormula(str);
|
|
if (calcRes) {
|
|
res.argumentsResult[i] = i === argNum ? convertFormulaResultByType(calcRes) : calcRes.toLocaleString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.isActiveCellFormula = function () {
|
|
var activeCell = this.selectionRange.activeCell;
|
|
var res;
|
|
this.getCell3(activeCell.row, activeCell.col)._foreachNoEmpty(function (cell) {
|
|
if (cell.isFormula()) {
|
|
res = true;
|
|
}
|
|
});
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.calculateWizardFormula = function (formula, type) {
|
|
let res = null, resultStr = null;
|
|
if (formula) {
|
|
let parser = new AscCommonExcel.parserFormula(formula, /*formulaParsed.parent*/null, this);
|
|
let parseResultArg = new AscCommonExcel.ParseResult([], []);
|
|
parser.parse(true, true, parseResultArg, true);
|
|
if (!parseResultArg.error) {
|
|
res = parser.calculate();
|
|
}
|
|
|
|
resultStr = "";
|
|
if (res) {
|
|
const maxArrayRowCount = 20;
|
|
const maxArrayColCount = 20;
|
|
//TODO рассчеты аргументов зависят от конкретных функций
|
|
//допустим, sum и acos - типа аргумента number, но результат для cellsRange3D разный
|
|
|
|
if (res.type === AscCommonExcel.cElementType.cell || res.type === AscCommonExcel.cElementType.cell3D) {
|
|
res = res.getValue();
|
|
}
|
|
|
|
//TODO если полная проверка, то выводим ошибки - если нет, то вовзращаем пустую строку
|
|
if (type === undefined || type === null || res.type === AscCommonExcel.cElementType.error) {
|
|
return {str: res.toLocaleString(), obj: res};
|
|
}
|
|
|
|
if (type === Asc.c_oAscFormulaArgumentType.number) {
|
|
//in most cases in ms array/range -> {1,2,..} if NUMBER type
|
|
if (res.type === AscCommonExcel.cElementType.array) {
|
|
resultStr = res.toLocaleString();
|
|
} else if (res.type === AscCommonExcel.cElementType.cellsRange || res.type === AscCommonExcel.cElementType.cellsRange3D) {
|
|
res = res.getFullArray(new AscCommonExcel.cNumber(0), maxArrayRowCount, maxArrayColCount);
|
|
if (res) {
|
|
resultStr = res.toLocaleString();
|
|
}
|
|
} else {
|
|
res = res.tocNumber();
|
|
if (res) {
|
|
resultStr = res.toLocaleString();
|
|
}
|
|
}
|
|
} else if (type === Asc.c_oAscFormulaArgumentType.text) {
|
|
if (res.type === AscCommonExcel.cElementType.array) {
|
|
res = res.getElementRowCol(0, 0);
|
|
res = res.tocString();
|
|
if (res) {
|
|
resultStr = '"' + res.toLocaleString() + '"';
|
|
}
|
|
} else if (res.type === AscCommonExcel.cElementType.cellsRange) {
|
|
resultStr = res.toLocaleString();
|
|
} else if (res.type !== AscCommonExcel.cElementType.cellsRange3D) {
|
|
res = res.tocString();
|
|
if (res) {
|
|
resultStr = '"' + res.toLocaleString() + '"';
|
|
}
|
|
}
|
|
} else if (type === Asc.c_oAscFormulaArgumentType.logical) {
|
|
if (res.type === AscCommonExcel.cElementType.cellsRange || res.type === AscCommonExcel.cElementType.cellsRange3D) {
|
|
res = res.getFullArray(new AscCommonExcel.cNumber(0), maxArrayRowCount, maxArrayColCount);
|
|
} else if (res.type !== AscCommonExcel.cElementType.array) {
|
|
res = res.tocBool();
|
|
}
|
|
if (res) {
|
|
resultStr = res.toLocaleString();
|
|
}
|
|
} else if (type === Asc.c_oAscFormulaArgumentType.any) {
|
|
if (res.type === AscCommonExcel.cElementType.array) {
|
|
res = res.getElementRowCol(0, 0);
|
|
res = res.tocString();
|
|
if (res) {
|
|
resultStr = res.toLocaleString();
|
|
}
|
|
} else if (res.type === AscCommonExcel.cElementType.cellsRange) {
|
|
resultStr = res.toLocaleString();
|
|
} else if (res.type === AscCommonExcel.cElementType.cellsRange3D) {
|
|
resultStr = res.toLocaleString();
|
|
} else {
|
|
res = res.tocString();
|
|
if (res) {
|
|
resultStr = '"' + res.toLocaleString() + '"';
|
|
}
|
|
}
|
|
} else if (type === Asc.c_oAscFormulaArgumentType.reference) {
|
|
if (res.type === AscCommonExcel.cElementType.array) {
|
|
resultStr = res.toLocaleString();
|
|
} else if (res.type === AscCommonExcel.cElementType.cellsRange || res.type === AscCommonExcel.cElementType.cellsRange3D) {
|
|
res = res.getFullArray(new AscCommonExcel.cNumber(0), maxArrayRowCount, maxArrayColCount);
|
|
if (res) {
|
|
resultStr = res.toLocaleString();
|
|
}
|
|
} else {
|
|
resultStr = res.toLocaleString();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return {str: resultStr, obj: res};
|
|
};
|
|
|
|
|
|
Worksheet.prototype.insertSlicer = function (name, obj_name, type, pivotTable, slicerCacheDefinition) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
//TODO недостаточно ли вместо всей данной длинной структуры использовать только tableId(name) и columnName?
|
|
var slicer = new window['Asc'].CT_slicer(this);
|
|
slicer.cacheDefinition = slicerCacheDefinition || null;
|
|
var isNewCache = slicer.init(name, obj_name, type, undefined, pivotTable);
|
|
this.aSlicers.push(slicer);
|
|
var oCache = slicer.getCacheDefinition();
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SlicerAdd, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_FromTo(null, slicer));
|
|
|
|
if (isNewCache) {
|
|
slicer.updateItemsWithNoData();
|
|
}
|
|
|
|
if (oCache) {
|
|
var _name = oCache.name;
|
|
var newDefName = new Asc.asc_CDefName(_name, "#N/A", null, Asc.c_oAscDefNameType.slicer);
|
|
this.workbook.editDefinesNames(null, newDefName);
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
return slicer;
|
|
};
|
|
|
|
Worksheet.prototype.deleteSlicer = function (name, doDelDefName) {
|
|
var res = false;
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
var slicerObj = this.getSlicerIndexByName(name);
|
|
if (null !== slicerObj) {
|
|
this.aSlicers.splice(slicerObj.index, 1);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SlicerDelete, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_FromTo(slicerObj.obj, null));
|
|
this.workbook.onSlicerDelete(name);
|
|
res = true;
|
|
if ((!this.workbook.bUndoChanges && !this.workbook.bRedoChanges) || doDelDefName)
|
|
{
|
|
var cache = slicerObj.obj.getCacheDefinition();
|
|
//удаляем именованный диапазон только если на данный кэш уже никто не ссылается
|
|
if (cache && null === this.workbook.getSlicersByCacheName(cache.name)) {
|
|
var defName = this.workbook.getDefinesNames(cache.name);
|
|
if (defName) {
|
|
this.workbook.delDefinesNames(defName.getAscCDefName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicerCachesBySourceName = function (name) {
|
|
var res = null
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i] && this.aSlicers[i].getSlicerCache();
|
|
if (cache && name === cache.sourceName) {
|
|
if (!res) {
|
|
res = [];
|
|
}
|
|
res.push(cache);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicersByCaption = function (name) {
|
|
var res = [];
|
|
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
if (this.aSlicers[i] && name === this.aSlicers[i].caption) {
|
|
res.push({obj: this.aSlicers[i], index: i});
|
|
}
|
|
}
|
|
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicersByCacheName = function (name) {
|
|
var res = [];
|
|
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i] && this.aSlicers[i].getSlicerCache();
|
|
if (cache && name === cache.name) {
|
|
res.push(this.aSlicers[i]);
|
|
}
|
|
}
|
|
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicerCacheByCacheName = function (name) {
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i] && this.aSlicers[i].getSlicerCache();
|
|
if (cache && name === cache.name) {
|
|
return cache;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicerByName = function (name) {
|
|
var res = null;
|
|
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
if (this.aSlicers[i] && name === this.aSlicers[i].name) {
|
|
res = this.aSlicers[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicerViewByName = function (name) {
|
|
var res = null;
|
|
for (var i = 0; i < this.Drawings.length; i++) {
|
|
res = this.Drawings[i].getSlicerViewByName(name);
|
|
if(res) {
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicerIndexByName = function (name) {
|
|
var res = null;
|
|
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
if (this.aSlicers[i] && name === this.aSlicers[i].name) {
|
|
res = {obj: this.aSlicers[i], index: i};
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicerCacheByName = function (name) {
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var cache = this.aSlicers[i] && this.aSlicers[i].getSlicerCache();
|
|
if (cache && name === cache.name) {
|
|
return cache;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicersByTableName = function (val) {
|
|
var res = [];
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
//пока сделал только для форматированных таблиц
|
|
var tableSlicerCache = this.aSlicers[i] && this.aSlicers[i].getTableSlicerCache();
|
|
if (tableSlicerCache && tableSlicerCache.tableId === val) {
|
|
res.push(this.aSlicers[i]);
|
|
}
|
|
}
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.getSlicersByTableColName = function (tableName, colName) {
|
|
var res = [];
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
//пока сделал только для форматированных таблиц
|
|
var tableSlicerCache = this.aSlicers[i] && this.aSlicers[i].getTableSlicerCache();
|
|
if (tableSlicerCache && tableSlicerCache.tableId === tableName && tableSlicerCache.column === colName) {
|
|
res.push(this.aSlicers[i]);
|
|
}
|
|
}
|
|
return res.length ? res : null;
|
|
};
|
|
Worksheet.prototype.handleDrawings = function (fCallback) {
|
|
for(var nIndex = 0; nIndex < this.Drawings.length; ++nIndex) {
|
|
this.Drawings[nIndex].handleObject(fCallback);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.changeTableColName = function (tableName, oldVal, newVal) {
|
|
if (this.workbook.bUndoChanges || this.workbook.bRedoChanges) {
|
|
return;
|
|
}
|
|
|
|
var slicers = this.getSlicersByTableColName(tableName, oldVal);
|
|
if (slicers) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
for (var i = 0; i < slicers.length; i++) {
|
|
slicers[i].setTableColName(oldVal, newVal);
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.changeTableName = function (oldVal, newVal) {
|
|
if (this.workbook.bUndoChanges || this.workbook.bRedoChanges) {
|
|
return;
|
|
}
|
|
|
|
var slicers = this.workbook.getSlicersByTableName(oldVal);
|
|
if (slicers) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
for (var i = 0; i < slicers.length; i++) {
|
|
slicers[i].setTableName(newVal);
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.setSlicerTableName = function (tableName, newTableName) {
|
|
//TODO history
|
|
for (var i = 0; i < this.aSlicers.length; i++) {
|
|
var tableSlicerCache = this.aSlicers[i].getTableSlicerCache();
|
|
if (tableSlicerCache && tableSlicerCache.tableId === tableName) {
|
|
tableSlicerCache.setTableName(newTableName);
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.onSlicerUpdate = function (sName) {
|
|
var bRet = false;
|
|
for(var i = 0; i < this.Drawings.length; ++i) {
|
|
bRet = bRet || this.Drawings[i].onSlicerUpdate(sName);
|
|
}
|
|
return bRet;
|
|
};
|
|
|
|
Worksheet.prototype.onSlicerDelete = function (sName) {
|
|
var bRet = false;
|
|
for(var i = 0; i < this.Drawings.length; ++i) {
|
|
bRet = bRet || this.Drawings[i].onSlicerDelete(sName);
|
|
}
|
|
return bRet;
|
|
};
|
|
Worksheet.prototype.onSlicerLock = function (sName, bLock) {
|
|
for(var i = 0; i < this.Drawings.length; ++i) {
|
|
this.Drawings[i].onSlicerLock(sName, bLock);
|
|
}
|
|
};
|
|
Worksheet.prototype.onSlicerChangeName = function (sName, sNewName) {
|
|
for(var i = 0; i < this.Drawings.length; ++i) {
|
|
this.Drawings[i].onSlicerChangeName(sName, sNewName);
|
|
}
|
|
};
|
|
Worksheet.prototype.onTimeSlicerDelete = function (sName) {
|
|
for(var i = 0; i < this.Drawings.length; ++i) {
|
|
this.Drawings[i].onTimeSlicerDelete(sName);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.deleteSlicersByTable = function (tableName) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
var slicers = this.workbook.getSlicersByTableName(tableName);
|
|
if (slicers) {
|
|
for (var i = 0; i < slicers.length; i++) {
|
|
this.deleteSlicer(slicers[i].name);
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
|
|
Worksheet.prototype.deleteSlicersByTableCol = function (tableName, colMap) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
for (var j in colMap) {
|
|
var slicers = this.getSlicersByTableColName(tableName, j);
|
|
if (slicers) {
|
|
for (var i = 0; i < slicers.length; i++) {
|
|
this.deleteSlicer(slicers[i].name);
|
|
}
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
|
|
Worksheet.prototype.changeSlicerCacheName = function (oldVal, newVal) {
|
|
if (this.workbook.bUndoChanges || this.workbook.bRedoChanges) {
|
|
return;
|
|
}
|
|
|
|
var slicers = this.getSlicersByCacheName(oldVal);
|
|
if (slicers) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
for (var i = 0; i < slicers.length; i++) {
|
|
slicers[i].setCacheName(newVal);
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.checkChangeTablesContent = function (arn) {
|
|
this.autoFilters.renameTableColumn(arn);
|
|
var tables = this.autoFilters.getTablesIntersectionRange(arn);
|
|
if (tables) {
|
|
for (var i = 0; i < tables.length; i++) {
|
|
this.workbook.slicersUpdateAfterChangeTable(tables[i].DisplayName);
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.updateSlicersByRange = function (range) {
|
|
var tables = this.autoFilters.getTablesIntersectionRange(range);
|
|
if (tables) {
|
|
for (var i = 0; i < tables.length; i++) {
|
|
this.workbook.slicersUpdateAfterChangeTable(tables[i].DisplayName);
|
|
}
|
|
}
|
|
var pivot = false;
|
|
if (pivot) {
|
|
|
|
}
|
|
};
|
|
|
|
|
|
Worksheet.prototype.getActiveNamedSheetViewId = function () {
|
|
return this.activeNamedSheetViewId;
|
|
};
|
|
|
|
Worksheet.prototype.setActiveNamedSheetView = function (id) {
|
|
this.activeNamedSheetViewId = id;
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_onChangeActiveNamedSheetView");
|
|
};
|
|
|
|
Worksheet.prototype.getNvsFilterByTableName = function (val, opt_name, viewId) {
|
|
var activeNamedSheetViewId;
|
|
if (viewId) {
|
|
activeNamedSheetViewId = viewId;
|
|
} else {
|
|
activeNamedSheetViewId = opt_name ? this.getIdNamedSheetViewByName(opt_name) : this.getActiveNamedSheetViewId();
|
|
}
|
|
|
|
if (activeNamedSheetViewId === null) {
|
|
return;
|
|
}
|
|
|
|
if (Asc.CT_NamedSheetView.prototype.getNsvFiltersByTableId) {
|
|
var sheetView = this.getNamedSheetViewById(activeNamedSheetViewId);
|
|
return sheetView ? sheetView.getNsvFiltersByTableId(val) : null;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getNamedSheetViewFilterColumns = function (val) {
|
|
var nsvFilter = this.getNvsFilterByTableName(val);
|
|
if (nsvFilter && nsvFilter.columnsFilter) {
|
|
return nsvFilter.columnsFilter;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.addNamedSheetView = function (sheetView, isDuplicate) {
|
|
|
|
if (!sheetView) {
|
|
sheetView = new Asc.CT_NamedSheetView();
|
|
sheetView.name = sheetView.generateName();
|
|
}
|
|
|
|
var _filter;
|
|
if (!isDuplicate) {
|
|
for (var i = 0; i < this.TableParts.length; i++) {
|
|
_filter = new Asc.CT_NsvFilter();
|
|
_filter.init(this.TableParts[i]);
|
|
sheetView.nsvFilters.push(_filter);
|
|
}
|
|
if (this.AutoFilter) {
|
|
_filter = new Asc.CT_NsvFilter();
|
|
_filter.init(this.AutoFilter);
|
|
sheetView.nsvFilters.push(_filter);
|
|
}
|
|
}
|
|
|
|
this.insertNamedSheetView(sheetView, true);
|
|
};
|
|
|
|
Worksheet.prototype.deleteNamedSheetViews = function (arr, doNotAddHistory) {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews && arr) {
|
|
var diff = 0;
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (!arr[i]) {
|
|
continue;
|
|
}
|
|
var index = this.getIndexNamedSheetViewByName(arr[i].name);
|
|
var namedSheetView = this.getNamedSheetViewByName(arr[i].name);
|
|
if (namedSheetView.Id === this.getActiveNamedSheetViewId()) {
|
|
if (this.workbook.oApi.asc_setActiveNamedSheetView) {
|
|
this.workbook.oApi.asc_setActiveNamedSheetView(null);
|
|
}
|
|
}
|
|
|
|
if (!doNotAddHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SheetViewDelete, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_NamedSheetViewRedo(namedSheetView.Get_Id(), namedSheetView, null));
|
|
}
|
|
|
|
namedSheetViews.splice(index - diff, 1);
|
|
diff++;
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.insertNamedSheetView = function (sheetView, addToHistory) {
|
|
sheetView.ws = this;
|
|
this.aNamedSheetViews.push(sheetView);
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SheetViewAdd, this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_BinaryWrapper(sheetView));
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getNamedSheetViews = function () {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews) {
|
|
var res = [], ascSheetView;
|
|
for (var i = 0; i < namedSheetViews.length; i++) {
|
|
ascSheetView = namedSheetViews[i];
|
|
ascSheetView._isActive = ascSheetView.Id === this.getActiveNamedSheetViewId();
|
|
res.push(ascSheetView);
|
|
}
|
|
return res;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getNamedSheetViewByName = function (name) {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews) {
|
|
for (var i = 0; i < namedSheetViews.length; i++) {
|
|
if (name === namedSheetViews[i].name) {
|
|
return namedSheetViews[i];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getNamedSheetViewById = function (id) {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews) {
|
|
for (var i = 0; i < namedSheetViews.length; i++) {
|
|
if (id === namedSheetViews[i].Get_Id()) {
|
|
return namedSheetViews[i];
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getIndexNamedSheetViewByName = function (name) {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews) {
|
|
for (var i = 0; i < namedSheetViews.length; i++) {
|
|
if (name === namedSheetViews[i].name) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getIdNamedSheetViewByName = function (name) {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews) {
|
|
for (var i = 0; i < namedSheetViews.length; i++) {
|
|
if (name === namedSheetViews[i].name) {
|
|
return namedSheetViews[i].Id;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.forEachView = function (actionView) {
|
|
var namedSheetViews = this.aNamedSheetViews;
|
|
if (namedSheetViews) {
|
|
var activeId = this.getActiveNamedSheetViewId();
|
|
for (var i = 0; i < namedSheetViews.length; i++) {
|
|
actionView(namedSheetViews[i], activeId === namedSheetViews[i].Id);
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.checkCorrectTables = function () {
|
|
for (let i = 0; i < this.TableParts.length; ++i) {
|
|
let table = this.TableParts[i];
|
|
if (table.isHeaderRow()) {
|
|
|
|
this.workbook.dependencyFormulas.lockRecal();
|
|
for (let j = 0; j < table.TableColumns.length; j++) {
|
|
let tableColName = table.TableColumns[j].getTableColumnName();
|
|
this._getCell(table.Ref.r1, table.Ref.c1 + j, function(cell) {
|
|
let valueData = cell.getValueData();
|
|
let val = valueData && valueData.value && valueData.value.text;
|
|
if (val !== tableColName){
|
|
cell.setValueData(
|
|
new AscCommonExcel.UndoRedoData_CellValueData(null, new AscCommonExcel.CCellValue({
|
|
text: tableColName,
|
|
type: CellValueType.String
|
|
})));
|
|
}
|
|
});
|
|
}
|
|
this.workbook.dependencyFormulas.unlockRecal(true);
|
|
|
|
if (table.TableColumns.length < (table.Ref.c2 - table.Ref.c1 + 1)) {
|
|
table.Ref.c2 = table.Ref.c1 + table.TableColumns.length - 1;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getDataValidationProps = function (doExtend, ranges) {
|
|
var _selection = ranges ? ranges : this.getSelection().ranges;
|
|
|
|
if (!this.dataValidations) {
|
|
var newDataValidation = new window['AscCommonExcel'].CDataValidation();
|
|
newDataValidation.showErrorMessage = true;
|
|
newDataValidation.showInputMessage = true;
|
|
newDataValidation.allowBlank = true;
|
|
return newDataValidation;
|
|
} else {
|
|
return this.dataValidations.getProps(_selection, doExtend, this);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.setDataValidationProps = function (props) {
|
|
var _selection = this.getSelection();
|
|
|
|
if (!this.dataValidations) {
|
|
this.dataValidations = new window['AscCommonExcel'].CDataValidations();
|
|
}
|
|
|
|
this.dataValidations.setProps(this, _selection.ranges, props);
|
|
};
|
|
|
|
Worksheet.prototype.addDataValidation = function (dataValidation, addToHistory) {
|
|
if (!this.dataValidations) {
|
|
this.dataValidations = new window['AscCommonExcel'].CDataValidations();
|
|
}
|
|
this.dataValidations.add(this, dataValidation, addToHistory);
|
|
};
|
|
|
|
Worksheet.prototype.deleteDataValidationById = function (id) {
|
|
if (this.dataValidations) {
|
|
this.dataValidations.delete(this, id);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getDataValidationById = function (id) {
|
|
if (this.dataValidations) {
|
|
return this.dataValidations.getById(id);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.shiftDataValidation = function (bInsert, operType, updateRange, addToHistory) {
|
|
if (this.dataValidations) {
|
|
this.dataValidations.shift(this, bInsert, operType, updateRange, addToHistory);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.clearDataValidation = function (ranges, addToHistory) {
|
|
if (this.dataValidations) {
|
|
this.dataValidations.clear(this, ranges, addToHistory);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype._moveDataValidation = function (oBBoxFrom, oBBoxTo, copyRange, offset, wsTo) {
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (false === this.workbook.bUndoChanges && false === this.workbook.bRedoChanges) {
|
|
wsTo.clearDataValidation([oBBoxTo], true);
|
|
|
|
if (this === wsTo) {
|
|
if (this.dataValidations) {
|
|
this.dataValidations.move(this, oBBoxFrom, oBBoxTo, copyRange, offset);
|
|
}
|
|
} else {
|
|
var aDataValidations = this._getCopyDataValidationByRange(oBBoxFrom, offset);
|
|
if (aDataValidations) {
|
|
if (!copyRange) {
|
|
this.clearDataValidation([oBBoxFrom], true);
|
|
}
|
|
|
|
//далее необходимо создать новые объекты на новом листе
|
|
for (var i = 0; i < aDataValidations.length; i++) {
|
|
wsTo.addDataValidation(aDataValidations[i], true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype._getCopyDataValidationByRange = function (range, offset) {
|
|
if (this.dataValidations) {
|
|
return this.dataValidations.getCopyByRange(range, offset);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
|
|
Worksheet.prototype.setCFRule = function (val) {
|
|
if (!val) {
|
|
return;
|
|
}
|
|
var changedRule = this.getCFRuleById(val.id);
|
|
if (changedRule) {
|
|
this.changeCFRule(changedRule, val, true);
|
|
} else {
|
|
this.addCFRule(val, true);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getCFRuleById = function (id) {
|
|
if (this.isConditionalFormattingRules()) {
|
|
return this.aConditionalFormattingRules[id];
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.isConditionalFormattingRules = function () {
|
|
return this.aConditionalFormattingRules != null;
|
|
};
|
|
|
|
Worksheet.prototype.getConditionalFormattingRules = function () {
|
|
return this.aConditionalFormattingRules;
|
|
};
|
|
|
|
Worksheet.prototype.addConditionalFormattingRule = function (rule) {
|
|
if (!this.isConditionalFormattingRules()) {
|
|
this.aConditionalFormattingRules = {};
|
|
}
|
|
this.aConditionalFormattingRules[rule.id] = rule;
|
|
};
|
|
|
|
Worksheet.prototype.changeCFRule = function (from, to, addToHistory) {
|
|
if (!from) {
|
|
return;
|
|
}
|
|
|
|
var updateRange;
|
|
if (from) {
|
|
updateRange = from.ranges;
|
|
}
|
|
if (to) {
|
|
if (updateRange) {
|
|
updateRange = updateRange.concat(to.ranges);
|
|
} else {
|
|
updateRange = to.ranges;
|
|
}
|
|
}
|
|
if (updateRange) {
|
|
this.setDirtyConditionalFormatting(new AscCommonExcel.MultiplyRange(updateRange));
|
|
}
|
|
|
|
to.recalcInterfaceFormula(this);
|
|
from.set(to, addToHistory, this);
|
|
};
|
|
|
|
Worksheet.prototype.addCFRule = function (val, addToHistory) {
|
|
if (!val) {
|
|
return;
|
|
}
|
|
|
|
if (!val.ranges) {
|
|
val.ranges = [];
|
|
for (var i = 0; i < this.selectionRange.ranges.length; i++) {
|
|
val.ranges.push(this.selectionRange.ranges[i].clone());
|
|
}
|
|
}
|
|
|
|
|
|
val.recalcInterfaceFormula(this);
|
|
this.addConditionalFormattingRule(val);
|
|
this.cleanConditionalFormattingRangeIterator();
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_CFRuleAdd, this.getId(), val.getUnionRange(), new AscCommonExcel.UndoRedoData_CF(val.id, null, val.clone ? val.clone() : val));
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.tryClearCFRule = function (rule, ranges) {
|
|
if (!rule) {
|
|
return;
|
|
}
|
|
|
|
var isDel = false;
|
|
if (ranges) {
|
|
var _newRanges = [];
|
|
|
|
var ruleRanges = rule.ranges;
|
|
for (var i = 0; i < ruleRanges.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].intersection(tempRanges[k]) ? ranges[j].difference(tempRanges[k]) : tempRanges[k]);
|
|
}
|
|
tempRanges = tempRanges2;
|
|
} else {
|
|
tempRanges = ranges[j].intersection(ruleRanges[i]) ? ranges[j].difference(ruleRanges[i]) : ruleRanges[i];
|
|
}
|
|
}
|
|
_newRanges = _newRanges.concat(tempRanges);
|
|
}
|
|
|
|
if (!_newRanges.length) {
|
|
this.deleteCFRule(rule.id, true);
|
|
isDel = true;
|
|
} else {
|
|
var newRule = rule.clone();
|
|
newRule.ranges = _newRanges;
|
|
this.changeCFRule(rule, newRule, true);
|
|
}
|
|
} else {
|
|
this.deleteCFRule(rule.id, true);
|
|
isDel = true;
|
|
}
|
|
|
|
return isDel;
|
|
};
|
|
|
|
Worksheet.prototype.deleteCFRule = function (id, addToHistory) {
|
|
let oRule = this.getCFRuleById(id);
|
|
if (oRule) {
|
|
delete this.aConditionalFormattingRules[id];
|
|
this.cleanConditionalFormattingRangeIterator();
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_CFRuleDelete, this.getId(), oRule.getUnionRange(),
|
|
new AscCommonExcel.UndoRedoData_CF(id, oRule));
|
|
}
|
|
if (oRule.ranges) {
|
|
this.setDirtyConditionalFormatting(new AscCommonExcel.MultiplyRange(oRule.ranges));
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.generateCFRuleFromPreset = function (presetId) {
|
|
if (!presetId || !presetId.length) {
|
|
return null;
|
|
}
|
|
|
|
var oRule = new AscCommonExcel.CConditionalFormattingRule();
|
|
oRule.applyPreset(presetId);
|
|
return oRule;
|
|
};
|
|
|
|
Worksheet.prototype.updateConditionalFormattingOffset = function (range, offset) {
|
|
let t = this;
|
|
if (offset.row < 0 || offset.col < 0) {
|
|
this.forEachConditionalFormattingRules(function (val) {
|
|
if (val.containsIntoRange(range)) {
|
|
t.deleteCFRule(val.id, true);
|
|
}
|
|
});
|
|
}
|
|
this.setConditionalFormattingOffset(range, offset);
|
|
};
|
|
Worksheet.prototype.setConditionalFormattingOffset = function (range, offset) {
|
|
let t = this;
|
|
this.forEachConditionalFormattingRules(function (oRule) {
|
|
oRule.setOffset(offset, range, t, true);
|
|
});
|
|
};
|
|
Worksheet.prototype.moveConditionalFormatting = function (oBBoxFrom, oBBoxTo, copyRange, offset, wsTo, wsFrom, bTransposeTo) {
|
|
var t = this;
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (false === this.workbook.bUndoChanges && false === this.workbook.bRedoChanges) {
|
|
//чистим ту область, куда переносим
|
|
wsTo.clearConditionalFormattingRulesByRanges([oBBoxTo], oBBoxFrom);
|
|
|
|
if (!wsFrom) {
|
|
wsFrom = this;
|
|
}
|
|
wsFrom.forEachConditionalFormattingRules(function (_rule) {
|
|
//если клонируем - то добавляем новое правило со смещенным диапазоном пересечения
|
|
//если нет + если в пределах одного листа - меняем диапазона у текущего правила
|
|
//если на другой лист - меняем диапазон у текущего правила + создаём новое со смещенным диапазоном пересечения
|
|
|
|
var isChanged = null;
|
|
var ruleRanges = _rule.ranges;
|
|
var constantPart, movePart;
|
|
var _moveRanges = [];
|
|
var _constantRanges = [];
|
|
for (var i = 0; i < ruleRanges.length; i++) {
|
|
movePart = ruleRanges[i].intersection(oBBoxFrom);
|
|
if (movePart) {
|
|
if (!copyRange) {
|
|
constantPart = oBBoxFrom.difference(ruleRanges[i]);
|
|
_constantRanges = _constantRanges.concat(constantPart);
|
|
}
|
|
if (bTransposeTo) {
|
|
movePart = movePart.transpose(oBBoxFrom.c1, oBBoxFrom.r1);
|
|
}
|
|
movePart.setOffset(offset);
|
|
_moveRanges.push(movePart);
|
|
isChanged = true;
|
|
} else if (!copyRange) {
|
|
_constantRanges.push(ruleRanges[i]);
|
|
}
|
|
}
|
|
if (isChanged) {
|
|
//в случае клонирования фрагмента - создаём новое правило
|
|
var _newRule;
|
|
if (copyRange) {
|
|
_newRule = _rule.clone();
|
|
_newRule.ranges = _moveRanges;
|
|
wsTo.addCFRule(_newRule, true);
|
|
} else {
|
|
if (t !== wsTo) {
|
|
if (_moveRanges.length) {
|
|
_newRule = _rule.clone();
|
|
_newRule.ranges = _moveRanges;
|
|
wsTo.addCFRule(_newRule, true);
|
|
}
|
|
if (_constantRanges.length) {
|
|
_rule.setLocation(_constantRanges, t, true);
|
|
}
|
|
} else {
|
|
_rule.setLocation(_constantRanges.concat(_moveRanges), t, true);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
wsTo && wsTo.forEachConditionalFormattingRules(function (_rule) {
|
|
_rule.updateFormulas(wsTo);
|
|
});
|
|
wsFrom && wsFrom.forEachConditionalFormattingRules(function (_rule) {
|
|
_rule.updateFormulas(wsFrom);
|
|
});
|
|
};
|
|
|
|
Worksheet.prototype.clearConditionalFormattingRulesByRanges = function (ranges, exceptionRange) {
|
|
let t = this;
|
|
this.forEachConditionalFormattingRules(function (oRule) {
|
|
var isExcept = exceptionRange && oRule.getIntersections(exceptionRange);
|
|
if (!isExcept) {
|
|
t.tryClearCFRule(oRule, ranges);
|
|
}
|
|
});
|
|
};
|
|
|
|
Worksheet.prototype.forEachConditionalFormattingRules = function (callback) {
|
|
if (!this.isConditionalFormattingRules()) {
|
|
return;
|
|
}
|
|
for (let i in this.aConditionalFormattingRules) {
|
|
if (callback(this.aConditionalFormattingRules[i], i)) {
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.cleanConditionalFormattingRangeIterator = function() {
|
|
this.conditionalFormattingRangeIterator = null;
|
|
};
|
|
Worksheet.prototype.getConditionalFormattingRangeIterator = function() {
|
|
if (!this.conditionalFormattingRangeIterator) {
|
|
let aRules = [];
|
|
if (this.isConditionalFormattingRules()) {
|
|
this.forEachConditionalFormattingRules(function (val) {
|
|
aRules.push(val);
|
|
})
|
|
}
|
|
aRules.sort(function(v1, v2) {
|
|
return v2.priority - v1.priority;
|
|
});
|
|
this.conditionalFormattingRangeIterator = new AscCommon.RangeTopBottomIterator();
|
|
this.conditionalFormattingRangeIterator.init(aRules, function(rule) {
|
|
return rule.ranges || [];
|
|
});
|
|
}
|
|
return this.conditionalFormattingRangeIterator;
|
|
};
|
|
Worksheet.prototype.updateTopLeftCell = function(range) {
|
|
this.setTopLeftCell(this.generateTopLeftCellFromRange(range), true);
|
|
};
|
|
Worksheet.prototype.generateTopLeftCellFromRange = function(range) {
|
|
if (!range) {
|
|
return null;
|
|
}
|
|
|
|
//todo закрепленные области
|
|
var newVal;
|
|
if (range.c1 === 0 && range.r1 === 0) {
|
|
newVal = null;
|
|
} else {
|
|
var topLeftFrozenCell = this.sheetViews[0] && this.sheetViews[0].pane && this.sheetViews[0].pane.topLeftFrozenCell;
|
|
if (topLeftFrozenCell && topLeftFrozenCell.col > 1 && topLeftFrozenCell.row > 1) {
|
|
newVal = null;
|
|
} else {
|
|
newVal = new Asc.Range(0, 0, 0, 0);
|
|
if (!topLeftFrozenCell || topLeftFrozenCell.col <= 1) {
|
|
newVal.c1 = newVal.c2 = range.c1;
|
|
}
|
|
if (!topLeftFrozenCell || topLeftFrozenCell.row <= 1) {
|
|
newVal.r1 = newVal.r2 = range.r1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return newVal;
|
|
};
|
|
Worksheet.prototype.setTopLeftCell = function(val, addToHistory) {
|
|
var view = this.sheetViews[0];
|
|
|
|
if (!view) {
|
|
return;
|
|
}
|
|
|
|
if ((!val && view.topLeftCell) || (val && !view.topLeftCell) || (val && view.topLeftCell && !val.isEqual(view.topLeftCell))) {
|
|
var oldValue = view.topLeftCell ? view.topLeftCell.clone() : null;
|
|
view.topLeftCell = val;
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetTopLeftCell,
|
|
this.getId(), null, new UndoRedoData_FromTo(oldValue ? new UndoRedoData_BBox(oldValue) : oldValue, val ? new UndoRedoData_BBox(val) : val));
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getTopLeftCell = function() {
|
|
var view = this.sheetViews && this.sheetViews[0];
|
|
return view && view.topLeftCell;
|
|
};
|
|
|
|
Worksheet.prototype.setCustomSort = function(props, obj, doNotSortRange, cellCommentator, opt_range) {
|
|
//формируем sortState из настроек
|
|
var t = this;
|
|
var selection = opt_range ? opt_range : this.selectionRange.getLast();
|
|
var sortState = new AscCommonExcel.SortState();
|
|
|
|
//? activeRange
|
|
sortState.Ref = new Asc.Range(selection.c1, selection.r1, selection.c2, selection.r2);
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
var columnSort = props.columnSort;
|
|
sortState.ColumnSort = !columnSort;
|
|
sortState.CaseSensitive = props.caseSensitive;
|
|
for(var i = 0; i < props.levels.length; i++) {
|
|
var sortCondition = new AscCommonExcel.SortCondition();
|
|
var level = props.levels[i];
|
|
var r1 = columnSort ? selection.r1 : level.index + selection.r1;
|
|
var c1 = columnSort ? selection.c1 + level.index : selection.c1;
|
|
var r2 = columnSort ? selection.r2 : level.index + selection.r1;
|
|
var c2 = columnSort ? selection.c1 + level.index : selection.c2;
|
|
sortCondition.Ref = new Asc.Range(c1, r1, c2, r2);
|
|
sortCondition.ConditionSortBy = null;
|
|
sortCondition.ConditionDescending = Asc.c_oAscSortOptions.Descending === level.descending;
|
|
|
|
var conditionSortBy = level.sortBy;
|
|
var sortColor = null, newDxf, isRgbColor;
|
|
switch (conditionSortBy) {
|
|
case Asc.c_oAscSortOptions.ByColorFill: {
|
|
sortCondition.ConditionSortBy = Asc.ESortBy.sortbyCellColor;
|
|
sortColor = level.color;
|
|
isRgbColor = sortColor && sortColor.getType && sortColor.getType() === AscCommonExcel.UndoRedoDataTypes.RgbColor;
|
|
sortColor = sortColor && !isRgbColor ? new AscCommonExcel.RgbColor((sortColor.asc_getR() << 16) + (sortColor.asc_getG() << 8) + sortColor.asc_getB()) : null;
|
|
|
|
newDxf = new AscCommonExcel.CellXfs();
|
|
newDxf.fill = new AscCommonExcel.Fill();
|
|
newDxf.fill.fromColor(sortColor);
|
|
|
|
break;
|
|
}
|
|
case Asc.c_oAscSortOptions.ByColorFont: {
|
|
sortCondition.ConditionSortBy = Asc.ESortBy.sortbyFontColor;
|
|
sortColor = level.color;
|
|
isRgbColor = sortColor && sortColor.getType && sortColor.getType() === AscCommonExcel.UndoRedoDataTypes.RgbColor;
|
|
sortColor = sortColor && !isRgbColor ? new AscCommonExcel.RgbColor((sortColor.asc_getR() << 16) + (sortColor.asc_getG() << 8) + sortColor.asc_getB()) : null;
|
|
|
|
newDxf = new AscCommonExcel.CellXfs();
|
|
newDxf.font = new AscCommonExcel.Font();
|
|
newDxf.font.setColor(sortColor);
|
|
|
|
break;
|
|
}
|
|
case Asc.c_oAscSortOptions.ByIcon: {
|
|
sortCondition.ConditionSortBy = Asc.ESortBy.sortbyIcon;
|
|
break;
|
|
}
|
|
default: {
|
|
sortCondition.ConditionSortBy = Asc.ESortBy.sortbyValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(newDxf) {
|
|
sortCondition.dxf = AscCommonExcel.g_StyleCache.addXf(newDxf);
|
|
}
|
|
|
|
|
|
if(!sortState.SortConditions) {
|
|
sortState.SortConditions = [];
|
|
}
|
|
|
|
sortState.SortConditions.push(sortCondition);
|
|
}
|
|
|
|
if(obj) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoSortState, AscCH.historyitem_SortState_Add, t.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_SortState(obj.sortState ? obj.sortState.clone() : null, sortState ? sortState.clone() : null, true, obj.DisplayName));
|
|
|
|
obj.SortState = sortState;
|
|
} else {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoSortState, AscCH.historyitem_SortState_Add, t.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_SortState(t.sortState ? t.sortState.clone() : null, sortState ? sortState.clone() : null));
|
|
|
|
sortState._hasHeaders = props.hasHeaders;
|
|
t.sortState = sortState;
|
|
}
|
|
|
|
if(!doNotSortRange) {
|
|
var range = t.getRange3(selection.r1, selection.c1, selection.r2, selection.c2);
|
|
var oSort = t._doSort(range, null, null, null, null, !columnSort, sortState);
|
|
if (cellCommentator) {
|
|
cellCommentator.sortComments(oSort);
|
|
}
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
|
|
Worksheet.prototype._doSort = function (range, nOption, nStartRowCol, sortColor, opt_guessHeader, opt_by_row, opt_custom_sort) {
|
|
var res;
|
|
|
|
var bordersArr = [];
|
|
range._foreachNoEmpty(function(cell, row, col) {
|
|
var style = cell ? cell.getStyle() : null;
|
|
if(style && style.border) {
|
|
if(!bordersArr[row]) {
|
|
bordersArr[row] = [];
|
|
}
|
|
bordersArr[row][col] = style.border;
|
|
cell.setBorder(null);
|
|
}
|
|
});
|
|
res = range.sort(nOption, nStartRowCol, sortColor, opt_guessHeader, opt_by_row, opt_custom_sort);
|
|
for(var i = 0; i < bordersArr.length; i++) {
|
|
if(bordersArr[i]) {
|
|
for(var j = 0; j < bordersArr[i].length; j++) {
|
|
if(bordersArr[i][j]) {
|
|
var curBorder = bordersArr[i][j];
|
|
this._getCell(i, j, function(cell) {
|
|
cell.setBorder(curBorder);
|
|
});
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getIntersectionRules = function (range) {
|
|
var t = this;
|
|
var res = [];
|
|
this.forEachConditionalFormattingRules(function (_rule) {
|
|
var changedRanges = _rule.getIntersections(range);
|
|
if (changedRanges) {
|
|
res.push({ranges: changedRanges, id: _rule.id});
|
|
}
|
|
});
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.getRuleById = function (id) {
|
|
var t = this;
|
|
var res = null;
|
|
this.forEachConditionalFormattingRules(function (_rule, index) {
|
|
if (_rule.id === id) {
|
|
res = {data: _rule, index: index};
|
|
return true;
|
|
}
|
|
});
|
|
return res;
|
|
};
|
|
|
|
|
|
Worksheet.prototype.setProtectedSheet = function (props, addToHistory) {
|
|
if (!this.sheetProtection) {
|
|
this.sheetProtection = new window["Asc"].CSheetProtection();
|
|
this.sheetProtection.setDefaultInterface();
|
|
}
|
|
this.cleanTempProtectedRanges();
|
|
this.sheetProtection.set(props, addToHistory, this);
|
|
if (this.sheetProtection.isDefault()) {
|
|
this.sheetProtection = null;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Worksheet.prototype.cleanTempProtectedRanges = function () {
|
|
if (this.aProtectedRanges && this.aProtectedRanges.length) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
this.aProtectedRanges[i].cleanTemp();
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getSheetProtection = function (type) {
|
|
var res = false;
|
|
|
|
if (this.sheetProtection && this.sheetProtection.getSheet()) {
|
|
//если тип не определен возвращаем защищен лист или нет
|
|
res = true;
|
|
switch (type) {
|
|
case Asc.c_oAscSheetProtectType.objects:
|
|
res = this.sheetProtection.getObjects();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.scenarios:
|
|
res = this.sheetProtection.getScenarios();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.formatCells:
|
|
res = this.sheetProtection.getFormatCells();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.formatColumns:
|
|
res = this.sheetProtection.getFormatColumns();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.formatRows:
|
|
res = this.sheetProtection.getFormatRows();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.insertColumns:
|
|
res = this.sheetProtection.getInsertColumns();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.insertRows:
|
|
res = this.sheetProtection.getInsertRows();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.insertHyperlinks:
|
|
res = this.sheetProtection.getInsertHyperlinks();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.deleteColumns:
|
|
res = this.sheetProtection.getDeleteColumns();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.deleteRows:
|
|
res = this.sheetProtection.getDeleteRows();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.selectLockedCells:
|
|
res = this.sheetProtection.getSelectLockedCells();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.sort:
|
|
res = this.sheetProtection.getSort();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.autoFilter:
|
|
res = this.sheetProtection.getAutoFilter();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.pivotTables:
|
|
res = this.sheetProtection.getPivotTables();
|
|
break;
|
|
case Asc.c_oAscSheetProtectType.selectUnlockedCells:
|
|
res = this.sheetProtection.getSelectUnlockedCells();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getLockedCell = function (c, r) {
|
|
var cellTo = this.getCell3(r, c);
|
|
if (cellTo) {
|
|
var cellxfs = cellTo.getXfs(false);
|
|
return cellxfs && cellxfs.asc_getLocked();
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getUnlockedCellInRange = function (range) {
|
|
if (!range) {
|
|
range = new Asc.Range(0, 0, gc_nMaxCol0, gc_nMaxRow0);
|
|
}
|
|
var res = null;
|
|
this.getRange3(range.r1, range.c1, range.r2, range.c2)._foreachNoEmpty(function(cell) {
|
|
if (cell) {
|
|
var cellxfs = cell.xfs;
|
|
if (cellxfs && !cellxfs.asc_getLocked()) {
|
|
res = cell;
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.protectedRangesContains = function (c, r) {
|
|
var res = [];
|
|
if (this.aProtectedRanges && this.aProtectedRanges.length) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (this.aProtectedRanges[i].contains(c, r)) {
|
|
res.push(this.aProtectedRanges[i]);
|
|
}
|
|
}
|
|
}
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.protectedRangesContainsRanges = function (ranges) {
|
|
for (var i = 0; i < ranges.length; i++) {
|
|
if (!this.protectedRangesContainsRange(ranges[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Worksheet.prototype.protectedRangesContainsRange = function (range, ignoreWithoutPassword) {
|
|
var res = [];
|
|
if (this.aProtectedRanges && this.aProtectedRanges.length) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (this.aProtectedRanges[i].containsRange(range)) {
|
|
var isPassword = this.aProtectedRanges[i].asc_isPassword();
|
|
if (!ignoreWithoutPassword || (ignoreWithoutPassword && isPassword && !this.aProtectedRanges[i].isUserEnteredPassword())) {
|
|
res.push(this.aProtectedRanges[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.checkProtectedRangesPassword = function (val, data, callback) {
|
|
//здесь првоеряем в тч при попытке ввода в ячейку
|
|
var t = this;
|
|
if (this.aProtectedRanges && this.aProtectedRanges.length) {
|
|
var aCheckHash = [];
|
|
var checkRanges = [];
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (!this.aProtectedRanges[i].contains(data.col, data.row)) {
|
|
continue;
|
|
}
|
|
if (!this.aProtectedRanges[i].asc_isPassword() || this.aProtectedRanges[i]._isEnterPassword) {
|
|
callback && callback(true);
|
|
return;
|
|
} else if (this.aProtectedRanges[i].asc_isPassword()) {
|
|
checkRanges.push(this.aProtectedRanges[i]);
|
|
aCheckHash.push({
|
|
password: val,
|
|
salt: this.aProtectedRanges[i].saltValue,
|
|
spinCount: this.aProtectedRanges[i].spinCount,
|
|
alg: AscCommon.fromModelAlgorithmName(this.aProtectedRanges[i].algorithmName)
|
|
});
|
|
}
|
|
}
|
|
if (aCheckHash && aCheckHash.length) {
|
|
AscCommon.calculateProtectHash(aCheckHash, function (aHash) {
|
|
for (var i = 0; i < aHash.length; i++) {
|
|
if (aHash[i] === checkRanges[i].hashValue) {
|
|
checkRanges[i]._isEnterPassword = true;
|
|
callback && callback(true);
|
|
return;
|
|
}
|
|
}
|
|
callback && callback(false);
|
|
});
|
|
} else {
|
|
callback && callback(true);
|
|
}
|
|
} else {
|
|
callback && callback(true);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.checkProtectedRangeName = function (name) {
|
|
var res = c_oAscDefinedNameReason.OK;
|
|
//TODO пересмотреть проверку на rx_defName
|
|
if (!AscCommon.rx_protectedRangeName.test(name.toLowerCase()) || name.length > g_nDefNameMaxLength) {
|
|
return c_oAscDefinedNameReason.WrongName;
|
|
}
|
|
|
|
var pR = this.getProtectedRangeByName(name);
|
|
if (pR) {
|
|
res = c_oAscDefinedNameReason.Existed;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.isIntersectLockedRanges = function (ranges) {
|
|
for (var i = 0; i < ranges.length; i++) {
|
|
if (this.isLockedRange(ranges[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Worksheet.prototype.isLockedRange = function (range) {
|
|
let oRange = this.getRange3(range.r1, range.c1, range.r2, range.c2);
|
|
let res = true;
|
|
|
|
let _getLocked = function (_xfs) {
|
|
let _res = null;
|
|
if (_xfs/* && _xfs.applyProtection*/) {
|
|
_res = true;//null/true
|
|
if (_xfs.getLocked() === false) {
|
|
_res = false;
|
|
}
|
|
}
|
|
return _res;
|
|
};
|
|
|
|
//1. init default value
|
|
//all cells
|
|
if (null != this.oAllCol && this.oAllCol.xfs && this.oAllCol.xfs.locked != null) {
|
|
res = _getLocked(this.oAllCol.xfs);
|
|
}
|
|
|
|
//all selected rows
|
|
let unLockedRowIndex = range.r1 - 1;
|
|
oRange._foreachRowNoEmpty(function(row){
|
|
if(null != row && row.xfs && !res === _getLocked(row.xfs)) {
|
|
if (unLockedRowIndex + 1 === row.index) {
|
|
unLockedRowIndex++;
|
|
}
|
|
}
|
|
});
|
|
if (unLockedRowIndex === range.r2) {
|
|
res = !res;
|
|
}
|
|
|
|
//all selected cols
|
|
let unLockedColIndex = range.c1 - 1;
|
|
oRange._foreachColNoEmpty(function(col){
|
|
if(null != col && col.xfs && !res === _getLocked(col.xfs)) {
|
|
if (unLockedColIndex + 1 === col.index) {
|
|
unLockedColIndex++;
|
|
}
|
|
}
|
|
});
|
|
if (unLockedColIndex === range.c2) {
|
|
res = !res;
|
|
}
|
|
|
|
let counter = 0;
|
|
let bbox = oRange.getBBox0 && oRange.getBBox0();
|
|
let sizeRange = bbox ? bbox.getHeight() * bbox.getWidth() : null;
|
|
oRange._foreachNoEmpty(function(cell){
|
|
if (!cell) {
|
|
return;
|
|
}
|
|
|
|
var isLocked = _getLocked(cell.xfs);
|
|
if (isLocked === true) {
|
|
res = true;
|
|
return true;
|
|
} else if (isLocked === false) {
|
|
counter++;
|
|
if (res === true && sizeRange) {
|
|
if (counter === sizeRange) {
|
|
res = false;
|
|
}
|
|
} else {
|
|
res = false;
|
|
}
|
|
}
|
|
});
|
|
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getLockedRanges = function (range) {
|
|
var res = [range.clone()];
|
|
this.getRange3(range.r1, range.c1, range.r2, range.c2)._foreachNoEmpty(function(cell){
|
|
if (!cell) {
|
|
return;
|
|
}
|
|
var cellxfs = cell && cell.xfs;
|
|
var isLocked = cellxfs && cellxfs.asc_getLocked();
|
|
if (isLocked === false) {
|
|
//исключаем ячейку из общего диапазона
|
|
var _range = new Asc.Range(cell.nCol, cell.nRow, cell.nCol, cell.nRow);
|
|
var newRange = [];
|
|
for (var i = 0; i < res.length; i++) {
|
|
var _difference = _range.difference(res[i]);
|
|
if (_difference && _difference.length) {
|
|
newRange = newRange.concat(_difference);
|
|
}
|
|
}
|
|
res = newRange;
|
|
}
|
|
});
|
|
return res;
|
|
};
|
|
|
|
|
|
Worksheet.prototype.getProtectedRanges = function (needClone) {
|
|
var protectedRanges = this.aProtectedRanges;
|
|
var res = null;
|
|
if (needClone && protectedRanges && protectedRanges.length) {
|
|
res = [];
|
|
for (var i = 0; i < protectedRanges.length; i++) {
|
|
var id = protectedRanges[i].Id;
|
|
var cloneRange = protectedRanges[i].clone();
|
|
cloneRange.Id = id;
|
|
cloneRange.isLock = protectedRanges[i].isLock;
|
|
res.push(cloneRange);
|
|
}
|
|
}
|
|
return !res ? protectedRanges : res;
|
|
};
|
|
|
|
Worksheet.prototype.setProtectedRange = function (val) {
|
|
if (!val) {
|
|
return;
|
|
}
|
|
var pR = this.getProtectedRangeById(val.Id);
|
|
if (pR) {
|
|
this.changeProtectedRange(pR.val, val, true);
|
|
} else {
|
|
this.addProtectedRange(val, true);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getProtectedRangeById = function (id) {
|
|
if (this.aProtectedRanges) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (this.aProtectedRanges[i].Id === id) {
|
|
return {val: this.aProtectedRanges[i], index: i};
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getProtectedRangeByRange = function (range) {
|
|
if (this.aProtectedRanges) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (this.aProtectedRanges[i].intersection(range)) {
|
|
return {val: this.aProtectedRanges[i], index: i};
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.getProtectedRangeByName = function (name) {
|
|
if (this.aProtectedRanges) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (this.aProtectedRanges[i].name === name) {
|
|
return {val: this.aProtectedRanges[i], index: i};
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.changeProtectedRange = function (from, to, addToHistory) {
|
|
if (!from) {
|
|
return;
|
|
}
|
|
from.set(to, addToHistory, this);
|
|
};
|
|
|
|
Worksheet.prototype.addProtectedRange = function (val, addToHistory) {
|
|
if (!val) {
|
|
return;
|
|
}
|
|
|
|
this.aProtectedRanges.push(val);
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_AddProtectedRange,
|
|
this.getId(), /*val.getUnionRange()*/null,
|
|
new AscCommonExcel.UndoRedoData_ProtectedRange(val.Id, null, val));
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.deleteProtectedRange = function (id, addToHistory) {
|
|
var protectedRange = this.getProtectedRangeById(id);
|
|
if (protectedRange) {
|
|
this.aProtectedRanges.splice(protectedRange.index, 1);
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_DelProtectedRange,
|
|
this.getId(), /*oRule.val.getUnionRange()*/null,
|
|
new AscCommonExcel.UndoRedoData_ProtectedRange(id, protectedRange.val));
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.updateProtectedRangeOffset = function (range, offset) {
|
|
if (offset.row < 0 || offset.col < 0) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; ++i) {
|
|
if (this.aProtectedRanges[i].containsIntoRange(range)) {
|
|
this.deleteProtectedRange(this.aProtectedRanges[i].Id, true);
|
|
}
|
|
}
|
|
}
|
|
this.setProtectedRangeOffset(range, offset);
|
|
};
|
|
|
|
Worksheet.prototype.setProtectedRangeOffset = function (range, offset) {
|
|
var protectedRange;
|
|
for (var i = 0; i < this.aProtectedRanges.length; ++i) {
|
|
protectedRange = this.aProtectedRanges[i];
|
|
protectedRange.setOffset(offset, range, this, true);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.moveProtectedRange = function (oBBoxFrom, oBBoxTo, copyRange, offset, wsTo, wsFrom, bTransposeTo) {
|
|
var t = this;
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
|
|
if (wsTo.isUserProtectedRangesIntersection(oBBoxTo) || (wsFrom && wsFrom.isUserProtectedRangesIntersection(oBBoxFrom))) {
|
|
wsTo.workbook.handlers && wsTo.workbook.handlers.trigger("asc_onError", c_oAscError.ID.ProtectedRangeByOtherUser, c_oAscError.Level.NoCritical);
|
|
return;
|
|
}
|
|
|
|
if (wsTo.getSheetProtection()) {
|
|
return;
|
|
}
|
|
if (false === this.workbook.bUndoChanges && false === this.workbook.bRedoChanges) {
|
|
//чистим ту область, куда переносим
|
|
if (wsTo.aProtectedRanges && wsTo.aProtectedRanges.length) {
|
|
wsTo.aProtectedRanges.forEach(function (_protectedRange) {
|
|
t.tryClearProtectedRange(_protectedRange, [oBBoxTo]);
|
|
});
|
|
}
|
|
|
|
if (!wsFrom) {
|
|
wsFrom = this;
|
|
}
|
|
|
|
if (wsFrom.aProtectedRanges && wsFrom.aProtectedRanges.length) {
|
|
wsFrom.aProtectedRanges.forEach(function (pR) {
|
|
//если клонируем - то добавляем новый диапазон со смещенным диапазоном пересечения
|
|
//если нет + если в пределах одного листа - меняем диапазона у текущего правила
|
|
//если на другой лист - меняем диапазон у текущего + создаём новый со смещенным диапазоном пересечения
|
|
|
|
var isChanged = null;
|
|
var _protectedSqref = pR.sqref;
|
|
var constantPart, movePart;
|
|
var _moveRanges = [];
|
|
var _constantRanges = [];
|
|
for (var i = 0; i < _protectedSqref.length; i++) {
|
|
movePart = _protectedSqref[i].intersection(oBBoxFrom);
|
|
if (movePart) {
|
|
if (!copyRange) {
|
|
constantPart = oBBoxFrom.difference(_protectedSqref[i]);
|
|
_constantRanges = _constantRanges.concat(constantPart);
|
|
}
|
|
|
|
if (bTransposeTo) {
|
|
movePart = movePart.transpose(oBBoxFrom.c1, oBBoxFrom.r1);
|
|
}
|
|
|
|
movePart.setOffset(offset);
|
|
_moveRanges.push(movePart);
|
|
isChanged = true;
|
|
} else if (!copyRange) {
|
|
_constantRanges.push(_protectedSqref[i]);
|
|
}
|
|
}
|
|
if (isChanged) {
|
|
//в случае клонирования фрагмента - создаём новый
|
|
var _newPr;
|
|
if (copyRange) {
|
|
if (wsFrom === wsTo) {
|
|
pR.setSqref(pR.sqref.concat(_moveRanges), t, true);
|
|
} else {
|
|
_newPr = pR.clone();
|
|
_newPr.sqref = _moveRanges;
|
|
_newPr.generateNewName(wsTo.aProtectedRanges);
|
|
wsTo.addProtectedRange(_newPr, true);
|
|
}
|
|
} else {
|
|
if (t !== wsTo) {
|
|
if (_moveRanges.length) {
|
|
_newPr = pR.clone();
|
|
_newPr.sqref = _moveRanges;
|
|
wsTo.addProtectedRange(_newPr, true);
|
|
}
|
|
if (_constantRanges.length) {
|
|
pR.setSqref(_constantRanges, t, true);
|
|
}
|
|
} else {
|
|
pR.setSqref(_constantRanges.concat(_moveRanges), t, true);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.tryClearProtectedRange = function (protectedRange, ranges) {
|
|
if (!protectedRange) {
|
|
return;
|
|
}
|
|
|
|
if (ranges) {
|
|
var _newRanges = [];
|
|
|
|
var protectedSqref = protectedRange.sqref;
|
|
for (var i = 0; i < protectedSqref.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].intersection(tempRanges[k]) ? ranges[j].difference(tempRanges[k]) : tempRanges[k]);
|
|
}
|
|
tempRanges = tempRanges2;
|
|
} else {
|
|
tempRanges = ranges[j].intersection(protectedSqref[i]) ? ranges[j].difference(protectedSqref[i]) : protectedSqref[i];
|
|
}
|
|
}
|
|
_newRanges = _newRanges.concat(tempRanges);
|
|
}
|
|
|
|
if (!_newRanges.length) {
|
|
this.deleteProtectedRange(protectedRange.Id, true)
|
|
} else {
|
|
var newProtectedRange = protectedRange.clone();
|
|
newProtectedRange.sqref = _newRanges;
|
|
this.changeProtectedRange(protectedRange, newProtectedRange, true);
|
|
}
|
|
} else {
|
|
this.deleteProtectedRange(protectedRange.Id, true);
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getProtectedRangesByActiveCell = function () {
|
|
var activeCell = this.selectionRange.activeCell;
|
|
var res = [];
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
if (this.aProtectedRanges[i].contains(activeCell.col, activeCell.row)) {
|
|
res.push(this.aProtectedRanges[i]);
|
|
}
|
|
}
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.getProtectedRangesByActiveRange = function () {
|
|
var res = [];
|
|
var activeRanges = this.selectionRange.ranges;
|
|
|
|
if (this.aProtectedRanges) {
|
|
for (var i = 0; i < this.aProtectedRanges.length; i++) {
|
|
for (var j = 0; j < activeRanges.length; j++) {
|
|
if (this.aProtectedRanges[i].intersection(activeRanges[j])) {
|
|
res.push(this.aProtectedRanges[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res.length ? res : null;
|
|
};
|
|
|
|
Worksheet.prototype.isLockedActiveCell = function () {
|
|
var activeCell = this.selectionRange.activeCell;
|
|
return this.getLockedCell(activeCell.col, activeCell.row);
|
|
};
|
|
|
|
Worksheet.prototype.getPrintOptionsJson = function () {
|
|
var printProps = this.PagePrintOptions;
|
|
printProps.initPrintTitles();
|
|
printProps = printProps.clone();
|
|
printProps.pageSetup.headerFooter = this && this.headerFooter && this.headerFooter.getForInterface();
|
|
var printArea = this.workbook.getDefinesNames("Print_Area", this.getId());
|
|
printProps.pageSetup.printArea = printArea ? printArea.clone() : false;
|
|
printProps.pageSetup.selection = this.selectionRange.ranges;
|
|
|
|
printProps.printTitlesHeight = this.PagePrintOptions.printTitlesHeight;
|
|
printProps.printTitlesWidth = this.PagePrintOptions.printTitlesWidth;
|
|
|
|
if (this.PagePrintOptions && this.PagePrintOptions.pageSetup) {
|
|
printProps.pageSetup.fitToHeight = this.PagePrintOptions.pageSetup.asc_getFitToHeight();
|
|
printProps.pageSetup.fitToWidth = this.PagePrintOptions.pageSetup.asc_getFitToWidth();
|
|
}
|
|
|
|
return printProps.getJson(this);
|
|
};
|
|
|
|
Worksheet.prototype.changeRowColBreaks = function (from, to, range, byCol, addToHistory) {
|
|
let min = null;
|
|
let max = !byCol ? gc_nMaxCol0 : gc_nMaxRow0;
|
|
let man = true, pt = null;
|
|
|
|
let printArea = this.workbook.getDefinesNames("Print_Area", this.getId());
|
|
if (printArea && range) {
|
|
if (byCol) {
|
|
min = range.r1;
|
|
max = range.r2;
|
|
} else {
|
|
min = range.c1;
|
|
max = range.c2;
|
|
}
|
|
}
|
|
|
|
this._changeRowColBreaks(from, to, min, max, man, pt, byCol, addToHistory);
|
|
};
|
|
|
|
Worksheet.prototype._changeRowColBreaks = function (from, to, min, max, man, pt, byCol, addToHistory) {
|
|
let t = this;
|
|
let rowColBreaks = !byCol ? t.rowBreaks : t.colBreaks;
|
|
|
|
let checkInit = function () {
|
|
if (!byCol) {
|
|
if (!t.rowBreaks) {
|
|
t.rowBreaks = new AscCommonExcel.CRowColBreaks();
|
|
rowColBreaks = t.rowBreaks;
|
|
}
|
|
} else {
|
|
if (!t.colBreaks) {
|
|
t.colBreaks = new AscCommonExcel.CRowColBreaks();
|
|
rowColBreaks = t.colBreaks;
|
|
}
|
|
}
|
|
};
|
|
|
|
let isChanged = false;
|
|
let oFromBreak = rowColBreaks && rowColBreaks.getBreak(from, min, max);
|
|
if (oFromBreak) {
|
|
if (to) {
|
|
//change
|
|
checkInit();
|
|
isChanged = rowColBreaks.changeBreak(from, to, min, max, true);
|
|
} else {
|
|
//delete
|
|
isChanged = rowColBreaks && rowColBreaks.removeBreak(from, min, max);
|
|
}
|
|
} else if (to) {
|
|
//add
|
|
checkInit();
|
|
isChanged = rowColBreaks.addBreak(to, min, max, true, null)
|
|
}
|
|
|
|
if (isChanged && addToHistory) {
|
|
let fromData = oFromBreak && new AscCommonExcel.UndoRedoData_RowColBreaks(from, oFromBreak.min, oFromBreak.max, oFromBreak.man, oFromBreak.pt, byCol);
|
|
let toData = new AscCommonExcel.UndoRedoData_RowColBreaks(to, min, max, man, pt, byCol);
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ChangeRowColBreaks, this.getId(),
|
|
null, new AscCommonExcel.UndoRedoData_FromTo(fromData, toData));
|
|
}
|
|
|
|
this.workbook.handlers.trigger("onChangePageSetupProps", this.getId());
|
|
};
|
|
|
|
Worksheet.prototype.isBreak = function (index, range, byCol) {
|
|
let min = null;
|
|
let max = !byCol ? gc_nMaxCol0 : gc_nMaxRow0;
|
|
|
|
let printArea = this.workbook.getDefinesNames("Print_Area", this.getId());
|
|
if (printArea && range) {
|
|
if (byCol) {
|
|
min = range.r1;
|
|
max = range.r2;
|
|
} else {
|
|
min = range.c1;
|
|
max = range.c2;
|
|
}
|
|
}
|
|
|
|
let rowColBreaks = !byCol ? this.rowBreaks : this.colBreaks;
|
|
return rowColBreaks && rowColBreaks.isBreak(index, min, max);
|
|
};
|
|
|
|
Worksheet.prototype.resetAllPageBreaks = function () {
|
|
let t = this;
|
|
|
|
let doRemoveBreaks = function(_breaks, byCol) {
|
|
if (!_breaks) {
|
|
return;
|
|
}
|
|
let aBreaks = _breaks.getBreaks();
|
|
for (let i = 0; i < aBreaks.length; i++) {
|
|
let fromData = new AscCommonExcel.UndoRedoData_RowColBreaks(aBreaks[i].id, aBreaks[i].min, aBreaks[i].max, aBreaks[i].man, aBreaks[i].pt, byCol);
|
|
if (_breaks.removeBreak(aBreaks[i].id)) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ChangeRowColBreaks, t.getId(),
|
|
null, new AscCommonExcel.UndoRedoData_FromTo(fromData, null));
|
|
i--;
|
|
}
|
|
}
|
|
};
|
|
|
|
if (this.rowBreaks) {
|
|
doRemoveBreaks(this.rowBreaks);
|
|
}
|
|
if (this.colBreaks) {
|
|
doRemoveBreaks(this.colBreaks, true);
|
|
}
|
|
this.workbook.handlers.trigger("onChangePageSetupProps", this.getId());
|
|
};
|
|
|
|
Worksheet.prototype.getPrintAreaRangeByRowCol = function (row, col) {
|
|
let printArea = this.workbook.getDefinesNames("Print_Area", this.getId());
|
|
let t = this;
|
|
|
|
if (printArea) {
|
|
let ranges;
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
ranges = AscCommonExcel.getRangeByRef(printArea.ref, t, true, true)
|
|
});
|
|
if (ranges) {
|
|
for (let i = 0; i < ranges.length; i++) {
|
|
if (ranges[i].bbox.contains(col, row)) {
|
|
return ranges[i].bbox;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
Worksheet.prototype.addCellWatch = function (ref, addToHistory) {
|
|
for (var i = 0; i < this.aCellWatches.length; i++) {
|
|
if (ref.isEqual(this.aCellWatches[i].r)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
var cellWatch = new AscCommonExcel.CCellWatch(this);
|
|
cellWatch.setRef(ref);
|
|
this.aCellWatches.push(cellWatch);
|
|
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_AddCellWatch, this.getId(),
|
|
null, new AscCommonExcel.UndoRedoData_FromTo(null, new AscCommonExcel.UndoRedoData_BBox(ref)));
|
|
}
|
|
|
|
this.workbook.handlers && this.workbook.handlers.trigger("changeCellWatches", this.getIndex());
|
|
};
|
|
|
|
Worksheet.prototype.deleteCellWatch = function (ref, addToHistory) {
|
|
for (var i = 0; i < this.aCellWatches.length; i++) {
|
|
if (ref.isEqual(this.aCellWatches[i].r)) {
|
|
this.aCellWatches.splice(i, 1);
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_DelCellWatch,
|
|
this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_FromTo(new AscCommonExcel.UndoRedoData_BBox(ref), null));
|
|
}
|
|
this.workbook.handlers && this.workbook.handlers.trigger("changeCellWatches", this.getIndex());
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.deleteCellWatches = function (addToHistory) {
|
|
if (addToHistory) {
|
|
for (var i = 0; i < this.aCellWatches.length; i++) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_DelCellWatch,
|
|
this.getId(), null,
|
|
new AscCommonExcel.UndoRedoData_FromTo(new AscCommonExcel.UndoRedoData_BBox(this.aCellWatches[i].r), null));
|
|
}
|
|
}
|
|
this.aCellWatches = [];
|
|
this.workbook.handlers && this.workbook.handlers.trigger("changeCellWatches", this.getIndex());
|
|
};
|
|
|
|
Worksheet.prototype.deleteCellWatchesByRange = function (range, addToHistory) {
|
|
for (var i = 0; i < this.aCellWatches.length; i++) {
|
|
if (range.containsRange(this.aCellWatches[i].r)) {
|
|
this.deleteCellWatch(this.aCellWatches[i].r, addToHistory);
|
|
i--;
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.getCellWatchesByRange = function (range) {
|
|
let res = [];
|
|
for (var i = 0; i < this.aCellWatches.length; i++) {
|
|
if (range.containsRange(this.aCellWatches[i].r)) {
|
|
res.push(this.aCellWatches[i]);
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.checkImportXmlLocationForError = function(ranges) {
|
|
for (var i = 0; i < ranges.length; ++i) {
|
|
var range = ranges[i];
|
|
if (this.autoFilters.isIntersectionTable(range)) {
|
|
return c_oAscError.ID.PivotOverlap;
|
|
}
|
|
if (this.inPivotTable(range)) {
|
|
return c_oAscError.ID.PivotOverlap;
|
|
}
|
|
}
|
|
return c_oAscError.ID.No;
|
|
};
|
|
|
|
//*****user range protect*****
|
|
Worksheet.prototype.editUserProtectedRanges = function(oldObj, newObj, addToHistory) {
|
|
//if undo/redo - need apply changes
|
|
if (addToHistory && ((newObj && this.isIntersectionOtherUserProtectedRanges(newObj.ref)) ||
|
|
(oldObj && this.isIntersectionOtherUserProtectedRanges(oldObj.ref)))) {
|
|
return false;
|
|
}
|
|
|
|
let newRes;
|
|
if (oldObj || newObj) {
|
|
let cloneNewOnj = newObj && newObj.clone();
|
|
newRes = cloneNewOnj;
|
|
if (cloneNewOnj) {
|
|
cloneNewOnj.Id = newObj.Id;
|
|
cloneNewOnj._ws = this;
|
|
}
|
|
if (oldObj) {
|
|
let modelUserRange = this.getUserProtectedRangeById(oldObj.Id);
|
|
if (modelUserRange) {
|
|
//TODO clone
|
|
if (cloneNewOnj) {
|
|
this.userProtectedRanges[modelUserRange.index] = cloneNewOnj;
|
|
} else {
|
|
this.userProtectedRanges.splice(modelUserRange.index, 1);
|
|
}
|
|
}
|
|
} else if (cloneNewOnj) {
|
|
this.userProtectedRanges.push(cloneNewOnj);
|
|
}
|
|
|
|
if (addToHistory) {
|
|
let updateRange = null;
|
|
if (oldObj && newObj && oldObj.ref && newObj.ref) {
|
|
updateRange = oldObj.ref.clone();
|
|
updateRange.union2(newObj.ref);
|
|
} else if (oldObj && oldObj.ref) {
|
|
updateRange = oldObj.ref.clone();
|
|
} else if (newObj && newObj.ref) {
|
|
updateRange = newObj.ref.clone();
|
|
}
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ChangeUserProtectedRange, this.getId(), updateRange,
|
|
new UndoRedoData_FromTo(oldObj, newObj));
|
|
}
|
|
}
|
|
|
|
return newRes ? newRes : true;
|
|
};
|
|
|
|
Worksheet.prototype.deleteUserProtectedRanges = function (range) {
|
|
for (var i = this.userProtectedRanges.length - 1; i >= 0; --i) {
|
|
var userProtectedRange = this.userProtectedRanges[i];
|
|
if (range.containsRange(userProtectedRange.ref)) {
|
|
this.editUserProtectedRanges(userProtectedRange, null, true);
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Worksheet.prototype.getUserProtectedRangeById = function(id) {
|
|
var res = null;
|
|
if(!this.userProtectedRanges)
|
|
return res;
|
|
|
|
for(var i = 0; i < this.userProtectedRanges.length; i++)
|
|
{
|
|
if(this.userProtectedRanges[i].Id === id)
|
|
{
|
|
res = {obj: this.userProtectedRanges[i], index: i};
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.getUserProtectedRangeByName = function(name) {
|
|
var res = null;
|
|
if(!this.userProtectedRanges)
|
|
return res;
|
|
|
|
for(var i = 0; i < this.userProtectedRanges.length; i++)
|
|
{
|
|
if(this.userProtectedRanges[i].name === name)
|
|
{
|
|
res = {obj: this.userProtectedRanges[i], index: i};
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.unlockUserProtectedRanges = function(){
|
|
if (this.userProtectedRanges) {
|
|
for (let i = 0; i < this.userProtectedRanges.length; i++) {
|
|
this.userProtectedRanges[i].isLock = null;
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.isIntersectionOtherUserProtectedRanges = function(range){
|
|
let res = false;
|
|
if (this.userProtectedRanges) {
|
|
let oApi = Asc.editor;
|
|
let sUserId = oApi.DocInfo && oApi.DocInfo.get_UserId();
|
|
if (sUserId) {
|
|
for (let i = 0; i < this.userProtectedRanges.length; i++) {
|
|
let curUserProtectedRange = this.userProtectedRanges[i];
|
|
if (curUserProtectedRange.intersection(range) && !curUserProtectedRange.isUserCanEdit(sUserId)) {
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.isUserProtectedRangesIntersection = function (range, userId, notCheckUser, type) {
|
|
//range - array of ranges or range
|
|
let res = false;
|
|
if (!this.userProtectedRanges || !this.userProtectedRanges.length) {
|
|
return res;
|
|
}
|
|
|
|
if (!userId) {
|
|
let oApi = Asc.editor;
|
|
userId = oApi.DocInfo && oApi.DocInfo.get_UserId();
|
|
}
|
|
if (this.userProtectedRanges && userId) {
|
|
for (let i = 0; i < this.userProtectedRanges.length; i++) {
|
|
let curUserProtectedRange = this.userProtectedRanges[i];
|
|
if (range && range.length) {
|
|
for (let j = 0; j < range.length; j++) {
|
|
if (curUserProtectedRange.intersection(range[j]) && (notCheckUser || !curUserProtectedRange.isUserCanDoByType(userId, type))) {
|
|
return true;
|
|
}
|
|
}
|
|
} else if ((!range || curUserProtectedRange.intersection(range)) && (notCheckUser || !curUserProtectedRange.isUserCanDoByType(userId, type))) {
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.isUserProtectedRangesIntersectionCell = function(oCell, userId, notCheckUser, type){
|
|
//range - array of ranges or range
|
|
let res = false;
|
|
if (!this.userProtectedRanges || !this.userProtectedRanges.length || !oCell) {
|
|
return res;
|
|
}
|
|
if (!userId) {
|
|
let oApi = Asc.editor;
|
|
userId = oApi && oApi.DocInfo && oApi.DocInfo.get_UserId();
|
|
}
|
|
|
|
if (this.userProtectedRanges && userId) {
|
|
for (let i = 0; i < this.userProtectedRanges.length; i++) {
|
|
let curUserProtectedRange = this.userProtectedRanges[i];
|
|
if (curUserProtectedRange.contains(oCell.nCol, oCell.nRow) && (notCheckUser || !curUserProtectedRange.isUserCanDoByType(userId, type))) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.isUserProtectedRangesCanView = function(oCell, userId){
|
|
//range - array of ranges or range
|
|
let res = true;
|
|
if (!this.userProtectedRanges || !this.userProtectedRanges.length || !oCell) {
|
|
return res;
|
|
}
|
|
if (!userId) {
|
|
let oApi = Asc.editor;
|
|
userId = oApi.DocInfo && oApi.DocInfo.get_UserId();
|
|
}
|
|
|
|
oCell = {col: oCell.nCol, row: oCell.nRow};
|
|
|
|
if (this.userProtectedRanges && userId) {
|
|
for (let i = 0; i < this.userProtectedRanges.length; i++) {
|
|
let curUserProtectedRange = this.userProtectedRanges[i];
|
|
if (curUserProtectedRange.contains2(oCell) && !curUserProtectedRange.isUserCanView(userId)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
|
|
Worksheet.prototype.updateUserProtectedRangesOffset = function (range, offset) {
|
|
if (offset.row < 0 || offset.col < 0) {
|
|
this.deleteUserProtectedRanges(range);
|
|
}
|
|
|
|
this.shiftUserProtectedRanges(range, offset);
|
|
};
|
|
Worksheet.prototype.moveUserProtectedRangesOffset = function (range, offset) {
|
|
var userProtectedRange;
|
|
for (var i = 0; i < this.userProtectedRanges.length; ++i) {
|
|
userProtectedRange = this.userProtectedRanges[i];
|
|
if (userProtectedRange.isInRange(range)) {
|
|
userProtectedRange.setOffset(offset, true);
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype._moveUserProtectedRange = function (oBBoxFrom, oBBoxTo, copyRange, offset, wsTo) {
|
|
if (!wsTo) {
|
|
wsTo = this;
|
|
}
|
|
if (false == this.workbook.bUndoChanges && false == this.workbook.bRedoChanges) {
|
|
if (copyRange) {
|
|
wsTo.deleteUserProtectedRanges(oBBoxTo);
|
|
this.copyUserProtectedRanges(oBBoxFrom, offset, wsTo);
|
|
} else {
|
|
if (this === wsTo) {
|
|
this.moveUserProtectedRangesOffset(oBBoxFrom, offset);
|
|
} else {
|
|
this.copyUserProtectedRanges(oBBoxFrom, offset, wsTo);
|
|
this.deleteUserProtectedRanges(oBBoxFrom);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.copyUserProtectedRanges = function (range, offset, wsTo) {
|
|
var t = this;
|
|
var userProtectedRange;
|
|
for (var i = this.userProtectedRanges.length - 1; i >= 0; --i) {
|
|
userProtectedRange = this.userProtectedRanges[i];
|
|
if (userProtectedRange.isInRange(range)) {
|
|
var newUserProtectedRange = userProtectedRange.clone(wsTo);
|
|
newUserProtectedRange.setOffset(offset, false);
|
|
wsTo.editUserProtectedRanges(null, newUserProtectedRange, true);
|
|
}
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.shiftUserProtectedRanges = function (range, offset, wsTo) {
|
|
var t = this;
|
|
var userProtectedRange;
|
|
for (var i = this.userProtectedRanges.length - 1; i >= 0; --i) {
|
|
userProtectedRange = this.userProtectedRanges[i];
|
|
|
|
if (range.isIntersectForShift(userProtectedRange.ref, offset)) {
|
|
let newRef = userProtectedRange.ref.clone();
|
|
newRef.forShift(range, offset);
|
|
if (!userProtectedRange.ref.isEqual(newRef)) {
|
|
userProtectedRange.setLocation(newRef, true);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
Worksheet.prototype.setSheetViewType = function(val, addToHistory) {
|
|
var sheetView = this.sheetViews[0];
|
|
|
|
if (!sheetView) {
|
|
return;
|
|
}
|
|
|
|
var oldValue = sheetView.view;
|
|
if (oldValue !== val) {
|
|
sheetView.view = val;
|
|
if (addToHistory) {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_SetSheetViewType,
|
|
this.getId(), null, new UndoRedoData_FromTo(oldValue, val));
|
|
|
|
AscCommon.History.EndTransaction();
|
|
}
|
|
|
|
this.workbook.handlers && this.workbook.handlers.trigger("asc_updateSheetViewType", this.index);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.setColsCount = function(val) {
|
|
this.nColsCount = val;
|
|
};
|
|
|
|
Worksheet.prototype.changeLegacyDrawingHFPictures = function(picturesMap) {
|
|
if (!this.legacyDrawingHF) {
|
|
this.legacyDrawingHF = new AscCommonExcel.CLegacyDrawingHF(this);
|
|
}
|
|
this.legacyDrawingHF.addPictures(picturesMap);
|
|
};
|
|
|
|
Worksheet.prototype.removeLegacyDrawingHFPictures = function(aPictures) {
|
|
if (!this.legacyDrawingHF) {
|
|
this.legacyDrawingHF = new AscCommonExcel.CLegacyDrawingHF(this);
|
|
}
|
|
this.legacyDrawingHF.removePictures(aPictures);
|
|
};
|
|
|
|
Worksheet.prototype.getLegacyDrawingHFById = function(val) {
|
|
if (!this.legacyDrawingHF) {
|
|
return null;
|
|
}
|
|
return this.legacyDrawingHF.getDrawingById(val);
|
|
};
|
|
|
|
Worksheet.prototype.getCountNoEmptyCells = function() {
|
|
if (this.nRowsCount === 0 || this.nColsCount === 0) {
|
|
return 0;
|
|
}
|
|
let count = 0;
|
|
let range = this.getRange3(0, 0, this.nRowsCount - 1, this.nColsCount - 1);
|
|
range._foreachNoEmptyByCol(function () {
|
|
count++;
|
|
});
|
|
return count;
|
|
};
|
|
/**
|
|
* The method returns a flag that recognizes fill handle was called from right click
|
|
* @returns {boolean}
|
|
*/
|
|
Worksheet.prototype.getFillHandleRightClick = function () {
|
|
return this.bFillHandleRightClick;
|
|
};
|
|
/**
|
|
* The method sets a flag that recognizes fill handle was called from right click
|
|
* @param {boolean} bFillHandleRightClick
|
|
*/
|
|
Worksheet.prototype.setFillHandleRightClick = function (bFillHandleRightClick) {
|
|
this.bFillHandleRightClick = bFillHandleRightClick;
|
|
};
|
|
/**
|
|
* The method returns the value of chosen property from context menu for autofill.
|
|
* @memberof Worksheet
|
|
* @returns {Asc.c_oAscFillType}
|
|
*/
|
|
Worksheet.prototype.getFillMenuChosenProp = function () {
|
|
return this.nFillMenuChosenProp;
|
|
};
|
|
/**
|
|
* The method sets the value of chosen property from context menu for autofill.
|
|
* @memberof Worksheet
|
|
* @param {Asc.c_oAscFillType} nFillMenuChosenProp
|
|
*/
|
|
Worksheet.prototype.setFillMenuChosenProp = function (nFillMenuChosenProp) {
|
|
this.nFillMenuChosenProp = nFillMenuChosenProp;
|
|
}
|
|
Worksheet.prototype.getActiveFillType = function () {
|
|
return this.activeFillType;
|
|
};
|
|
Worksheet.prototype.setActiveFillType = function (val) {
|
|
this.activeFillType = val;
|
|
};
|
|
Worksheet.prototype.onTimelinesDelete = function(name, addToHistory) {
|
|
if (this.timelines && this.timelines.length) {
|
|
for (let i = 0; i < this.timelines.length; i++) {
|
|
if (this.timelines[i].name === name) {
|
|
if (addToHistory) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_TimelineDelete,
|
|
this.getId(), null, new UndoRedoData_FromTo(this.timelines[i], null));
|
|
}
|
|
|
|
this.timelines.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.isSelectedTab = function () {
|
|
for (let i = 0; i < this.sheetViews.length; i++) {
|
|
if (this.sheetViews[i].tabSelected) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
Worksheet.prototype.addChangedArray = function (rangeName, arrayInfo) {
|
|
if (!rangeName || !arrayInfo) {
|
|
return
|
|
}
|
|
|
|
if (!this.changedArrays) {
|
|
this.changedArrays = {};
|
|
}
|
|
|
|
if (!this.changedArrays[rangeName]) {
|
|
this.changedArrays[rangeName] = arrayInfo
|
|
}
|
|
};
|
|
Worksheet.prototype.getChangedArrayList = function () {
|
|
if (!this.changedArrays) {
|
|
return
|
|
}
|
|
|
|
return this.changedArrays
|
|
};
|
|
Worksheet.prototype.removeFromChangedArrayList = function (name) {
|
|
if (!this.changedArrays) {
|
|
return
|
|
}
|
|
|
|
return this.changedArrays[name]
|
|
};
|
|
Worksheet.prototype.clearChangedArrayList = function () {
|
|
this.changedArrays = null;
|
|
};
|
|
Worksheet.prototype.recalculateVolatileArrays = function () {
|
|
if (AscCommonExcel.bIsSupportDynamicArrays) {
|
|
const ws = this;
|
|
|
|
// recalculate all volatile arrays on page
|
|
if (ws && ws.workbook && ws.workbook.dependencyFormulas) {
|
|
let depGraph = ws.workbook.dependencyFormulas;
|
|
// get volatileArraysList
|
|
let volatileArrayList = depGraph.getVolatileArrays();
|
|
if (volatileArrayList) {
|
|
for (let listenerId in volatileArrayList) {
|
|
let formula = volatileArrayList[listenerId];
|
|
let formulaResult = formula.calculate();
|
|
let firstCellRef = formula.parent && new Asc.Range(formula.parent.nCol, formula.parent.nRow, formula.parent.nCol, formula.parent.nRow);
|
|
if (!(formula.aca && formula.ca)) {
|
|
// array can expand, setValue for each cell except first
|
|
let dimensions = formulaResult.getDimensions();
|
|
let newRef = new Asc.Range(firstCellRef.c1, firstCellRef.r1, firstCellRef.c1 + dimensions.col - 1, firstCellRef.r1 + dimensions.row - 1);
|
|
formula.setDynamicRef(newRef);
|
|
if (newRef) {
|
|
for (let row = newRef.r1; row <= newRef.r2; row++) {
|
|
for (let col = newRef.c1; col <= newRef.c2; col++) {
|
|
// if (row === newRef.r1 && col === newRef.c1) {
|
|
// continue
|
|
// }
|
|
// get cell and setPF to it
|
|
ws._getCell(row, col, function(cell) {
|
|
cell && cell.setFormulaInternal(formula);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
depGraph.addToChangedRange2(formula.getWs().getId(), formula.getDynamicRef());
|
|
depGraph.endListeningVolatileArray(listenerId);
|
|
} else {
|
|
formula.setDynamicRef(firstCellRef);
|
|
ws._getCell(firstCellRef.r1, firstCellRef.c1, function(cell) {
|
|
cell && cell.setFormulaInternal(formula);
|
|
});
|
|
|
|
depGraph.addToChangedRange2(formula.getWs().getId(), formula.getArrayFormulaRef());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Worksheet.prototype.getRefDynamicInfo = function (formula, calculateResult) {
|
|
if (formula) {
|
|
let applyByArray = true, ctrlKey = true, dynamicRange = null, cannotChangeFormulaArray = false;
|
|
|
|
if (formula.ref) {
|
|
dynamicRange = formula.ref;
|
|
} else {
|
|
let tempRef = new Asc.Range(formula.parent.nCol, formula.parent.nRow, formula.parent.nCol, formula.parent.nRow);
|
|
formula.ref = tempRef;
|
|
|
|
let formulaResult = formula.calculate(null, null, null, null, calculateResult);
|
|
let arraySize = formulaResult.getDimensions(true);
|
|
let newR2 = (formula.parent.nRow + arraySize.row) > AscCommon.gc_nMaxRow ? AscCommon.gc_nMaxRow - 1 : (formula.parent.nRow + arraySize.row - 1);
|
|
let newC2 = (formula.parent.nCol + arraySize.col) > AscCommon.gc_nMaxCol ? AscCommon.gc_nMaxCol - 1 : (formula.parent.nCol + arraySize.col - 1);
|
|
|
|
if (formulaResult.type !== cElementType.array) {
|
|
return false;
|
|
}
|
|
|
|
let tempDynamicSelectionRange = this.getRange3(formula.parent.nRow, formula.parent.nCol, newR2, newC2);
|
|
tempDynamicSelectionRange._foreachNoEmpty(function (cell) {
|
|
let ref = cell.formulaParsed && cell.formulaParsed.ref ? cell.formulaParsed.ref : null;
|
|
|
|
if (ref && !tempDynamicSelectionRange.bbox.containsRange(ref)) {
|
|
cannotChangeFormulaArray = true;
|
|
return false;
|
|
}
|
|
});
|
|
|
|
if (tempDynamicSelectionRange.bbox.isOneCell() && (formulaResult.type !== cElementType.array && formulaResult.type !== cElementType.cellsRange && formulaResult.type !== cElementType.cellsRange3D)) {
|
|
applyByArray = false;
|
|
ctrlKey = false;
|
|
}
|
|
|
|
dynamicRange = tempDynamicSelectionRange.bbox;
|
|
}
|
|
|
|
return {applyByArray: applyByArray, ctrlKey: ctrlKey, dynamicRange: dynamicRange, cannotChangeFormulaArray: cannotChangeFormulaArray};
|
|
}
|
|
};
|
|
|
|
Worksheet.prototype.findEOT = function (bCheckStyles) {
|
|
var maxCols = this.getColsCount();
|
|
var maxRows = this.getRowsCount();
|
|
var lastC = -1, lastR = -1;
|
|
|
|
let t = this;
|
|
let _cell = null;
|
|
let _getCell = function (_col, _row) {
|
|
if (_col < 0 || _col > gc_nMaxCol0 || _row < 0 || _row > gc_nMaxRow0) {
|
|
return null;
|
|
}
|
|
|
|
return t.getCell3(_row, _col);
|
|
};
|
|
let _isCellNullText = function (_col, _row) {
|
|
let c = _col;
|
|
_cell = null;
|
|
if (row !== undefined) {
|
|
c = _getCell(_col, _row);
|
|
_cell = c;
|
|
}
|
|
return null === c || c.isNullText();
|
|
};
|
|
|
|
let isEmptyCell = function () {
|
|
if (_cell) {
|
|
if (_cell.hasMerged()) {
|
|
return false;
|
|
} else {
|
|
var ws = _cell.worksheet;
|
|
var nRow = _cell.bbox.r1;
|
|
var nCol = _cell.bbox.c1;
|
|
var xfs;
|
|
ws._getCellNoEmpty(nRow, nCol, function (oCell) {
|
|
xfs = ws.getCompiledStyle(nRow, nCol, oCell);
|
|
});
|
|
if (xfs) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
for (var col = 0; col < maxCols; ++col) {
|
|
for (var row = 0; row < maxRows; ++row) {
|
|
if (!_isCellNullText(col, row) || (bCheckStyles && !isEmptyCell())) {
|
|
lastC = Math.max(lastC, col);
|
|
lastR = Math.max(lastR, row);
|
|
}
|
|
}
|
|
}
|
|
|
|
return new AscCommon.CellBase(lastR, lastC);
|
|
};
|
|
|
|
Worksheet.prototype.getAllInks = function(arrInks) {
|
|
arrInks = arrInks || [];
|
|
for (let i = 0; i < this.Drawings.length; i++) {
|
|
const oGraphicObject = this.Drawings[i].graphicObject;
|
|
if (oGraphicObject.isInk() || oGraphicObject.isHaveOnlyInks()) {
|
|
arrInks.push(oGraphicObject);
|
|
} else {
|
|
oGraphicObject.getAllInks(arrInks);
|
|
}
|
|
}
|
|
return arrInks;
|
|
};
|
|
Worksheet.prototype.getDrawingControls = function () {
|
|
const arrControls = [];
|
|
this.handleDrawings(function (oDrawing) {
|
|
if (oDrawing.isControl()) {
|
|
arrControls.push(oDrawing);
|
|
}
|
|
});
|
|
return arrControls;
|
|
};
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
var g_nCellStructSize = 4 + 4 + 8;
|
|
|
|
var g_nCellFlag_empty = 0;
|
|
var g_nCellFlag_init = 1;
|
|
var g_nCellFlag_typeMask = 6;
|
|
var g_nCellFlag_valueMask = 24;
|
|
var g_nCellFlag_isDirtyMask = 32;
|
|
var g_nCellFlag_isCalcMask = 64;
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function Cell(worksheet){
|
|
this.ws = worksheet;
|
|
this.nRow = -1;
|
|
this.nCol = -1;
|
|
this.xfs = null;
|
|
this.formulaParsed = null;
|
|
|
|
this.type = CellValueType.Number;
|
|
this.number = null;
|
|
this.text = null;
|
|
this.multiText = null;
|
|
this.textIndex = null;
|
|
|
|
this.isDirty = false;
|
|
this.isCalc = false;
|
|
|
|
this.cm = null;
|
|
this.vm = null;
|
|
|
|
this._hasChanged = false;
|
|
}
|
|
Cell.prototype.clear = function(keepIndex) {
|
|
this.nRow = -1;
|
|
this.nCol = -1;
|
|
this.clearData();
|
|
|
|
this._hasChanged = false;
|
|
};
|
|
Cell.prototype.clearData = function() {
|
|
this.xfs = null;
|
|
this.formulaParsed = null;
|
|
|
|
this.type = CellValueType.Number;
|
|
this.number = null;
|
|
this.text = null;
|
|
this.multiText = null;
|
|
this.textIndex = null;
|
|
|
|
this.isDirty = false;
|
|
this.isCalc = false;
|
|
|
|
this.cm = null;
|
|
this.vm = null;
|
|
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.clearDataKeepXf = function(border) {
|
|
var xfs = this.xfs;
|
|
this.clearData();
|
|
this.xfs = xfs;
|
|
AscCommon.History.TurnOff();
|
|
this.setBorder(border);
|
|
AscCommon.History.TurnOn();
|
|
};
|
|
Cell.prototype.saveContent = function(opt_inCaseOfChange) {
|
|
if (this.hasRowCol() && (!opt_inCaseOfChange || this._hasChanged)) {
|
|
this._hasChanged = false;
|
|
var wb = this.ws.workbook;
|
|
var sheetMemory = this.ws.getColData(this.nCol);
|
|
sheetMemory.checkIndex(this.nRow);
|
|
var xfSave = this.xfs ? this.xfs.getIndexNumber() : 0;
|
|
var numberSave = 0;
|
|
var formulaSave = this.formulaParsed ? wb.workbookFormulas.add(this.formulaParsed).getIndexNumber() : 0;
|
|
var flagValue = 0;
|
|
if (null != this.number) {
|
|
flagValue = 1;
|
|
const flags = this._toFlags(flagValue);
|
|
sheetMemory.setInt32(this.nRow, 0, xfSave | (flags << 24));
|
|
sheetMemory.setInt32(this.nRow, 4, formulaSave);
|
|
sheetMemory.setFloat64(this.nRow, 8, this.number);
|
|
} else if (null != this.text || null != this.multiText) {
|
|
flagValue = 2;
|
|
const flags = this._toFlags(flagValue);
|
|
sheetMemory.setInt32(this.nRow, 0, xfSave | (flags << 24));
|
|
sheetMemory.setInt32(this.nRow, 4, formulaSave);
|
|
numberSave = this.getTextIndex();
|
|
sheetMemory.setInt32(this.nRow, 8, numberSave);
|
|
} else {
|
|
const flags = this._toFlags(flagValue);
|
|
sheetMemory.setInt32(this.nRow, 0, xfSave | (flags << 24));
|
|
sheetMemory.setInt32(this.nRow, 4, formulaSave);
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype.loadContent = function(row, col, opt_sheetMemory) {
|
|
var res = false;
|
|
this.clear();
|
|
this.nRow = row;
|
|
this.nCol = col;
|
|
let sheetMemory = opt_sheetMemory;
|
|
if (!sheetMemory) {
|
|
sheetMemory = this.ws.getColDataNoEmpty(this.nCol);
|
|
if (!sheetMemory) {
|
|
return res;
|
|
}
|
|
}
|
|
if (sheetMemory.hasIndex(this.nRow)) {
|
|
const mix = sheetMemory.getInt32(this.nRow, 0);
|
|
const flags = (mix >> 24) & 0xff;
|
|
const xfIndex = mix & 0xffffff;
|
|
if (0 !== (g_nCellFlag_init & flags)) {
|
|
var wb = this.ws.workbook;
|
|
var flagValue = this._fromFlags(flags);
|
|
if (xfIndex > 0) {
|
|
this.xfs = g_StyleCache.getXf(xfIndex);
|
|
}
|
|
const formulaIndex = sheetMemory.getInt32(this.nRow, 4)
|
|
if (formulaIndex > 0) {
|
|
this.formulaParsed = wb.workbookFormulas.get(formulaIndex);
|
|
}
|
|
if (1 === flagValue) {
|
|
this.number = sheetMemory.getFloat64(this.nRow, 8);
|
|
} else if (2 === flagValue) {
|
|
this.textIndex = sheetMemory.getInt32(this.nRow, 8);
|
|
const text = wb.sharedStrings.get(this.textIndex);
|
|
typeof text === 'string' ? this.text = text : this.multiText = text;
|
|
}
|
|
res = true;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Cell.prototype._toFlags = function(flagValue) {
|
|
var flags = g_nCellFlag_init | (this.type << 1) | (flagValue << 3);
|
|
if(this.isDirty){
|
|
flags |= g_nCellFlag_isDirtyMask;
|
|
}
|
|
if(this.isCalc){
|
|
flags |= g_nCellFlag_isCalcMask;
|
|
}
|
|
return flags;
|
|
};
|
|
Cell.prototype._fromFlags = function(flags) {
|
|
this.type = (flags & g_nCellFlag_typeMask) >>> 1;
|
|
this.isDirty = 0 != (flags & g_nCellFlag_isDirtyMask);
|
|
this.isCalc = 0 != (flags & g_nCellFlag_isCalcMask);
|
|
return (flags & g_nCellFlag_valueMask) >>> 3;
|
|
};
|
|
Cell.prototype.processFormula = function(callback) {
|
|
if (this.formulaParsed) {
|
|
var shared = this.formulaParsed.getShared();
|
|
var offsetRow, offsetCol;
|
|
if (shared) {
|
|
offsetRow = this.nRow - shared.base.nRow;
|
|
offsetCol = this.nCol - shared.base.nCol;
|
|
if (0 !== offsetRow || 0 !== offsetCol) {
|
|
var oldRow = this.formulaParsed.parent.nRow;
|
|
var oldCol = this.formulaParsed.parent.nCol;
|
|
|
|
//todo assemble by param
|
|
var old = AscCommonExcel.g_ProcessShared;
|
|
AscCommonExcel.g_ProcessShared = true;
|
|
var offsetShared = new AscCommon.CellBase(offsetRow, offsetCol);
|
|
this.formulaParsed.changeOffset(offsetShared, false);
|
|
this.formulaParsed.parent.nRow = this.nRow;
|
|
this.formulaParsed.parent.nCol = this.nCol;
|
|
callback(this.formulaParsed);
|
|
offsetShared.row = -offsetRow;
|
|
offsetShared.col = -offsetCol;
|
|
this.formulaParsed.changeOffset(offsetShared, false);
|
|
this.formulaParsed.parent.nRow = oldRow;
|
|
this.formulaParsed.parent.nCol = oldCol;
|
|
AscCommonExcel.g_ProcessShared = old;
|
|
} else {
|
|
callback(this.formulaParsed);
|
|
}
|
|
} else {
|
|
callback(this.formulaParsed);
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype.setChanged = function(val) {
|
|
this._hasChanged = val;
|
|
};
|
|
Cell.prototype.getStyle=function(){
|
|
return this.xfs;
|
|
};
|
|
Cell.prototype.getCompiledStyle = function (opt_styleComponents, opt_AffectingText) {
|
|
return this.ws.getCompiledStyle(this.nRow, this.nCol, this, opt_styleComponents, opt_AffectingText);
|
|
};
|
|
Cell.prototype.getCompiledStyleCustom = function(needTable, needCell, needConditional) {
|
|
return this.ws.getCompiledStyleCustom(this.nRow, this.nCol, needTable, needCell, needConditional, this);
|
|
};
|
|
Cell.prototype.getTableStyle = function () {
|
|
var hiddenManager = this.ws.hiddenManager;
|
|
var sheetMergedStyles = this.ws.sheetMergedStyles;
|
|
var styleComponents = sheetMergedStyles.getStyle(hiddenManager, this.nRow, this.nCol, this.ws);
|
|
return getCompiledStyleFromArray(null, styleComponents.table);
|
|
};
|
|
Cell.prototype.duplicate=function(){
|
|
var t = this;
|
|
var oNewCell = new Cell(this.ws);
|
|
oNewCell.nRow = this.nRow;
|
|
oNewCell.nCol = this.nCol;
|
|
oNewCell.xfs = this.xfs;
|
|
oNewCell.type = this.type;
|
|
oNewCell.number = this.number;
|
|
oNewCell.text = this.text;
|
|
oNewCell.multiText = this.multiText;
|
|
this.processFormula(function(parsed) {
|
|
//todo without parse
|
|
var newFormula = new parserFormula(parsed.getFormula(), oNewCell, t.ws);
|
|
AscCommonExcel.executeInR1C1Mode(false, function () {
|
|
newFormula.parse();
|
|
});
|
|
if (parsed.ca) { // For recursive formulas
|
|
newFormula.ca = parsed.ca;
|
|
}
|
|
var arrayFormulaRef = parsed.getArrayFormulaRef();
|
|
if(arrayFormulaRef) {
|
|
newFormula.setArrayFormulaRef(arrayFormulaRef);
|
|
}
|
|
oNewCell.setFormulaInternal(newFormula);
|
|
});
|
|
return oNewCell;
|
|
};
|
|
Cell.prototype.clone=function(oNewWs, renameParams){
|
|
if(!oNewWs)
|
|
oNewWs = this.ws;
|
|
let oThis = this;
|
|
var oNewCell = new Cell(oNewWs);
|
|
oNewCell.nRow = this.nRow;
|
|
oNewCell.nCol = this.nCol;
|
|
if(null != this.xfs)
|
|
oNewCell.xfs = this.xfs;
|
|
oNewCell.type = this.type;
|
|
oNewCell.number = this.number;
|
|
oNewCell.text = this.text;
|
|
oNewCell.multiText = this.multiText;
|
|
this.processFormula(function(parsed) {
|
|
var newFormula;
|
|
if (oNewWs != oThis.ws && renameParams) {
|
|
var formula = parsed.clone(null, null, this.ws);
|
|
formula.renameSheetCopy(renameParams);
|
|
newFormula = formula.assemble(true);
|
|
} else {
|
|
newFormula = parsed.getFormula();
|
|
}
|
|
oNewCell.setFormulaInternal(new parserFormula(newFormula, oNewCell, oNewWs));
|
|
oNewWs.workbook.dependencyFormulas.addToBuildDependencyCell(oNewCell);
|
|
});
|
|
return oNewCell;
|
|
};
|
|
Cell.prototype.setRowCol=function(nRow, nCol){
|
|
this.nRow = nRow;
|
|
this.nCol = nCol;
|
|
};
|
|
Cell.prototype.hasRowCol = function() {
|
|
return this.nRow >= 0 && this.nCol >= 0;
|
|
};
|
|
Cell.prototype.isEqual = function (options) {
|
|
var cellText;
|
|
cellText = (options.lookIn === Asc.c_oAscFindLookIn.Formulas) ? this.getValueForEdit() : this.getValue();
|
|
if (true !== options.isMatchCase) {
|
|
cellText = cellText.toLowerCase();
|
|
}
|
|
var isWordEnter = cellText.indexOf(options.findWhat);
|
|
if (options.findWhat instanceof RegExp && options.isWholeWord) {
|
|
isWordEnter = cellText.search(options.findWhat);
|
|
}
|
|
return (0 <= isWordEnter) &&
|
|
(true !== options.isWholeCell || options.findWhat.length === cellText.length);
|
|
|
|
};
|
|
Cell.prototype.isNullText=function(){
|
|
return this.isNullTextString() && !this.formulaParsed;
|
|
};
|
|
Cell.prototype.isEmptyTextString = function() {
|
|
this._checkDirty();
|
|
if(null != this.number || (null != this.text && "" != this.text))
|
|
return false;
|
|
if(null != this.multiText && "" != AscCommonExcel.getStringFromMultiText(this.multiText))
|
|
return false;
|
|
return true;
|
|
};
|
|
Cell.prototype.isNullTextString = function() {
|
|
this._checkDirty();
|
|
return null === this.number && null === this.text && null === this.multiText;
|
|
};
|
|
Cell.prototype.isEmpty=function(){
|
|
if(false == this.isNullText())
|
|
return false;
|
|
if(null != this.xfs)
|
|
return false;
|
|
return true;
|
|
};
|
|
Cell.prototype.isFormula=function(){
|
|
return this.formulaParsed ? true : false;
|
|
};
|
|
Cell.prototype.getName=function(){
|
|
return g_oCellAddressUtils.getCellId(this.nRow, this.nCol);
|
|
};
|
|
Cell.prototype.setTypeInternal=function(val) {
|
|
this.type = val;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.correctValueByType = function() {
|
|
//todo implemented only Number->String. other is stub
|
|
switch (this.type) {
|
|
case CellValueType.Number:
|
|
if (null !== this.text) {
|
|
this.setValueNumberInternal(parseInt(this.text) || 0);
|
|
} else if (null !== this.multiText) {
|
|
this.setValueNumberInternal(0);
|
|
}
|
|
break;
|
|
case CellValueType.Bool:
|
|
if (null !== this.text || null !== this.multiText) {
|
|
this.setValueNumberInternal(0);
|
|
}
|
|
break;
|
|
case CellValueType.String:
|
|
if (null !== this.number) {
|
|
this.setValueTextInternal(this.number.toString());
|
|
}
|
|
break;
|
|
case CellValueType.Error:
|
|
if (null !== this.number) {
|
|
this.setValueTextInternal(cErrorOrigin["nil"]);
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
Cell.prototype.setValueNumberInternal=function(val) {
|
|
this.number = val;
|
|
this.text = null;
|
|
this.multiText = null;
|
|
this.textIndex = null;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.setValueTextInternal=function(val) {
|
|
this.number = null;
|
|
this.text = val;
|
|
this.multiText = null;
|
|
this.textIndex = null;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.setValueMultiTextInternal=function(val) {
|
|
this.number = null;
|
|
this.text = null;
|
|
this.multiText = val;
|
|
this.textIndex = null;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.setValue=function(val,callback, isCopyPaste, byRef, ignoreHyperlink, dynamicRange, skipExternalCheck) {
|
|
var ws = this.ws;
|
|
var wb = ws.workbook;
|
|
var DataOld = null;
|
|
if (AscCommon.History.Is_On()) {
|
|
DataOld = this.getValueData();
|
|
}
|
|
var isFirstArrayFormulaCell = byRef && this.nCol === byRef.c1 && this.nRow === byRef.r1;
|
|
var newFP = this.setValueGetParsed(val, callback, isCopyPaste, byRef, dynamicRange);
|
|
if (undefined === newFP) {
|
|
return;
|
|
}
|
|
|
|
var oldFP = this.formulaParsed;
|
|
//удаляем старые значения
|
|
this.cleanText();
|
|
this.setFormulaInternal(null);
|
|
|
|
if (newFP) {
|
|
this.setFormulaInternal(newFP);
|
|
if(byRef) {
|
|
if(isFirstArrayFormulaCell) {
|
|
if (dynamicRange) {
|
|
this.setDynamicArrayFlags();
|
|
}
|
|
wb.dependencyFormulas.addToBuildDependencyArray(newFP);
|
|
}
|
|
} else {
|
|
wb.dependencyFormulas.addToBuildDependencyCell(this);
|
|
}
|
|
if (this.ws.workbook.handlers) {
|
|
this.ws.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.cellValue, this, null, this.ws.getId());
|
|
}
|
|
} else if (val) {
|
|
this._setValue(val, ignoreHyperlink);
|
|
if (!ignoreHyperlink && window['AscCommonExcel'].g_AutoCorrectHyperlinks) {
|
|
this._autoformatHyperlink(val);
|
|
}
|
|
wb.dependencyFormulas.addToChangedCell(this);
|
|
} else {
|
|
// when deleting a cell value we get here
|
|
if (oldFP && oldFP.dynamicRange) {
|
|
isFirstArrayFormulaCell = this.nCol === oldFP.dynamicRange.c1 && this.nRow === oldFP.dynamicRange.r1;
|
|
// we check here and add the range with daf to the dependency sheet
|
|
if (isFirstArrayFormulaCell) {
|
|
wb.dependencyFormulas.addToChangedRange2(oldFP.getWs().getId(), oldFP.getDynamicRef());
|
|
}
|
|
} else {
|
|
wb.dependencyFormulas.addToChangedCell(this);
|
|
}
|
|
if (this.ws.workbook.handlers) {
|
|
this.ws.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.cellValue, this, null, this.ws.getId());
|
|
}
|
|
}
|
|
|
|
var DataNew = null;
|
|
if (g_cCalcRecursion.getCellPasteValue() != null) {
|
|
this.setValueNumberInternal(g_cCalcRecursion.getCellPasteValue());
|
|
g_cCalcRecursion.setCellPasteValue(null);
|
|
}
|
|
if (AscCommon.History.Is_On()) {
|
|
DataNew = this.getValueData();
|
|
}
|
|
if (AscCommon.History.Is_On() && false == DataOld.isEqual(DataNew)) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(),
|
|
new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow),
|
|
new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, DataNew));
|
|
}
|
|
//sortDependency вызывается ниже AscCommon.History.Add(AscCH.historyitem_Cell_ChangeValue, потому что в ней может быть выставлен формат ячейки(если это текстовый, то принимая изменения формула станет текстом)
|
|
this.ws.workbook.sortDependency();
|
|
if (!this.ws.workbook.dependencyFormulas.isLockRecal()) {
|
|
this._adjustCellFormat();
|
|
}
|
|
|
|
//todo не должны удаляться ссылки, если сделать merge ее части.
|
|
if (this.isNullTextString() && !this.isFormula()) {
|
|
var cell = this.ws.getCell3(this.nRow, this.nCol);
|
|
cell.removeHyperlink();
|
|
}
|
|
|
|
if (!skipExternalCheck) {
|
|
this.checkRemoveExternalReferences(newFP, oldFP);
|
|
}
|
|
};
|
|
|
|
Cell.prototype.checkRemoveExternalReferences=function(fNew, fOld) {
|
|
//1.проверяем, были ли ссылки на внешние данные
|
|
let externalLinks;
|
|
let i;
|
|
if (fOld && (!fNew || fNew.Formula !== fOld.Formula) && fOld.outStack) {
|
|
let needCheckImportFuncs = false;
|
|
for (i = 0; i < fOld.outStack.length; i++) {
|
|
if (fOld.outStack[i].externalLink) {
|
|
if (!externalLinks) {
|
|
externalLinks = {};
|
|
}
|
|
externalLinks[fOld.outStack[i].externalLink] = fOld.outStack[i].getWsId();
|
|
} else if (fOld.outStack[i].type === cElementType.func && fOld.outStack[i].name === "IMPORTRANGE") {
|
|
needCheckImportFuncs = true;
|
|
}
|
|
}
|
|
|
|
if (needCheckImportFuncs) {
|
|
AscCommonExcel.importRangeLinksState.startBuildImportRangeLinks = true;
|
|
fOld.calculate();
|
|
AscCommonExcel.importRangeLinksState.startBuildImportRangeLinks = null;
|
|
|
|
if (AscCommonExcel.importRangeLinksState.importRangeLinks) {
|
|
for (i in AscCommonExcel.importRangeLinksState.importRangeLinks) {
|
|
for (let j = 0; j < AscCommonExcel.importRangeLinksState.importRangeLinks[i].length; j++) {
|
|
if (AscCommonExcel.importRangeLinksState.importRangeLinks[i][j]) {
|
|
let ws = this.ws.workbook.getExternalWorksheet(i, AscCommonExcel.importRangeLinksState.importRangeLinks[i][j].sheet);
|
|
if (ws) {
|
|
if (!externalLinks) {
|
|
externalLinks = {};
|
|
}
|
|
externalLinks[i] = ws.getId();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
AscCommonExcel.importRangeLinksState.importRangeLinks = null;
|
|
}
|
|
}
|
|
|
|
|
|
//2. проверяем, каких ссылок не осталось в новых данных
|
|
if (externalLinks && fNew && fNew.outStack) {
|
|
for (i = 0; i < fNew.outStack.length; i++) {
|
|
if (fNew.outStack[i].externalLink) {
|
|
if (externalLinks[fNew.outStack[i].externalLink]) {
|
|
delete externalLinks[fNew.outStack[i].externalLink];
|
|
}
|
|
}
|
|
}
|
|
if (fNew.importFunctionsRangeLinks) {
|
|
for (i in fNew.importFunctionsRangeLinks) {
|
|
if (externalLinks[i]) {
|
|
delete externalLinks[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//3. проверям, не ссылаются ли на эти ссылки кто-то другой
|
|
if (externalLinks && fOld) {
|
|
let listenerId = fOld.getListenerId();
|
|
|
|
for (let link in externalLinks) {
|
|
// check all external link listeners
|
|
// let erIndex = this.getExternalLinkIndexBySheetId(sheetId);
|
|
// let eR = this.ws.workbook.externalReferences[+index - 1];
|
|
let index = this.ws.workbook.getExternalLinkIndexBySheetId(externalLinks[link]);
|
|
let eR = this.ws.workbook.externalReferences[index - 1];
|
|
|
|
if (eR && null != listenerId) {
|
|
let hasListeners;
|
|
for (let ws in eR.worksheets) {
|
|
// if listeners are found, then we interrupt the cycle and move on to the next external link
|
|
if (hasListeners) {
|
|
break
|
|
}
|
|
|
|
let wsId = eR.worksheets[ws].getId();
|
|
let sheetContainer = fOld.wb && fOld.wb.dependencyFormulas && fOld.wb.dependencyFormulas.sheetListeners && fOld.wb.dependencyFormulas.sheetListeners[wsId];
|
|
|
|
if (sheetContainer) {
|
|
if (Object.keys(sheetContainer.cellMap).length === 0 && Object.keys(sheetContainer.areaMap).length === 0 && Object.keys(sheetContainer.defName3d).length === 0) {
|
|
hasListeners = false;
|
|
} else {
|
|
hasListeners = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!hasListeners) {
|
|
this.ws && this.ws.workbook && this.ws.workbook.removeExternalReference(index, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// //3. проверям, не ссылаются ли на эти ссылки кто-то другой
|
|
// if (externalLinks && fOld) {
|
|
// let listenerId = fOld.getListenerId();
|
|
// for (i in externalLinks) {
|
|
// if (null != listenerId) {
|
|
// let sheetId = externalLinks[i];
|
|
// let sheetContainer = fOld.wb && fOld.wb.dependencyFormulas && fOld.wb.dependencyFormulas.sheetListeners && fOld.wb.dependencyFormulas.sheetListeners[sheetId];
|
|
// if (sheetContainer && Object.keys(sheetContainer.cellMap).length === 0) {
|
|
// //если есть ссылки на внешние источники, необходимо их удалить
|
|
// this.ws && this.ws.workbook && this.ws.workbook.removeExternalReferenceBySheet(sheetId);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
};
|
|
|
|
Cell.prototype.setValueGetParsed=function(val,callback, isCopyPaste, byRef, dynamicRange) {
|
|
var ws = this.ws;
|
|
var wb = ws.workbook;
|
|
var bIsTextFormat = false;
|
|
if (!isCopyPaste) {
|
|
var sNumFormat;
|
|
if (null != this.xfs && null != this.xfs.num) {
|
|
sNumFormat = this.xfs.num.getFormat();
|
|
} else {
|
|
sNumFormat = g_oDefaultFormat.Num.getFormat();
|
|
}
|
|
var numFormat = oNumFormatCache.get(sNumFormat);
|
|
bIsTextFormat = numFormat.isTextFormat();
|
|
}
|
|
|
|
var isFirstArrayFormulaCell = byRef && this.nCol === byRef.c1 && this.nRow === byRef.r1;
|
|
var newFP = null;
|
|
if (false == bIsTextFormat || (byRef && !isFirstArrayFormulaCell)) {
|
|
/*
|
|
Устанавливаем значение в Range ячеек. При этом происходит проверка значения на формулу.
|
|
Если значение является формулой, то проверяем содержиться ли в ячейке формула или нет, если "да" - то очищаем в графе зависимостей список, от которых зависит формула(masterNodes), позже будет построен новый. Затем выставляем флаг о необходимости дальнейшего пересчета, и заносим ячейку в список пересчитываемых ячеек.
|
|
*/
|
|
if (null != val && val[0] == "=" && val.length > 1) {
|
|
//***array-formula***
|
|
if(byRef && !isFirstArrayFormulaCell) {
|
|
newFP = this.ws.formulaArrayLink;
|
|
if(newFP === null) {
|
|
return;
|
|
}
|
|
if(this.nCol === byRef.c2 && this.nRow === byRef.r2) {
|
|
this.ws.formulaArrayLink = null;
|
|
}
|
|
} else {
|
|
var cellWithFormula = new CCellWithFormula(this.ws, this.nRow, this.nCol);
|
|
newFP = new parserFormula(val.substring(1), cellWithFormula, this.ws);
|
|
|
|
var formulaLocaleParse = isCopyPaste === true ? false : oFormulaLocaleInfo.Parse;
|
|
var formulaLocaleDigetSep = isCopyPaste === true ? false : oFormulaLocaleInfo.DigitSep;
|
|
var parseResult = new AscCommonExcel.ParseResult();
|
|
if (!newFP.parse(formulaLocaleParse, formulaLocaleDigetSep, parseResult)) {
|
|
switch (parseResult.error) {
|
|
case c_oAscError.ID.FrmlWrongFunctionName:
|
|
break;
|
|
case c_oAscError.ID.FrmlParenthesesCorrectCount:
|
|
return this.setValueGetParsed("=" + newFP.getFormula(), callback, isCopyPaste, byRef);
|
|
default :
|
|
{
|
|
var _pasteHelper = window['AscCommon'].g_specialPasteHelper;
|
|
var isPaste = _pasteHelper && _pasteHelper.pasteStart;
|
|
if (isPaste) {
|
|
if (!_pasteHelper._formulaError) {
|
|
_pasteHelper._formulaError = true;
|
|
wb.handlers && wb.handlers.trigger("asc_onError", parseResult.error, c_oAscError.Level.NoCritical);
|
|
}
|
|
} else {
|
|
wb.handlers && wb.handlers.trigger("asc_onError", parseResult.error, c_oAscError.Level.NoCritical);
|
|
}
|
|
if (callback) {
|
|
callback(false);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
newFP.setFormulaString(newFP.assemble());
|
|
//***dynamic-array-formula***
|
|
if(byRef && dynamicRange) {
|
|
newFP.dynamicRange = dynamicRange;
|
|
newFP.ref = byRef;
|
|
this.ws.formulaArrayLink = newFP;
|
|
}
|
|
//***array-formula***
|
|
else if(byRef) {
|
|
newFP.ref = byRef;
|
|
this.ws.formulaArrayLink = newFP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return newFP;
|
|
};
|
|
Cell.prototype.setValue2=function(array){
|
|
var DataOld = null;
|
|
if(AscCommon.History.Is_On())
|
|
DataOld = this.getValueData();
|
|
//[{text:"",format:TextFormat},{}...]
|
|
var xfTableAndCond = this.getCompiledStyleCustom(true, false, true);
|
|
var oldFP = this.formulaParsed;
|
|
this.setFormulaInternal(null);
|
|
this.cleanText();
|
|
this._setValue2(array, undefined, xfTableAndCond);
|
|
this.ws.workbook.dependencyFormulas.addToChangedCell(this);
|
|
this.ws.workbook.sortDependency();
|
|
var DataNew = null;
|
|
if(AscCommon.History.Is_On())
|
|
DataNew = this.getValueData();
|
|
if(AscCommon.History.Is_On() && false == DataOld.isEqual(DataNew)) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, DataNew));
|
|
}
|
|
//todo не должны удаляться ссылки, если сделать merge ее части.
|
|
if(this.isNullTextString())
|
|
{
|
|
var cell = this.ws.getCell3(this.nRow, this.nCol);
|
|
cell.removeHyperlink();
|
|
}
|
|
this.checkRemoveExternalReferences(this.formulaParsed, oldFP);
|
|
};
|
|
Cell.prototype.setValueForValidation = function(array, formula, callback, isCopyPaste, byRef) {
|
|
this.setFormulaInternal(null, true);
|
|
this.cleanText();
|
|
if (formula) {
|
|
var newFP = this.setValueGetParsed(formula, callback, isCopyPaste, byRef);
|
|
this.ws.formulaArrayLink = null;//todo
|
|
if (newFP) {
|
|
this.setFormulaInternal(newFP, true);
|
|
newFP.calculate();
|
|
this._updateCellValue();
|
|
} else if (undefined !== newFP) {
|
|
this._setValue(formula);
|
|
}
|
|
} else {
|
|
this._setValue2(array, true);
|
|
}
|
|
};
|
|
Cell.prototype.setFormulaTemplate = function(bHistoryUndo, action) {
|
|
const formulaParsed = this.getFormulaParsed();
|
|
let DataOld = null;
|
|
let DataNew = null;
|
|
if (AscCommon.History.Is_On()) {
|
|
DataOld = this.getValueData();
|
|
}
|
|
|
|
if (!formulaParsed || (formulaParsed && !formulaParsed.ca)) {
|
|
this.cleanText();
|
|
}
|
|
action(this);
|
|
|
|
if (AscCommon.History.Is_On()) {
|
|
DataNew = this.getValueData();
|
|
if (DataOld.isEqual(DataNew) === false){
|
|
let typeHistory = bHistoryUndo ? AscCH.historyitem_Cell_ChangeValueUndo : AscCH.historyitem_Cell_ChangeValue;
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, typeHistory, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, DataNew), bHistoryUndo);}
|
|
}
|
|
};
|
|
Cell.prototype.setFormula = function(formula, bHistoryUndo, formulaRef, caProps) {
|
|
var cellWithFormula = new CCellWithFormula(this.ws, this.nRow, this.nCol);
|
|
var parser = new parserFormula(formula, cellWithFormula, this.ws);
|
|
if (caProps && caProps.ca) {
|
|
parser.ca = caProps.ca;
|
|
}
|
|
if(formulaRef) {
|
|
/* when merging, the formulaRef is taken with the old data, we need to shift ref to topLeftCell */
|
|
// parser.setArrayFormulaRef(formulaRef);
|
|
// this.ws.getRange3(formulaRef.r1, formulaRef.c1, formulaRef.r2, formulaRef.c2)._foreachNoEmpty(function(cell){
|
|
// cell.setFormulaParsed(parser, bHistoryUndo);
|
|
// });
|
|
if ((this.nCol !== formulaRef.c1 || this.nRow !== formulaRef.r1) && !formulaRef.isOneCell()) {
|
|
return;
|
|
}
|
|
let newFormulaRef = formulaRef.isOneCell() ? new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow) : formulaRef;
|
|
parser.setArrayFormulaRef(newFormulaRef);
|
|
this.ws.getRange3(newFormulaRef.r1, newFormulaRef.c1, newFormulaRef.r2, newFormulaRef.c2)._foreach2(function(cell){
|
|
cell && cell.setFormulaParsed(parser, bHistoryUndo);
|
|
});
|
|
} else {
|
|
this.setFormulaParsed(parser, bHistoryUndo, caProps);
|
|
}
|
|
};
|
|
Cell.prototype.setFormulaParsed = function(parsed, bHistoryUndo, caProps) {
|
|
this.setFormulaTemplate(bHistoryUndo, function(cell){
|
|
cell.setFormulaInternal(parsed);
|
|
cell.ws.workbook.dependencyFormulas.addToBuildDependencyCell(cell);
|
|
if (caProps) {
|
|
if (caProps.oldValue != null) {
|
|
cell.setValueNumberInternal(caProps.oldValue);
|
|
} else if (caProps.oldValueText != null) {
|
|
cell.setTypeInternal(CellValueType.String);
|
|
cell.setValueTextInternal(caProps.oldValueText);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Cell.prototype.setFormulaInternal = function(formula, dontTouchPrev) {
|
|
if (!dontTouchPrev && this.formulaParsed) {
|
|
let shared = this.formulaParsed.getShared();
|
|
let arrayFormula = this.formulaParsed.getArrayFormulaRef();
|
|
let dynamicRange = this.formulaParsed.getDynamicRef();
|
|
if (shared) {
|
|
if (shared.ref.isOnTheEdge(this.nCol, this.nRow)) {
|
|
this.ws.workbook.dependencyFormulas.addToChangedShared(this.formulaParsed);
|
|
}
|
|
var index = this.ws.workbook.workbookFormulas.add(this.formulaParsed).getIndexNumber();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_RemoveSharedFormula, this.ws.getId(),
|
|
new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, index, null), true);
|
|
} else if(arrayFormula && this.formulaParsed.checkFirstCellArray(this)) {
|
|
//***array-formula***
|
|
var fText = "=" + this.formulaParsed.getFormula();
|
|
this.formulaParsed.removeDependencies();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoArrayFormula, AscCH.historyitem_ArrayFromula_DeleteFormula, this.ws.getId(),
|
|
new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new AscCommonExcel.UndoRedoData_ArrayFormula(arrayFormula, fText), true);
|
|
} else {
|
|
this.formulaParsed.removeDependencies();
|
|
}
|
|
}
|
|
this.formulaParsed = formula;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.transformSharedFormula = function() {
|
|
var res = false;
|
|
var parsed = this.formulaParsed;
|
|
if (parsed) {
|
|
var shared = parsed.getShared();
|
|
if (shared) {
|
|
var offsetShared = new AscCommon.CellBase(this.nRow - shared.base.nRow, this.nCol - shared.base.nCol);
|
|
var cellWithFormula = new AscCommonExcel.CCellWithFormula(this.ws, this.nRow, this.nCol);
|
|
var newFormula = parsed.clone(undefined, cellWithFormula);
|
|
newFormula.removeShared();
|
|
newFormula.changeOffset(offsetShared, false);
|
|
newFormula.setFormulaString(newFormula.assemble(true));
|
|
this.setFormulaInternal(newFormula);
|
|
res = true;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Cell.prototype.changeOffset = function(offset, canResize, bHistoryUndo, notOffset3d) {
|
|
this.setFormulaTemplate(bHistoryUndo, function(cell){
|
|
cell.transformSharedFormula();
|
|
var parsed = cell.getFormulaParsed();
|
|
parsed.removeDependencies();
|
|
parsed.changeOffset(offset, canResize, null, notOffset3d);
|
|
parsed.setFormulaString(parsed.assemble(true));
|
|
parsed.buildDependencies();
|
|
});
|
|
};
|
|
Cell.prototype.setType=function(type){
|
|
if(type != this.type){
|
|
var DataOld = this.getValueData();
|
|
this.setTypeInternal(type);
|
|
this.correctValueByType();
|
|
this._hasChanged = true;
|
|
var DataNew = this.getValueData();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, DataNew));
|
|
}
|
|
return type;
|
|
};
|
|
Cell.prototype.changeTextCase=function(type){
|
|
if (this.isEmpty() || this.isFormula()) {
|
|
return;
|
|
}
|
|
|
|
if(null != this.multiText) {
|
|
let dataOld = this._cloneMultiText();
|
|
let changedText = changeTextCase(this.multiText, type);
|
|
|
|
if (changedText) {
|
|
let dataNew = this._cloneMultiText();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeArrayValueFormat,
|
|
this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow),
|
|
new UndoRedoData_CellSimpleData(this.nRow, this.nCol, dataOld, dataNew));
|
|
}
|
|
} else if (null != this.text) {
|
|
let changedText = changeTextCase([{text: this.text}], type);
|
|
if (changedText && changedText.text) {
|
|
this.setValue(changedText.text);
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype.getType=function(){
|
|
this._checkDirty();
|
|
return this.type;
|
|
};
|
|
Cell.prototype.setCellStyle=function(val){
|
|
var oStyle;
|
|
var newVal = this.ws.workbook.CellStyles._prepareCellStyle(val);
|
|
var oRes = this.ws.workbook.oStyleManager.setCellStyle(this, newVal);
|
|
if(AscCommon.History.Is_On()) {
|
|
var oldStyleName = this.ws.workbook.CellStyles.getStyleNameByXfId(oRes.oldVal);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Style, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oldStyleName, val));
|
|
|
|
// Выставляем стиль
|
|
oStyle = this.ws.workbook.CellStyles.getStyleByXfId(oRes.newVal);
|
|
if (oStyle.ApplyFont)
|
|
this.setFont(oStyle.getFont());
|
|
if (oStyle.ApplyFill)
|
|
this.setFill(oStyle.getFill());
|
|
if (oStyle.ApplyBorder)
|
|
this.setBorder(oStyle.getBorder());
|
|
if (oStyle.ApplyNumberFormat)
|
|
this.setNumFormat(oStyle.getNumFormatStr());
|
|
}
|
|
return oStyle;
|
|
};
|
|
Cell.prototype.setNumFormat=function(val){
|
|
this.setNum(new AscCommonExcel.Num({f:val}));
|
|
};
|
|
Cell.prototype.setNum=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setNum(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Num, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.getShiftedNumFormat=function(nShift, dDigitsCount){
|
|
let newNumFormat;
|
|
var sNumFormat;
|
|
if(null != this.xfs && null != this.xfs.num)
|
|
sNumFormat = this.xfs.num.getFormat();
|
|
else
|
|
sNumFormat = g_oDefaultFormat.Num.getFormat();
|
|
var type = this.getType();
|
|
var oCurNumFormat = oNumFormatCache.get(sNumFormat);
|
|
if (null != oCurNumFormat && !oCurNumFormat.isGeneralFormat()) {
|
|
let output = {};
|
|
if (oCurNumFormat.shiftFormat(output, nShift)) {
|
|
newNumFormat = output.format;
|
|
}
|
|
} else if (CellValueType.Number == type) {
|
|
var sGeneral = AscCommon.DecodeGeneralFormat(this.number, type, dDigitsCount);
|
|
var oGeneral = oNumFormatCache.get(sGeneral);
|
|
if (null != oGeneral && !oGeneral.isGeneralFormat()) {
|
|
let output = {};
|
|
if (oGeneral.shiftFormat(output, nShift)) {
|
|
newNumFormat = output.format;
|
|
}
|
|
}
|
|
}
|
|
return newNumFormat;
|
|
};
|
|
Cell.prototype.setFont=function(val, bModifyValue){
|
|
if(false != bModifyValue)
|
|
{
|
|
//убираем комплексные строки
|
|
if(null != this.multiText && false == this.ws.workbook.bUndoChanges && false == this.ws.workbook.bRedoChanges)
|
|
{
|
|
var oldVal = null;
|
|
if(AscCommon.History.Is_On())
|
|
oldVal = this.getValueData();
|
|
this.setValueTextInternal(AscCommonExcel.getStringFromMultiText(this.multiText));
|
|
if(AscCommon.History.Is_On())
|
|
{
|
|
var newVal = this.getValueData();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oldVal, newVal));
|
|
}
|
|
}
|
|
}
|
|
var oRes = this.ws.workbook.oStyleManager.setFont(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
{
|
|
var oldVal = null;
|
|
if(null != oRes.oldVal)
|
|
oldVal = oRes.oldVal.clone();
|
|
var newVal = null;
|
|
if(null != oRes.newVal)
|
|
newVal = oRes.newVal.clone();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetFont, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oldVal, newVal));
|
|
}
|
|
};
|
|
Cell.prototype.setFontname=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setFontname(this, val);
|
|
this._setFontProp(function(format){return val != format.getName();}, function(format){format.setName(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Fontname, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setFontsize=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setFontsize(this, val);
|
|
this._setFontProp(function(format){return val != format.getSize();}, function(format){format.setSize(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Fontsize, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setFontcolor=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setFontcolor(this, val);
|
|
this._setFontProp(function(format){return val != format.getColor();}, function(format){format.setColor(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Fontcolor, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setBold=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setBold(this, val);
|
|
this._setFontProp(function(format){return val != format.getBold();}, function(format){format.setBold(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Bold, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setItalic=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setItalic(this, val);
|
|
this._setFontProp(function(format){return val != format.getItalic();}, function(format){format.setItalic(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Italic, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setUnderline=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setUnderline(this, val);
|
|
this._setFontProp(function(format){return val != format.getUnderline();}, function(format){format.setUnderline(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Underline, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setStrikeout=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setStrikeout(this, val);
|
|
this._setFontProp(function(format){return val != format.getStrikeout();}, function(format){format.setStrikeout(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Strikeout, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setFontAlign=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setFontAlign(this, val);
|
|
this._setFontProp(function(format){return val != format.getVerticalAlign();}, function(format){format.setVerticalAlign(val);});
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_FontAlign, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setAlignVertical=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setAlignVertical(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_AlignVertical, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setAlignHorizontal=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setAlignHorizontal(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_AlignHorizontal, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setReadingOrder=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setReadingOrder(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ReadingOrder, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setFill=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setFill(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Fill, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setFillColor=function(val){
|
|
var fill = new AscCommonExcel.Fill();
|
|
fill.fromColor(val);
|
|
return this.setFill(fill);
|
|
};
|
|
Cell.prototype.setBorder=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setBorder(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal){
|
|
var oldVal = null;
|
|
if(null != oRes.oldVal)
|
|
oldVal = oRes.oldVal.clone();
|
|
var newVal = null;
|
|
if(null != oRes.newVal)
|
|
newVal = oRes.newVal.clone();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Border, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oldVal, newVal));
|
|
}
|
|
};
|
|
Cell.prototype.setShrinkToFit=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setShrinkToFit(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ShrinkToFit, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setWrap=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setWrap(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Wrap, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setAngle=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setAngle(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Angle, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setIndent=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setIndent(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_Indent, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setQuotePrefix=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setQuotePrefix(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetQuotePrefix, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setApplyProtection=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setApplyProtection(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetApplyProtection, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setLocked=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setLocked(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetLocked, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setHiddenFormulas=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setHiddenFormulas(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetHidden, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setPivotButton=function(val){
|
|
var oRes = this.ws.workbook.oStyleManager.setPivotButton(this, val);
|
|
if(AscCommon.History.Is_On() && oRes.oldVal != oRes.newVal)
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetPivotButton, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oRes.oldVal, oRes.newVal));
|
|
};
|
|
Cell.prototype.setStyle=function(xfs){
|
|
var oldVal = this.xfs;
|
|
this.setStyleInternal(xfs);
|
|
if(AscCommon.History.Is_On() && oldVal != this.xfs)
|
|
{
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_SetStyle, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, oldVal, this.xfs));
|
|
}
|
|
};
|
|
Cell.prototype.setStyleInternal = function(xfs) {
|
|
this.xfs = g_StyleCache.addXf(xfs);
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.getFormula=function(){
|
|
var res = "";
|
|
this.processFormula(function(parsed) {
|
|
res = parsed.getFormula();
|
|
});
|
|
return res;
|
|
};
|
|
Cell.prototype.getFormulaParsed=function(){
|
|
return this.formulaParsed;
|
|
};
|
|
Cell.prototype.getValueForEdit = function(checkFormulaArray) {
|
|
this._checkDirty();
|
|
//todo
|
|
// if (CellValueType.Error == this.getType()) {
|
|
// return this._getValueTypeError(textValueForEdit);
|
|
// }
|
|
if ((this.ws && this.ws.getSheetProtection() && this.xfs && this.xfs.getHidden()) ||
|
|
(this.ws.isUserProtectedRangesIntersectionCell(this, null, null, Asc.c_oSerUserProtectedRangeType.View))
|
|
|| !this.ws.isUserProtectedRangesCanView(this, null)) {
|
|
return "";
|
|
}
|
|
|
|
var res = AscCommonExcel.getStringFromMultiText(this.getValueForEdit2());
|
|
return this.formulaParsed && this.formulaParsed.ref && checkFormulaArray ? "{" + res + "}" : res;
|
|
};
|
|
Cell.prototype.getValueForEdit2 = function() {
|
|
this._checkDirty();
|
|
var cultureInfo = AscCommon.g_oDefaultCultureInfo;
|
|
//todo проблема точности. в excel у чисел только 15 значащих цифр у нас больше.
|
|
//применяем форматирование
|
|
var oValueText = null;
|
|
var oValueArray = null;
|
|
var xfs = this.getCompiledStyle();
|
|
if (this.isFormula()) {
|
|
if (!((this.ws && this.ws.getSheetProtection() && this.xfs && this.xfs.getHidden() ||
|
|
(this.ws.isUserProtectedRangesIntersectionCell(this, null, null, Asc.c_oSerUserProtectedRangeType.View))))) {
|
|
this.processFormula(function (parsed) {
|
|
// ToDo если будет притормаживать, то завести переменную и не рассчитывать каждый раз!
|
|
oValueText = "=" + parsed.assembleLocale(AscCommonExcel.cFormulaFunctionToLocale, true);
|
|
});
|
|
}
|
|
} else {
|
|
if(null != this.text || null != this.number)
|
|
{
|
|
if (CellValueType.Bool === this.type && null != this.number)
|
|
oValueText = (this.number == 1) ? cBoolLocal.t : cBoolLocal.f;
|
|
else
|
|
{
|
|
if(null != this.text)
|
|
oValueText = this.text;
|
|
if(CellValueType.Number === this.type || CellValueType.String === this.type)
|
|
{
|
|
var oNumFormat;
|
|
if(null != xfs && null != xfs.num)
|
|
oNumFormat = oNumFormatCache.get(xfs.num.getFormat());
|
|
else
|
|
oNumFormat = oNumFormatCache.get(g_oDefaultFormat.Num.getFormat());
|
|
if(CellValueType.String != this.type && null != oNumFormat && null != this.number)
|
|
{
|
|
var nValue = this.number;
|
|
var oTargetFormat = oNumFormat.getFormatByValue(nValue);
|
|
if(oTargetFormat)
|
|
{
|
|
if(1 == oTargetFormat.nPercent)
|
|
{
|
|
//prercent
|
|
oValueText = AscCommon.oGeneralEditFormatCache.format(nValue * 100) + "%";
|
|
}
|
|
else if(oTargetFormat.bDateTime)
|
|
{
|
|
//Если число не подходит под формат даты возвращаем само число
|
|
if(false == oTargetFormat.isInvalidDateValue(nValue))
|
|
{
|
|
var bDate = oTargetFormat.bDate;
|
|
var bTime = oTargetFormat.bTime;
|
|
if(false == bDate && nValue >= 1)
|
|
bDate = true;
|
|
if(false == bTime && Math.floor(nValue) != nValue)
|
|
bTime = true;
|
|
var sDateFormat = "";
|
|
if (bDate) {
|
|
sDateFormat = AscCommon.getShortDateFormat(cultureInfo);
|
|
}
|
|
var sTimeFormat = 'h:mm:ss';
|
|
|
|
if (AscCommon.is12HourTimeFormat(cultureInfo)){
|
|
sTimeFormat += ' AM/PM';
|
|
}
|
|
if(bDate && bTime)
|
|
oNumFormat = oNumFormatCache.get(sDateFormat + ' ' + sTimeFormat);
|
|
else if(bTime)
|
|
oNumFormat = oNumFormatCache.get(sTimeFormat);
|
|
else
|
|
oNumFormat = oNumFormatCache.get(sDateFormat);
|
|
|
|
var aFormatedValue = oNumFormat.format(nValue, CellValueType.Number, AscCommon.gc_nMaxDigCount);
|
|
oValueText = "";
|
|
for(var i = 0, length = aFormatedValue.length; i < length; ++i)
|
|
oValueText += aFormatedValue[i].text;
|
|
}
|
|
else
|
|
oValueText = AscCommon.oGeneralEditFormatCache.format(nValue);
|
|
}
|
|
else
|
|
oValueText = AscCommon.oGeneralEditFormatCache.format(nValue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(this.multiText)
|
|
oValueArray = this.multiText;
|
|
}
|
|
if(null != xfs && true == xfs.QuotePrefix && CellValueType.String == this.type && false == this.isFormula())
|
|
{
|
|
if(null != oValueText)
|
|
oValueText = "'" + oValueText;
|
|
else if(null != oValueArray)
|
|
oValueArray = [{text:"'"}].concat(oValueArray);
|
|
}
|
|
return this._getValue2Result(oValueText, oValueArray, true);
|
|
};
|
|
Cell.prototype.getValueForExample = function(numFormat, cultureInfo) {
|
|
var aText = this._getValue2(AscCommon.gc_nMaxDigCountView, function(){return true;}, numFormat, cultureInfo, true);
|
|
return AscCommonExcel.getStringFromMultiText(aText);
|
|
};
|
|
Cell.prototype.getValueWithoutFormat = function() {
|
|
this._checkDirty();
|
|
var sResult = "";
|
|
if(null != this.number)
|
|
{
|
|
if(CellValueType.Bool === this.type)
|
|
sResult = this.number == 1 ? cBoolLocal.t : cBoolLocal.f;
|
|
else
|
|
sResult = this.number.toString();
|
|
}
|
|
else if(null != this.text)
|
|
sResult = this.text;
|
|
else if(null != this.multiText)
|
|
sResult = AscCommonExcel.getStringFromMultiText(this.multiText);
|
|
return sResult;
|
|
};
|
|
Cell.prototype.getValue = function() {
|
|
this._checkDirty();
|
|
let aTextValue2 = this._getValue2(AscCommon.gc_nMaxDigCountView, function() {return true;},
|
|
undefined, undefined, true);
|
|
return AscCommonExcel.getStringFromMultiText(aTextValue2);
|
|
};
|
|
Cell.prototype.getValueSkipToSpace = function() {
|
|
this._checkDirty();
|
|
let aTextValue2 = this._getValue2(AscCommon.gc_nMaxDigCountView, function() {return true;},
|
|
undefined, undefined, true);
|
|
return AscCommonExcel.getStringFromMultiTextSkipToSpace(aTextValue2);
|
|
};
|
|
Cell.prototype.getValue2 = function(dDigitsCount, fIsFitMeasurer) {
|
|
this._checkDirty();
|
|
if(null == fIsFitMeasurer)
|
|
fIsFitMeasurer = function(aText){return true;};
|
|
if(null == dDigitsCount)
|
|
dDigitsCount = AscCommon.gc_nMaxDigCountView;
|
|
return this._getValue2(dDigitsCount, fIsFitMeasurer);
|
|
};
|
|
Cell.prototype.getNumberValue = function() {
|
|
this._checkDirty();
|
|
return this.number;
|
|
};
|
|
Cell.prototype.getBoolValue = function() {
|
|
this._checkDirty();
|
|
return this.number == 1;
|
|
};
|
|
Cell.prototype.getErrorValue = function() {
|
|
this._checkDirty();
|
|
return AscCommonExcel.cError.prototype.getErrorTypeFromString(this.text);
|
|
};
|
|
Cell.prototype.getValueText = function() {
|
|
this._checkDirty();
|
|
return this.text;
|
|
};
|
|
Cell.prototype.getTextIndex = function() {
|
|
if (null === this.textIndex) {
|
|
var wb = this.ws.workbook;
|
|
if (null != this.text) {
|
|
this.textIndex = wb.sharedStrings.addText(this.text);
|
|
} else if (null != this.multiText) {
|
|
this.textIndex = wb.sharedStrings.addMultiText(this.multiText);
|
|
}
|
|
}
|
|
return this.textIndex;
|
|
};
|
|
Cell.prototype.getValueMultiText = function() {
|
|
this._checkDirty();
|
|
return this.multiText;
|
|
};
|
|
Cell.prototype.getNumFormatStr=function(){
|
|
if(null != this.xfs && null != this.xfs.num)
|
|
return this.xfs.num.getFormat();
|
|
return g_oDefaultFormat.Num.getFormat();
|
|
};
|
|
Cell.prototype.getNumFormat=function(){
|
|
return oNumFormatCache.get(this.getNumFormatStr());
|
|
};
|
|
Cell.prototype.getNumFormatType=function(){
|
|
return this.getNumFormat().getType();
|
|
};
|
|
Cell.prototype.getOffset=function(cell){
|
|
return this.getOffset3(cell.nCol + 1, cell.nRow + 1);
|
|
};
|
|
Cell.prototype.getOffset2=function(cellId){
|
|
var cAddr2 = new CellAddress(cellId);
|
|
return this.getOffset3(cAddr2.col, cAddr2.row);
|
|
};
|
|
Cell.prototype.getOffset3=function(col, row){
|
|
return new AscCommon.CellBase(this.nRow - row + 1, this.nCol - col + 1);
|
|
};
|
|
Cell.prototype.getValueData = function(){
|
|
this._checkDirty();
|
|
var formula = this.isFormula() ? this.getFormula() : null;
|
|
var formulaRef;
|
|
let ca;
|
|
if(formula) {
|
|
var parser = this.getFormulaParsed();
|
|
if(parser) {
|
|
formulaRef = parser.getArrayFormulaRef();
|
|
ca = parser.ca;
|
|
}
|
|
}
|
|
return new UndoRedoData_CellValueData(formula, new AscCommonExcel.CCellValue(this), formulaRef, ca);
|
|
};
|
|
Cell.prototype.setValueData = function(Val){
|
|
//значения устанавляваются через setValue, чтобы пересчитались формулы
|
|
if (null != Val.formula) {
|
|
let caProps = {
|
|
ca: Val.ca,
|
|
oldValue: Val.value.number,
|
|
oldValueText: Val.value.text
|
|
};
|
|
this.setFormula(Val.formula, null, Val.formulaRef, caProps);
|
|
} else if (null != Val.value) {
|
|
var DataOld = null;
|
|
var DataNew = null;
|
|
if (AscCommon.History.Is_On())
|
|
DataOld = this.getValueData();
|
|
if (this.formulaParsed && this.formulaParsed.getDynamicRef()) {
|
|
this.ws.workbook.dependencyFormulas.addToChangedRange2(this.formulaParsed.getWs().getId(), this.formulaParsed.getDynamicRef());
|
|
if (Val.value.getTextValue()) {
|
|
// non empty val, delete PF from cell
|
|
this.setFormulaInternal(null);
|
|
}
|
|
} else {
|
|
this.setFormulaInternal(null);
|
|
this.ws.workbook.dependencyFormulas.addToChangedCell(this);
|
|
}
|
|
|
|
this._setValueData(Val.value);
|
|
this.ws.workbook.sortDependency();
|
|
if (AscCommon.History.Is_On()) {
|
|
DataNew = this.getValueData();
|
|
if (false == DataOld.isEqual(DataNew))
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, DataNew));
|
|
}
|
|
}
|
|
else
|
|
this.setValue("");
|
|
|
|
if (this.ws.workbook.handlers) {
|
|
this.ws.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.cellValue, this, null, this.ws.getId());
|
|
}
|
|
};
|
|
Cell.prototype.getQuotePrefix = function () {
|
|
return this.xfs && this.xfs.getQuotePrefix();
|
|
};
|
|
|
|
/**
|
|
* Checks whether the formula is an exclude formula, which doesn't need recursive check.
|
|
* @param {[]} aOutStack
|
|
* @param {string} sFunctionName
|
|
* @returns {boolean}
|
|
* @private
|
|
*/
|
|
function _isExcludeFormula(aOutStack, sFunctionName) {
|
|
const aExcludeFormulas = AscCommonExcel.aExcludeRecursiveFormulas;
|
|
const aUnOperators = ['un_minus', 'un_plus'];
|
|
let nFuncCount = 0;
|
|
|
|
if (!sFunctionName) {
|
|
return false;
|
|
}
|
|
if (!aExcludeFormulas.includes(sFunctionName)) {
|
|
return false;
|
|
}
|
|
aOutStack.forEach(function (oElem) {
|
|
if (oElem.type === cElementType.func || (oElem.type === cElementType.operator && !aUnOperators.includes(oElem.name))) {
|
|
nFuncCount++;
|
|
}
|
|
});
|
|
if (nFuncCount === 1 && aExcludeFormulas.includes(sFunctionName)) {
|
|
if (sFunctionName === 'CELL') {
|
|
let oStringElem, nCountArgs = null;
|
|
aOutStack.forEach(function (oElem) {
|
|
if (oElem.type === cElementType.string && !oStringElem) {
|
|
oStringElem = oElem;
|
|
} else if (nCountArgs === null && typeof oElem === 'number') {
|
|
nCountArgs = oElem;
|
|
}
|
|
});
|
|
const sValue = oStringElem && oStringElem.toString().toLowerCase();
|
|
if ((sValue && sValue === 'contents') && (nCountArgs && nCountArgs === 2)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
/**
|
|
* Checks "areaMap" belongs formula that ignores recursion rules
|
|
* @param {[]} aOutStack
|
|
* @param {object} oAreaMap
|
|
* @returns {boolean}
|
|
* @private
|
|
*/
|
|
function _areaMapIsExcludeFormula(aOutStack, oAreaMap) {
|
|
const aExcludeFormulas = AscCommonExcel.aExcludeRecursiveFormulas;
|
|
for (let i = 0, length = aOutStack.length; i < length; i++) {
|
|
const oElem = aOutStack[i];
|
|
if (oElem.type === cElementType.func && aExcludeFormulas.includes(oElem.name)) {
|
|
let nIndexOfArgCount = i - 1;
|
|
let nArgCount = aOutStack[nIndexOfArgCount];
|
|
let nStartArgIndex = nIndexOfArgCount - nArgCount;
|
|
let bBelongToFormula = false;
|
|
for (let j = nStartArgIndex; j < nIndexOfArgCount; j++) {
|
|
let oArgElem = aOutStack[j];
|
|
let oBbox = null;
|
|
let aRef = [cElementType.cell, cElementType.cell3D, cElementType.cellsRange, cElementType.cellsRange3D];
|
|
|
|
if (oArgElem.type === cElementType.name || oArgElem.type === cElementType.name3D) {
|
|
const oElemValue = oArgElem.getValue();
|
|
if (!aRef.includes(oElemValue.type)) {
|
|
continue;
|
|
}
|
|
oBbox = oElemValue.getBBox0();
|
|
} else if (oArgElem.type === cElementType.table) {
|
|
oBbox = oArgElem.getRange().getBBox0();
|
|
} else if (aRef.includes(oArgElem.type)) {
|
|
oBbox = oArgElem.getBBox0();
|
|
}
|
|
bBelongToFormula = !!oBbox && oAreaMap.bbox.isIntersect(oBbox);
|
|
if (bBelongToFormula) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Method returns listeners of cell
|
|
* @returns {object}
|
|
*/
|
|
Cell.prototype.getListeners = function () {
|
|
const ws = this.ws;
|
|
const oDepFormulas = ws.workbook.dependencyFormulas;
|
|
|
|
if (!oDepFormulas || !oDepFormulas.sheetListeners.hasOwnProperty(ws.Id)) {
|
|
return null;
|
|
}
|
|
|
|
const nCellIndex = getCellIndex(this.nRow, this.nCol);
|
|
const oFormulaParsed = this.getFormulaParsed();
|
|
const sFunctionName = oFormulaParsed && oFormulaParsed.getFunctionName();
|
|
if (oFormulaParsed && !oFormulaParsed.ca && !g_cCalcRecursion.getFunctionsResult().length) {
|
|
return null;
|
|
}
|
|
const aOutStack = oFormulaParsed && oFormulaParsed.outStack;
|
|
const oSheetListeners = oDepFormulas.sheetListeners[ws.Id];
|
|
|
|
if (oSheetListeners.cellMap.hasOwnProperty(nCellIndex) && !_isExcludeFormula(aOutStack, sFunctionName)) {
|
|
return oSheetListeners.cellMap[nCellIndex];
|
|
} else if (aOutStack && aOutStack.length && sFunctionName) {
|
|
for (let nIndex in oSheetListeners.areaMap) {
|
|
if (oSheetListeners.areaMap[nIndex].bbox.contains(this.nCol, this.nRow)) {
|
|
return _areaMapIsExcludeFormula(aOutStack, oSheetListeners.areaMap[nIndex]) ? null : oSheetListeners.areaMap[nIndex];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Iterative extract listeners of a cell
|
|
* @param fAction {Function} Action on the listener.
|
|
* @param oCell {Cell}
|
|
* @param oCellListeners {object}
|
|
* @private
|
|
*/
|
|
function _foreachListeners(fAction, oCell, oCellListeners) {
|
|
const oListeners = oCellListeners.listeners;
|
|
for (let i in oListeners) {
|
|
let oListenerCell = oListeners[i].getParent();
|
|
if (!oListenerCell) {
|
|
continue;
|
|
}
|
|
let nListenerCellIndex = null;
|
|
if (oListenerCell instanceof DefName) {
|
|
if (!oListeners[i].ca) {
|
|
continue;
|
|
}
|
|
let oParserRef = oListenerCell.parsedRef;
|
|
let aRef = [cElementType.cell, cElementType.cell3D, cElementType.cellsRange, cElementType.cellsRange3D];
|
|
let oOutStackElem = oParserRef.outStack.find(function (oElem) {
|
|
return aRef.includes(oElem.type);
|
|
});
|
|
let oRange = oOutStackElem && oOutStackElem.getRange();
|
|
if (oRange && oRange.isOneCell()) {
|
|
nListenerCellIndex = getCellIndex(oRange.bbox.r1, oRange.bbox.c1);
|
|
let oWs = oRange.worksheet;
|
|
oWs._getCell(oRange.bbox.r1, oRange.bbox.c1, function (oCell) {
|
|
oListenerCell = oCell;
|
|
});
|
|
} else if (oRange) {
|
|
oRange._foreachNoEmpty(function (oCell) {
|
|
if (oCell.isFormula()) {
|
|
nListenerCellIndex = getCellIndex(oCell.nRow, oCell.nCol);
|
|
oListenerCell = oCell;
|
|
return true; // break loop;
|
|
}
|
|
})
|
|
}
|
|
} else if (oListeners[i].getShared() && !oListeners[i].is3D && oCellListeners.bbox) {
|
|
const oShared = oListeners[i].getShared();
|
|
const oCurrentRange = new Asc.Range(oCell.nCol, oCell.nRow, oCell.nCol, oCell.nRow);
|
|
const oListenerSharedRange = oCellListeners.bbox.getSharedIntersect(oShared.ref, oCurrentRange);
|
|
oListenerCell.ws._getCell(oListenerSharedRange.r1, oListenerSharedRange.c1, function (oCell) {
|
|
oListenerCell = oCell;
|
|
});
|
|
nListenerCellIndex = getCellIndex(oListenerCell.nRow, oListenerCell.nCol);
|
|
} else {
|
|
nListenerCellIndex = getCellIndex(oListenerCell.nRow, oListenerCell.nCol);
|
|
}
|
|
if (nListenerCellIndex == null || isNaN(nListenerCellIndex)) {
|
|
continue;
|
|
}
|
|
if (oListenerCell instanceof Asc.CT_WorksheetSource) {
|
|
continue;
|
|
}
|
|
if (oListeners[i].getFunctionName() && oCell.compareCellIndex(oListenerCell)) {
|
|
const aOutStack = oListeners[i].outStack;
|
|
const aExcludeFormulas = AscCommonExcel.aExcludeRecursiveFormulas;
|
|
const oCycleCells = new Map();
|
|
|
|
foreachRefElements(function (oElem, nIndex, nLastIndex) {
|
|
if (oElem.containCell2(oListenerCell)) {
|
|
const nIndexWithFunction = nIndex + 2;
|
|
if (nIndexWithFunction > nLastIndex) {
|
|
return;
|
|
}
|
|
const oElemWithFunction = aOutStack[nIndexWithFunction];
|
|
if (oElemWithFunction && oElemWithFunction.type === cElementType.func && aExcludeFormulas.includes(oElemWithFunction.name)) {
|
|
oCycleCells.set(true, nIndex);
|
|
return;
|
|
}
|
|
oCycleCells.set(false, nIndex);
|
|
}
|
|
}, aOutStack);
|
|
if (oCycleCells.size > 0 && oCycleCells.get(false) === undefined) {
|
|
continue;
|
|
}
|
|
}
|
|
let oRes = fAction(oListenerCell, oCell, nListenerCellIndex);
|
|
if (oRes != null) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compares cell index of two cells.
|
|
* @memberof Cell
|
|
* @param {Cell|CCellWithFormula} oCompareCell
|
|
* @returns {boolean}
|
|
*/
|
|
Cell.prototype.compareCellIndex = function (oCompareCell) {
|
|
const nCellIndex = getCellIndex(this.nRow, this.nCol);
|
|
const nCompareCellIndex = getCellIndex(oCompareCell.nRow, oCompareCell.nCol);
|
|
const sWsName = this.ws.getName();
|
|
const sCompareWsName = oCompareCell.ws.getName();
|
|
|
|
return nCellIndex === nCompareCellIndex && sWsName === sCompareWsName;
|
|
};
|
|
/**
|
|
* Checks cell contains in formula.
|
|
* @memberof Cell
|
|
* @returns {boolean}
|
|
*/
|
|
Cell.prototype.containInFormula = function () {
|
|
const oThis = this;
|
|
const formulaParsed = this.getFormulaParsed();
|
|
const aOutStack = formulaParsed && formulaParsed.outStack;
|
|
if (!aOutStack) {
|
|
return false;
|
|
}
|
|
let bContainsInFormula = false;
|
|
foreachRefElements(function (oRange) {
|
|
if (oRange.containCell2(oThis)) {
|
|
bContainsInFormula = true;
|
|
return true;
|
|
}
|
|
}, aOutStack);
|
|
|
|
return bContainsInFormula;
|
|
};
|
|
/**
|
|
* Method finds a start cell index of recursion formula.
|
|
* Uses for iterative calculations feature.
|
|
* @param {Cell} [oPrevCell] - Previous cell in recursion.
|
|
* @param {Cell} [oFirstCell] - First cell in recursion.
|
|
* @param {Cell[]} [aPassedCells] - Passed cells in recursion.
|
|
* @memberof Cell
|
|
*/
|
|
Cell.prototype.initStartCellForIterCalc = function (oPrevCell, oFirstCell, aPassedCells) {
|
|
if (g_cCalcRecursion.checkRecursionCounter()) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
|
|
const oParserFormula = this.getFormulaParsed();
|
|
const sFunctionName = oParserFormula && oParserFormula.getFunctionName();
|
|
if (oParserFormula && oParserFormula._isConditionalFormula(sFunctionName) && this.containInFormula() && !oParserFormula.isRecursiveCondFormula(sFunctionName)) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
const oCellListeners = this.getListeners();
|
|
if (!oCellListeners) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
const nCellIndex = getCellIndex(this.nRow, this.nCol);
|
|
let oCellFromListener = null;
|
|
let nPrevCellIndex = oPrevCell ? getCellIndex(oPrevCell.nRow, oPrevCell.nCol) : null;
|
|
oFirstCell = oFirstCell || this;
|
|
let nFirstCellIndex = getCellIndex(oFirstCell.nRow, oFirstCell.nCol);
|
|
aPassedCells = aPassedCells || [];
|
|
let bBreakFunction = false
|
|
_foreachListeners(function (oListenerCell, oThis) {
|
|
if (oThis.compareCellIndex(oListenerCell) && oThis.containInFormula()) {
|
|
g_cCalcRecursion.setStartCellIndex({cellId: nCellIndex, wsName: oThis.ws.getName().toLowerCase()});
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return true;
|
|
} else if (nPrevCellIndex != null && oPrevCell.compareCellIndex(oListenerCell)) {
|
|
let sPrevCellWsName = oPrevCell.ws.getName().toLowerCase();
|
|
let sThisCellWsName = oThis.ws.getName().toLowerCase();
|
|
let sCellProp = sPrevCellWsName !== sThisCellWsName ? sThisCellWsName : nCellIndex.toString();
|
|
let sPrevCellProp = sPrevCellWsName !== sThisCellWsName ? sPrevCellWsName : nPrevCellIndex.toString();
|
|
if (sPrevCellProp < sCellProp) {
|
|
g_cCalcRecursion.setStartCellIndex({cellId: nPrevCellIndex, wsName: sPrevCellWsName});
|
|
} else {
|
|
g_cCalcRecursion.setStartCellIndex({cellId: nCellIndex, wsName: sThisCellWsName});
|
|
}
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return true;
|
|
} else if (oFirstCell.compareCellIndex(oListenerCell) && g_cCalcRecursion.getRecursionCounter() > 0) {
|
|
g_cCalcRecursion.setStartCellIndex({cellId: nFirstCellIndex, wsName: oFirstCell.ws.getName().toLowerCase()});
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return true;
|
|
} else {
|
|
let oWs = oListenerCell.ws;
|
|
oWs._getCell(oListenerCell.nRow, oListenerCell.nCol, function (oCell) {
|
|
oCellFromListener = oCell;
|
|
});
|
|
if (oCellFromListener.compareCellIndex(oThis)) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
bBreakFunction = true;
|
|
return;
|
|
}
|
|
let bPassedCell = aPassedCells.some(function (oPassedCell) {
|
|
let nPassedCellIndex = getCellIndex(oPassedCell.nRow, oPassedCell.nCol);
|
|
let nCellIndex = getCellIndex(oCellFromListener.nRow, oCellFromListener.nCol);
|
|
return nPassedCellIndex === nCellIndex && oPassedCell.ws.getName() === oCellFromListener.ws.getName();
|
|
});
|
|
if (bPassedCell) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
aPassedCells.push(oCellFromListener);
|
|
g_cCalcRecursion.incRecursionCounter();
|
|
oCellFromListener.initStartCellForIterCalc(oThis, oFirstCell, aPassedCells);
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
if (g_cCalcRecursion.getStartCellIndex() != null) {
|
|
return true;
|
|
}
|
|
}
|
|
}, this, oCellListeners);
|
|
if (!g_cCalcRecursion.getStartCellIndex() && !bBreakFunction) {
|
|
let oTableStructOperand = oParserFormula && oParserFormula.outStack.find(function (oOperand) {
|
|
return oOperand.type === cElementType.table;
|
|
});
|
|
if (oTableStructOperand) {
|
|
let oTableOpRange = oTableStructOperand.getRange();
|
|
if (oTableOpRange.worksheet.getName() !== this.ws.getName() || (oTableOpRange.bbox && !oTableOpRange.bbox.contains(this.nCol, this.nRow))) {
|
|
return;
|
|
}
|
|
let bContainRange = oCellListeners.bbox && oCellListeners.bbox.containsRange(oTableOpRange.bbox);
|
|
if (bContainRange && oCellListeners.bbox.contains(this.nCol, this.nRow)) {
|
|
g_cCalcRecursion.setStartCellIndex({cellId: nCellIndex, wsName: this.ws.getName().toLowerCase()});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Function returns an array of reference cells from outStack attribute of parserFormula class.
|
|
* @param {parserFormula} oFormulaParsed
|
|
* @returns {[]}
|
|
* @private
|
|
*/
|
|
function _getRefElements(oFormulaParsed) {
|
|
const aRefElements = [];
|
|
for (let i = 0, length = oFormulaParsed.getOutStackSize(); i < length; i++) {
|
|
const oOutStackElem = oFormulaParsed.getOutStackElem(i);
|
|
const nElemType = oOutStackElem.type;
|
|
const b3D = nElemType === cElementType.cell3D || nElemType === cElementType.cellsRange3D || nElemType === cElementType.name3D;
|
|
const bArea = nElemType === cElementType.cellsRange || nElemType === cElementType.name;
|
|
const bDefName = nElemType === cElementType.name || nElemType === cElementType.name3D;
|
|
const bTable = nElemType === cElementType.table;
|
|
|
|
if (nElemType === cElementType.cell || b3D || bArea || bDefName || bTable) {
|
|
aRefElements.push(oOutStackElem);
|
|
}
|
|
}
|
|
|
|
return aRefElements;
|
|
}
|
|
|
|
/**
|
|
* Iterative extract reference elements from outStack attribute of parserFormula class.
|
|
* @param {Function} fAction - Action with reference element
|
|
* @param {[]} aRefElements
|
|
*/
|
|
function foreachRefElements (fAction, aRefElements) {
|
|
if (!aRefElements.length) {
|
|
return;
|
|
}
|
|
let nLastIndex = aRefElements.length - 1;
|
|
for (let i = 0; i < aRefElements.length; i++) {
|
|
const oRefElement = aRefElements[i];
|
|
const nRefType = oRefElement.type;
|
|
const b3D = nRefType === cElementType.cell3D || nRefType === cElementType.cellsRange3D;
|
|
const bArea = nRefType === cElementType.cellsRange;
|
|
const bDefName = nRefType === cElementType.name || nRefType === cElementType.name3D;
|
|
const bTable = nRefType === cElementType.table;
|
|
let oRange = null;
|
|
|
|
if (nRefType !== cElementType.cell && !b3D && !bArea && !bDefName && !bTable) {
|
|
continue;
|
|
}
|
|
if (nRefType === cElementType.name || nRefType === cElementType.name3D) {
|
|
const oElemValue = oRefElement.getValue();
|
|
const oElemType = oElemValue.type;
|
|
let aRef = [cElementType.cell, cElementType.cell3D, cElementType.cellsRange, cElementType.cellsRange3D];
|
|
if (!aRef.includes(oElemType)) {
|
|
return;
|
|
}
|
|
oRange = oElemValue.getRange();
|
|
} else if (nRefType === cElementType.table) {
|
|
let oRefElem = oRefElement.toRef();
|
|
oRange = oRefElem.getRange();
|
|
} else {
|
|
oRange = oRefElement.getRange();
|
|
}
|
|
let oRes = fAction(oRange, i, nLastIndex);
|
|
if (oRes != null) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Changes ca flag of cell from listener.
|
|
* Function is recursive.
|
|
* @param {Cell} oSourceCell
|
|
* @private
|
|
*/
|
|
function _changeCellsFromListener (oSourceCell) {
|
|
if (g_cCalcRecursion.checkRecursionCounter()) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
const oCellListeners = oSourceCell.getListeners();
|
|
if (!oCellListeners) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
_foreachListeners(function (oListenerCellWithFormula, oCell) {
|
|
const oWs = oCell.ws;
|
|
let oListenerCell = null;
|
|
oWs._getCell(oListenerCellWithFormula.nRow, oListenerCellWithFormula.nCol, function (oCell) {
|
|
oListenerCell = oCell;
|
|
})
|
|
if (!oListenerCell.isFormula()) {
|
|
return;
|
|
}
|
|
const oFormulaParsed = oListenerCell.getFormulaParsed();
|
|
if (oFormulaParsed.ca) {
|
|
return;
|
|
}
|
|
oFormulaParsed.ca = true;
|
|
if (oListenerCell.getListeners()) {
|
|
g_cCalcRecursion.incRecursionCounter();
|
|
_changeCellsFromListener(oListenerCell);
|
|
}
|
|
}, oSourceCell, oCellListeners);
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
}
|
|
|
|
/**
|
|
* Method checks is cell has recursive formula.
|
|
* Recursion method
|
|
* @param {CCellWithFormula} oCellWithFormula
|
|
* @param {Cell[]} [aPassedCell]
|
|
* @returns {boolean}
|
|
*/
|
|
Cell.prototype.checkRecursiveFormula = function (oCellWithFormula, aPassedCell) {
|
|
if (g_cCalcRecursion.checkRecursionCounter() || oCellWithFormula == null) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return false;
|
|
}
|
|
|
|
const nCellIndexFromFormula = getCellIndex(oCellWithFormula.nRow, oCellWithFormula.nCol);
|
|
if (isNaN(nCellIndexFromFormula)) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return false;
|
|
}
|
|
if (this.compareCellIndex(oCellWithFormula)) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return true;
|
|
}
|
|
|
|
if (!this.isFormula()) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return false;
|
|
}
|
|
const oFormulaParsed = this.getFormulaParsed();
|
|
const aRefElements = _getRefElements(oFormulaParsed);
|
|
const oThis = this;
|
|
let bRecursiveFormula = false;
|
|
aPassedCell = aPassedCell || [];
|
|
foreachRefElements(function (oRange) {
|
|
if (!oRange) {
|
|
return;
|
|
}
|
|
oRange._foreachNoEmpty(function (oCell) {
|
|
if (!oCell) {
|
|
return;
|
|
}
|
|
let bCellIsPassed = aPassedCell.some(function (oElem) {
|
|
return oCell.compareCellIndex(oElem);
|
|
});
|
|
if (oCell.compareCellIndex(oCellWithFormula)) {
|
|
bRecursiveFormula = true;
|
|
return true; // break loop
|
|
} else if (!bRecursiveFormula && oCell.isFormula() && !bCellIsPassed) {
|
|
g_cCalcRecursion.incRecursionCounter();
|
|
aPassedCell.push(oCell);
|
|
bRecursiveFormula = oCell.checkRecursiveFormula(oCellWithFormula, aPassedCell);
|
|
}
|
|
if (bRecursiveFormula) {
|
|
return true; // break loop
|
|
}
|
|
});
|
|
if (bRecursiveFormula) {
|
|
if (g_cCalcRecursion.getRecursionCounter() === 0 && aPassedCell.length) {
|
|
const oWs = oThis.ws;
|
|
if (oWs) {
|
|
let oSourceCell = null;
|
|
oWs._getCell(oCellWithFormula.nRow, oCellWithFormula.nCol, function (oCell) {
|
|
oSourceCell = oCell;
|
|
});
|
|
if (oSourceCell) {
|
|
_changeCellsFromListener(oSourceCell);
|
|
}
|
|
}
|
|
}
|
|
oFormulaParsed.ca = true;
|
|
return true;
|
|
}
|
|
}, aRefElements);
|
|
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return bRecursiveFormula;
|
|
};
|
|
/**
|
|
* Method modifies linked cell.
|
|
* @param {function} fAction - Callback function with logic for modifying cell.
|
|
* @param {boolean} bRecursiveCall - Changed all linked cells or only nearby cell.
|
|
* @memberof Cell
|
|
*/
|
|
Cell.prototype.changeLinkedCell = function (fAction, bRecursiveCall) {
|
|
const oThis = this;
|
|
const nThisIndex = getCellIndex(this.nRow, this.nCol);
|
|
const oFormulaParsed = this.getFormulaParsed();
|
|
|
|
if (!oFormulaParsed) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
if (g_cCalcRecursion.checkRecursionCounter()) {
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
return;
|
|
}
|
|
|
|
const aRefElements = _getRefElements(oFormulaParsed);
|
|
foreachRefElements(function (oRange, nIndex, nLastRefElemIndex) {
|
|
oRange._foreachNoEmpty(function(oCell) {
|
|
let nCellIndex = getCellIndex(oCell.nRow, oCell.nCol);
|
|
let sCellWsName = oCell.ws.getName().toLowerCase();
|
|
let sThisWsName = oThis.ws.getName().toLowerCase();
|
|
if (!oCell.isFormula()) {
|
|
return;
|
|
}
|
|
if ((nCellIndex !== nThisIndex && nCellIndex > nThisIndex) || sCellWsName > sThisWsName) {
|
|
let res = fAction(oCell);
|
|
if (res != null) {
|
|
return true;
|
|
}
|
|
if (bRecursiveCall) {
|
|
g_cCalcRecursion.incRecursionCounter();
|
|
oCell.changeLinkedCell(fAction, true);
|
|
}
|
|
} else if (nIndex === nLastRefElemIndex && nCellIndex === nThisIndex && sCellWsName === sThisWsName) {
|
|
// Try to find listener with linked cell.
|
|
const oCellListeners = oCell.getListeners();
|
|
if (!oCellListeners) {
|
|
return;
|
|
}
|
|
_foreachListeners(function (oListenerCell, oThis, nListenerCellIndex) {
|
|
let sThisWsName = oThis.ws.getName().toLowerCase();
|
|
let sListenerWsName = oListenerCell.ws.getName().toLowerCase();
|
|
if (nListenerCellIndex !== nCellIndex || sThisWsName !== sListenerWsName) {
|
|
let oWs = oListenerCell.ws;
|
|
oWs._getCell(oListenerCell.nRow, oListenerCell.nCol, function (oCell) {
|
|
if (oCell.isFormula()) {
|
|
let res = fAction(oCell);
|
|
if (res != null) {
|
|
return;
|
|
}
|
|
if (bRecursiveCall) {
|
|
g_cCalcRecursion.incRecursionCounter();
|
|
oCell.changeLinkedCell(fAction, true);
|
|
}
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
}, oCell, oCellListeners);
|
|
}
|
|
});
|
|
}, aRefElements);
|
|
g_cCalcRecursion.resetRecursionCounter();
|
|
};
|
|
/**
|
|
* Fills array of recursive cells.
|
|
* Uses for Iterative calculation.
|
|
* @memberof Cell
|
|
* @param {{cellId:number, wsName:string}[]}aRecursiveCells
|
|
* @param {{cellId:number, wsName:string}}oStartCellIndex
|
|
*/
|
|
Cell.prototype.fillRecursiveCells = function (aRecursiveCells, oStartCellIndex) {
|
|
aRecursiveCells.unshift(oStartCellIndex); // The first element of the array is always a start cell.
|
|
this.changeLinkedCell(function (oCell) {
|
|
let oCellIndex = {
|
|
cellId: getCellIndex(oCell.nRow, oCell.nCol),
|
|
wsName: oCell.ws.getName().toLowerCase()
|
|
};
|
|
let aPrevRecursiveCell = g_cCalcRecursion.getRecursiveCells(oCell);
|
|
if (aPrevRecursiveCell.length) {
|
|
const oPrevStartCellIndex = aPrevRecursiveCell[0];
|
|
aPrevRecursiveCell = aPrevRecursiveCell.filter(function (oPrevCellIndex) {
|
|
return oPrevCellIndex.cellId !== oCellIndex.cellId || oPrevCellIndex.wsName !== oCellIndex.wsName;
|
|
})
|
|
g_cCalcRecursion.updateRecursiveCells(oPrevStartCellIndex, aPrevRecursiveCell);
|
|
}
|
|
let bDuplicateElem = aRecursiveCells.some(function (oElem) {
|
|
return oElem.cellId === oCellIndex.cellId && oElem.wsName === oCellIndex.wsName;
|
|
});
|
|
if (bDuplicateElem) {
|
|
return true;
|
|
}
|
|
aRecursiveCells.push(oCellIndex);
|
|
}, true);
|
|
g_cCalcRecursion.addRecursiveCells(this, aRecursiveCells);
|
|
};
|
|
/**
|
|
* Method calculates cells with formula aren't calculated yet.
|
|
* @memberof Cell
|
|
* @private
|
|
*/
|
|
Cell.prototype._checkDirty = function() {
|
|
const t = this;
|
|
// Checks cell contains formula or formula is not calculated yet
|
|
if (this.getIsDirty()) {
|
|
if (g_cCalcRecursion.checkLevel()) {
|
|
g_cCalcRecursion.incLevel();
|
|
const isCalc = this.getIsCalc();
|
|
this.setIsCalc(true);
|
|
const calculatedArrayFormulas = [];
|
|
this.processFormula(function(parsed) {
|
|
if (!isCalc) {
|
|
//***array-formula***
|
|
//добавлен последний параметр для обработки формулы массива
|
|
if(parsed.getArrayFormulaRef()) {
|
|
const listenerId = parsed.getListenerId();
|
|
if(parsed.checkFirstCellArray(t) && !calculatedArrayFormulas[listenerId]) {
|
|
parsed.calculate();
|
|
calculatedArrayFormulas[listenerId] = 1;
|
|
} else {
|
|
if(null === parsed.value && !calculatedArrayFormulas[listenerId]) {
|
|
parsed.calculate();
|
|
calculatedArrayFormulas[listenerId] = 1;
|
|
}
|
|
|
|
let oldParent = parsed.parent;
|
|
parsed.parent = new AscCommonExcel.CCellWithFormula(t.ws, t.nRow, t.nCol);
|
|
parsed._endCalculate();
|
|
parsed.parent = oldParent;
|
|
}
|
|
} else {
|
|
parsed.calculate();
|
|
}
|
|
if (g_cCalcRecursion.getFunctionsResult().length && g_cCalcRecursion.getIterStep() === 1 && g_cCalcRecursion.getLevel() === 1) {
|
|
const functionsResult = g_cCalcRecursion.getFunctionsResult();
|
|
const isEnabledRecursion = g_cCalcRecursion.getIsEnabledRecursion();
|
|
let isCycleCell = false;
|
|
|
|
foreachRefElements(function (range) {
|
|
if (range.bbox.contains(t.nCol, t.nRow) && range.worksheet.getName() === t.ws.getName()) {
|
|
if (!parsed.ca) {
|
|
parsed.ca = true;
|
|
}
|
|
isCycleCell = true;
|
|
!isEnabledRecursion && g_cCalcRecursion.addCycleCell(t);
|
|
} else {
|
|
range._foreachNoEmpty(function (cell) {
|
|
if (cell.isFormula()) {
|
|
cell.initStartCellForIterCalc();
|
|
if (g_cCalcRecursion.getStartCellIndex() != null) {
|
|
if (!cell.getFormulaParsed().ca) {
|
|
cell.getFormulaParsed().ca = true;
|
|
}
|
|
isCycleCell = true;
|
|
!isEnabledRecursion && g_cCalcRecursion.addCycleCell(cell);
|
|
g_cCalcRecursion.getStartCellIndex() && g_cCalcRecursion.setStartCellIndex(null);
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
if (isCycleCell) {
|
|
return true;
|
|
}
|
|
}, functionsResult);
|
|
if (isCycleCell) {
|
|
if (isEnabledRecursion) {
|
|
const recursiveCells = g_cCalcRecursion.getRecursiveCells(t);
|
|
if (!recursiveCells.length) {
|
|
const cellIndex = {
|
|
cellId: getCellIndex(t.nRow, t.nCol),
|
|
wsName: t.ws.getName().toLowerCase()
|
|
};
|
|
t.fillRecursiveCells(recursiveCells, cellIndex);
|
|
}
|
|
|
|
} else {
|
|
parsed.value = null;
|
|
t.setIsDirty(false);
|
|
if (t.getType() !== CellValueType.Number) {
|
|
t.setTypeInternal(CellValueType.Number);
|
|
}
|
|
t.setValueNumberInternal(0);
|
|
}
|
|
}
|
|
}
|
|
if (g_cCalcRecursion.getFunctionsResult().length) {
|
|
g_cCalcRecursion.clearFunctionsResult();
|
|
}
|
|
}
|
|
});
|
|
|
|
g_cCalcRecursion.decLevel();
|
|
if (g_cCalcRecursion.getIsForceBacktracking()) {
|
|
g_cCalcRecursion.insert({ws: this.ws, nRow: this.nRow, nCol: this.nCol});
|
|
if (g_cCalcRecursion.getLevel() === 0 && !g_cCalcRecursion.getIsProcessRecursion()) {
|
|
g_cCalcRecursion.setIsProcessRecursion(true);
|
|
do {
|
|
g_cCalcRecursion.setIsForceBacktracking(false);
|
|
g_cCalcRecursion.foreachInReverse(function(oElem) {
|
|
oElem.ws._getCellNoEmpty(oElem.nRow, oElem.nCol, function(oCell) {
|
|
if(oCell && oCell.getIsDirty()) {
|
|
oCell.setIsCalc(false);
|
|
oCell._checkDirty();
|
|
}
|
|
});
|
|
});
|
|
} while (g_cCalcRecursion.getIsForceBacktracking());
|
|
g_cCalcRecursion.setIsProcessRecursion(false);
|
|
}
|
|
} else {
|
|
this.setIsCalc(false);
|
|
this.setIsDirty(false);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype.getFont=function(){
|
|
var xfs = this.getCompiledStyle();
|
|
if(null != xfs && null != xfs.font)
|
|
return xfs.font;
|
|
return g_oDefaultFormat.Font;
|
|
};
|
|
Cell.prototype.getCellFont = function() {
|
|
return (this.xfs && this.xfs.font) || g_oDefaultFormat.Font;
|
|
};
|
|
Cell.prototype.getFillColor = function () {
|
|
return this.getFill().bg();
|
|
};
|
|
Cell.prototype.getFill = function () {
|
|
var xfs = this.getCompiledStyle();
|
|
if(null != xfs && null != xfs.fill)
|
|
return xfs.fill;
|
|
return g_oDefaultFormat.Fill;
|
|
};
|
|
Cell.prototype.getBorderSrc = function () {
|
|
var xfs = this.getCompiledStyle();
|
|
if(null != xfs && null != xfs.border)
|
|
return xfs.border;
|
|
return g_oDefaultFormat.Border;
|
|
};
|
|
Cell.prototype.getBorder = function () {
|
|
return this.getBorderSrc();
|
|
};
|
|
Cell.prototype.getAlign=function(){
|
|
var xfs = this.getCompiledStyle();
|
|
if (xfs) {
|
|
return xfs.align || g_oDefaultFormat.AlignAbs;
|
|
}
|
|
return g_oDefaultFormat.Align;
|
|
};
|
|
Cell.prototype._adjustCellFormat = function() {
|
|
var t = this;
|
|
this.processFormula(function(parsed) {
|
|
var valueCalc = parsed.value;
|
|
if (valueCalc) {
|
|
if (0 <= valueCalc.numFormat) {
|
|
if (aStandartNumFormatsId[t.getNumFormatStr()] == 0) {
|
|
t.setNum(new AscCommonExcel.Num({id: valueCalc.numFormat}));
|
|
}
|
|
} else if (typeof valueCalc.numFormat === "string") {
|
|
t.setNum(new AscCommonExcel.Num({f: valueCalc.numFormat}));
|
|
} else if (AscCommonExcel.cNumFormatFirstCell === valueCalc.numFormat) {
|
|
//ищет в формуле первый рэндж и устанавливает формат ячейки как формат первой ячейки в рэндже
|
|
//принимают формат первой ячейки в рейндже только функции с inheritFormat = true
|
|
//причём это не касается внутренних функий в формуле. если одна из внешних функций принимает формат, тогда выставляем формат у ячейки
|
|
|
|
var r = parsed.getFirstRange();
|
|
if (r && r.getNumFormatStr) {
|
|
var sCurFormat = t.getNumFormatStr();
|
|
if (g_oDefaultFormat.Num.getFormat() == sCurFormat) {
|
|
var sNewFormat = r.getNumFormatStr();
|
|
if (sCurFormat != sNewFormat) {
|
|
t.setNumFormat(sNewFormat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Cell.prototype._updateCellValue = function() {
|
|
if (!this.isFormula()) {
|
|
return;
|
|
}
|
|
var parsed = this.getFormulaParsed();
|
|
var res = parsed.simplifyRefType(parsed.value, this.ws, this.nRow, this.nCol);
|
|
|
|
let DataOld, DataNew;
|
|
if (AscCommon.History.Is_On()) {
|
|
DataOld = this.getValueData();
|
|
}
|
|
|
|
if (res) {
|
|
this.cleanText();
|
|
switch (res.type) {
|
|
case cElementType.number:
|
|
this.setTypeInternal(CellValueType.Number);
|
|
this.setValueNumberInternal(res.getValue());
|
|
break;
|
|
case cElementType.bool:
|
|
this.setTypeInternal(CellValueType.Bool);
|
|
this.setValueNumberInternal(res.value ? 1 : 0);
|
|
break;
|
|
case cElementType.error:
|
|
this.setTypeInternal(CellValueType.Error);
|
|
this.setValueTextInternal(res.getValue().toString());
|
|
break;
|
|
case cElementType.name:
|
|
this.setTypeInternal(CellValueType.Error);
|
|
this.setValueTextInternal(res.getValue().toString());
|
|
break;
|
|
case cElementType.empty:
|
|
//=A1:A3
|
|
this.setTypeInternal(CellValueType.Number);
|
|
this.setValueNumberInternal(res.tocNumber().getValue());
|
|
break;
|
|
default:
|
|
this.setTypeInternal(CellValueType.String);
|
|
this.setValueTextInternal(res.getValue().toString());
|
|
}
|
|
|
|
//обработка для функции hyperlink. необходимо проставить формат.
|
|
var isArray = parsed.getArrayFormulaRef();
|
|
var firstArrayRef = parsed.checkFirstCellArray(this);
|
|
if(res.getHyperlink && null !== res.getHyperlink() && (!isArray || (isArray && firstArrayRef))) {
|
|
var oHyperlinkFont = new AscCommonExcel.Font();
|
|
oHyperlinkFont.setName(this.ws.workbook.getDefaultFont());
|
|
oHyperlinkFont.setSize(this.ws.workbook.getDefaultSize());
|
|
oHyperlinkFont.setUnderline(Asc.EUnderline.underlineSingle);
|
|
oHyperlinkFont.setColor(AscCommonExcel.g_oColorManager.getThemeColor(AscCommonExcel.g_nColorHyperlink));
|
|
AscFormat.ExecuteNoHistory(function () {
|
|
this.setFont(oHyperlinkFont);
|
|
}, this, []);
|
|
}
|
|
|
|
if (AscCommon.History.Is_On()) {
|
|
DataNew = this.getValueData();
|
|
}
|
|
|
|
let _replaceFormulaType = parsed.replaceFormulaAfterCalc;
|
|
if (AscCommon.History.Is_On() && (parsed.unknownOrCustomFunction || _replaceFormulaType === AscCommonExcel.cReplaceFormulaType.formula)
|
|
&& !(DataNew.value && DataNew.value.type === CellValueType.Error && DataNew.value.text === AscCommon.cErrorOrigin['busy'])) {
|
|
|
|
let wb = Asc["editor"] && Asc["editor"].wb;
|
|
let currentFunc = wb && wb.customFunctionEngine && wb.customFunctionEngine.getFunc(parsed.unknownOrCustomFunction);
|
|
|
|
if ((currentFunc && currentFunc.replaceFormulaToVal) || _replaceFormulaType) {
|
|
if (_replaceFormulaType === AscCommonExcel.cReplaceFormulaType.formula) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(),
|
|
new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow),
|
|
new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, this.getValueData()));
|
|
} else {
|
|
this.setFormulaInternal(null);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(),
|
|
new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow),
|
|
new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, this.getValueData()));
|
|
}
|
|
} else if (!DataOld.isEqual(DataNew)) {
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(),
|
|
new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow),
|
|
new UndoRedoData_CellSimpleData(this.nRow, this.nCol, DataOld, DataNew));
|
|
}
|
|
parsed.replaceFormulaAfterCalc = null;
|
|
}
|
|
|
|
this.ws.workbook.dependencyFormulas.addToCleanCellCache(this.ws.getId(), this.nRow, this.nCol);
|
|
AscCommonExcel.g_oLOOKUPCache.remove(this);
|
|
AscCommonExcel.g_oVLOOKUPCache.remove(this, DataOld, res);
|
|
AscCommonExcel.g_oHLOOKUPCache.remove(this);
|
|
AscCommonExcel.g_oMatchCache.remove(this);
|
|
AscCommonExcel.g_oSUMIFSCache.remove(this);
|
|
AscCommonExcel.g_oFormulaRangesCache.remove(this);
|
|
AscCommonExcel.g_oCountIfCache.remove(this);
|
|
}
|
|
};
|
|
Cell.prototype.cleanText = function() {
|
|
this.number = null;
|
|
this.text = null;
|
|
this.multiText = null;
|
|
this.textIndex = null;
|
|
this.type = CellValueType.Number;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype._BuildDependencies = function(parse, opt_dirty) {
|
|
var parsed = this.getFormulaParsed();
|
|
if (parsed) {
|
|
if (parse) {
|
|
parsed.parse();
|
|
}
|
|
parsed.buildDependencies();
|
|
if (opt_dirty || parsed.ca || this.isNullTextString()) {
|
|
this.ws.workbook.dependencyFormulas.addToChangedCell(this);
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype._setValueData = function(val){
|
|
this.number = val.number;
|
|
this.text = val.text;
|
|
this.multiText = val.multiText;
|
|
this.textIndex = null;
|
|
this.type = val.type;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype._getValue2 = function(dDigitsCount, fIsFitMeasurer, opt_numFormat, opt_cultureInfo, opt_AffectingText) {
|
|
var aRes = null;
|
|
var bNeedMeasure = true;
|
|
var sText = null;
|
|
var aText = null;
|
|
var isMultyText = false;
|
|
if (CellValueType.Number == this.type || CellValueType.String == this.type) {
|
|
if (null != this.text) {
|
|
sText = this.text;
|
|
} else if (null != this.multiText) {
|
|
aText = this.multiText;
|
|
isMultyText = true;
|
|
}
|
|
|
|
if (CellValueType.String == this.type) {
|
|
bNeedMeasure = false;
|
|
}
|
|
var oNumFormat;
|
|
if (opt_numFormat) {
|
|
oNumFormat = opt_numFormat;
|
|
} else {
|
|
var xfs = this.getCompiledStyle(undefined, opt_AffectingText);
|
|
if (null != xfs && null != xfs.num) {
|
|
oNumFormat = oNumFormatCache.get(xfs.num.getFormat());
|
|
} else {
|
|
oNumFormat = oNumFormatCache.get(g_oDefaultFormat.Num.getFormat());
|
|
}
|
|
}
|
|
|
|
if (false == oNumFormat.isGeneralFormat()) {
|
|
if (null != this.number) {
|
|
aText = oNumFormat.format(this.number, this.type, dDigitsCount, false, opt_cultureInfo);
|
|
isMultyText = false;
|
|
sText = null;
|
|
} else if (CellValueType.String == this.type) {
|
|
var oTextFormat = oNumFormat.getTextFormat();
|
|
if (null != oTextFormat && "@" != oTextFormat.formatString) {
|
|
if (null != this.text) {
|
|
aText = oNumFormat.format(this.text, this.type, dDigitsCount, false, opt_cultureInfo);
|
|
isMultyText = false;
|
|
sText = null;
|
|
} else if (null != this.multiText) {
|
|
var sSimpleString = AscCommonExcel.getStringFromMultiText(this.multiText);
|
|
aText = oNumFormat.format(sSimpleString, this.type, dDigitsCount, false, opt_cultureInfo);
|
|
isMultyText = false;
|
|
sText = null;
|
|
}
|
|
}
|
|
}
|
|
} else if (CellValueType.Number == this.type && null != this.number) {
|
|
bNeedMeasure = false;
|
|
var bFindResult = false;
|
|
//варируем dDigitsCount чтобы результат влез в ячейку
|
|
var nTempDigCount = Math.ceil(dDigitsCount);
|
|
var sOriginText = this.number;
|
|
while (nTempDigCount >= 1) {
|
|
//Строим подходящий general format
|
|
var sGeneral = AscCommon.DecodeGeneralFormat(sOriginText, this.type, nTempDigCount);
|
|
if (null != sGeneral) {
|
|
oNumFormat = oNumFormatCache.get(sGeneral);
|
|
}
|
|
|
|
if (null != oNumFormat) {
|
|
sText = null;
|
|
isMultyText = false;
|
|
aText = oNumFormat.format(sOriginText, this.type, dDigitsCount, false, opt_cultureInfo);
|
|
if (true == oNumFormat.isTextFormat()) {
|
|
break;
|
|
} else {
|
|
aRes = this._getValue2Result(sText, aText, isMultyText, opt_AffectingText);
|
|
//Проверяем влезает ли текст
|
|
if (true == fIsFitMeasurer(aRes)) {
|
|
bFindResult = true;
|
|
break;
|
|
}
|
|
aRes = null;
|
|
}
|
|
}
|
|
nTempDigCount--;
|
|
}
|
|
if (false == bFindResult) {
|
|
aRes = null;
|
|
sText = null;
|
|
isMultyText = false;
|
|
var font = new AscCommonExcel.Font();
|
|
if (dDigitsCount > 1) {
|
|
font.setRepeat(true);
|
|
aText = [{text: "#", format: font}];
|
|
} else {
|
|
aText = [{text: "", format: font}];
|
|
}
|
|
}
|
|
}
|
|
} else if (CellValueType.Bool === this.type) {
|
|
if (null != this.number) {
|
|
sText = (0 != this.number) ? cBoolLocal.t : cBoolLocal.f;
|
|
}
|
|
} else if (CellValueType.Error === this.type) {
|
|
if (null != this.text) {
|
|
sText = this._getValueTypeError(this.text);
|
|
}
|
|
}
|
|
if (bNeedMeasure) {
|
|
aRes = this._getValue2Result(sText, aText, isMultyText, opt_AffectingText);
|
|
//Проверяем влезает ли текст
|
|
if (false == fIsFitMeasurer(aRes)) {
|
|
aRes = null;
|
|
sText = null;
|
|
isMultyText = false;
|
|
var font = new AscCommonExcel.Font();
|
|
font.setRepeat(true);
|
|
aText = [{text: "#", format: font}];
|
|
}
|
|
}
|
|
if (null == aRes) {
|
|
aRes = this._getValue2Result(sText, aText, isMultyText, opt_AffectingText);
|
|
}
|
|
return aRes;
|
|
};
|
|
Cell.prototype._setValue = function(val)
|
|
{
|
|
this.cleanText();
|
|
|
|
function checkCellValueTypeError(sUpText){
|
|
switch (sUpText){
|
|
case cErrorLocal["nil"]:
|
|
return cErrorOrigin["nil"];
|
|
break;
|
|
case cErrorLocal["div"]:
|
|
return cErrorOrigin["div"];
|
|
break;
|
|
case cErrorLocal["value"]:
|
|
return cErrorOrigin["value"];
|
|
break;
|
|
case cErrorLocal["ref"]:
|
|
return cErrorOrigin["ref"];
|
|
break;
|
|
case cErrorLocal["name"]:
|
|
case cErrorLocal["name"].replace('\\', ''): // ToDo это неправильная правка для бага 32463 (нужно переделать parse формул)
|
|
return cErrorOrigin["name"];
|
|
break;
|
|
case cErrorLocal["num"]:
|
|
return cErrorOrigin["num"];
|
|
break;
|
|
case cErrorLocal["na"]:
|
|
return cErrorOrigin["na"];
|
|
break;
|
|
case cErrorLocal["getdata"]:
|
|
return cErrorOrigin["getdata"];
|
|
break;
|
|
case cErrorLocal["uf"]:
|
|
return cErrorOrigin["uf"];
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
if("" == val) {
|
|
if (this.ws.workbook.handlers) {
|
|
this.ws.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.cellValue, this, null, this.ws.getId());
|
|
}
|
|
return;
|
|
}
|
|
|
|
var oNumFormat;
|
|
var xfs = this.getCompiledStyle(undefined, true);
|
|
if(null != xfs && null != xfs.num)
|
|
oNumFormat = oNumFormatCache.get(xfs.num.getFormat());
|
|
else
|
|
oNumFormat = oNumFormatCache.get(g_oDefaultFormat.Num.getFormat());
|
|
if(oNumFormat.isTextFormat())
|
|
{
|
|
this.setTypeInternal(CellValueType.String);
|
|
this.setValueTextInternal(val);
|
|
}
|
|
else
|
|
{
|
|
if (AscCommon.g_oFormatParser.isLocaleNumber(val))
|
|
{
|
|
this.setTypeInternal(CellValueType.Number);
|
|
this.setValueNumberInternal(AscCommon.g_oFormatParser.parseLocaleNumber(val));
|
|
if (/E/i.test(val)) {
|
|
this.setNumFormat('0.00E+00');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var sUpText = val.toUpperCase();
|
|
if(cBoolLocal.t === sUpText || cBoolLocal.f === sUpText)
|
|
{
|
|
this.setTypeInternal(CellValueType.Bool);
|
|
this.setValueNumberInternal((cBoolLocal.t === sUpText) ? 1 : 0);
|
|
}
|
|
else if(checkCellValueTypeError(sUpText))
|
|
{
|
|
this.setTypeInternal(CellValueType.Error);
|
|
this.setValueTextInternal(checkCellValueTypeError(sUpText));
|
|
}
|
|
else
|
|
{
|
|
//распознаем формат
|
|
var res = AscCommon.g_oFormatParser.parse(val);
|
|
if(null != res)
|
|
{
|
|
//Сравниваем с текущим форматом, если типы совпадают - меняем только значение ячейки
|
|
var nFormatType = oNumFormat.getType();
|
|
if(!((c_oAscNumFormatType.Percent == nFormatType && res.bPercent) ||
|
|
(c_oAscNumFormatType.Currency == nFormatType && res.bCurrency) ||
|
|
(c_oAscNumFormatType.Date == nFormatType && res.bDate) ||
|
|
(c_oAscNumFormatType.Time == nFormatType && res.bTime)) && res.format != oNumFormat.sFormat) {
|
|
this.setNumFormat(res.format);
|
|
}
|
|
this.setTypeInternal(CellValueType.Number);
|
|
this.setValueNumberInternal(res.value);
|
|
}
|
|
else
|
|
{
|
|
this.setTypeInternal(CellValueType.String);
|
|
//проверяем QuotePrefix
|
|
if(val.length > 0 && "'" == val[0])
|
|
{
|
|
this.setQuotePrefix(true);
|
|
val = val.substring(1);
|
|
}
|
|
this.setValueTextInternal(val);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (this.ws.workbook.handlers) {
|
|
this.ws.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.cellValue, this, null, this.ws.getId());
|
|
}
|
|
};
|
|
Cell.prototype._autoformatHyperlink = function(val){
|
|
if (AscCommon.rx_allowedProtocols.test(val) || /^(www.)|@/i.test(val)) {
|
|
// Удаляем концевые пробелы и переводы строки перед проверкой гиперссылок
|
|
val = val.replace(/\s+$/, '');
|
|
var typeHyp = AscCommon.getUrlType(val);
|
|
if (AscCommon.c_oAscUrlType.Invalid != typeHyp) {
|
|
val = AscCommon.prepareUrl(val, typeHyp);
|
|
|
|
var oNewHyperlink = new AscCommonExcel.Hyperlink();
|
|
oNewHyperlink.Ref = this.ws.getCell3(this.nRow, this.nCol);
|
|
oNewHyperlink.Hyperlink = val;
|
|
oNewHyperlink.Ref.setHyperlink(oNewHyperlink);
|
|
}
|
|
}
|
|
}
|
|
Cell.prototype._setValue2 = function(aVal, ignoreHyperlink, xfTableAndCond)
|
|
{
|
|
var sSimpleText = "";
|
|
for(var i = 0, length = aVal.length; i < length; ++i)
|
|
sSimpleText += aVal[i].getFragmentText ? aVal[i].getFragmentText() : aVal[i].text;
|
|
this._setValue(sSimpleText);
|
|
if (!ignoreHyperlink && window['AscCommonExcel'].g_AutoCorrectHyperlinks) {
|
|
this._autoformatHyperlink(sSimpleText);
|
|
}
|
|
var nRow = this.nRow;
|
|
var nCol = this.nCol;
|
|
if(CellValueType.String == this.type && null == this.ws.hyperlinkManager.getByCell(nRow, nCol))
|
|
{
|
|
this.cleanText();
|
|
this.setTypeInternal(CellValueType.String);
|
|
//проверяем можно ли перевести массив в простую строку.
|
|
if(aVal.length > 0)
|
|
{
|
|
this.multiText = [];
|
|
for(var i = 0, length = aVal.length; i < length; i++){
|
|
var item = aVal[i];
|
|
var oNewElem = new AscCommonExcel.CMultiTextElem();
|
|
oNewElem.text = item.getFragmentText ? item.getFragmentText() : item.text;
|
|
if (null != item.format) {
|
|
oNewElem.format = new AscCommonExcel.Font();
|
|
oNewElem.format.assign(item.format);
|
|
}
|
|
this.multiText.push(oNewElem);
|
|
}
|
|
this._subtractFontFromMultiText(xfTableAndCond && xfTableAndCond.font);
|
|
this._minimizeMultiText(true);
|
|
}
|
|
//обрабатываем QuotePrefix
|
|
if(null != this.text)
|
|
{
|
|
if(this.text.length > 0 && "'" == this.text[0])
|
|
{
|
|
this.setQuotePrefix(true);
|
|
this.setValueTextInternal(this.text.substring(1));
|
|
}
|
|
}
|
|
else if(null != this.multiText)
|
|
{
|
|
if(this.multiText.length > 0)
|
|
{
|
|
var oFirstItem = this.multiText[0];
|
|
if(null != oFirstItem.text && oFirstItem.text.length > 0 && "'" == oFirstItem.text[0])
|
|
{
|
|
this.setQuotePrefix(true);
|
|
if(1 != oFirstItem.text.length)
|
|
oFirstItem.text = oFirstItem.text.substring(1);
|
|
else
|
|
{
|
|
this.multiText.shift();
|
|
if(0 == this.multiText.length)
|
|
{
|
|
this.setValueTextInternal("");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype._setFontProp = function(fCheck, fAction)
|
|
{
|
|
var bRes = false;
|
|
if(null != this.multiText)
|
|
{
|
|
//проверяем поменяются ли свойства
|
|
var bChange = false;
|
|
for(var i = 0, length = this.multiText.length; i < length; ++i)
|
|
{
|
|
var elem = this.multiText[i];
|
|
if (null != elem.format && true == fCheck(elem.format))
|
|
{
|
|
bChange = true;
|
|
break;
|
|
}
|
|
}
|
|
if(bChange)
|
|
{
|
|
var backupObj = this.getValueData();
|
|
let newMultiText = this._cloneMultiText();
|
|
for (var i = 0, length = newMultiText.length; i < length; ++i) {
|
|
var elem = newMultiText[i];
|
|
if (null != elem.format)
|
|
fAction(elem.format)
|
|
}
|
|
this.setValueMultiTextInternal(newMultiText);
|
|
//пробуем преобразовать в простую строку
|
|
if(this._minimizeMultiText(false))
|
|
{
|
|
var DataNew = this.getValueData();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeValue, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow,this.nCol, backupObj, DataNew));
|
|
}
|
|
else
|
|
{
|
|
var DataNew = this._cloneMultiText();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoCell, AscCH.historyitem_Cell_ChangeArrayValueFormat, this.ws.getId(), new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow), new UndoRedoData_CellSimpleData(this.nRow, this.nCol, backupObj.value.multiText, DataNew));
|
|
}
|
|
}
|
|
bRes = true;
|
|
}
|
|
return bRes;
|
|
};
|
|
Cell.prototype._getValue2Result = function(sText, aText, isMultyText, opt_AffectingText)
|
|
{
|
|
var aResult = [];
|
|
if(null == sText && null == aText)
|
|
sText = "";
|
|
var oNewItem, cellfont = g_oDefaultFormat.Font;
|
|
var cellSelfFont = this.xfs && this.xfs.font;
|
|
var xfs = this.getCompiledStyle(undefined, opt_AffectingText);
|
|
if(null != xfs && null != xfs.font)
|
|
cellfont = xfs.font;
|
|
if(null != sText){
|
|
oNewItem = new AscCommonExcel.Fragment();
|
|
oNewItem.setFragmentText(sText);
|
|
oNewItem.format = cellfont.clone();
|
|
oNewItem.checkVisitedHyperlink(this.nRow, this.nCol, this.ws.hyperlinkManager);
|
|
oNewItem.format.setSkip(false);
|
|
oNewItem.format.setRepeat(false);
|
|
aResult.push(oNewItem);
|
|
} else if(null != aText){
|
|
for(var i = 0; i < aText.length; i++){
|
|
oNewItem = new AscCommonExcel.Fragment();
|
|
var oCurtext = aText[i];
|
|
if(null != oCurtext.text)
|
|
{
|
|
oNewItem.setFragmentText(oCurtext.text);
|
|
var oCurFormat = new AscCommonExcel.Font();
|
|
if (isMultyText && xfs && xfs.font) {
|
|
if (null != oCurtext.format && !(cellSelfFont && cellSelfFont.isEqual(oCurtext.format))) {
|
|
//MultyText format equals to cell font
|
|
if (this.xfs && !this.xfs.isNormalFont()) {
|
|
//cell font is not default
|
|
oCurFormat.assign(oCurtext.format);
|
|
if (cellSelfFont && cellSelfFont.c && oCurtext.format.c && oCurtext.format.c.isEqual(cellSelfFont.c)) {
|
|
oCurFormat.c = xfs.font.c;
|
|
}
|
|
} else {
|
|
//like in CellXfs.prototype.merge
|
|
var isTableColor = oCurtext.format.isNormalXfColor();
|
|
let mergedFont = xfs._mergeProperty(g_StyleCache.addFont, oCurtext.format, xfs.font, true, isTableColor);
|
|
oCurFormat.assign(mergedFont);
|
|
}
|
|
} else {
|
|
oCurFormat.assign(cellfont);
|
|
oCurFormat.setSkip(false);
|
|
oCurFormat.setRepeat(false);
|
|
}
|
|
} else {
|
|
oCurFormat.assign(cellfont);
|
|
oCurFormat.setSkip(false);
|
|
oCurFormat.setRepeat(false);
|
|
if (null != oCurtext.format) {
|
|
oCurFormat.assignFromObject(oCurtext.format);
|
|
}
|
|
}
|
|
oNewItem.format = oCurFormat;
|
|
oNewItem.checkVisitedHyperlink(this.nRow, this.nCol, this.ws.hyperlinkManager);
|
|
aResult.push(oNewItem);
|
|
}
|
|
}
|
|
}
|
|
return aResult;
|
|
};
|
|
Cell.prototype._getValueTypeError = function(text) {
|
|
switch (text){
|
|
case cErrorOrigin["nil"]:
|
|
return cErrorLocal["nil"];
|
|
break;
|
|
case cErrorOrigin["div"]:
|
|
return cErrorLocal["div"];
|
|
break;
|
|
case cErrorOrigin["value"]:
|
|
return cErrorLocal["value"];
|
|
break;
|
|
case cErrorOrigin["ref"]:
|
|
return cErrorLocal["ref"];
|
|
break;
|
|
case cErrorOrigin["name"]:
|
|
return cErrorLocal["name"].replace('\\', ''); // ToDo это неправильная правка для бага 32463 (нужно переделать parse формул)
|
|
break;
|
|
case cErrorOrigin["num"]:
|
|
return cErrorLocal["num"];
|
|
break;
|
|
case cErrorOrigin["na"]:
|
|
return cErrorLocal["na"];
|
|
break;
|
|
case cErrorOrigin["getdata"]:
|
|
return cErrorLocal["getdata"];
|
|
break;
|
|
case cErrorOrigin["uf"]:
|
|
return cErrorLocal["uf"];
|
|
break;
|
|
case cErrorOrigin["calc"]:
|
|
return cErrorLocal["calc"];
|
|
break;
|
|
case cErrorOrigin["spill"]:
|
|
return cErrorLocal["spill"];
|
|
break;
|
|
case cErrorOrigin["busy"]:
|
|
return cErrorLocal["busy"];
|
|
break;
|
|
}
|
|
return cErrorLocal["nil"];
|
|
};
|
|
Cell.prototype._subtractFontFromMultiText = function(font) {
|
|
if (!font) {
|
|
return;
|
|
}
|
|
var cellFont = this.getCellFont();
|
|
for (var i = 0; i < this.multiText.length; i++) {
|
|
var elem = this.multiText[i];
|
|
if (null != elem.format) {
|
|
elem.format = elem.format.clone();
|
|
elem.format.subtractEqual(font, cellFont);
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype._minimizeMultiText = function(bSetCellFont) {
|
|
var bRes = false;
|
|
if(null != this.multiText && this.multiText.length > 0)
|
|
{
|
|
var cellFont = this.getCellFont();
|
|
var oIntersectFont = null;
|
|
for (var i = 0, length = this.multiText.length; i < length; i++) {
|
|
var elem = this.multiText[i];
|
|
if (null != elem.format) {
|
|
if (null == oIntersectFont)
|
|
oIntersectFont = elem.format.clone();
|
|
oIntersectFont.intersect(elem.format, cellFont);
|
|
}
|
|
else {
|
|
oIntersectFont = cellFont;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bSetCellFont)
|
|
{
|
|
if (oIntersectFont.isEqual(g_oDefaultFormat.Font))
|
|
this.setFont(null, false);
|
|
else
|
|
this.setFont(oIntersectFont, false);
|
|
}
|
|
//если у всех элементов один формат, то сохраняем только текст
|
|
var bIsEqual = true;
|
|
for (var i = 0, length = this.multiText.length; i < length; i++)
|
|
{
|
|
var elem = this.multiText[i];
|
|
if (null != elem.format && false == oIntersectFont.isEqual(elem.format))
|
|
{
|
|
bIsEqual = false;
|
|
break;
|
|
}
|
|
}
|
|
if(bIsEqual)
|
|
{
|
|
this.setValueTextInternal(AscCommonExcel.getStringFromMultiText(this.multiText));
|
|
bRes = true;
|
|
}
|
|
}
|
|
return bRes;
|
|
};
|
|
Cell.prototype._cloneMultiText = function() {
|
|
var oRes = [];
|
|
for(var i = 0, length = this.multiText.length; i < length; ++i)
|
|
oRes.push(this.multiText[i].clone());
|
|
return oRes;
|
|
};
|
|
Cell.prototype.getIsDirty = function() {
|
|
return this.isDirty;
|
|
};
|
|
Cell.prototype.setIsDirty = function(val) {
|
|
this.isDirty = val;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.getIsCalc = function() {
|
|
return this.isCalc;
|
|
};
|
|
Cell.prototype.setIsCalc = function(val) {
|
|
this.isCalc = val;
|
|
this._hasChanged = true;
|
|
};
|
|
Cell.prototype.fromXLSB = function(stream, type, row, aCellXfs, tmp, formula) {
|
|
var end = stream.XlsbReadRecordLength() + stream.GetCurPos();
|
|
|
|
this.setRowCol(row, stream.GetULongLE() & 0x3FFF);
|
|
var nFlags2 = stream.GetULongLE();
|
|
if (0 !== (nFlags2 & 0xFFFFFF)) {
|
|
var xf = aCellXfs[nFlags2 & 0xFFFFF];
|
|
if (xf) {
|
|
this.setStyle(xf);
|
|
}
|
|
}
|
|
//todo rt_CELL_RK
|
|
if (AscCommonExcel.XLSB.rt_CELL_REAL === type || AscCommonExcel.XLSB.rt_FMLA_NUM === type) {
|
|
this.setTypeInternal(CellValueType.Number);
|
|
this.setValueNumberInternal(stream.GetDoubleLE());
|
|
} else if (AscCommonExcel.XLSB.rt_CELL_ISST === type) {
|
|
this.setTypeInternal(CellValueType.String);
|
|
this.setValueTextInternal("");//without text textIndex is ignored
|
|
this.textIndex = stream.GetULongLE() + 1;// 1-based indexing
|
|
} else if (AscCommonExcel.XLSB.rt_CELL_ST === type || AscCommonExcel.XLSB.rt_FMLA_STRING === type) {
|
|
this.setTypeInternal(CellValueType.String);
|
|
this.setValueTextInternal(stream.GetString());
|
|
} else if (AscCommonExcel.XLSB.rt_CELL_ERROR === type || AscCommonExcel.XLSB.rt_FMLA_ERROR === type) {
|
|
this.setTypeInternal(CellValueType.Error);
|
|
switch (stream.GetByte()) {
|
|
case 0x00:
|
|
this.setValueTextInternal("#NULL!");
|
|
break;
|
|
case 0x07:
|
|
this.setValueTextInternal("#DIV/0!");
|
|
break;
|
|
case 0x0F:
|
|
this.setValueTextInternal("#VALUE!");
|
|
break;
|
|
case 0x17:
|
|
this.setValueTextInternal("#REF!");
|
|
break;
|
|
case 0x1D:
|
|
this.setValueTextInternal("#NAME?");
|
|
break;
|
|
case 0x24:
|
|
this.setValueTextInternal("#NUM!");
|
|
break;
|
|
case 0x2A:
|
|
this.setValueTextInternal("#N/A");
|
|
break;
|
|
case 0x2B:
|
|
this.setValueTextInternal("#GETTING_DATA");
|
|
break;
|
|
}
|
|
} else if (AscCommonExcel.XLSB.rt_CELL_BOOL === type || AscCommonExcel.XLSB.rt_FMLA_BOOL === type) {
|
|
this.setTypeInternal(CellValueType.Bool);
|
|
this.setValueNumberInternal(stream.GetByte());
|
|
} else {
|
|
this.setTypeInternal(CellValueType.Number);
|
|
}
|
|
if (AscCommonExcel.XLSB.rt_FMLA_STRING <= type && type <= AscCommonExcel.XLSB.rt_FMLA_ERROR) {
|
|
this.fromXLSBFormula(stream, tmp.formula);
|
|
}
|
|
var flags = stream.GetUShortLE();
|
|
if (0 !== (flags & 0x4)) {
|
|
this.fromXLSBFormulaExt(stream, tmp.formula, flags);
|
|
if (0 !== (flags & 0x4000)) {
|
|
this.setTypeInternal(CellValueType.Number);
|
|
this.setValueNumberInternal(null);
|
|
}
|
|
}
|
|
if (0 !== (flags & 0x2000)) {
|
|
this.setTypeInternal(CellValueType.String);
|
|
var multiText = [];
|
|
if (this.fromXLSBRichText(stream, multiText)) {
|
|
this.setValueMultiTextInternal(multiText);
|
|
} else {
|
|
var text = multiText.reduce(function(accumulator, currentValue) {
|
|
return accumulator + currentValue.text;
|
|
}, '');
|
|
this.setValueTextInternal(text);
|
|
}
|
|
}
|
|
if (0 !== (nFlags2 & 0x2000000))
|
|
{
|
|
this.setCm(stream.GetULong());
|
|
}
|
|
if (0 !== (nFlags2 & 0x4000000))
|
|
{
|
|
this.setVm(stream.GetULong());
|
|
}
|
|
|
|
stream.Seek2(end);
|
|
};
|
|
Cell.prototype.fromXLSBFormula = function(stream, formula) {
|
|
var flags = stream.GetUChar();
|
|
stream.Skip2(9);
|
|
if (0 !== (flags & 0x2)) {
|
|
formula.ca = true;
|
|
}
|
|
};
|
|
Cell.prototype.fromXLSBFormulaExt = function(stream, formula, flags) {
|
|
formula.t = flags & 0x3;
|
|
formula.v = stream.GetString();
|
|
if (0 !== (flags & 0x8)) {
|
|
formula.aca = true;
|
|
}
|
|
if (0 !== (flags & 0x10)) {
|
|
formula.bx = true;
|
|
}
|
|
if (0 !== (flags & 0x20)) {
|
|
formula.del1 = true;
|
|
}
|
|
if (0 !== (flags & 0x40)) {
|
|
formula.del2 = true;
|
|
}
|
|
if (0 !== (flags & 0x80)) {
|
|
formula.dt2d = true;
|
|
}
|
|
if (0 !== (flags & 0x100)) {
|
|
formula.dtr = true;
|
|
}
|
|
if (0 !== (flags & 0x200)) {
|
|
formula.r1 = stream.GetString();
|
|
}
|
|
if (0 !== (flags & 0x400)) {
|
|
formula.r2 = stream.GetString();
|
|
}
|
|
if (0 !== (flags & 0x800)) {
|
|
formula.ref = stream.GetString();
|
|
}
|
|
if (0 !== (flags & 0x1000)) {
|
|
formula.si = stream.GetULongLE();
|
|
}
|
|
};
|
|
Cell.prototype.fromXLSBRichText = function(stream, richText) {
|
|
var hasFormat = false;
|
|
var count = stream.GetULongLE();
|
|
while (count-- > 0) {
|
|
var typeRun = stream.GetUChar();
|
|
var run;
|
|
if (0x1 === typeRun) {
|
|
run = new AscCommonExcel.CMultiTextElem();
|
|
run.text = "";
|
|
if (stream.GetBool()) {
|
|
hasFormat = true;
|
|
run.format = new AscCommonExcel.Font();
|
|
run.format.fromXLSB(stream);
|
|
run.format.checkSchemeFont(this.ws.workbook.theme);
|
|
}
|
|
var textCount = stream.GetULongLE();
|
|
while (textCount-- > 0) {
|
|
run.text += stream.GetString();
|
|
}
|
|
richText.push(run);
|
|
}
|
|
else if (0x2 === typeRun) {
|
|
run = new AscCommonExcel.CMultiTextElem();
|
|
run.text = stream.GetString();
|
|
richText.push(run);
|
|
}
|
|
}
|
|
return hasFormat;
|
|
};
|
|
Cell.prototype.toXLSB = function(stream, nXfsId, formulaToWrite, oSharedStrings) {
|
|
var len = 4 + 4 + 2;
|
|
var type = AscCommonExcel.XLSB.rt_CELL_BLANK;
|
|
if (formulaToWrite) {
|
|
len += this.getXLSBSizeFormula(formulaToWrite);
|
|
}
|
|
var textToWrite;
|
|
var isBlankFormula = false;
|
|
if (formulaToWrite) {
|
|
if (!this.isNullTextString()) {
|
|
switch (this.type) {
|
|
case CellValueType.Number:
|
|
type = AscCommonExcel.XLSB.rt_FMLA_NUM;
|
|
len += 8;
|
|
break;
|
|
case CellValueType.String:
|
|
type = AscCommonExcel.XLSB.rt_FMLA_STRING;
|
|
textToWrite = this.text ? this.text : AscCommonExcel.getStringFromMultiText(this.multiText);
|
|
len += 4 + 2 * textToWrite.length;
|
|
break;
|
|
case CellValueType.Error:
|
|
type = AscCommonExcel.XLSB.rt_FMLA_ERROR;
|
|
len += 1;
|
|
break;
|
|
case CellValueType.Bool:
|
|
type = AscCommonExcel.XLSB.rt_FMLA_BOOL;
|
|
len += 1;
|
|
break;
|
|
}
|
|
} else {
|
|
type = AscCommonExcel.XLSB.rt_FMLA_STRING;
|
|
textToWrite = "";
|
|
len += 4 + 2 * textToWrite.length;
|
|
isBlankFormula = true;
|
|
}
|
|
} else {
|
|
if (!this.isNullTextString()) {
|
|
switch (this.type) {
|
|
case CellValueType.Number:
|
|
type = AscCommonExcel.XLSB.rt_CELL_REAL;
|
|
len += 8;
|
|
break;
|
|
case CellValueType.String:
|
|
type = AscCommonExcel.XLSB.rt_CELL_ISST;
|
|
len += 4;
|
|
break;
|
|
case CellValueType.Error:
|
|
type = AscCommonExcel.XLSB.rt_CELL_ERROR;
|
|
len += 1;
|
|
break;
|
|
case CellValueType.Bool:
|
|
type = AscCommonExcel.XLSB.rt_CELL_BOOL;
|
|
len += 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
stream.XlsbStartRecord(type, len);
|
|
stream.WriteULong(this.nCol & 0x3FFF);
|
|
var nFlags2 = 0;
|
|
if (null !== nXfsId) {
|
|
nFlags2 = nXfsId;
|
|
}
|
|
if (this.cm != null) {
|
|
nFlags2 |= 0x2000000;
|
|
}
|
|
if (this.vm != null) {
|
|
nFlags2 |= 0x4000000;
|
|
}
|
|
stream.WriteULong(nFlags2);
|
|
|
|
//todo RkNumber
|
|
switch (type) {
|
|
case AscCommonExcel.XLSB.rt_CELL_REAL:
|
|
case AscCommonExcel.XLSB.rt_FMLA_NUM:
|
|
stream.WriteDouble2(this.number);
|
|
break;
|
|
case AscCommonExcel.XLSB.rt_CELL_ISST:
|
|
var index;
|
|
var textIndex = this.getTextIndex();
|
|
if (null !== textIndex) {
|
|
index = oSharedStrings.strings[textIndex];
|
|
if (undefined === index) {
|
|
index = oSharedStrings.index++;
|
|
oSharedStrings.strings[textIndex] = index;
|
|
}
|
|
}
|
|
stream.WriteULong(index);
|
|
break;
|
|
case AscCommonExcel.XLSB.rt_CELL_ST:
|
|
case AscCommonExcel.XLSB.rt_FMLA_STRING:
|
|
stream.WriteString4(textToWrite);
|
|
break;
|
|
case AscCommonExcel.XLSB.rt_CELL_ERROR:
|
|
case AscCommonExcel.XLSB.rt_FMLA_ERROR:
|
|
if ("#NULL!" == this.text) {
|
|
stream.WriteByte(0x00);
|
|
}
|
|
else if ("#DIV/0!" == this.text) {
|
|
stream.WriteByte(0x07);
|
|
}
|
|
else if ("#VALUE!" == this.text) {
|
|
stream.WriteByte(0x0F);
|
|
}
|
|
else if ("#REF!" == this.text) {
|
|
stream.WriteByte(0x17);
|
|
}
|
|
else if ("#NAME?" == this.text) {
|
|
stream.WriteByte(0x1D);
|
|
}
|
|
else if ("#NUM!" == this.text) {
|
|
stream.WriteByte(0x24);
|
|
}
|
|
else if ("#N/A" == this.text) {
|
|
stream.WriteByte(0x2A);
|
|
}
|
|
else {
|
|
stream.WriteByte(0x2B);
|
|
}
|
|
break;
|
|
case AscCommonExcel.XLSB.rt_CELL_BOOL:
|
|
case AscCommonExcel.XLSB.rt_FMLA_BOOL:
|
|
stream.WriteByte(this.number);
|
|
break;
|
|
}
|
|
var flags = 0;
|
|
if (formulaToWrite) {
|
|
flags = this.toXLSBFormula(stream, formulaToWrite, isBlankFormula);
|
|
}
|
|
|
|
|
|
stream.WriteUShort(flags);
|
|
|
|
if (formulaToWrite) {
|
|
flags = this.toXLSBFormulaExt(stream, formulaToWrite);
|
|
}
|
|
|
|
if (this.cm != null) {
|
|
stream.WriteULong(this.cm);
|
|
}
|
|
if (this.vm != null) {
|
|
stream.WriteULong(this.vm);
|
|
}
|
|
|
|
stream.XlsbEndRecord();
|
|
};
|
|
Cell.prototype.readAttributes = function(attr, uq) {
|
|
if (attr()) {
|
|
this.parseAttributes(attr(), uq);
|
|
}
|
|
};
|
|
Cell.prototype.parseAttributes = function(vals, uq) {
|
|
var val;
|
|
val = vals["r"];
|
|
if (undefined !== val) {
|
|
var oCellAddress = AscCommon.g_oCellAddressUtils.getCellAddress(val);
|
|
this.setRowCol(oCellAddress.getRow0(), oCellAddress.getCol0());
|
|
this.ws.nRowsCount = Math.max(this.ws.nRowsCount, this.nRow);
|
|
this.ws.nColsCount = Math.max(this.ws.nColsCount, this.nCol);
|
|
this.ws.cellsByColRowsCount = Math.max(this.ws.cellsByColRowsCount, this.nCol);
|
|
}
|
|
val = vals["t"];
|
|
if (undefined !== val) {
|
|
if("s" === val) {
|
|
this.type = CellValueType.String;
|
|
}
|
|
}
|
|
};
|
|
Cell.prototype.onStartNode = function(elem, attr, uq, tagend, getStrNode) {
|
|
var attrVals;
|
|
if ('v' === elem) {
|
|
return this;
|
|
}
|
|
return this;
|
|
};
|
|
Cell.prototype.onTextNode = function(text, uq) {
|
|
if(CellValueType.String === this.type) {
|
|
this.text = AscCommon.unleakString(uq(text));
|
|
} else if(CellValueType.Number === this.type) {
|
|
this.number = parseInt(text);
|
|
}
|
|
};
|
|
Cell.prototype.onEndNode = function(prevContext, elem) {
|
|
var res = true;
|
|
if ('v' === elem) {
|
|
} else {
|
|
res = false;
|
|
}
|
|
return res;
|
|
};
|
|
Cell.prototype.getXLSBSizeFormula = function(formulaToWrite) {
|
|
var len = 2 + 4 + 4;
|
|
if (formulaToWrite.formula) {
|
|
len += 4 + 2 * formulaToWrite.formula.length;
|
|
} else {
|
|
len += 4;
|
|
}
|
|
if (undefined !== formulaToWrite.ref) {
|
|
len += 4 + 2 * formulaToWrite.ref.getName().length;
|
|
}
|
|
if (undefined !== formulaToWrite.si) {
|
|
len += 4;
|
|
}
|
|
return len;
|
|
};
|
|
Cell.prototype.toXLSBFormula = function(stream, formulaToWrite, isBlankFormula) {
|
|
var flags = 0;
|
|
if (formulaToWrite.ca) {
|
|
flags |= 0x2;
|
|
}
|
|
stream.WriteUShort(flags);
|
|
stream.WriteULong(0);//cce
|
|
stream.WriteULong(0);//cb
|
|
|
|
var flagsExt = 0;
|
|
if (undefined !== formulaToWrite.type) {
|
|
flagsExt |= formulaToWrite.type;
|
|
}
|
|
else {
|
|
flagsExt |= Asc.ECellFormulaType.cellformulatypeNormal;
|
|
}
|
|
flagsExt |= 0x4;
|
|
if (undefined !== formulaToWrite.ref) {
|
|
flagsExt |= 0x800;
|
|
}
|
|
if (undefined !== formulaToWrite.si) {
|
|
flagsExt |= 0x1000;
|
|
}
|
|
if (isBlankFormula) {
|
|
flagsExt |= 0x4000;
|
|
}
|
|
return flagsExt;
|
|
};
|
|
Cell.prototype.toXLSBFormulaExt = function(stream, formulaToWrite) {
|
|
if (undefined !== formulaToWrite.formula) {
|
|
stream.WriteString4(formulaToWrite.formula);
|
|
} else {
|
|
stream.WriteString4("");
|
|
}
|
|
if (undefined !== formulaToWrite.ref) {
|
|
stream.WriteString4(formulaToWrite.ref.getName());
|
|
}
|
|
if (undefined !== formulaToWrite.si) {
|
|
stream.WriteULong(formulaToWrite.si);
|
|
}
|
|
};
|
|
Cell.prototype.setDynamicArrayFlags = function () {
|
|
this.cm = 1;
|
|
// this.vm = 1;
|
|
// todo prop vm - determines the order in which dynamic arrays are expanded?
|
|
// presumably the metadata it refers to contains the estimated size of the array
|
|
// the size of the array is unique and has its own number in the order of initialization on the page
|
|
// for example array 3x1 initialized before than array 2x1 will have the number 1 in vm prop
|
|
};
|
|
Cell.prototype.setCm = function(val) {
|
|
this.cm = val;
|
|
};
|
|
Cell.prototype.setVm = function(val) {
|
|
this.vm = val;
|
|
};
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
function CCellWithFormula(ws, row, col) {
|
|
this.ws = ws;
|
|
this.nRow = row;
|
|
this.nCol = col;
|
|
}
|
|
CCellWithFormula.prototype.onFormulaEvent = function(type, eventData) {
|
|
if (AscCommon.c_oNotifyParentType.GetRangeCell === type) {
|
|
return new Asc.Range(this.nCol, this.nRow, this.nCol, this.nRow);
|
|
} else if (AscCommon.c_oNotifyParentType.Change === type) {
|
|
this._onChange(eventData);
|
|
} else if (AscCommon.c_oNotifyParentType.ChangeFormula === type) {
|
|
this._onChangeFormula(eventData);
|
|
} else if (AscCommon.c_oNotifyParentType.EndCalculate === type) {
|
|
this.ws._getCell(this.nRow, this.nCol, function(cell) {
|
|
cell._updateCellValue();
|
|
});
|
|
} else if (AscCommon.c_oNotifyParentType.Shared === type) {
|
|
return this._onShared(eventData);
|
|
}
|
|
};
|
|
CCellWithFormula.prototype._onChange = function(eventData) {
|
|
var areaData = eventData.notifyData.areaData;
|
|
var shared = eventData.formula.getShared();
|
|
var arrayF = eventData.formula.getArrayFormulaRef();
|
|
var dependencyFormulas = this.ws.workbook.dependencyFormulas;
|
|
if (shared) {
|
|
if (areaData) {
|
|
var bbox = areaData.bbox;
|
|
var changedRange = bbox.getSharedIntersect(shared.ref, areaData.changedBBox);
|
|
dependencyFormulas.addToChangedRange2(this.ws.getId(), changedRange);
|
|
} else {
|
|
dependencyFormulas.addToChangedRange2(this.ws.getId(), shared.ref);
|
|
}
|
|
} else if(arrayF) {
|
|
dependencyFormulas.addToChangedRange2(this.ws.getId(), arrayF);
|
|
} else {
|
|
this.ws.workbook.dependencyFormulas.addToChangedCell(this);
|
|
}
|
|
};
|
|
CCellWithFormula.prototype._onChangeFormula = function(eventData) {
|
|
var t = this;
|
|
var wb = this.ws.workbook;
|
|
var parsed = eventData.formula;
|
|
var shared = parsed.getShared();
|
|
if (shared) {
|
|
var index = wb.workbookFormulas.add(parsed).getIndexNumber();
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoSharedFormula, AscCH.historyitem_SharedFormula_ChangeFormula, null, null, new UndoRedoData_IndexSimpleProp(index, false, parsed.getFormulaRaw(), eventData.assemble), true);
|
|
wb.dependencyFormulas.addToChangedRange2(this.ws.getId(), shared.ref);
|
|
} else {
|
|
this.ws._getCell(this.nRow, this.nCol, function(cell) {
|
|
if (parsed === cell.formulaParsed) {
|
|
cell.setFormulaTemplate(true, function(cell) {
|
|
cell.formulaParsed.setFormulaString(eventData.assemble);
|
|
wb.dependencyFormulas.addToChangedCell(cell);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
};
|
|
CCellWithFormula.prototype._onShared = function(eventData) {
|
|
var res = false;
|
|
var data = eventData.notifyData;
|
|
var parsed = eventData.formula;
|
|
var forceTransform = false;
|
|
var sharedShift;//affected shared
|
|
var ranges;//ranges than needed to be transform
|
|
var i;
|
|
var shared = parsed.getShared();
|
|
if (shared) {
|
|
if (c_oNotifyType.Shift === data.type) {
|
|
var bHor = 0 !== data.offset.col;
|
|
var toDelete = data.offset.col < 0 || data.offset.row < 0;
|
|
var bboxShift = AscCommonExcel.shiftGetBBox(data.bbox, bHor);
|
|
sharedShift = parsed.getSharedIntersect(data.sheetId, bboxShift);
|
|
if (sharedShift) {
|
|
//try to remain as many shared formulas as possible
|
|
//that shared can only be at intersection with bboxShift
|
|
var sharedIntersect;
|
|
if (parsed.canShiftShared(bHor) && (sharedIntersect = bboxShift.intersectionSimple(shared.ref))) {
|
|
//collect relative complement of sharedShift and sharedIntersect
|
|
ranges = sharedIntersect.difference(sharedShift);
|
|
ranges = ranges.concat(sharedShift.difference(sharedIntersect));
|
|
//cut off shared than affected relative complement of bboxShift
|
|
var cantBeShared;
|
|
var diff = bboxShift.difference(new Asc.Range(0, 0, gc_nMaxCol0, gc_nMaxRow0));
|
|
if (toDelete) {
|
|
//cut off shared than affected delete range
|
|
diff.push(data.bbox);
|
|
}
|
|
for (i = 0; i < diff.length; ++i) {
|
|
var elem = parsed.getSharedIntersect(data.sheetId, diff[i]);
|
|
if (elem) {
|
|
if (cantBeShared) {
|
|
cantBeShared.union2(elem)
|
|
} else {
|
|
cantBeShared = elem;
|
|
}
|
|
}
|
|
}
|
|
if (cantBeShared) {
|
|
var intersection = sharedIntersect.intersectionSimple(cantBeShared);
|
|
if (intersection) {
|
|
ranges.push(intersection);
|
|
}
|
|
}
|
|
forceTransform = true;
|
|
data.shiftedShared[parsed.getListenerId()] = c_oSharedShiftType.PreProcessed;
|
|
} else {
|
|
ranges = [sharedShift];
|
|
}
|
|
}
|
|
res = true;
|
|
} else if (c_oNotifyType.Move === data.type || c_oNotifyType.Delete === data.type) {
|
|
sharedShift = parsed.getSharedIntersect(data.sheetId, data.bbox);
|
|
if (sharedShift) {
|
|
ranges = [sharedShift];
|
|
}
|
|
res = true;
|
|
} else if (AscCommon.c_oNotifyType.ChangeDefName === data.type && data.bConvertTableFormulaToRef) {
|
|
this._processShared(shared, shared.ref, data, parsed, true, function(newFormula) {
|
|
return newFormula.processNotify(data);
|
|
});
|
|
res = true;
|
|
}
|
|
if (ranges) {
|
|
for (i = 0; i < ranges.length; ++i) {
|
|
this._processShared(shared, ranges[i], data, parsed, forceTransform, function(newFormula) {
|
|
return newFormula.shiftCells(data.type, data.sheetId, data.bbox, data.offset, data.sheetIdTo);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
CCellWithFormula.prototype._processShared = function(shared, ref, data, parsed, forceTransform, action) {
|
|
var t = this;
|
|
var cellWithFormula;
|
|
var cellOffset = new AscCommon.CellBase();
|
|
var newFormula;
|
|
this.ws.getRange3(ref.r1, ref.c1, ref.r2, ref.c2)._foreachNoEmpty(function(cell) {
|
|
if (parsed === cell.getFormulaParsed()) {
|
|
if (!cellWithFormula) {
|
|
cellWithFormula = new AscCommonExcel.CCellWithFormula(cell.ws, cell.nRow, cell.nCol);
|
|
newFormula = parsed.clone(undefined, cellWithFormula);
|
|
newFormula.removeShared();
|
|
cellOffset.row = cell.nRow - shared.base.nRow;
|
|
cellOffset.col = cell.nCol - shared.base.nCol;
|
|
} else {
|
|
cellOffset.row = cell.nRow - cellWithFormula.nRow;
|
|
cellOffset.col = cell.nCol - cellWithFormula.nCol;
|
|
cellWithFormula.nRow = cell.nRow;
|
|
cellWithFormula.nCol = cell.nCol;
|
|
}
|
|
newFormula.changeOffset(cellOffset, false);
|
|
if (action(newFormula) || forceTransform) {
|
|
cellWithFormula = undefined;
|
|
newFormula.setFormulaString(newFormula.assemble(true));
|
|
cell.setFormulaTemplate(true, function(cell) {
|
|
cell.setFormulaInternal(newFormula);
|
|
newFormula.buildDependencies();
|
|
});
|
|
}
|
|
t.ws.workbook.dependencyFormulas.addToChangedCell(cell);
|
|
}
|
|
});
|
|
};
|
|
|
|
function CellTypeAndValue(type, v) {
|
|
this.type = type;
|
|
this.v = v;
|
|
}
|
|
CellTypeAndValue.prototype.valueOf = function() {
|
|
return this.v;
|
|
};
|
|
|
|
function ignoreFirstRowSort(worksheet, bbox) {
|
|
var res = false;
|
|
|
|
var oldExcludeVal = worksheet.bExcludeHiddenRows;
|
|
worksheet.bExcludeHiddenRows = false;
|
|
if(bbox.r1 < bbox.r2) {
|
|
var rowFirst = worksheet.getRange3(bbox.r1, bbox.c1, bbox.r1, bbox.c2);
|
|
var rowSecond = worksheet.getRange3(bbox.r1 + 1, bbox.c1, bbox.r1 + 1, bbox.c2);
|
|
var typesFirst = [];
|
|
var typesSecond = [];
|
|
rowFirst._setPropertyNoEmpty(null, null, function(cell, row, col) {
|
|
if (cell && !cell.isNullTextString()) {
|
|
typesFirst.push({col: col, type: cell.getType()});
|
|
}
|
|
});
|
|
rowSecond._setPropertyNoEmpty(null, null, function(cell, row, col) {
|
|
if (cell && !cell.isNullTextString()) {
|
|
typesSecond.push({col: col, type: cell.getType()});
|
|
}
|
|
});
|
|
var indexFirst = 0;
|
|
var indexSecond = 0;
|
|
while (indexFirst < typesFirst.length && indexSecond < typesSecond.length) {
|
|
var curFirst = typesFirst[indexFirst];
|
|
var curSecond = typesSecond[indexSecond];
|
|
if (curFirst.col < curSecond.col) {
|
|
indexFirst++;
|
|
} else if (curFirst.col > curSecond.col) {
|
|
indexSecond++;
|
|
} else {
|
|
if (curFirst.type != curSecond.type) {
|
|
//has head
|
|
res = true;
|
|
break;
|
|
}
|
|
indexFirst++;
|
|
indexSecond++;
|
|
}
|
|
}
|
|
}
|
|
worksheet.bExcludeHiddenRows = oldExcludeVal;
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function Range(worksheet, r1, c1, r2, c2){
|
|
this.worksheet = worksheet;
|
|
this.bbox = new Asc.Range(c1, r1, c2, r2);
|
|
}
|
|
Range.prototype.createFromBBox=function(worksheet, bbox){
|
|
var oRes = new Range(worksheet, bbox.r1, bbox.c1, bbox.r2, bbox.c2);
|
|
oRes.bbox = bbox.clone();
|
|
return oRes;
|
|
};
|
|
Range.prototype.clone=function(oNewWs){
|
|
if(!oNewWs)
|
|
oNewWs = this.worksheet;
|
|
return this.createFromBBox(oNewWs, this.bbox);
|
|
};
|
|
Range.prototype.isIntersect=function(oRange){
|
|
if(this.worksheet === oRange.worksheet) {
|
|
return this.bbox.isIntersect(oRange.bbox);
|
|
}
|
|
return false;
|
|
};
|
|
Range.prototype.containsRange=function(oRange){
|
|
if(this.worksheet === oRange.worksheet) {
|
|
return this.bbox.containsRange(oRange.bbox);
|
|
}
|
|
return false;
|
|
};
|
|
Range.prototype.isIntersectForInsertColRow=function(oRange, isInsertCol){
|
|
if(this.worksheet === oRange.worksheet) {
|
|
return this.bbox.isIntersectForInsertColRow(oRange.bbox, isInsertCol);
|
|
}
|
|
return false;
|
|
};
|
|
Range.prototype._foreach = function(action) {
|
|
if (null != action) {
|
|
var wb = this.worksheet.workbook;
|
|
var tempCell = new Cell(this.worksheet);
|
|
wb.loadCells.push(tempCell);
|
|
var oBBox = this.bbox;
|
|
for (var i = oBBox.r1; i <= oBBox.r2; i++) {
|
|
if (this.worksheet.bExcludeHiddenRows && this.worksheet.getRowHidden(i)) {
|
|
continue;
|
|
}
|
|
for (var j = oBBox.c1; j <= oBBox.c2; j++) {
|
|
var targetCell = null;
|
|
for (var k = 0; k < wb.loadCells.length - 1; ++k) {
|
|
var elem = wb.loadCells[k];
|
|
if (elem.nRow == i && elem.nCol == j && this.worksheet === elem.ws) {
|
|
targetCell = elem;
|
|
break;
|
|
}
|
|
}
|
|
if (null === targetCell) {
|
|
if (!tempCell.loadContent(i, j)) {
|
|
this.worksheet._initCell(tempCell, i, j);
|
|
}
|
|
action(tempCell, i, j, oBBox.r1, oBBox.c1);
|
|
tempCell.saveContent(true);
|
|
} else {
|
|
action(targetCell, i, j, oBBox.r1, oBBox.c1);
|
|
}
|
|
}
|
|
}
|
|
wb.loadCells.pop();
|
|
}
|
|
};
|
|
Range.prototype._foreach2=function(action){
|
|
if(null != action)
|
|
{
|
|
var wb = this.worksheet.workbook;
|
|
var oRes;
|
|
var tempCell = new Cell(this.worksheet);
|
|
wb.loadCells.push(tempCell);
|
|
var oBBox = this.bbox, minC = Math.min( this.worksheet.getColDataLength(), oBBox.c2 ), minR = Math.min( this.worksheet.cellsByColRowsCount - 1, oBBox.r2 );
|
|
for(var i = oBBox.r1; i <= minR; i++){
|
|
if (this.worksheet.bExcludeHiddenRows && this.worksheet.getRowHidden(i)) {
|
|
continue;
|
|
}
|
|
for(var j = oBBox.c1; j <= minC; j++){
|
|
var targetCell = null;
|
|
for (var k = 0; k < wb.loadCells.length - 1; ++k) {
|
|
var elem = wb.loadCells[k];
|
|
if (elem.nRow == i && elem.nCol == j && this.worksheet === elem.ws) {
|
|
targetCell = elem;
|
|
break;
|
|
}
|
|
}
|
|
if (null === targetCell) {
|
|
if (tempCell.loadContent(i, j)) {
|
|
oRes = action(tempCell, i, j, oBBox.r1, oBBox.c1);
|
|
tempCell.saveContent(true);
|
|
} else {
|
|
oRes = action(null, i, j, oBBox.r1, oBBox.c1);
|
|
}
|
|
} else {
|
|
oRes = action(targetCell, i, j, oBBox.r1, oBBox.c1);
|
|
}
|
|
|
|
if(null != oRes){
|
|
wb.loadCells.pop();
|
|
return oRes;
|
|
}
|
|
}
|
|
}
|
|
wb.loadCells.pop();
|
|
}
|
|
};
|
|
Range.prototype._foreachNoEmpty = function(actionCell, actionRow, excludeHiddenRows) {
|
|
var oRes, i, oBBox = this.bbox, minR = Math.max(this.worksheet.cellsByColRowsCount - 1, this.worksheet.rowsData.getMaxIndex());
|
|
minR = Math.min(minR, oBBox.r2);
|
|
if (actionCell || actionRow) {
|
|
var itRow = new RowIterator();
|
|
if (actionCell) {
|
|
itRow.init(this.worksheet, this.bbox.r1, this.bbox.c1, this.bbox.c2);
|
|
}
|
|
var bExcludeHiddenRows = (this.worksheet.bExcludeHiddenRows || excludeHiddenRows);
|
|
var excludedCount = 0;
|
|
var tempCell;
|
|
var tempRow = new AscCommonExcel.Row(this.worksheet);
|
|
var allRow = this.worksheet.getAllRow();
|
|
var allRowHidden = allRow && allRow.getHidden();
|
|
for (i = oBBox.r1; i <= minR; i++) {
|
|
if (actionRow) {
|
|
if (tempRow.loadContent(i)) {
|
|
if (bExcludeHiddenRows && tempRow.getHidden()) {
|
|
excludedCount++;
|
|
continue;
|
|
}
|
|
oRes = actionRow(tempRow, excludedCount);
|
|
tempRow.saveContent(true);
|
|
if (null != oRes) {
|
|
if (actionCell) {
|
|
itRow.release();
|
|
}
|
|
return oRes;
|
|
}
|
|
} else if (bExcludeHiddenRows && allRowHidden) {
|
|
excludedCount++;
|
|
continue;
|
|
}
|
|
} else if (bExcludeHiddenRows && this.worksheet.getRowHidden(i)) {
|
|
excludedCount++;
|
|
continue;
|
|
}
|
|
if (actionCell) {
|
|
itRow.setRow(i);
|
|
while (tempCell = itRow.next()) {
|
|
oRes = actionCell(tempCell, i, tempCell.nCol, oBBox.r1, oBBox.c1, excludedCount);
|
|
if (null != oRes) {
|
|
if (actionCell) {
|
|
itRow.release();
|
|
}
|
|
return oRes;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (actionCell) {
|
|
itRow.release();
|
|
}
|
|
}
|
|
};
|
|
Range.prototype._foreachNoEmptyByCol = function(actionCell, excludeHiddenRows) {
|
|
var oRes, i, j, colData;
|
|
var wb = this.worksheet.workbook;
|
|
var oBBox = this.bbox, minR = Math.min(this.worksheet.cellsByColRowsCount - 1, oBBox.r2);
|
|
var minC = Math.min(this.worksheet.getColDataLength() - 1, oBBox.c2);
|
|
if (actionCell && oBBox.c1 <= minC && oBBox.r1 <= minR) {
|
|
var bExcludeHiddenRows = (this.worksheet.bExcludeHiddenRows || excludeHiddenRows);
|
|
var excludedCount = 0;
|
|
var tempCell = new Cell(this.worksheet);
|
|
wb.loadCells.push(tempCell);
|
|
for (j = oBBox.c1; j <= minC; ++j) {
|
|
colData = this.worksheet.getColDataNoEmpty(j);
|
|
if (colData) {
|
|
for (i = oBBox.r1; i <= Math.min(minR, colData.getMaxIndex()); i++) {
|
|
if (bExcludeHiddenRows && this.worksheet.getRowHidden(i)) {
|
|
excludedCount++;
|
|
continue;
|
|
}
|
|
var targetCell = null;
|
|
for (var k = 0; k < wb.loadCells.length - 1; ++k) {
|
|
var elem = wb.loadCells[k];
|
|
if (elem.nRow == i && elem.nCol == j && this.worksheet === elem.ws) {
|
|
targetCell = elem;
|
|
break;
|
|
}
|
|
}
|
|
if (null === targetCell) {
|
|
if (tempCell.loadContent(i, j, colData)) {
|
|
oRes = actionCell(tempCell, i, j, oBBox.r1, oBBox.c1, excludedCount);
|
|
tempCell.saveContent(true);
|
|
}
|
|
} else {
|
|
oRes = actionCell(targetCell, i, j, oBBox.r1, oBBox.c1, excludedCount);
|
|
}
|
|
if (null != oRes) {
|
|
wb.loadCells.pop();
|
|
return oRes;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
wb.loadCells.pop();
|
|
}
|
|
};
|
|
Range.prototype._foreachRow = function(actionRow, actionCell){
|
|
var oBBox = this.bbox;
|
|
if (null != actionRow) {
|
|
var tempRow = new AscCommonExcel.Row(this.worksheet);
|
|
for (var i = oBBox.r1; i <= oBBox.r2; i++) {
|
|
if (!tempRow.loadContent(i)) {
|
|
this.worksheet._initRow(tempRow, i);
|
|
}
|
|
if (this.worksheet.bExcludeHiddenRows && tempRow.getHidden()) {
|
|
continue;
|
|
}
|
|
actionRow(tempRow);
|
|
tempRow.saveContent(true);
|
|
}
|
|
}
|
|
if (null != actionCell) {
|
|
return this._foreachNoEmpty(actionCell);
|
|
}
|
|
};
|
|
Range.prototype._foreachRowNoEmpty = function(actionRow, actionCell, excludeHiddenRows) {
|
|
return this._foreachNoEmpty(actionCell, actionRow, excludeHiddenRows);
|
|
};
|
|
Range.prototype._foreachCol = function(actionCol, actionCell){
|
|
var oBBox = this.bbox;
|
|
if(null != actionCol)
|
|
{
|
|
for(var i = oBBox.c1; i <= oBBox.c2; ++i)
|
|
{
|
|
var col = this.worksheet._getCol(i);
|
|
if(null != col)
|
|
actionCol(col);
|
|
}
|
|
}
|
|
if(null != actionCell) {
|
|
this._foreachNoEmpty(actionCell);
|
|
}
|
|
};
|
|
Range.prototype._foreachColNoEmpty=function(actionCol, actionCell){
|
|
var oBBox = this.bbox;
|
|
var minC = Math.min(oBBox.c2, this.worksheet.aCols.length);
|
|
if(null != actionCol)
|
|
{
|
|
for(var i = oBBox.c1; i <= minC; ++i)
|
|
{
|
|
var col = this.worksheet._getColNoEmpty(i);
|
|
if(null != col)
|
|
{
|
|
var oRes = actionCol(col);
|
|
if(null != oRes)
|
|
return oRes;
|
|
}
|
|
}
|
|
}
|
|
if (null != actionCell) {
|
|
return this._foreachNoEmpty(actionCell);
|
|
}
|
|
};
|
|
Range.prototype._getRangeType=function(oBBox){
|
|
if(null == oBBox)
|
|
oBBox = this.bbox;
|
|
return getRangeType(oBBox);
|
|
};
|
|
Range.prototype._getValues = function (numbers) {
|
|
var res = [];
|
|
var fAction = numbers ? function (c) {
|
|
var v = c.getNumberValue();
|
|
if (null !== v) {
|
|
res.push(v);
|
|
}
|
|
} : function (c) {
|
|
res.push(new CellTypeAndValue(c.getType(), c.getValueWithoutFormat()));
|
|
};
|
|
this._setPropertyNoEmpty(null, null, fAction);
|
|
return res;
|
|
};
|
|
Range.prototype._getValuesAndMap = function (withEmpty) {
|
|
var v, arrRes = [], mapRes = {};
|
|
var fAction = function(c) {
|
|
v = c.getValueWithoutFormat();
|
|
arrRes.push(new CellTypeAndValue(c.getType(), v));
|
|
mapRes[v.toLowerCase()] = true;
|
|
};
|
|
if (withEmpty) {
|
|
this._foreach(fAction);
|
|
} else {
|
|
this._setPropertyNoEmpty(null, null, fAction);
|
|
}
|
|
return {values: arrRes, map: mapRes};
|
|
};
|
|
Range.prototype._setProperty=function(actionRow, actionCol, actionCell){
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.Range == nRangeType)
|
|
this._foreach(actionCell);
|
|
else if(c_oRangeType.Row == nRangeType)
|
|
this._foreachRow(actionRow, actionCell);
|
|
else if(c_oRangeType.Col == nRangeType)
|
|
this._foreachCol(actionCol, actionCell);
|
|
else
|
|
{
|
|
//сюда не должны заходить вообще
|
|
// this._foreachRow(actionRow, actionCell);
|
|
// if(null != actionCol)
|
|
// this._foreachCol(actionCol, null);
|
|
}
|
|
};
|
|
Range.prototype._setPropertyNoEmpty=function(actionRow, actionCol, actionCell){
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.Range == nRangeType)
|
|
return this._foreachNoEmpty(actionCell);
|
|
else if(c_oRangeType.Row == nRangeType)
|
|
return this._foreachRowNoEmpty(actionRow, actionCell);
|
|
else if(c_oRangeType.Col == nRangeType)
|
|
return this._foreachColNoEmpty(actionCol, actionCell);
|
|
else
|
|
{
|
|
var oRes = this._foreachRowNoEmpty(actionRow, actionCell);
|
|
if(null != oRes)
|
|
return oRes;
|
|
if(null != actionCol)
|
|
oRes = this._foreachColNoEmpty(actionCol, null);
|
|
return oRes;
|
|
}
|
|
};
|
|
Range.prototype.containCell=function(cellId){
|
|
var cellAddress = cellId;
|
|
return cellAddress.getRow0() >= this.bbox.r1 && cellAddress.getCol0() >= this.bbox.c1 &&
|
|
cellAddress.getRow0() <= this.bbox.r2 && cellAddress.getCol0() <= this.bbox.c2;
|
|
};
|
|
Range.prototype.containCell2=function(cell){
|
|
return cell.nRow >= this.bbox.r1 && cell.nCol >= this.bbox.c1 &&
|
|
cell.nRow <= this.bbox.r2 && cell.nCol <= this.bbox.c2;
|
|
};
|
|
Range.prototype.cross = function(bbox){
|
|
if( bbox.r1 >= this.bbox.r1 && bbox.r1 <= this.bbox.r2 && this.bbox.c1 == this.bbox.c2)
|
|
return {r:bbox.r1};
|
|
if( bbox.c1 >= this.bbox.c1 && bbox.c1 <= this.bbox.c2 && this.bbox.r1 == this.bbox.r2)
|
|
return {c:bbox.c1};
|
|
|
|
return undefined;
|
|
};
|
|
Range.prototype.getWorksheet=function(){
|
|
return this.worksheet;
|
|
};
|
|
Range.prototype.isFormula = function(){
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var isFormula;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function(cell) {
|
|
isFormula = cell.isFormula();
|
|
});
|
|
return isFormula;
|
|
};
|
|
Range.prototype.isOneCell=function(){
|
|
var oBBox = this.bbox;
|
|
return oBBox.r1 === oBBox.r2 && oBBox.c1 === oBBox.c2;
|
|
};
|
|
Range.prototype.getBBox0=function(){
|
|
//0 - based
|
|
return this.bbox;
|
|
};
|
|
Range.prototype.getName=function(){
|
|
return this.bbox.getName();
|
|
};
|
|
Range.prototype.getMinimalCellsRange = function() {
|
|
var nType = this._getRangeType();
|
|
var oMinRange;
|
|
if(nType === c_oRangeType.Range) {
|
|
return this;
|
|
} else {
|
|
oMinRange = this.worksheet.getMinimalRange();
|
|
if(!oMinRange) {
|
|
return null;
|
|
}
|
|
var oBB = this.bbox;
|
|
var r1 = oBB.r1, c1 = oBB.c1, r2 = oBB.r2, c2 = oBB.c2;
|
|
if(nType === c_oRangeType.Col) {
|
|
r1 = oMinRange.r1;
|
|
r2 = oMinRange.r2;
|
|
} else if(nType === c_oRangeType.Row) {
|
|
c1 = oMinRange.c1;
|
|
c2 = oMinRange.c2;
|
|
} else {
|
|
r1 = oMinRange.r1;
|
|
r2 = oMinRange.r2;
|
|
c1 = oMinRange.c1;
|
|
c2 = oMinRange.c2;
|
|
}
|
|
return new Range(this.worksheet, r1, c1, r2, c2);
|
|
}
|
|
};
|
|
Range.prototype.setValue=function(val, callback, isCopyPaste, byRef, ignoreHyperlink, dynamicRange){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
//не хотелось бы вводить дополнительный параметр, поэтому если byRef == null
|
|
//то в качестве значения придёт формула, которой необходимо сделать offset в зависимости от range
|
|
//при вызове данной функции обратить внимание на параметр byRef
|
|
var _formula, t = this, activeCell;
|
|
if (byRef === null) {
|
|
_formula = new AscCommonExcel.parserFormula(val.substr(1), null, this.worksheet);
|
|
if (!_formula.parse(true)) {
|
|
_formula = null;
|
|
} else {
|
|
var _selection = this.worksheet.getSelection();
|
|
activeCell = _selection.activeCell;
|
|
}
|
|
}
|
|
this._foreach(function(cell){
|
|
if (cell.ws.isUserProtectedRangesIntersectionCell(cell)) {
|
|
return;
|
|
}
|
|
var _val = val;
|
|
if (_formula) {
|
|
_formula.isParsed = false;
|
|
_formula.outStack = [];
|
|
_formula.parse(true);
|
|
var offset = new AscCommon.CellBase(cell.nRow - activeCell.row, cell.nCol - activeCell.col);
|
|
_val = "=" + _formula.changeOffset(offset, null, true).assembleLocale(AscCommonExcel.cFormulaFunctionToLocale, true, true);
|
|
}
|
|
// when creating new array formulas, it is necessary to transfer information about the dynamic array because regular ref is used
|
|
cell.setValue(_val, callback, isCopyPaste, byRef, ignoreHyperlink, dynamicRange);
|
|
});
|
|
|
|
//***array-formula***
|
|
let _sFormula = this.getFormula();
|
|
if(_sFormula && byRef) {
|
|
History.Add(AscCommonExcel.g_oUndoRedoArrayFormula, AscCH.historyitem_ArrayFromula_AddFormula, this.worksheet.getId(),
|
|
new Asc.Range(this.bbox.c1, this.bbox.r1, this.bbox.c2, this.bbox.r2), new AscCommonExcel.UndoRedoData_ArrayFormula(this.bbox, "=" + _sFormula));
|
|
}
|
|
|
|
AscCommon.History.EndTransaction();
|
|
this.onWorksheetChange();
|
|
};
|
|
Range.prototype.setValue2=function(array, pushOnlyFirstMergedCell){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
//[{"text":"qwe","format":{"b":true, "i":false, "u":Asc.EUnderline.underlineNone, "s":false, "fn":"Arial", "fs": 12, "c": 0xff00ff, "va": "subscript" }},{}...]
|
|
/*
|
|
Устанавливаем значение в Range ячеек. В отличае от setValue, сюда мы попадаем только в случае ввода значения отличного от формулы. Таким образом, если в ячейке была формула, то для нее в графе очищается список ячеек от которых зависела. После чего выставляем флаг о необходимости пересчета.
|
|
*/
|
|
let t = this;
|
|
this._foreach(function(cell){
|
|
if (pushOnlyFirstMergedCell) {
|
|
let merged = t.worksheet.getMergedByCell(cell.nRow, cell.nCol);
|
|
if (!merged || (merged && merged.r1 === cell.nRow && merged.c1 === cell.nCol)) {
|
|
cell.setValue2(array);
|
|
}
|
|
} else {
|
|
cell.setValue2(array);
|
|
}
|
|
// if(cell.isEmpty())
|
|
// cell.Remove();
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
this.onWorksheetChange();
|
|
};
|
|
Range.prototype.setValueData = function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
this._foreach(function(cell){
|
|
cell.setValueData(val);
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.setCellStyle=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var oStyle;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
oStyle = this.worksheet.getAllCol().setCellStyle(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
oStyle = row.setCellStyle(val);
|
|
},
|
|
function(col){
|
|
oStyle = col.setCellStyle(val);
|
|
},
|
|
function(cell){
|
|
oStyle = cell.setCellStyle(val);
|
|
});
|
|
if (oStyle && oStyle.ApplyNumberFormat)
|
|
this.setNumFormatPivot(oStyle.getNumFormatStr());
|
|
};
|
|
Range.prototype.setStyle=function(val){
|
|
if (val === null) {
|
|
return;
|
|
}
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setStyle(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setStyle(val);
|
|
},
|
|
function(col){
|
|
col.setStyle(val);
|
|
},
|
|
function(cell){
|
|
cell.setStyle(val);
|
|
});
|
|
};
|
|
Range.prototype.clearTableStyle = function() {
|
|
this.worksheet.sheetMergedStyles.clearTablePivotStyle(this.bbox);
|
|
};
|
|
Range.prototype.setTableStyle = function(xf, stripe) {
|
|
if (xf) {
|
|
this.worksheet.sheetMergedStyles.setTablePivotStyle(this.bbox, xf, stripe);
|
|
}
|
|
};
|
|
Range.prototype.setNumFormatPivot=function(val){
|
|
const pivotTables = this.worksheet.getPivotTablesIntersectingRange(this.bbox);
|
|
pivotTables.forEach(function (pivotTable) {
|
|
pivotTable.formatsManager.setNum(this.bbox, val);
|
|
}, this);
|
|
}
|
|
Range.prototype.setNumFormat=function(val){
|
|
this.setNum(new AscCommonExcel.Num({f:val}));
|
|
this.setNumFormatPivot(val);
|
|
};
|
|
Range.prototype.setNum = function(val) {
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if (c_oRangeType.All == nRangeType) {
|
|
this.worksheet.getAllCol().setNum(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row) {
|
|
if (c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setNum(val);
|
|
},
|
|
function(col) {
|
|
col.setNum(val);
|
|
},
|
|
function(cell) {
|
|
cell.setNum(val);
|
|
});
|
|
};
|
|
Range.prototype.getShiftedNumFormat=function(nShift, dDigitsCount){
|
|
AscCommon.History.Create_NewPoint();
|
|
let newNumFormat;
|
|
this._setPropertyNoEmpty(null, null, function(cell, nRow0, nCol0, nRowStart, nColStart){
|
|
newNumFormat = cell.getShiftedNumFormat(nShift, dDigitsCount);
|
|
});
|
|
return newNumFormat;
|
|
};
|
|
Range.prototype.setFont=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setFont(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setFont(val);
|
|
},
|
|
function(col){
|
|
col.setFont(val);
|
|
},
|
|
function(cell){
|
|
cell.setFont(val);
|
|
});
|
|
};
|
|
Range.prototype.setFontname=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setFontname(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setFontname(val);
|
|
},
|
|
function(col){
|
|
col.setFontname(val);
|
|
},
|
|
function(cell){
|
|
cell.setFontname(val);
|
|
});
|
|
};
|
|
Range.prototype.setFontsize=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setFontsize(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setFontsize(val);
|
|
},
|
|
function(col){
|
|
col.setFontsize(val);
|
|
},
|
|
function(cell){
|
|
cell.setFontsize(val);
|
|
});
|
|
};
|
|
Range.prototype.setFontcolor=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setFontcolor(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setFontcolor(val);
|
|
},
|
|
function(col){
|
|
col.setFontcolor(val);
|
|
},
|
|
function(cell){
|
|
cell.setFontcolor(val);
|
|
});
|
|
};
|
|
Range.prototype.setBold=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setBold(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setBold(val);
|
|
},
|
|
function(col){
|
|
col.setBold(val);
|
|
},
|
|
function(cell){
|
|
cell.setBold(val);
|
|
});
|
|
};
|
|
Range.prototype.setItalic=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setItalic(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setItalic(val);
|
|
},
|
|
function(col){
|
|
col.setItalic(val);
|
|
},
|
|
function(cell){
|
|
cell.setItalic(val);
|
|
});
|
|
};
|
|
Range.prototype.setUnderline=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setUnderline(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setUnderline(val);
|
|
},
|
|
function(col){
|
|
col.setUnderline(val);
|
|
},
|
|
function(cell){
|
|
cell.setUnderline(val);
|
|
});
|
|
};
|
|
Range.prototype.setStrikeout=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setStrikeout(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setStrikeout(val);
|
|
},
|
|
function(col){
|
|
col.setStrikeout(val);
|
|
},
|
|
function(cell){
|
|
cell.setStrikeout(val);
|
|
});
|
|
};
|
|
Range.prototype.setFontAlign=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setFontAlign(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setFontAlign(val);
|
|
},
|
|
function(col){
|
|
col.setFontAlign(val);
|
|
},
|
|
function(cell){
|
|
cell.setFontAlign(val);
|
|
});
|
|
};
|
|
Range.prototype.setAlignVertical=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setAlignVertical(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setAlignVertical(val);
|
|
},
|
|
function(col){
|
|
col.setAlignVertical(val);
|
|
},
|
|
function(cell){
|
|
cell.setAlignVertical(val);
|
|
});
|
|
};
|
|
Range.prototype.setAlignHorizontal=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setAlignHorizontal(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setAlignHorizontal(val);
|
|
},
|
|
function(col){
|
|
col.setAlignHorizontal(val);
|
|
},
|
|
function(cell){
|
|
cell.setAlignHorizontal(val);
|
|
});
|
|
};
|
|
Range.prototype.setReadingOrder=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setReadingOrder(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setReadingOrder(val);
|
|
},
|
|
function(col){
|
|
col.setReadingOrder(val);
|
|
},
|
|
function(cell){
|
|
cell.setReadingOrder(val);
|
|
});
|
|
};
|
|
Range.prototype.setFill=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setFill(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setFill(val);
|
|
},
|
|
function(col){
|
|
col.setFill(val);
|
|
},
|
|
function(cell){
|
|
cell.setFill(val);
|
|
});
|
|
};
|
|
Range.prototype.setFillColor=function(val){
|
|
var fill = new AscCommonExcel.Fill();
|
|
fill.fromColor(val);
|
|
return this.setFill(fill);
|
|
};
|
|
Range.prototype.setBorderSrc=function(border){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
if (null == border)
|
|
border = new Border();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setBorder(border.clone());
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setBorder(border.clone());
|
|
},
|
|
function(col){
|
|
col.setBorder(border.clone());
|
|
},
|
|
function(cell){
|
|
cell.setBorder(border.clone());
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype._setBorderMerge=function(bLeft, bTop, bRight, bBottom, oNewBorder, oCurBorder){
|
|
var oTargetBorder = new Border();
|
|
//не делаем clone для свойств потому у нас нельзя поменять свойство отдельное свойство border можно только применить border целиком
|
|
if(bLeft)
|
|
oTargetBorder.l = oNewBorder.l;
|
|
else
|
|
oTargetBorder.l = oNewBorder.iv;
|
|
if(bTop)
|
|
oTargetBorder.t = oNewBorder.t;
|
|
else
|
|
oTargetBorder.t = oNewBorder.ih;
|
|
if(bRight)
|
|
oTargetBorder.r = oNewBorder.r;
|
|
else
|
|
oTargetBorder.r = oNewBorder.iv;
|
|
if(bBottom)
|
|
oTargetBorder.b = oNewBorder.b;
|
|
else
|
|
oTargetBorder.b = oNewBorder.ih;
|
|
oTargetBorder.d = oNewBorder.d;
|
|
oTargetBorder.dd = oNewBorder.dd;
|
|
oTargetBorder.du = oNewBorder.du;
|
|
var oRes = null;
|
|
if(null != oCurBorder)
|
|
{
|
|
oCurBorder.mergeInner(oTargetBorder);
|
|
oRes = oCurBorder;
|
|
}
|
|
else
|
|
oRes = oTargetBorder;
|
|
return oRes;
|
|
};
|
|
Range.prototype._setCellBorder=function(bbox, cell, oNewBorder){
|
|
if(null == oNewBorder)
|
|
cell.setBorder(oNewBorder);
|
|
else
|
|
{
|
|
var oCurBorder = null;
|
|
if(null != cell.xfs && null != cell.xfs.border)
|
|
oCurBorder = cell.xfs.border.clone();
|
|
else
|
|
oCurBorder = g_oDefaultFormat.Border.clone();
|
|
var nRow = cell.nRow;
|
|
var nCol = cell.nCol;
|
|
cell.setBorder(this._setBorderMerge(nCol == bbox.c1, nRow == bbox.r1, nCol == bbox.c2, nRow == bbox.r2, oNewBorder, oCurBorder));
|
|
}
|
|
};
|
|
Range.prototype._setRowColBorder=function(bbox, rowcol, bRow, oNewBorder){
|
|
if(null == oNewBorder)
|
|
rowcol.setBorder(oNewBorder);
|
|
else
|
|
{
|
|
var oCurBorder = null;
|
|
if(null != rowcol.xfs && null != rowcol.xfs.border)
|
|
oCurBorder = rowcol.xfs.border.clone();
|
|
var bLeft, bTop, bRight, bBottom = false;
|
|
if(bRow)
|
|
{
|
|
bTop = rowcol.index == bbox.r1;
|
|
bBottom = rowcol.index == bbox.r2;
|
|
}
|
|
else
|
|
{
|
|
bLeft = rowcol.index == bbox.c1;
|
|
bRight = rowcol.index == bbox.c2;
|
|
}
|
|
rowcol.setBorder(this._setBorderMerge(bLeft, bTop, bRight, bBottom, oNewBorder, oCurBorder));
|
|
}
|
|
};
|
|
Range.prototype._setBorderEdge=function(bbox, oItemWithXfs, nRow, nCol, oNewBorder){
|
|
var oCurBorder = null;
|
|
if(null != oItemWithXfs.xfs && null != oItemWithXfs.xfs.border)
|
|
oCurBorder = oItemWithXfs.xfs.border;
|
|
if(null != oCurBorder)
|
|
{
|
|
var oCurBorderProp = null;
|
|
if(nCol == bbox.c1 - 1)
|
|
oCurBorderProp = oCurBorder.r;
|
|
else if(nRow == bbox.r1 - 1)
|
|
oCurBorderProp = oCurBorder.b;
|
|
else if(nCol == bbox.c2 + 1)
|
|
oCurBorderProp = oCurBorder.l;
|
|
else if(nRow == bbox.r2 + 1)
|
|
oCurBorderProp = oCurBorder.t;
|
|
var oNewBorderProp = null;
|
|
if(null == oNewBorder)
|
|
oNewBorderProp = new AscCommonExcel.BorderProp();
|
|
else
|
|
{
|
|
if(nCol == bbox.c1 - 1)
|
|
oNewBorderProp = oNewBorder.l;
|
|
else if(nRow == bbox.r1 - 1)
|
|
oNewBorderProp = oNewBorder.t;
|
|
else if(nCol == bbox.c2 + 1)
|
|
oNewBorderProp = oNewBorder.r;
|
|
else if(nRow == bbox.r2 + 1)
|
|
oNewBorderProp = oNewBorder.b;
|
|
}
|
|
|
|
if(null != oNewBorderProp && null != oCurBorderProp && c_oAscBorderStyles.None != oCurBorderProp.s && (null == oNewBorder || c_oAscBorderStyles.None != oNewBorderProp.s) &&
|
|
(oNewBorderProp.s != oCurBorderProp.s || oNewBorderProp.getRgbOrNull() != oCurBorderProp.getRgbOrNull())){
|
|
var oTargetBorder = oCurBorder.clone();
|
|
if(nCol == bbox.c1 - 1)
|
|
oTargetBorder.r = new AscCommonExcel.BorderProp();
|
|
else if(nRow == bbox.r1 - 1)
|
|
oTargetBorder.b = new AscCommonExcel.BorderProp();
|
|
else if(nCol == bbox.c2 + 1)
|
|
oTargetBorder.l = new AscCommonExcel.BorderProp();
|
|
else if(nRow == bbox.r2 + 1)
|
|
oTargetBorder.t = new AscCommonExcel.BorderProp();
|
|
oItemWithXfs.setBorder(oTargetBorder);
|
|
}
|
|
}
|
|
};
|
|
Range.prototype.setBorder=function(border){
|
|
//border = null очисть border
|
|
//"ih" - внутренние горизонтальные, "iv" - внутренние вертикальные
|
|
AscCommon.History.Create_NewPoint();
|
|
var _this = this;
|
|
var oBBox = this.bbox;
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
var oAllCol = this.worksheet.getAllCol();
|
|
_this._setRowColBorder(oBBox, oAllCol, false, border);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
_this._setRowColBorder(oBBox, row, true, border);
|
|
},
|
|
function(col){
|
|
_this._setRowColBorder(oBBox, col, false, border);
|
|
},
|
|
function(cell){
|
|
_this._setCellBorder(oBBox, cell, border);
|
|
});
|
|
//убираем граничные border
|
|
var aEdgeBorders = [];
|
|
if(oBBox.c1 > 0 && (null == border || (border.l && !border.l.isEmpty())))
|
|
aEdgeBorders.push(this.worksheet.getRange3(oBBox.r1, oBBox.c1 - 1, oBBox.r2, oBBox.c1 - 1));
|
|
if(oBBox.r1 > 0 && (null == border || (border.t && !border.t.isEmpty())))
|
|
aEdgeBorders.push(this.worksheet.getRange3(oBBox.r1 - 1, oBBox.c1, oBBox.r1 - 1, oBBox.c2));
|
|
if(oBBox.c2 < gc_nMaxCol0 && (null == border || (border.r && !border.r.isEmpty())))
|
|
aEdgeBorders.push(this.worksheet.getRange3(oBBox.r1, oBBox.c2 + 1, oBBox.r2, oBBox.c2 + 1));
|
|
if(oBBox.r2 < gc_nMaxRow0 && (null == border || (border.b && !border.b.isEmpty())))
|
|
aEdgeBorders.push(this.worksheet.getRange3(oBBox.r2 + 1, oBBox.c1, oBBox.r2 + 1, oBBox.c2));
|
|
for(var i = 0, length = aEdgeBorders.length; i < length; i++)
|
|
{
|
|
var range = aEdgeBorders[i];
|
|
range._setPropertyNoEmpty(function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
_this._setBorderEdge(oBBox, row, row.index, 0, border);
|
|
},
|
|
function(col){
|
|
_this._setBorderEdge(oBBox, col, 0, col.index, border);
|
|
},
|
|
function(cell){
|
|
_this._setBorderEdge(oBBox, cell, cell.nRow, cell.nCol, border);
|
|
});
|
|
}
|
|
};
|
|
Range.prototype.setShrinkToFit=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setShrinkToFit(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setShrinkToFit(val);
|
|
},
|
|
function(col){
|
|
col.setShrinkToFit(val);
|
|
},
|
|
function(cell){
|
|
cell.setShrinkToFit(val);
|
|
});
|
|
};
|
|
Range.prototype.setWrap=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setWrap(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setWrap(val);
|
|
},
|
|
function(col){
|
|
col.setWrap(val);
|
|
},
|
|
function(cell){
|
|
cell.setWrap(val);
|
|
});
|
|
};
|
|
Range.prototype.setAngle=function(val){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
this.worksheet.getAllCol().setAngle(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(c_oRangeType.All == nRangeType && null == row.xfs)
|
|
return;
|
|
row.setAngle(val);
|
|
},
|
|
function(col){
|
|
col.setAngle(val);
|
|
},
|
|
function(cell){
|
|
cell.setAngle(val);
|
|
});
|
|
};
|
|
Range.prototype.setIndent = function (val) {
|
|
if (val < 0) {
|
|
return;
|
|
}
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if (c_oRangeType.All == nRangeType) {
|
|
this.worksheet.getAllCol().setAngle(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function (row) {
|
|
if (c_oRangeType.All == nRangeType && null == row.xfs) {
|
|
return;
|
|
}
|
|
row.setIndent(val);
|
|
}, function (col) {
|
|
col.setIndent(val);
|
|
}, function (cell) {
|
|
cell.setIndent(val);
|
|
});
|
|
};
|
|
Range.prototype.setApplyProtection = function (val) {
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if (c_oRangeType.All == nRangeType) {
|
|
this.worksheet.getAllCol().setApplyProtection(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function (row) {
|
|
if (c_oRangeType.All == nRangeType && null == row.xfs) {
|
|
return;
|
|
}
|
|
row.setApplyProtection(val);
|
|
}, function (col) {
|
|
col.setApplyProtection(val);
|
|
}, function (cell) {
|
|
cell.setApplyProtection(val);
|
|
});
|
|
};
|
|
Range.prototype.setLocked = function (val) {
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if (c_oRangeType.All == nRangeType) {
|
|
this.worksheet.getAllCol().setLocked(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function (row) {
|
|
if (c_oRangeType.All == nRangeType && null == row.xfs) {
|
|
return;
|
|
}
|
|
row.setLocked(val);
|
|
}, function (col) {
|
|
col.setLocked(val);
|
|
}, function (cell) {
|
|
cell.setLocked(val);
|
|
});
|
|
};
|
|
Range.prototype.setHiddenFormulas = function (val) {
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if (c_oRangeType.All == nRangeType) {
|
|
this.worksheet.getAllCol().setHiddenFormulas(val);
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
}
|
|
fSetProperty.call(this, function (row) {
|
|
if (c_oRangeType.All == nRangeType && null == row.xfs) {
|
|
return;
|
|
}
|
|
row.setHiddenFormulas(val);
|
|
}, function (col) {
|
|
col.setHiddenFormulas(val);
|
|
}, function (cell) {
|
|
cell.setHiddenFormulas(val);
|
|
});
|
|
};
|
|
Range.prototype.setType=function(type){
|
|
AscCommon.History.Create_NewPoint();
|
|
this.createCellOnRowColCross();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
fSetProperty.call(this, null, null,
|
|
function(cell){
|
|
cell.setType(type);
|
|
});
|
|
};
|
|
Range.prototype.changeTextCase=function(type){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
this._setPropertyNoEmpty(null, null,function(cell){
|
|
cell.changeTextCase(type);
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.changeReadingOrder=function(readingOrder){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
this._setPropertyNoEmpty(null, null,function(cell){
|
|
cell.changeTextCase(readingOrder);
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.getType=function(){
|
|
var type;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
type = cell.getType();
|
|
else
|
|
type = null;
|
|
});
|
|
return type;
|
|
};
|
|
Range.prototype.isNullText=function(){
|
|
var isNullText;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
isNullText = (null != cell) ? cell.isNullText() : true;
|
|
});
|
|
return isNullText;
|
|
};
|
|
Range.prototype.isEmptyTextString=function(){
|
|
var isEmptyTextString;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
isEmptyTextString = (null != cell) ? cell.isEmptyTextString() : true;
|
|
});
|
|
return isEmptyTextString;
|
|
};
|
|
Range.prototype.isNullTextString=function(){
|
|
var isNullTextString;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
isNullTextString = (null != cell) ? cell.isNullTextString() : true;
|
|
});
|
|
return isNullTextString;
|
|
};
|
|
Range.prototype.isFormula=function(){
|
|
var isFormula;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
isFormula = (null != cell) ? cell.isFormula() : false;
|
|
});
|
|
return isFormula;
|
|
};
|
|
Range.prototype.isFormulaContains=function(){
|
|
var isFormula;
|
|
this._foreachNoEmpty(function(cell) {
|
|
isFormula = (null != cell) ? cell.isFormula() : false;
|
|
return isFormula ? isFormula : null;
|
|
});
|
|
return isFormula;
|
|
};
|
|
Range.prototype.getFormula=function(){
|
|
var formula;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
formula = cell.getFormula();
|
|
else
|
|
formula = "";
|
|
});
|
|
return formula;
|
|
};
|
|
Range.prototype.getValueForEdit=function(checkFormulaArray){
|
|
var t = this;
|
|
var valueForEdit;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
{
|
|
valueForEdit = cell.getValueForEdit(checkFormulaArray);
|
|
}
|
|
else
|
|
valueForEdit = "";
|
|
});
|
|
return valueForEdit;
|
|
};
|
|
Range.prototype.getValueForEdit2=function(){
|
|
var t = this;
|
|
var valueForEdit2;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
{
|
|
valueForEdit2 = cell.getValueForEdit2();
|
|
}
|
|
else
|
|
{
|
|
var xfs = null;
|
|
t.worksheet._getRowNoEmpty(t.bbox.r1, function(row){
|
|
var oCol = t.worksheet._getColNoEmptyWithAll(t.bbox.c1);
|
|
if(row && null != row.xfs)
|
|
xfs = row.xfs.clone();
|
|
else if(null != oCol && null != oCol.xfs)
|
|
xfs = oCol.xfs.clone();
|
|
});
|
|
var oTempCell = new Cell(t.worksheet);
|
|
oTempCell.setRowCol(t.bbox.r1, t.bbox.c1);
|
|
oTempCell.setStyleInternal(xfs);
|
|
valueForEdit2 = oTempCell.getValueForEdit2();
|
|
}
|
|
});
|
|
return valueForEdit2;
|
|
};
|
|
Range.prototype.getValueWithoutFormat=function(){
|
|
var valueWithoutFormat;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
valueWithoutFormat = cell.getValueWithoutFormat();
|
|
else
|
|
valueWithoutFormat = "";
|
|
});
|
|
return valueWithoutFormat;
|
|
};
|
|
Range.prototype.getQuotePrefix=function(){
|
|
let res = false;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell) {
|
|
if(null != cell && cell.getQuotePrefix())
|
|
res = true;
|
|
});
|
|
return res;
|
|
};
|
|
Range.prototype.getValue=function(){
|
|
return this.getValueWithoutFormat();
|
|
};
|
|
Range.prototype.getValueWithFormat=function(){
|
|
var value;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
value = cell.getValue();
|
|
else
|
|
value = "";
|
|
});
|
|
return value;
|
|
};
|
|
Range.prototype.getValueWithFormatSkipToSpace=function(){
|
|
var value;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
value = cell.getValueSkipToSpace();
|
|
else
|
|
value = "";
|
|
});
|
|
return value;
|
|
};
|
|
Range.prototype.getValue2=function(dDigitsCount, fIsFitMeasurer){
|
|
//[{"text":"qwe","format":{"b":true, "i":false, "u":Asc.EUnderline.underlineNone, "s":false, "fn":"Arial", "fs": 12, "c": 0xff00ff, "va": "subscript" }},{}...]
|
|
var t = this;
|
|
var value2;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell){
|
|
if(null != cell)
|
|
value2 = cell.getValue2(dDigitsCount, fIsFitMeasurer);
|
|
else
|
|
{
|
|
var xfs = null;
|
|
t.worksheet._getRowNoEmpty(t.bbox.r1, function(row){
|
|
var oCol = t.worksheet._getColNoEmptyWithAll(t.bbox.c1);
|
|
|
|
if(row && null != row.xfs)
|
|
xfs = row.xfs.clone();
|
|
else if(null != oCol && null != oCol.xfs)
|
|
xfs = oCol.xfs.clone();
|
|
});
|
|
var oTempCell = new Cell(t.worksheet);
|
|
oTempCell.setRowCol(t.bbox.r1, t.bbox.c1);
|
|
oTempCell.setStyleInternal(xfs);
|
|
value2 = oTempCell.getValue2(dDigitsCount, fIsFitMeasurer);
|
|
}
|
|
});
|
|
return value2;
|
|
};
|
|
Range.prototype.getNumberValue = function() {
|
|
var numberValue;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell) {
|
|
numberValue = null != cell ? cell.getNumberValue() : null;
|
|
});
|
|
return numberValue;
|
|
};
|
|
Range.prototype.getValueData=function(){
|
|
var res = null;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, function(cell) {
|
|
if(null != cell)
|
|
res = cell.getValueData();
|
|
});
|
|
return res;
|
|
};
|
|
Range.prototype.getXfs = function (compiled) {
|
|
var ws = this.worksheet;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var xfs;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
xfs = ws.getCompiledStyle(nRow, nCol, cell, compiled ? null : emptyStyleComponents);
|
|
});
|
|
return xfs || g_oDefaultFormat.xfs;
|
|
};
|
|
Range.prototype.getStyle = Range.prototype.getXfs;
|
|
Range.prototype.getXfId = function () {
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var XfId = g_oDefaultFormat.XfId;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs && null !== xfs.XfId) {
|
|
XfId = xfs.XfId;
|
|
}
|
|
});
|
|
return XfId;
|
|
};
|
|
Range.prototype.getStyleName=function(){
|
|
var res = this.worksheet.workbook.CellStyles.getStyleNameByXfId(this.getXfId());
|
|
|
|
// ToDo убрать эту заглушку (нужно делать на открытии) в InitStyleManager
|
|
return res || this.worksheet.workbook.CellStyles.getStyleNameByXfId(g_oDefaultFormat.XfId);
|
|
};
|
|
Range.prototype.getTableStyle=function(){
|
|
var tableStyle;
|
|
this.worksheet._getCellNoEmpty(this.bbox.r1,this.bbox.c1, function(cell) {
|
|
tableStyle = cell ? cell.getTableStyle() : null;
|
|
});
|
|
return tableStyle;
|
|
};
|
|
Range.prototype.getCompiledStyleCustom = function(needTable, needCell, needConditional) {
|
|
return this.worksheet.getCompiledStyleCustom(this.bbox.r1,this.bbox.c1, needTable, needCell, needConditional);
|
|
};
|
|
Range.prototype.getNumFormat=function(){
|
|
return oNumFormatCache.get(this.getNumFormatStr());
|
|
};
|
|
Range.prototype.getNumFormatStr = function () {
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var numFormatStr = g_oDefaultFormat.Num.getFormat();
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs && xfs.num) {
|
|
numFormatStr = xfs.num.getFormat();
|
|
}
|
|
});
|
|
return numFormatStr;
|
|
};
|
|
Range.prototype.getNumFormatType=function(){
|
|
return this.getNumFormat().getType();
|
|
};
|
|
// Узнаем отличается ли шрифт (размер и гарнитура) в ячейке от шрифта в строке
|
|
Range.prototype.isNotDefaultFont = function () {
|
|
// Получаем фонт ячейки
|
|
var t = this;
|
|
var cellFont = this.getFont();
|
|
var rowFont = g_oDefaultFormat.Font;
|
|
this.worksheet._getRowNoEmpty(this.bbox.r1, function(row) {
|
|
if (row && null != row.xfs && null != row.xfs.font)
|
|
rowFont = row.xfs.font;
|
|
else if (null != t.worksheet.oAllCol && t.worksheet.oAllCol.xfs && t.worksheet.oAllCol.xfs.font)
|
|
rowFont = t.worksheet.oAllCol.xfs.font;
|
|
});
|
|
|
|
return (cellFont.getName() !== rowFont.getName() || cellFont.getSize() !== rowFont.getSize());
|
|
};
|
|
Range.prototype.getFont = function (original) {
|
|
// ToDo разобраться. Есть предположение, что эта функция не нужна и она работает не верно
|
|
// при выставлении стиля всему столбцу и тексте в ячейке
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var font = g_oDefaultFormat.Font;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs;
|
|
if (cell) {
|
|
xfs = original ? cell.getStyle() : cell.getCompiledStyle();
|
|
} else {
|
|
xfs = t.worksheet.getCompiledStyle(nRow, nCol, null, original ? emptyStyleComponents : null);
|
|
}
|
|
if (xfs && xfs.font) {
|
|
font = xfs.font;
|
|
}
|
|
});
|
|
return font;
|
|
};
|
|
Range.prototype.getAlignHorizontalByValue=function(align){
|
|
//возвращает Align в зависимости от значния в ячейке
|
|
//values: none, center, justify, left , right, null
|
|
var t = this;
|
|
if(null == align){
|
|
//пытаемся определить по значению
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function(cell) {
|
|
if(cell){
|
|
switch(cell.getType()){
|
|
case CellValueType.String: {
|
|
|
|
let dir = AscCommon.getFirstStrongDirection(cell.text);
|
|
if (dir === AscBidi.DIRECTION_FLAG.RTL) {
|
|
align = AscCommon.align_Right;
|
|
}
|
|
else {
|
|
align = AscCommon.align_Left;
|
|
}
|
|
break;
|
|
}
|
|
case CellValueType.Bool:
|
|
case CellValueType.Error:align = AscCommon.align_Center;break;
|
|
default:
|
|
//Если есть value и не проставлен тип значит это число, у всех остальных типов значение не null
|
|
if(t.getValueWithoutFormat())
|
|
{
|
|
//смотрим
|
|
var oNumFmt = t.getNumFormat();
|
|
if(true == oNumFmt.isTextFormat())
|
|
align = AscCommon.align_Left;
|
|
else
|
|
align = AscCommon.align_Right;
|
|
}
|
|
else
|
|
align = AscCommon.align_Left;
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
if(null == align)
|
|
align = AscCommon.align_Left;
|
|
}
|
|
return align;
|
|
};
|
|
|
|
Range.prototype.getAngle = function () {
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var angle;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var align = cell.getAlign();
|
|
angle = align.getAngle();
|
|
});
|
|
return angle;
|
|
}
|
|
|
|
Range.prototype.getFillColor = function () {
|
|
return this.getFill().bg();
|
|
};
|
|
Range.prototype.getFill = function () {
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var fill = g_oDefaultFormat.Fill;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs && xfs.fill) {
|
|
fill = xfs.fill;
|
|
}
|
|
});
|
|
return fill;
|
|
};
|
|
Range.prototype.getLocked = function () {
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var isLocked = true;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs) {
|
|
isLocked = xfs.getLocked();
|
|
}
|
|
});
|
|
return isLocked;
|
|
};
|
|
Range.prototype.getHidden = function () {
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var isHidden = false;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs) {
|
|
isHidden = xfs.getHidden();
|
|
}
|
|
});
|
|
return isHidden;
|
|
};
|
|
Range.prototype.getBorderSrc = function (opt_row, opt_col) {
|
|
//Возвращает как записано в файле, не проверяя бордеры соседних ячеек
|
|
//формат
|
|
//\{"l": {"s": "solid", "c": 0xff0000}, "t": {} ,"r": {} ,"b": {} ,"d": {},"dd": false ,"du": false }
|
|
//"s" values: none, thick, thin, medium, dashDot, dashDotDot, dashed, dotted, double, hair, mediumDashDot, mediumDashDotDot, mediumDashed, slantDashDot
|
|
//"dd" diagonal line, starting at the top left corner of the cell and moving down to the bottom right corner of the cell
|
|
//"du" diagonal line, starting at the bottom left corner of the cell and moving up to the top right corner of the cell
|
|
var t = this;
|
|
var nRow = null != opt_row ? opt_row : this.bbox.r1;
|
|
var nCol = null != opt_col ? opt_col : this.bbox.c1;
|
|
var border = g_oDefaultFormat.Border;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function (cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs && xfs.border) {
|
|
border = xfs.border;
|
|
}
|
|
});
|
|
return border;
|
|
};
|
|
Range.prototype.getBorder = function (opt_row, opt_col) {
|
|
//Возвращает как записано в файле, не проверяя бордеры соседних ячеек
|
|
//формат
|
|
//\{"l": {"s": "solid", "c": 0xff0000}, "t": {} ,"r": {} ,"b": {} ,"d": {},"dd": false ,"du": false }
|
|
//"s" values: none, thick, thin, medium, dashDot, dashDotDot, dashed, dotted, double, hair, mediumDashDot, mediumDashDotDot, mediumDashed, slantDashDot
|
|
//"dd" diagonal line, starting at the top left corner of the cell and moving down to the bottom right corner of the cell
|
|
//"du" diagonal line, starting at the bottom left corner of the cell and moving up to the top right corner of the cell
|
|
return this.getBorderSrc(opt_row, opt_col) || g_oDefaultFormat.Border;
|
|
};
|
|
Range.prototype.getBorderFull=function(){
|
|
//Возвращает как excel, т.е. проверяет бордеры соседних ячеек
|
|
//
|
|
//\{"l": {"s": "solid", "c": 0xff0000}, "t": {} ,"r": {} ,"b": {} ,"d": {},"dd": false ,"du": false }
|
|
//"s" values: none, thick, thin, medium, dashDot, dashDotDot, dashed, dotted, double, hair, mediumDashDot, mediumDashDotDot, mediumDashed, slantDashDot
|
|
//
|
|
//"dd" diagonal line, starting at the top left corner of the cell and moving down to the bottom right corner of the cell
|
|
//"du" diagonal line, starting at the bottom left corner of the cell and moving up to the top right corner of the cell
|
|
var borders = this.getBorder(this.bbox.r1, this.bbox.c1).clone();
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
if(!borders.l || borders.l.isEmpty()){
|
|
if(nCol > 1){
|
|
var left = this.getBorder(nRow, nCol - 1);
|
|
if(left.r && !left.r.isEmpty())
|
|
borders.l = left.r;
|
|
}
|
|
}
|
|
if(!borders.t || borders.t.isEmpty()){
|
|
if(nRow > 1){
|
|
var top = this.getBorder(nRow - 1, nCol);
|
|
if(top.b && !top.b.isEmpty())
|
|
borders.t = top.b;
|
|
}
|
|
}
|
|
if(!borders.r || borders.r.isEmpty()){
|
|
var right = this.getBorder(nRow, nCol + 1);
|
|
if(right.l && !right.l.isEmpty())
|
|
borders.r = right.l;
|
|
}
|
|
if(!borders.b || borders.b.isEmpty()){
|
|
var bottom = this.getBorder(nRow + 1, nCol);
|
|
if(bottom.t && !bottom.t.isEmpty())
|
|
borders.b = bottom.t;
|
|
}
|
|
return borders;
|
|
};
|
|
Range.prototype.getAlign=function(){
|
|
//угол от -90 до 90 против часовой стрелки от оси OX
|
|
var t = this;
|
|
var nRow = this.bbox.r1;
|
|
var nCol = this.bbox.c1;
|
|
var align = g_oDefaultFormat.Align;
|
|
this.worksheet._getCellNoEmpty(nRow, nCol, function(cell) {
|
|
var xfs = cell ? cell.getCompiledStyle() : t.worksheet.getCompiledStyle(nRow, nCol);
|
|
if (xfs) {
|
|
align = xfs.align || g_oDefaultFormat.AlignAbs;
|
|
}
|
|
});
|
|
return align;
|
|
};
|
|
Range.prototype.hasMerged=function(){
|
|
var res = this.worksheet.mergeManager.getAny(this.bbox);
|
|
return res ? res.bbox : null;
|
|
};
|
|
Range.prototype.mergeOpen=function(){
|
|
this.worksheet.mergeManager.add(this.bbox, 1);
|
|
};
|
|
Range.prototype.merge=function(type){
|
|
const t = this;
|
|
if(null == type)
|
|
type = Asc.c_oAscMergeOptions.Merge;
|
|
var oBBox = this.bbox;
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
if(oBBox.r1 == oBBox.r2 && oBBox.c1 == oBBox.c2){
|
|
if(type == Asc.c_oAscMergeOptions.MergeCenter)
|
|
this.setAlignHorizontal(AscCommon.align_Center);
|
|
AscCommon.History.EndTransaction();
|
|
return;
|
|
}
|
|
if(this.hasMerged())
|
|
{
|
|
this.unmerge();
|
|
if(type == Asc.c_oAscMergeOptions.MergeCenter)
|
|
{
|
|
//сбрасываем AlignHorizontal
|
|
this.setAlignHorizontal(null);
|
|
AscCommon.History.EndTransaction();
|
|
return;
|
|
}
|
|
}
|
|
|
|
//пробегаемся по границе диапазона, чтобы посмотреть какие границы нужно оставлять
|
|
var oLeftBorder = null;
|
|
var oTopBorder = null;
|
|
var oRightBorder = null;
|
|
var oBottomBorder = null;
|
|
var nRangeType = this._getRangeType(oBBox);
|
|
if(c_oRangeType.Range == nRangeType)
|
|
{
|
|
var oThis = this;
|
|
var fGetBorder = function(bRow, v1, v2, v3, type)
|
|
{
|
|
var oRes = null;
|
|
for(var i = v1; i <= v2; ++i)
|
|
{
|
|
var bNeedDelete = true;
|
|
oThis.worksheet._getCellNoEmpty(bRow ? v3 : i, bRow ? i : v3, function(cell) {
|
|
if(null != cell && null != cell.xfs && null != cell.xfs.border)
|
|
{
|
|
var border = cell.xfs.border;
|
|
var oBorderProp;
|
|
switch(type)
|
|
{
|
|
case 1: oBorderProp = border.l;break;
|
|
case 2: oBorderProp = border.t;break;
|
|
case 3: oBorderProp = border.r;break;
|
|
case 4: oBorderProp = border.b;break;
|
|
}
|
|
if(oBorderProp && !oBorderProp.isEmpty())
|
|
{
|
|
if(null == oRes)
|
|
{
|
|
oRes = oBorderProp;
|
|
bNeedDelete = false;
|
|
}
|
|
else if(true == oRes.isEqual(oBorderProp))
|
|
bNeedDelete = false;
|
|
}
|
|
}
|
|
});
|
|
if(bNeedDelete)
|
|
{
|
|
oRes = null;
|
|
break;
|
|
}
|
|
}
|
|
return oRes;
|
|
};
|
|
oLeftBorder = fGetBorder(false, oBBox.r1, oBBox.r2, oBBox.c1, 1);
|
|
oTopBorder = fGetBorder(true, oBBox.c1, oBBox.c2, oBBox.r1, 2);
|
|
oRightBorder = fGetBorder(false, oBBox.r1, oBBox.r2, oBBox.c2, 3);
|
|
oBottomBorder = fGetBorder(true, oBBox.c1, oBBox.c2, oBBox.r2, 4);
|
|
}
|
|
else if(c_oRangeType.Row == nRangeType)
|
|
{
|
|
this.worksheet._getRowNoEmpty(oBBox.r1, function(row){
|
|
if(row && null != row.xfs && null != row.xfs.border && row.xfs.border.t && !row.xfs.border.t.isEmpty())
|
|
oTopBorder = row.xfs.border.t;
|
|
});
|
|
this.worksheet._getRowNoEmpty(oBBox.r2, function(row){
|
|
if(row && null != row.xfs && null != row.xfs.border && row.xfs.border.b && !row.xfs.border.b.isEmpty())
|
|
oBottomBorder = row.xfs.border.b;
|
|
});
|
|
}
|
|
else
|
|
{
|
|
var oLeftCol = this.worksheet._getColNoEmptyWithAll(oBBox.c1);
|
|
if(null != oLeftCol && null != oLeftCol.xfs && null != oLeftCol.xfs.border && oLeftCol.xfs.border.l && !oLeftCol.xfs.border.l.isEmpty())
|
|
oLeftBorder = oLeftCol.xfs.border.l;
|
|
var oRightCol = this.worksheet._getColNoEmptyWithAll(oBBox.c2);
|
|
if(null != oRightCol && null != oRightCol.xfs && null != oRightCol.xfs.border && oRightCol.xfs.border.r && !oRightCol.xfs.border.r.isEmpty())
|
|
oRightBorder = oRightCol.xfs.border.r;
|
|
}
|
|
|
|
var bFirst = true;
|
|
var oLeftTopCellStyle = null;
|
|
var oFirstCellStyle = null;
|
|
var oFirstCellValue = null;
|
|
var oFirstCellRow = null;
|
|
var oFirstCellCol = null;
|
|
var oFirstCellHyperlink = null;
|
|
|
|
let error = false;
|
|
let firstMergeCellIndex;
|
|
|
|
this._setPropertyNoEmpty(null, null,
|
|
function(cell, nRow0, nCol0, nRowStart, nColStart) {
|
|
if (!error) {
|
|
let formulaRef = cell.formulaParsed && cell.formulaParsed.getArrayFormulaRef();
|
|
|
|
if (bFirst && false == cell.isNullText()) {
|
|
if (formulaRef && !formulaRef.isOneCell()) {
|
|
/* if an array larger than 1x1 cell is encountered, then no value is written in ms */
|
|
bFirst = false;
|
|
oFirstCellValue = null;
|
|
} else {
|
|
bFirst = false;
|
|
oFirstCellStyle = cell.getStyle();
|
|
oFirstCellValue = cell.getValueData();
|
|
oFirstCellRow = cell.nRow;
|
|
oFirstCellCol = cell.nCol;
|
|
|
|
/* we write down the coordinates of the first cell with data, that we will skip when clearing dependencies */
|
|
firstMergeCellIndex = AscCommonExcel.getCellIndex(oFirstCellRow, oFirstCellCol);
|
|
}
|
|
}
|
|
|
|
/* checking whether the ref is included in the selected merge area (if not, then we return an error) */
|
|
if (formulaRef && !t.bbox.containsRange(formulaRef)) {
|
|
error = c_oAscError.ID.CannotChangeFormulaArray;
|
|
return false;
|
|
} else if (nRow0 == nRowStart && nCol0 == nColStart) {
|
|
if (formulaRef && !formulaRef.isOneCell()) {
|
|
error = c_oAscError.ID.CannotChangeFormulaArray;
|
|
return false;
|
|
} else {
|
|
oLeftTopCellStyle = cell.getStyle();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (error) {
|
|
/* Complete the transaction in history before exiting the function merge */
|
|
AscCommon.History.EndTransaction();
|
|
return {errorType: error};
|
|
}
|
|
|
|
this.worksheet.workbook.handlers.trigger(
|
|
"changeDocument",
|
|
AscCommonExcel.docChangedType.mergeRange,
|
|
true, /* arg1 */
|
|
this.bbox, /* arg2 */
|
|
this.worksheet.getId(),
|
|
firstMergeCellIndex
|
|
);
|
|
//правила работы с гиперссылками во время merge(отличются от Excel в случаем областей, например hyperlink: C3:D3 мержим C2:C3)
|
|
// 1)оставляем все ссылки, которые не полностью лежат в merge области
|
|
// 2)оставляем многоклеточные ссылки, top граница которых совпадает с top границей merge области, а высота merge > 1 или совпадает с высотой области merge
|
|
// 3)оставляем и переносим в первую ячейку одну одноклеточную ссылку, если она находится в первой ячейке с данными
|
|
var aHyperlinks = this.worksheet.hyperlinkManager.get(oBBox);
|
|
var aHyperlinksToRestore = [];
|
|
for(var i = 0, length = aHyperlinks.inner.length; i < length; i++)
|
|
{
|
|
var elem = aHyperlinks.inner[i];
|
|
if(oFirstCellRow == elem.bbox.r1 && oFirstCellCol == elem.bbox.c1 && elem.bbox.r1 == elem.bbox.r2 && elem.bbox.c1 == elem.bbox.c2)
|
|
{
|
|
var oNewHyperlink = elem.data.clone();
|
|
oNewHyperlink.Ref.setOffset(new AscCommon.CellBase(oBBox.r1 - oFirstCellRow, oBBox.c1 - oFirstCellCol));
|
|
aHyperlinksToRestore.push(oNewHyperlink);
|
|
}
|
|
else if( oBBox.r1 == elem.bbox.r1 && (elem.bbox.r1 != elem.bbox.r2 || (elem.bbox.c1 != elem.bbox.c2 && oBBox.r1 == oBBox.r2)))
|
|
aHyperlinksToRestore.push(elem.data);
|
|
}
|
|
this.cleanAll();
|
|
//восстанавливаем hyperlink
|
|
for(var i = 0, length = aHyperlinksToRestore.length; i < length; i++)
|
|
{
|
|
var elem = aHyperlinksToRestore[i];
|
|
this.worksheet.hyperlinkManager.add(elem.Ref.getBBox0(), elem);
|
|
}
|
|
var oTargetStyle = null;
|
|
if(null != oFirstCellValue && null != oFirstCellRow && null != oFirstCellCol)
|
|
{
|
|
if(null != oFirstCellStyle)
|
|
oTargetStyle = oFirstCellStyle.clone();
|
|
this.worksheet._getCell(oBBox.r1, oBBox.c1, function(cell){
|
|
cell.setValueData(oFirstCellValue);
|
|
});
|
|
if(null != oFirstCellHyperlink)
|
|
{
|
|
var oLeftTopRange = this.worksheet.getCell3(oBBox.r1, oBBox.c1);
|
|
oLeftTopRange.setHyperlink(oFirstCellHyperlink, true);
|
|
}
|
|
}
|
|
else if(null != oLeftTopCellStyle)
|
|
oTargetStyle = oLeftTopCellStyle.clone();
|
|
|
|
//убираем бордеры
|
|
if(null != oTargetStyle)
|
|
{
|
|
if(null != oTargetStyle.border)
|
|
oTargetStyle.border = null;
|
|
}
|
|
else if(null != oLeftBorder || null != oTopBorder || null != oRightBorder || null != oBottomBorder)
|
|
oTargetStyle = new AscCommonExcel.CellXfs();
|
|
var fSetProperty = this._setProperty;
|
|
var nRangeType = this._getRangeType();
|
|
if(c_oRangeType.All == nRangeType)
|
|
{
|
|
fSetProperty = this._setPropertyNoEmpty;
|
|
oTargetStyle = null
|
|
}
|
|
fSetProperty.call(this, function(row){
|
|
if(null == oTargetStyle)
|
|
row.setStyle(null);
|
|
else
|
|
{
|
|
var oNewStyle = oTargetStyle.clone();
|
|
if(row.index == oBBox.r1 && null != oTopBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
oNewStyle.border.t = oTopBorder.clone();
|
|
if(row.index == oBBox.r2 && null != oBottomBorder) {
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
}
|
|
}
|
|
else if(row.index == oBBox.r2 && null != oBottomBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
}
|
|
row.setStyle(oNewStyle);
|
|
}
|
|
},function(col){
|
|
if(null == oTargetStyle)
|
|
col.setStyle(null);
|
|
else
|
|
{
|
|
var oNewStyle = oTargetStyle.clone();
|
|
if(col.index == oBBox.c1 && null != oLeftBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
oNewStyle.border.l = oLeftBorder.clone();
|
|
if(col.index == oBBox.c2 && null != oRightBorder) {
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
}
|
|
}
|
|
else if(col.index == oBBox.c2 && null != oRightBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
}
|
|
col.setStyle(oNewStyle);
|
|
}
|
|
},
|
|
function(cell, nRow, nCol, nRowStart, nColStart){
|
|
//важно установить именно здесь, чтобы ячейка не удалилась после применения стилей.
|
|
if(null == oTargetStyle)
|
|
cell.setStyle(null);
|
|
else
|
|
{
|
|
var oNewStyle = oTargetStyle.clone();
|
|
if(oBBox.r1 == nRow && oBBox.c1 == nCol)
|
|
{
|
|
if(null != oLeftBorder || null != oTopBorder || (oBBox.r1 == oBBox.r2 && null != oBottomBorder) || (oBBox.c1 == oBBox.c2 && null != oRightBorder))
|
|
{
|
|
oNewStyle.border = new Border();
|
|
if(null != oLeftBorder)
|
|
oNewStyle.border.l = oLeftBorder.clone();
|
|
if(null != oTopBorder)
|
|
oNewStyle.border.t = oTopBorder.clone();
|
|
if(oBBox.r1 == oBBox.r2 && null != oBottomBorder)
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
if(oBBox.c1 == oBBox.c2 && null != oRightBorder)
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.r1 == nRow && oBBox.c2 == nCol)
|
|
{
|
|
if(null != oRightBorder || null != oTopBorder || (oBBox.r1 == oBBox.r2 && null != oBottomBorder))
|
|
{
|
|
oNewStyle.border = new Border();
|
|
if(null != oRightBorder)
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
if(null != oTopBorder)
|
|
oNewStyle.border.t = oTopBorder.clone();
|
|
if(oBBox.r1 == oBBox.r2 && null != oBottomBorder)
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.r2 == nRow && oBBox.c1 == nCol)
|
|
{
|
|
if(null != oLeftBorder || null != oBottomBorder || (oBBox.c1 == oBBox.c2 && null != oRightBorder))
|
|
{
|
|
oNewStyle.border = new Border();
|
|
if(null != oLeftBorder)
|
|
oNewStyle.border.l = oLeftBorder.clone();
|
|
if(null != oBottomBorder)
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
if(oBBox.c1 == oBBox.c2 && null != oRightBorder)
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.r2 == nRow && oBBox.c2 == nCol)
|
|
{
|
|
if(null != oRightBorder || null != oBottomBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
if(null != oRightBorder)
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
if(null != oBottomBorder)
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.r1 == nRow)
|
|
{
|
|
if(null != oTopBorder || (oBBox.r1 == oBBox.r2 && null != oBottomBorder))
|
|
{
|
|
oNewStyle.border = new Border();
|
|
if(null != oTopBorder)
|
|
oNewStyle.border.t = oTopBorder.clone();
|
|
if(oBBox.r1 == oBBox.r2 && null != oBottomBorder)
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.r2 == nRow)
|
|
{
|
|
if(null != oBottomBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
oNewStyle.border.b = oBottomBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.c1 == nCol)
|
|
{
|
|
if(null != oLeftBorder || (oBBox.c1 == oBBox.c2 && null != oRightBorder))
|
|
{
|
|
oNewStyle.border = new Border();
|
|
if(null != oLeftBorder)
|
|
oNewStyle.border.l = oLeftBorder.clone();
|
|
if(oBBox.c1 == oBBox.c2 && null != oRightBorder)
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
}
|
|
}
|
|
else if(oBBox.c2 == nCol)
|
|
{
|
|
if(null != oRightBorder)
|
|
{
|
|
oNewStyle.border = new Border();
|
|
oNewStyle.border.r = oRightBorder.clone();
|
|
}
|
|
}
|
|
cell.setStyle(oNewStyle);
|
|
}
|
|
});
|
|
if(type == Asc.c_oAscMergeOptions.MergeCenter)
|
|
this.setAlignHorizontal(AscCommon.align_Center);
|
|
if(false == this.worksheet.workbook.bUndoChanges && false == this.worksheet.workbook.bRedoChanges)
|
|
this.worksheet.mergeManager.add(this.bbox, 1);
|
|
|
|
//сбрасываем dataValidation кроме 1 ячейки
|
|
var dataValidationRanges = Asc.Range(this.bbox.c1, this.bbox.r1, this.bbox.c1, this.bbox.r1).difference(this.bbox);
|
|
if (dataValidationRanges) {
|
|
this.worksheet.clearDataValidation(dataValidationRanges, true);
|
|
}
|
|
this.worksheet.workbook.handlers.trigger(
|
|
"changeDocument",
|
|
AscCommonExcel.docChangedType.mergeRange,
|
|
null, /* arg1 */
|
|
this.bbox, /* arg2 */
|
|
this.worksheet.getId(),
|
|
firstMergeCellIndex
|
|
);
|
|
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.unmerge=function(bOnlyInRange){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
if(false == this.worksheet.workbook.bUndoChanges && false == this.worksheet.workbook.bRedoChanges)
|
|
this.worksheet.mergeManager.remove(this.bbox);
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype._getHyperlinks=function(){
|
|
var nRangeType = this._getRangeType();
|
|
var result = [];
|
|
var oThis = this;
|
|
if(c_oRangeType.Range == nRangeType)
|
|
{
|
|
var oTempRows = {};
|
|
var fAddToTempRows = function(oTempRows, bbox, data){
|
|
if(null != bbox)
|
|
{
|
|
for(var i = bbox.r1; i <= bbox.r2; i++)
|
|
{
|
|
var row = oTempRows[i];
|
|
if(null == row)
|
|
{
|
|
row = {};
|
|
oTempRows[i] = row;
|
|
}
|
|
for(var j = bbox.c1; j <= bbox.c2; j++)
|
|
{
|
|
var cell = row[j];
|
|
if(null == cell)
|
|
row[j] = data;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
//todo возможно надо сделать оптимизацию для скрытых строк
|
|
var aHyperlinks = this.worksheet.hyperlinkManager.get(this.bbox);
|
|
for(var i = 0, length = aHyperlinks.all.length; i < length; i++)
|
|
{
|
|
var hyp = aHyperlinks.all[i];
|
|
var hypBBox = hyp.bbox.intersectionSimple(this.bbox);
|
|
fAddToTempRows(oTempRows, hypBBox, hyp.data);
|
|
//расширяем гиперссылки на merge ячейках
|
|
var aMerged = this.worksheet.mergeManager.get(hyp.bbox);
|
|
for(var j = 0, length2 = aMerged.all.length; j < length2; j++)
|
|
{
|
|
var merge = aMerged.all[j];
|
|
var mergeBBox = merge.bbox.intersectionSimple(this.bbox);
|
|
fAddToTempRows(oTempRows, mergeBBox, hyp.data);
|
|
}
|
|
}
|
|
//формируем результат
|
|
for(var i in oTempRows)
|
|
{
|
|
var nRowIndex = i - 0;
|
|
var row = oTempRows[i];
|
|
for(var j in row)
|
|
{
|
|
var nColIndex = j - 0;
|
|
var oCurHyp = row[j];
|
|
result.push({hyperlink: oCurHyp, col: nColIndex, row: nRowIndex});
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
Range.prototype.getHyperlink=function(){
|
|
var aHyperlinks = this._getHyperlinks();
|
|
if(null != aHyperlinks && aHyperlinks.length > 0)
|
|
return aHyperlinks[0].hyperlink;
|
|
return null;
|
|
};
|
|
Range.prototype.getHyperlinks=function(){
|
|
return this._getHyperlinks();
|
|
};
|
|
Range.prototype.setHyperlinkOpen=function(val){
|
|
if(null != val && false == val.isValid())
|
|
return;
|
|
this.worksheet.hyperlinkManager.add(val.Ref.getBBox0(), val);
|
|
};
|
|
Range.prototype.setHyperlink=function(val, bWithoutStyle){
|
|
if(null != val && false == val.isValid())
|
|
return;
|
|
|
|
//проверяем, может эта ссылка уже существует
|
|
var i, length, hyp;
|
|
var bExist = false;
|
|
var aHyperlinks = this.worksheet.hyperlinkManager.get(this.bbox);
|
|
for(i = 0, length = aHyperlinks.all.length; i < length; i++)
|
|
{
|
|
hyp = aHyperlinks.all[i];
|
|
if(hyp.data.isEqual(val))
|
|
{
|
|
bExist = true;
|
|
break;
|
|
}
|
|
}
|
|
if(false == bExist)
|
|
{
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
if(false == this.worksheet.workbook.bUndoChanges && false == this.worksheet.workbook.bRedoChanges)
|
|
{
|
|
//удаляем ссылки с тем же адресом
|
|
for(i = 0, length = aHyperlinks.all.length; i < length; i++)
|
|
{
|
|
hyp = aHyperlinks.all[i];
|
|
if(hyp.bbox.isEqual(this.bbox))
|
|
this.worksheet.hyperlinkManager.removeElement(hyp);
|
|
}
|
|
}
|
|
//todo перейти на CellStyle
|
|
if(true != bWithoutStyle)
|
|
{
|
|
var oHyperlinkFont = new AscCommonExcel.Font();
|
|
oHyperlinkFont.setName(this.worksheet.workbook.getDefaultFont());
|
|
oHyperlinkFont.setSize(this.worksheet.workbook.getDefaultSize());
|
|
oHyperlinkFont.setUnderline(Asc.EUnderline.underlineSingle);
|
|
oHyperlinkFont.setColor(AscCommonExcel.g_oColorManager.getThemeColor(AscCommonExcel.g_nColorHyperlink));
|
|
this.setFont(oHyperlinkFont);
|
|
}
|
|
if(false == this.worksheet.workbook.bUndoChanges && false == this.worksheet.workbook.bRedoChanges)
|
|
this.worksheet.hyperlinkManager.add(val.Ref.getBBox0(), val);
|
|
AscCommon.History.EndTransaction();
|
|
}
|
|
};
|
|
Range.prototype.removeHyperlink = function (elem, removeStyle) {
|
|
var bbox = this.bbox;
|
|
if(false == this.worksheet.workbook.bUndoChanges && false == this.worksheet.workbook.bRedoChanges)
|
|
{
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
var oChangeParam = { removeStyle: removeStyle };
|
|
if(elem)
|
|
this.worksheet.hyperlinkManager.removeElement(elem, oChangeParam);
|
|
else
|
|
this.worksheet.hyperlinkManager.remove(bbox, !bbox.isOneCell(), oChangeParam);
|
|
AscCommon.History.EndTransaction();
|
|
}
|
|
};
|
|
Range.prototype.deleteCellsShiftUp=function(preDeleteAction){
|
|
return this._shiftUpDown(true, preDeleteAction);
|
|
};
|
|
Range.prototype.addCellsShiftBottom=function(displayNameFormatTable){
|
|
return this._shiftUpDown(false, null, displayNameFormatTable);
|
|
};
|
|
Range.prototype.addCellsShiftRight=function(displayNameFormatTable){
|
|
return this._shiftLeftRight(false, null,displayNameFormatTable);
|
|
};
|
|
Range.prototype.deleteCellsShiftLeft=function(preDeleteAction){
|
|
return this._shiftLeftRight(true, preDeleteAction);
|
|
};
|
|
Range.prototype._canShiftLeftRight=function(bLeft){
|
|
var aColsToDelete = [], aCellsToDelete = [];
|
|
var oBBox = this.bbox;
|
|
var nRangeType = this._getRangeType(oBBox);
|
|
if(c_oRangeType.Range != nRangeType && c_oRangeType.Col != nRangeType)
|
|
return null;
|
|
|
|
var nWidth = oBBox.c2 - oBBox.c1 + 1;
|
|
if(!bLeft && !this.worksheet.workbook.bUndoChanges && !this.worksheet.workbook.bRedoChanges){
|
|
var rangeEdge = this.worksheet.getRange3(oBBox.r1, gc_nMaxCol0 - nWidth + 1, oBBox.r2, gc_nMaxCol0);
|
|
var aMerged = this.worksheet.mergeManager.get(rangeEdge.bbox);
|
|
if(aMerged.all.length > 0)
|
|
return null;
|
|
var aHyperlink = this.worksheet.hyperlinkManager.get(rangeEdge.bbox);
|
|
if(aHyperlink.all.length > 0)
|
|
return null;
|
|
|
|
var bError = rangeEdge._setPropertyNoEmpty(null, function(col){
|
|
if(null != col){
|
|
if(null != col && null != col.xfs && null != col.xfs.fill && col.xfs.fill.notEmpty())
|
|
return true;
|
|
aColsToDelete.push(col);
|
|
}
|
|
}, function(cell){
|
|
if(null != cell){
|
|
if(null != cell.xfs && null != cell.xfs.fill && cell.xfs.fill.notEmpty())
|
|
return true;
|
|
if(!cell.isNullText())
|
|
return true;
|
|
aCellsToDelete.push(cell.nRow, cell.nCol);
|
|
}
|
|
});
|
|
if(bError)
|
|
return null;
|
|
}
|
|
return {aColsToDelete: aColsToDelete, aCellsToDelete: aCellsToDelete};
|
|
};
|
|
Range.prototype._shiftLeftRight=function(bLeft, preDeleteAction, displayNameFormatTable){
|
|
var canShiftRes = this._canShiftLeftRight(bLeft);
|
|
if(null === canShiftRes)
|
|
return false;
|
|
|
|
if (preDeleteAction)
|
|
preDeleteAction();
|
|
|
|
//удаляем крайние колонки и ячейки
|
|
var i, length, colIndex;
|
|
for(i = 0, length = canShiftRes.aColsToDelete.length; i < length; ++i){
|
|
colIndex = canShiftRes.aColsToDelete[i].index;
|
|
this.worksheet._removeCols(colIndex, colIndex);
|
|
}
|
|
for(i = 0; i < canShiftRes.aCellsToDelete.length; i+=2)
|
|
this.worksheet._removeCell(canShiftRes.aCellsToDelete[i], canShiftRes.aCellsToDelete[i + 1]);
|
|
|
|
var oBBox = this.bbox;
|
|
var nWidth = oBBox.c2 - oBBox.c1 + 1;
|
|
var nRangeType = this._getRangeType(oBBox);
|
|
var mergeManager = this.worksheet.mergeManager;
|
|
this.worksheet.workbook.dependencyFormulas.lockRecal();
|
|
//todo вставить предупреждение, что будет unmerge
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
var oShiftGet = null;
|
|
if (false == this.worksheet.workbook.bUndoChanges && (false == this.worksheet.workbook.bRedoChanges || this.worksheet.workbook.bCollaborativeChanges))
|
|
{
|
|
AscCommon.History.LocalChange = true;
|
|
oShiftGet = mergeManager.shiftGet(this.bbox, true);
|
|
var aMerged = oShiftGet.elems;
|
|
if(null != aMerged.outer && aMerged.outer.length > 0)
|
|
{
|
|
var bChanged = false;
|
|
for(i = 0, length = aMerged.outer.length; i < length; i++)
|
|
{
|
|
var elem = aMerged.outer[i];
|
|
if(!(elem.bbox.c1 < oShiftGet.bbox.c1 && oShiftGet.bbox.r1 <= elem.bbox.r1 && elem.bbox.r2 <= oShiftGet.bbox.r2))
|
|
{
|
|
mergeManager.removeElement(elem);
|
|
bChanged = true;
|
|
}
|
|
}
|
|
if(bChanged)
|
|
oShiftGet = null;
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
//сдвигаем ячейки
|
|
if(bLeft)
|
|
{
|
|
if(c_oRangeType.Range == nRangeType)
|
|
this.worksheet._shiftCellsLeft(oBBox);
|
|
else
|
|
this.worksheet._removeCols(oBBox.c1, oBBox.c2);
|
|
}
|
|
else
|
|
{
|
|
if(c_oRangeType.Range == nRangeType)
|
|
this.worksheet._shiftCellsRight(oBBox, displayNameFormatTable);
|
|
else
|
|
this.worksheet._insertColsBefore(oBBox.c1, nWidth);
|
|
}
|
|
if (false == this.worksheet.workbook.bUndoChanges && (false == this.worksheet.workbook.bRedoChanges || this.worksheet.workbook.bCollaborativeChanges))
|
|
{
|
|
AscCommon.History.LocalChange = true;
|
|
mergeManager.shift(this.bbox, !bLeft, true, oShiftGet);
|
|
this.worksheet.hyperlinkManager.shift(this.bbox, !bLeft, true);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
AscCommon.History.EndTransaction();
|
|
this.worksheet.workbook.dependencyFormulas.unlockRecal();
|
|
return true;
|
|
};
|
|
Range.prototype._canShiftUpDown=function(bUp){
|
|
var aRowsToDelete = [], aCellsToDelete = [];
|
|
var oBBox = this.bbox;
|
|
var nRangeType = this._getRangeType(oBBox);
|
|
if(c_oRangeType.Range != nRangeType && c_oRangeType.Row != nRangeType)
|
|
return null;
|
|
|
|
var nHeight = oBBox.r2 - oBBox.r1 + 1;
|
|
if(!bUp && !this.worksheet.workbook.bUndoChanges && !this.worksheet.workbook.bRedoChanges){
|
|
var rangeEdge = this.worksheet.getRange3(gc_nMaxRow0 - nHeight + 1, oBBox.c1, gc_nMaxRow0, oBBox.c2);
|
|
var aMerged = this.worksheet.mergeManager.get(rangeEdge.bbox);
|
|
if(aMerged.all.length > 0)
|
|
return null;
|
|
var aHyperlink = this.worksheet.hyperlinkManager.get(rangeEdge.bbox);
|
|
if(aHyperlink.all.length > 0)
|
|
return null;
|
|
|
|
var bError = rangeEdge._setPropertyNoEmpty(function(row){
|
|
if(null != row){
|
|
if(null != row.xfs && null != row.xfs.fill && row.xfs.fill.notEmpty())
|
|
return true;
|
|
aRowsToDelete.push(row.index);
|
|
}
|
|
}, null, function(cell){
|
|
if(null != cell){
|
|
if(null != cell.xfs && null != cell.xfs.fill && cell.xfs.fill.notEmpty())
|
|
return true;
|
|
if(!cell.isNullText())
|
|
return true;
|
|
aCellsToDelete.push(cell.nRow, cell.nCol);
|
|
}
|
|
});
|
|
if(bError)
|
|
return null;
|
|
}
|
|
return {aRowsToDelete: aRowsToDelete, aCellsToDelete: aCellsToDelete};
|
|
};
|
|
Range.prototype._shiftUpDown = function (bUp, preDeleteAction, displayNameFormatTable) {
|
|
var canShiftRes = this._canShiftUpDown(bUp);
|
|
if(null === canShiftRes)
|
|
return false;
|
|
|
|
if (preDeleteAction)
|
|
preDeleteAction();
|
|
|
|
//удаляем крайние колонки и ячейки
|
|
var i, length, rowIndex;
|
|
for(i = 0, length = canShiftRes.aRowsToDelete.length; i < length; ++i){
|
|
rowIndex = canShiftRes.aRowsToDelete[i];
|
|
this.worksheet._removeRows(rowIndex, rowIndex);
|
|
}
|
|
for(i = 0; i < canShiftRes.aCellsToDelete.length; i+=2)
|
|
this.worksheet._removeCell(canShiftRes.aCellsToDelete[i], canShiftRes.aCellsToDelete[i + 1]);
|
|
|
|
var oBBox = this.bbox;
|
|
var nHeight = oBBox.r2 - oBBox.r1 + 1;
|
|
var nRangeType = this._getRangeType(oBBox);
|
|
var mergeManager = this.worksheet.mergeManager;
|
|
this.worksheet.workbook.dependencyFormulas.lockRecal();
|
|
//todo вставить предупреждение, что будет unmerge
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
var oShiftGet = null;
|
|
if (false == this.worksheet.workbook.bUndoChanges && (false == this.worksheet.workbook.bRedoChanges || this.worksheet.workbook.bCollaborativeChanges))
|
|
{
|
|
AscCommon.History.LocalChange = true;
|
|
oShiftGet = mergeManager.shiftGet(this.bbox, false);
|
|
var aMerged = oShiftGet.elems;
|
|
if(null != aMerged.outer && aMerged.outer.length > 0)
|
|
{
|
|
var bChanged = false;
|
|
for(i = 0, length = aMerged.outer.length; i < length; i++)
|
|
{
|
|
var elem = aMerged.outer[i];
|
|
if(!(elem.bbox.r1 < oShiftGet.bbox.r1 && oShiftGet.bbox.c1 <= elem.bbox.c1 && elem.bbox.c2 <= oShiftGet.bbox.c2))
|
|
{
|
|
mergeManager.removeElement(elem);
|
|
bChanged = true;
|
|
}
|
|
}
|
|
if(bChanged)
|
|
oShiftGet = null;
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
//сдвигаем ячейки
|
|
if(bUp)
|
|
{
|
|
if(c_oRangeType.Range == nRangeType)
|
|
this.worksheet._shiftCellsUp(oBBox);
|
|
else
|
|
this.worksheet._removeRows(oBBox.r1, oBBox.r2);
|
|
}
|
|
else
|
|
{
|
|
if(c_oRangeType.Range == nRangeType)
|
|
this.worksheet._shiftCellsBottom(oBBox, displayNameFormatTable);
|
|
else
|
|
this.worksheet._insertRowsBefore(oBBox.r1, nHeight);
|
|
}
|
|
if (false == this.worksheet.workbook.bUndoChanges && (false == this.worksheet.workbook.bRedoChanges || this.worksheet.workbook.bCollaborativeChanges))
|
|
{
|
|
AscCommon.History.LocalChange = true;
|
|
mergeManager.shift(this.bbox, !bUp, false, oShiftGet);
|
|
this.worksheet.hyperlinkManager.shift(this.bbox, !bUp, false);
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
AscCommon.History.EndTransaction();
|
|
this.worksheet.workbook.dependencyFormulas.unlockRecal();
|
|
return true;
|
|
};
|
|
Range.prototype.setOffset=function(offset){
|
|
this.bbox.setOffset(offset);
|
|
};
|
|
Range.prototype.setOffsetFirst=function(offset){
|
|
this.bbox.setOffsetFirst(offset);
|
|
};
|
|
Range.prototype.setOffsetLast=function(offset){
|
|
this.bbox.setOffsetLast(offset);
|
|
};
|
|
Range.prototype.setOffsetWithAbs = function() {
|
|
this.bbox.setOffsetWithAbs.apply(this.bbox, arguments);
|
|
};
|
|
Range.prototype.intersect=function(range){
|
|
var oBBox1 = this.bbox;
|
|
var oBBox2 = range.bbox;
|
|
var r1 = Math.max(oBBox1.r1, oBBox2.r1);
|
|
var c1 = Math.max(oBBox1.c1, oBBox2.c1);
|
|
var r2 = Math.min(oBBox1.r2, oBBox2.r2);
|
|
var c2 = Math.min(oBBox1.c2, oBBox2.c2);
|
|
if(r1 <= r2 && c1 <= c2)
|
|
return this.worksheet.getRange3(r1, c1, r2, c2);
|
|
return null;
|
|
};
|
|
Range.prototype.cleanFormat=function(ignoreNoEmpty){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
this.unmerge();
|
|
|
|
let fSetProperty = ignoreNoEmpty ? this._setProperty : this._setPropertyNoEmpty;
|
|
fSetProperty.call(this, function(row){
|
|
row.setStyle(null);
|
|
// if(row.isEmpty())
|
|
// row.Remove();
|
|
},function(col){
|
|
col.setStyle(null);
|
|
// if(col.isEmpty())
|
|
// col.Remove();
|
|
},function(cell, nRow0, nCol0, nRowStart, nColStart){
|
|
cell.setStyle(null);
|
|
// if(cell.isEmpty())
|
|
// cell.Remove();
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.cleanText = function () {
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
this._setPropertyNoEmpty(null, null,
|
|
function (cell, nRow0, nCol0, nRowStart, nColStart) {
|
|
cell.setValue("");
|
|
// if(cell.isEmpty())
|
|
// cell.Remove();
|
|
});
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.cleanTextExceptFirst = function () {
|
|
History.Create_NewPoint();
|
|
History.StartTransaction();
|
|
this._setPropertyNoEmpty(null, null,
|
|
function (cell, nRow0, nCol0, nRowStart, nColStart) {
|
|
if (!(cell.nRow === nRowStart && cell.nCol === nColStart)) {
|
|
cell.setValue("");
|
|
}
|
|
});
|
|
History.EndTransaction();
|
|
};
|
|
Range.prototype.cleanAll=function(ignoreNoEmpty){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
this.unmerge();
|
|
//удаляем только гиперссылки, которые полностью лежат в области
|
|
var aHyperlinks = this.worksheet.hyperlinkManager.get(this.bbox);
|
|
for(var i = 0, length = aHyperlinks.inner.length; i < length; ++i)
|
|
this.removeHyperlink(aHyperlinks.inner[i]);
|
|
var oThis = this;
|
|
let fSetProperty = ignoreNoEmpty ? this._setProperty : this._setPropertyNoEmpty;
|
|
fSetProperty.call(this, function(row){
|
|
row.setStyle(null);
|
|
// if(row.isEmpty())
|
|
// row.Remove();
|
|
},function(col){
|
|
col.setStyle(null);
|
|
// if(col.isEmpty())
|
|
// col.Remove();
|
|
},function(cell, nRow0, nCol0, nRowStart, nColStart){
|
|
oThis.worksheet._removeCell(nRow0, nCol0, cell, ignoreNoEmpty);
|
|
});
|
|
|
|
this.worksheet.workbook.dependencyFormulas.calcTree();
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.cleanHyperlinks=function(){
|
|
AscCommon.History.Create_NewPoint();
|
|
AscCommon.History.StartTransaction();
|
|
//удаляем только гиперссылки, которые полностью лежат в области
|
|
var aHyperlinks = this.worksheet.hyperlinkManager.get(this.bbox);
|
|
for(var i = 0, length = aHyperlinks.inner.length; i < length; ++i)
|
|
this.removeHyperlink(aHyperlinks.inner[i]);
|
|
AscCommon.History.EndTransaction();
|
|
};
|
|
Range.prototype.sort = function (nOption, nStartRowCol, sortColor, opt_guessHeader, opt_by_row, opt_custom_sort) {
|
|
var bbox = this.bbox;
|
|
if (opt_guessHeader) {
|
|
//если тип ячеек первого и второго row попарно совпадает, то считаем первую строку заголовком
|
|
//todo рассмотреть замерженые ячейки. стили тоже влияют, но непонятно как сравнивать border
|
|
var bIgnoreFirstRow = ignoreFirstRowSort(this.worksheet, bbox);
|
|
|
|
if (bIgnoreFirstRow) {
|
|
bbox = bbox.clone();
|
|
bbox.r1++;
|
|
}
|
|
}
|
|
|
|
//todo горизонтальная сортировка
|
|
var aMerged = this.worksheet.mergeManager.get(bbox);
|
|
if (aMerged.outer.length > 0 || (aMerged.inner.length > 0 && null == _isSameSizeMerged(bbox, aMerged.inner, true))) {
|
|
return null;
|
|
}
|
|
|
|
var nMergedWidth = 1;
|
|
var nMergedHeight = 1;
|
|
if (aMerged.inner.length > 0) {
|
|
var merged = aMerged.inner[0];
|
|
if (opt_by_row) {
|
|
nMergedWidth = merged.bbox.c2 - merged.bbox.c1 + 1;
|
|
//меняем nStartCol, потому что приходит колонка той ячейки, на которой начали выделение
|
|
nStartRowCol = merged.bbox.r1;
|
|
} else {
|
|
nMergedHeight = merged.bbox.r2 - merged.bbox.r1 + 1;
|
|
//меняем nStartCol, потому что приходит колонка той ячейки, на которой начали выделение
|
|
nStartRowCol = merged.bbox.c1;
|
|
}
|
|
|
|
}
|
|
|
|
this.worksheet.workbook.dependencyFormulas.lockRecal();
|
|
|
|
var oRes = null;
|
|
var oThis = this;
|
|
var bAscent = false;
|
|
if (nOption == Asc.c_oAscSortOptions.Ascending) {
|
|
bAscent = true;
|
|
}
|
|
|
|
//get sort elems
|
|
//_getSortElems - for split big function
|
|
var elemObj = this._getSortElems(bbox, nStartRowCol, nOption, sortColor, opt_by_row, opt_custom_sort);
|
|
var aSortElems = elemObj.aSortElems;
|
|
var nColFirst0 = elemObj.nColFirst0;
|
|
var nRowFirst0 = elemObj.nRowFirst0;
|
|
var nLastRow0 = elemObj.nLastRow0;
|
|
var nLastCol0 = elemObj.nLastCol0;
|
|
|
|
|
|
//проверяем что это не пустая операция
|
|
var aSortData = [];
|
|
var nHiddenCount = 0;
|
|
var oFromArray = {};
|
|
|
|
var nNewIndex, oNewElem, i, length;
|
|
var nColMax = 0, nRowMax = 0;
|
|
var nColMin = gc_nMaxCol0, nRowMin = gc_nMaxRow0;
|
|
var nToMax = 0;
|
|
for (i = 0, length = aSortElems.length; i < length; ++i) {
|
|
var item = aSortElems[i];
|
|
if (opt_by_row) {
|
|
nNewIndex = i * nMergedWidth + nColFirst0 + nHiddenCount;
|
|
while (false != oThis.worksheet.getColHidden(nNewIndex)) {
|
|
nHiddenCount++;
|
|
nNewIndex = i * nMergedWidth + nColFirst0 + nHiddenCount;
|
|
}
|
|
oNewElem = new UndoRedoData_FromToRowCol(false, item.col, nNewIndex);
|
|
oFromArray[item.col] = 1;
|
|
if (nColMax < item.col) {
|
|
nColMax = item.col;
|
|
}
|
|
if (nColMax < nNewIndex) {
|
|
nColMax = nNewIndex;
|
|
}
|
|
if (nColMin > item.col) {
|
|
nColMin = item.col;
|
|
}
|
|
if (nColMin > nNewIndex) {
|
|
nColMin = nNewIndex;
|
|
}
|
|
} else {
|
|
nNewIndex = i * nMergedHeight + nRowFirst0 + nHiddenCount;
|
|
while (false != oThis.worksheet.getRowHidden(nNewIndex)) {
|
|
nHiddenCount++;
|
|
nNewIndex = i * nMergedHeight + nRowFirst0 + nHiddenCount;
|
|
}
|
|
oNewElem = new UndoRedoData_FromToRowCol(true, item.row, nNewIndex);
|
|
oFromArray[item.row] = 1;
|
|
if (nRowMax < item.row) {
|
|
nRowMax = item.row;
|
|
}
|
|
if (nRowMax < nNewIndex) {
|
|
nRowMax = nNewIndex;
|
|
}
|
|
if (nRowMin > item.row) {
|
|
nRowMin = item.row;
|
|
}
|
|
if (nRowMin > nNewIndex) {
|
|
nRowMin = nNewIndex;
|
|
}
|
|
}
|
|
if (nToMax < nNewIndex) {
|
|
nToMax = nNewIndex;
|
|
}
|
|
if (oNewElem.from != oNewElem.to) {
|
|
aSortData.push(oNewElem);
|
|
}
|
|
}
|
|
|
|
|
|
if (aSortData.length > 0) {
|
|
//добавляем индексы перехода пустых ячеек(нужно для сортировки комментариев)
|
|
var nRowColMin = opt_by_row ? nColMin : nRowMin;
|
|
var nRowColMax = opt_by_row ? nColMax : nRowMax;
|
|
var hiddenFunc = opt_by_row ? oThis.worksheet.getColHidden : oThis.worksheet.getRowHidden;
|
|
for (i = nRowColMin; i <= nRowColMax; ++i) {
|
|
if (null == oFromArray[i] && false == hiddenFunc.apply(oThis.worksheet, [i])) {
|
|
var nFrom = i;
|
|
var nTo = ++nToMax;
|
|
while (false != hiddenFunc.apply(oThis.worksheet, [nTo]))
|
|
nTo = ++nToMax;
|
|
if (nFrom != nTo) {
|
|
oNewElem = new UndoRedoData_FromToRowCol(false, nFrom, nTo);
|
|
aSortData.push(oNewElem);
|
|
}
|
|
}
|
|
}
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
var oSelection = AscCommon.History.GetSelection();
|
|
if (null != oSelection) {
|
|
oSelection = oSelection.clone();
|
|
oSelection.assign(nColFirst0, nRowFirst0, nLastCol0, nLastRow0);
|
|
AscCommon.History.SetSelection(oSelection);
|
|
AscCommon.History.SetSelectionRedo(oSelection);
|
|
}
|
|
var oUndoRedoBBox = new UndoRedoData_BBox({r1: nRowFirst0, c1: nColFirst0, r2: nLastRow0, c2: nLastCol0});
|
|
oRes = new AscCommonExcel.UndoRedoData_SortData(oUndoRedoBBox, aSortData, opt_by_row);
|
|
this._sortByArray(oUndoRedoBBox, aSortData, null, opt_by_row);
|
|
|
|
var range = opt_by_row ? new Asc.Range(nColFirst0, 0, nLastCol0, gc_nMaxRow0) : new Asc.Range(0, nRowFirst0, gc_nMaxCol0, nLastRow0);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_Sort, this.worksheet.getId(), range, oRes)
|
|
}
|
|
this.worksheet.workbook.dependencyFormulas.unlockRecal();
|
|
return oRes;
|
|
};
|
|
Range.prototype._getSortElems = function (bbox, nStartRowCol, nOption, sortColor, opt_by_row, opt_custom_sort) {
|
|
var oThis = this;
|
|
|
|
var bAscent = false;
|
|
if (nOption == Asc.c_oAscSortOptions.Ascending) {
|
|
bAscent = true;
|
|
}
|
|
|
|
var colorFill = nOption === Asc.c_oAscSortOptions.ByColorFill;
|
|
var colorText = nOption === Asc.c_oAscSortOptions.ByColorFont;
|
|
var isSortColor = colorFill || colorText;
|
|
|
|
var nRowFirst0 = bbox.r1;
|
|
var nRowLast0 = bbox.r2;
|
|
var nColFirst0 = bbox.c1;
|
|
var nColLast0 = bbox.c2;
|
|
|
|
var bWholeCol = false;
|
|
var bWholeRow = false;
|
|
if (0 == nRowFirst0 && gc_nMaxRow0 == nRowLast0) {
|
|
bWholeCol = true;
|
|
}
|
|
if (0 == nColFirst0 && gc_nMaxCol0 == nColLast0) {
|
|
bWholeRow = true;
|
|
}
|
|
|
|
var sortConditions, caseSensitive;
|
|
if(opt_custom_sort && opt_custom_sort.SortConditions) {
|
|
sortConditions = opt_custom_sort.SortConditions;
|
|
nStartRowCol = opt_by_row ? sortConditions[0].Ref.r1 : sortConditions[0].Ref.c1;
|
|
bAscent = !sortConditions[0].ConditionDescending;
|
|
}
|
|
if(opt_custom_sort) {
|
|
//caseSensitive = opt_custom_sort.CaseSensitive;
|
|
//пока игнорируем данный флаг, поскольку сравнения строк в excel при сортировке работает иначе(например - "Green" > "green")
|
|
//возможно, стоит воспользоваться функцией localeCompare - но для этого необходимо проверить грамотное ли сравнение будет
|
|
}
|
|
|
|
var nLastRow0, nLastCol0;
|
|
if (opt_by_row) {
|
|
var oRangeRow = this.worksheet.getRange(new CellAddress(nStartRowCol, nColFirst0, 0), new CellAddress(nStartRowCol, nColLast0, 0));
|
|
nLastRow0 = nRowLast0;
|
|
nLastCol0 = 0;
|
|
if (true == bWholeCol) {
|
|
nLastRow0 = 0;
|
|
this._foreachColNoEmpty(null, function (cell) {
|
|
var nCurRow0 = cell.nRow;
|
|
if (nCurRow0 > nLastRow0) {
|
|
nLastRow0 = nCurRow0;
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
var oRangeCol = this.worksheet.getRange(new CellAddress(nRowFirst0, nStartRowCol, 0), new CellAddress(nRowLast0, nStartRowCol, 0));
|
|
nLastRow0 = 0;
|
|
nLastCol0 = nColLast0;
|
|
if (true == bWholeRow) {
|
|
nLastCol0 = 0;
|
|
this._foreachRowNoEmpty(null, function (cell) {
|
|
var nCurCol0 = cell.nCol;
|
|
if (nCurCol0 > nLastCol0) {
|
|
nLastCol0 = nCurCol0;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
var aMerged = this.worksheet.mergeManager.get(this.bbox);
|
|
var checkMerged = function(_cell) {
|
|
var res = null;
|
|
|
|
if(aMerged && aMerged.inner && aMerged.inner.length > 0) {
|
|
for(var i = 0; i < aMerged.inner.length; i++) {
|
|
if(aMerged.inner[i].bbox.contains(_cell.nCol, _cell.nRow)) {
|
|
if(aMerged.inner[i].bbox.r1 === _cell.nRow && aMerged.inner[i].bbox.c1 === _cell.nCol) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
//собираем массив обьектов для сортировки
|
|
var aSortElems = [];
|
|
var putElem = false;
|
|
var fAddSortElems = function (oCell, nRow0, nCol0) {
|
|
//не сортируем сткрытие строки
|
|
if ((opt_by_row && !oThis.worksheet.getColHidden(nCol0)) || (!opt_by_row && !oThis.worksheet.getRowHidden(nRow0))) {
|
|
if (!opt_by_row && nLastRow0 < nRow0) {
|
|
nLastRow0 = nRow0;
|
|
}
|
|
if (opt_by_row && nLastCol0 < nCol0) {
|
|
nLastCol0 = nCol0;
|
|
}
|
|
var val = oCell.getValueWithoutFormat();
|
|
|
|
if(opt_custom_sort && false === checkMerged(oCell)) {
|
|
return;
|
|
}
|
|
|
|
//for sort color
|
|
var colorFillCell, colorsTextCell = null;
|
|
if (colorFill || opt_custom_sort) {
|
|
var styleCell = oCell.getCompiledStyleCustom(false, true, true);
|
|
colorFillCell = styleCell !== null && styleCell.fill ? styleCell.fill.bg() : null;
|
|
}
|
|
if (colorText || opt_custom_sort) {
|
|
var value2 = oCell.getValue2();
|
|
for (var n = 0; n < value2.length; n++) {
|
|
if (null === colorsTextCell) {
|
|
colorsTextCell = [];
|
|
}
|
|
|
|
colorsTextCell.push(value2[n].format.getColor());
|
|
}
|
|
}
|
|
|
|
var nNumber = null;
|
|
var sText = null;
|
|
var res;
|
|
if ("" != val) {
|
|
var nVal = val - 0;
|
|
if (nVal == val) {
|
|
nNumber = nVal;
|
|
} else {
|
|
sText = val;
|
|
}
|
|
if (opt_by_row) {
|
|
res = {col: nCol0, num: nNumber, text: sText, colorFill: colorFillCell, colorsText: colorsTextCell};
|
|
} else {
|
|
res = {row: nRow0, num: nNumber, text: sText, colorFill: colorFillCell, colorsText: colorsTextCell};
|
|
}
|
|
} else if (isSortColor || (opt_custom_sort && (colorFillCell || colorsTextCell))) {
|
|
if (opt_by_row) {
|
|
res = {col: nCol0, num: nNumber, text: sText, colorFill: colorFillCell, colorsText: colorsTextCell};
|
|
} else {
|
|
res = {row: nRow0, num: nNumber, text: sText, colorFill: colorFillCell, colorsText: colorsTextCell};
|
|
}
|
|
}
|
|
|
|
if(!putElem) {
|
|
return res;
|
|
} else if(res) {
|
|
aSortElems.push(res);
|
|
}
|
|
}
|
|
};
|
|
|
|
putElem = true;
|
|
if (opt_by_row) {
|
|
if (nRowFirst0 == nStartRowCol) {
|
|
while (0 == aSortElems.length && nStartRowCol <= nLastRow0) {
|
|
if (false == bWholeRow) {
|
|
oRangeRow._foreachNoEmptyByCol(fAddSortElems);
|
|
} else {
|
|
oRangeRow._foreachRowNoEmpty(null, fAddSortElems);
|
|
}
|
|
if (0 == aSortElems.length) {
|
|
nStartRowCol++;
|
|
oRangeRow = this.worksheet.getRange(new CellAddress(nStartRowCol, nColFirst0, 0), new CellAddress(nStartRowCol, nColLast0, 0));
|
|
}
|
|
}
|
|
} else {
|
|
if (false == bWholeRow) {
|
|
oRangeRow._foreachNoEmptyByCol(fAddSortElems);
|
|
} else {
|
|
oRangeRow._foreachRowNoEmpty(null, fAddSortElems);
|
|
}
|
|
}
|
|
} else {
|
|
if (nColFirst0 == nStartRowCol) {
|
|
while (0 == aSortElems.length && nStartRowCol <= nLastCol0) {
|
|
if (false == bWholeCol) {
|
|
oRangeCol._foreachNoEmpty(fAddSortElems);
|
|
} else {
|
|
oRangeCol._foreachColNoEmpty(null, fAddSortElems);
|
|
}
|
|
if (0 == aSortElems.length) {
|
|
nStartRowCol++;
|
|
oRangeCol = this.worksheet.getRange(new CellAddress(nRowFirst0, nStartRowCol, 0), new CellAddress(nRowLast0, nStartRowCol, 0));
|
|
}
|
|
}
|
|
} else {
|
|
if (false == bWholeCol) {
|
|
oRangeCol._foreachNoEmpty(fAddSortElems);
|
|
} else {
|
|
oRangeCol._foreachColNoEmpty(null, fAddSortElems);
|
|
}
|
|
}
|
|
}
|
|
//color sort
|
|
var colorFillCmp = function (color1, color2, _customCellColor) {
|
|
var res = false;
|
|
//TODO возможно так сравнивать не правильно, позже пересмотреть
|
|
if (colorFill || _customCellColor === true) {
|
|
res = (color1 !== null && color2 !== null && color1.rgb === color2.rgb) || (color1 === color2);
|
|
} else if ((colorText || _customCellColor === false) && color1 && color1.length) {
|
|
for (var n = 0; n < color1.length; n++) {
|
|
if (color1[n] && color2 !== null && color1[n].rgb === color2.rgb) {
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
var getSortElem = function(row, col) {
|
|
var oCell;
|
|
oThis.worksheet._getCellNoEmpty(row, col, function(cell) {
|
|
oCell = cell;
|
|
});
|
|
return oCell ? fAddSortElems(oCell, row, col) : null;
|
|
};
|
|
|
|
putElem = false;
|
|
if (isSortColor) {
|
|
var newArrayNeedColor = [];
|
|
var newArrayAnotherColor = [];
|
|
|
|
for (var i = 0; i < aSortElems.length; i++) {
|
|
var color = colorFill ? aSortElems[i].colorFill : aSortElems[i].colorsText;
|
|
if (colorFillCmp(color, sortColor)) {
|
|
newArrayNeedColor.push(aSortElems[i]);
|
|
} else {
|
|
newArrayAnotherColor.push(aSortElems[i]);
|
|
}
|
|
}
|
|
|
|
aSortElems = newArrayNeedColor.concat(newArrayAnotherColor);
|
|
} else {
|
|
aSortElems.sort(function (a, b) {
|
|
var res = 0;
|
|
var nullVal = false;
|
|
var compare = function(_a, _b, _sortCondition) {
|
|
//если есть opt_custom_sort(->sortConditions) - тогда может быть несколько условий сортировки
|
|
//в данном случае идём по отдельной ветке и по-другому обрабатываем сортировку по цвету
|
|
//TODO стоит рассмотреть вариант одной обработки для разных вариантов сортировки
|
|
if(_sortCondition && (_sortCondition.ConditionSortBy === Asc.ESortBy.sortbyCellColor || _sortCondition.ConditionSortBy === Asc.ESortBy.sortbyFontColor)) {
|
|
if(!_a || !_b) {
|
|
return res;
|
|
}
|
|
var _isCellColor = _sortCondition.ConditionSortBy === Asc.ESortBy.sortbyCellColor;
|
|
var _color1 = _isCellColor ? _a.colorFill : _a.colorsText;
|
|
var _color2 = _isCellColor ? _b.colorFill : _b.colorsText;
|
|
var _sortColor = _isCellColor ? _sortCondition.dxf.fill.bg() : _sortCondition.dxf.font.getColor();
|
|
var cmp1 = colorFillCmp(_color1, _sortColor, _isCellColor);
|
|
var cmp2 = colorFillCmp(_color2, _sortColor, _isCellColor);
|
|
|
|
if(cmp1 === cmp2) {
|
|
res = 0;
|
|
} else if(cmp1 && !cmp2) {
|
|
res = -1;
|
|
} else if(!cmp1 && cmp2) {
|
|
res = 1;
|
|
}
|
|
} else {
|
|
if (_a && null != _a.text) {
|
|
if (_b && null != _b.text) {
|
|
var val1 = caseSensitive ? _a.text : _a.text.toUpperCase();
|
|
var val2 = caseSensitive ? _b.text : _b.text.toUpperCase();
|
|
res = stringCompare(val1, val2);
|
|
} else if(_b && null != _b.num) {
|
|
res = 1;
|
|
} else {
|
|
res = -1;
|
|
nullVal = true;
|
|
}
|
|
} else if (_a && null != _a.num) {
|
|
if (_b && null != _b.num) {
|
|
res = _a.num - _b.num;
|
|
} else if(_b && null != _b.text) {
|
|
res = -1;
|
|
} else {
|
|
res = -1;
|
|
nullVal = true;
|
|
}
|
|
} else if(_b && (null != _b.num || null != _b.text)){
|
|
res = 1;
|
|
nullVal = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
compare(a, b, sortConditions ? sortConditions[0] : null);
|
|
if (0 == res) {
|
|
if(sortConditions) {
|
|
for(var i = 1; i < sortConditions.length; i++) {
|
|
var row = sortConditions[i].Ref.r1;
|
|
var col = sortConditions[i].Ref.c1;
|
|
var row1 = opt_by_row ? row : a.row;
|
|
var col1 = !opt_by_row ? col : a.col;
|
|
var row2 = opt_by_row ? row : b.row;
|
|
var col2 = !opt_by_row ? col : b.col;
|
|
var tempA = getSortElem(row1, col1);
|
|
var tempB = getSortElem(row2, col2);
|
|
compare(tempA, tempB, sortConditions[i]);
|
|
var tempAscent = !sortConditions[i].ConditionDescending;
|
|
if(res != 0) {
|
|
if(!tempAscent) {
|
|
res = -res;
|
|
}
|
|
break;
|
|
} else if(i === sortConditions.length - 1 && tempA && tempB) {
|
|
res = opt_by_row ? tempA.col - tempB.col : tempA.row - tempB.row;
|
|
}
|
|
}
|
|
} else {
|
|
res = opt_by_row ? a.col - b.col : a.row - b.row;
|
|
}
|
|
} else if (!bAscent && !nullVal) {
|
|
res = -res;
|
|
}
|
|
return res;
|
|
});
|
|
}
|
|
|
|
return {aSortElems: aSortElems, nRowFirst0: nRowFirst0, nColFirst0: nColFirst0, nLastRow0: nLastRow0, nLastCol0: nLastCol0};
|
|
};
|
|
Range.prototype._sortByArray = function (oBBox, aSortData, bUndo, opt_by_row) {
|
|
var t = this;
|
|
var height = oBBox.r2 - oBBox.r1 + 1;
|
|
var oSortedIndexes = {};
|
|
var nFrom, nTo, length, i;
|
|
for (i = 0, length = aSortData.length; i < length; ++i) {
|
|
var item = aSortData[i];
|
|
nFrom = item.from;
|
|
nTo = item.to;
|
|
if (true == this.worksheet.workbook.bUndoChanges) {
|
|
nFrom = item.to;
|
|
nTo = item.from;
|
|
}
|
|
oSortedIndexes[nFrom] = nTo;
|
|
}
|
|
//сортируются только одинарные гиперссылки, все неодинарные оставляем
|
|
var aSortedHyperlinks = [], hyp;
|
|
if (false == this.worksheet.workbook.bUndoChanges && (false == this.worksheet.workbook.bRedoChanges || this.worksheet.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
var aHyperlinks = this.worksheet.hyperlinkManager.get(this.bbox);
|
|
for (i = 0, length = aHyperlinks.inner.length; i < length; i++) {
|
|
var elem = aHyperlinks.inner[i];
|
|
hyp = elem.data;
|
|
if (hyp.Ref.isOneCell()) {
|
|
nFrom = opt_by_row ? elem.bbox.c1 : elem.bbox.r1;
|
|
nTo = oSortedIndexes[nFrom];
|
|
if (null != nTo) {
|
|
//удаляем ссылки, а не перемещаем, чтобы не было конфликтов(например в случае если все ячейки имеют ссылки
|
|
// и их надо передвинуть)
|
|
this.worksheet.hyperlinkManager.removeElement(elem);
|
|
var oNewHyp = hyp.clone();
|
|
if(opt_by_row) {
|
|
oNewHyp.Ref.setOffset(new AscCommon.CellBase(0, nTo - nFrom));
|
|
} else {
|
|
oNewHyp.Ref.setOffset(new AscCommon.CellBase(nTo - nFrom, 0));
|
|
}
|
|
aSortedHyperlinks.push(oNewHyp);
|
|
}
|
|
}
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
|
|
var tempRange = this.worksheet.getRange3(oBBox.r1, oBBox.c1, oBBox.r2, oBBox.c2);
|
|
var func = opt_by_row ? tempRange._foreachNoEmptyByCol : tempRange._foreachNoEmpty;
|
|
func.apply(tempRange, [(function (cell) {
|
|
var ws = t.worksheet;
|
|
var formula = cell.getFormulaParsed();
|
|
if (formula) {
|
|
var cellWithFormula = formula.getParent();
|
|
var nFrom = opt_by_row ? cell.nCol : cell.nRow;
|
|
var nTo = oSortedIndexes[nFrom];
|
|
if (null != nTo) {
|
|
if (!cell.formulaParsed.isParsed) {
|
|
cell.formulaParsed.parse();
|
|
}
|
|
if (opt_by_row) {
|
|
cell.changeOffset(new AscCommon.CellBase(0, nTo - nFrom), true, true, true);
|
|
} else {
|
|
cell.changeOffset(new AscCommon.CellBase(nTo - nFrom, 0), true, true, true);
|
|
}
|
|
formula = cell.getFormulaParsed();
|
|
cellWithFormula = formula.getParent();
|
|
if (opt_by_row) {
|
|
cellWithFormula.nCol = nTo;
|
|
} else {
|
|
cellWithFormula.nRow = nTo;
|
|
}
|
|
}
|
|
ws.workbook.dependencyFormulas.addToChangedCell(cellWithFormula);
|
|
}
|
|
})]);
|
|
|
|
|
|
var tempSheetMemory, nIndexFrom, nIndexTo, j;
|
|
if (opt_by_row) {
|
|
tempSheetMemory = [];
|
|
for (j in oSortedIndexes) {
|
|
nIndexFrom = j - 0;
|
|
nIndexTo = oSortedIndexes[j];
|
|
var sheetMemoryFrom = this.worksheet.getColData(nIndexFrom);
|
|
var sheetMemoryTo = this.worksheet.getColData(nIndexTo);
|
|
|
|
tempSheetMemory[nIndexTo] = new AscCommonExcel.SheetMemory(g_nCellStructSize, height);
|
|
tempSheetMemory[nIndexTo].copyRange(sheetMemoryTo, oBBox.r1, 0, height);
|
|
|
|
if (tempSheetMemory[nIndexFrom]) {
|
|
sheetMemoryTo.copyRange(tempSheetMemory[nIndexFrom], 0, oBBox.r1, height);
|
|
} else {
|
|
sheetMemoryTo.copyRange(sheetMemoryFrom, oBBox.r1, oBBox.r1, height);
|
|
}
|
|
}
|
|
} else {
|
|
tempSheetMemory = new AscCommonExcel.SheetMemory(g_nCellStructSize, height);
|
|
for (i = oBBox.c1; i <= oBBox.c2; ++i) {
|
|
var sheetMemory = this.worksheet.getColDataNoEmpty(i);
|
|
if (sheetMemory) {
|
|
tempSheetMemory.copyRange(sheetMemory, oBBox.r1, 0, height);
|
|
for (j in oSortedIndexes) {
|
|
nIndexFrom = j - 0;
|
|
nIndexTo = oSortedIndexes[j];
|
|
tempSheetMemory.copyRange(sheetMemory, nIndexFrom, nIndexTo - oBBox.r1, 1);
|
|
}
|
|
sheetMemory.copyRange(tempSheetMemory, 0, oBBox.r1, height);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.worksheet.workbook.dependencyFormulas.addToChangedRange(this.worksheet.getId(), new Asc.Range(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r2));
|
|
this.worksheet.workbook.dependencyFormulas.calcTree();
|
|
if (this.worksheet.workbook.handlers) {
|
|
this.worksheet.workbook.handlers.trigger("changeDocument", AscCommonExcel.docChangedType.sheetContent, this.worksheet, null, this.worksheet.getId());
|
|
}
|
|
|
|
if (false == this.worksheet.workbook.bUndoChanges && (false == this.worksheet.workbook.bRedoChanges || this.worksheet.workbook.bCollaborativeChanges)) {
|
|
AscCommon.History.LocalChange = true;
|
|
//восстанавливаем удаленые гиперссылки
|
|
if (aSortedHyperlinks.length > 0) {
|
|
for (i = 0, length = aSortedHyperlinks.length; i < length; i++) {
|
|
hyp = aSortedHyperlinks[i];
|
|
this.worksheet.hyperlinkManager.add(hyp.Ref.getBBox0(), hyp);
|
|
}
|
|
}
|
|
AscCommon.History.LocalChange = false;
|
|
}
|
|
};
|
|
Range.prototype.fillData=function(data){
|
|
for (var i = 0; i < data.length; ++i) {
|
|
var row = data[i];
|
|
for (var j = 0; j < row.length; ++j) {
|
|
this.setOffset(new AscCommon.CellBase(i, j));
|
|
var val = row[j];
|
|
if ("string" === typeof val) {
|
|
this.setValue(val);
|
|
} else {
|
|
if (val.value) {
|
|
this.setValueData(new AscCommonExcel.UndoRedoData_CellValueData(null, val.value));
|
|
}
|
|
if (val.format) {
|
|
this.setNumFormat(val.format);
|
|
}
|
|
}
|
|
this.setOffset(new AscCommon.CellBase(-i, -j));
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
function _isSameSizeMerged(bbox, aMerged, checkProportion) {
|
|
var oRes = null;
|
|
var nWidth = null;
|
|
var nHeight = null;
|
|
for (var i = 0, length = aMerged.length; i < length; i++) {
|
|
var mergedBBox = aMerged[i].bbox;
|
|
var nCurWidth = mergedBBox.c2 - mergedBBox.c1 + 1;
|
|
var nCurHeight = mergedBBox.r2 - mergedBBox.r1 + 1;
|
|
if (null == nWidth || null == nHeight) {
|
|
nWidth = nCurWidth;
|
|
nHeight = nCurHeight;
|
|
} else if (nCurWidth != nWidth || nCurHeight != nHeight) {
|
|
nWidth = null;
|
|
nHeight = null;
|
|
break;
|
|
}
|
|
}
|
|
if (null != nWidth && null != nHeight) {
|
|
var getRowColArr = function (byCol) {
|
|
var _aRowColTest = byCol ? new Array(nBBoxWidth) : new Array(nBBoxHeight);
|
|
for (var i = 0, length = aMerged.length; i < length; i++) {
|
|
var merged = aMerged[i];
|
|
var j;
|
|
if (byCol) {
|
|
for (j = merged.bbox.c1; j <= merged.bbox.c2; j++) {
|
|
_aRowColTest[j - bbox.c1] = 1;
|
|
}
|
|
} else {
|
|
for (j = merged.bbox.r1; j <= merged.bbox.r2; j++) {
|
|
_aRowColTest[j - bbox.r1] = 1;
|
|
}
|
|
}
|
|
|
|
}
|
|
return _aRowColTest;
|
|
};
|
|
var checkArr = function (_aRowColTest) {
|
|
var _res = null;
|
|
var bExistNull = false;
|
|
for (var i = 0, length = _aRowColTest.length; i < length; i++) {
|
|
if (null == _aRowColTest[i]) {
|
|
bExistNull = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!bExistNull) {
|
|
_res = true;
|
|
}
|
|
|
|
return _res;
|
|
};
|
|
|
|
//проверяем что merge ячеки полностью заполняют область
|
|
var nBBoxWidth = bbox.c2 - bbox.c1 + 1;
|
|
var nBBoxHeight = bbox.r2 - bbox.r1 + 1;
|
|
if (checkProportion && nBBoxWidth % nWidth === 0 && nBBoxHeight % nHeight === 0) {
|
|
aRowColTest = getRowColArr();
|
|
bRes = checkArr(aRowColTest);
|
|
if (bRes) {
|
|
aRowColTest = getRowColArr(true);
|
|
bRes = checkArr(aRowColTest);
|
|
}
|
|
if (bRes) {
|
|
oRes = {width: nWidth, height: nHeight};
|
|
}
|
|
} else if (nBBoxWidth == nWidth || nBBoxHeight == nHeight) {
|
|
var bRes = false;
|
|
var aRowColTest = null;
|
|
if (nBBoxWidth == nWidth && nBBoxHeight == nHeight) {
|
|
bRes = true;
|
|
} else if (nBBoxWidth == nWidth) {
|
|
aRowColTest = getRowColArr();
|
|
} else if (nBBoxHeight == nHeight) {
|
|
aRowColTest = getRowColArr(true);
|
|
}
|
|
if (null != aRowColTest) {
|
|
bRes = checkArr(aRowColTest);
|
|
}
|
|
if (bRes) {
|
|
oRes = {width: nWidth, height: nHeight};
|
|
}
|
|
}
|
|
}
|
|
return oRes;
|
|
}
|
|
function _canPromote(from, wsFrom, to, wsTo, bIsPromote, nWidth, nHeight, bVertical, nIndex) {
|
|
var oRes = {oMergedFrom: null, oMergedTo: null, to: to};
|
|
//если надо только удалить внутреннее содержимое не смотрим на замерженость
|
|
if(!bIsPromote || !((true == bVertical && nIndex >= 0 && nIndex < nHeight) || (false == bVertical && nIndex >= 0 && nIndex < nWidth)))
|
|
{
|
|
if(null != to){
|
|
var oMergedTo = wsTo.mergeManager.get(to);
|
|
if(oMergedTo.outer.length > 0)
|
|
oRes = null;
|
|
else
|
|
{
|
|
var oMergedFrom = wsFrom.mergeManager.get(from);
|
|
oRes.oMergedFrom = oMergedFrom;
|
|
if(oMergedTo.inner.length > 0)
|
|
{
|
|
oRes.oMergedTo = oMergedTo;
|
|
if (bIsPromote) {
|
|
if (oMergedFrom.inner.length > 0) {
|
|
//merge области должны иметь одинаковый размер
|
|
var oSizeFrom = _isSameSizeMerged(from, oMergedFrom.inner);
|
|
var oSizeTo = _isSameSizeMerged(to, oMergedTo.inner);
|
|
if (!(null != oSizeFrom && null != oSizeTo && oSizeTo.width == oSizeFrom.width && oSizeTo.height == oSizeFrom.height))
|
|
oRes = null;
|
|
}
|
|
else
|
|
oRes = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return oRes;
|
|
}
|
|
// Подготовка Copy Style
|
|
function preparePromoteFromTo(from, to) {
|
|
var bSuccess = true;
|
|
if (to.isOneCell())
|
|
to.setOffsetLast(new AscCommon.CellBase((from.r2 - from.r1) - (to.r2 - to.r1), (from.c2 - from.c1) - (to.c2 - to.c1)));
|
|
|
|
if(!from.isIntersect(to)) {
|
|
var bFromWholeCol = (0 == from.c1 && gc_nMaxCol0 == from.c2);
|
|
var bFromWholeRow = (0 == from.r1 && gc_nMaxRow0 == from.r2);
|
|
var bToWholeCol = (0 == to.c1 && gc_nMaxCol0 == to.c2);
|
|
var bToWholeRow = (0 == to.r1 && gc_nMaxRow0 == to.r2);
|
|
bSuccess = (bFromWholeCol === bToWholeCol && bFromWholeRow === bToWholeRow);
|
|
} else
|
|
bSuccess = false;
|
|
return bSuccess;
|
|
}
|
|
// Перед promoteFromTo обязательно должна быть вызывана функция preparePromoteFromTo
|
|
function promoteFromTo(from, wsFrom, to, wsTo) {
|
|
var bVertical = true;
|
|
var nIndex = 1;
|
|
//проверяем можно ли осуществить promote
|
|
var oCanPromote = _canPromote(from, wsFrom, to, wsTo, false, 1, 1, bVertical, nIndex);
|
|
if(null != oCanPromote)
|
|
{
|
|
AscCommon.History.Create_NewPoint();
|
|
var oSelection = AscCommon.History.GetSelection();
|
|
if(null != oSelection)
|
|
{
|
|
oSelection = oSelection.clone();
|
|
oSelection.assign(from.c1, from.r1, from.c2, from.r2);
|
|
AscCommon.History.SetSelection(oSelection);
|
|
}
|
|
var oSelectionRedo = AscCommon.History.GetSelectionRedo();
|
|
if(null != oSelectionRedo)
|
|
{
|
|
oSelectionRedo = oSelectionRedo.clone();
|
|
oSelectionRedo.assign(to.c1, to.r1, to.c2, to.r2);
|
|
AscCommon.History.SetSelectionRedo(oSelectionRedo);
|
|
}
|
|
//удаляем merge ячейки в to(после _canPromote должны остаться только inner)
|
|
wsTo.mergeManager.remove(to, true);
|
|
_promoteFromTo(from, wsFrom, to, wsTo, false, oCanPromote, false, bVertical, nIndex);
|
|
}
|
|
}
|
|
Range.prototype.canPromote=function(bCtrl, bVertical, nIndex){
|
|
var oBBox = this.bbox;
|
|
var nWidth = oBBox.c2 - oBBox.c1 + 1;
|
|
var nHeight = oBBox.r2 - oBBox.r1 + 1;
|
|
var bWholeCol = false; var bWholeRow = false;
|
|
if(0 == oBBox.r1 && gc_nMaxRow0 == oBBox.r2)
|
|
bWholeCol = true;
|
|
if(0 == oBBox.c1 && gc_nMaxCol0 == oBBox.c2)
|
|
bWholeRow = true;
|
|
if((bWholeCol && bWholeRow) || (true == bVertical && bWholeCol) || (false == bVertical && bWholeRow))
|
|
return null;
|
|
var oPromoteAscRange = null;
|
|
if(0 == nIndex)
|
|
oPromoteAscRange = new Asc.Range(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r2);
|
|
else
|
|
{
|
|
if(bVertical)
|
|
{
|
|
if(nIndex > 0)
|
|
{
|
|
if(nIndex >= nHeight)
|
|
oPromoteAscRange = new Asc.Range(oBBox.c1, oBBox.r2 + 1, oBBox.c2, oBBox.r1 + nIndex);
|
|
else
|
|
oPromoteAscRange = new Asc.Range(oBBox.c1, oBBox.r1 + nIndex, oBBox.c2, oBBox.r2);
|
|
}
|
|
else
|
|
oPromoteAscRange = new Asc.Range(oBBox.c1, oBBox.r1 + nIndex, oBBox.c2, oBBox.r1 - 1);
|
|
}
|
|
else
|
|
{
|
|
if(nIndex > 0)
|
|
{
|
|
if(nIndex >= nWidth)
|
|
oPromoteAscRange = new Asc.Range(oBBox.c2 + 1, oBBox.r1, oBBox.c1 + nIndex, oBBox.r2);
|
|
else
|
|
oPromoteAscRange = new Asc.Range(oBBox.c1 + nIndex, oBBox.r1, oBBox.c2, oBBox.r2);
|
|
}
|
|
else
|
|
oPromoteAscRange = new Asc.Range(oBBox.c1 + nIndex, oBBox.r1, oBBox.c1 - 1, oBBox.r2);
|
|
}
|
|
}
|
|
//проверяем можно ли осуществить promote
|
|
return _canPromote(oBBox, this.worksheet, oPromoteAscRange, this.worksheet, true, nWidth, nHeight, bVertical, nIndex);
|
|
};
|
|
Range.prototype.promote=function(bCtrl, bVertical, nIndex, oCanPromote){
|
|
//todo отдельный метод для promote в таблицах и merge в таблицах
|
|
if (!oCanPromote) {
|
|
oCanPromote = this.canPromote(bCtrl, bVertical, nIndex);
|
|
}
|
|
var oBBox = this.bbox;
|
|
var nWidth = oBBox.c2 - oBBox.c1 + 1;
|
|
var nHeight = oBBox.r2 - oBBox.r1 + 1;
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
var oSelection = AscCommon.History.GetSelection();
|
|
if(null != oSelection)
|
|
{
|
|
oSelection = oSelection.clone();
|
|
oSelection.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r2);
|
|
AscCommon.History.SetSelection(oSelection);
|
|
}
|
|
var oSelectionRedo = AscCommon.History.GetSelectionRedo();
|
|
if(null != oSelectionRedo)
|
|
{
|
|
oSelectionRedo = oSelectionRedo.clone();
|
|
if(0 == nIndex)
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r2);
|
|
else
|
|
{
|
|
if(bVertical)
|
|
{
|
|
if(nIndex > 0)
|
|
{
|
|
if(nIndex >= nHeight)
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r1 + nIndex);
|
|
else
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r1 + nIndex - 1);
|
|
}
|
|
else
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1 + nIndex, oBBox.c2, oBBox.r2);
|
|
}
|
|
else
|
|
{
|
|
if(nIndex > 0)
|
|
{
|
|
if(nIndex >= nWidth)
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c1 + nIndex, oBBox.r2);
|
|
else
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c1 + nIndex - 1, oBBox.r2);
|
|
}
|
|
else
|
|
oSelectionRedo.assign(oBBox.c1 + nIndex, oBBox.r1, oBBox.c2, oBBox.r2);
|
|
}
|
|
}
|
|
AscCommon.History.SetSelectionRedo(oSelectionRedo);
|
|
}
|
|
_promoteFromTo(oBBox, this.worksheet, oCanPromote.to, this.worksheet, true, oCanPromote, bCtrl, bVertical, nIndex);
|
|
};
|
|
function _addAInputTimePeriod(aTimePeriodName, bNeedSwapFirstLastElem) {
|
|
let aTimePeriod = aTimePeriodName.map(function (sTimePeriod) {
|
|
return sTimePeriod.toLowerCase();
|
|
});
|
|
const nLastIndex = aTimePeriod.length - 1;
|
|
|
|
if(!aTimePeriod[nLastIndex]) {
|
|
aTimePeriod.pop();
|
|
}
|
|
|
|
if (bNeedSwapFirstLastElem) {
|
|
let sLastElem = aTimePeriod.pop();
|
|
aTimePeriod.unshift(sLastElem);
|
|
}
|
|
|
|
return aTimePeriod;
|
|
}
|
|
function _updateATimePeriod (aTimePeriods, sValue) {
|
|
let sFirstSymbols = sValue.slice(0,2);
|
|
|
|
return aTimePeriods.map(function (sTimePeriod) {
|
|
if (sFirstSymbols === sFirstSymbols.toUpperCase()) {
|
|
return sTimePeriod.toUpperCase();
|
|
}
|
|
if (sFirstSymbols === sFirstSymbols.toLowerCase()) {
|
|
// Because source array already has elements in lowercase
|
|
return sTimePeriod
|
|
}
|
|
// For cases like Monday, MoNdAy or mOnDaY. If first symbol is lowercase then values in lowercase else values start with capitalized
|
|
if (sFirstSymbols[0] === sFirstSymbols[0].toUpperCase()) {
|
|
return sTimePeriod[0].toUpperCase() + sTimePeriod.slice(1);
|
|
}
|
|
|
|
return sTimePeriod;
|
|
});
|
|
}
|
|
function _getIndexATimePeriods(aTimePeriods, sValue) {
|
|
let sFirstSymbols = sValue.slice(0,2);
|
|
let sFormatedValue = '';
|
|
let sSlicedValue = sValue.slice(1);
|
|
|
|
if (sValue === sValue.toLowerCase() || sValue === sValue.toUpperCase()) {
|
|
return aTimePeriods.indexOf(sValue);
|
|
}
|
|
|
|
// For cases like Monday, MoNdAy, MOnDaY or mOnDaY. If first symbol is lowercase then sValue convert in lowercase else sValue convert to start with capitalized
|
|
if (sFirstSymbols[0] === sFirstSymbols[0].toLowerCase()) {
|
|
sFormatedValue = sValue.toLowerCase();
|
|
return aTimePeriods.indexOf(sFormatedValue);
|
|
}
|
|
if (sFirstSymbols === sFirstSymbols.toUpperCase()) {
|
|
sFormatedValue = sValue.toUpperCase();
|
|
return aTimePeriods.indexOf(sFormatedValue);
|
|
}
|
|
sFormatedValue = sSlicedValue === sSlicedValue.toLowerCase() ? sValue : sValue[0] + sSlicedValue.toLowerCase();
|
|
return aTimePeriods.indexOf(sFormatedValue);
|
|
}
|
|
function _getRepeatTimePeriod(nRepeat, nPreviousVal, nIndex, nMaxTimePeriod) {
|
|
let bIsSequence = false;
|
|
let nDiff = 0;
|
|
let nCurrentVal = nIndex;
|
|
let nLastElement = nMaxTimePeriod - 1;
|
|
|
|
if (nPreviousVal) {
|
|
// Defining is datas has asc sequence like Monday, Tuesday etc or even\odd sequence?
|
|
if (nIndex === 0 && nPreviousVal === nLastElement) {
|
|
bIsSequence = true;
|
|
} else {
|
|
if (nRepeat > 0) nCurrentVal += nMaxTimePeriod * nRepeat;
|
|
nDiff = nCurrentVal - nPreviousVal;
|
|
if (nDiff === 1) {
|
|
bIsSequence = true;
|
|
}
|
|
}
|
|
if (bIsSequence) {
|
|
return nIndex === 0 ? nRepeat + 1 : nRepeat;
|
|
} else if (nIndex === 0 || (nIndex === 1 && nPreviousVal >= nLastElement)) {
|
|
return nRepeat + 1;
|
|
}
|
|
}
|
|
|
|
return nRepeat;
|
|
}
|
|
function _findIndexAInputTimePeriod(aTimePeriodsList, sValue) {
|
|
return aTimePeriodsList.findIndex(function (aTimePeriod) {
|
|
return aTimePeriod.includes(sValue.toLowerCase());
|
|
});
|
|
}
|
|
function _getAInputTimePeriod(aInputTimePeriodList, nIndex, nPrevIndex, sValue, sNextValue) {
|
|
let aInputTimePeriod = aInputTimePeriodList[nIndex];
|
|
// Checking nearby cells if value has in both arrays (short and full names)
|
|
let sValueLowReg = sValue.toLowerCase();
|
|
let aPrevInputTimePeriod = nPrevIndex ? aInputTimePeriodList[nPrevIndex] : null;
|
|
|
|
if (aPrevInputTimePeriod && nIndex !== nPrevIndex && aPrevInputTimePeriod.includes(sValueLowReg)) {
|
|
aInputTimePeriod = aPrevInputTimePeriod;
|
|
} else if (!aPrevInputTimePeriod && sNextValue) { // doesn't check next cell if previous cell exist
|
|
let nNextIndex = _findIndexAInputTimePeriod(aInputTimePeriodList, sNextValue);
|
|
let aNextInputTimePeriod = aInputTimePeriodList[nNextIndex];
|
|
if (aNextInputTimePeriod && nIndex !== nNextIndex && aNextInputTimePeriod.includes(sValueLowReg)) {
|
|
aInputTimePeriod = aNextInputTimePeriod;
|
|
}
|
|
}
|
|
|
|
return aInputTimePeriod
|
|
}
|
|
function _getNextValue(wsFrom, oCell, bVertical, from) {
|
|
if (bVertical) {
|
|
let nNextItRow = oCell.nRow + 1;
|
|
if (nNextItRow <= from.r2) {
|
|
return wsFrom.getCell3(nNextItRow, oCell.nCol).getValueWithoutFormat();
|
|
}
|
|
} else {
|
|
let nNextItCol = oCell.nCol + 1;
|
|
if (nNextItCol <= from.c2) {
|
|
return wsFrom.getCell3(oCell.nRow, nNextItCol).getValueWithoutFormat();
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
function _promoteFromTo(from, wsFrom, to, wsTo, bIsPromote, oCanPromote, bCtrl, bVertical, nIndex) {
|
|
var wb = wsFrom.workbook;
|
|
const oDefaultCultureInfo = AscCommon.g_oDefaultCultureInfo;
|
|
|
|
wb.dependencyFormulas.lockRecal();
|
|
AscCommon.History.StartTransaction();
|
|
|
|
var oldExcludeHiddenRows = wsFrom.bExcludeHiddenRows;
|
|
if(wsFrom.autoFilters.bIsExcludeHiddenRows(from, wsFrom.selectionRange.activeCell)){
|
|
wsFrom.excludeHiddenRows(true);
|
|
}
|
|
|
|
var toRange = wsTo.getRange3(to.r1, to.c1, to.r2, to.c2);
|
|
var fromRange = wsFrom.getRange3(from.r1, from.c1, from.r2, from.c2);
|
|
var bChangeRowColProp = false;
|
|
var nLastCol = from.c2;
|
|
if (0 == from.c1 && gc_nMaxCol0 == from.c2)
|
|
{
|
|
var aRowProperties = [];
|
|
nLastCol = 0;
|
|
fromRange._foreachRowNoEmpty(function(row){
|
|
if(!row.isEmptyProp())
|
|
aRowProperties.push({index: row.index - from.r1, prop: row.getHeightProp(), style: row.getStyle()});
|
|
}, function(cell){
|
|
var nCurCol0 = cell.nCol;
|
|
if(nCurCol0 > nLastCol)
|
|
nLastCol = nCurCol0;
|
|
});
|
|
if(aRowProperties.length > 0)
|
|
{
|
|
bChangeRowColProp = true;
|
|
var nCurCount = 0;
|
|
var nCurIndex = 0;
|
|
while (true) {
|
|
for (var i = 0, length = aRowProperties.length; i < length; ++i) {
|
|
var propElem = aRowProperties[i];
|
|
nCurIndex = to.r1 + nCurCount * (from.r2 - from.r1 + 1) + propElem.index;
|
|
if (nCurIndex > to.r2)
|
|
break;
|
|
else{
|
|
wsTo._getRow(nCurIndex, function(row) {
|
|
if (null != propElem.style)
|
|
row.setStyle(propElem.style);
|
|
if (null != propElem.prop) {
|
|
var oNewProps = propElem.prop;
|
|
var oOldProps = row.getHeightProp();
|
|
if (false === oOldProps.isEqual(oNewProps)) {
|
|
row.setHeightProp(oNewProps);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_RowProp, wsTo.getId(), row._getUpdateRange(), new UndoRedoData_IndexSimpleProp(nCurIndex, true, oOldProps, oNewProps));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
nCurCount++;
|
|
if (nCurIndex > to.r2)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
var nLastRow = from.r2;
|
|
if (0 == from.r1 && gc_nMaxRow0 == from.r2)
|
|
{
|
|
var aColProperties = [];
|
|
nLastRow = 0;
|
|
fromRange._foreachColNoEmpty(function(col){
|
|
if(!col.isEmpty())
|
|
aColProperties.push({ index: col.index - from.c1, prop: col.getWidthProp(), style: col.getStyle() });
|
|
}, function(cell){
|
|
var nCurRow0 = cell.nRow;
|
|
if(nCurRow0 > nLastRow)
|
|
nLastRow = nCurRow0;
|
|
});
|
|
if (aColProperties.length > 0)
|
|
{
|
|
bChangeRowColProp = true;
|
|
var nCurCount = 0;
|
|
var nCurIndex = 0;
|
|
while (true) {
|
|
for (var i = 0, length = aColProperties.length; i < length; ++i) {
|
|
var propElem = aColProperties[i];
|
|
nCurIndex = to.c1 + nCurCount * (from.c2 - from.c1 + 1) + propElem.index;
|
|
if (nCurIndex > to.c2)
|
|
break;
|
|
else{
|
|
var col = wsTo._getCol(nCurIndex);
|
|
if (null != propElem.style)
|
|
col.setStyle(propElem.style);
|
|
if (null != propElem.prop) {
|
|
var oNewProps = propElem.prop;
|
|
var oOldProps = col.getWidthProp();
|
|
if (false == oOldProps.isEqual(oNewProps)) {
|
|
col.setWidthProp(oNewProps);
|
|
wsTo.initColumn(col);
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoWorksheet, AscCH.historyitem_Worksheet_ColProp, wsTo.getId(), new Asc.Range(nCurIndex, 0, nCurIndex, gc_nMaxRow0), new UndoRedoData_IndexSimpleProp(nCurIndex, false, oOldProps, oNewProps));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
nCurCount++;
|
|
if (nCurIndex > to.c2)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (bChangeRowColProp) {
|
|
wb.handlers && wb.handlers.trigger("changeWorksheetUpdate", wsTo.getId());
|
|
}
|
|
if(nLastCol != from.c2 || nLastRow != from.r2)
|
|
{
|
|
var offset = new AscCommon.CellBase(nLastRow - from.r2, nLastCol - from.c2);
|
|
toRange.setOffsetLast(offset);
|
|
to = toRange.getBBox0();
|
|
fromRange.setOffsetLast(offset);
|
|
from = fromRange.getBBox0();
|
|
}
|
|
var nWidth = from.c2 - from.c1 + 1;
|
|
var nHeight = from.r2 - from.r1 + 1;
|
|
//удаляем текст или все в области для заполнения
|
|
if(bIsPromote && nIndex >= 0 && ((true == bVertical && nHeight > nIndex) || (false == bVertical && nWidth > nIndex)))
|
|
{
|
|
//удаляем только текст в области для заполнения
|
|
toRange.cleanText();
|
|
}
|
|
else
|
|
{
|
|
//удаляем все в области для заполнения
|
|
if(bIsPromote)
|
|
toRange.cleanAll();
|
|
else
|
|
toRange.cleanFormat();
|
|
//собираем все данные
|
|
var bReverse = false;
|
|
if(nIndex < 0)
|
|
bReverse = true;
|
|
let oPromoteHelper = new PromoteHelper(bVertical, bReverse, from);
|
|
oPromoteHelper.setFillHandleRightClick(wsFrom.getFillHandleRightClick());
|
|
let aInputDaysOfWeek = _addAInputTimePeriod(oDefaultCultureInfo.DayNames, false);
|
|
let aInputShortDaysOfWeek = _addAInputTimePeriod(oDefaultCultureInfo.AbbreviatedDayNames, false);
|
|
let aInputMonths = _addAInputTimePeriod(oDefaultCultureInfo.MonthNames, true);
|
|
let aInputMonthShort = _addAInputTimePeriod(oDefaultCultureInfo.AbbreviatedMonthNames, true);
|
|
let aInputTimePeriodList = [aInputDaysOfWeek, aInputShortDaysOfWeek, aInputMonths, aInputMonthShort];
|
|
let nPreviousVal = null;
|
|
let nPrevInputTimePeriod = null;
|
|
let nRepeat = 0;
|
|
fromRange._foreachNoEmpty(function(oCell, nRow0, nCol0, nRowStart0, nColStart0){
|
|
if(null != oCell)
|
|
{
|
|
function calcTimePeriodValues() {
|
|
// Update array of a time period based on sValue
|
|
aTimePeriods = _updateATimePeriod(aInputTimePeriod, sValue);
|
|
let nMaxTimePeriod = aTimePeriods.length;
|
|
let nIndex = _getIndexATimePeriods(aTimePeriods, sValue);
|
|
nRepeat = _getRepeatTimePeriod(nRepeat, nPreviousVal, nIndex, nMaxTimePeriod);
|
|
// In nVal stores number of a time period.
|
|
// e.g. "index from array days of the week + 7 (count days in week) * count of repeat"
|
|
nVal = nIndex + nMaxTimePeriod * nRepeat;
|
|
bDate = true;
|
|
nPreviousVal = nVal;
|
|
nPrevInputTimePeriod = nInputTimePeriod;
|
|
}
|
|
var nVal = null;
|
|
var bDelimiter = false;
|
|
var sPrefix = null;
|
|
var padding = 0;
|
|
var bDate = false;
|
|
let aTimePeriods = null;
|
|
let aInputTimePeriod = null;
|
|
let sNextValue = null;
|
|
let nInputTimePeriod = null;
|
|
if(bIsPromote)
|
|
{
|
|
if (!oCell.isFormula())
|
|
{
|
|
var sValue = oCell.getValueWithoutFormat();
|
|
if("" != sValue)
|
|
{
|
|
bDelimiter = true;
|
|
var nType = oCell.getType();
|
|
if(CellValueType.Number == nType || CellValueType.String == nType)
|
|
{
|
|
if(CellValueType.Number == nType)
|
|
nVal = sValue - 0;
|
|
else
|
|
{
|
|
//если текст заканчивается на цифру тоже используем ее
|
|
var nEndIndex = sValue.length;
|
|
for(var k = sValue.length - 1; k >= 0; --k)
|
|
{
|
|
var sCurChart = sValue[k];
|
|
if('0' <= sCurChart && sCurChart <= '9')
|
|
nEndIndex--;
|
|
else
|
|
break;
|
|
}
|
|
if(sValue.length != nEndIndex)
|
|
{
|
|
sPrefix = sValue.substring(0, nEndIndex);
|
|
var sNumber = sValue.substring(nEndIndex);
|
|
//sNumber have no decimal point, so can use simple parseInt
|
|
nVal = sNumber - 0;
|
|
padding = sNumber[0] === '0' ? sNumber.length : 0;
|
|
}
|
|
// Value of cell is it a time period?
|
|
sValue = sValue.replace(/[.]$/, '').trim();
|
|
sNextValue = _getNextValue(wsFrom, oCell, bVertical, from);
|
|
nInputTimePeriod = _findIndexAInputTimePeriod(aInputTimePeriodList, sValue);
|
|
aInputTimePeriod = _getAInputTimePeriod(aInputTimePeriodList, nInputTimePeriod, nPrevInputTimePeriod, sValue, sNextValue);
|
|
if (aInputTimePeriod) {
|
|
calcTimePeriodValues();
|
|
}
|
|
}
|
|
}
|
|
if(null != oCell.xfs && null != oCell.xfs.num && null != oCell.xfs.num.getFormat()){
|
|
var numFormat = oNumFormatCache.get(oCell.xfs.num.getFormat());
|
|
if(numFormat.isDateTimeFormat())
|
|
bDate = true;
|
|
}
|
|
if(null != nVal)
|
|
bDelimiter = false;
|
|
}
|
|
}
|
|
else
|
|
bDelimiter = true;
|
|
}
|
|
oPromoteHelper.add(nRow0 - nRowStart0, nCol0 - nColStart0, nVal, bDelimiter, sPrefix, padding, bDate, oCell.duplicate(), aTimePeriods);
|
|
}
|
|
});
|
|
var bCopy = false;
|
|
if(bCtrl)
|
|
bCopy = true;
|
|
//в случае одной ячейки с числом меняется смысл bCtrl
|
|
if(1 == nWidth && 1 == nHeight && oPromoteHelper.isOnlyIntegerSequence()) {
|
|
let fillType = wsTo && wsTo.getActiveFillType();
|
|
if (fillType !== Asc.c_oAscFillType.fillDown && fillType !== Asc.c_oAscFillType.fillUp
|
|
&& fillType !== Asc.c_oAscFillType.fillLeft && fillType !== Asc.c_oAscFillType.fillRight) {
|
|
bCopy = !bCopy;
|
|
}
|
|
}
|
|
oPromoteHelper.setFillMenuChosenProp(wsFrom.getFillMenuChosenProp());
|
|
oPromoteHelper.finishAdd(bCopy);
|
|
//заполняем ячейки данными
|
|
var nStartRow, nEndRow, nStartCol, nEndCol, nColDx, bRowFirst;
|
|
if(bVertical)
|
|
{
|
|
nStartRow = to.c1;
|
|
nEndRow = to.c2;
|
|
bRowFirst = false;
|
|
if(bReverse)
|
|
{
|
|
nStartCol = to.r2;
|
|
nEndCol = to.r1;
|
|
nColDx = -1;
|
|
}
|
|
else
|
|
{
|
|
nStartCol = to.r1;
|
|
nEndCol = to.r2;
|
|
nColDx = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nStartRow = to.r1;
|
|
nEndRow = to.r2;
|
|
bRowFirst = true;
|
|
if(bReverse)
|
|
{
|
|
nStartCol = to.c2;
|
|
nEndCol = to.c1;
|
|
nColDx = -1;
|
|
}
|
|
else
|
|
{
|
|
nStartCol = to.c1;
|
|
nEndCol = to.c2;
|
|
nColDx = 1;
|
|
}
|
|
}
|
|
var addedFormulasArray = [];
|
|
var isAddFormulaArray = function(arrayRef) {
|
|
var res = false;
|
|
for(var n = 0; n < addedFormulasArray.length; n++) {
|
|
if(addedFormulasArray[n].isEqual(arrayRef)) {
|
|
res = true;
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
for(var i = nStartRow; i <= nEndRow; i ++)
|
|
{
|
|
oPromoteHelper.setIndex(i - nStartRow);
|
|
for(var j = nStartCol; (nStartCol - j) * (nEndCol - j) <= 0; j += nColDx)
|
|
{
|
|
if (bVertical && wsTo.bExcludeHiddenRows && wsTo.getRowHidden(j))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var data = oPromoteHelper.getNext();
|
|
if(null != data && (data.getAdditional() || (false == bCopy && null != data.getCurValue())))
|
|
{
|
|
var oFromCell = data.getAdditional();
|
|
var nRow = bRowFirst ? i : j;
|
|
var nCol = bRowFirst ? j : i;
|
|
let sPrefix = data.getPrefix();
|
|
let nCurValue = data.getCurValue();
|
|
let nPadding = data.getPadding();
|
|
let aTimePeriods = data.getTimePeriods();
|
|
let aReverseTimePeriods = [];
|
|
|
|
if (aTimePeriods && (bReverse || nCurValue < 0)) {
|
|
aReverseTimePeriods = aTimePeriods.slice();
|
|
aReverseTimePeriods.reverse();
|
|
}
|
|
wsTo._getCell(nRow, nCol, function(oCopyCell){
|
|
if(bIsPromote)
|
|
{
|
|
if(false === bCopy && null != nCurValue)
|
|
{
|
|
var oCellValue = new AscCommonExcel.CCellValue();
|
|
if (null != sPrefix) {
|
|
var sVal = sPrefix;
|
|
//toString enough, because nCurValue nave not decimal part
|
|
var sNumber = nCurValue.toString();
|
|
if (sNumber.length < nPadding) {
|
|
sNumber = '0'.repeat(nPadding - sNumber.length) + sNumber;
|
|
}
|
|
sVal += sNumber;
|
|
oCellValue.text = sVal;
|
|
oCellValue.type = CellValueType.String;
|
|
} else if (aTimePeriods) {
|
|
let nIndexDay = nCurValue % aTimePeriods.length;
|
|
if (nIndexDay < 0) {
|
|
oCellValue.text = aReverseTimePeriods[~nIndexDay];
|
|
} else {
|
|
oCellValue.text = aTimePeriods[nIndexDay];
|
|
}
|
|
oCellValue.type = CellValueType.String;
|
|
} else {
|
|
oCellValue.number = nCurValue;
|
|
oCellValue.type = CellValueType.Number;
|
|
}
|
|
oCopyCell.setValueData(new UndoRedoData_CellValueData(null, oCellValue));
|
|
}
|
|
else if(null != oFromCell)
|
|
{
|
|
//копируем полностью
|
|
if(!oFromCell.isFormula()){
|
|
oCopyCell.setValueData(oFromCell.getValueData());
|
|
//todo
|
|
// if(oCopyCell.isEmptyTextString())
|
|
// wsTo._getHyperlink().remove({r1: oCopyCell.nRow, c1: oCopyCell.nCol, r2: oCopyCell.nRow, c2: oCopyCell.nCol});
|
|
} else {
|
|
var fromFormulaParsed = oFromCell.getFormulaParsed();
|
|
var formulaArrayRef = fromFormulaParsed.getArrayFormulaRef();
|
|
|
|
var _p_,offset, offsetArray, assemb;
|
|
if(formulaArrayRef) {
|
|
var intersectionFrom = from.intersection(formulaArrayRef);
|
|
if(intersectionFrom) {
|
|
if((intersectionFrom.c1 === oFromCell.nCol && intersectionFrom.r1 === oFromCell.nRow) || (intersectionFrom.c2 === oFromCell.nCol && intersectionFrom.r2 === oFromCell.nRow)) {
|
|
|
|
offsetArray = oCopyCell.getOffset2(oFromCell.getName());
|
|
intersectionFrom.setOffset(offsetArray);
|
|
|
|
var intersectionTo = intersectionFrom.intersection(to);
|
|
if(intersectionTo && !isAddFormulaArray(intersectionTo)) {
|
|
addedFormulasArray.push(intersectionTo);
|
|
//offset = oCopyCell.getOffset3(formulaArrayRef.c1 + 1, formulaArrayRef.r1 + 1);
|
|
offset = new AscCommon.CellBase(intersectionTo.r1 - formulaArrayRef.r1, intersectionTo.c1 - formulaArrayRef.c1);
|
|
_p_ = oFromCell.getFormulaParsed().clone(null, oFromCell, this);
|
|
_p_.changeOffset(offset);
|
|
|
|
var rangeFormulaArray = oCopyCell.ws.getRange3(intersectionTo.r1, intersectionTo.c1, intersectionTo.r2, intersectionTo.c2);
|
|
rangeFormulaArray.setValue("=" + _p_.assemble(true), function (r) {}, null, intersectionTo);
|
|
|
|
AscCommon.History.Add(AscCommonExcel.g_oUndoRedoArrayFormula,
|
|
AscCH.historyitem_ArrayFromula_AddFormula, oCopyCell.ws.getId(),
|
|
new Asc.Range(intersectionTo.c1, intersectionTo.r1, intersectionTo.c2, intersectionTo.r2),
|
|
new AscCommonExcel.UndoRedoData_ArrayFormula(intersectionTo, "=" + oCopyCell.getFormulaParsed().assemble(true)));
|
|
}
|
|
|
|
}
|
|
}
|
|
} else {
|
|
_p_ = oFromCell.getFormulaParsed().clone(null, oFromCell, this);
|
|
offset = oCopyCell.getOffset2(oFromCell.getName());
|
|
assemb = _p_.changeOffset(offset).assemble(true);
|
|
let oCaProps = {};
|
|
if (_p_.ca) { // for recursion formulas
|
|
oCaProps.ca = _p_.ca;
|
|
oCaProps.oldValue = oFromCell.getNumberValue();
|
|
}
|
|
oCopyCell.setFormula(assemb, null, null, oCaProps);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
//выставляем стиль после текста, потому что если выставить числовой стиль ячейки 'text', то после этого не применится формула
|
|
if (null != oFromCell) {
|
|
oCopyCell.setStyle(oFromCell.getStyle());
|
|
if (bIsPromote)
|
|
oCopyCell.setType(oFromCell.getType());
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
if(bIsPromote) {
|
|
wb.dependencyFormulas.addToChangedRange( wsTo.Id, to );
|
|
}
|
|
//добавляем замерженые области
|
|
var nDx = from.c2 - from.c1 + 1;
|
|
var nDy = from.r2 - from.r1 + 1;
|
|
var oMergedFrom = oCanPromote.oMergedFrom;
|
|
if(null != oMergedFrom && oMergedFrom.all.length > 0)
|
|
{
|
|
for (var i = to.c1; i <= to.c2; i += nDx) {
|
|
for (var j = to.r1; j <= to.r2; j += nDy) {
|
|
for (var k = 0, length3 = oMergedFrom.all.length; k < length3; k++) {
|
|
var oMergedBBox = oMergedFrom.all[k].bbox;
|
|
var oNewMerged = new Asc.Range(i + oMergedBBox.c1 - from.c1, j + oMergedBBox.r1 - from.r1, i + oMergedBBox.c2 - from.c1, j + oMergedBBox.r2 - from.r1);
|
|
if(to.contains(oNewMerged.c1, oNewMerged.r1)) {
|
|
if(to.c2 < oNewMerged.c2)
|
|
oNewMerged.c2 = to.c2;
|
|
if(to.r2 < oNewMerged.r2)
|
|
oNewMerged.r2 = to.r2;
|
|
if(!oNewMerged.isOneCell())
|
|
wsTo.mergeManager.add(oNewMerged, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(bIsPromote)
|
|
{
|
|
//добавляем ссылки
|
|
//не как в Excel поддерживаются ссылки на диапазоны
|
|
var oHyperlinks = wsFrom.hyperlinkManager.get(from);
|
|
if(oHyperlinks.inner.length > 0)
|
|
{
|
|
for (var i = to.c1; i <= to.c2; i += nDx) {
|
|
for (var j = to.r1; j <= to.r2; j += nDy) {
|
|
for(var k = 0, length3 = oHyperlinks.inner.length; k < length3; k++){
|
|
var oHyperlink = oHyperlinks.inner[k];
|
|
var oHyperlinkBBox = oHyperlink.bbox;
|
|
var oNewHyperlink = new Asc.Range(i + oHyperlinkBBox.c1 - from.c1, j + oHyperlinkBBox.r1 - from.r1, i + oHyperlinkBBox.c2 - from.c1, j + oHyperlinkBBox.r2 - from.r1);
|
|
if (to.containsRange(oNewHyperlink))
|
|
wsTo.hyperlinkManager.add(oNewHyperlink, oHyperlink.data.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
var aDataValidations;
|
|
if (wsFrom.dataValidations && wsTo.dataValidations) {
|
|
wsTo.clearDataValidation([to], true);
|
|
aDataValidations = wsFrom.dataValidations.getIntersectionByRange(from);
|
|
}
|
|
if(aDataValidations && aDataValidations.length > 0) {
|
|
var newDataValidations = [];
|
|
for (var i = to.c1; i <= to.c2; i += nDx) {
|
|
for (var j = to.r1; j <= to.r2; j += nDy) {
|
|
for(var k = 0, length3 = aDataValidations.length; k < length3; k++){
|
|
var oDataValidation = aDataValidations[k];
|
|
var ranges = oDataValidation.ranges;
|
|
for (var n = 0; n < ranges.length; n++) {
|
|
var _newRange = new Asc.Range(i + ranges[n].c1 - from.c1, j + ranges[n].r1 - from.r1, i + ranges[n].c2 - from.c1, j + ranges[n].r2 - from.r1);
|
|
if (to.containsRange(_newRange)) {
|
|
if (!newDataValidations[k]) {
|
|
newDataValidations[k] = [];
|
|
}
|
|
newDataValidations[k].push(_newRange);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (newDataValidations && newDataValidations.length) {
|
|
for (var i = 0; i < newDataValidations.length; i++) {
|
|
if (newDataValidations[i] && newDataValidations[i].length) {
|
|
var fromDataValidation = wsFrom.getDataValidationById(aDataValidations[i].id);
|
|
if (fromDataValidation) {
|
|
fromDataValidation = fromDataValidation.data;
|
|
var toDataValidation = fromDataValidation.clone();
|
|
toDataValidation.ranges = fromDataValidation.ranges.concat(newDataValidations[i]);
|
|
wsTo.dataValidations.change(wsTo, fromDataValidation, toDataValidation, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (wsTo.aSparklineGroups && wsTo.aSparklineGroups.length) {
|
|
wsTo.removeSparklines(to);
|
|
}
|
|
if(wsFrom === wsTo && wsFrom.aSparklineGroups && wsFrom.aSparklineGroups.length) {
|
|
for (var i = to.c1; i <= to.c2; i += nDx) {
|
|
for (var j = to.r1; j <= to.r2; j += nDy) {
|
|
for(var k = 0, length3 = wsFrom.aSparklineGroups.length; k < length3; k++){
|
|
var _arrSparklines = wsFrom.aSparklineGroups[k].getModifySparklinesForPromote(from, to, new AscCommon.CellBase(j - from.r1, i - from.c1));
|
|
if (_arrSparklines) {
|
|
wsFrom.aSparklineGroups[k].setSparklines(_arrSparklines, true, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var aRules;
|
|
if (wsTo.isConditionalFormattingRules()) {
|
|
wsTo.clearConditionalFormattingRulesByRanges([to])
|
|
}
|
|
if (wsFrom.isConditionalFormattingRules()) {
|
|
aRules = wsFrom.getIntersectionRules(from);
|
|
}
|
|
if(aRules && aRules.length > 0) {
|
|
//TODO сделать объединение диапазонов! (допустим, при копировании стиля на несколько ячеек)
|
|
var newRules = [];
|
|
for (var i = to.c1; i <= to.c2; i += nDx) {
|
|
for (var j = to.r1; j <= to.r2; j += nDy) {
|
|
for(var k = 0, length3 = aRules.length; k < length3; k++){
|
|
var oRule = aRules[k];
|
|
var ranges = oRule.ranges;
|
|
for (var n = 0; n < ranges.length; n++) {
|
|
var _newRange = new Asc.Range(i + ranges[n].c1 - from.c1, j + ranges[n].r1 - from.r1, i + ranges[n].c2 - from.c1, j + ranges[n].r2 - from.r1);
|
|
if (!to.containsRange(_newRange)) {
|
|
_newRange = to.intersection(_newRange);
|
|
}
|
|
if (_newRange) {
|
|
if (!newRules[k]) {
|
|
newRules[k] = [];
|
|
}
|
|
newRules[k].push(_newRange);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (newRules && newRules.length) {
|
|
for (var i = 0; i < newRules.length; i++) {
|
|
if (newRules[i] && newRules[i].length) {
|
|
var fromRule = wsFrom.getRuleById(aRules[i].id);
|
|
if (fromRule) {
|
|
fromRule = fromRule.data;
|
|
var toRule = fromRule.clone();
|
|
//toRule.id = fromRule.id;
|
|
if (bIsPromote) {
|
|
toRule.id = fromRule.id;
|
|
toRule.ranges = fromRule.ranges.concat(newRules[i]);
|
|
toRule.combineRangesToSingle();
|
|
} else {
|
|
toRule.ranges = newRules[i];
|
|
}
|
|
wsTo.setCFRule(toRule);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
wsFrom.excludeHiddenRows(oldExcludeHiddenRows);
|
|
AscCommon.History.EndTransaction();
|
|
wb.dependencyFormulas.unlockRecal();
|
|
}
|
|
Range.prototype.createCellOnRowColCross=function(){
|
|
var oThis = this;
|
|
var bbox = this.bbox;
|
|
var nRangeType = this._getRangeType(bbox);
|
|
if(c_oRangeType.Row == nRangeType)
|
|
{
|
|
this._foreachColNoEmpty(function(col){
|
|
if(null != col.xfs)
|
|
{
|
|
for(var i = bbox.r1; i <= bbox.r2; ++i)
|
|
oThis.worksheet._getCell(i, col.index, function(){});
|
|
}
|
|
}, null);
|
|
}
|
|
else if(c_oRangeType.Col == nRangeType)
|
|
{
|
|
this._foreachRowNoEmpty(function(row){
|
|
if(null != row.xfs)
|
|
{
|
|
for(var i = bbox.c1; i <= bbox.c2; ++i)
|
|
oThis.worksheet._getCell(row.index, i, function(){});
|
|
}
|
|
}, null);
|
|
}
|
|
};
|
|
|
|
Range.prototype.getLeftTopCell = function(fAction) {
|
|
return this.worksheet._getCell(this.bbox.r1, this.bbox.c1, fAction);
|
|
};
|
|
|
|
Range.prototype.getLeftTopCellNoEmpty = function(fAction) {
|
|
return this.worksheet._getCellNoEmpty(this.bbox.r1, this.bbox.c1, fAction);
|
|
};
|
|
|
|
Range.prototype.move = function (oBBoxTo, copyRange, wsTo) {
|
|
this.worksheet._moveRange(this.bbox, oBBoxTo, copyRange, wsTo);
|
|
};
|
|
Range.prototype.onWorksheetChange = function () {
|
|
this.worksheet.workbook && this.worksheet.workbook.oApi && this.worksheet.workbook.oApi.onWorksheetChange && this.worksheet.workbook.oApi.onWorksheetChange(this.bbox);
|
|
};
|
|
|
|
function SweepLineRowIterator() {
|
|
this.cellsByCol = null;
|
|
this.row = -1;
|
|
this.col = -1;
|
|
this.colData = null;
|
|
|
|
this.colDatas = [];
|
|
this.colDatasCol = [];
|
|
this.colDatasIndex = 0;
|
|
|
|
this.toInsert = [];
|
|
this.toInsertIndex = 0;
|
|
this.toDelete = [];
|
|
this.toDeleteIndex = 0;
|
|
|
|
this.r1 = [];
|
|
this.r1Index = 0;
|
|
this.r2 = [];
|
|
this.r2Index = 0;
|
|
}
|
|
|
|
SweepLineRowIterator.prototype.init = function (cellsByCol, r1, c1, c2) {
|
|
this.cellsByCol = cellsByCol;
|
|
this.row = r1 - 1;
|
|
this.col = -1;
|
|
this.colData = null;
|
|
|
|
this.colDatas = [];
|
|
this.colDatasCol = [];
|
|
this.colDatasIndex = 0;
|
|
|
|
this.toInsert = [];
|
|
this.toInsertIndex = 0;
|
|
this.toDelete = [];
|
|
this.toDeleteIndex = 0;
|
|
this.r1 = [];
|
|
this.r1Index = 0;
|
|
this.r2 = [];
|
|
this.r2Index = 0;
|
|
|
|
c2 = Math.min(c2, this.cellsByCol.length - 1);
|
|
for (let i = c1; i <= c2; i++) {
|
|
let colData = this.cellsByCol[i];
|
|
if (colData && r1 <= colData.getMaxIndex()) {
|
|
//minIndex is max of
|
|
let elem = {col: i, minIndex: Math.max(r1, colData.getMinIndex()), maxIndex: colData.getMaxIndex(), isInserted: false}
|
|
this.r1.push(elem);
|
|
this.r2.push(elem);
|
|
}
|
|
}
|
|
//Array.sort is stable in all browsers
|
|
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
|
|
this.r1.sort(function (a, b) {
|
|
return a.minIndex - b.minIndex
|
|
});
|
|
this.r2.sort(function (a, b) {
|
|
return a.maxIndex - b.maxIndex
|
|
});
|
|
};
|
|
SweepLineRowIterator.prototype.setRow = function (row) {
|
|
while (this.row < row) {
|
|
//structure of r1 and r2 forces rows to be changed with fixed step
|
|
this.nextRow();
|
|
if (this.row < row) {
|
|
while (this.nextCol()) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SweepLineRowIterator.prototype.nextRow = function () {
|
|
this.row++;
|
|
this.col = -1;
|
|
this.colData = null;
|
|
this.colDatasIndex = 0;
|
|
while (this.r1Index < this.r1.length && this.row >= this.r1[this.r1Index].minIndex) {
|
|
let elem = this.r1[this.r1Index];
|
|
if (this.row <= elem.maxIndex) {
|
|
elem.isInserted = true;
|
|
this.toInsert.push(elem.col);
|
|
}
|
|
this.r1Index++;
|
|
}
|
|
while (this.r2Index < this.r2.length && this.row > this.r2[this.r2Index].maxIndex) {
|
|
let elem = this.r2[this.r2Index];
|
|
if (elem.isInserted) {
|
|
this.toDelete.push(elem.col);
|
|
}
|
|
this.r2Index++;
|
|
}
|
|
}
|
|
SweepLineRowIterator.prototype.nextCol = function () {
|
|
this.col = -1;
|
|
this.colData = null;
|
|
if (this.colDatasIndex < this.colDatasCol.length) {
|
|
this.col = this.colDatasCol[this.colDatasIndex];
|
|
this.colData = this.colDatas[this.colDatasIndex];
|
|
this.colDatasIndex++;
|
|
//delete
|
|
let toDeleteOld = this.toDeleteIndex;
|
|
while (this.toDeleteIndex < this.toDelete.length && this.toDelete[this.toDeleteIndex] === this.col) {
|
|
this.toDeleteIndex++;
|
|
if (this.colDatasIndex < this.colDatasCol.length) {
|
|
this.col = this.colDatasCol[this.colDatasIndex];
|
|
this.colData = this.colDatas[this.colDatasIndex];
|
|
this.colDatasIndex++;
|
|
} else {
|
|
this.col = -1;
|
|
this.colData = undefined;
|
|
}
|
|
}
|
|
if (toDeleteOld !== this.toDeleteIndex) {
|
|
let deleteCount = this.toDeleteIndex - toDeleteOld;
|
|
this.colDatasIndex -= -1 === this.col ? deleteCount : deleteCount + 1;
|
|
this.colDatas.splice(this.colDatasIndex, deleteCount);
|
|
this.colDatasCol.splice(this.colDatasIndex, deleteCount);
|
|
if (this.colDatasIndex < this.colDatasCol.length) {
|
|
this.col = this.colDatasCol[this.colDatasIndex];
|
|
this.colData = this.colDatas[this.colDatasIndex];
|
|
this.colDatasIndex++;
|
|
} else {
|
|
this.col = -1;
|
|
this.colData = undefined;
|
|
}
|
|
}
|
|
}
|
|
//insert
|
|
let toInsertOld = this.toInsertIndex;
|
|
if (-1 !== this.col) {
|
|
while (this.toInsertIndex < this.toInsert.length && this.toInsert[this.toInsertIndex] < this.col) {
|
|
this.toInsertIndex++;
|
|
}
|
|
} else {
|
|
this.toInsertIndex = this.toInsert.length;
|
|
}
|
|
if (toInsertOld !== this.toInsertIndex) {
|
|
let cols = [];
|
|
let datas = [];
|
|
for (let i = toInsertOld; i < this.toInsertIndex; ++i) {
|
|
let curCol = this.toInsert[i];
|
|
let colData = this.cellsByCol[curCol];
|
|
if (colData && this.row <= colData.getMaxIndex()) {
|
|
cols.push(curCol);
|
|
datas.push(colData);
|
|
}
|
|
}
|
|
if (-1 !== this.col) {
|
|
this.colDatasIndex--;
|
|
}
|
|
this.colDatas.splice.apply(this.colDatas, [this.colDatasIndex, 0].concat(datas));
|
|
this.colDatasCol.splice.apply(this.colDatasCol, [this.colDatasIndex, 0].concat(cols));
|
|
|
|
if (this.colDatasIndex < this.colDatasCol.length) {
|
|
this.col = this.colDatasCol[this.colDatasIndex];
|
|
this.colData = this.colDatas[this.colDatasIndex];
|
|
this.colDatasIndex++;
|
|
} else {
|
|
this.col = -1;
|
|
this.colData = undefined;
|
|
}
|
|
}
|
|
return -1 !== this.col;
|
|
};
|
|
|
|
function RowIterator() {
|
|
}
|
|
|
|
RowIterator.prototype.init = function (ws, r1, c1, c2) {
|
|
this.ws = ws;
|
|
this.cell = new Cell(ws);
|
|
this.ws.workbook.loadCells.push(this.cell);
|
|
|
|
this.iter = new SweepLineRowIterator();
|
|
this.iter.init(ws.cellsByCol, r1, c1, c2);
|
|
};
|
|
RowIterator.prototype.release = function () {
|
|
this.cell.saveContent(true);
|
|
this.ws.workbook.loadCells.pop();
|
|
};
|
|
RowIterator.prototype.setRow = function (index) {
|
|
this.iter.setRow(index);
|
|
};
|
|
RowIterator.prototype.next = function () {
|
|
var wb = this.ws.workbook;
|
|
this.cell.saveContent(true);
|
|
while (this.iter.nextCol()) {
|
|
var nRow = this.iter.row;
|
|
var nCol = this.iter.col;
|
|
var colData = this.iter.colData;
|
|
var targetCell = null;
|
|
for (var k = 0; k < wb.loadCells.length - 1; ++k) {
|
|
var elem = wb.loadCells[k];
|
|
if (elem.nRow === nRow && elem.nCol === nCol && this.ws === elem.ws) {
|
|
targetCell = elem;
|
|
break;
|
|
}
|
|
}
|
|
if (null === targetCell) {
|
|
if (this.cell.loadContent(nRow, nCol, colData)) {
|
|
return this.cell;
|
|
}
|
|
} else {
|
|
return targetCell;
|
|
}
|
|
}
|
|
};
|
|
//-------------------------------------------------------------------------------------------------
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function PromoteHelper(bVerical, bReverse, bbox){
|
|
//автозаполнение происходит всегда в правую сторону, поэтому менются индексы в методе add, и это надо учитывать при вызове getNext
|
|
this.bVerical = bVerical;
|
|
this.bReverse = bReverse;
|
|
this.bbox = bbox;
|
|
this.oDataRow = {};
|
|
//для get
|
|
this.oCurRow = null;
|
|
this.nCurColIndex = null;
|
|
this.nRowLength = 0;
|
|
this.nColLength = 0;
|
|
if(this.bVerical)
|
|
{
|
|
this.nRowLength = this.bbox.c2 - this.bbox.c1 + 1;
|
|
this.nColLength = this.bbox.r2 - this.bbox.r1 + 1;
|
|
}
|
|
else
|
|
{
|
|
this.nRowLength = this.bbox.r2 - this.bbox.r1 + 1;
|
|
this.nColLength = this.bbox.c2 - this.bbox.c1 + 1;
|
|
}
|
|
// Attributes for work with context menu of autofill.
|
|
this.bFillHandleRightClick = false;
|
|
this.nFillMenuChosenProp = null;
|
|
this.nLastDayInMonth = null;
|
|
this.nDaysInYear = null;
|
|
this.nPrevDateValue = null;
|
|
this.nPrevIntDateValue = null;
|
|
this.bDiffDirectionDateTime = null;
|
|
this.nCurrentDayValue = null; // Using for Date & Time format for month step mode when day changed.
|
|
|
|
this.bOneSelectedCell = false;
|
|
}
|
|
PromoteHelper.prototype = {
|
|
add: function(nRow, nCol, nVal, bDelimiter, sPrefix, padding, bDate, oAdditional, aTimePeriods){
|
|
if(this.bVerical) {
|
|
//транспонируем для удобства
|
|
var temp = nRow;
|
|
nRow = nCol;
|
|
nCol = temp;
|
|
}
|
|
if(this.bReverse)
|
|
nCol = this.nColLength - nCol - 1;
|
|
var row = this.oDataRow[nRow];
|
|
if(null == row) {
|
|
row = {};
|
|
this.oDataRow[nRow] = row;
|
|
}
|
|
row[nCol] = new cDataRow(nCol, nVal, bDelimiter, sPrefix, padding, bDate, oAdditional, aTimePeriods);
|
|
// Checking Date format has Date & Time
|
|
if (bDate && oAdditional.xfs && oAdditional.xfs.num && oAdditional.xfs.num.getFormat()) {
|
|
let oNumFormat = oNumFormatCache.get(oAdditional.xfs.num.getFormat());
|
|
if (oNumFormat.isTimeFormat() && oNumFormat.isDateFormat()) {
|
|
row[nCol].setIsDateTime(true);
|
|
} else if (oNumFormat.isTimeFormat() && !oNumFormat.isDateFormat()) {
|
|
row[nCol].setIsTime(true);
|
|
}
|
|
}
|
|
row[nCol].setStartValue(nVal);
|
|
},
|
|
isOnlyIntegerSequence: function(){
|
|
var bRes = true;
|
|
var bEmpty = true;
|
|
for(var i in this.oDataRow) {
|
|
var row = this.oDataRow[i];
|
|
for(var j in row) {
|
|
var data = row[j];
|
|
bEmpty = false;
|
|
if(!(null != data.getVal() && true != data.getIsDate() && null == data.getPrefix())) {
|
|
bRes = false;
|
|
break;
|
|
}
|
|
}
|
|
if(!bRes)
|
|
break;
|
|
}
|
|
if(bEmpty)
|
|
bRes = false;
|
|
return bRes;
|
|
},
|
|
_promoteSequence: function(aDigits){
|
|
// Это коэффициенты линейного приближения (http://office.microsoft.com/ru-ru/excel-help/HP010072685.aspx)
|
|
// y=a1*x+a0 (где: x=0,1....; y=значения в ячейках; a0 и a1 - это решения приближения функции методом наименьших квадратов
|
|
// (n+1)*a0 + (x0+x1+....) *a1=(y0+y1+...)
|
|
// (x0+x1+....)*a0 + (x0*x0+x1*x1+....)*a1=(y0*x0+y1*x1+...)
|
|
// http://www.exponenta.ru/educat/class/courses/vvm/theme_7/theory.asp
|
|
var a0 = 0.0;
|
|
var a1 = 0.0;
|
|
// Индекс X
|
|
var nX = 0;
|
|
if(1 == aDigits.length)
|
|
{
|
|
nX = 1;
|
|
a1 = 1;
|
|
a0 = aDigits[0].y;
|
|
}
|
|
else
|
|
{
|
|
// (n+1)
|
|
var nN = aDigits.length;
|
|
// (x0+x1+....)
|
|
var nXi = 0;
|
|
// (x0*x0+x1*x1+....)
|
|
var nXiXi = 0;
|
|
// (y0+y1+...)
|
|
var dYi = 0.0;
|
|
// (y0*x0+y1*x1+...)
|
|
var dYiXi = 0.0;
|
|
|
|
// Цикл по всем строкам
|
|
for (var i = 0, length = aDigits.length; i < length; ++i)
|
|
{
|
|
var data = aDigits[i];
|
|
nX = data.x;
|
|
var dValue = data.y;
|
|
|
|
// Вычисляем значения
|
|
nXi += nX;
|
|
nXiXi += nX * nX;
|
|
dYi += dValue;
|
|
dYiXi += dValue * nX;
|
|
}
|
|
nX++;
|
|
|
|
// Теперь решаем систему уравнений
|
|
// Общий детерминант
|
|
var dD = nN * nXiXi - nXi * nXi;
|
|
// Детерминант первого корня
|
|
var dD1 = dYi * nXiXi - nXi * dYiXi;
|
|
// Детерминант второго корня
|
|
var dD2 = nN * dYiXi - dYi * nXi;
|
|
|
|
a0 = dD1 / dD;
|
|
a1 = dD2 / dD;
|
|
}
|
|
return {a0: a0, a1: a1, nX: nX};
|
|
},
|
|
_addSequenceToRow : function(nRowIndex, aSortRowIndex, row, aCurSequence){
|
|
if(aCurSequence.length > 0) {
|
|
var oFirstData = aCurSequence[0];
|
|
var bCanPromote = true;
|
|
const bFillHandleRightClick = this.getFillHandleRightClick();
|
|
//если последовательность состоит из одного числа и той же колонке есть еще последовательности, то надо копировать, а не автозаполнять
|
|
if(aCurSequence.length === 1 && !bFillHandleRightClick) {
|
|
var bVisitRowIndex = false;
|
|
var oVisitData = null;
|
|
for(var i = 0, length = aSortRowIndex.length; i < length; i++) {
|
|
var nCurRowIndex = aSortRowIndex[i];
|
|
if(nRowIndex == nCurRowIndex) {
|
|
bVisitRowIndex = true;
|
|
if(oVisitData && oFirstData.prefixDataCompare(oVisitData)) {
|
|
bCanPromote = false;
|
|
break;
|
|
}
|
|
} else {
|
|
var oCurRow = this.oDataRow[nCurRowIndex];
|
|
if(oCurRow) {
|
|
var data = oCurRow[oFirstData.getCol()];
|
|
if(null != data) {
|
|
if(null != data.getVal()) {
|
|
oVisitData = data;
|
|
if(bVisitRowIndex) {
|
|
if(oFirstData.prefixDataCompare(oVisitData))
|
|
bCanPromote = false;
|
|
break;
|
|
}
|
|
}
|
|
else if(data.getDelimiter()) {
|
|
oVisitData = null;
|
|
if(bVisitRowIndex)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(bCanPromote) {
|
|
var nMinIndex = null;
|
|
var nMaxIndex = null;
|
|
var bValidIndexDif = true;
|
|
var nPrevX = null;
|
|
var nPrevVal = null;
|
|
var nIndexDif = null;
|
|
var nValueDif = null;
|
|
var nMaxPadding = 0;
|
|
//анализируем последовательность, если числа расположены не на одинаковом расстоянии, то считаем их сплошной последовательностью
|
|
//последовательность с промежутками может быть только целочисленной
|
|
for(let i = 0, length = aCurSequence.length; i < length; i++) {
|
|
var data = aCurSequence[i];
|
|
var nCurX = data.getCol();
|
|
let nCurVal = data.getVal();
|
|
if(null == nMinIndex || null == nMaxIndex)
|
|
nMinIndex = nMaxIndex = nCurX;
|
|
else {
|
|
if(nCurX < nMinIndex)
|
|
nMinIndex = nCurX;
|
|
if(nCurX > nMaxIndex)
|
|
nMaxIndex = nCurX;
|
|
}
|
|
if(bValidIndexDif) {
|
|
if(null != nPrevX && null != nPrevVal) {
|
|
var nCurDif = nCurX - nPrevX;
|
|
var nCurValDif = nCurVal - nPrevVal;
|
|
if(null == nIndexDif || null == nCurValDif) {
|
|
nIndexDif = nCurDif;
|
|
nValueDif = nCurValDif;
|
|
}
|
|
else if(nIndexDif != nCurDif || nValueDif != nCurValDif) {
|
|
nIndexDif = null;
|
|
bValidIndexDif = false;
|
|
}
|
|
}
|
|
}
|
|
nMaxPadding = Math.max(nMaxPadding, data.getPadding());
|
|
nPrevX = nCurX;
|
|
nPrevVal = nCurVal;
|
|
}
|
|
var bWithSpace = false;
|
|
if(null != nIndexDif) {
|
|
nIndexDif = Math.abs(nIndexDif);
|
|
if(nIndexDif > 1)
|
|
bWithSpace = true;
|
|
}
|
|
//заполняем массив с координатами
|
|
var bExistSpace = false;
|
|
nPrevX = null;
|
|
var aDigits = [];
|
|
for (let i = 0, length = aCurSequence.length; i < length; i++) {
|
|
var data = aCurSequence[i];
|
|
data.setPadding(nMaxPadding);
|
|
var nCurX = data.getCol();
|
|
var x = nCurX - nMinIndex;
|
|
if(null != nIndexDif && nIndexDif > 0)
|
|
x /= nIndexDif;
|
|
if(null != nPrevX && nCurX - nPrevX > 1)
|
|
bExistSpace = true;
|
|
var y = data.getVal();
|
|
//даты автозаполняем только по целой части
|
|
if(data.getIsDate() && !data.getIsDateTime() && !data.getIsMixedDateFormat() && !data.getIsTime()) {
|
|
y = parseInt(y);
|
|
}
|
|
aDigits.push({x: x, y: y});
|
|
nPrevX = nCurX;
|
|
}
|
|
if(aDigits.length > 0) {
|
|
let bMixedDateFormat = oFirstData.getIsMixedDateFormat();
|
|
let bTime = oFirstData.getIsTime();
|
|
let bDate = oFirstData.getIsDate();
|
|
let bDateTime = oFirstData.getIsDateTime();
|
|
let oSequence = null;
|
|
const aMenuPropsForDate = [oFillType.fillMonths, oFillType.fillYears];
|
|
|
|
// For activating month or year calculate mode in default autofill. Using for data of date format.
|
|
if (bDate && this.getFillMenuChosenProp() === oFillType.fillSeries) {
|
|
this.setFillMenuChosenProp(null);
|
|
}
|
|
if (this.getFillMenuChosenProp() == null && bDate && aDigits.length > 1) {
|
|
this.initFillMenuChosenProp(aDigits, oFirstData.getVal());
|
|
}
|
|
let nMenuChosenProp = this.getFillMenuChosenProp();
|
|
let bIsCalcDateMode = bDate && nMenuChosenProp != null && aMenuPropsForDate.includes(nMenuChosenProp);
|
|
if (bDate && nMenuChosenProp != null) {
|
|
let nLastValFromRange = aDigits[aDigits.length - 1].y;
|
|
this.setPrevDateValue(nLastValFromRange);
|
|
this.setPrevIntDateValue(nLastValFromRange);
|
|
}
|
|
if (bMixedDateFormat || (bIsCalcDateMode && bDateTime && aDigits.length > 2)) {
|
|
/* In a mixed date format, the promotion sequence should be calculated similarly to the Date format.
|
|
But, the original array should be saved to use the time portion of the cell with the Date & Time format
|
|
as a constant value for the correct sequence. */
|
|
let aIntDigits = aDigits.map(function (elem) {
|
|
return {x: elem.x, y: parseInt(elem.y)};
|
|
});
|
|
oSequence = this._promoteSequence(aIntDigits);
|
|
} else {
|
|
oSequence = this._promoteSequence(aDigits);
|
|
}
|
|
if (aDigits.length === 1) {
|
|
this.setIsOneSelectedCell(true);
|
|
if (bTime) {
|
|
// For one selected cell, step for Time format must be 1 hour.
|
|
// The time component of a serial value increases by 1/86,400 each second.
|
|
oSequence.a1 = (1 / 86400) * 3600;
|
|
}
|
|
if (this.bReverse) {
|
|
//меняем коэффициенты для случая одного числа в последовательности, иначе она в любую сторону будет возрастающей
|
|
oSequence.a1 *= -1;
|
|
if (bTime && oSequence.a0 === 0) {
|
|
oSequence.a0 = 1;
|
|
}
|
|
}
|
|
}
|
|
if (aDigits.length === 2 && bDateTime) {
|
|
this.initDiffDirectionDateTime(aDigits);
|
|
}
|
|
//для дат и чисел с префиксом автозаполняются только целочисленные последовательности
|
|
let nFirstVal = oFirstData.getVal();
|
|
let bIsNotIntegerSequence = oSequence.a1 !== parseInt(oSequence.a1);
|
|
let bDateCalcModeHasDiffDay = aDigits.length > 1 && bIsCalcDateMode && this.isDiffDaysForCalcMode(aDigits, nFirstVal);
|
|
let bDateCalcModeCorrectSeq = bIsCalcDateMode && !bDateCalcModeHasDiffDay && parseInt(nFirstVal) === Math.round(oSequence.a0);
|
|
let sPrefix = oFirstData.getPrefix();
|
|
let bDelimiter = oFirstData.getDelimiter();
|
|
// For Date format
|
|
let bStepForDateIsZero = bDate && oSequence.a1 === 0;
|
|
let bIntStartValue = bDate && oSequence.a0 === parseInt(oSequence.a0);
|
|
// For Date & Time format
|
|
let bDayOfDateDiff = aDigits.length > 1 ? Math.floor(aDigits[0].y) !== Math.floor(aDigits[1].y) : true;
|
|
let bDateTimeSeqIsCorrect = aDigits[0].y.toFixed(3) === oSequence.a0.toFixed(3);
|
|
// If Date & Time format hasn't diff in days of date, but sequence by time is not correct we use step = 0
|
|
// and start sequence point is equal first element of aDigits or for reverse sequence the last element of aDigit.
|
|
if (bDateTime && !bDayOfDateDiff && !bDateTimeSeqIsCorrect && (oSequence.a1 < 1 && oSequence.a1 > -1)) {
|
|
oSequence.a0 = this.bReverse ? aDigits[aDigits.length - 1].y : aDigits[0].y;
|
|
oSequence.a1 = parseInt(oSequence.a1);
|
|
}
|
|
if (bMixedDateFormat || (bIsCalcDateMode && bDateTime && aDigits.length > 2)) {
|
|
// The start element needs to add part of the time from the first (or last for reverse sequences) cell
|
|
// with Date & Time format from the selected range.
|
|
let aDigitsWithDateTime = aDigits.filter(function(item) {
|
|
return item.y !== parseInt(item.y);
|
|
});
|
|
let nDateTimeVal = this.bReverse ? aDigitsWithDateTime[aDigitsWithDateTime.length - 1].y : aDigitsWithDateTime[0].y;
|
|
let nTimePart = nDateTimeVal - parseInt(nDateTimeVal);
|
|
oSequence.a0 = parseInt(oSequence.a0) + nTimePart;
|
|
}
|
|
if (bTime && bDayOfDateDiff && aDigits.length > 1) {
|
|
if (this.bReverse && aDigits[0].y - aDigits[aDigits.length - 1].y >= 1) {
|
|
let nDateVal = parseInt(aDigits[aDigits.length - 1].y)
|
|
oSequence.a0 = (oSequence.a0 - parseInt(oSequence.a0)) + nDateVal;
|
|
}
|
|
oSequence.a1 = oSequence.a1 - parseInt(oSequence.a1);
|
|
}
|
|
if(!((sPrefix != null || (bDate && !bDateTime && !bMixedDateFormat && !bTime)) && bIsNotIntegerSequence && !bDateCalcModeCorrectSeq)) {
|
|
// If for Date or Date & Time format the sequence is not correct or sequence step is 0, skip work with oSequence
|
|
if (bDate) {
|
|
if (bStepForDateIsZero && !bDateTime && !bMixedDateFormat) {
|
|
return;
|
|
}
|
|
if (!bIntStartValue && !bDateCalcModeCorrectSeq && !bDateTime && !bTime) {
|
|
return;
|
|
}
|
|
if (bDateTime && bDayOfDateDiff && !bDateTimeSeqIsCorrect && !bDateCalcModeCorrectSeq) {
|
|
return;
|
|
}
|
|
}
|
|
if(!bWithSpace && bExistSpace) {
|
|
for (let i = nMinIndex; i <= nMaxIndex; i++) {
|
|
var data = row[i];
|
|
if(null == data) {
|
|
data = new cDataRow(i, null, bDelimiter, sPrefix, null, bDate);
|
|
row[i] = data;
|
|
}
|
|
data.setSequence(oSequence);
|
|
}
|
|
}
|
|
else {
|
|
for(let i = 0, length = aCurSequence.length; i < length; i++) {
|
|
var nCurX = aCurSequence[i].nCol;
|
|
if(null != nCurX)
|
|
row[nCurX].setSequence(oSequence);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
finishAdd : function(bCopy) {
|
|
if(true != bCopy) {
|
|
var aSortRowIndex = [];
|
|
for(var i in this.oDataRow)
|
|
aSortRowIndex.push(i - 0);
|
|
aSortRowIndex.sort(fSortAscending);
|
|
for(var i = 0, length = aSortRowIndex.length; i < length; i++) {
|
|
var nRowIndex = aSortRowIndex[i];
|
|
var row = this.oDataRow[nRowIndex];
|
|
//собираем информация о последовательностях в row
|
|
var aSortIndex = [];
|
|
for(var j in row)
|
|
aSortIndex.push(j - 0);
|
|
aSortIndex.sort(fSortAscending);
|
|
var aCurSequence = [];
|
|
var oPrevRowData = null;
|
|
for(var j = 0, length2 = aSortIndex.length; j < length2; j++) {
|
|
var nColIndex = aSortIndex[j];
|
|
var rowData = row[nColIndex];
|
|
let rowDataNext = nColIndex + 1 < length2 && row[nColIndex + 1];
|
|
let bDate = rowData.getIsDate();
|
|
let bDateTime = rowData.getIsDateTime();
|
|
let bDateNextRow = rowDataNext && rowDataNext.getIsDate();
|
|
let bDateTimeNextRow = rowDataNext && rowDataNext.getIsDateTime();
|
|
if ((bDate && bDateTime && bDateNextRow && !bDateTimeNextRow) || (bDate && !bDateTime && bDateNextRow && bDateTimeNextRow)) {
|
|
let nFirstColIndex = aSortIndex[0];
|
|
let oFirstRowData = row[nFirstColIndex];
|
|
oFirstRowData.setIsMixedDateFormat(true);
|
|
oFirstRowData.setIsDateTime(false);
|
|
if (rowDataNext) {
|
|
rowDataNext.setIsMixedDateFormat(true);
|
|
rowDataNext.setIsDateTime(false);
|
|
}
|
|
}
|
|
var bAddToSequence = false;
|
|
let nVal = rowData.getVal();
|
|
let bDelimiter = rowData.getDelimiter();
|
|
if(null != nVal) {
|
|
bAddToSequence = true;
|
|
if(null != oPrevRowData && !rowData.compare(oPrevRowData)) {
|
|
this._addSequenceToRow(nRowIndex, aSortRowIndex, row, aCurSequence);
|
|
aCurSequence = [];
|
|
oPrevRowData = null;
|
|
}
|
|
oPrevRowData = rowData;
|
|
}
|
|
else if(bDelimiter) {
|
|
this._addSequenceToRow(nRowIndex, aSortRowIndex, row, aCurSequence);
|
|
aCurSequence = [];
|
|
oPrevRowData = null;
|
|
}
|
|
if(bAddToSequence)
|
|
aCurSequence.push(rowData);
|
|
}
|
|
this._addSequenceToRow(nRowIndex, aSortRowIndex, row, aCurSequence);
|
|
}
|
|
}
|
|
},
|
|
setIndex: function(index){
|
|
if(0 != this.nRowLength && index >= this.nRowLength)
|
|
index = index % (this.nRowLength);
|
|
this.oCurRow = this.oDataRow[index];
|
|
this.nCurColIndex = 0;
|
|
},
|
|
getNext: function() {
|
|
let oRes = null;
|
|
if(this.oCurRow) {
|
|
oRes = this.oCurRow[this.nCurColIndex];
|
|
if(oRes != null) {
|
|
oRes.setCurValue(null);
|
|
if(oRes.getSequence() != null) {
|
|
let sequence = oRes.getSequence();
|
|
// Define modes fill: "By Month", " By Week" or "By Years" for values in Date format.
|
|
let nFillMenuChosenProp = this.getFillMenuChosenProp();
|
|
const aMenuPropsForDate = [oFillType.fillWeekdays, oFillType.fillMonths, oFillType.fillYears];
|
|
if(oRes.getPrefix() != null) {
|
|
oRes.setCurValue(Math.abs(sequence.a1 * sequence.nX + sequence.a0));
|
|
} else if (oRes.getIsDate() && !oRes.getTimePeriods()) {
|
|
let nCurValue;
|
|
if (nFillMenuChosenProp && aMenuPropsForDate.includes(nFillMenuChosenProp)) {
|
|
nCurValue = this.calculateDate(oRes);
|
|
} else {
|
|
nCurValue = sequence.a1 * sequence.nX + sequence.a0;
|
|
}
|
|
if (nCurValue >= 0 || (oRes.getIsDateTime() && parseInt(sequence.a1) !== sequence.a1 && sequence.a1 > -1)) {
|
|
oRes.setCurValue(nCurValue);
|
|
} else if (oRes.getIsTime() && nCurValue < 0) {
|
|
// Reset nX and start from beginning
|
|
sequence.nX = this.getIsOneSelectedCell() ? 1 : 0;
|
|
oRes.setCurValue(sequence.a1 * sequence.nX + sequence.a0);
|
|
}
|
|
} else {
|
|
oRes.setCurValue(sequence.a1 * sequence.nX + sequence.a0);
|
|
}
|
|
sequence.nX++;
|
|
}
|
|
}
|
|
this.nCurColIndex++;
|
|
if(this.nCurColIndex >= this.nColLength)
|
|
this.nCurColIndex = 0;
|
|
}
|
|
return oRes;
|
|
},
|
|
getFillHandleRightClick: function () {
|
|
return this.bFillHandleRightClick;
|
|
},
|
|
setFillHandleRightClick: function (bFillHandleRightClick) {
|
|
this.bFillHandleRightClick = bFillHandleRightClick;
|
|
},
|
|
/**
|
|
* Returns chosen property from context menu.
|
|
* @returns {Asc.c_oAscFillType}
|
|
*/
|
|
getFillMenuChosenProp: function () {
|
|
return this.nFillMenuChosenProp;
|
|
},
|
|
/**
|
|
* Sets chosen property from context menu.
|
|
* @param {Asc.c_oAscFillType} nFillMenuChosenProp
|
|
*/
|
|
setFillMenuChosenProp: function (nFillMenuChosenProp) {
|
|
this.nFillMenuChosenProp = nFillMenuChosenProp;
|
|
},
|
|
/**
|
|
* Returns the last day of a month.
|
|
* @returns {number}
|
|
*/
|
|
getLastDayOfMonth: function () {
|
|
return this.nLastDayInMonth;
|
|
},
|
|
/**
|
|
* Sets the last day of a month taken from ExcelDateValue.
|
|
* @param {number} nExcelDateValue
|
|
*/
|
|
setLastDayOfMonth: function (nExcelDateValue) {
|
|
const CURRENT_MONTH = 0;
|
|
let dtLastDayInMonth = AscCommonExcel.getLastDayInMonth(nExcelDateValue, CURRENT_MONTH);
|
|
|
|
this.nLastDayInMonth = dtLastDayInMonth.getDate();
|
|
},
|
|
/**
|
|
* Returns days in year.
|
|
* @returns {number}
|
|
*/
|
|
getDaysInYear: function () {
|
|
return this.nDaysInYear;
|
|
},
|
|
/**
|
|
* Sets days in year taken from ExcelDateValue.
|
|
* @param {number} nExcelDateValue
|
|
*/
|
|
setDaysInYear: function (nExcelDateValue) {
|
|
const oDayCountBasis = AscCommonExcel.DayCountBasis;
|
|
|
|
this.nDaysInYear = AscCommonExcel.daysInYear(nExcelDateValue, oDayCountBasis.ActualActual).getValue();
|
|
},
|
|
/**
|
|
* Returns previous date value while calculating for modes: "Fill months", "Fill years" and "Fill weekdays".
|
|
* @returns {number}
|
|
*/
|
|
getPrevDateValue: function () {
|
|
return this.nPrevDateValue;
|
|
},
|
|
/**
|
|
* Sets previous date value while calculating for modes: "Fill months", "Fill years" and "Fill weekdays".
|
|
* @param {number} nPrevDateValue
|
|
*/
|
|
setPrevDateValue: function (nPrevDateValue) {
|
|
this.nPrevDateValue = nPrevDateValue;
|
|
},
|
|
/**
|
|
* Returns previous integer date value while calculating for modes: "Fill months", "Fill years".
|
|
* Using when step is fractional number.
|
|
* @returns {number}
|
|
*/
|
|
getPrevIntDateValue: function () {
|
|
return this.nPrevIntDateValue;
|
|
},
|
|
/**
|
|
* Sets previous integer date value while calculating for modes: "Fill months", "Fill years".
|
|
* Using when step is fractional number.
|
|
* @param {number} nPrevIntDateValue
|
|
*/
|
|
setPrevIntDateValue: function (nPrevIntDateValue) {
|
|
this.nPrevIntDateValue = nPrevIntDateValue;
|
|
},
|
|
/**
|
|
* Returns the current state of the flag recognizing different direction at date and time.
|
|
* @returns {boolean}
|
|
*/
|
|
getIsDiffDirectionDateTime: function () {
|
|
return this.bDiffDirectionDateTime;
|
|
},
|
|
/**
|
|
* Sets the current state of the flag recognizing different direction at date and time.
|
|
* @param {boolean} bDiffDirectionDateTime
|
|
*/
|
|
setIsDiffDirectionDateTime: function (bDiffDirectionDateTime) {
|
|
this.bDiffDirectionDateTime = bDiffDirectionDateTime;
|
|
},
|
|
/**
|
|
* Returns current day value for Date & Time format.
|
|
* Using for month step mode when day changed.
|
|
* @returns {number}
|
|
*/
|
|
getCurrentDayValue: function () {
|
|
return this.nCurrentDayValue;
|
|
},
|
|
/**
|
|
* Sets current day value for Date & Time format.
|
|
* Using for month step mode when day changed.
|
|
* @param {number} nCurrentDayValue
|
|
*/
|
|
setCurrentDayValue: function (nCurrentDayValue) {
|
|
this.nCurrentDayValue = nCurrentDayValue;
|
|
},
|
|
/**
|
|
* Initializes flag recognizing that date and time have different direction between each other.
|
|
* true - date and time have different direction.
|
|
* false - date and time have same direction
|
|
* @param {{x:number, y:number}[]} aDigits
|
|
*/
|
|
initDiffDirectionDateTime: function (aDigits) {
|
|
let nFirstValueTimePart = aDigits[0].y - parseInt(aDigits[0].y);
|
|
let nSecondValueTimePart = aDigits[1].y - parseInt(aDigits[1].y);
|
|
let nFirstValueDatePart = parseInt(aDigits[0].y);
|
|
let nSecondValueDatePart = parseInt(aDigits[1].y);
|
|
let bAscTimePart = nSecondValueTimePart > nFirstValueTimePart;
|
|
let bAscDatePart = nSecondValueDatePart > nFirstValueDatePart;
|
|
|
|
this.setIsDiffDirectionDateTime(bAscTimePart !== bAscDatePart);
|
|
},
|
|
/**
|
|
* Initializes property of autofill context menu if in default autofill, has the required step to needed mode.
|
|
* Modes: "Fill months", "Fill years".
|
|
* @param {{x:number, y:number}[]} aDigits
|
|
* @param {number} nFirstValue
|
|
*/
|
|
initFillMenuChosenProp: function (aDigits, nFirstValue) {
|
|
const SECOND_VALUE_INDEX = 1;
|
|
const oFillType = Asc.c_oAscFillType;
|
|
const nSecondValue = aDigits[SECOND_VALUE_INDEX].y;
|
|
const dtFirstValue = new Asc.cDate().getDateFromExcel(nFirstValue < 60 ? nFirstValue + 1 : nFirstValue);
|
|
const dtSecondValue = new Asc.cDate().getDateFromExcel(nSecondValue < 60 ? nSecondValue + 1 : nSecondValue);
|
|
|
|
let nDayFirstValue = dtFirstValue.getDate();
|
|
let nMonthFirstValue = dtFirstValue.getMonth();
|
|
let nYearFirstValue = dtFirstValue.getFullYear();
|
|
|
|
let nDaySecondValue = dtSecondValue.getDate();
|
|
let nMonthSecondValue = dtSecondValue.getMonth();
|
|
let nYearSecondValue = dtSecondValue.getFullYear();
|
|
|
|
if (nDayFirstValue === nDaySecondValue && nMonthFirstValue !== nMonthSecondValue) {
|
|
this.setFillMenuChosenProp(oFillType.fillMonths);
|
|
} else if (nDayFirstValue === nDaySecondValue && nMonthFirstValue === nMonthSecondValue && nYearFirstValue !== nYearSecondValue) {
|
|
this.setFillMenuChosenProp(oFillType.fillYears);
|
|
}
|
|
},
|
|
/**
|
|
* Checks has different days in the date of the selected range for date calculate modes from the context menu.
|
|
* Applies for modes : "Fill months", "Fill years".
|
|
* @param {{x:number, y:number}[]} aDigits
|
|
* @param {number} nFirstValue
|
|
* @returns {boolean}
|
|
*/
|
|
isDiffDaysForCalcMode: function (aDigits, nFirstValue) {
|
|
const SECOND_VALUE_INDEX = 1;
|
|
const nSecondValue = aDigits[SECOND_VALUE_INDEX].y;
|
|
const dtFirstValue = new Asc.cDate().getDateFromExcel(nFirstValue < 60 ? nFirstValue + 1 : nFirstValue);
|
|
const dtSecondValue = new Asc.cDate().getDateFromExcel(nSecondValue < 60 ? nSecondValue + 1 : nSecondValue);
|
|
|
|
return dtFirstValue.getDate() !== dtSecondValue.getDate();
|
|
},
|
|
/**
|
|
* Calculates date based on step and modes: "Fill months", "Fill years" or "Fill weekdays".
|
|
* @param {cDataRow} oDataRow
|
|
* @returns {number}
|
|
*/
|
|
calculateDate: function (oDataRow) {
|
|
const DEFAULT_STEP = this.bReverse ? -1 : 1;
|
|
const oSequence = oDataRow.getSequence();
|
|
const nChosenMenuItem = this.getFillMenuChosenProp();
|
|
let nStep = null;
|
|
let nStepDivider = null;
|
|
let nUnitDate = null;
|
|
// Flag for "Fill Month" and "Fill years". If the step is less than the last day of the month or days in the year,
|
|
// we change nVal of DataRow and work with it as previous value for every cell of selected range.
|
|
let bUseValFromDataRow = false;
|
|
|
|
// Find last day of month and days in year for correct work with month and year mode.
|
|
if (this.getLastDayOfMonth() == null && this.getDaysInYear() == null) {
|
|
let nFirstVal = oDataRow.getVal();
|
|
this.setLastDayOfMonth(nFirstVal);
|
|
this.setDaysInYear(nFirstVal);
|
|
}
|
|
switch (nChosenMenuItem) {
|
|
case Asc.c_oAscFillType.fillWeekdays:
|
|
nUnitDate = oSeriesDateUnitType.weekday;
|
|
nStepDivider = 1;
|
|
break;
|
|
case Asc.c_oAscFillType.fillMonths:
|
|
nUnitDate = oSeriesDateUnitType.month
|
|
nStepDivider = this.getLastDayOfMonth();
|
|
break;
|
|
case Asc.c_oAscFillType.fillYears:
|
|
nUnitDate = oSeriesDateUnitType.year
|
|
nStepDivider = this.getDaysInYear();
|
|
break;
|
|
}
|
|
if (!this.getIsOneSelectedCell() && nChosenMenuItem !== Asc.c_oAscFillType.fillWeekdays) {
|
|
bUseValFromDataRow = Math.abs(oSequence.a1) < nStepDivider;
|
|
}
|
|
if (bUseValFromDataRow) {
|
|
nStep = DEFAULT_STEP;
|
|
const oCellInfo = {
|
|
step: nStep,
|
|
dateUnit: nUnitDate,
|
|
previousValue: oDataRow.getVal(),
|
|
previousIntValue: oDataRow.getVal(),
|
|
expectedDayValue: oDataRow.getStartValue()
|
|
};
|
|
const oResult = _calculateDate(oCellInfo, true);
|
|
oDataRow.setVal(oResult.previousValue);
|
|
|
|
return oResult.currentValue;
|
|
}
|
|
nStep = this.getIsOneSelectedCell() ? oSequence.a1 : Math.round(oSequence.a1 / nStepDivider);
|
|
const oCellInfo = {
|
|
step: nStep,
|
|
dateUnit: nUnitDate,
|
|
previousValue: this.getPrevDateValue(),
|
|
previousIntValue: this.getPrevIntDateValue(),
|
|
expectedDayValue: oDataRow.getVal()
|
|
};
|
|
if (oDataRow.getIsDateTime() && this.nColLength === 2) {
|
|
if (oSequence.nX === this.nColLength) { // For first iteration using element from selected range.
|
|
this.setCurrentDayValue(oDataRow.getVal());
|
|
}
|
|
oCellInfo.expectedDayValue = this.getCurrentDayValue();
|
|
}
|
|
const oResult = _calculateDate(oCellInfo, true);
|
|
let bFloatDate = oDataRow.getIsDateTime() || oDataRow.getIsMixedDateFormat();
|
|
// Logic for time.
|
|
if (bFloatDate && !this.getFillHandleRightClick()) {
|
|
let nTimePart = oSequence.a0 - parseInt(oSequence.a0);
|
|
if (oDataRow.getIsDateTime() && this.nColLength === 2) {
|
|
nTimePart = oCellInfo.previousValue - parseInt(oCellInfo.previousValue);
|
|
nTimePart += (oSequence.a1 - parseInt(oSequence.a1));
|
|
if (this.getIsDiffDirectionDateTime()) {
|
|
if (this.bReverse) {
|
|
if (Math.sign(nTimePart) < 0) {
|
|
nTimePart = nTimePart + 1;
|
|
} else {
|
|
nTimePart += 1;
|
|
}
|
|
} else {
|
|
if (nTimePart > 1) {
|
|
nTimePart -= parseInt(nTimePart);
|
|
} else {
|
|
nTimePart = nTimePart - 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
oResult.previousValue += nTimePart;
|
|
if (oResult.previousIntValue) {
|
|
oResult.previousIntValue += nTimePart;
|
|
if (nTimePart > 1 || Math.sign(nTimePart) < 0) {
|
|
this.setCurrentDayValue(oResult.previousIntValue);
|
|
}
|
|
}
|
|
oResult.currentValue += nTimePart;
|
|
}
|
|
this.setPrevDateValue(oResult.previousValue);
|
|
if (oResult.previousIntValue) {
|
|
this.setPrevIntDateValue(oResult.previousIntValue);
|
|
}
|
|
|
|
return oResult.currentValue;
|
|
},
|
|
/**
|
|
* Returns flag that recognizes it as one selected cell.
|
|
* @returns {boolean}
|
|
*/
|
|
getIsOneSelectedCell: function () {
|
|
return this.bOneSelectedCell;
|
|
},
|
|
/**
|
|
* Sets flag that recognizes it as one selected cell.
|
|
* @param {boolean} bOneSelectedCell
|
|
*/
|
|
setIsOneSelectedCell: function (bOneSelectedCell) {
|
|
this.bOneSelectedCell = bOneSelectedCell;
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
function HiddenManager(ws) {
|
|
this.ws = ws;
|
|
this.hiddenRowsSum = [];
|
|
this.hiddenColsSum = [];
|
|
this.dirty = true;
|
|
this.recalcHiddenRows = {};
|
|
this.recalcHiddenCols = {};
|
|
this.hiddenRowMin = gc_nMaxRow0;
|
|
this.hiddenRowMax = 0;
|
|
}
|
|
HiddenManager.prototype.initPostOpen = function () {
|
|
this.hiddenRowMin = gc_nMaxRow0;
|
|
this.hiddenRowMax = 0;
|
|
};
|
|
HiddenManager.prototype.addHidden = function (isRow, index) {
|
|
(isRow ? this.recalcHiddenRows : this.recalcHiddenCols)[index] = true;
|
|
if (isRow) {
|
|
this.hiddenRowMin = Math.min(this.hiddenRowMin, index);
|
|
this.hiddenRowMax = Math.max(this.hiddenRowMax, index);
|
|
}
|
|
this.setDirty(true);
|
|
};
|
|
HiddenManager.prototype.getRecalcHidden = function () {
|
|
var res = [];
|
|
var i;
|
|
for (i in this.recalcHiddenRows) {
|
|
i = +i;
|
|
res.push(new Asc.Range(0, i, gc_nMaxCol0, i));
|
|
}
|
|
for (i in this.recalcHiddenCols) {
|
|
i = +i;
|
|
res.push(new Asc.Range(i, 0, i, gc_nMaxRow0));
|
|
}
|
|
this.recalcHiddenRows = {};
|
|
this.recalcHiddenCols = {};
|
|
return res;
|
|
};
|
|
HiddenManager.prototype.getHiddenRowsRange = function() {
|
|
var res;
|
|
if (this.hiddenRowMin <= this.hiddenRowMax) {
|
|
res = {r1: this.hiddenRowMin, r2: this.hiddenRowMax};
|
|
this.hiddenRowMin = gc_nMaxRow0;
|
|
this.hiddenRowMax = 0;
|
|
}
|
|
return res;
|
|
};
|
|
HiddenManager.prototype.setDirty = function(val) {
|
|
this.dirty = val;
|
|
};
|
|
HiddenManager.prototype.getHiddenRowsCount = function(from, to) {
|
|
return this._getHiddenCount(true, from, to);
|
|
};
|
|
HiddenManager.prototype.getHiddenColsCount = function(from, to) {
|
|
return this._getHiddenCount(false, from, to);
|
|
};
|
|
HiddenManager.prototype._getHiddenCount = function(isRow, from, to) {
|
|
//todo wrong result if 'to' is hidden
|
|
if (this.dirty) {
|
|
this.dirty = false;
|
|
this._init();
|
|
}
|
|
var hiddenSum = isRow ? this.hiddenRowsSum : this.hiddenColsSum;
|
|
var toCount = to < hiddenSum.length ? hiddenSum[to] : 0;
|
|
var fromCount = from < hiddenSum.length ? hiddenSum[from] : 0;
|
|
return fromCount - toCount;
|
|
};
|
|
HiddenManager.prototype._init = function() {
|
|
if (this.ws) {
|
|
this.hiddenColsSum = this._initHiddenSumCol(this.ws.aCols);
|
|
this.hiddenRowsSum = this._initHiddenSumRow();
|
|
}
|
|
};
|
|
HiddenManager.prototype._initHiddenSumCol = function(elems) {
|
|
var hiddenSum = [];
|
|
if (this.ws) {
|
|
var i;
|
|
var hiddenFlags = [];
|
|
for (i in elems) {
|
|
if (elems.hasOwnProperty(i)) {
|
|
var elem = elems[i];
|
|
if (null != elem && elem.getHidden()) {
|
|
hiddenFlags[i] = 1;
|
|
}
|
|
}
|
|
}
|
|
var sum = 0;
|
|
for (i = hiddenFlags.length - 1; i >= 0; --i) {
|
|
if (hiddenFlags[i] > 0) {
|
|
sum++;
|
|
}
|
|
hiddenSum[i] = sum;
|
|
}
|
|
}
|
|
return hiddenSum;
|
|
};
|
|
HiddenManager.prototype._initHiddenSumRow = function() {
|
|
var hiddenSum = [];
|
|
if (this.ws) {
|
|
var i;
|
|
var hiddenFlags = [];
|
|
this.ws._forEachRow(function(row) {
|
|
if (row.getHidden()) {
|
|
hiddenFlags[row.getIndex()] = 1;
|
|
}
|
|
});
|
|
var sum = 0;
|
|
for (i = hiddenFlags.length - 1; i >= 0; --i) {
|
|
if (hiddenFlags[i] > 0) {
|
|
sum++;
|
|
}
|
|
hiddenSum[i] = sum;
|
|
}
|
|
}
|
|
return hiddenSum;
|
|
};
|
|
|
|
|
|
function tryTranslateToPrintArea(val) {
|
|
const printAreaStr = "Print_Area";
|
|
const printAreaStrLocale = AscCommon.translateManager && AscCommon.translateManager.getValue(printAreaStr);
|
|
if(printAreaStrLocale && printAreaStrLocale.toLowerCase() === val.toLowerCase()) {
|
|
return printAreaStr;
|
|
}
|
|
return null;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------
|
|
/**
|
|
* Class represents data using for calculating a sequence of filling cells in autofill.
|
|
* @constructor
|
|
*/
|
|
function cDataRow(nCol, nVal, bDelimiter, sPrefix, nPadding, bDate, oAdditional, aTimePeriods) {
|
|
this.nCol = nCol;
|
|
this.nVal = nVal;
|
|
this.nStartVal = null;
|
|
this.bDelimiter = bDelimiter;
|
|
this.sPrefix = sPrefix;
|
|
this.nPadding = nPadding;
|
|
this.bDate = bDate;
|
|
this.bDateTime = false;
|
|
this.bTime = false;
|
|
this.bMixedDateFormat = false;
|
|
this.oAdditional = oAdditional;
|
|
this.aTimePeriods = aTimePeriods;
|
|
this.oSequence = null;
|
|
this.nCurValue = null;
|
|
}
|
|
|
|
/**
|
|
* Method returns column number
|
|
* @memberof cDataRow
|
|
* @returns {number}
|
|
*/
|
|
cDataRow.prototype.getCol = function() {
|
|
return this.nCol;
|
|
};
|
|
/**
|
|
* Method returns value of current cell
|
|
* @memberof cDataRow
|
|
* @returns {number}
|
|
*/
|
|
cDataRow.prototype.getVal = function() {
|
|
return this.nVal;
|
|
};
|
|
/**
|
|
* Method sets value of current cell
|
|
* @memberof cDataRow
|
|
* @param {number} nVal
|
|
*/
|
|
cDataRow.prototype.setVal = function(nVal) {
|
|
this.nVal = nVal;
|
|
};
|
|
/**
|
|
* Method returns initial value of current cell.
|
|
* Uses to autofill by context menu for "Fill months", "Fill years".
|
|
* @memberof cDataRow
|
|
* @returns {number}
|
|
*/
|
|
cDataRow.prototype.getStartValue = function() {
|
|
return this.nStartVal;
|
|
};
|
|
/**
|
|
* Method sets initial value of current cell.
|
|
* Uses to autofill by context menu for "Fill months", "Fill years".
|
|
* @memberOf cDataRow
|
|
* @param {number} nVal
|
|
*/
|
|
cDataRow.prototype.setStartValue = function(nVal) {
|
|
this.nStartVal = nVal;
|
|
};
|
|
/**
|
|
* Method returns flag which checks cell has delimiter.
|
|
* @memberof cDataRow
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.getDelimiter = function() {
|
|
return this.bDelimiter;
|
|
};
|
|
/**
|
|
* Method returns prefix of current cell
|
|
* @memberof cDataRow
|
|
* @returns {string}
|
|
*/
|
|
cDataRow.prototype.getPrefix = function () {
|
|
return this.sPrefix;
|
|
};
|
|
/**
|
|
* Method returns padding of current cell
|
|
* @memberof cDataRow
|
|
* @returns {number}
|
|
*/
|
|
cDataRow.prototype.getPadding = function() {
|
|
return this.nPadding;
|
|
};
|
|
/**
|
|
* Method sets padding of current cell
|
|
* @memberof cDataRow
|
|
* @param {number} nPadding
|
|
*/
|
|
cDataRow.prototype.setPadding = function(nPadding) {
|
|
this.nPadding = nPadding;
|
|
};
|
|
/**
|
|
* Method returns flag which recognizes a current cell has format Date or not.
|
|
* @memberof cDataRow
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.getIsDate = function() {
|
|
return this.bDate;
|
|
};
|
|
/**
|
|
* Method returns flag which recognizes a current cell has format Date & Time or not.
|
|
* @memberof cDataRow
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.getIsDateTime = function() {
|
|
return this.bDateTime;
|
|
};
|
|
/**
|
|
* Method sets flag which recognizes a current cell has format Date & Time or not.
|
|
* @memberof cDataRow
|
|
* @param {boolean} bDateTime
|
|
*/
|
|
cDataRow.prototype.setIsDateTime = function(bDateTime) {
|
|
this.bDateTime = bDateTime;
|
|
};
|
|
/**
|
|
* Method returns flag which recognizes a current cell has mixed format of Dates or not.
|
|
* @memberof cDataRow
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.getIsMixedDateFormat = function () {
|
|
return this.bMixedDateFormat;
|
|
};
|
|
/**
|
|
* Method sets flag which recognizes a current cell has mixed format of Dates or not.
|
|
* @memberof cDataRow
|
|
* @param {boolean} bMixedDateFormat
|
|
*/
|
|
cDataRow.prototype.setIsMixedDateFormat = function (bMixedDateFormat) {
|
|
this.bMixedDateFormat = bMixedDateFormat;
|
|
};
|
|
/**
|
|
* Method returns flag which recognizes a current cell has format Time or not.
|
|
* @memberof cDataRow
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.getIsTime = function() {
|
|
return this.bTime;
|
|
};
|
|
/**
|
|
* Method sets flag which recognizes a current cell has format Time or not.
|
|
* @param {boolean} bTime
|
|
*/
|
|
cDataRow.prototype.setIsTime = function(bTime) {
|
|
this.bTime = bTime;
|
|
};
|
|
/**
|
|
* Method returns additional data
|
|
* @memberof cDataRow
|
|
* @returns {Cell}
|
|
*/
|
|
cDataRow.prototype.getAdditional = function() {
|
|
return this.oAdditional;
|
|
};
|
|
/**
|
|
* Method returns array of time periods
|
|
* @memberof cDataRow
|
|
* @returns {[]}
|
|
*/
|
|
cDataRow.prototype.getTimePeriods = function () {
|
|
return this.aTimePeriods;
|
|
};
|
|
/**
|
|
* Method returns sequence of calculated step and start cell. For fill next cells in autofill.
|
|
* @memberof cDataRow
|
|
* @returns {null|{a0:number, a1:number, nX:number}}
|
|
*/
|
|
cDataRow.prototype.getSequence = function() {
|
|
return this.oSequence;
|
|
};
|
|
/**
|
|
* Method sets sequence of calculated step and start cell. For fill next cells in autofill.
|
|
* @memberof cDataRow
|
|
* @param {{a0:number, a1:number, nX:number}} oSequence
|
|
*/
|
|
cDataRow.prototype.setSequence = function (oSequence) {
|
|
this.oSequence = oSequence;
|
|
};
|
|
/**
|
|
* Method returns the current calculated value for cell who need to be filled.
|
|
* @memberof cDataRow
|
|
* @returns {number}
|
|
*/
|
|
cDataRow.prototype.getCurValue = function() {
|
|
return this.nCurValue;
|
|
};
|
|
/**
|
|
* Method sets the current calculated value for cell who need to be filled.
|
|
* @memberof cDataRow
|
|
* @param {number} nCurValue
|
|
*/
|
|
cDataRow.prototype.setCurValue = function(nCurValue) {
|
|
this.nCurValue = nCurValue;
|
|
};
|
|
/**
|
|
* Method compares 2 DataRow objects for equality
|
|
* @memberof cDataRow
|
|
* @param {cDataRow} oComparedRowData
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.compare = function(oComparedRowData) {
|
|
let sComparedTimePeriods = oComparedRowData.getTimePeriods() ? oComparedRowData.getTimePeriods().join() : null;
|
|
let sTimePeriods = this.getTimePeriods() ? this.getTimePeriods().join() : null;
|
|
let bComparedDelimiter = oComparedRowData.getDelimiter();
|
|
let bDelimiter = this.getDelimiter();
|
|
let sComparedPrefix = oComparedRowData.getPrefix();
|
|
let sPrefix = this.getPrefix();
|
|
let bComparedDate = oComparedRowData.getIsDate();
|
|
let bDate = this.getIsDate();
|
|
|
|
return bComparedDelimiter === bDelimiter && sComparedPrefix === sPrefix && bComparedDate === bDate && sComparedTimePeriods === sTimePeriods;
|
|
};
|
|
/**
|
|
* Method compares bDate and Prefix for equality between two DataRow objects.
|
|
* @memberof cDataRow
|
|
* @param {cDataRow} oComparedRowData
|
|
* @returns {boolean}
|
|
*/
|
|
cDataRow.prototype.prefixDataCompare = function(oComparedRowData) {
|
|
let sComparedPrefix = oComparedRowData.getPrefix();
|
|
let sPrefix = this.getPrefix();
|
|
let bComparedDate = oComparedRowData.getIsDate();
|
|
let bDate = this.getIsDate();
|
|
|
|
return sComparedPrefix === sPrefix && bComparedDate === bDate;
|
|
};
|
|
//-------------------------------------------------------------------------------------------------
|
|
/**
|
|
* Class representing a Series feature
|
|
* @param {asc_CSeriesSettings} settings - Data from dialog window
|
|
* @constructor
|
|
*/
|
|
function CSerial (settings) {
|
|
this.bVertical = settings.seriesIn === oSeriesInType.columns;
|
|
this.nType = settings.type;
|
|
this.nDateUnit = settings.dateUnit;
|
|
this.nStep = settings.stepValue;
|
|
this.nStopValue = settings.stopValue;
|
|
this.bTrend = settings.trend;
|
|
this.nChosenContextMenuProp = settings.contextMenuChosenProperty;
|
|
|
|
this.oFromRange = null;
|
|
this.oToRange = null;
|
|
this.oActiveFillHandle = null;
|
|
this.ws = null;
|
|
this.nPrevValue = null;
|
|
this.nIndex = null;
|
|
|
|
// Iteration coordinates for range who needs to be fill
|
|
this.nStartIndex = null;
|
|
this.nEndIndex = null;
|
|
this.nDirectionStep = null;
|
|
}
|
|
/**
|
|
* Returns the range direction flag. Vertical or horizontal direction
|
|
* @memberof CSerial
|
|
* @returns {boolean}
|
|
*/
|
|
CSerial.prototype.getVertical = function () {
|
|
return this.bVertical;
|
|
};
|
|
/**
|
|
* Returns modes of progressions.
|
|
* @memberof CSerial
|
|
* @returns {c_oAscSeriesType}
|
|
*/
|
|
CSerial.prototype.getType = function () {
|
|
return this.nType;
|
|
};
|
|
/**
|
|
* Returns modes for work with date
|
|
* @memberof CSerial
|
|
* @returns {c_oAscDateUnitType}
|
|
*/
|
|
CSerial.prototype.getDateUnit = function () {
|
|
return this.nDateUnit;
|
|
};
|
|
/**
|
|
* Returns a step of progression
|
|
* @memberof CSerial
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getStep = function () {
|
|
return this.nStep;
|
|
};
|
|
/**
|
|
* Returns a stop value. Fills a progression to value inputted in "Stop value"
|
|
* @memberof CSerial
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getStopValue = function () {
|
|
return this.nStopValue;
|
|
};
|
|
/**
|
|
* Returns a flag of trend mode. true - Fills cells in trend mode. Step defines automatically. false - Fills cells according step value
|
|
* @memberof CSerial
|
|
* @returns {boolean}
|
|
*/
|
|
CSerial.prototype.getTrend = function () {
|
|
return this.bTrend;
|
|
};
|
|
/**
|
|
* Returns a chosen context menu property
|
|
* @returns {asc_CSeriesSettings.contextMenuChosenProperty|c_oAscFillType}
|
|
*/
|
|
CSerial.prototype.getChosenContextMenuProp = function () {
|
|
return this.nChosenContextMenuProp;
|
|
};
|
|
/**
|
|
* Sets a range of selected cells
|
|
* @memberof CSerial
|
|
* @param {Range} oFromRange
|
|
*/
|
|
CSerial.prototype.setFromRange = function (oFromRange) {
|
|
this.oFromRange = oFromRange;
|
|
this.setWs(oFromRange.worksheet);
|
|
};
|
|
/**
|
|
* Returns a range of selected cells
|
|
* @memberof CSerial
|
|
* @returns {Range}
|
|
*/
|
|
CSerial.prototype.getFromRange = function () {
|
|
return this.oFromRange;
|
|
};
|
|
/**
|
|
* Sets a range of cells who will be fill
|
|
* @memberof CSerial
|
|
* @param {Range} oRange
|
|
*/
|
|
CSerial.prototype.setToRange = function (oRange) {
|
|
this.oToRange = oRange;
|
|
};
|
|
/**
|
|
* Returns a range of cells who will be fill
|
|
* @memberof CSerial
|
|
* @returns {Range}
|
|
*/
|
|
CSerial.prototype.getToRange = function () {
|
|
return this.oToRange;
|
|
};
|
|
/**
|
|
* Sets an active fill handle.
|
|
* @param {Asc.Range} oActiveFillHandle
|
|
*/
|
|
CSerial.prototype.setActiveFillHandle = function (oActiveFillHandle) {
|
|
this.oActiveFillHandle = oActiveFillHandle;
|
|
};
|
|
/**
|
|
* Returns an active fill handle
|
|
* @returns {Asc.Range}
|
|
*/
|
|
CSerial.prototype.getActiveFillHandle = function () {
|
|
return this.oActiveFillHandle;
|
|
};
|
|
/**
|
|
* Sets a worksheet of selected range
|
|
* @param {Worksheet} ws
|
|
*/
|
|
CSerial.prototype.setWs = function (ws) {
|
|
this.ws = ws;
|
|
};
|
|
/**
|
|
* Returns a worksheet of selected range
|
|
* @memberof CSerial
|
|
* @returns {Worksheet}
|
|
*/
|
|
CSerial.prototype.getWs = function () {
|
|
return this.ws;
|
|
};
|
|
/**
|
|
* Sets a previous value of progression
|
|
* @memberof CSerial
|
|
* @param {number} nValue
|
|
*/
|
|
CSerial.prototype.setPrevValue = function (nValue) {
|
|
this.nPrevValue = nValue;
|
|
};
|
|
/**
|
|
* Returns a previous value of progression
|
|
* @memberof CSerial
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getPrevValue = function () {
|
|
return this.nPrevValue;
|
|
};
|
|
/**
|
|
* Sets a last index of selected range
|
|
* @memberof CSerial
|
|
* @param {number} nIndex
|
|
*/
|
|
CSerial.prototype.setIndex = function (nIndex) {
|
|
this.nIndex = nIndex;
|
|
};
|
|
/**
|
|
* Returns a last index of selected range
|
|
* @memberof CSerial
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getIndex = function () {
|
|
return this.nIndex;
|
|
};
|
|
/**
|
|
* Initialize a last index of selected range
|
|
* @memberof CSerial
|
|
*/
|
|
CSerial.prototype.initIndex = function () {
|
|
let ws = this.getWs();
|
|
let oActiveFillHandle = this.getActiveFillHandle();
|
|
let oRange = ws.selectionRange.getLast();
|
|
|
|
if (oActiveFillHandle) {
|
|
this.setIndex(this.getVertical() ? oActiveFillHandle.r2 - oRange.r1 : oActiveFillHandle.c2 - oRange.c1);
|
|
} else {
|
|
this.setIndex(this.getVertical() ? oRange.r2 - oRange.r1 : oRange.c2 - oRange.c1);
|
|
}
|
|
};
|
|
/**
|
|
* Sets a start point of a range needs to be fill
|
|
* @memberof CSerial
|
|
* @param {number} nStartIndex
|
|
*/
|
|
CSerial.prototype.setStartIndex = function (nStartIndex) {
|
|
this.nStartIndex = nStartIndex;
|
|
};
|
|
/**
|
|
* Returns a start point of a range needs to be fill
|
|
* @memberof CSerial
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getStartIndex = function () {
|
|
return this.nStartIndex;
|
|
};
|
|
/**
|
|
* Sets a finish point of a range who needs to be fill
|
|
* @param {number} nEndIndex
|
|
*/
|
|
CSerial.prototype.setEndIndex = function (nEndIndex) {
|
|
this.nEndIndex = nEndIndex;
|
|
};
|
|
/**
|
|
* Returns a finish point of a range who needs to be fill
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getEndIndex = function () {
|
|
return this.nEndIndex;
|
|
};
|
|
/**
|
|
* Sets a direction step
|
|
* @param {number} nDirectionStep
|
|
*/
|
|
CSerial.prototype.setDirectionStep = function (nDirectionStep) {
|
|
this.nDirectionStep = nDirectionStep;
|
|
};
|
|
/**
|
|
* Returns a direction step
|
|
* @returns {number}
|
|
*/
|
|
CSerial.prototype.getDirectionStep = function () {
|
|
return this.nDirectionStep;
|
|
};
|
|
/**
|
|
* Initializes iteration coordinates for promote cells in trend mode
|
|
* @param {Object} oFilledLine - Line of cells which need to fill and first filled cell
|
|
* @param {number} oFilledLine.nValue - Value of first cell in line
|
|
* @param {Range} oFilledLine.oToRange - Range of cells which will be fill
|
|
* @param {Cell} oFilledLine.oCell - First cell of line
|
|
* @param {Range} oFilledLine.oFilledRange - Range with filled cells
|
|
* @param {number} oFilledLine.nIndex - Index of shift
|
|
*/
|
|
CSerial.prototype.initTrendIterCoords = function (oFilledLine) {
|
|
const bReverse = this.getIndex() < 0;
|
|
const bActiveFillHandleExists = !!this.getActiveFillHandle();
|
|
const bVertical = this.getVertical();
|
|
const oFrom = this.getFromRange().bbox;
|
|
const oFilled = oFilledLine.oFilledRange.bbox;
|
|
const nIndex = oFilledLine.nIndex;
|
|
|
|
if (bActiveFillHandleExists && this.getChosenContextMenuProp() !== Asc.c_oAscFillType.series) {
|
|
this.initToRange(this.getFromRange());
|
|
const oTo = this.getToRange().bbox;
|
|
if (bReverse) {
|
|
this.setStartIndex(bVertical ? oTo.r2 : oTo.c2);
|
|
this.setEndIndex(bVertical ? oTo.r1 - 1 : oTo.c1 - 1);
|
|
this.setDirectionStep(-1);
|
|
} else {
|
|
this.setStartIndex(bVertical ? oTo.r1 : oTo.c1);
|
|
this.setEndIndex(bVertical ? oTo.r2 + 1 : oTo.c2 + 1);
|
|
this.setDirectionStep(1);
|
|
}
|
|
} else {
|
|
if (bReverse) {
|
|
let nEndIndexFilledRange = bVertical ? oFrom.r1 : oFrom.c1;
|
|
this.setStartIndex(bVertical ? oFrom.r2 : oFrom.c2);
|
|
this.setEndIndex((nIndex + nEndIndexFilledRange) - 1);
|
|
this.setDirectionStep(-1);
|
|
} else {
|
|
let nStartIndexFilled = bVertical ? oFilled.r1 : oFilled.c1;
|
|
this.setStartIndex(bVertical ? oFrom.r1 : oFrom.c1);
|
|
this.setEndIndex((nIndex + nStartIndexFilled) + 1);
|
|
this.setDirectionStep(1);
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* Creates and returns a range with filled cells
|
|
* @memberof CSerial
|
|
* @param {number} [nIndexLine] - Line index of filled cells. Not required param
|
|
* @returns {Range}
|
|
*/
|
|
CSerial.prototype.getFilledRange = function (nIndexLine) {
|
|
let oFilledRange = this.getFromRange().clone();
|
|
let bVertical = this.getVertical();
|
|
let bTrend = this.getTrend();
|
|
let nRow = oFilledRange.bbox.r1;
|
|
let nCol = oFilledRange.bbox.c1;
|
|
let sFirstValue = null;
|
|
let ws = oFilledRange.worksheet;
|
|
let oBBox = oFilledRange.bbox;
|
|
let nType = this.getType();
|
|
|
|
if (nIndexLine != null) {
|
|
if (bVertical) {
|
|
oFilledRange.bbox.c1 = nIndexLine;
|
|
oFilledRange.bbox.c2 = nIndexLine;
|
|
} else {
|
|
oFilledRange.bbox.r1 = nIndexLine;
|
|
oFilledRange.bbox.r2 = nIndexLine;
|
|
}
|
|
}
|
|
if (bTrend) {
|
|
oFilledRange._foreach(function (oCell, nCurRow, nCurCol) {
|
|
if (oCell && oCell.getValueWithoutFormat()) {
|
|
nRow = nCurRow;
|
|
nCol = nCurCol;
|
|
if (nCurRow === oFilledRange.bbox.r1 && nCurCol === oFilledRange.bbox.c1) {
|
|
sFirstValue = oCell.getValueWithoutFormat();
|
|
}
|
|
} else {
|
|
let sNextValue = _getNextValue(ws, oCell, bVertical, oBBox);
|
|
if (!sFirstValue && sNextValue) {
|
|
if (bVertical) {
|
|
oFilledRange.bbox.r1 = nCurRow + 1;
|
|
oFilledRange.bbox.c1 = nCurCol;
|
|
} else {
|
|
oFilledRange.bbox.c1 = nCurCol + 1;
|
|
oFilledRange.bbox.r1 = nCurRow;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
oFilledRange._foreachNoEmpty(function (oCell, nCurRow, nCurCol) {
|
|
if (oCell && oCell.getValueWithoutFormat()) {
|
|
if (nType === oSeriesType.autoFill) {
|
|
nRow = nCurRow;
|
|
nCol = nCurCol;
|
|
} else { // for other modes use only first filled cell in range
|
|
nRow = nCurRow;
|
|
nCol = nCurCol;
|
|
return true; // break loop
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Check if the filled range has merged cells
|
|
if (!bTrend || this.getChosenContextMenuProp() !== Asc.c_oAscFillType.series) {
|
|
let aMergedFilled = oFilledRange.worksheet.mergeManager.get(oFilledRange.bbox).all;
|
|
if (aMergedFilled.length) {
|
|
// Get the last merged range as the last points of the filled range for Growth and Linear trend of context menu
|
|
let oMergedRange = bTrend ? aMergedFilled[aMergedFilled.length - 1] : aMergedFilled[0];
|
|
nRow = oMergedRange.bbox.r2;
|
|
nCol = oMergedRange.bbox.c2;
|
|
}
|
|
}
|
|
|
|
oFilledRange.bbox.r2 = nRow;
|
|
oFilledRange.bbox.c2 = nCol;
|
|
|
|
return oFilledRange;
|
|
};
|
|
/**
|
|
* Creates a range to be filled
|
|
* @memberof CSerial
|
|
* @param {Range} oFilledRange - Range of filled line of cells.
|
|
*/
|
|
CSerial.prototype.initToRange = function (oFilledRange) {
|
|
let ws = this.getWs();
|
|
let oTo = null;
|
|
let oFrom = this.getActiveFillHandle() ? this.getActiveFillHandle(): this.getFromRange().bbox;
|
|
let oFilled = oFilledRange.bbox;
|
|
|
|
this.initIndex();
|
|
let bFilledRangeHasShift = this.getVertical() ? oFilled.r1 !== oFrom.r1 : oFilled.c1 !== oFrom.c1;
|
|
if (this.getIndex() < 0) {
|
|
if (!this.getTrend()) {
|
|
return;
|
|
}
|
|
bFilledRangeHasShift = this.getVertical() ? oFilled.r2 !== oFrom.r1 : oFilled.c2 !== oFrom.c1;
|
|
let oActiveFillHandle = this.getActiveFillHandle();
|
|
oFrom = new Asc.Range(oActiveFillHandle.c2, oActiveFillHandle.r2, oActiveFillHandle.c1, oActiveFillHandle.r1);
|
|
}
|
|
// For a filled range, need to correct the index according to a shift in the start point in the filled range
|
|
if (bFilledRangeHasShift) {
|
|
let nIndex = this.getIndex();
|
|
this.setIndex(this.getVertical() ? nIndex - oFilled.r1 : nIndex - oFilled.c1);
|
|
}
|
|
if (this.getIndex() === 0) {
|
|
let oCanPromote = oFilledRange.canPromote(false, this.getVertical(), 1);
|
|
if (oCanPromote) {
|
|
oTo = oCanPromote.to;
|
|
}
|
|
} else {
|
|
let oCanPromote = oFilledRange.canPromote(false, this.getVertical(), this.getIndex());
|
|
if (oCanPromote) {
|
|
oTo = oCanPromote.to;
|
|
}
|
|
}
|
|
if (oTo) {
|
|
if (!oFrom.containsRange(oTo) && this.getStopValue() == null) {
|
|
return;
|
|
}
|
|
this.setToRange(ws.getRange3(oTo.r1, oTo.c1, oTo.r2, oTo.c2));
|
|
}
|
|
};
|
|
/**
|
|
* Returns an array of Objects that contains: the value of first cell, the range which will be fill data and object of the cell
|
|
* @memberof CSerial
|
|
* @returns {Object[]}
|
|
*/
|
|
CSerial.prototype.getFilledCells = function () {
|
|
let oSerial = this;
|
|
let oFromRange = this.getFromRange();
|
|
let bVertical = this.getVertical();
|
|
let nType = this.getType();
|
|
let aFilledCells = [];
|
|
|
|
oFromRange._foreachNoEmpty(function (oCell, nRow, nCol) {
|
|
if (oCell && oCell.getValueWithoutFormat() && nType !== oSeriesType.autoFill) {
|
|
let nTypeCell = oCell.getType();
|
|
let oFilledRange = oSerial.getFilledRange(bVertical ? nCol : nRow);
|
|
let bFirstCellInRange = bVertical ? nRow === oFilledRange.bbox.r1 : nCol === oFilledRange.bbox.c1;
|
|
if (bFirstCellInRange && nTypeCell === CellValueType.Number) {
|
|
oSerial.initToRange(oFilledRange);
|
|
let oToRange = oSerial.getToRange();
|
|
if (!oToRange) {
|
|
return true; // break loop
|
|
} else {
|
|
aFilledCells.push({
|
|
nValue: oCell.getNumberValue(),
|
|
oToRange: oToRange,
|
|
oCell: oCell.duplicate(),
|
|
oFilledRange: oFilledRange,
|
|
nIndex: oSerial.getIndex()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
return aFilledCells;
|
|
};
|
|
/**
|
|
* Creates a history point for "Series" feature
|
|
* @memberof CSerial
|
|
*/
|
|
CSerial.prototype.initHistoryPoint = function () {
|
|
let nIndex = this.getIndex();
|
|
let oBBox = this.getFromRange().bbox;
|
|
let nWidth = oBBox.c2 - oBBox.c1 + 1;
|
|
let nHeight = oBBox.r2 - oBBox.r1 + 1;
|
|
|
|
AscCommon.History.Create_NewPoint();
|
|
let oSelection = AscCommon.History.GetSelection();
|
|
if (null != oSelection) {
|
|
oSelection = oSelection.clone();
|
|
oSelection.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r2);
|
|
AscCommon.History.SetSelection(oSelection);
|
|
}
|
|
let oSelectionRedo = AscCommon.History.GetSelectionRedo();
|
|
if (null != oSelectionRedo) {
|
|
oSelectionRedo = oSelectionRedo.clone();
|
|
if (this.getVertical()) {
|
|
if (nIndex >= nHeight) {
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r1 + nIndex);
|
|
} else {
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c2, oBBox.r1 + nIndex - 1);
|
|
}
|
|
} else {
|
|
if (nIndex >= nWidth) {
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c1 + nIndex, oBBox.r2);
|
|
} else {
|
|
oSelectionRedo.assign(oBBox.c1, oBBox.r1, oBBox.c1 + nIndex - 1, oBBox.r2);
|
|
}
|
|
}
|
|
AscCommon.History.SetSelectionRedo(oSelectionRedo);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Rounds a float number for correct calculation.
|
|
* @param {number} nValue - The value which will be rounded.
|
|
* @param {number} nFloatNumTemplate - The number template will be used for counting numbers after the decimal point.
|
|
* @returns {number} - Rounded number
|
|
* @private
|
|
*/
|
|
function _smartRound(nValue, nFloatNumTemplate) {
|
|
if (!Number.isInteger(nFloatNumTemplate)) {
|
|
let nCountNumsAfterDec = nFloatNumTemplate.toString().split(".")[1].length;
|
|
return nValue.toFixed(nCountNumsAfterDec) - 0;
|
|
}
|
|
|
|
return nValue;
|
|
}
|
|
/**
|
|
* Checks if the next month is February and the day of the current date is more than the last day of February
|
|
* or isn't the last day of the current month.
|
|
* Using for fixed problem with February month, when the day of the current date that needs to be increased to Feb
|
|
* is more than the last day of Feb, the Date function may skip this month.
|
|
* @param {number} nCurrentExcelDate
|
|
* @param {number} nStep
|
|
* @return {{nextMonthIsFeb:boolean, lastDayOfFeb:number}}
|
|
*/
|
|
function checkNextMonthIsFeb (nCurrentExcelDate, nStep) {
|
|
const CURRENT_MONTH = 0;
|
|
const FEB_MONTH = 1;
|
|
|
|
let dtTempCurrentDate = new Asc.cDate().getDateFromExcel(nCurrentExcelDate);
|
|
let nMonthIdOfCurrentDate = dtTempCurrentDate.getMonth();
|
|
let nNextMonthId = (nMonthIdOfCurrentDate + nStep) % 12;
|
|
let nDayOfCurrentDate = dtTempCurrentDate.getDate();
|
|
let nLastDayOfCurrentMonth = AscCommonExcel.getLastDayInMonth(nCurrentExcelDate, CURRENT_MONTH).getDate();
|
|
dtTempCurrentDate.addMonths(nStep) // For recognize correct year for next month
|
|
let nCurrentYear = dtTempCurrentDate.getFullYear();
|
|
let nLastDayOfFeb = AscCommonExcel.getLastDayInMonth(new Asc.cDate(nCurrentYear, FEB_MONTH, 1, 12).getExcelDate(), CURRENT_MONTH).getDate();
|
|
|
|
return {
|
|
nextMonthIsFeb: nNextMonthId === FEB_MONTH && nDayOfCurrentDate > nLastDayOfFeb && nDayOfCurrentDate < nLastDayOfCurrentMonth,
|
|
lastDayOfFeb: nLastDayOfFeb
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Calculates date for autofill and Series.
|
|
* @param {{step:number, dateUnit:c_oAscDateUnitType, previousValue:number, previousIntValue:number, expectedDayValue:number}} oCellInfo
|
|
* @param {boolean} bAutofill
|
|
* @returns {{previousValue:number, currentValue:number, previousIntValue:number}}
|
|
* @private
|
|
*/
|
|
function _calculateDate(oCellInfo, bAutofill) {
|
|
const nStep = oCellInfo.step;
|
|
const nDateUnit = oCellInfo.dateUnit;
|
|
const bDate1904 = AscCommon.bDate1904;
|
|
let nPrevValue = oCellInfo.previousValue;
|
|
let nPrevIntValue = oCellInfo.previousIntValue;
|
|
let dtExpectedDayValue = new Asc.cDate().getDateFromExcel(oCellInfo.expectedDayValue < 59 && !bDate1904 ? oCellInfo.expectedDayValue + 1 : oCellInfo.expectedDayValue);
|
|
let oReturn = {};
|
|
|
|
// Condition: nPrevVal < 60 is temporary solution for "01/01/1900 - 01/03/1900" dates
|
|
/* TODO Need make system solution for cDate class for case when excelDate is 1 (01/01/1900).
|
|
For now if try convert "1" to Date using getDateFromExcel method result is 31/12/1899
|
|
by this reason of next methods addDays and getExcelDate work incorrect. Result of function is always "-30"
|
|
If for the "1" value add 1 day and try to use getDateFromExcel method, it returns 01/01/1900 =>
|
|
Temporary solution for "01/01/1900 - 01/03/1900" dates - always need add 1 day for getDateFromExcel.
|
|
*/
|
|
if (nDateUnit === oSeriesDateUnitType.weekday) {
|
|
const aWeekdays = [1, 2, 3, 4, 5];
|
|
const MAX_LIMIT_STEP = 2147483647;
|
|
let oCurrentValDate = null;
|
|
let nCurrentVal = nPrevValue;
|
|
let i = 0;
|
|
let nIntStep = Math.floor(nStep);
|
|
let nFinalStep = Math.sign(nIntStep) + _smartRound(nStep - nIntStep, nStep);
|
|
do {
|
|
if (nFinalStep !== 0) {
|
|
nCurrentVal = _smartRound(nCurrentVal + nFinalStep, nStep);
|
|
}
|
|
// Convert number to cDate object
|
|
oCurrentValDate = new Asc.cDate().getDateFromExcel(nPrevValue < 59 && !bDate1904 ? nCurrentVal + 1 : nCurrentVal);
|
|
let nDayOfWeek = nPrevValue < 60 ? oCurrentValDate.getDay() - 1 : oCurrentValDate.getDay();
|
|
if (!aWeekdays.includes(nDayOfWeek)) {
|
|
while (true) {
|
|
nCurrentVal += Math.sign(nStep);
|
|
oCurrentValDate = new Asc.cDate().getDateFromExcel(nCurrentVal < 59 && !bDate1904 ? nCurrentVal + 1 : nCurrentVal);
|
|
nDayOfWeek = nCurrentVal < 60 && !bDate1904 ? oCurrentValDate.getDay() - 1 : oCurrentValDate.getDay();
|
|
if (aWeekdays.includes(nDayOfWeek)) {
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
i++;
|
|
}
|
|
} while (i < Math.abs(nIntStep) && Math.abs(nIntStep) <= MAX_LIMIT_STEP);
|
|
|
|
oReturn.previousValue = nCurrentVal;
|
|
oReturn.currentValue = nCurrentVal < 0 ? nCurrentVal : oCurrentValDate.getExcelDate();
|
|
return oReturn;
|
|
}
|
|
|
|
let nCurrentVal = _smartRound(nPrevValue + nStep, nStep);
|
|
oReturn.previousValue = nCurrentVal;
|
|
if (nDateUnit === oSeriesDateUnitType.day) {
|
|
if (nStep > -1 && nStep < 0 && nCurrentVal < 0) {
|
|
oReturn.previousValue = nCurrentVal + 1;
|
|
oReturn.currentValue = nCurrentVal + 1;
|
|
return oReturn;
|
|
}
|
|
oReturn.currentValue = nCurrentVal;
|
|
return oReturn;
|
|
}
|
|
let nIntegerVal = nPrevIntValue;
|
|
let oCurrentValDate = new Asc.cDate().getDateFromExcel(nIntegerVal < 59 && !bDate1904 ? nIntegerVal + 1 : nIntegerVal);
|
|
let nFinalStep = _smartRound(nCurrentVal - nIntegerVal, nStep);
|
|
if (nFinalStep < 0 && !bAutofill) {
|
|
oReturn.currentValue = NaN;
|
|
return oReturn;
|
|
}
|
|
if (nDateUnit === oSeriesDateUnitType.month) {
|
|
let oRes = checkNextMonthIsFeb(nIntegerVal, nFinalStep);
|
|
let bNextMonthIsFeb = oRes.nextMonthIsFeb;
|
|
if(bNextMonthIsFeb) {
|
|
// Change day to the last day of february for don't skip Feb month.
|
|
oCurrentValDate.setUTCDate(oRes.lastDayOfFeb);
|
|
}
|
|
if (Number.isInteger(nFinalStep)) {
|
|
oCurrentValDate.addMonths(nFinalStep);
|
|
let nLastDayOfCurrentMonth = AscCommonExcel.getLastDayInMonth(oCurrentValDate.getExcelDate(), 0).getDate();
|
|
if (!bNextMonthIsFeb && nLastDayOfCurrentMonth >= dtExpectedDayValue.getDate() && dtExpectedDayValue.getDate() !== oCurrentValDate.getDate()) {
|
|
oCurrentValDate.setUTCDate(dtExpectedDayValue.getDate());
|
|
}
|
|
oReturn.currentValue = oCurrentValDate.getExcelDate();
|
|
oReturn.previousIntValue = oReturn.currentValue;
|
|
oReturn.previousValue = oReturn.currentValue;
|
|
return oReturn;
|
|
}
|
|
oCurrentValDate.addMonths(nFinalStep);
|
|
let nLastDayOfCurrentMonth = AscCommonExcel.getLastDayInMonth(oCurrentValDate.getExcelDate(), 0).getDate();
|
|
if (!bNextMonthIsFeb && nLastDayOfCurrentMonth >= dtExpectedDayValue.getDate() && dtExpectedDayValue.getDate() !== oCurrentValDate.getDate()) {
|
|
oCurrentValDate.setUTCDate(dtExpectedDayValue.getDate());
|
|
}
|
|
oReturn.currentValue = oCurrentValDate.getExcelDate();
|
|
return oReturn;
|
|
}
|
|
if (nDateUnit === oSeriesDateUnitType.year) {
|
|
if (Number.isInteger(nFinalStep)) {
|
|
oCurrentValDate.addYears(nFinalStep);
|
|
oReturn.currentValue = oCurrentValDate.getExcelDate();
|
|
oReturn.previousIntValue = oReturn.currentValue;
|
|
oReturn.previousValue = oReturn.currentValue;
|
|
return oReturn;
|
|
}
|
|
oCurrentValDate.addYears(nFinalStep);
|
|
oReturn.currentValue = oCurrentValDate.getExcelDate();
|
|
return oReturn;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fills current value for Date type
|
|
* @memberof CSerial
|
|
* @param {object} oFilledLine - Value of first cell in line
|
|
* @param {number} oFilledLine.nValue - Value of first cell in line
|
|
* @param {Range} oFilledLine.oToRange - Range of cells which will be fill
|
|
* @param {Cell} oFilledLine.oCell - First cell of line
|
|
* @param {Range} oFilledLine.oFilledRange - Range with filled cells
|
|
* @param {number} oFilledLine.nIndex - Index of shift
|
|
* @returns {number} Current value in ExcelDate format
|
|
* @private
|
|
*/
|
|
CSerial.prototype._fillExcelDate = function (oFilledLine) {
|
|
const oCellInfo = {
|
|
step: this.getStep(),
|
|
dateUnit: this.getDateUnit(),
|
|
previousValue: this.getPrevValue(),
|
|
previousIntValue: oFilledLine.nValue,
|
|
expectedDayValue: oFilledLine.oCell.getNumberValue()
|
|
}
|
|
|
|
const oResult = _calculateDate(oCellInfo, false);
|
|
this.setPrevValue(oResult.previousValue);
|
|
if (oResult.previousIntValue) {
|
|
oFilledLine.nValue = oResult.previousIntValue;
|
|
}
|
|
|
|
return oResult.currentValue;
|
|
};
|
|
/**
|
|
* Fills cells in Linear and Growth regression except Trend mode. Works with:
|
|
* - Type: Linear, Growth, Date.
|
|
* - Stop value
|
|
* - Step value
|
|
* @memberof CSerial
|
|
* @param {Object} oFilledLine - Line of cells which need to fill and first filled cell
|
|
* @param {number} oFilledLine.nValue - Value of first cell in line
|
|
* @param {Range} oFilledLine.oToRange - Range of cells which will be fill
|
|
* @param {Cell} oFilledLine.oCell - First cell of line
|
|
* @param {Range} oFilledLine.oFilledRange - Range with filled cells
|
|
* @param {number} oFilledLine.nIndex - Index of shift
|
|
*/
|
|
CSerial.prototype.promoteCells = function (oFilledLine) {
|
|
function fillCell(nRow, nCol) {
|
|
let bStopLoop = false
|
|
oWsTo._getCell(nRow, nCol, function (oCopyCell) {
|
|
if (oSerial.getPrevValue() != null) {
|
|
let oCellValue = new AscCommonExcel.CCellValue();
|
|
let nCurrentValue = oProgressionCalc[oSerial.getType()]();
|
|
let bNeedStopLoop = false;
|
|
if (nStopValue != null) {
|
|
if (isNaN(nCurrentValue)) {
|
|
bNeedStopLoop = true;
|
|
} else if (oSerial.getType() === oSeriesType.growth) {
|
|
bNeedStopLoop = Number.isInteger(nStep) ? nCurrentValue > nStopValue : nCurrentValue < nStopValue;
|
|
} else if (oSerial.getDateUnit() === oSeriesDateUnitType.weekday) {
|
|
bNeedStopLoop = nCurrentValue <= 0;
|
|
} else {
|
|
bNeedStopLoop = nStep > 0 ? nCurrentValue > nStopValue : nCurrentValue < nStopValue;
|
|
}
|
|
}
|
|
if (bNeedStopLoop || (nRow === gc_nMaxRow0 || nCol === gc_nMaxCol0)) {
|
|
bStopLoop = true;
|
|
return;
|
|
}
|
|
if (isNaN(nCurrentValue)) {
|
|
let oErrorValue = new cError(cErrorType.not_numeric);
|
|
oCellValue.type = CellValueType.Error
|
|
oCellValue.text = oErrorValue.value;
|
|
} else {
|
|
oCellValue.type = CellValueType.Number;
|
|
oCellValue.number = nCurrentValue;
|
|
}
|
|
oCopyCell.setValueData(new UndoRedoData_CellValueData(null, oCellValue));
|
|
// Add styles from firstCell
|
|
if (null != oFromCell) {
|
|
oCopyCell.setStyle(oFromCell.getStyle());
|
|
}
|
|
}
|
|
});
|
|
|
|
return bStopLoop;
|
|
}
|
|
|
|
let oSerial = this;
|
|
let nStep = this.getStep();
|
|
let nStopValue = this.getStopValue() != null ? this.getStopValue() : null;
|
|
let nIndexFilledLine = this.getVertical() ? oFilledLine.oCell.nCol : oFilledLine.oCell.nRow;
|
|
let oTo = oFilledLine.oToRange.bbox;
|
|
let oWsTo = oFilledLine.oToRange.worksheet;
|
|
let oFromCell = oFilledLine.oCell;
|
|
let oFilledRange = oFilledLine.oFilledRange;
|
|
let oFrom = oFilledRange.bbox;
|
|
this.setPrevValue(oFilledLine.nValue);
|
|
// Init variables for filling cells
|
|
let nStartIndex = this.getVertical() ? oTo.r1 : oTo.c1;
|
|
let nEndIndex = this.getVertical() ? oTo.r2 : oTo.c2;
|
|
let nDirectStep = 1;
|
|
// Fill range cells for i row or col
|
|
let oProgressionCalc = {
|
|
0: function () { // linear
|
|
let nCurrentVal = _smartRound(oSerial.getPrevValue() + nStep, nStep);
|
|
oSerial.setPrevValue(nCurrentVal);
|
|
return nCurrentVal;
|
|
}, 1: function () { // growth
|
|
let nCurrentVal = oSerial.getPrevValue() * nStep
|
|
oSerial.setPrevValue(nCurrentVal);
|
|
return nCurrentVal;
|
|
}, 2: function () { // date
|
|
return oSerial._fillExcelDate(oFilledLine);
|
|
}
|
|
};
|
|
let bStopLoop = false;
|
|
let bIncorrectStopValue = false;
|
|
|
|
if (nStopValue != null) {
|
|
if (this.getType() === oSeriesType.growth) {
|
|
bIncorrectStopValue = (nStep <= 0 || nStep === 1) || nStopValue <= 0;
|
|
} else {
|
|
let nStartVal = oFilledLine.nValue;
|
|
bIncorrectStopValue = nStep < 0 ? nStartVal <= nStopValue : nStartVal >= nStopValue;
|
|
}
|
|
}
|
|
if (bIncorrectStopValue) {
|
|
return;
|
|
}
|
|
if (oFilledRange.hasMerged()) {
|
|
nDirectStep = this.getVertical() ? oFrom.r2 - oFrom.r1 + 1 : oFrom.c2 - oFrom.c1 + 1;
|
|
}
|
|
if (nStopValue != null && nStartIndex === nEndIndex) {
|
|
let nIndex = nStartIndex;
|
|
do {
|
|
let nRow = this.getVertical() ? nIndex : nIndexFilledLine;
|
|
let nCol = this.getVertical() ? nIndexFilledLine : nIndex;
|
|
bStopLoop = fillCell(nRow, nCol);
|
|
nIndex += nDirectStep;
|
|
} while (!bStopLoop);
|
|
} else {
|
|
for (let j = nStartIndex; j <= nEndIndex; j += nDirectStep) {
|
|
let nRow = this.getVertical() ? j : nIndexFilledLine;
|
|
let nCol = this.getVertical() ? nIndexFilledLine : j;
|
|
bStopLoop = fillCell(nRow, nCol);
|
|
if (bStopLoop) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* Gets value and index filled cell in loop for calculate sum in fAction. Uses for linear regression formula
|
|
* in promoteCellsWithTrend method. Trend mode
|
|
* @memberof CSerial
|
|
* @param {number} nStartIndex - Index for start loop
|
|
* @param {number} nEndIndex - Index for finish loop
|
|
* @param {number} nFilledCellIter - Iteration of filled cell. Uses for define nRow or nCol at getting cell
|
|
* @param fAction - Callback function for calculate sum with parameters: nValue, nIndexCell
|
|
*/
|
|
CSerial.prototype._calcSum = function (nStartIndex, nEndIndex, nFilledCellIter, fAction) {
|
|
if (fAction) {
|
|
let oSerial = this;
|
|
let oWsFrom = this.getWs();
|
|
let oRes = null;
|
|
for (let i = nStartIndex; i < nEndIndex; i++) {
|
|
let nRow = this.getVertical() ? i : nFilledCellIter;
|
|
let nCol = this.getVertical() ? nFilledCellIter : i;
|
|
oWsFrom._getCell(nRow, nCol, function (oCell) {
|
|
let nValue = oCell.getNumberValue();
|
|
if (nValue !== null) {
|
|
// For Growth type take ln from value
|
|
if (oSerial.getType() === oSeriesType.growth) {
|
|
nValue = Math.log(nValue);
|
|
}
|
|
oRes = fAction(nValue, i);
|
|
}
|
|
});
|
|
if (oRes != null) {
|
|
return oRes;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* Fills cells in Trend mode. For fill cells Trend mode uses linear regression formula - y = a + bx, when:
|
|
* a - intercept,
|
|
* b - slop,
|
|
* x - index of cell who must be fill.
|
|
* Works only for Linear and Growth types and without "Step value" and "Stop value" data.
|
|
* @memberof CSerial
|
|
* @param {Object} oFilledLine - Line of filled cells and cells which need to fill
|
|
* @param {number} oFilledLine.nValue - Value of first cell in line
|
|
* @param {Range} oFilledLine.oToRange - Range of cells which will be fill
|
|
* @param {Cell} oFilledLine.oCell - First cell of line
|
|
* @param {Range} oFilledLine.oFilledRange - Range with filled cells
|
|
* @param {number} oFilledLine.nIndex - Index of shift
|
|
* @param {number} nFilledLineLength - Length line of filled cells
|
|
*/
|
|
CSerial.prototype.promoteCellsWithTrend = function (oFilledLine, nFilledLineLength) {
|
|
this.initTrendIterCoords(oFilledLine);
|
|
let oSerial = this;
|
|
let oFilledRange = oFilledLine.oFilledRange;
|
|
let nIndexFilledLine = this.getVertical() ? oFilledLine.oCell.nCol : oFilledLine.oCell.nRow;
|
|
let nFilledStartIndex = this.getVertical() ? oFilledRange.bbox.r1 : oFilledRange.bbox.c1;
|
|
// If the first cell after calculating the linear regression for "growth trend" is Infinity, then the next cells in range fill 0.
|
|
// This flag is only uses for the Growth trend with an active fill handle
|
|
let bFirstCellValueInf = false;
|
|
// Define variables for calculate linear regression
|
|
let nSumX = 0;
|
|
let nSumY = 0;
|
|
let nNumeratorOfSlope = 0;
|
|
let nDenominatorOfSlope = 0;
|
|
let nSlope = null;
|
|
// Calculate nEndIndex for Filled line with taking into account the shift first element in the filled range
|
|
let nEndIndexFilledLine = nFilledLineLength + nFilledStartIndex;
|
|
// Getting filled cells and calculating sum of index cell (x) and values (y) for calculate intercept and slop
|
|
// for linear regression formula: y = intercept + slop * x
|
|
let nFilledRangeLength = 0;
|
|
this._calcSum(nFilledStartIndex, nEndIndexFilledLine, nIndexFilledLine, function (nValue, nCellIndex) {
|
|
nFilledRangeLength++;
|
|
if ((nValue === -Infinity || isNaN(nValue)) && nFilledStartIndex === nCellIndex && oSerial.getActiveFillHandle()) {
|
|
bFirstCellValueInf = true;
|
|
return true; // break loop
|
|
}
|
|
nSumX += nCellIndex;
|
|
nSumY += nValue;
|
|
});
|
|
let nXAvg = nSumX / nFilledRangeLength;
|
|
let nYAvg = nSumY / nFilledRangeLength;
|
|
if (nFilledLineLength > 1 && !bFirstCellValueInf) {
|
|
this._calcSum(nFilledStartIndex, nEndIndexFilledLine, nIndexFilledLine, function (nValue, nCellIndex) {
|
|
nNumeratorOfSlope += (nCellIndex - nXAvg) * (nValue - nYAvg);
|
|
nDenominatorOfSlope += Math.pow((nCellIndex - nXAvg), 2);
|
|
});
|
|
nSlope = nNumeratorOfSlope / nDenominatorOfSlope;
|
|
} else {
|
|
nSlope = this.getType() === oSeriesType.growth ? 0 : 1;
|
|
}
|
|
let nIntercept = nYAvg - nSlope * nXAvg;
|
|
if (isNaN(nSlope) || isNaN(nIntercept)) {
|
|
return;
|
|
}
|
|
// Fill cells in selection range
|
|
let nStartIndex = this.getStartIndex();
|
|
let nEndIndex = this.getEndIndex();
|
|
let nDirectionStep = this.getDirectionStep();
|
|
let oFromCell = oFilledLine.oCell;
|
|
let oWsTo = oFilledLine.oToRange.worksheet;
|
|
for (let x = nStartIndex; x !== nEndIndex; x += nDirectionStep) {
|
|
let nRow = this.getVertical() ? x : nIndexFilledLine;
|
|
let nCol = this.getVertical() ? nIndexFilledLine : x;
|
|
oWsTo._getCell(nRow, nCol, function (oCopyCell) {
|
|
let oCellValue = new AscCommonExcel.CCellValue();
|
|
let nCellValue = nIntercept + nSlope * x;
|
|
if (oSerial.getType() === oSeriesType.growth) {
|
|
nCellValue = bFirstCellValueInf ? nCellValue : Math.exp(nCellValue);
|
|
}
|
|
oCellValue.type = CellValueType.Number;
|
|
oCellValue.number = nCellValue;
|
|
oCopyCell.setValueData(new UndoRedoData_CellValueData(null, oCellValue));
|
|
// Add styles from firstCell
|
|
if (null != oFromCell) {
|
|
oCopyCell.setStyle(oFromCell.getStyle());
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Gets length of filled line
|
|
* @param {Range} oToRange - Range of cells which will be fill
|
|
* @param {Range} oFilledRange - Range with filled cells
|
|
* @param {boolean} bVertical - Flag recognizes is vertical or horizontal direction
|
|
* @param {number} nIndex - Index of cell who must be fill
|
|
* @returns {number}
|
|
* @private
|
|
*/
|
|
function _getFilledLineLength(oToRange, oFilledRange, bVertical, nIndex) {
|
|
if (nIndex > 0) {
|
|
return bVertical ? oToRange.bbox.r1 - oFilledRange.bbox.r1 : oToRange.bbox.c1 - oFilledRange.bbox.c1;
|
|
}
|
|
// Reverse direction
|
|
return bVertical ? oFilledRange.bbox.r2 - oToRange.bbox.r2 : oFilledRange.bbox.c2 - oToRange.bbox.c2;
|
|
}
|
|
|
|
/**
|
|
* Creates merged cells
|
|
* @param {Range} oFromRange - Filled range.
|
|
* @param {Range} oToRange - The range that needs to be filled.
|
|
* @private
|
|
*/
|
|
function _mergeCells(oFromRange, oToRange) {
|
|
const oFrom = oFromRange.bbox;
|
|
const oTo = oToRange.bbox;
|
|
const oWsFrom = oFromRange.worksheet;
|
|
const oWsTo = oToRange.worksheet;
|
|
const oMergedFrom = oWsFrom.mergeManager.get(oFrom);
|
|
|
|
let nDx = oFrom.c2 - oFrom.c1 + 1;
|
|
let nDy = oFrom.r2 - oFrom.r1 + 1;
|
|
|
|
if(oMergedFrom && oMergedFrom.all.length > 0) {
|
|
for (let i = oTo.c1; i <= oTo.c2; i += nDx) {
|
|
for (let j = oTo.r1; j <= oTo.r2; j += nDy) {
|
|
for (let k = 0, length = oMergedFrom.all.length; k < length; k++) {
|
|
const oMergedBBox = oMergedFrom.all[k].bbox;
|
|
let nC1 = i + oMergedBBox.c1 - oFrom.c1;
|
|
let nR1 = j + oMergedBBox.r1 - oFrom.r1;
|
|
let nC2 = i + oMergedBBox.c2 - oFrom.c1;
|
|
let nR2 = j + oMergedBBox.r2 - oFrom.r1;
|
|
const oNewMerged = new Asc.Range(nC1, nR1, nC2, nR2);
|
|
if(oTo.contains(oNewMerged.c1, oNewMerged.r1)) {
|
|
if(oTo.c2 < oNewMerged.c2) {
|
|
oNewMerged.c2 = oTo.c2;
|
|
}
|
|
if(oTo.r2 < oNewMerged.r2) {
|
|
oNewMerged.r2 = oTo.r2;
|
|
}
|
|
if(!oNewMerged.isOneCell()) {
|
|
oWsTo.mergeManager.add(oNewMerged, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Main method runs "Series" feature according to the specified parameters
|
|
* @memberof CSerial
|
|
*/
|
|
CSerial.prototype.exec = function () {
|
|
let bVertical = this.getVertical();
|
|
let nType = this.getType();
|
|
let oFromRange = this.getFromRange();
|
|
let oWs = this.getWs();
|
|
let oMergedFrom = oWs.mergeManager.get(oFromRange.bbox);
|
|
|
|
if (nType === oSeriesType.autoFill) {
|
|
let oFilledRange = this.getFilledRange();
|
|
let oFilled = oFilledRange.bbox;
|
|
this.initIndex();
|
|
let oCanPromote = oFilledRange.canPromote(false, bVertical, this.getIndex());
|
|
if (!oFilled.containsRange(oCanPromote.to)) {
|
|
oFilledRange.promote(false, this.getVertical(), this.getIndex(), oCanPromote);
|
|
}
|
|
} else {
|
|
let aFilledCells = this.getFilledCells();
|
|
if (aFilledCells.length) {
|
|
this.initHistoryPoint();
|
|
AscCommon.History.StartTransaction();
|
|
for (let i = 0, length = aFilledCells.length; i < length; i++) {
|
|
let oToRange = aFilledCells[i].oToRange;
|
|
let oFilledRange = aFilledCells[i].oFilledRange;
|
|
let nFilledLineLength = _getFilledLineLength(oToRange, oFilledRange, bVertical, this.getIndex());
|
|
if (this.getTrend()) {
|
|
this.promoteCellsWithTrend(aFilledCells[i], nFilledLineLength);
|
|
} else {
|
|
this.promoteCells(aFilledCells[i]);
|
|
}
|
|
_mergeCells(oFilledRange, oToRange);
|
|
}
|
|
AscCommon.History.EndTransaction();
|
|
} else if (oMergedFrom.all.length) {
|
|
let oApi = Asc.editor;
|
|
oApi.sendEvent("asc_onError", c_oAscError.ID.CannotFillRange, c_oAscError.Level.NoCritical);
|
|
}
|
|
}
|
|
};
|
|
|
|
function CExternalReferenceHelper(wb) {
|
|
this.wb = wb;
|
|
}
|
|
|
|
CExternalReferenceHelper.prototype.getExternalLinkStr = function (nExternalLinkIndex, locale, isShortLink) {
|
|
let index = nExternalLinkIndex;
|
|
|
|
let sameFile;
|
|
let fileName = window["Asc"]["editor"].DocInfo && window["Asc"]["editor"].DocInfo.get_Title();
|
|
if ((fileName != null && index === fileName) || index == "0") {
|
|
sameFile = true;
|
|
}
|
|
|
|
let wbModel = this.wb;
|
|
let oExternalLink = nExternalLinkIndex && wbModel && wbModel.getExternalLinkByIndex(index - 1, true);
|
|
|
|
if (oExternalLink && !locale) {
|
|
return "[" + index + "]";
|
|
}
|
|
let path = oExternalLink && oExternalLink.path;
|
|
let name = oExternalLink && oExternalLink.name;
|
|
let res = "";
|
|
if (path || name) {
|
|
if (path) {
|
|
res += path;
|
|
}
|
|
if (name) {
|
|
res += isShortLink ? name : "[" + name + "]";
|
|
}
|
|
} else if (oExternalLink) {
|
|
res = oExternalLink;
|
|
} else if (sameFile) {
|
|
res += locale ? fileName : "[0]";
|
|
}
|
|
return res;
|
|
};
|
|
|
|
CExternalReferenceHelper.prototype.check3dRef = function (_3DRefTmp, local) {
|
|
let t = this;
|
|
let externalLink = _3DRefTmp[3];
|
|
let externalDefName, externalSheetName, receivedDefName, receivedLink, isShortLink, isCurrentFile;
|
|
|
|
// this argument contain shortLink object with full formula and two parts of it
|
|
let receivedShortLink = _3DRefTmp[4];
|
|
if (receivedShortLink) {
|
|
// receivedShortLink - the received, short formula that needs to be checked for an internal link (they have the same in structure)
|
|
// the link can be either to another sheet or to another book - they have the same entry
|
|
receivedLink = receivedShortLink.externalLink;
|
|
externalSheetName = receivedShortLink.externalLink;
|
|
receivedDefName = receivedShortLink.defname;
|
|
isCurrentFile = receivedShortLink.currentFile;
|
|
}
|
|
|
|
// This check of short links is performed only when opening/reading, manual input is processed differently
|
|
if (receivedShortLink && !local) {
|
|
let eReference = t.wb.getExternalLinkByIndex(externalLink - 1);
|
|
if (eReference && eReference.DefinedNames) {
|
|
for (let i = 0; i < eReference.DefinedNames.length; i++) {
|
|
if (eReference.DefinedNames[i].Name === receivedDefName) {
|
|
externalDefName = eReference.DefinedNames[i];
|
|
if (externalDefName.SheetId !== null) {
|
|
externalSheetName = eReference.SheetNames[eReference.DefinedNames[i].SheetId];
|
|
}
|
|
else if (!externalDefName.SheetId && externalDefName.RefersTo) {
|
|
// RefersTo differs from the wsName and may contain several exclamation marks,
|
|
// so we use a condition and a regular expression to get the correct name
|
|
|
|
let refString = externalDefName.RefersTo;
|
|
let exclamationMarkIndex = refString.lastIndexOf("!");
|
|
|
|
refString = refString.slice(0, exclamationMarkIndex);
|
|
refString = refString[0] === "=" ? refString.substring(1) : refString;
|
|
externalSheetName = refString;
|
|
|
|
// regex to find string enclosed in single qoutes
|
|
let regex = /^'(.*)'$/;
|
|
let match = regex.exec(refString);
|
|
if (match && match[1]) {
|
|
externalSheetName = match[1];
|
|
} else if (refString) {
|
|
let externalWB = eReference.getWb();
|
|
let depFormulas = externalWB && externalWB.dependencyFormulas;
|
|
if (depFormulas && depFormulas.defNames && depFormulas.defNames.wb && depFormulas.defNames.wb[receivedDefName]) {
|
|
externalSheetName = refString;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let sheetName = _3DRefTmp[1] ? _3DRefTmp[1] : externalSheetName;
|
|
if (!sheetName && local) {
|
|
return false;
|
|
}
|
|
|
|
let externalName = _3DRefTmp[3];
|
|
//check on add to this document
|
|
let thisTitle = externalLink && window["Asc"]["editor"] && window["Asc"]["editor"].DocInfo && window["Asc"]["editor"].DocInfo.get_Title();
|
|
if (thisTitle === externalLink) {
|
|
externalLink = null;
|
|
}
|
|
|
|
// we check whether sheetName is part of the document or is it a short link to external data
|
|
if (local && !externalLink && receivedShortLink) {
|
|
// if there is a sheet with the same name, we link to it, otherwise we create an external link (shortened)
|
|
let innerSheet = t.wb.getWorksheetByName(sheetName);
|
|
if (!innerSheet) {
|
|
let eReference = t.wb.getExternalLinkByName(sheetName);
|
|
if (eReference && eReference.DefinedNames) {
|
|
for (let i = 0; i < eReference.DefinedNames.length; i++) {
|
|
if (eReference.DefinedNames[i].Name === receivedDefName) {
|
|
externalDefName = eReference.DefinedNames[i];
|
|
if (externalDefName.SheetId !== null) {
|
|
externalSheetName = eReference.SheetNames[eReference.DefinedNames[i].SheetId];
|
|
} else if (!externalDefName.SheetId && externalDefName.RefersTo) {
|
|
// RefersTo differs from the wsName and may contain several exclamation marks,
|
|
// so we use a condition and a regular expression to get the correct name
|
|
|
|
let refString = externalDefName.RefersTo;
|
|
let exclamationMarkIndex = refString.lastIndexOf("!");
|
|
|
|
refString = refString.slice(0, exclamationMarkIndex);
|
|
refString = refString[0] === "=" ? refString.substring(1) : refString;
|
|
externalSheetName = refString;
|
|
|
|
// regex to find string enclosed in single qoutes
|
|
let regex = /^'(.*)'$/;
|
|
let match = regex.exec(refString);
|
|
if (match && match[1]) {
|
|
externalSheetName = match[1];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
sheetName = externalSheetName ? externalSheetName : receivedLink.split(".")[0];
|
|
externalName = receivedLink;
|
|
externalLink = receivedLink;
|
|
isShortLink = true;
|
|
}
|
|
}
|
|
|
|
return {
|
|
sheetName: sheetName,
|
|
externalLink: externalLink,
|
|
receivedLink: receivedLink,
|
|
externalName: externalName,
|
|
isShortLink: isCurrentFile ? true : isShortLink,
|
|
isCurrentFile: isCurrentFile,
|
|
currentFileDefname: isCurrentFile ? receivedDefName : null
|
|
};
|
|
};
|
|
|
|
function safeJsonParse(jsonString) {
|
|
if (!jsonString || typeof jsonString !== "string") {
|
|
return jsonString;
|
|
}
|
|
try {
|
|
return JSON.parse(jsonString);
|
|
} catch (e) {
|
|
console.warn("merge custom functions: Invalid JSON format", e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function mergeCustomFunctions(lsFunctions, opt_get_obj) {
|
|
const api = window["Asc"]["editor"];
|
|
const oLsFunctions = safeJsonParse(lsFunctions) || (typeof lsFunctions === "object" ? lsFunctions : null);
|
|
|
|
let oFileFunctions = null;
|
|
if (api && api.wb && api.wb.model && api.wb.model.fileCustomFunctions) {
|
|
const fileFunctions = api.wb.model.fileCustomFunctions;
|
|
oFileFunctions = safeJsonParse(fileFunctions) || (typeof fileFunctions === "object" ? fileFunctions : null);
|
|
}
|
|
|
|
if (!oLsFunctions || !oFileFunctions) {
|
|
const fallback = oLsFunctions || oFileFunctions;
|
|
return opt_get_obj ? fallback : (fallback ? JSON.stringify(fallback) : null);
|
|
}
|
|
|
|
if (!oLsFunctions) {
|
|
return opt_get_obj ? oFileFunctions : JSON.stringify(oFileFunctions);
|
|
}
|
|
if (!oFileFunctions) {
|
|
return opt_get_obj ? oLsFunctions : JSON.stringify(oLsFunctions);
|
|
}
|
|
|
|
const oUnionFunctions = {
|
|
"macrosArray": []
|
|
};
|
|
const fileFunctionsMap = {};
|
|
let i, macro;
|
|
const fileArrayLength = oFileFunctions["macrosArray"] ? oFileFunctions["macrosArray"].length : 0;
|
|
const lsArrayLength = oLsFunctions["macrosArray"] ? oLsFunctions["macrosArray"].length : 0;
|
|
|
|
for (i = 0; i < fileArrayLength; i++) {
|
|
macro = oFileFunctions["macrosArray"][i];
|
|
if (macro && macro.name) {
|
|
fileFunctionsMap[macro.name] = true;
|
|
oUnionFunctions["macrosArray"].push(macro);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < lsArrayLength; i++) {
|
|
macro = oLsFunctions["macrosArray"][i];
|
|
if (macro && macro.name && !fileFunctionsMap[macro.name]) {
|
|
oUnionFunctions["macrosArray"].push(macro);
|
|
}
|
|
}
|
|
|
|
return opt_get_obj ? oUnionFunctions : JSON.stringify(oUnionFunctions);
|
|
}
|
|
|
|
// Export
|
|
window['AscCommonExcel'] = window['AscCommonExcel'] || {};
|
|
window['AscCommonExcel'].g_nVerticalTextAngle = g_nVerticalTextAngle;
|
|
window['AscCommonExcel'].g_nSheetNameMaxLength = g_nSheetNameMaxLength;
|
|
window['AscCommonExcel'].oDefaultMetrics = oDefaultMetrics;
|
|
window['AscCommonExcel'].g_nAllColIndex = g_nAllColIndex;
|
|
window['AscCommonExcel'].g_nAllRowIndex = g_nAllRowIndex;
|
|
window['AscCommonExcel'].g_DefNameWorksheet = null;
|
|
window['AscCommonExcel'].aStandartNumFormats = aStandartNumFormats;
|
|
window['AscCommonExcel'].aStandartNumFormatsId = aStandartNumFormatsId;
|
|
window['AscCommonExcel'].oFormulaLocaleInfo = oFormulaLocaleInfo;
|
|
window['AscCommonExcel'].getDefNameIndex = getDefNameIndex;
|
|
window['AscCommonExcel'].getCellIndex = getCellIndex;
|
|
window['AscCommonExcel'].getFromCellIndex = getFromCellIndex;
|
|
window['AscCommonExcel'].angleFormatToInterface2 = angleFormatToInterface2;
|
|
window['AscCommonExcel'].angleInterfaceToFormat = angleInterfaceToFormat;
|
|
window['AscCommonExcel'].Workbook = Workbook;
|
|
window['AscCommonExcel'].Worksheet = Worksheet;
|
|
window['AscCommonExcel'].Cell = Cell;
|
|
window['AscCommonExcel'].Range = Range;
|
|
window['AscCommonExcel'].DefName = DefName;
|
|
window['AscCommonExcel'].DependencyGraph = DependencyGraph;
|
|
window['AscCommonExcel'].HiddenManager = HiddenManager;
|
|
window['AscCommonExcel'].CCellWithFormula = CCellWithFormula;
|
|
window['AscCommonExcel'].preparePromoteFromTo = preparePromoteFromTo;
|
|
window['AscCommonExcel'].promoteFromTo = promoteFromTo;
|
|
window['AscCommonExcel'].getCompiledStyle = getCompiledStyle;
|
|
window['AscCommonExcel'].getCompiledStyleFromArray = getCompiledStyleFromArray;
|
|
window['AscCommonExcel'].ignoreFirstRowSort = ignoreFirstRowSort;
|
|
window['AscCommonExcel'].tryTranslateToPrintArea = tryTranslateToPrintArea;
|
|
window['AscCommonExcel']._isSameSizeMerged = _isSameSizeMerged;
|
|
window['AscCommonExcel'].g_nDefNameMaxLength = g_nDefNameMaxLength;
|
|
window['AscCommonExcel'].changeTextCase = changeTextCase;
|
|
window['AscCommonExcel'].g_sNewSheetNamePattern = g_sNewSheetNamePattern;
|
|
window['AscCommonExcel'].CSerial = CSerial;
|
|
window['AscCommonExcel'].SweepLineRowIterator = SweepLineRowIterator;
|
|
window['AscCommonExcel'].BroadcastHelper = BroadcastHelper;
|
|
window['AscCommonExcel'].foreachRefElements = foreachRefElements;
|
|
|
|
window['AscCommonExcel'].mergeCustomFunctions = mergeCustomFunctions;
|
|
window['AscCommonExcel'].safeJsonParse = safeJsonParse;
|
|
window['AscCommonExcel'].stringCompare = stringCompare;
|
|
|
|
})(window);
|