@odoo/o-spreadsheet 18.3.23 → 18.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 18.3.23
6
- * @date 2025-10-07T10:00:57.144Z
7
- * @hash b4764cb
5
+ * @version 18.3.24
6
+ * @date 2025-10-16T06:38:12.942Z
7
+ * @hash f13dd1c
8
8
  */
9
9
 
10
10
  (function (exports, owl) {
@@ -3942,7 +3942,17 @@
3942
3942
  return toMatrix(data).map((row) => {
3943
3943
  return row.map((cell) => {
3944
3944
  if (typeof cell.value !== "number") {
3945
- throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects number values for %s, but got a %s.", argName, typeof cell.value));
3945
+ let message = "";
3946
+ if (typeof cell === "object") {
3947
+ message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got an empty value.", argName);
3948
+ }
3949
+ else if (typeof cell === "string") {
3950
+ message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a string.", argName);
3951
+ }
3952
+ else if (typeof cell === "boolean") {
3953
+ message = _t("Function [[FUNCTION_NAME]] expects number values for %s, but got a boolean.", argName);
3954
+ }
3955
+ throw new EvaluationError(message);
3946
3956
  }
3947
3957
  return cell.value;
3948
3958
  });
@@ -9127,7 +9137,7 @@
9127
9137
  pasteCell(origin, target, clipboardOption) {
9128
9138
  const { sheetId, col, row } = target;
9129
9139
  const targetCell = this.getters.getEvaluatedCell(target);
9130
- const originFormat = origin?.format ?? origin.evaluatedCell.format;
9140
+ const originFormat = origin?.format || origin.evaluatedCell.format;
9131
9141
  if (clipboardOption?.pasteOption === "asValue") {
9132
9142
  this.dispatch("UPDATE_CELL", {
9133
9143
  ...target,
@@ -12833,7 +12843,7 @@ stores.inject(MyMetaStore, storeInstance);
12833
12843
  ],
12834
12844
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
12835
12845
  assertNonEmptyMatrix(knownDataY, "known_data_y");
12836
- return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "the first argument (known_data_y)")), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
12846
+ return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "known_data_y")), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b)));
12837
12847
  },
12838
12848
  };
12839
12849
  // -----------------------------------------------------------------------------
@@ -12898,7 +12908,7 @@ stores.inject(MyMetaStore, storeInstance);
12898
12908
  ],
12899
12909
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12900
12910
  assertNonEmptyMatrix(dataY, "data_y");
12901
- return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
12911
+ return fullLinearRegression(toNumberMatrix(dataX, "data_x"), toNumberMatrix(dataY, "data_y"), toBoolean(calculateB), toBoolean(verbose));
12902
12912
  },
12903
12913
  isExported: true,
12904
12914
  };
@@ -12915,7 +12925,7 @@ stores.inject(MyMetaStore, storeInstance);
12915
12925
  ],
12916
12926
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
12917
12927
  assertNonEmptyMatrix(dataY, "data_y");
12918
- const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
12928
+ const coeffs = fullLinearRegression(toNumberMatrix(dataX, "data_x"), logM(toNumberMatrix(dataY, "data_y")), toBoolean(calculateB), toBoolean(verbose));
12919
12929
  for (let i = 0; i < coeffs.length; i++) {
12920
12930
  coeffs[i][0] = Math.exp(coeffs[i][0]);
12921
12931
  }
@@ -13505,7 +13515,7 @@ stores.inject(MyMetaStore, storeInstance);
13505
13515
  ],
13506
13516
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13507
13517
  assertNonEmptyMatrix(knownDataY, "known_data_y");
13508
- return predictLinearValues(toNumberMatrix(knownDataY, "the first argument (known_data_y)"), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
13518
+ return predictLinearValues(toNumberMatrix(knownDataY, "known_data_y"), toNumberMatrix(knownDataX, "known_data_x"), toNumberMatrix(newDataX, "new_data_y"), toBoolean(b));
13509
13519
  },
13510
13520
  };
13511
13521
  // -----------------------------------------------------------------------------
