@odoo/o-spreadsheet 17.4.9 → 17.4.11

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.9
6
- * @date 2024-10-14T07:53:51.633Z
7
- * @hash b7015b7
5
+ * @version 17.4.11
6
+ * @date 2024-11-08T12:15:26.239Z
7
+ * @hash 2eb3f1c
8
8
  */
9
9
 
10
10
  'use strict';
@@ -7627,7 +7627,10 @@ function parseOperand(tokens) {
7627
7627
  case "STRING":
7628
7628
  return { type: "STRING", value: removeStringQuotes(current.value) };
7629
7629
  case "INVALID_REFERENCE":
7630
- throw new InvalidReferenceError();
7630
+ return {
7631
+ type: "REFERENCE",
7632
+ value: CellErrorType.InvalidReference,
7633
+ };
7631
7634
  case "REFERENCE":
7632
7635
  if (tokens[0]?.value === ":" && tokens[1]?.type === "REFERENCE") {
7633
7636
  tokens.shift();
@@ -8431,6 +8434,7 @@ const ChartTerms = {
8431
8434
  StackedBarChart: _t("Stacked bar chart"),
8432
8435
  StackedLineChart: _t("Stacked line chart"),
8433
8436
  StackedAreaChart: _t("Stacked area chart"),
8437
+ StackedColumnChart: _t("Stacked column chart"),
8434
8438
  CumulativeData: _t("Cumulative data"),
8435
8439
  TreatLabelsAsText: _t("Treat labels as text"),
8436
8440
  AggregatedChart: _t("Aggregate"),
@@ -10625,67 +10629,112 @@ const chartShowValuesPlugin = {
10625
10629
  ctx.save();
10626
10630
  ctx.textAlign = "center";
10627
10631
  ctx.textBaseline = "middle";
10628
- ctx.fillStyle = chartFontColor(options.background);
10629
- ctx.strokeStyle = chartFontColor(ctx.fillStyle);
10630
- chart._metasets.forEach(function (dataset) {
10631
- switch (dataset.type) {
10632
- case "doughnut":
10633
- case "pie": {
10634
- for (let i = 0; i < dataset._parsed.length; i++) {
10635
- const bar = dataset.data[i];
10636
- const { startAngle, endAngle, innerRadius, outerRadius } = bar;
10637
- const midAngle = (startAngle + endAngle) / 2;
10638
- const midRadius = (innerRadius + outerRadius) / 2;
10639
- const x = bar.x + midRadius * Math.cos(midAngle);
10640
- const y = bar.y + midRadius * Math.sin(midAngle) + 7;
10641
- ctx.fillStyle = chartFontColor(bar.options.backgroundColor);
10642
- ctx.strokeStyle = chartFontColor(ctx.fillStyle);
10643
- const value = options.callback(dataset._parsed[i]);
10644
- ctx.strokeText(value, x, y);
10645
- ctx.fillText(value, x, y);
10646
- }
10647
- break;
10648
- }
10649
- case "bar":
10650
- case "line": {
10651
- const yOffset = dataset.type === "bar" && !options.horizontal ? 0 : 3;
10652
- for (let i = 0; i < dataset._parsed.length; i++) {
10653
- const point = dataset.data[i];
10654
- const value = options.horizontal ? dataset._parsed[i].x : dataset._parsed[i].y;
10655
- const displayedValue = options.callback(value - 0);
10656
- let xPosition = 0, yPosition = 0;
10657
- if (options.horizontal) {
10658
- yPosition = point.y;
10659
- if (value < 0) {
10660
- ctx.textAlign = "right";
10661
- xPosition = point.x - yOffset;
10662
- }
10663
- else {
10664
- ctx.textAlign = "left";
10665
- xPosition = point.x + yOffset;
10666
- }
10667
- }
10668
- else {
10669
- xPosition = point.x;
10670
- if (value < 0) {
10671
- ctx.textBaseline = "top";
10672
- yPosition = point.y + yOffset;
10673
- }
10674
- else {
10675
- ctx.textBaseline = "bottom";
10676
- yPosition = point.y - yOffset;
10677
- }
10678
- }
10679
- ctx.strokeText(displayedValue, xPosition, yPosition);
10680
- ctx.fillText(displayedValue, xPosition, yPosition);
10681
- }
10682
- break;
10683
- }
10684
- }
10685
- });
10632
+ ctx.miterLimit = 1; // Avoid sharp artifacts on strokeText
10633
+ switch (chart.config.type) {
10634
+ case "pie":
10635
+ case "doughnut":
10636
+ drawPieChartValues(chart, options, ctx);
10637
+ break;
10638
+ case "bar":
10639
+ case "line":
10640
+ options.horizontal
10641
+ ? drawHorizontalBarChartValues(chart, options, ctx)
10642
+ : drawLineOrBarChartValues(chart, options, ctx);
10643
+ break;
10644
+ }
10686
10645
  ctx.restore();
10687
10646
  },
10688
10647
  };
10648
+ function drawTextWithBackground(text, x, y, ctx) {
10649
+ ctx.lineWidth = 3; // Stroke the text with a big lineWidth width to have some kind of background
10650
+ ctx.strokeText(text, x, y);
10651
+ ctx.lineWidth = 1;
10652
+ ctx.fillText(text, x, y);
10653
+ }
10654
+ function drawLineOrBarChartValues(chart, options, ctx) {
10655
+ const yMax = chart.chartArea.bottom;
10656
+ const yMin = chart.chartArea.top;
10657
+ const textsPositions = {};
10658
+ for (const dataset of chart._metasets) {
10659
+ for (let i = 0; i < dataset._parsed.length; i++) {
10660
+ const value = dataset._parsed[i].y;
10661
+ const point = dataset.data[i];
10662
+ const xPosition = point.x;
10663
+ let yPosition = 0;
10664
+ if (chart.config.type === "line") {
10665
+ yPosition = point.y - 10;
10666
+ }
10667
+ else {
10668
+ yPosition = value < 0 ? point.y - point.height / 2 : point.y + point.height / 2;
10669
+ }
10670
+ yPosition = Math.min(yPosition, yMax);
10671
+ yPosition = Math.max(yPosition, yMin);
10672
+ // Avoid overlapping texts with same X
10673
+ if (!textsPositions[xPosition]) {
10674
+ textsPositions[xPosition] = [];
10675
+ }
10676
+ for (const otherPosition of textsPositions[xPosition] || []) {
10677
+ if (Math.abs(otherPosition - yPosition) < 13) {
10678
+ yPosition = otherPosition - 13;
10679
+ }
10680
+ }
10681
+ textsPositions[xPosition].push(yPosition);
10682
+ ctx.fillStyle = point.options.backgroundColor;
10683
+ ctx.strokeStyle = options.background || "#ffffff";
10684
+ drawTextWithBackground(options.callback(value - 0), xPosition, yPosition, ctx);
10685
+ }
10686
+ }
10687
+ }
10688
+ function drawHorizontalBarChartValues(chart, options, ctx) {
10689
+ const xMax = chart.chartArea.right;
10690
+ const xMin = chart.chartArea.left;
10691
+ const textsPositions = {};
10692
+ for (const dataset of chart._metasets) {
10693
+ for (let i = 0; i < dataset._parsed.length; i++) {
10694
+ const value = dataset._parsed[i].x;
10695
+ const displayValue = options.callback(value - 0);
10696
+ const point = dataset.data[i];
10697
+ const yPosition = point.y;
10698
+ let xPosition = value < 0 ? point.x + point.width / 2 : point.x - point.width / 2;
10699
+ xPosition = Math.min(xPosition, xMax);
10700
+ xPosition = Math.max(xPosition, xMin);
10701
+ // Avoid overlapping texts with same Y
10702
+ if (!textsPositions[yPosition]) {
10703
+ textsPositions[yPosition] = [];
10704
+ }
10705
+ const textWidth = computeTextWidth(ctx, displayValue, { fontSize: 12 }, "px");
10706
+ for (const otherPosition of textsPositions[yPosition]) {
10707
+ if (Math.abs(otherPosition - xPosition) < textWidth) {
10708
+ xPosition = otherPosition + textWidth + 3;
10709
+ }
10710
+ }
10711
+ textsPositions[yPosition].push(xPosition);
10712
+ ctx.fillStyle = point.options.backgroundColor;
10713
+ ctx.strokeStyle = options.background || "#ffffff";
10714
+ drawTextWithBackground(displayValue, xPosition, yPosition, ctx);
10715
+ }
10716
+ }
10717
+ }
10718
+ function drawPieChartValues(chart, options, ctx) {
10719
+ for (const dataset of chart._metasets) {
10720
+ for (let i = 0; i < dataset._parsed.length; i++) {
10721
+ const value = Number(dataset._parsed[i]);
10722
+ if (isNaN(value) || value === 0) {
10723
+ continue;
10724
+ }
10725
+ const bar = dataset.data[i];
10726
+ const { startAngle, endAngle, innerRadius, outerRadius } = bar;
10727
+ const midAngle = (startAngle + endAngle) / 2;
10728
+ const midRadius = (innerRadius + outerRadius) / 2;
10729
+ const x = bar.x + midRadius * Math.cos(midAngle);
10730
+ const y = bar.y + midRadius * Math.sin(midAngle) + 7;
10731
+ ctx.fillStyle = chartFontColor(options.background);
10732
+ ctx.strokeStyle = options.background || "#ffffff";
10733
+ const displayValue = options.callback(value);
10734
+ drawTextWithBackground(displayValue, x, y, ctx);
10735
+ }
10736
+ }
10737
+ }
10689
10738
 
10690
10739
  /** This is a chartJS plugin that will draw connector lines between the bars of a Waterfall chart */
10691
10740
  const waterfallLinesPlugin = {
@@ -23415,7 +23464,7 @@ function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, tr
23415
23464
  const xLabel = tooltipItem.dataset?.label || tooltipItem.label;
23416
23465
  // tooltipItem.parsed can be an object or a number for pie charts
23417
23466
  let yLabel = horizontalChart ? tooltipItem.parsed.x : tooltipItem.parsed.y;
23418
- if (!yLabel) {
23467
+ if (yLabel === undefined || yLabel === null) {
23419
23468
  yLabel = tooltipItem.parsed;
23420
23469
  }
23421
23470
  const toolTipFormat = !format && Math.abs(yLabel) >= 1000 ? "#,##" : format;
@@ -31586,6 +31635,12 @@ class GenericChartConfigPanel extends owl.Component {
31586
31635
 
31587
31636
  class BarConfigPanel extends GenericChartConfigPanel {
31588
31637
  static template = "o-spreadsheet-BarConfigPanel";
31638
+ get stackedLabel() {
31639
+ const definition = this.props.definition;
31640
+ return definition.horizontal
31641
+ ? this.chartTerms.StackedBarChart
31642
+ : this.chartTerms.StackedColumnChart;
31643
+ }
31589
31644
  onUpdateStacked(stacked) {
31590
31645
  this.props.updateChart(this.props.figureId, {
31591
31646
  stacked,
@@ -32754,7 +32809,9 @@ class LineConfigPanel extends GenericChartConfigPanel {
32754
32809
  }
32755
32810
  get stackedLabel() {
32756
32811
  const definition = this.props.definition;
32757
- return definition.fillArea ? this.chartTerms.StackedAreaChart : this.chartTerms.StackedBarChart;
32812
+ return definition.fillArea
32813
+ ? this.chartTerms.StackedAreaChart
32814
+ : this.chartTerms.StackedLineChart;
32758
32815
  }
32759
32816
  getLabelRangeOptions() {
32760
32817
  const options = super.getLabelRangeOptions();
@@ -46532,7 +46589,7 @@ function load(data, verboseImport) {
46532
46589
  if (!data) {
46533
46590
  return createEmptyWorkbookData();
46534
46591
  }
46535
- console.group("Loading data");
46592
+ console.debug("### Loading data ###");
46536
46593
  const start = performance.now();
46537
46594
  if (data["[Content_Types].xml"]) {
46538
46595
  const reader = new XlsxReader(data);
@@ -46546,13 +46603,13 @@ function load(data, verboseImport) {
46546
46603
  // apply migrations, if needed
46547
46604
  if ("version" in data) {
46548
46605
  if (data.version < CURRENT_VERSION) {
46549
- console.info("Migrating data from version", data.version);
46606
+ console.debug("Migrating data from version", data.version);
46550
46607
  data = migrate(data);
46551
46608
  }
46552
46609
  }
46553
46610
  data = repairData(data);
46554
- console.info("Data loaded in", performance.now() - start, "ms");
46555
- console.groupEnd();
46611
+ console.debug("Data loaded in", performance.now() - start, "ms");
46612
+ console.debug("###");
46556
46613
  return data;
46557
46614
  }
46558
46615
  function migrate(data) {
@@ -46561,7 +46618,7 @@ function migrate(data) {
46561
46618
  for (let i = index; i < MIGRATIONS.length; i++) {
46562
46619
  data = MIGRATIONS[i].applyMigration(data);
46563
46620
  }
46564
- console.info("Data migrated in", performance.now() - start, "ms");
46621
+ console.debug("Data migrated in", performance.now() - start, "ms");
46565
46622
  return data;
46566
46623
  }
46567
46624
  const MIGRATIONS = [
@@ -54121,7 +54178,7 @@ class Evaluator {
54121
54178
  cellsToCompute.addMany(arrayFormulasPositions);
54122
54179
  cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositions));
54123
54180
  this.evaluate(cellsToCompute);
54124
- console.info("evaluate Cells", performance.now() - start, "ms");
54181
+ console.debug("evaluate Cells", performance.now() - start, "ms");
54125
54182
  }
54126
54183
  getArrayFormulasImpactedByChangesOf(positions) {
54127
54184
  const impactedPositions = this.createEmptyPositionSet();
@@ -54160,7 +54217,7 @@ class Evaluator {
54160
54217
  const start = performance.now();
54161
54218
  this.evaluatedCells = new PositionMap();
54162
54219
  this.evaluate(this.getAllCells());
54163
- console.info("evaluate all cells", performance.now() - start, "ms");
54220
+ console.debug("evaluate all cells", performance.now() - start, "ms");
54164
54221
  }
54165
54222
  evaluateFormulaResult(sheetId, formulaString) {
54166
54223
  try {
@@ -55982,6 +56039,10 @@ class PivotUIPlugin extends UIPlugin {
55982
56039
  if (!pivot.isValid()) {
55983
56040
  return EMPTY_PIVOT_CELL;
55984
56041
  }
56042
+ if (functionName === "PIVOT" &&
56043
+ !cell.content.replaceAll(" ", "").toUpperCase().startsWith("=PIVOT")) {
56044
+ return EMPTY_PIVOT_CELL;
56045
+ }
55985
56046
  if (functionName === "PIVOT") {
55986
56047
  const includeTotal = args[2] === false ? false : undefined;
55987
56048
  const includeColumnHeaders = args[3] === false ? false : undefined;
@@ -57310,7 +57371,7 @@ class Session extends EventBus {
57310
57371
  this.onMessageReceived(message);
57311
57372
  }
57312
57373
  this.isReplayingInitialRevisions = false;
57313
- console.info("Replayed", numberOfCommands, "commands in", performance.now() - start, "ms");
57374
+ console.debug("Replayed", numberOfCommands, "commands in", performance.now() - start, "ms");
57314
57375
  }
57315
57376
  /**
57316
57377
  * Notify the server that the user client left the collaborative session
@@ -66573,7 +66634,8 @@ function addFormula(cell) {
66573
66634
  }
66574
66635
  const attrs = [["t", type]];
66575
66636
  const XlsxFormula = adaptFormulaToExcel(formula);
66576
- const node = escapeXml /*xml*/ `<f>${XlsxFormula}</f><v>${cell.value}</v>`;
66637
+ const exportedValue = adaptFormulaValueToExcel(cell.value);
66638
+ const node = escapeXml /*xml*/ `<f>${XlsxFormula}</f><v>${exportedValue}</v>`;
66577
66639
  return { attrs, node };
66578
66640
  }
66579
66641
  function addContent(content, sharedStrings, forceString = false) {
@@ -66608,8 +66670,14 @@ function adaptFormulaToExcel(formulaText) {
66608
66670
  ast = addMissingRequiredArgs(ast);
66609
66671
  return ast;
66610
66672
  });
66673
+ ast = convertAstNodes(ast, "REFERENCE", (ast) => {
66674
+ return ast.value === CellErrorType.InvalidReference ? { ...ast, value: "#REF!" } : ast;
66675
+ });
66611
66676
  return ast ? astToFormula(ast) : formulaText;
66612
66677
  }
66678
+ function adaptFormulaValueToExcel(formulaValue) {
66679
+ return formulaValue === CellErrorType.InvalidReference ? "#REF!" : formulaValue;
66680
+ }
66613
66681
  /**
66614
66682
  * Some Excel function need required args that might not be mandatory in o-spreadsheet.
66615
66683
  * This adds those missing args.
@@ -67920,7 +67988,7 @@ class Model extends EventBus {
67920
67988
  coreHandlers = [];
67921
67989
  constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
67922
67990
  const start = performance.now();
67923
- console.group("Model creation");
67991
+ console.debug("##### Model creation #####");
67924
67992
  super();
67925
67993
  setDefaultTranslationMethod();
67926
67994
  stateUpdateMessages = repairInitialMessages(data, stateUpdateMessages);
@@ -67992,16 +68060,16 @@ class Model extends EventBus {
67992
68060
  this.joinSession();
67993
68061
  if (config.snapshotRequested) {
67994
68062
  const startSnapshot = performance.now();
67995
- console.info("Snapshot requested");
68063
+ console.debug("Snapshot requested");
67996
68064
  this.session.snapshot(this.exportData());
67997
68065
  this.garbageCollectExternalResources();
67998
- console.info("Snapshot taken in", performance.now() - startSnapshot, "ms");
68066
+ console.debug("Snapshot taken in", performance.now() - startSnapshot, "ms");
67999
68067
  }
68000
68068
  // mark all models as "raw", so they will not be turned into reactive objects
68001
68069
  // by owl, since we do not rely on reactivity
68002
68070
  owl.markRaw(this);
68003
- console.info("Model created in", performance.now() - start, "ms");
68004
- console.groupEnd();
68071
+ console.debug("Model created in", performance.now() - start, "ms");
68072
+ console.debug("######");
68005
68073
  }
68006
68074
  joinSession() {
68007
68075
  this.session.join(this.config.client);
@@ -68224,7 +68292,7 @@ class Model extends EventBus {
68224
68292
  this.finalize();
68225
68293
  const time = performance.now() - start;
68226
68294
  if (time > 5) {
68227
- console.info(type, time, "ms");
68295
+ console.debug(type, time, "ms");
68228
68296
  }
68229
68297
  });
68230
68298
  this.session.save(command, commands, changes);
@@ -68610,6 +68678,6 @@ exports.tokenColors = tokenColors;
68610
68678
  exports.tokenize = tokenize;
68611
68679
 
68612
68680
 
68613
- __info__.version = "17.4.9";
68614
- __info__.date = "2024-10-14T07:53:51.633Z";
68615
- __info__.hash = "b7015b7";
68681
+ __info__.version = "17.4.11";
68682
+ __info__.date = "2024-11-08T12:15:26.239Z";
68683
+ __info__.hash = "2eb3f1c";
@@ -6714,6 +6714,7 @@ declare class GenericChartConfigPanel extends Component<Props$W, SpreadsheetChil
6714
6714
  StackedBarChart: string;
6715
6715
  StackedLineChart: string;
6716
6716
  StackedAreaChart: string;
6717
+ StackedColumnChart: string;
6717
6718
  CumulativeData: string;
6718
6719
  TreatLabelsAsText: string;
6719
6720
  AggregatedChart: string;
@@ -6766,6 +6767,7 @@ declare class GenericChartConfigPanel extends Component<Props$W, SpreadsheetChil
6766
6767
 
6767
6768
  declare class BarConfigPanel extends GenericChartConfigPanel {
6768
6769
  static template: string;
6770
+ get stackedLabel(): string;
6769
6771
  onUpdateStacked(stacked: boolean): void;
6770
6772
  onUpdateAggregated(aggregated: boolean): void;
6771
6773
  }
@@ -11615,6 +11617,7 @@ declare const constants: {
11615
11617
  StackedBarChart: string;
11616
11618
  StackedLineChart: string;
11617
11619
  StackedAreaChart: string;
11620
+ StackedColumnChart: string;
11618
11621
  CumulativeData: string;
11619
11622
  TreatLabelsAsText: string;
11620
11623
  AggregatedChart: string;