1370 lines
49 KiB
JavaScript
1370 lines
49 KiB
JavaScript
/*
|
|
* (c) Copyright Ascensio System SIA 2010-2015
|
|
*
|
|
* 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 Lubanas st. 125a-25, Riga, Latvia,
|
|
* EU, LV-1021.
|
|
*
|
|
* 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 _getRowTitle(row) {
|
|
return "" + (row + 1);
|
|
}
|
|
cFormulaFunction.LookupAndReference = {
|
|
"groupName": "LookupAndReference",
|
|
"ADDRESS": cADDRESS,
|
|
"AREAS": cAREAS,
|
|
"CHOOSE": cCHOOSE,
|
|
"COLUMN": cCOLUMN,
|
|
"COLUMNS": cCOLUMNS,
|
|
"GETPIVOTDATA": cGETPIVOTDATA,
|
|
"HLOOKUP": cHLOOKUP,
|
|
"HYPERLINK": cHYPERLINK,
|
|
"INDEX": cINDEX,
|
|
"INDIRECT": cINDIRECT,
|
|
"LOOKUP": cLOOKUP,
|
|
"MATCH": cMATCH,
|
|
"OFFSET": cOFFSET,
|
|
"ROW": cROW,
|
|
"ROWS": cROWS,
|
|
"RTD": cRTD,
|
|
"TRANSPOSE": cTRANSPOSE,
|
|
"VLOOKUP": cVLOOKUP
|
|
};
|
|
function cADDRESS() {
|
|
this.name = "ADDRESS";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 2;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 5;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cADDRESS.prototype = Object.create(cBaseFunction.prototype);
|
|
cADDRESS.prototype.Calculate = function (arg) {
|
|
var rowNumber = arg[0],
|
|
colNumber = arg[1],
|
|
refType = arg[2] ? arg[2] : new cNumber(1),
|
|
A1RefType = arg[3] ? arg[3] : new cBool(true),
|
|
sheetName = arg[4] ? arg[4] : new cEmpty();
|
|
if (rowNumber instanceof cArea || rowNumber instanceof cArea3D) {
|
|
rowNumber = rowNumber.cross(arguments[1].first);
|
|
} else {
|
|
if (rowNumber instanceof cArray) {
|
|
rowNumber = rowNumber.getElementRowCol(0, 0);
|
|
}
|
|
}
|
|
if (colNumber instanceof cArea || colNumber instanceof cArea3D) {
|
|
colNumber = colNumber.cross(arguments[1].first);
|
|
} else {
|
|
if (colNumber instanceof cArray) {
|
|
colNumber = colNumber.getElementRowCol(0, 0);
|
|
}
|
|
}
|
|
if (refType instanceof cArea || refType instanceof cArea3D) {
|
|
refType = refType.cross(arguments[1].first);
|
|
} else {
|
|
if (refType instanceof cArray) {
|
|
refType = refType.getElementRowCol(0, 0);
|
|
}
|
|
}
|
|
if (A1RefType instanceof cArea || A1RefType instanceof cArea3D) {
|
|
A1RefType = A1RefType.cross(arguments[1].first);
|
|
} else {
|
|
if (A1RefType instanceof cArray) {
|
|
A1RefType = A1RefType.getElementRowCol(0, 0);
|
|
}
|
|
}
|
|
if (sheetName instanceof cArea || sheetName instanceof cArea3D) {
|
|
sheetName = sheetName.cross(arguments[1].first);
|
|
} else {
|
|
if (sheetName instanceof cArray) {
|
|
sheetName = sheetName.getElementRowCol(0, 0);
|
|
}
|
|
}
|
|
rowNumber = rowNumber.tocNumber();
|
|
colNumber = colNumber.tocNumber();
|
|
refType = refType.tocNumber();
|
|
A1RefType = A1RefType.tocBool();
|
|
if (rowNumber instanceof cError) {
|
|
return this.value = rowNumber;
|
|
}
|
|
if (colNumber instanceof cError) {
|
|
return this.value = colNumber;
|
|
}
|
|
if (refType instanceof cError) {
|
|
return this.value = refType;
|
|
}
|
|
if (A1RefType instanceof cError) {
|
|
return this.value = A1RefType;
|
|
}
|
|
if (sheetName instanceof cError) {
|
|
return this.value = sheetName;
|
|
}
|
|
if (refType.getValue() > 4 && refType.getValue() < 1 || rowNumber.getValue() < 1 || colNumber.getValue() < 1) {
|
|
return this.value = new cError(cErrorType.not_numeric);
|
|
}
|
|
var strRef;
|
|
switch (refType.getValue()) {
|
|
case 1:
|
|
strRef = "$" + g_oCellAddressUtils.colnumToColstrFromWsView(colNumber.getValue() - 1) + "$" + _getRowTitle(rowNumber.getValue() - 1);
|
|
break;
|
|
case 2:
|
|
strRef = g_oCellAddressUtils.colnumToColstrFromWsView(colNumber.getValue() - 1) + "$" + _getRowTitle(rowNumber.getValue() - 1);
|
|
break;
|
|
case 3:
|
|
strRef = "$" + g_oCellAddressUtils.colnumToColstrFromWsView(colNumber.getValue() - 1) + _getRowTitle(rowNumber.getValue() - 1);
|
|
break;
|
|
case 4:
|
|
strRef = g_oCellAddressUtils.colnumToColstrFromWsView(colNumber.getValue() - 1) + _getRowTitle(rowNumber.getValue() - 1);
|
|
break;
|
|
}
|
|
return this.value = new cString((sheetName instanceof cEmpty) ? strRef : parserHelp.get3DRef(sheetName.toString(), strRef));
|
|
};
|
|
cADDRESS.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( row-number , col-number [ , [ ref-type ] [ , [ A1-ref-style-flag ] [ , sheet-name ] ] ] )"
|
|
};
|
|
};
|
|
function cAREAS() {
|
|
cBaseFunction.call(this, "AREAS");
|
|
}
|
|
cAREAS.prototype = Object.create(cBaseFunction.prototype);
|
|
function cCHOOSE() {
|
|
this.name = "CHOOSE";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 2;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 30;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cCHOOSE.prototype = Object.create(cBaseFunction.prototype);
|
|
cCHOOSE.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0];
|
|
if (arg0 instanceof cArea || arg0 instanceof cArea3D) {
|
|
arg0 = arg0.cross(arguments[1].first);
|
|
}
|
|
arg0 = arg0.tocNumber();
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
}
|
|
if (arg0 instanceof cNumber) {
|
|
if (arg0.getValue() < 1 || arg0.getValue() > this.getArguments()) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
return this.value = arg[arg0.getValue()];
|
|
}
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
};
|
|
cCHOOSE.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( index , argument-list )"
|
|
};
|
|
};
|
|
function cCOLUMN() {
|
|
this.name = "COLUMN";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 0;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 1;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cCOLUMN.prototype = Object.create(cBaseFunction.prototype);
|
|
cCOLUMN.prototype.Calculate = function (arg) {
|
|
var arg0;
|
|
if (this.argumentsCurrent == 0) {
|
|
arg0 = arguments[1];
|
|
return this.value = new cNumber(arg0.getFirst().getCol());
|
|
}
|
|
arg0 = arg[0];
|
|
if (arg0 instanceof cRef || arg0 instanceof cRef3D || arg0 instanceof cArea) {
|
|
var range = arg0.getRange();
|
|
if (range) {
|
|
return this.value = new cNumber(range.getFirst().getCol());
|
|
} else {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
} else {
|
|
if (arg0 instanceof cArea3D) {
|
|
var r = arg0.getRange();
|
|
if (r && r[0] && r[0].getFirst()) {
|
|
return this.value = new cNumber(r[0].getFirst().getCol());
|
|
} else {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
} else {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
}
|
|
};
|
|
cCOLUMN.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( [ reference ] )"
|
|
};
|
|
};
|
|
function cCOLUMNS() {
|
|
this.name = "COLUMNS";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 1;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 1;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cCOLUMNS.prototype = Object.create(cBaseFunction.prototype);
|
|
cCOLUMNS.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0];
|
|
if (arg0 instanceof cArray) {
|
|
return this.value = new cNumber(arg0.getCountElementInRow());
|
|
} else {
|
|
if (arg0 instanceof cArea || arg0 instanceof cRef || arg0 instanceof cRef3D) {
|
|
var range = arg0.getRange();
|
|
return this.value = new cNumber(Math.abs(range.getBBox().c1 - range.getBBox().c2) + 1);
|
|
} else {
|
|
if (arg0 instanceof cArea3D) {
|
|
var range = arg0.getRange();
|
|
if (range.length > 1) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
return this.value = new cNumber(Math.abs(range[0].getBBox().c1 - range[0].getBBox().c2) + 1);
|
|
} else {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
cCOLUMNS.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( array )"
|
|
};
|
|
};
|
|
function cGETPIVOTDATA() {
|
|
cBaseFunction.call(this, "GETPIVOTDATA");
|
|
}
|
|
cGETPIVOTDATA.prototype = Object.create(cBaseFunction.prototype);
|
|
var g_oHLOOKUPCache = new VHLOOKUPCache(true);
|
|
function cHLOOKUP() {
|
|
this.name = "HLOOKUP";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 3;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 4;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cHLOOKUP.prototype = Object.create(cBaseFunction.prototype);
|
|
cHLOOKUP.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0],
|
|
arg1 = arg[1],
|
|
arg2 = arg[2],
|
|
arg3 = this.argumentsCurrent == 4 ? arg[3].tocBool() : new cBool(true);
|
|
var numberRow = arg2.getValue() - 1,
|
|
valueForSearching = arg0.getValue(),
|
|
resC = -1,
|
|
min,
|
|
regexp;
|
|
if (isNaN(numberRow)) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
if (numberRow < 0) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
if (arg0 instanceof cString) {
|
|
valueForSearching = arg0.getValue();
|
|
regexp = searchRegExp(valueForSearching);
|
|
} else {
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
} else {
|
|
valueForSearching = arg0.getValue();
|
|
}
|
|
}
|
|
var found = false,
|
|
bb;
|
|
if (arg1 instanceof cRef || arg1 instanceof cRef3D || arg1 instanceof cArea) {
|
|
var range = arg1.getRange(),
|
|
ws = arg1.getWS();
|
|
bb = range.getBBox0();
|
|
if (numberRow > bb.r2 - bb.r1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
var oSearchRange = ws.getRange3(bb.r1, bb.c1, bb.r1, bb.c2);
|
|
var oCache = g_oHLOOKUPCache.get(oSearchRange, valueForSearching, arg0 instanceof cString, arg3.value);
|
|
if (oCache) {
|
|
resC = oCache.index;
|
|
min = oCache.min;
|
|
}
|
|
} else {
|
|
if (arg1 instanceof cArea3D) {
|
|
var range = arg1.getRange()[0],
|
|
ws = arg1.getWS();
|
|
bb = range.getBBox0();
|
|
if (numberRow > bb.r2 - bb.r1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
var oSearchRange = ws.getRange3(bb.r1, bb.c1, bb.r1, bb.c2);
|
|
var oCache = g_oHLOOKUPCache.get(oSearchRange, valueForSearching, arg0 instanceof cString, arg3.value);
|
|
if (oCache) {
|
|
resC = oCache.index;
|
|
min = oCache.min;
|
|
}
|
|
} else {
|
|
if (arg1 instanceof cArray) {
|
|
arg1.foreach(function (elem, r, c) {
|
|
if (c == 0) {
|
|
min = elem.getValue();
|
|
}
|
|
if (arg3.value == true) {
|
|
if (valueForSearching == elem.getValue()) {
|
|
resC = c;
|
|
found = true;
|
|
} else {
|
|
if (valueForSearching > elem.getValue() && !found) {
|
|
resC = c;
|
|
}
|
|
}
|
|
} else {
|
|
if (arg0 instanceof cString) {
|
|
if (regexp.test(elem.getValue())) {
|
|
resC = c;
|
|
}
|
|
} else {
|
|
if (valueForSearching == elem.getValue()) {
|
|
resC = c;
|
|
}
|
|
}
|
|
}
|
|
min = Math.min(min, elem.getValue());
|
|
});
|
|
if (min > valueForSearching) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (resC == -1) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (numberRow > arg1.getRowCount() - 1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
return this.value = arg1.getElementRowCol(numberRow, resC);
|
|
}
|
|
}
|
|
}
|
|
if (min > valueForSearching) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (resC == -1) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
var c = new CellAddress(bb.r1 + numberRow, resC, 0);
|
|
var v = arg1.getWS()._getCellNoEmpty(c.getRow0(), c.getCol0());
|
|
if (v) {
|
|
v = v.getValueWithoutFormat();
|
|
} else {
|
|
v = "";
|
|
}
|
|
return this.value = checkTypeCell(v);
|
|
};
|
|
cHLOOKUP.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( lookup-value , table-array , row-index-num [ , [ range-lookup-flag ] ] )"
|
|
};
|
|
};
|
|
function cHYPERLINK() {
|
|
cBaseFunction.call(this, "HYPERLINK");
|
|
}
|
|
cHYPERLINK.prototype = Object.create(cBaseFunction.prototype);
|
|
function cINDEX() {
|
|
this.name = "INDEX";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 2;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 4;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cINDEX.prototype = Object.create(cBaseFunction.prototype);
|
|
cINDEX.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0],
|
|
arg1 = arg[1] && !(arg[1] instanceof cEmpty) ? arg[1] : new cNumber(1),
|
|
arg2 = arg[2] && !(arg[2] instanceof cEmpty) ? arg[2] : new cNumber(1),
|
|
arg3 = arg[3] && !(arg[3] instanceof cEmpty) ? arg[3] : new cNumber(1),
|
|
res;
|
|
if (arg0 instanceof cArea3D) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
} else {
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
}
|
|
}
|
|
arg1 = arg1.tocNumber();
|
|
arg2 = arg2.tocNumber();
|
|
arg3 = arg3.tocNumber();
|
|
if (arg1 instanceof cError || arg2 instanceof cError || arg3 instanceof cError) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
if (arg1.getValue() < 0 || arg2.getValue() < 0) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
if (arg0 instanceof cArray || arg0 instanceof cArea) {
|
|
res = arg0.getValue2(arg1.getValue() - 1, arg2.getValue() - 1);
|
|
} else {
|
|
res = arg0.tryConvert();
|
|
}
|
|
return this.value = res ? res : new cError(cErrorType.bad_reference);
|
|
};
|
|
cINDEX.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( array , [ row-number ] [ , [ column-number ] ] ) " + this.name + "( reference , [ row-number ] [ , [ column-number ] [ , [ area-number ] ] ] )"
|
|
};
|
|
};
|
|
function cINDIRECT() {
|
|
this.name = "INDIRECT";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 1;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 2;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cINDIRECT.prototype = Object.create(cBaseFunction.prototype);
|
|
cINDIRECT.prototype.Calculate = function (arg) {
|
|
var t = this,
|
|
arg0 = arg[0].tocString(),
|
|
arg1 = arg[1] ? arg[1] : new cBool(true),
|
|
r = arguments[1],
|
|
wb = r.worksheet.workbook,
|
|
o = {
|
|
Formula: "",
|
|
pCurrPos: 0
|
|
},
|
|
ref,
|
|
found_operand;
|
|
function parseReference() {
|
|
if ((ref = parserHelp.is3DRef.call(o, o.Formula, o.pCurrPos))[0]) {
|
|
var _wsFrom = ref[1],
|
|
_wsTo = ((ref[2] !== null) && (ref[2] !== undefined)) ? ref[2] : _wsFrom;
|
|
if (! (wb.getWorksheetByName(_wsFrom) && wb.getWorksheetByName(_wsTo))) {
|
|
return t.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
if (parserHelp.isArea.call(o, o.Formula, o.pCurrPos)) {
|
|
found_operand = new cArea3D(o.operand_str.toUpperCase(), _wsFrom, _wsTo, wb);
|
|
if (o.operand_str.indexOf("$") > -1) {
|
|
found_operand.isAbsolute = true;
|
|
}
|
|
} else {
|
|
if (parserHelp.isRef.call(o, o.Formula, o.pCurrPos)) {
|
|
if (_wsTo != _wsFrom) {
|
|
found_operand = new cArea3D(o.operand_str.toUpperCase(), _wsFrom, _wsTo, wb);
|
|
} else {
|
|
found_operand = new cRef3D(o.operand_str.toUpperCase(), _wsFrom, wb);
|
|
}
|
|
if (o.operand_str.indexOf("$") > -1) {
|
|
found_operand.isAbsolute = true;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (parserHelp.isName.call(o, o.Formula, o.pCurrPos, wb)[0]) {
|
|
found_operand = new cName(o.operand_str, wb);
|
|
} else {
|
|
if (parserHelp.isArea.call(o, o.Formula, o.pCurrPos)) {
|
|
found_operand = new cArea(o.operand_str.toUpperCase(), r.worksheet);
|
|
if (o.operand_str.indexOf("$") > -1) {
|
|
found_operand.isAbsolute = true;
|
|
}
|
|
} else {
|
|
if (parserHelp.isRef.call(o, o.Formula, o.pCurrPos, true)) {
|
|
found_operand = new cRef(o.operand_str.toUpperCase(), r.worksheet);
|
|
if (o.operand_str.indexOf("$") > -1) {
|
|
found_operand.isAbsolute = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (arg0 instanceof cArray) {
|
|
var ret = new cArray();
|
|
arg0.foreach(function (elem, r, c) {
|
|
o = {
|
|
Formula: elem.toString(),
|
|
pCurrPos: 0
|
|
};
|
|
parseReference();
|
|
if (!ret.array[r]) {
|
|
ret.addRow();
|
|
}
|
|
ret.addElement(found_operand);
|
|
});
|
|
return this.value = ret;
|
|
} else {
|
|
o.Formula = arg0.toString();
|
|
parseReference();
|
|
}
|
|
if (found_operand) {
|
|
if (found_operand instanceof cName) {
|
|
found_operand = found_operand.toRef();
|
|
}
|
|
var cellName = r.getFirst().getID(),
|
|
wsId = r.worksheet.getId();
|
|
if ((found_operand instanceof cRef || found_operand instanceof cRef3D || found_operand instanceof cArea) && found_operand.isValid()) {
|
|
var nFrom = wb.dependencyFormulas.addNode(wsId, cellName),
|
|
nTo = wb.dependencyFormulas.addNode(found_operand.getWsId(), found_operand._cells);
|
|
found_operand.setNode(nTo);
|
|
wb.dependencyFormulas.addEdge2(nFrom, nTo);
|
|
} else {
|
|
if (found_operand instanceof cArea3D && found_operand.isValid()) {
|
|
var wsR = found_operand.wsRange();
|
|
for (var j = 0; j < wsR.length; j++) {
|
|
wb.dependencyFormulas.addEdge(wsId, cellName.replace(/\$/g, ""), wsR[j].Id, found_operand._cells.replace(/\$/g, ""));
|
|
}
|
|
}
|
|
}
|
|
return this.value = found_operand;
|
|
}
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
};
|
|
cINDIRECT.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( ref-text [ , [ A1-ref-style-flag ] ] )"
|
|
};
|
|
};
|
|
function cLOOKUP() {
|
|
this.name = "LOOKUP";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 2;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 3;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cLOOKUP.prototype = Object.create(cBaseFunction.prototype);
|
|
cLOOKUP.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0],
|
|
arg1 = arg[1],
|
|
arg2 = this.argumentsCurrent == 2 ? arg1 : arg[2],
|
|
resC = -1,
|
|
resR = -1;
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
}
|
|
if (arg0 instanceof cRef) {
|
|
arg0 = arg0.tryConvert();
|
|
}
|
|
function arrFinder(arr) {
|
|
if (arr.getRowCount() > arr.getCountElementInRow()) {
|
|
resC = arr.getCountElementInRow() > 1 ? 1 : 0;
|
|
var arrCol = arr.getCol(0);
|
|
resR = _func.binarySearch(arg0, arrCol);
|
|
} else {
|
|
resR = arr.getRowCount() > 1 ? 1 : 0;
|
|
var arrRow = arr.getRow(0);
|
|
resC = _func.binarySearch(arg0, arrRow);
|
|
}
|
|
}
|
|
if (! (arg1 instanceof cArea || arg1 instanceof cArea3D || arg1 instanceof cArray || arg2 instanceof cArea || arg2 instanceof cArea3D || arg2 instanceof cArray)) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (arg1 instanceof cArray && arg2 instanceof cArray) {
|
|
if (arg1.getRowCount() != arg2.getRowCount() && arg1.getCountElementInRow() != arg2.getCountElementInRow()) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
arrFinder(arg1);
|
|
if (resR <= -1 && resC <= -1 || resR <= -2 || resC <= -2) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
return this.value = arg2.getElementRowCol(resR, resC);
|
|
} else {
|
|
if (arg1 instanceof cArray || arg2 instanceof cArray) {
|
|
var _arg1, _arg2;
|
|
_arg1 = arg1 instanceof cArray ? arg1 : arg2;
|
|
_arg2 = arg2 instanceof cArray ? arg1 : arg2;
|
|
var BBox = _arg2.getBBox();
|
|
if (_arg1.getRowCount() != (BBox.r2 - BBox.r1) && _arg1.getCountElementInRow() != (BBox.c2 - BBox.c1)) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
arrFinder(_arg1);
|
|
if (resR <= -1 && resC <= -1 || resR <= -2 || resC <= -2) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
var c = new CellAddress(BBox.r1 + resR, BBox.c1 + resC);
|
|
return this.value = checkTypeCell(_arg2.getWS()._getCellNoEmpty(c.getRow0(), c.getCol0()).getValueWithoutFormat());
|
|
} else {
|
|
var arg1Range = arg1.getRange(),
|
|
arg2Range = arg2.getRange();
|
|
if (arg1 instanceof cArea3D && arg1Range.length > 1 || arg2 instanceof cArea3D && arg2Range.length > 1) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (arg1 instanceof cArea3D) {
|
|
arg1Range = arg1.getMatrix()[0];
|
|
} else {
|
|
if (arg1 instanceof cArea) {
|
|
arg1Range = arg1.getMatrix();
|
|
}
|
|
}
|
|
if (arg2 instanceof cArea3D) {
|
|
arg2Range = arg2.getMatrix()[0];
|
|
} else {
|
|
if (arg2 instanceof cArea) {
|
|
arg2Range = arg2.getMatrix();
|
|
}
|
|
}
|
|
var index = _func.binarySearch(arg0, function () {
|
|
var a = [];
|
|
for (var i = 0; i < arg1Range.length; i++) {
|
|
a.push(arg1Range[i][0]);
|
|
}
|
|
return a;
|
|
} ());
|
|
if (index < 0) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (this.argumentsCurrent == 2) {
|
|
if (arg1Range[0].length >= 2) {
|
|
var b = arg1.getBBox();
|
|
return this.value = new cRef(arg1.ws.getCell3((b.r1 - 1) + index, (b.c1 - 1) + 1).getName(), arg1.ws);
|
|
} else {
|
|
return this.value = new cRef(arg1.ws.getCell3((b.r1 - 1) + 0, (b.c1 - 1) + index).getName(), arg1.ws);
|
|
}
|
|
} else {
|
|
var b = arg2.getBBox();
|
|
if (arg2Range.length == 1) {
|
|
return this.value = new cRef(arg1.ws.getCell3((b.r1 - 1) + 0, (b.c1 - 1) + index).getName(), arg1.ws);
|
|
} else {
|
|
return this.value = new cRef(arg1.ws.getCell3((b.r1 - 1) + index, (b.c1 - 1) + 0).getName(), arg1.ws);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
cLOOKUP.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( lookup-value , lookup-vector , result-vector )"
|
|
};
|
|
};
|
|
function cMATCH() {
|
|
this.name = "MATCH";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 2;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 3;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cMATCH.prototype = Object.create(cBaseFunction.prototype);
|
|
cMATCH.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0],
|
|
arg1 = arg[1],
|
|
arg2 = arg[2] ? arg[2] : new cNumber(1);
|
|
function findMatch(a0, a1, a2) {
|
|
var a1RowCount = a1.length,
|
|
a1ColumnCount = a1[0].length,
|
|
a0Value = a0.getValue(),
|
|
a2Value = a2.getValue(),
|
|
arr = [],
|
|
res = new cError(cErrorType.not_available),
|
|
index = -1;
|
|
if (a1RowCount > 1 && a1ColumnCount > 1) {
|
|
return new cError(cErrorType.not_available);
|
|
} else {
|
|
if (a1RowCount == 1 && a1ColumnCount > 1) {
|
|
for (var i = 0; i < a1ColumnCount; i++) {
|
|
arr[i] = a1[0][i].getValue();
|
|
}
|
|
} else {
|
|
if (a1RowCount > 1 && a1ColumnCount == 1) {
|
|
for (var i = 0; i < a1RowCount; i++) {
|
|
arr[i] = a1[i][0].getValue();
|
|
}
|
|
} else {
|
|
arr[0] = a1[0][0];
|
|
}
|
|
}
|
|
}
|
|
if (! (a2Value == 1 || a2Value == 0 || a2Value == -1)) {
|
|
return new cError(cErrorType.not_numeric);
|
|
}
|
|
if (a2Value == -1) {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (arr[i] >= a0Value) {
|
|
index = i;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if (a2Value == 0) {
|
|
if (a0 instanceof cString) {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (searchRegExp2(arr[i].toString(), a0Value)) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (arr[i] == a0Value) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (a2Value == 1) {
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (arr[i] <= a0Value) {
|
|
index = i;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (index > -1) {
|
|
res = new cNumber(index + 1);
|
|
}
|
|
return res;
|
|
}
|
|
if (arg0 instanceof cArea3D || arg0 instanceof cArray || arg0 instanceof cArea) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
} else {
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
}
|
|
}
|
|
if (arg1 instanceof cArray || arg1 instanceof cArea) {
|
|
arg1 = arg1.getMatrix();
|
|
} else {
|
|
if (arg1 instanceof cArea3D && arg1.wsFrom == arg1.wsTo) {
|
|
arg1 = arg1.getMatrix()[0];
|
|
} else {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
}
|
|
if (arg2 instanceof cNumber || arg2 instanceof cBool) {} else {
|
|
if (arg2 instanceof cError) {
|
|
return this.value = arg2;
|
|
} else {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
}
|
|
return this.value = findMatch(arg0, arg1, arg2);
|
|
};
|
|
cMATCH.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( lookup-value , lookup-array [ , [ match-type ]] )"
|
|
};
|
|
};
|
|
function cOFFSET() {
|
|
this.name = "OFFSET";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 3;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 5;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cOFFSET.prototype = Object.create(cBaseFunction.prototype);
|
|
cOFFSET.prototype.Calculate = function (arg) {
|
|
function validBBOX(bbox) {
|
|
return 0 <= bbox.r1 && bbox.r1 <= gc_nMaxRow0 && 0 <= bbox.c1 && bbox.c1 <= gc_nMaxCol0 && 0 <= bbox.r2 && bbox.r2 <= gc_nMaxRow0 && 0 <= bbox.c2 && bbox.c2 <= gc_nMaxCol0;
|
|
}
|
|
var arg0 = arg[0],
|
|
arg1 = arg[1].tocNumber(),
|
|
arg2 = arg[2].tocNumber(),
|
|
arg3 = new cNumber(-1),
|
|
arg4 = new cNumber(-1);
|
|
if (this.argumentsCurrent >= 4) {
|
|
arg3 = arg[3].tocNumber();
|
|
}
|
|
if (this.argumentsCurrent == 5) {
|
|
arg4 = arg[4].tocNumber();
|
|
}
|
|
if (arg1 instanceof cError || arg2 instanceof cError || arg3 instanceof cError || arg4 instanceof cError) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
arg1 = arg1.getValue();
|
|
arg2 = arg2.getValue();
|
|
arg3 = arg3.getValue();
|
|
arg4 = arg4.getValue();
|
|
if (arg3 < 0) {
|
|
arg3 = 1;
|
|
}
|
|
if (arg4 < 0) {
|
|
arg4 = 1;
|
|
}
|
|
if (arg0 instanceof cRef || arg0 instanceof cRef3D) {
|
|
var range = arg0.getRange(),
|
|
bbox = range.getBBox0(),
|
|
box = {
|
|
r1: 0,
|
|
r2: 0,
|
|
c1: 0,
|
|
c2: 0
|
|
},
|
|
ref;
|
|
box.r1 = bbox.r1 + arg1;
|
|
box.c1 = bbox.c1 + arg2;
|
|
box.r2 = bbox.r1 + arg1 + arg3 - 1;
|
|
box.c2 = bbox.c1 + arg2 + arg4 - 1;
|
|
if (!validBBOX(box)) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
var wsName = arg0.ws.getName();
|
|
if (box.r1 == box.r2 && box.c1 == box.c2) {
|
|
ref = g_oCellAddressUtils.colnumToColstrFromWsView(box.c1 + 1) + _getRowTitle(box.r1);
|
|
this.value = (arg0 instanceof cRef) ? new cRef(ref, arg0.ws) : new cRef3D(ref, wsName, arg0.wb);
|
|
} else {
|
|
ref = g_oCellAddressUtils.colnumToColstrFromWsView(box.c1 + 1) + _getRowTitle(box.r1) + ":" + g_oCellAddressUtils.colnumToColstrFromWsView(box.c2 + 1) + _getRowTitle(box.r2);
|
|
this.value = (arg0 instanceof cRef) ? new cArea(ref, arg0.ws) : new cArea3D(ref, wsName, wsName, arg0.wb);
|
|
}
|
|
} else {
|
|
if (arg0 instanceof cArea) {
|
|
var bbox = arg0.getBBox0(),
|
|
box = {
|
|
r1: 0,
|
|
r2: 0,
|
|
c1: 0,
|
|
c2: 0
|
|
},
|
|
ref;
|
|
box.r1 = bbox.r1 + arg1;
|
|
box.c1 = bbox.c1 + arg2;
|
|
box.r2 = bbox.r1 + arg1 + arg3 - 1;
|
|
box.c2 = bbox.c1 + arg2 + arg4 - 1;
|
|
if (!validBBOX(box)) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
if (box.r1 == box.r2 && box.c1 == box.c2) {
|
|
ref = g_oCellAddressUtils.colnumToColstrFromWsView(box.c1 + 1) + _getRowTitle(box.r1);
|
|
this.value = new cRef(ref, arg0.ws);
|
|
} else {
|
|
ref = g_oCellAddressUtils.colnumToColstrFromWsView(box.c1 + 1) + _getRowTitle(box.r1) + ":" + g_oCellAddressUtils.colnumToColstrFromWsView(box.c2 + 1) + _getRowTitle(box.r2);
|
|
this.value = new cArea(ref, arg0.ws);
|
|
}
|
|
} else {
|
|
this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
}
|
|
if (this.value instanceof cArea || this.value instanceof cRef || this.value instanceof cRef3D || this.value instanceof cArea3D) {
|
|
var r = arguments[1],
|
|
wb = r.worksheet.workbook,
|
|
cellName = r.getFirst().getID(),
|
|
wsId = r.worksheet.getId();
|
|
if ((this.value instanceof cRef || this.value instanceof cRef3D || this.value instanceof cArea) && this.value.isValid()) {
|
|
var nFrom = wb.dependencyFormulas.addNode(wsId, cellName),
|
|
nTo = wb.dependencyFormulas.addNode(this.value.getWsId(), this.value._cells);
|
|
this.value.setNode(nTo);
|
|
wb.dependencyFormulas.addEdge2(nFrom, nTo);
|
|
} else {
|
|
if (this.value instanceof cArea3D && this.value.isValid()) {
|
|
var wsR = this.value.wsRange();
|
|
for (var j = 0; j < wsR.length; j++) {
|
|
wb.dependencyFormulas.addEdge(wsId, cellName.replace(/\$/g, ""), wsR[j].Id, this.value._cells.replace(/\$/g, ""));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return this.value;
|
|
};
|
|
cOFFSET.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( reference , rows , cols [ , [ height ] [ , [ width ] ] ] )"
|
|
};
|
|
};
|
|
function cROW() {
|
|
this.name = "ROW";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 0;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 1;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cROW.prototype = Object.create(cBaseFunction.prototype);
|
|
cROW.prototype.Calculate = function (arg) {
|
|
var arg0;
|
|
if (this.argumentsCurrent == 0) {
|
|
arg0 = arguments[1];
|
|
return this.value = new cNumber(arg0.getFirst().getRow());
|
|
}
|
|
arg0 = arg[0];
|
|
if (arg0 instanceof cRef || arg0 instanceof cRef3D || arg0 instanceof cArea) {
|
|
var range = arg0.getRange();
|
|
if (range) {
|
|
return this.value = new cNumber(range.getFirst().getRow());
|
|
} else {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
} else {
|
|
if (arg0 instanceof cArea3D) {
|
|
var r = arg0.getRange();
|
|
if (r && r[0] && r[0].getFirst()) {
|
|
return this.value = new cNumber(r[0].getFirst().getRow());
|
|
} else {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
} else {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
}
|
|
};
|
|
cROW.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( [ reference ] )"
|
|
};
|
|
};
|
|
function cROWS() {
|
|
this.name = "ROWS";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 1;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 1;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cROWS.prototype = Object.create(cBaseFunction.prototype);
|
|
cROWS.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0];
|
|
if (arg0 instanceof cArray) {
|
|
return this.value = new cNumber(arg0.getRowCount());
|
|
} else {
|
|
if (arg0 instanceof cArea || arg0 instanceof cRef || arg0 instanceof cRef3D) {
|
|
var range = arg0.getRange();
|
|
return this.value = new cNumber(Math.abs(range.getBBox().r1 - range.getBBox().r2) + 1);
|
|
} else {
|
|
if (arg0 instanceof cArea3D) {
|
|
var range = arg0.getRange();
|
|
if (range.length > 1) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
return this.value = new cNumber(Math.abs(range[0].getBBox().r1 - range[0].getBBox().r2) + 1);
|
|
} else {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
cROWS.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( array )"
|
|
};
|
|
};
|
|
function cRTD() {
|
|
cBaseFunction.call(this, "RTD");
|
|
}
|
|
cRTD.prototype = Object.create(cBaseFunction.prototype);
|
|
function cTRANSPOSE() {
|
|
this.name = "TRANSPOSE";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 1;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 1;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.noneFormat;
|
|
}
|
|
cTRANSPOSE.prototype = Object.create(cBaseFunction.prototype);
|
|
cTRANSPOSE.prototype.Calculate = function (arg) {
|
|
function TransposeMatrix(A) {
|
|
var tMatrix = [],
|
|
res = new cArray();
|
|
for (var i = 0; i < A.length; i++) {
|
|
for (var j = 0; j < A[i].length; j++) {
|
|
if (!tMatrix[j]) {
|
|
tMatrix[j] = [];
|
|
}
|
|
tMatrix[j][i] = A[i][j];
|
|
}
|
|
}
|
|
res.fillFromArray(tMatrix);
|
|
return res;
|
|
}
|
|
var arg0 = arg[0];
|
|
if (arg0 instanceof cArea || arg0 instanceof cArray) {
|
|
arg0 = arg0.getMatrix();
|
|
} else {
|
|
if (arg0 instanceof cNumber || arg0 instanceof cString || arg0 instanceof cBool || arg0 instanceof cRef || arg0 instanceof cRef3D) {
|
|
return this.value = arg0.getValue();
|
|
} else {
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
} else {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
}
|
|
}
|
|
return this.value = TransposeMatrix(arg0);
|
|
};
|
|
cTRANSPOSE.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( array )"
|
|
};
|
|
};
|
|
function VHLOOKUPCache(bHor) {
|
|
this.cacheId = {};
|
|
this.cacheRanges = {};
|
|
this.bHor = bHor;
|
|
}
|
|
VHLOOKUPCache.prototype.get = function (range, valueForSearching, isValueString, arg3Value) {
|
|
var res = null;
|
|
var _this = this;
|
|
var wsId = range.getWorksheet().getId();
|
|
var sRangeName = wsId + cCharDelimiter + range.getName();
|
|
var cacheElem = this.cacheId[sRangeName];
|
|
if (null == cacheElem) {
|
|
cacheElem = {
|
|
id: sRangeName,
|
|
foreachArray: [],
|
|
results: {}
|
|
};
|
|
range._foreachNoEmpty(function (cell, r, c, r1, c1) {
|
|
var cv = cell.getValueWithoutFormat();
|
|
if (_this.bHor) {
|
|
cacheElem.foreachArray.push({
|
|
cv: cv,
|
|
cvType: checkTypeCell(cv),
|
|
index: c,
|
|
indexStart: c1
|
|
});
|
|
} else {
|
|
cacheElem.foreachArray.push({
|
|
cv: cv,
|
|
cvType: checkTypeCell(cv),
|
|
index: r,
|
|
indexStart: r1
|
|
});
|
|
}
|
|
});
|
|
this.cacheId[sRangeName] = cacheElem;
|
|
var cacheRange = this.cacheRanges[wsId];
|
|
if (null == cacheRange) {
|
|
cacheRange = new RangeDataManager(null);
|
|
this.cacheRanges[wsId] = cacheRange;
|
|
}
|
|
cacheRange.add(range.getBBox0(), cacheElem);
|
|
}
|
|
var sInputKey = valueForSearching + cCharDelimiter + isValueString + cCharDelimiter + arg3Value;
|
|
res = cacheElem.results[sInputKey];
|
|
if (null == res) {
|
|
res = this._calculate(cacheElem.foreachArray, valueForSearching, isValueString, arg3Value);
|
|
cacheElem.results[sInputKey] = res;
|
|
}
|
|
return res;
|
|
};
|
|
VHLOOKUPCache.prototype._calculate = function (cacheArray, valueForSearching, isValueString, arg3Value) {
|
|
var res = {
|
|
min: undefined,
|
|
index: -1
|
|
},
|
|
found = false,
|
|
regexp = null;
|
|
for (var i = 0, length = cacheArray.length; i < length; i++) {
|
|
var cache = cacheArray[i];
|
|
var cv = cache.cv;
|
|
var index = cache.index;
|
|
var indexStart = cache.indexStart;
|
|
var cvType = cache.cvType;
|
|
if (index == indexStart) {
|
|
res.min = cv;
|
|
} else {
|
|
if (res.min > cv) {
|
|
res.min = cv;
|
|
}
|
|
}
|
|
if (arg3Value == true) {
|
|
if (isValueString) {
|
|
if (cvType instanceof cString) {
|
|
if (valueForSearching.localeCompare(cvType.getValue()) == 0) {
|
|
res.index = index;
|
|
found = true;
|
|
} else {
|
|
if (valueForSearching.localeCompare(cvType.getValue()) == 1 && !found) {
|
|
res.index = index;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (valueForSearching == cv) {
|
|
res.index = index;
|
|
found = true;
|
|
} else {
|
|
if (valueForSearching > cv && !found) {
|
|
res.index = index;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (isValueString) {
|
|
if (null == regexp) {
|
|
regexp = searchRegExp(valueForSearching);
|
|
}
|
|
if (regexp.test(cv)) {
|
|
res.index = index;
|
|
}
|
|
} else {
|
|
if (valueForSearching == cv) {
|
|
res.index = index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
VHLOOKUPCache.prototype.remove = function (cell) {
|
|
var wsId = cell.ws.getId();
|
|
var cacheRange = this.cacheRanges[wsId];
|
|
if (null != cacheRange) {
|
|
var oGetRes = cacheRange.get(new Asc.Range(cell.nCol, cell.nRow, cell.nCol, cell.nRow));
|
|
for (var i = 0, length = oGetRes.all.length; i < length; ++i) {
|
|
var elem = oGetRes.all[i];
|
|
elem.data.results = {};
|
|
}
|
|
}
|
|
};
|
|
VHLOOKUPCache.prototype.clean = function () {
|
|
this.cacheId = {};
|
|
this.cacheRanges = {};
|
|
};
|
|
var g_oVLOOKUPCache = new VHLOOKUPCache(false);
|
|
function cVLOOKUP() {
|
|
this.name = "VLOOKUP";
|
|
this.type = cElementType.func;
|
|
this.value = null;
|
|
this.argumentsMin = 3;
|
|
this.argumentsCurrent = 0;
|
|
this.argumentsMax = 4;
|
|
this.formatType = {
|
|
def: -1,
|
|
noneFormat: -2
|
|
};
|
|
this.numFormat = this.formatType.def;
|
|
}
|
|
cVLOOKUP.prototype = Object.create(cBaseFunction.prototype);
|
|
cVLOOKUP.prototype.Calculate = function (arg) {
|
|
var arg0 = arg[0],
|
|
arg1 = arg[1],
|
|
arg2 = arg[2],
|
|
arg3 = this.argumentsCurrent == 4 ? arg[3].tocBool() : new cBool(true);
|
|
var numberCol = arg2.getValue() - 1,
|
|
valueForSearching,
|
|
resR = -1,
|
|
min,
|
|
regexp;
|
|
if (isNaN(numberCol)) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
if (numberCol < 0) {
|
|
return this.value = new cError(cErrorType.wrong_value_type);
|
|
}
|
|
if (arg0 instanceof cRef) {
|
|
arg0 = arg0.getValue();
|
|
}
|
|
if (arg0 instanceof cString) {
|
|
valueForSearching = arg0.getValue();
|
|
} else {
|
|
if (arg0 instanceof cError) {
|
|
return this.value = arg0;
|
|
} else {
|
|
valueForSearching = arg0.getValue();
|
|
}
|
|
}
|
|
var found = false,
|
|
bb;
|
|
if (arg1 instanceof cRef || arg1 instanceof cRef3D) {
|
|
var range = arg1.getRange(),
|
|
ws = arg1.getWS();
|
|
bb = range.getBBox0();
|
|
if (numberCol > bb.c2 - bb.c1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
var oSearchRange = ws.getRange3(bb.r1, bb.c1, bb.r2, bb.c1);
|
|
var oCache = g_oVLOOKUPCache.get(oSearchRange, valueForSearching, arg0 instanceof cString, arg3.value);
|
|
if (oCache) {
|
|
resR = oCache.index;
|
|
min = oCache.min;
|
|
}
|
|
} else {
|
|
if (arg1 instanceof cArea) {
|
|
var range = arg1.getRange(),
|
|
ws = arg1.getWS();
|
|
bb = range.getBBox0();
|
|
if (numberCol > bb.c2 - bb.c1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
var oSearchRange = ws.getRange3(bb.r1, bb.c1, bb.r2, bb.c1);
|
|
var oCache = g_oVLOOKUPCache.get(oSearchRange, valueForSearching, arg0 instanceof cString, arg3.value);
|
|
if (oCache) {
|
|
resR = oCache.index;
|
|
min = oCache.min;
|
|
}
|
|
} else {
|
|
if (arg1 instanceof cArea3D) {
|
|
var range = arg1.getRange()[0],
|
|
ws = arg1.getWS();
|
|
bb = range.getBBox0();
|
|
if (numberCol > bb.c2 - bb.c1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
var oSearchRange = ws.getRange3(bb.r1, bb.c1, bb.r2, bb.c1);
|
|
var oCache = g_oVLOOKUPCache.get(oSearchRange, valueForSearching, arg0 instanceof cString, arg3.value);
|
|
if (oCache) {
|
|
resR = oCache.index;
|
|
min = oCache.min;
|
|
}
|
|
} else {
|
|
if (arg1 instanceof cArray) {
|
|
if (arg0 instanceof cString) {
|
|
regexp = searchRegExp(valueForSearching);
|
|
}
|
|
arg1.foreach(function (elem, r, c) {
|
|
if (r == 0) {
|
|
min = elem.getValue();
|
|
}
|
|
if (arg3.value == true) {
|
|
if (valueForSearching == elem.getValue()) {
|
|
resR = r;
|
|
found = true;
|
|
} else {
|
|
if (valueForSearching > elem.getValue() && !found) {
|
|
resR = r;
|
|
}
|
|
}
|
|
} else {
|
|
if (arg0 instanceof cString) {
|
|
if (regexp.test(elem.getValue())) {
|
|
resR = r;
|
|
}
|
|
} else {
|
|
if (valueForSearching == elem.getValue()) {
|
|
resR = r;
|
|
}
|
|
}
|
|
}
|
|
min = Math.min(min, elem.getValue());
|
|
});
|
|
if (min > valueForSearching) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (resR == -1) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (numberCol > arg1.getCountElementInRow() - 1) {
|
|
return this.value = new cError(cErrorType.bad_reference);
|
|
}
|
|
return this.value = arg1.getElementRowCol(resR, numberCol);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (min > valueForSearching) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
if (resR == -1) {
|
|
return this.value = new cError(cErrorType.not_available);
|
|
}
|
|
var c = new CellAddress(resR, bb.c1 + numberCol, 0);
|
|
var v = arg1.getWS()._getCellNoEmpty(c.getRow0(), c.getCol0());
|
|
if (v) {
|
|
v = v.getValueWithoutFormat();
|
|
} else {
|
|
v = "";
|
|
}
|
|
return this.value = checkTypeCell(v);
|
|
};
|
|
cVLOOKUP.prototype.getInfo = function () {
|
|
return {
|
|
name: this.name,
|
|
args: "( lookup-value , table-array , col-index-num [ , [ range-lookup-flag ] ] )"
|
|
};
|
|
}; |