Skip to content

Commit 14b22ad

Browse files
committed
[IMP] Errors: Add error origin position for #SPILL errors
Currently, Errors that spill because they would collide with other cells content have an error message that references the problematic cell but the link to jump to that cell is missing. closes #8005 Task: 5959985 Signed-off-by: Pierre Rousseau (pro) <pro@odoo.com>
1 parent de067dd commit 14b22ad

File tree

5 files changed

+55
-18
lines changed

5 files changed

+55
-18
lines changed

src/helpers/cells/cell_evaluation.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { isEvaluationError, toString } from "../../functions/helpers";
22
import {
33
BooleanCell,
44
Cell,
5+
CellPosition,
56
CellValue,
67
CellValueType,
78
DEFAULT_LOCALE,
@@ -88,12 +89,12 @@ function _createEvaluatedCell(
8889
locale: Locale,
8990
cell?: Cell
9091
): EvaluatedCell {
91-
let { value, format, message } = functionResult;
92+
let { value, format, message, errorOriginPosition } = functionResult;
9293
format = cell?.format || format;
9394

9495
const formattedValue = formatValue(value, { format, locale });
9596
if (isEvaluationError(value)) {
96-
return errorCell(value, message);
97+
return errorCell(value, message, errorOriginPosition);
9798
}
9899
if (value === null) {
99100
return emptyCell(format);
@@ -185,13 +186,14 @@ function booleanCell(
185186
};
186187
}
187188

188-
function errorCell(value: string, message?: string): ErrorCell {
189+
function errorCell(value: string, message?: string, errorOriginPosition?: CellPosition): ErrorCell {
189190
return {
190191
value,
191192
formattedValue: value,
192193
message,
193194
type: CellValueType.error,
194195
isAutoSummable: false,
195196
defaultAlign: "center",
197+
errorOriginPosition,
196198
};
197199
}

src/plugins/ui_core_views/cell_evaluation/evaluator.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
excludeTopLeft,
77
lazy,
88
positionToZone,
9-
toXC,
109
union,
1110
} from "../../../helpers";
1211
import { createEvaluatedCell, evaluateLiteral } from "../../../helpers/cells";
@@ -358,6 +357,7 @@ export class Evaluator {
358357
} catch (e) {
359358
e.value = e?.value || CellErrorType.GenericError;
360359
e.message = e?.message || implementationErrorMessage;
360+
e.errorOriginPosition = e?.errorOriginPosition;
361361
return createEvaluatedCell(e);
362362
} finally {
363363
this.cellsBeingComputed.delete(cellId);
@@ -504,10 +504,8 @@ export class Evaluator {
504504
) {
505505
this.blockedArrayFormulas.add(formulaPosition);
506506
throw new SplillBlockedError(
507-
_t(
508-
"Array result was not expanded because it would overwrite data in %s.",
509-
toXC(position.col, position.row)
510-
)
507+
_t("Array result was not expanded because it would overwrite data."),
508+
position
511509
);
512510
}
513511
this.blockedArrayFormulas.delete(formulaPosition);

src/types/errors.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { _t } from "../translation";
2+
import { CellPosition } from "./misc";
23

34
export const CellErrorType = {
45
NotAvailable: "#N/A",
@@ -53,7 +54,10 @@ export class UnknownFunctionError extends EvaluationError {
5354
}
5455

5556
export class SplillBlockedError extends EvaluationError {
56-
constructor(message = _t("Spill range is not empty")) {
57+
constructor(
58+
message = _t("Spill range is not empty"),
59+
readonly errorOriginPosition?: CellPosition
60+
) {
5761
super(message, CellErrorType.SpilledBlocked);
5862
}
5963
}

tests/evaluation/evaluation_formula_array.test.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
unMerge,
1919
} from "../test_helpers/commands_helpers";
2020
import { getCellContent, getCellError, getEvaluatedCell } from "../test_helpers/getters_helpers";
21-
import { restoreDefaultFunctions } from "../test_helpers/helpers";
21+
import { restoreDefaultFunctions, toCellPosition } from "../test_helpers/helpers";
2222

2323
let model: Model;
2424
let sheetId: UID;
@@ -250,18 +250,25 @@ describe("evaluate formulas that return an array", () => {
250250

251251
describe("result array can collides with other cell", () => {
252252
test("throw error on the formula when collide with cell having content", () => {
253+
const sheetId = model.getters.getActiveSheetId();
253254
setCellContent(model, "B2", "kikou");
254255
setCellContent(model, "A1", "=MFILL(2,2, 42)");
255256
expect(getEvaluatedCell(model, "A1").value).toBe("#SPILL!");
256257
expect(getCellError(model, "A1")).toBe(
257-
"Array result was not expanded because it would overwrite data in B2."
258+
"Array result was not expanded because it would overwrite data."
259+
);
260+
expect(getEvaluatedCell(model, "A1").errorOriginPosition).toStrictEqual(
261+
toCellPosition(sheetId, "B2")
258262
);
259263

260264
setCellContent(model, "A4", "kikou");
261265
setCellContent(model, "A3", "=MFILL(2,2, 42)");
262266
expect(getEvaluatedCell(model, "A3").value).toBe("#SPILL!");
263267
expect(getCellError(model, "A3")).toBe(
264-
"Array result was not expanded because it would overwrite data in A4."
268+
"Array result was not expanded because it would overwrite data."
269+
);
270+
expect(getEvaluatedCell(model, "A1").errorOriginPosition).toStrictEqual(
271+
toCellPosition(sheetId, "B2")
265272
);
266273
});
267274

@@ -270,7 +277,10 @@ describe("evaluate formulas that return an array", () => {
270277
setCellContent(model, "A1", "=MFILL(2,2, 42)");
271278
expect(getEvaluatedCell(model, "A1").value).toBe("#SPILL!");
272279
expect(getCellError(model, "A1")).toBe(
273-
"Array result was not expanded because it would overwrite data in B2."
280+
"Array result was not expanded because it would overwrite data."
281+
);
282+
expect(getEvaluatedCell(model, "A1").errorOriginPosition).toStrictEqual(
283+
toCellPosition(sheetId, "B2")
274284
);
275285
expect(getEvaluatedCell(model, "A2").value).toBe(null);
276286
expect(getEvaluatedCell(model, "B1").value).toBe(null);
@@ -283,7 +293,10 @@ describe("evaluate formulas that return an array", () => {
283293
setCellContent(model, "A3", "kikou");
284294
expect(getEvaluatedCell(model, "A1").value).toBe("#SPILL!");
285295
expect(getCellError(model, "A1")).toBe(
286-
"Array result was not expanded because it would overwrite data in A2."
296+
"Array result was not expanded because it would overwrite data."
297+
);
298+
expect(getEvaluatedCell(model, "A1").errorOriginPosition).toStrictEqual(
299+
toCellPosition(sheetId, "A2")
287300
);
288301
});
289302

@@ -293,7 +306,10 @@ describe("evaluate formulas that return an array", () => {
293306
setCellContent(model, "C1", "kikou");
294307
expect(getEvaluatedCell(model, "A1").value).toBe("#SPILL!");
295308
expect(getCellError(model, "A1")).toBe(
296-
"Array result was not expanded because it would overwrite data in B1."
309+
"Array result was not expanded because it would overwrite data."
310+
);
311+
expect(getEvaluatedCell(model, "A1").errorOriginPosition).toStrictEqual(
312+
toCellPosition(sheetId, "B1")
297313
);
298314
});
299315

@@ -818,7 +834,10 @@ describe("evaluate formulas that return an array", () => {
818834
expect(getEvaluatedCell(model, "B1").value).toBe(42);
819835
expect(getEvaluatedCell(model, "A2").value).toBe("#SPILL!");
820836
expect(getCellError(model, "A2")).toBe(
821-
"Array result was not expanded because it would overwrite data in B2."
837+
"Array result was not expanded because it would overwrite data."
838+
);
839+
expect(getEvaluatedCell(model, "A2").errorOriginPosition).toStrictEqual(
840+
toCellPosition(sheetId, "B2")
822841
);
823842
});
824843

@@ -828,7 +847,10 @@ describe("evaluate formulas that return an array", () => {
828847
expect(getEvaluatedCell(model, "B1").value).toBe("#SPILL!");
829848
expect(getEvaluatedCell(model, "A2").value).toBe(42);
830849
expect(getCellError(model, "B1")).toBe(
831-
"Array result was not expanded because it would overwrite data in B2."
850+
"Array result was not expanded because it would overwrite data."
851+
);
852+
expect(getEvaluatedCell(model, "B1").errorOriginPosition).toStrictEqual(
853+
toCellPosition(sheetId, "B2")
832854
);
833855
});
834856

@@ -838,7 +860,10 @@ describe("evaluate formulas that return an array", () => {
838860
expect(getEvaluatedCell(model, "B1").value).toBe("#SPILL!");
839861
expect(getEvaluatedCell(model, "A2").value).toBe(42);
840862
expect(getCellError(model, "B1")).toBe(
841-
"Array result was not expanded because it would overwrite data in B2."
863+
"Array result was not expanded because it would overwrite data."
864+
);
865+
expect(getEvaluatedCell(model, "B1").errorOriginPosition).toStrictEqual(
866+
toCellPosition(sheetId, "B2")
842867
);
843868
});
844869

tests/popover/error_tooltip_component.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ describe("Error tooltip component", () => {
7575
expect(".fst-italic").toHaveText(" Caused by A1");
7676
});
7777

78+
test("can display error origin position on a spill error", async () => {
79+
const model = new Model();
80+
setCellContent(model, "A1", "=RANDARRAY(2,2)");
81+
setCellContent(model, "A2", "2");
82+
await mountErrorTooltip(model, "A1");
83+
expect(".fst-italic").toHaveText(" Caused by A2");
84+
});
85+
7886
test("Do not display error origin position in dashboard", async () => {
7987
const model = new Model();
8088
setCellContent(model, "A1", "=1/0");

0 commit comments

Comments
 (0)