Skip to content

Commit

Permalink
calc: fix: named-range can't be used in function like SUM
Browse files Browse the repository at this point in the history
- also fixes the bug where nested formulas were not getting
autocompleted

Signed-off-by: Rashesh <[email protected]>
Change-Id: I80433d244296c14ce610e02a1f544bd9e01c1c91
  • Loading branch information
Rash419 committed Sep 6, 2024
1 parent 18d281d commit e48df77
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 8 deletions.
78 changes: 73 additions & 5 deletions browser/src/control/Control.FormulaAutoCompletePopup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,83 @@ class FormulaAutoCompletePopup extends L.Control.AutoCompletePopup {
return entries;
}

getAutocompleteText(
currentCellFormula: string,
functionName: string,
endIndex: number,
): string {
// Step-1: Find indexes of all the '(', ';'
const openBracketIndex: number[] = [];
const semicolonIndex: number[] = [];
const plusIndex: number[] = [];
const equalIndex: number = 0;

for (let i = 0; i < currentCellFormula.length; i++) {
if (currentCellFormula.charAt(i) === '(') openBracketIndex.push(i);
else if (currentCellFormula.charAt(i) === ';') semicolonIndex.push(i);
else if (currentCellFormula.charAt(i) === '+') plusIndex.push(i);
}

// Step-2: Find smallest difference between endIndex and indexes of all the '(', ';'
// that will give us the startIndex
let minDiff: number = Number.MAX_VALUE;
let startIndex: number;

const updateMinDiff = (index: number) => {
const tmp = endIndex - index;
if (tmp >= 0 && tmp < minDiff) {
minDiff = tmp;
startIndex = index + 1;
}
};

updateMinDiff(equalIndex);

openBracketIndex.forEach(updateMinDiff);

semicolonIndex.forEach(updateMinDiff);

plusIndex.forEach(updateMinDiff);

// Step-3: extract the text we want to complete using startIndex and endIndex
const partialText: string = currentCellFormula
.substring(startIndex, endIndex + 1)
.trim();

// Step-4: compare partialText and functionName to find remaining text need to autocomplete
let autoCompleteFunctionName: string = '';
for (
let i = 0;
i < Math.max(partialText.length, functionName.length);
i++
) {
if (
partialText.charAt(i).toLowerCase() !=
functionName.charAt(i).toLowerCase()
) {
autoCompleteFunctionName = functionName.substring(i);
break;
}
}

return autoCompleteFunctionName;
}

callback(objectType: any, eventType: any, object: any, index: number) {
if (eventType === 'close') {
this.closePopup();
} else if (eventType === 'select' || eventType === 'activate') {
var currentText = this.map._docLayer._lastFormula;
var chIndex = currentText.length - 1;
var functionName = this.functionList[index].name;
var namedRange = this.functionList[index].namedRange;
functionName = functionName.substring(chIndex);
const namedRange: string = this.functionList[index].namedRange;
const currentText: string = this.map._docLayer._lastFormula;
const addedCharacterIndex: number =
this.map._docLayer._newFormulaDiffIndex;

const functionName: string = this.getAutocompleteText(
currentText,
this.functionList[index].name,
addedCharacterIndex,
);

if (namedRange) this.map._textInput._sendText(functionName);
else this.map._textInput._sendText(functionName + '(');
this.closePopup();
Expand Down
23 changes: 20 additions & 3 deletions browser/src/layer/tile/CanvasTileLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1794,9 +1794,26 @@ L.CanvasTileLayer = L.Layer.extend({
// This is done because coolwsd will send several 'cellformula'
// messages during text composition, and resetting the contents
// of the clipboard container mid-composition will easily break it.
var formula = textMsg.substring(13);
this._lastFormula = formula;
this._map.fire('cellformula', {formula: formula});

let newFormula = textMsg.substring(13);
if (this._lastFormula) {
let minLength = Math.min(newFormula.length, this._lastFormula.length);
let index = -1;
for (let i = 0; i < minLength; i++) {
if (newFormula.charAt(i) !== this._lastFormula.charAt(i)) {
index = i;
break;
}
}
if (index === -1)
index = minLength;

// newFormulaDiffIndex have index of last added character in formula
// It is used during Formula Autocomplete to find partial remaining text
this._newFormulaDiffIndex = index;
}
this._lastFormula = newFormula;
this._map.fire('cellformula', {formula: newFormula});
},

_onCalcFunctionUsageMsg: function (textMsg) {
Expand Down

0 comments on commit e48df77

Please sign in to comment.