@odoo/o-spreadsheet 17.4.3 → 17.4.4

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 17.4.3
6
- * @date 2024-08-02T08:23:56.573Z
7
- * @hash 40ecd1e
5
+ * @version 17.4.4
6
+ * @date 2024-08-09T12:24:07.798Z
7
+ * @hash a43e855
8
8
  */
9
9
 
10
10
  'use strict';
@@ -10578,6 +10578,18 @@ function getDefinedAxis(definition) {
10578
10578
  useLeftAxis ||= !useRightAxis;
10579
10579
  return { useLeftAxis, useRightAxis };
10580
10580
  }
10581
+ function formatTickValue(localeFormat) {
10582
+ return (value) => {
10583
+ value = Number(value);
10584
+ if (isNaN(value))
10585
+ return value;
10586
+ const { locale, format } = localeFormat;
10587
+ return formatValue(value, {
10588
+ locale,
10589
+ format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
10590
+ });
10591
+ };
10592
+ }
10581
10593
 
10582
10594
  /** This is a chartJS plugin that will draw the values of each data next to the point/bar/pie slice */
10583
10595
  const chartShowValuesPlugin = {
@@ -19126,6 +19138,7 @@ const PIVOT_VALUE = {
19126
19138
  const pivot = this.getters.getPivot(pivotId);
19127
19139
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
19128
19140
  addPivotDependencies(this, coreDefinition);
19141
+ pivot.init({ reload: pivot.needsReevaluation });
19129
19142
  const error = pivot.assertIsValid({ throwOnError: false });
19130
19143
  if (error) {
19131
19144
  return error;
@@ -19154,6 +19167,7 @@ const PIVOT_HEADER = {
19154
19167
  const pivot = this.getters.getPivot(_pivotId);
19155
19168
  const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19156
19169
  addPivotDependencies(this, coreDefinition);
19170
+ pivot.init({ reload: pivot.needsReevaluation });
19157
19171
  const error = pivot.assertIsValid({ throwOnError: false });
19158
19172
  if (error) {
19159
19173
  return error;
@@ -20371,14 +20385,6 @@ for (let category of categories) {
20371
20385
  }
20372
20386
  const notAvailableError = new NotAvailableError(_t("Array arguments to [[FUNCTION_NAME]] are of different size."));
20373
20387
  function createComputeFunction(descr, functionName) {
20374
- function runtimeCompute(...args) {
20375
- try {
20376
- return vectorizedCompute.apply(this, args);
20377
- }
20378
- catch (e) {
20379
- return handleError(e, functionName);
20380
- }
20381
- }
20382
20388
  function vectorizedCompute(...args) {
20383
20389
  let countVectorizableCol = 1;
20384
20390
  let countVectorizableRow = 1;
@@ -20419,13 +20425,13 @@ function createComputeFunction(descr, functionName) {
20419
20425
  }
20420
20426
  }
20421
20427
  if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
20422
- throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
20428
+ throw new BadExpressionError(_t("Function %s expects the parameter '%s' to be reference to a cell or range.", functionName, (i + 1).toString()));
20423
20429
  }
20424
20430
  }
20425
20431
  //#endregion
20426
20432
  if (countVectorizableCol === 1 && countVectorizableRow === 1) {
20427
20433
  // either this function is not vectorized or it ends up with a 1x1 dimension
20428
- return computeFunctionToObject.apply(this, args);
20434
+ return errorHandlingCompute.apply(this, args);
20429
20435
  }
20430
20436
  const getArgOffset = (i, j) => args.map((arg, index) => {
20431
20437
  switch (vectorArgsType?.[index]) {
@@ -20443,7 +20449,7 @@ function createComputeFunction(descr, functionName) {
20443
20449
  if (col > vectorizableColLimit - 1 || row > vectorizableRowLimit - 1) {
20444
20450
  return notAvailableError;
20445
20451
  }
20446
- const singleCellComputeResult = computeFunctionToObject.apply(this, getArgOffset(col, row));
20452
+ const singleCellComputeResult = errorHandlingCompute.apply(this, getArgOffset(col, row));
20447
20453
  // In the case where the user tries to vectorize arguments of an array formula, we will get an
20448
20454
  // array for every combination of the vectorized arguments, which will lead to a 3D matrix and
20449
20455
  // we won't be able to return the values.
@@ -20458,6 +20464,14 @@ function createComputeFunction(descr, functionName) {
20458
20464
  : singleCellComputeResult;
20459
20465
  });
20460
20466
  }
20467
+ function errorHandlingCompute(...args) {
20468
+ try {
20469
+ return computeFunctionToObject.apply(this, args);
20470
+ }
20471
+ catch (e) {
20472
+ return handleError(e, functionName);
20473
+ }
20474
+ }
20461
20475
  function computeFunctionToObject(...args) {
20462
20476
  const result = descr.compute.apply(this, args);
20463
20477
  if (!isMatrix(result)) {
@@ -20473,7 +20487,7 @@ function createComputeFunction(descr, functionName) {
20473
20487
  }
20474
20488
  return matrixMap(result, (row) => ({ value: row }));
20475
20489
  }
20476
- return runtimeCompute;
20490
+ return vectorizedCompute;
20477
20491
  }
20478
20492
  function handleError(e, functionName) {
20479
20493
  // the error could be an user error (instance of EvaluationError)
@@ -23694,23 +23708,13 @@ function getBarConfiguration(chart, labels, localeFormat) {
23694
23708
  padding: { left: 20, right: 20, top: chart.title ? 10 : 25, bottom: 10 },
23695
23709
  };
23696
23710
  config.options.indexAxis = chart.horizontal ? "y" : "x";
23697
- const formatCallback = (value) => {
23698
- value = Number(value);
23699
- if (isNaN(value))
23700
- return value;
23701
- const { locale, format } = localeFormat;
23702
- return formatValue(value, {
23703
- locale,
23704
- format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
23705
- });
23706
- };
23707
23711
  config.options.scales = {};
23708
23712
  const labelsAxis = { ticks: { padding: 5, color: fontColor } };
23709
23713
  const valuesAxis = {
23710
23714
  beginAtZero: true, // the origin of the y axis is always zero
23711
23715
  ticks: {
23712
23716
  color: fontColor,
23713
- callback: formatCallback,
23717
+ callback: formatTickValue(localeFormat),
23714
23718
  },
23715
23719
  };
23716
23720
  const xAxis = chart.horizontal ? valuesAxis : labelsAxis;
@@ -23747,7 +23751,7 @@ function getBarConfiguration(chart, labels, localeFormat) {
23747
23751
  showValues: chart.showValues,
23748
23752
  background: chart.background,
23749
23753
  horizontal: chart.horizontal,
23750
- callback: formatCallback,
23754
+ callback: formatTickValue(localeFormat),
23751
23755
  };
23752
23756
  return config;
23753
23757
  }
@@ -24026,21 +24030,11 @@ function getLineOrScatterConfiguration(chart, labels, options) {
24026
24030
  title: getChartAxisTitleRuntime(chart.axesDesign?.x),
24027
24031
  },
24028
24032
  };
24029
- const formatCallback = (value) => {
24030
- value = Number(value);
24031
- if (isNaN(value))
24032
- return value;
24033
- const { locale, format } = options;
24034
- return formatValue(value, {
24035
- locale,
24036
- format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
24037
- });
24038
- };
24039
24033
  const yAxis = {
24040
24034
  beginAtZero: true, // the origin of the y axis is always zero
24041
24035
  ticks: {
24042
24036
  color: fontColor,
24043
- callback: formatCallback,
24037
+ callback: formatTickValue(options),
24044
24038
  },
24045
24039
  };
24046
24040
  const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
@@ -24071,7 +24065,7 @@ function getLineOrScatterConfiguration(chart, labels, options) {
24071
24065
  config.options.plugins.chartShowValuesPlugin = {
24072
24066
  showValues: chart.showValues,
24073
24067
  background: chart.background,
24074
- callback: formatCallback,
24068
+ callback: formatTickValue(options),
24075
24069
  };
24076
24070
  return config;
24077
24071
  }
@@ -24346,30 +24340,18 @@ function createComboChartRuntime(chart, getters) {
24346
24340
  title: getChartAxisTitleRuntime(chart.axesDesign?.x),
24347
24341
  },
24348
24342
  };
24349
- const formatCallback = (format) => {
24350
- return (value) => {
24351
- value = Number(value);
24352
- if (isNaN(value))
24353
- return value;
24354
- const { locale } = localeFormat;
24355
- return formatValue(value, {
24356
- locale,
24357
- format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
24358
- });
24359
- };
24360
- };
24361
24343
  const leftVerticalAxis = {
24362
24344
  beginAtZero: true, // the origin of the y axis is always zero
24363
24345
  ticks: {
24364
24346
  color: fontColor,
24365
- callback: formatCallback(mainDataSetFormat),
24347
+ callback: formatTickValue({ format: mainDataSetFormat, locale }),
24366
24348
  },
24367
24349
  };
24368
24350
  const rightVerticalAxis = {
24369
24351
  beginAtZero: true, // the origin of the y axis is always zero
24370
24352
  ticks: {
24371
24353
  color: fontColor,
24372
- callback: formatCallback(lineDataSetsFormat),
24354
+ callback: formatTickValue({ format: lineDataSetsFormat, locale }),
24373
24355
  },
24374
24356
  };
24375
24357
  const definition = chart.getDefinition();
@@ -24394,7 +24376,7 @@ function createComboChartRuntime(chart, getters) {
24394
24376
  config.options.plugins.chartShowValuesPlugin = {
24395
24377
  showValues: chart.showValues,
24396
24378
  background: chart.background,
24397
- callback: formatCallback(mainDataSetFormat),
24379
+ callback: formatTickValue({ format: mainDataSetFormat, locale }),
24398
24380
  };
24399
24381
  const colors = new ColorGenerator();
24400
24382
  for (let [index, { label, data }] of dataSetsValues.entries()) {
@@ -24926,7 +24908,10 @@ function getPieConfiguration(chart, labels, localeFormat) {
24926
24908
  const yLabelStr = formatValue(yLabel, { format: toolTipFormat, locale });
24927
24909
  return xLabel ? `${xLabel}: ${yLabelStr} (${percentage}%)` : `${yLabelStr} (${percentage}%)`;
24928
24910
  };
24929
- config.options.plugins.chartShowValuesPlugin = { showValues: chart.showValues };
24911
+ config.options.plugins.chartShowValuesPlugin = {
24912
+ showValues: chart.showValues,
24913
+ callback: formatTickValue(localeFormat),
24914
+ };
24930
24915
  return config;
24931
24916
  }
24932
24917
  function getPieColors(colors, dataSetsValues) {
@@ -25510,6 +25495,7 @@ function getWaterfallConfiguration(chart, labels, dataSeriesLabels, localeFormat
25510
25495
  config.options.plugins.chartShowValuesPlugin = {
25511
25496
  showValues: chart.showValues,
25512
25497
  background: chart.background,
25498
+ callback: formatTickValue(localeFormat),
25513
25499
  };
25514
25500
  return config;
25515
25501
  }
@@ -50414,7 +50400,7 @@ class RangeAdapter {
50414
50400
  * @param sheetXC the string description of a range, in the form SheetName!XC:XC
50415
50401
  */
50416
50402
  getRangeFromSheetXC(defaultSheetId, sheetXC) {
50417
- if (!rangeReference.test(sheetXC)) {
50403
+ if (!rangeReference.test(sheetXC) || !this.getters.tryGetSheet(defaultSheetId)) {
50418
50404
  return new RangeImpl({
50419
50405
  sheetId: "",
50420
50406
  zone: { left: -1, top: -1, right: -1, bottom: -1 },
@@ -54067,18 +54053,23 @@ class Evaluator {
54067
54053
  this.evaluate(this.getAllCells());
54068
54054
  console.info("evaluate all cells", performance.now() - start, "ms");
54069
54055
  }
54070
- evaluateFormula(sheetId, formulaString) {
54071
- const compiledFormula = compile(formulaString);
54072
- const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
54073
- this.updateCompilationParameters();
54074
- const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
54075
- if (isMatrix(result)) {
54076
- return matrixMap(result, (cell) => cell.value);
54056
+ evaluateFormulaResult(sheetId, formulaString) {
54057
+ try {
54058
+ const compiledFormula = compile(formulaString);
54059
+ const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
54060
+ this.updateCompilationParameters();
54061
+ const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
54062
+ if (isMatrix(result)) {
54063
+ return result;
54064
+ }
54065
+ if (result.value === null) {
54066
+ return { value: 0, format: result.format };
54067
+ }
54068
+ return result;
54077
54069
  }
54078
- if (result.value === null) {
54079
- return 0;
54070
+ catch (error) {
54071
+ return handleError(error, "");
54080
54072
  }
54081
- return result.value;
54082
54073
  }
54083
54074
  getAllCells() {
54084
54075
  const positions = this.createEmptyPositionSet();
@@ -54441,6 +54432,7 @@ function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId
54441
54432
  class EvaluationPlugin extends UIPlugin {
54442
54433
  static getters = [
54443
54434
  "evaluateFormula",
54435
+ "evaluateFormulaResult",
54444
54436
  "getCorrespondingFormulaCell",
54445
54437
  "getRangeFormattedValues",
54446
54438
  "getRangeValues",
@@ -54500,12 +54492,14 @@ class EvaluationPlugin extends UIPlugin {
54500
54492
  // Getters
54501
54493
  // ---------------------------------------------------------------------------
54502
54494
  evaluateFormula(sheetId, formulaString) {
54503
- try {
54504
- return this.evaluator.evaluateFormula(sheetId, formulaString);
54505
- }
54506
- catch (error) {
54507
- return error.value || CellErrorType.GenericError;
54495
+ const result = this.evaluateFormulaResult(sheetId, formulaString);
54496
+ if (isMatrix(result)) {
54497
+ return matrixMap(result, (cell) => cell.value);
54508
54498
  }
54499
+ return result.value;
54500
+ }
54501
+ evaluateFormulaResult(sheetId, formulaString) {
54502
+ return this.evaluator.evaluateFormulaResult(sheetId, formulaString);
54509
54503
  }
54510
54504
  /**
54511
54505
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -55888,28 +55882,33 @@ class PivotUIPlugin extends UIPlugin {
55888
55882
  const pivotRow = position.row - mainPosition.row;
55889
55883
  return pivotCells[pivotCol][pivotRow];
55890
55884
  }
55891
- if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
55892
- const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
55885
+ try {
55886
+ if (functionName === "PIVOT.HEADER" && args.at(-2) === "measure") {
55887
+ const domain = pivot.parseArgsToPivotDomain(args.slice(1, -2).map((value) => ({ value })));
55888
+ return {
55889
+ type: "MEASURE_HEADER",
55890
+ domain,
55891
+ measure: args.at(-1)?.toString() || "",
55892
+ };
55893
+ }
55894
+ else if (functionName === "PIVOT.HEADER") {
55895
+ const domain = pivot.parseArgsToPivotDomain(args.slice(1).map((value) => ({ value })));
55896
+ return {
55897
+ type: "HEADER",
55898
+ domain,
55899
+ };
55900
+ }
55901
+ const [measure, ...domainArgs] = args.slice(1);
55902
+ const domain = pivot.parseArgsToPivotDomain(domainArgs.map((value) => ({ value })));
55893
55903
  return {
55894
- type: "MEASURE_HEADER",
55904
+ type: "VALUE",
55895
55905
  domain,
55896
- measure: args.at(-1)?.toString() || "",
55906
+ measure: measure?.toString() || "",
55897
55907
  };
55898
55908
  }
55899
- else if (functionName === "PIVOT.HEADER") {
55900
- const domain = pivot.parseArgsToPivotDomain(args.slice(1).map((value) => ({ value })));
55901
- return {
55902
- type: "HEADER",
55903
- domain,
55904
- };
55909
+ catch (_) {
55910
+ return EMPTY_PIVOT_CELL;
55905
55911
  }
55906
- const [measure, ...domainArgs] = args.slice(1);
55907
- const domain = pivot.parseArgsToPivotDomain(domainArgs.map((value) => ({ value })));
55908
- return {
55909
- type: "VALUE",
55910
- domain,
55911
- measure: measure?.toString() || "",
55912
- };
55913
55912
  }
55914
55913
  getPivot(pivotId) {
55915
55914
  return this.pivots[pivotId];
@@ -57777,6 +57776,7 @@ class FormatPlugin extends UIPlugin {
57777
57776
  * evaluated and updated with the number type.
57778
57777
  */
57779
57778
  setDecimal(sheetId, zones, step) {
57779
+ const positionsByFormat = {};
57780
57780
  // Find the each cell with a number value and get the format
57781
57781
  for (const zone of recomputeZones(zones)) {
57782
57782
  for (const position of positions(zone)) {
@@ -57786,15 +57786,20 @@ class FormatPlugin extends UIPlugin {
57786
57786
  // of the format
57787
57787
  this.getters.getLocale();
57788
57788
  const newFormat = changeDecimalPlaces(numberFormat, step);
57789
- // Apply the new format on the whole zone
57790
- this.dispatch("SET_FORMATTING", {
57791
- sheetId,
57792
- target: [positionToZone(position)],
57793
- format: newFormat,
57794
- });
57789
+ positionsByFormat[newFormat] = positionsByFormat[newFormat] || [];
57790
+ positionsByFormat[newFormat].push(position);
57795
57791
  }
57796
57792
  }
57797
57793
  }
57794
+ // consolidate all positions with the same format in bigger zones
57795
+ for (const newFormat in positionsByFormat) {
57796
+ const zones = recomputeZones(positionsByFormat[newFormat].map((position) => positionToZone(position)));
57797
+ this.dispatch("SET_FORMATTING", {
57798
+ sheetId,
57799
+ format: newFormat,
57800
+ target: zones,
57801
+ });
57802
+ }
57798
57803
  }
57799
57804
  /**
57800
57805
  * Take a range of cells and return the format of the first cell containing a
@@ -68424,6 +68429,6 @@ exports.tokenColors = tokenColors;
68424
68429
  exports.tokenize = tokenize;
68425
68430
 
68426
68431
 
68427
- __info__.version = "17.4.3";
68428
- __info__.date = "2024-08-02T08:23:56.573Z";
68429
- __info__.hash = "40ecd1e";
68432
+ __info__.version = "17.4.4";
68433
+ __info__.date = "2024-08-09T12:24:07.798Z";
68434
+ __info__.hash = "a43e855";
@@ -3976,7 +3976,7 @@ declare class UIPlugin<State = any> extends BasePlugin<State, Command> {
3976
3976
  }
3977
3977
 
3978
3978
  declare class EvaluationPlugin extends UIPlugin {
3979
- static getters: readonly ["evaluateFormula", "getCorrespondingFormulaCell", "getRangeFormattedValues", "getRangeValues", "getRangeFormats", "getEvaluatedCell", "getEvaluatedCells", "getEvaluatedCellsInZone", "getEvaluatedCellsPositions", "getSpreadZone", "getArrayFormulaSpreadingOn", "isEmpty"];
3979
+ static getters: readonly ["evaluateFormula", "evaluateFormulaResult", "getCorrespondingFormulaCell", "getRangeFormattedValues", "getRangeValues", "getRangeFormats", "getEvaluatedCell", "getEvaluatedCells", "getEvaluatedCellsInZone", "getEvaluatedCellsPositions", "getSpreadZone", "getArrayFormulaSpreadingOn", "isEmpty"];
3980
3980
  private shouldRebuildDependenciesGraph;
3981
3981
  private evaluator;
3982
3982
  private positionsToUpdate;
@@ -3985,6 +3985,7 @@ declare class EvaluationPlugin extends UIPlugin {
3985
3985
  handle(cmd: CoreViewCommand): void;
3986
3986
  finalize(): void;
3987
3987
  evaluateFormula(sheetId: UID, formulaString: string): CellValue | Matrix<CellValue>;
3988
+ evaluateFormulaResult(sheetId: UID, formulaString: string): Matrix<FunctionResultObject> | FunctionResultObject;
3988
3989
  /**
3989
3990
  * Return the value of each cell in the range as they are displayed in the grid.
3990
3991
  */