@@ -21047,6 +21057,10 @@ stores.inject(MyMetaStore, storeInstance);
21047
21057
  }
21048
21058
  const ctx = chart.ctx;
21049
21059
  ctx.save();
21060
+ const { left, top, height, width } = chart.chartArea;
21061
+ ctx.beginPath();
21062
+ ctx.rect(left, top, width, height);
21063
+ ctx.clip();
21050
21064
  ctx.textAlign = "center";
21051
21065
  ctx.textBaseline = "middle";
21052
21066
  ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
@@ -25175,6 +25189,7 @@ stores.inject(MyMetaStore, storeInstance);
25175
25189
  parser: luxonFormat,
25176
25190
  displayFormats,
25177
25191
  unit: timeUnit ?? false,
25192
+ tooltipFormat: luxonFormat,
25178
25193
  };
25179
25194
  }
25180
25195
  /**
@@ -26244,6 +26259,7 @@ stores.inject(MyMetaStore, storeInstance);
26244
26259
  };
26245
26260
  Object.assign(scales.x, axis);
26246
26261
  scales.x.ticks.maxTicksLimit = 15;
26262
+ delete scales?.x?.ticks?.callback;
26247
26263
  }
26248
26264
  else if (axisType === "linear") {
26249
26265
  scales.x.type = "linear";
@@ -30837,6 +30853,74 @@ stores.inject(MyMetaStore, storeInstance);
30837
30853
  return undefined;
30838
30854
  });
30839
30855
 
30856
+ /**
30857
+ * Get the relative path between two files
30858
+ *
30859
+ * Eg.:
30860
+ * from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
30861
+ */
30862
+ function getRelativePath(from, to) {
30863
+ const fromPathParts = from.split("/");
30864
+ const toPathParts = to.split("/");
30865
+ let relPath = "";
30866
+ let startIndex = 0;
30867
+ for (let i = 0; i < fromPathParts.length - 1; i++) {
30868
+ if (fromPathParts[i] === toPathParts[i]) {
30869
+ startIndex++;
30870
+ }
30871
+ else {
30872
+ relPath += "../";
30873
+ }
30874
+ }
30875
+ relPath += toPathParts.slice(startIndex).join("/");
30876
+ return relPath;
30877
+ }
30878
+ /**
30879
+ * Convert an array of element into an object where the objects keys were the elements position in the array.
30880
+ * Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
30881
+ *
30882
+ * eg. : ["a", "b"] => {0:"a", 1:"b"}
30883
+ */
30884
+ function arrayToObject(array, indexOffset = 0) {
30885
+ const obj = {};
30886
+ for (let i = 0; i < array.length; i++) {
30887
+ if (array[i]) {
30888
+ obj[i + indexOffset] = array[i];
30889
+ }
30890
+ }
30891
+ return obj;
30892
+ }
30893
+ /**
30894
+ * In xlsx we can have string with unicode characters with the format _x00fa_.
30895
+ * Replace with characters understandable by JS
30896
+ */
30897
+ function fixXlsxUnicode(str) {
30898
+ return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
30899
+ return String.fromCharCode(parseInt(code, 16));
30900
+ });
30901
+ }
30902
+ /** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
30903
+ function getSheetDataHeader(sheetData, dimension, index) {
30904
+ if (dimension === "COL") {
30905
+ if (!sheetData.cols[index]) {
30906
+ sheetData.cols[index] = {};
30907
+ }
30908
+ return sheetData.cols[index];
30909
+ }
30910
+ if (!sheetData.rows[index]) {
30911
+ sheetData.rows[index] = {};
30912
+ }
30913
+ return sheetData.rows[index];
30914
+ }
30915
+ /** Prefix the string by "=" if the string looks like a formula */
30916
+ function prefixFormulaWithEqual(formula) {
30917
+ if (formula[0] === "=") {
30918
+ return formula;
30919
+ }
30920
+ const tokens = tokenize(formula);
30921
+ return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
30922
+ }
30923
+
30840
30924
  /**
30841
30925
  * Map of the different types of conversions warnings and their name in error messages
30842
30926
  */
