Skip to content

Commit

Permalink
Fix/bug 54946 (#2606)
Browse files Browse the repository at this point in the history
* [se] By bug 54946
  • Loading branch information
GoshaZotov authored Mar 3, 2022
1 parent 0d37903 commit bfd3f7f
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 3 deletions.
177 changes: 174 additions & 3 deletions cell/model/FormulaObjects/lookupandreferenceFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1666,9 +1666,7 @@ function (window, undefined) {
var cacheElem = this.cacheId[sRangeName];
if (!cacheElem) {
cacheElem = {elements: [], results: {}};
range._foreachNoEmpty(function (cell, r, c) {
cacheElem.elements.push({v: checkTypeCell(cell), i: (_this.bHor ? c : r)});
});
this.generateElements(range, cacheElem);
this.cacheId[sRangeName] = cacheElem;
var cacheRange = this.cacheRanges[wsId];
if (!cacheRange) {
Expand Down Expand Up @@ -1844,6 +1842,179 @@ function (window, undefined) {
this.cacheId = {};
this.cacheRanges = {};
};
VHLOOKUPCache.prototype.generateElements = function (range, cacheElem) {
var _this = this;

//сильного прироста не получил, пока оставляю прежнюю обработку, подумать на счёт разбития диапазонов
range._foreachNoEmpty(function (cell, r, c) {
cacheElem.elements.push({v: checkTypeCell(cell), i: (_this.bHor ? c : r)});
});
return;

//попытка оптимизации фукнции. если находим диапазон, который полностью перекрывает текущий или пересекаемся с текущим - тогда данные из кэша берём и не обращаемся к модели
//флаг - получаем из кэша только первый элемент
var bFast = true;
if (range && cacheElem) {
//ищем пересечения с уже имеющимися диапазонами
var elementsIntervals = [];
var addByIntervals = function (_elem, isIntersection) {
if (elementsIntervals && elementsIntervals.length) {
for (var k = 0; k < elementsIntervals.length; k++) {
if (elementsIntervals[k].bbox.containsRange(_elem)) {
return;
} else if (_elem.bbox.containsRange(elementsIntervals[k].bbox)) {
elementsIntervals.splice(k, 1);
elementsIntervals.push(_elem);
return;
}
}
}

elementsIntervals.push(_elem);
};

var ws = range.getWorksheet();
if (ws) {
var rangeData = this.getRangeDataBySheetId(ws.Id);
if (rangeData) {
var interval, elem, intersection;
if (bFast) {
interval = rangeData.getFirst(range.bbox);
if (interval) {
elem = interval;
if (elem.bbox.containsRange(range.bbox)) {
//диапазон в кэшэ полностью перекрывает новый
//формируем новый массив из того, которые в кэше
if (elem.data && elem.data.elements) {
cacheElem.elements = elem.data.slice(_this.bHor ? range.bbox.c1 - elem.bbox.c1 : range.bbox.r1 - elem.bbox.r1, _this.bHor ? elem.bbox.c2 - range.bbox.c2 : elem.bbox.r2 - range.bbox.r2);
return;
}
} else /*if (range.bbox.containsRange(elem.bbox))*/{
//ищем пересечение
intersection = elem.bbox.intersection(range.bbox);
addByIntervals({bbox: intersection, elements: elem.data.elements.slice(_this.bHor ? intersection.c1 - elem.bbox.c1 : intersection.r1 - elem.bbox.r1, _this.bHor ? elem.bbox.c2 - intersection.c1 : elem.bbox.r2 - intersection.r1)});
}
}
} else {
var intervals = rangeData.tree && rangeData.tree.searchNodes(range.bbox);
if (intervals && intervals.length) {
for (var i = 0; i < intervals.length; i++) {
interval = intervals[i];
elem = interval.data;
if (elem.bbox.isIntersect(range.bbox)) {
if (elem.bbox.containsRange(range.bbox)) {
//диапазон в кэшэ полностью перекрывает новый
//формируем новый массив из того, которые в кэше
if (elem.data && elem.data.elements) {
cacheElem.elements = elem.data.slice(_this.bHor ? range.bbox.c1 - elem.bbox.c1 : range.bbox.r1 - elem.bbox.r1,
_this.bHor ? elem.bbox.c2 - range.bbox.c2 : elem.bbox.r2 - range.bbox.r2);
return;
}
} else /*if (range.bbox.containsRange(elem.bbox))*/{
//ищем пересечение
intersection = elem.bbox.intersection(range.bbox);
addByIntervals({
bbox: intersection,
elements: elem.data.elements.slice(_this.bHor ? intersection.c1 - elem.bbox.c1 : intersection.r1 - elem.bbox.r1,
_this.bHor ? elem.bbox.c2 - intersection.c1 : elem.bbox.r2 - intersection.r1)
});
}
}
}
}

}
}
}

var addElemsFromWs = function (_range) {
_range._foreachNoEmpty(function (cell, r, c) {
cacheElem.elements.push({v: checkTypeCell(cell), i: (_this.bHor ? c : r)});
});
};

if (elementsIntervals && elementsIntervals.length) {
//сортируем по порядку
elementsIntervals.sort(function (a, b) {
return _this.bHor ? b.c1 - a.c1 : b.r1 - a.r1;
});

//проходимся по всем диапазонам, заполняем "окна"
for (var j = 0; j < elementsIntervals.length; j++) {
var lastCacheElem = cacheElem.elements[cacheElem.elements.length - 1];
var elemIndex = elementsIntervals[j].elements[0].i;

//если в cacheElem ещё ничего не добавлено или индекс следующего элемента из интервала не соответвует индексу + 1 элемента из кэша
var cacheIndex = lastCacheElem && lastCacheElem.i;
if (!lastCacheElem || elemIndex !== lastCacheElem.i + 1) {
var r1, c1, r2, c2;
if (!lastCacheElem) {
if (!_this.bHor && range.bbox.r1 === elemIndex || _this.bHor && range.bbox.c1 === elemIndex) {
//начало диапазонов совпадает
cacheElem.elements = cacheElem.elements.concat(elementsIntervals[j].elements);
if (j === elementsIntervals.length - 1) {
lastCacheElem = cacheElem.elements[cacheElem.elements.length - 1];
cacheIndex = lastCacheElem && lastCacheElem.i;

if (!(!_this.bHor && range.bbox.r1 === cacheIndex || _this.bHor && range.bbox.c1 === cacheIndex)) {
//берём последние элементы
r1 = !_this.bHor ? cacheIndex + 1 : range.bbox.r1;
c1 = _this.bHor ? cacheIndex + 1 : range.bbox.c1;

r2 = range.bbox.r2;
c2 = range.bbox.c2;

addElemsFromWs(ws.getRange3(r1, c1, r2, c2));
}
}
} else {
//берём от начала range до начала первого интервала
r1 = range.bbox.r1;
c1 = range.bbox.c1;

r2 = !_this.bHor ? elemIndex - 1: range.bbox.r2;
c2 = _this.bHor ? elemIndex - 1 : range.bbox.c2;

addElemsFromWs(ws.getRange3(r1, c1, r2, c2));
j--;
}

} else {
//берём от конца последнего элемента из кэша до начала интервала
r1 = !_this.bHor ? cacheIndex + 1 : range.bbox.r1;
c1 = _this.bHor ? cacheIndex + 1 : range.bbox.c1;

r2 = !_this.bHor ? elemIndex - 1: range.bbox.r2;
c2 = _this.bHor ? elemIndex - 1 : range.bbox.c2;

addElemsFromWs(ws.getRange3(r1, c1, r2, c2));
j--;
}
} else {
cacheElem.elements = cacheElem.elements.concat(elementsIntervals[j].elements);
if (j === elementsIntervals.length - 1) {
//берём последние элементы
r1 = !_this.bHor ? cacheIndex + 1 : range.bbox.r1;
c1 = _this.bHor ? cacheIndex + 1 : range.bbox.c1;

r2 = range.bbox.r2;
c2 = range.bbox.c2;

addElemsFromWs(ws.getRange3(r1, c1, r2, c2));
}
}
}
} else {
addElemsFromWs(range);
}
}
};
VHLOOKUPCache.prototype.getRangeDataBySheetId = function (id) {
return this.cacheRanges[id];
};




function MatchCache() {
this.cacheId = {};
Expand Down
12 changes: 12 additions & 0 deletions cell/model/WorkbookElems.js
Original file line number Diff line number Diff line change
Expand Up @@ -5672,6 +5672,18 @@ function RangeDataManagerElem(bbox, data)
}
return oRes;
};
RangeDataManager.prototype.getFirst = function (bbox) {
this._delayedInit();
var intervals = this.tree.searchNodes(bbox);
for (var i = 0; i < intervals.length; i++) {
var interval = intervals[i];
var elem = interval.data;
if (elem.bbox.isIntersect(bbox)) {
return elem
}
}
return null;
};
RangeDataManager.prototype.getAny = function (bbox) {
this._delayedInit();
return this.tree.searchAny(bbox);
Expand Down

0 comments on commit bfd3f7f

Please sign in to comment.