Skip to content

Commit

Permalink
[se] Fix bug 46174
Browse files Browse the repository at this point in the history
Fix added to a parser table for processing double brackets in a line
  • Loading branch information
DimitryOrlov authored and GoshaZotov committed Jan 28, 2025
1 parent 24608a5 commit 632ccae
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 17 deletions.
12 changes: 10 additions & 2 deletions cell/model/FormulaObjects/parserFormula.js
Original file line number Diff line number Diff line change
Expand Up @@ -2347,7 +2347,7 @@ parserHelp.setDigitSeparator(AscCommon.g_oDefaultCultureInfo.NumberDecimalSepara
} else if (null != this.reservedColumnIndex) {
if (this.isDynamic && isLocal && this.reservedColumnIndex === AscCommon.FormulaTablePartInfo.thisRow) {
tblStr += "[" + "@" + "]";
} else if (this.isDynamic) {
} else /*if (this.isDynamic)*/ {
tblStr += "[" + this._buildLocalTableString(this.reservedColumnIndex, isLocal) + "]";
}
} else if (this.hdtIndexes || this.hdtcstartIndex || this.hdtcendIndex) {
Expand Down Expand Up @@ -2422,6 +2422,14 @@ parserHelp.setDigitSeparator(AscCommon.g_oDefaultCultureInfo.NumberDecimalSepara
this.isDynamic = true;
}

let openBracketIndex = startCol.indexOf("[");
if (openBracketIndex !== -1) {
let closeBracketIndex = startCol.lastIndexOf("]");
if (closeBracketIndex !== -1) {
startCol = startCol.slice(openBracketIndex + 1, closeBracketIndex);
}
}

this.oneColumnIndex = this.wb.getTableIndexColumnByName(this.tableName, this.isDynamic ? startCol.slice(1) : startCol);
bRes = !!this.oneColumnIndex;
} else if (val['columnRange']) {
Expand Down Expand Up @@ -8278,7 +8286,7 @@ function parserFormula( formula, parent, _ws ) {
if (local || (local === false && digitDelim === false)) { // local and digitDelim with value false using only for copypaste mode.
t.ca = isRecursiveFormula(found_operand, t);
}
} else if (_tableTMP = parserHelp.isTable.call(ph, t.Formula, ph.pCurrPos, local)) {
} else if (_tableTMP = parserHelp.isTable.call(ph, t.Formula, ph.pCurrPos, local, t)) {
found_operand = cStrucTable.prototype.createFromVal(_tableTMP, t.wb, t.ws, tablesMap);

//todo undo delete column
Expand Down
41 changes: 33 additions & 8 deletions common/editorscommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -1491,14 +1491,14 @@

function build_rx_table_cur()
{
var loc_all = cStrucTableLocalColumns['a'],
let loc_all = cStrucTableLocalColumns['a'],
loc_headers = cStrucTableLocalColumns['h'],
loc_data = cStrucTableLocalColumns['d'],
loc_totals = cStrucTableLocalColumns['t'],
loc_this_row = cStrucTableLocalColumns['tr'],
structured_tables_headata = new XRegExp('(?:\\[\\#' + loc_headers + '\\]\\' + FormulaSeparators.functionArgumentSeparator + '\\[\\#' + loc_data + '\\])'),
structured_tables_datals = new XRegExp('(?:\\[\\#' + loc_data + '\\]\\' + FormulaSeparators.functionArgumentSeparator + '\\[\\#' + loc_totals + '\\])'),
structured_tables_userColumn = new XRegExp('(?:\'\\[|\'\\]|[^[\\]])+'),
structured_tables_userColumn = new XRegExp('\\s*\\[{0,1}(?:\'\\[|\'\\]|[^[\\]])+\\]{0,1}\\s*'),
structured_tables_reservedColumn = new XRegExp('\\#(?:' + loc_all + '|' + loc_headers + '|' + loc_totals + '|' + loc_data + /*'|' + loc_this_row + */')'),
structured_tables_thisRow = new XRegExp('(?:\\#(?:' + loc_this_row +')|(?:\\@))');

Expand All @@ -1524,7 +1524,7 @@
let argsSeparator = FormulaSeparators.functionArgumentSeparator;
return XRegExp.build('^(?<tableName>{{tableName}})\\[(?<columnName1>{{columnName}})?\\]', {
"tableName": new XRegExp("^(:?[" + str_namedRanges + "][" + str_namedRanges + "\\d.]*)"),
"columnName": XRegExp.build('(?<reservedColumn>{{reservedColumn}}|{{thisRow}})|(?<oneColumn>{{userColumn}})|(?<columnRange>{{userColumnRange}})|(?<hdtcc>{{hdtcc}})', {
"columnName": XRegExp.build('(?<hdtcc>{{hdtcc}})|(?<reservedColumn>{{reservedColumn}}|{{thisRow}})|(?<oneColumn>{{userColumn}})|(?<columnRange>{{userColumnRange}})', {
"userColumn": structured_tables_userColumn,
"reservedColumn": structured_tables_reservedColumn,
"thisRow": structured_tables_thisRow,
Expand Down Expand Up @@ -3869,19 +3869,44 @@
return true;
}
};
parserHelper.prototype.isTable = function (formula, start_pos, local)
parserHelper.prototype.isTable = function (formula, start_pos, local, parserFormula)
{
if (this instanceof parserHelper)
{
this._reset();
}
let subSTR = formula.substring(start_pos),
match = XRegExp.exec(subSTR, local ? rx_table_local : rx_table);
let subSTR = formula.substring(start_pos);
/*
short notation can be used inside table cells
short entry - an entry without table name, but with the same syntax
*/
let tableIntersection;
if (local && subSTR[0] === "[" && parserFormula.parent && parserFormula.ws && parserFormula.ws.TableParts) {
let col = parserFormula.parent.nCol;
let row = parserFormula.parent.nRow;
// go through each existing table and check intersection by col row
for (let i = 0; i < parserFormula.ws.TableParts.length; i++) {
let table = parserFormula.ws.TableParts[i];
let tableRef = table.Ref;
if (!tableRef.contains(col, row)) {
continue;
}
tableIntersection = table;
break;
}

if (tableIntersection) {
// add the table name to the beginning of the line for correct checking further
subSTR = tableIntersection.DisplayName + subSTR;
}
}

const match = XRegExp.exec(subSTR, local ? rx_table_local : rx_table);

if (match != null && match["tableName"])
{
this.operand_str = match[0];
this.pCurrPos += match[0].length;
this.operand_str = tableIntersection ? "[" + match.columnName1 + "]" : match[0];
this.pCurrPos += tableIntersection ? match.columnName1.length + 2 : match[0].length;
return match;
}

Expand Down
47 changes: 40 additions & 7 deletions tests/cell/spreadsheet-calculation/SheetStructureTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2843,8 +2843,8 @@ $(function () {
resCell = ws.getRange4(101, 70);
resCell.setValue("=" + tableName +"[#All]");

assert.strictEqual(resCell.getValueForEdit(), "=" + tableName, "Value for edit in cell after Table[#All] is typed");
assert.strictEqual(resCell.getFormula(), tableName, "Formula in cell after Table[#All] is typed");
assert.strictEqual(resCell.getValueForEdit(), "=" + tableName + "[#All]", "Value for edit in cell after Table[#All] is typed");
assert.strictEqual(resCell.getFormula(), tableName + "[#All]", "Formula in cell after Table[#All] is typed");


// calc res check
Expand Down Expand Up @@ -2883,8 +2883,8 @@ $(function () {
resCell = ws.getRange4(101, 80);
resCell.setValue("=" + tableName +"[#Data]");

assert.strictEqual(resCell.getValueForEdit(), "=" + tableName, "Value for edit in cell after Table[#Data] is typed");
assert.strictEqual(resCell.getFormula(), tableName, "Formula in cell after Table[#Data] is typed");
assert.strictEqual(resCell.getValueForEdit(), "=" + tableName +"[#Data]", "Value for edit in cell after Table[#Data] is typed");
assert.strictEqual(resCell.getFormula(), tableName +"[#Data]", "Formula in cell after Table[#Data] is typed");


// calc res check
Expand Down Expand Up @@ -3021,6 +3021,40 @@ $(function () {
assert.strictEqual(resCell.getValueForEdit(), "=" + tableName + "[[#Data],[#Headers]]", "Value for edit in cell after Table[[#Data],[#Headers]] is typed");
assert.strictEqual(resCell.getFormula(), tableName + "[[#Data],[#Headers]]", "Formula in cell after Table[[#Data],[#Headers]] is typed");

// for bug 46174
// calc res check
cellWithFormula = new AscCommonExcel.CCellWithFormula(ws, 104, 0);
oParser = new AscCommonExcel.parserFormula("[[Column1]]", cellWithFormula, ws);
assert.ok(oParser.parse(true));
array = oParser.calculate();
assert.strictEqual(array.getValueByRowCol(0, 0).getValue(), 1, 'Short notation. Result of [[Column1]][0,0] inside table');
assert.strictEqual(array.getValueByRowCol(1, 0).getValue(), 1, 'Short notation. Result of [[Column1]][1,0] inside table');
assert.strictEqual(array.getValueByRowCol(2, 0).getValue(), 1, 'Short notation. Result of [[Column1]][2,0] inside table');
assert.strictEqual(array.getValueByRowCol(3, 0).getValue(), 1, 'Short notation. Result of [[Column1]][3,0] inside table');

cellWithFormula = new AscCommonExcel.CCellWithFormula(ws, 105, 0);
oParser = new AscCommonExcel.parserFormula("[[Column1]]", cellWithFormula, ws);
assert.ok(!oParser.parse(true));
array = oParser.calculate();
assert.strictEqual(array.type, AscCommonExcel.cElementType.error, 'Short notation. Result of [[Column1]] outside table');

cellWithFormula = new AscCommonExcel.CCellWithFormula(ws, 101, 20);
oParser = new AscCommonExcel.parserFormula(tableName + "[[Column1]]", cellWithFormula, ws);
assert.ok(oParser.parse());
array = oParser.calculate();
assert.strictEqual(array.getValueByRowCol(0, 0).getValue(), 1, 'Result of [[Column1]][0,0]');
assert.strictEqual(array.getValueByRowCol(1, 0).getValue(), 1, 'Result of [[Column1]][1,0]');
assert.strictEqual(array.getValueByRowCol(2, 0).getValue(), 1, 'Result of [[Column1]][2,0]');
assert.strictEqual(array.getValueByRowCol(3, 0).getValue(), 1, 'Result of [[Column1]][3,0]');

// value for edit and formula in cell check
resCell = ws.getRange4(101, 20);
resCell.setValue("=" + tableName +"[[Column1]]");

assert.strictEqual(resCell.getValueForEdit(), "=" + tableName + "[Column1]", "Value for edit in cell after Table[[Column1]] is typed");
assert.strictEqual(resCell.getFormula(), tableName + "[Column1]", "Formula in cell after Table[[Column1]] is typed");


clearData(0, 99, 0, 105);
});

Expand All @@ -3040,7 +3074,6 @@ $(function () {
let tables = wsView.model.autoFilters.getTablesIntersectionRange(new Asc.Range(0, 100, 0, 100));
assert.strictEqual(tables.length, 1, "compare tables length");

debugger
let table = tables[0];
let tableName = table.DisplayName; // due to the fact that other tables are used in file, get the name of the one we need by this way
wsView.af_changeFormatTableInfo(tableName, Asc.c_oAscChangeTableStyleInfo.rowTotal, true);
Expand All @@ -3062,8 +3095,8 @@ $(function () {
resCell = ws.getRange4(101, 70);
resCell.setValue("=" + tableName +"[#All]");

assert.strictEqual(resCell.getValueForEdit(), "=" + tableName, "Value for edit in cell after Table[#All] is typed");
assert.strictEqual(resCell.getFormula(), tableName, "Formula in cell after Table[#All] is typed");
assert.strictEqual(resCell.getValueForEdit(), "=" + tableName + "[#All]", "Value for edit in cell after Table[#All] is typed");
assert.strictEqual(resCell.getFormula(), tableName + "[#All]", "Formula in cell after Table[#All] is typed");


/* column header check */
Expand Down

0 comments on commit 632ccae

Please sign in to comment.