@@ -31344,66 +31428,6 @@ stores.inject(MyMetaStore, storeInstance);
31344
31428
  */
31345
31429
  const DEFAULT_SYSTEM_COLOR = "FF000000";
31346
31430
 
31347
- /**
31348
- * Get the relative path between two files
31349
- *
31350
- * Eg.:
31351
- * from "folder1/file1.txt" to "folder2/file2.txt" => "../folder2/file2.txt"
31352
- */
31353
- function getRelativePath(from, to) {
31354
- const fromPathParts = from.split("/");
31355
- const toPathParts = to.split("/");
31356
- let relPath = "";
31357
- let startIndex = 0;
31358
- for (let i = 0; i < fromPathParts.length - 1; i++) {
31359
- if (fromPathParts[i] === toPathParts[i]) {
31360
- startIndex++;
31361
- }
31362
- else {
31363
- relPath += "../";
31364
- }
31365
- }
31366
- relPath += toPathParts.slice(startIndex).join("/");
31367
- return relPath;
31368
- }
31369
- /**
31370
- * Convert an array of element into an object where the objects keys were the elements position in the array.
31371
- * Can give an offset as argument, and all the array indexes will we shifted by this offset in the returned object.
31372
- *
31373
- * eg. : ["a", "b"] => {0:"a", 1:"b"}
31374
- */
31375
- function arrayToObject(array, indexOffset = 0) {
31376
- const obj = {};
31377
- for (let i = 0; i < array.length; i++) {
31378
- if (array[i]) {
31379
- obj[i + indexOffset] = array[i];
31380
- }
31381
- }
31382
- return obj;
31383
- }
31384
- /**
31385
- * In xlsx we can have string with unicode characters with the format _x00fa_.
31386
- * Replace with characters understandable by JS
31387
- */
31388
- function fixXlsxUnicode(str) {
31389
- return str.replace(/_x([0-9a-zA-Z]{4})_/g, (match, code) => {
31390
- return String.fromCharCode(parseInt(code, 16));
31391
- });
31392
- }
31393
- /** Get a header in the SheetData. Create the header if it doesn't exist in the SheetData */
31394
- function getSheetDataHeader(sheetData, dimension, index) {
31395
- if (dimension === "COL") {
31396
- if (!sheetData.cols[index]) {
31397
- sheetData.cols[index] = {};
31398
- }
31399
- return sheetData.cols[index];
31400
- }
31401
- if (!sheetData.rows[index]) {
31402
- sheetData.rows[index] = {};
31403
- }
31404
- return sheetData.rows[index];
31405
- }
31406
-
31407
31431
  const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
31408
31432
  /**
31409
31433
  * Convert excel format to o_spreadsheet format
@@ -31613,9 +31637,9 @@ stores.inject(MyMetaStore, storeInstance);
31613
31637
  if (!rule.operator || !rule.formula || rule.formula.length === 0)
31614
31638
  continue;
31615
31639
  operator = convertCFCellIsOperator(rule.operator);
31616
- values.push(prefixFormula(rule.formula[0]));
31640
+ values.push(prefixFormulaWithEqual(rule.formula[0]));
31617
31641
  if (rule.formula.length === 2) {
31618
- values.push(prefixFormula(rule.formula[1]));
31642
+ values.push(prefixFormulaWithEqual(rule.formula[1]));
31619
31643
  }
31620
31644
  break;
31621
31645
  }
@@ -31773,11 +31797,6 @@ stores.inject(MyMetaStore, storeInstance);
31773
31797
  ? ICON_SETS[iconSet].neutral
31774
31798
  : ICON_SETS[iconSet].good;
31775
31799
  }
31776
- /** Prefix the string by "=" if the string looks like a formula */
31777
- function prefixFormula(formula) {
31778
- const tokens = tokenize(formula);
31779
- return tokens.length === 1 && tokens[0].type !== "REFERENCE" ? formula : "=" + formula;
31780
- }
31781
31800
  // ---------------------------------------------------------------------------
31782
31801
  // Warnings
31783
31802
  // ---------------------------------------------------------------------------
@@ -32214,7 +32233,7 @@ stores.inject(MyMetaStore, storeInstance);
32214
32233
  dvRules.push(decimalRule);
32215
32234
  break;
32216
32235
  case "list":
32217
- const listRule = convertListrule(dvId++, dv);
32236
+ const listRule = convertListRule(dvId++, dv);
32218
32237
  dvRules.push(listRule);
32219
32238
  break;
32220
32239
  case "date":
@@ -32234,9 +32253,9 @@ stores.inject(MyMetaStore, storeInstance);
32234
32253
  return dvRules;
32235
32254
  }
32236
32255
  function convertDecimalRule(id, dv) {
32237
- const values = [dv.formula1.toString()];
32256
+ const values = [prefixFormulaWithEqual(dv.formula1.toString())];
32238
32257
  if (dv.formula2) {
32239
- values.push(dv.formula2.toString());
32258
+ values.push(prefixFormulaWithEqual(dv.formula2.toString()));
32240
32259
  }
32241
32260
  return {
32242
32261
  id: id.toString(),
@@ -32248,7 +32267,7 @@ stores.inject(MyMetaStore, storeInstance);
32248
32267
  },
32249
32268
  };
32250
32269
  }
32251
- function convertListrule(id, dv) {
32270
+ function convertListRule(id, dv) {
32252
32271
  const formula1 = dv.formula1.toString();
32253
32272
  const isRangeRule = rangeReference.test(formula1);
32254
32273
  return {
@@ -32264,9 +32283,9 @@ stores.inject(MyMetaStore, storeInstance);
32264
32283
  }
32265
32284
  function convertDateRule(id, dv) {
32266
32285
  let criterion;
32267
- const values = [dv.formula1.toString()];
32286
+ const values = [prefixFormulaWithEqual(dv.formula1.toString())];
32268
32287
  if (dv.formula2) {
32269
- values.push(dv.formula2.toString());
32288
+ values.push(prefixFormulaWithEqual(dv.formula2.toString()));
32270
32289
  criterion = {
32271
32290
  type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
32272
32291
  values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
@@ -32293,7 +32312,7 @@ stores.inject(MyMetaStore, storeInstance);
32293
32312
  isBlocking: dv.errorStyle !== "warning",
32294
32313
  criterion: {
32295
32314
  type: "customFormula",
32296
- values: [`=${dv.formula1.toString()}`],
32315
+ values: [prefixFormulaWithEqual(dv.formula1.toString())],
32297
32316
  },
32298
32317
  };
32299
32318
  }
@@ -47292,12 +47311,13 @@ stores.inject(MyMetaStore, storeInstance);
47292
47311
  onCloseSidePanel: { type: Function, optional: true },
47293
47312
  };
47294
47313
  state = owl.useState({ rule: this.defaultDataValidationRule, errors: [] });
47314
+ editingSheetId;
47295
47315
  setup() {
47316
+ this.editingSheetId = this.env.model.getters.getActiveSheetId();
47296
47317
  if (this.props.rule) {
47297
- const sheetId = this.env.model.getters.getActiveSheetId();
47298
47318
  this.state.rule = {
47299
47319
  ...this.props.rule,
47300
- ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, sheetId)),
47320
+ ranges: this.props.rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
47301
47321
  };
47302
47322
  this.state.rule.criterion.type = this.props.rule.criterion.type;
47303
47323
  }
@@ -47331,7 +47351,6 @@ stores.inject(MyMetaStore, storeInstance);
47331
47351
  const locale = this.env.model.getters.getLocale();
47332
47352
  const criterion = rule.criterion;
47333
47353
  const criterionEvaluator = dataValidationEvaluatorRegistry.get(criterion.type);
47334
- const sheetId = this.env.model.getters.getActiveSheetId();
47335
47354
  const values = criterion.values
47336
47355
  .slice(0, criterionEvaluator.numberOfValues(criterion))
47337
47356
  .map((value) => value?.trim())
@@ -47339,8 +47358,8 @@ stores.inject(MyMetaStore, storeInstance);
47339
47358
  .map((value) => canonicalizeContent(value, locale));
47340
47359
  rule.criterion = { ...criterion, values };
47341
47360
  return {
47342
- sheetId,
47343
- ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(sheetId, xc)),
47361
+ sheetId: this.editingSheetId,
47362
+ ranges: this.state.rule.ranges.map((xc) => this.env.model.getters.getRangeDataFromXc(this.editingSheetId, xc)),
47344
47363
  rule,
47345
47364
  };
47346
47365
  }
@@ -47870,6 +47889,7 @@ stores.inject(MyMetaStore, storeInstance);
47870
47889
  .o-button {
47871
47890
  height: 19px;
47872
47891
  width: 19px;
47892
+ box-sizing: content-box;
47873
47893
  .o-icon {
47874
47894
  height: 14px;
47875
47895
  width: 14px;
@@ -64060,7 +64080,7 @@ stores.inject(MyMetaStore, storeInstance);
64060
64080
  * in the correct order they should be evaluated.
64061
64081
  * This is called a topological ordering (excluding cycles)
64062
64082
  */
64063
- getCellsDependingOn(ranges) {
64083
+ getCellsDependingOn(ranges, ignore) {
64064
64084
  const visited = this.createEmptyPositionSet();
64065
64085
  const queue = Array.from(ranges).reverse();
64066
64086
  while (queue.length > 0) {
@@ -64075,7 +64095,7 @@ stores.inject(MyMetaStore, storeInstance);
64075
64095
  const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
64076
64096
  const nextInQueue = {};
64077
64097
  for (const position of impactedPositions) {
64078
- if (!visited.has(position)) {
64098
+ if (!visited.has(position) && !ignore.has(position)) {
64079
64099
  if (!nextInQueue[position.sheetId]) {
64080
64100
  nextInQueue[position.sheetId] = [];
64081
64101
  }
@@ -64632,7 +64652,7 @@ stores.inject(MyMetaStore, storeInstance);
64632
64652
  }
64633
64653
  invalidatePositionsDependingOnSpread(sheetId, resultZone) {
64634
64654
  // the result matrix is split in 2 zones to exclude the array formula position
64635
- const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
64655
+ const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })), this.nextPositionsToUpdate);
64636
64656
  invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
64637
64657
  this.nextPositionsToUpdate.addMany(invalidatedPositions);
64638
64658
  }
@@ -64750,7 +64770,7 @@ stores.inject(MyMetaStore, storeInstance);
64750
64770
  for (const sheetId in zonesBySheetIds) {
64751
64771
  ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
64752
64772
  }
64753
- return this.formulaDependencies().getCellsDependingOn(ranges);
64773
+ return this.formulaDependencies().getCellsDependingOn(ranges, this.nextPositionsToUpdate);
64754
64774
  }
64755
64775
  }
64756
64776
  function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
@@ -65962,7 +65982,8 @@ stores.inject(MyMetaStore, storeInstance);
65962
65982
  const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
65963
65983
  const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
65964
65984
  if (!parentSpreadingCell) {
65965
- return false;
65985
+ const evaluatedCell = this.getters.getEvaluatedCell(topLeft);
65986
+ return (evaluatedCell.value === CellErrorType.SpilledBlocked && !evaluatedCell.errorOriginPosition);
65966
65987
  }
65967
65988
  else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
65968
65989
  return true;
@@ -81033,9 +81054,9 @@ stores.inject(MyMetaStore, storeInstance);
81033
81054
  exports.tokenize = tokenize;
81034
81055
 
81035
81056
 
81036
- __info__.version = "18.3.23";
81037
- __info__.date = "2025-10-07T10:00:57.144Z";
81038
- __info__.hash = "b4764cb";
81057
+ __info__.version = "18.3.24";
81058
+ __info__.date = "2025-10-16T06:38:12.942Z";
81059
+ __info__.hash = "f13dd1c";
81039
81060
 
81040
81061
 
81041
81062
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);