@odoo/o-spreadsheet 18.0.43 → 18.0.45

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.0.43
6
- * @date 2025-09-05T07:38:36.406Z
7
- * @hash 0f02dde
5
+ * @version 18.0.45
6
+ * @date 2025-09-19T07:24:19.143Z
7
+ * @hash 54e799a
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -854,8 +854,19 @@ function memoize(func) {
854
854
  },
855
855
  }[funcName];
856
856
  }
857
+ /**
858
+ * Removes the specified indexes from the array.
859
+ * Sparse (empty) elements are transformed to undefined (unless their index is explicitly removed).
860
+ */
857
861
  function removeIndexesFromArray(array, indexes) {
858
- return array.filter((_, index) => !indexes.includes(index));
862
+ const toRemove = new Set(indexes);
863
+ const newArray = [];
864
+ for (let i = 0; i < array.length; i++) {
865
+ if (!toRemove.has(i)) {
866
+ newArray.push(array[i]);
867
+ }
868
+ }
869
+ return newArray;
859
870
  }
860
871
  function insertItemsAtIndex(array, items, index) {
861
872
  const newArray = [...array];
@@ -6739,7 +6750,7 @@ class ClipboardHandler {
6739
6750
  this.getters = getters;
6740
6751
  this.dispatch = dispatch;
6741
6752
  }
6742
- copy(data) {
6753
+ copy(data, mode = "copyPaste") {
6743
6754
  return;
6744
6755
  }
6745
6756
  paste(target, clippedContent, options) { }
@@ -6758,7 +6769,7 @@ class ClipboardHandler {
6758
6769
  }
6759
6770
 
6760
6771
  class AbstractCellClipboardHandler extends ClipboardHandler {
6761
- copy(data) {
6772
+ copy(data, mode = "copyPaste") {
6762
6773
  return;
6763
6774
  }
6764
6775
  pasteFromCopy(sheetId, target, content, options) {
@@ -8427,7 +8438,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8427
8438
  }
8428
8439
  return "Success" /* CommandResult.Success */;
8429
8440
  }
8430
- copy(data) {
8441
+ copy(data, mode = "copyPaste") {
8431
8442
  const sheetId = data.sheetId;
8432
8443
  const { clippedZones, rowsIndexes, columnsIndexes } = data;
8433
8444
  const clippedCells = [];
@@ -8440,7 +8451,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8440
8451
  const evaluatedCell = this.getters.getEvaluatedCell(position);
8441
8452
  const pivotId = this.getters.getPivotIdFromPosition(position);
8442
8453
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
8443
- if (pivotId && spreader) {
8454
+ if (mode !== "shiftCells" && pivotId && spreader) {
8444
8455
  const pivotZone = this.getters.getSpreadZone(spreader);
8445
8456
  if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
8446
8457
  pivotZone &&
@@ -8458,7 +8469,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8458
8469
  };
8459
8470
  }
8460
8471
  }
8461
- else {
8472
+ else if (mode !== "shiftCells") {
8462
8473
  if (spreader && !deepEquals(spreader, position)) {
8463
8474
  const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
8464
8475
  const content = isSpreaderCopied
@@ -9151,7 +9162,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
9151
9162
  }
9152
9163
 
9153
9164
  class TableClipboardHandler extends AbstractCellClipboardHandler {
9154
- copy(data) {
9165
+ copy(data, mode = "copyPaste") {
9155
9166
  const sheetId = data.sheetId;
9156
9167
  const { rowsIndexes, columnsIndexes, zones } = data;
9157
9168
  const copiedTablesIds = new Set();
@@ -9185,11 +9196,13 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
9185
9196
  type: coreTable.type,
9186
9197
  };
9187
9198
  }
9188
- tableCellsInRow.push({
9189
- table: copiedTable,
9190
- style: this.getTableStyleToCopy(position),
9191
- isWholeTableCopied: copiedTablesIds.has(table.id),
9192
- });
9199
+ if (mode !== "shiftCells") {
9200
+ tableCellsInRow.push({
9201
+ table: copiedTable,
9202
+ style: this.getTableStyleToCopy(position),
9203
+ isWholeTableCopied: copiedTablesIds.has(table.id),
9204
+ });
9205
+ }
9193
9206
  }
9194
9207
  }
9195
9208
  return {
@@ -15095,8 +15108,9 @@ function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
15095
15108
  }
15096
15109
 
15097
15110
  function sortMatrix(matrix, locale, ...criteria) {
15098
- for (const [i, value] of criteria.entries()) {
15099
- assert(() => value !== undefined, _t("Value for parameter %d is missing, while the function [[FUNCTION_NAME]] expect a number or a range.", i + 1));
15111
+ for (let i = 0; i < criteria.length; i++) {
15112
+ const param = i % 2 === 0 ? "sort_column" : "is_ascending";
15113
+ assert(() => criteria[i] !== undefined, _t("Value for parameter %s is missing in [[FUNCTION_NAME]].", param));
15100
15114
  }
15101
15115
  const sortingOrders = [];
15102
15116
  const sortColumns = [];
@@ -20787,7 +20801,7 @@ const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
20787
20801
  ];
20788
20802
  const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
20789
20803
  const SUPPORTED_FONTS = ["Arial"];
20790
- const SUPPORTED_FILL_PATTERNS = ["solid"];
20804
+ const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
20791
20805
  const SUPPORTED_CF_TYPES = [
20792
20806
  "expression",
20793
20807
  "cellIs",
@@ -20972,7 +20986,7 @@ const SUBTOTAL_FUNCTION_CONVERSION_MAP = {
20972
20986
  };
20973
20987
  /** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
20974
20988
  const XLSX_FORMATS_CONVERSION_MAP = {
20975
- 0: "",
20989
+ 0: "General",
20976
20990
  1: "0",
20977
20991
  2: "0.00",
20978
20992
  3: "#,#00",
@@ -21298,11 +21312,11 @@ const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/
21298
21312
  * Excel format are defined in openXML §18.8.31
21299
21313
  */
21300
21314
  function convertXlsxFormat(numFmtId, formats, warningManager) {
21301
- if (numFmtId === 0) {
21302
- return undefined;
21303
- }
21304
21315
  // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
21305
21316
  let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
21317
+ if (format === "General") {
21318
+ return undefined;
21319
+ }
21306
21320
  if (format) {
21307
21321
  try {
21308
21322
  let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
@@ -24260,10 +24274,11 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
24260
24274
  });
24261
24275
  }
24262
24276
  extractRows(worksheet) {
24277
+ const spilledCells = new Set();
24263
24278
  return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
24264
24279
  return {
24265
24280
  index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
24266
- cells: this.extractCells(rowElement),
24281
+ cells: this.extractCells(rowElement, spilledCells),
24267
24282
  height: this.extractAttr(rowElement, "ht")?.asNum(),
24268
24283
  customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
24269
24284
  hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
@@ -24273,14 +24288,26 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
24273
24288
  };
24274
24289
  });
24275
24290
  }
24276
- extractCells(row) {
24291
+ extractCells(row, spilledCells) {
24277
24292
  return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
24293
+ const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
24294
+ const formula = this.extractCellFormula(cellElement);
24295
+ if (formula?.ref && formula.sharedIndex === undefined) {
24296
+ const zone = toZone(formula.ref);
24297
+ for (const { col, row } of positions(zone)) {
24298
+ const followerXc = toXC(col, row);
24299
+ if (followerXc !== xc) {
24300
+ spilledCells.add(followerXc);
24301
+ }
24302
+ }
24303
+ }
24304
+ const isSpilled = spilledCells.has(xc);
24278
24305
  return {
24279
- xc: this.extractAttr(cellElement, "r", { required: true })?.asString(),
24306
+ xc,
24280
24307
  styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
24281
24308
  type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
24282
- value: this.extractChildTextContent(cellElement, "v"),
24283
- formula: this.extractCellFormula(cellElement),
24309
+ value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
24310
+ formula: isSpilled ? undefined : formula,
24284
24311
  };
24285
24312
  });
24286
24313
  }
@@ -24288,11 +24315,14 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
24288
24315
  const formulaElement = this.querySelector(cellElement, "f");
24289
24316
  if (!formulaElement)
24290
24317
  return undefined;
24291
- return {
24292
- content: this.extractTextContent(formulaElement),
24293
- sharedIndex: this.extractAttr(formulaElement, "si")?.asNum(),
24294
- ref: this.extractAttr(formulaElement, "ref")?.asString(),
24295
- };
24318
+ const content = this.extractTextContent(formulaElement);
24319
+ const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
24320
+ const ref = this.extractAttr(formulaElement, "ref")?.asString();
24321
+ // This is the case of spilled cells of array formulas where <f> is empty
24322
+ if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
24323
+ return undefined;
24324
+ }
24325
+ return { content, sharedIndex, ref };
24296
24326
  }
24297
24327
  extractHyperLinks(worksheet) {
24298
24328
  return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
@@ -43445,7 +43475,7 @@ class PivotMeasureEditor extends Component {
43445
43475
  });
43446
43476
  }
43447
43477
  get isCalculatedMeasureInvalid() {
43448
- return this.env.model.getters.getMeasureCompiledFormula(this.props.measure).isBadExpression;
43478
+ return compile(this.props.measure.computedBy?.formula ?? "").isBadExpression;
43449
43479
  }
43450
43480
  }
43451
43481
 
@@ -43640,12 +43670,13 @@ class PivotLayoutConfigurator extends Component {
43640
43670
  addCalculatedMeasure() {
43641
43671
  const { measures } = this.props.definition;
43642
43672
  const measureName = this.env.model.getters.generateNewCalculatedMeasureName(measures);
43673
+ const aggregator = "sum";
43643
43674
  this.props.onDimensionsUpdated({
43644
43675
  measures: measures.concat([
43645
43676
  {
43646
- id: this.getMeasureId(measureName),
43677
+ id: this.getMeasureId(measureName, aggregator),
43647
43678
  fieldName: measureName,
43648
- aggregator: "sum",
43679
+ aggregator,
43649
43680
  computedBy: {
43650
43681
  sheetId: this.env.model.getters.getActiveSheetId(),
43651
43682
  formula: "=0",
@@ -60708,7 +60739,7 @@ function withPivotPresentationLayer (PivotClass) {
60708
60739
  return { value: 0 };
60709
60740
  }
60710
60741
  const { columns, rows } = super.definition;
60711
- if (columns.length + rows.length !== domain.length) {
60742
+ if (measure.aggregator && columns.length + rows.length !== domain.length) {
60712
60743
  const values = this.getValuesToAggregate(measure, domain);
60713
60744
  const aggregator = AGGREGATORS_FN[measure.aggregator];
60714
60745
  if (!aggregator) {
@@ -60727,11 +60758,17 @@ function withPivotPresentationLayer (PivotClass) {
60727
60758
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
60728
60759
  const { colDomain } = domainToColRowDomain(this, domain);
60729
60760
  const symbolIndex = colDomain.findIndex((node) => node.field === symbolName);
60761
+ if (symbolIndex === -1) {
60762
+ return new NotAvailableError();
60763
+ }
60730
60764
  return this.getPivotHeaderValueAndFormat(colDomain.slice(0, symbolIndex + 1));
60731
60765
  }
60732
60766
  if (rows.find((row) => row.nameWithGranularity === symbolName)) {
60733
60767
  const { rowDomain } = domainToColRowDomain(this, domain);
60734
60768
  const symbolIndex = rowDomain.findIndex((row) => row.field === symbolName);
60769
+ if (symbolIndex === -1) {
60770
+ return new NotAvailableError();
60771
+ }
60735
60772
  return this.getPivotHeaderValueAndFormat(rowDomain.slice(0, symbolIndex + 1));
60736
60773
  }
60737
60774
  return this.getPivotCellValueAndFormat(symbolName, domain);
@@ -65166,12 +65203,12 @@ class ClipboardPlugin extends UIPlugin {
65166
65203
  }
65167
65204
  case "INSERT_CELL": {
65168
65205
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
65169
- const copiedData = this.copy(cut);
65206
+ const copiedData = this.copy(cut, "shiftCells");
65170
65207
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
65171
65208
  }
65172
65209
  case "DELETE_CELL": {
65173
65210
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
65174
- const copiedData = this.copy(cut);
65211
+ const copiedData = this.copy(cut, "shiftCells");
65175
65212
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
65176
65213
  }
65177
65214
  }
@@ -65261,13 +65298,13 @@ class ClipboardPlugin extends UIPlugin {
65261
65298
  });
65262
65299
  break;
65263
65300
  }
65264
- const copiedData = this.copy(cut);
65301
+ const copiedData = this.copy(cut, "shiftCells");
65265
65302
  this.paste(paste, copiedData, { isCutOperation: true });
65266
65303
  break;
65267
65304
  }
65268
65305
  case "INSERT_CELL": {
65269
65306
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
65270
- const copiedData = this.copy(cut);
65307
+ const copiedData = this.copy(cut, "shiftCells");
65271
65308
  this.paste(paste, copiedData, { isCutOperation: true });
65272
65309
  break;
65273
65310
  }
@@ -65382,11 +65419,11 @@ class ClipboardPlugin extends UIPlugin {
65382
65419
  }
65383
65420
  return false;
65384
65421
  }
65385
- copy(zones) {
65422
+ copy(zones, mode = "copyPaste") {
65386
65423
  let copiedData = {};
65387
65424
  const clipboardData = this.getClipboardData(zones);
65388
65425
  for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
65389
- const data = handler.copy(clipboardData);
65426
+ const data = handler.copy(clipboardData, mode);
65390
65427
  copiedData[handlerName] = data;
65391
65428
  const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
65392
65429
  for (const key of minimalKeys) {
@@ -66257,7 +66294,7 @@ class GridSelectionPlugin extends UIPlugin {
66257
66294
  ];
66258
66295
  for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
66259
66296
  const handler = new Handler(this.getters, this.dispatch);
66260
- const data = handler.copy(getClipboardDataPositions(sheetId, target));
66297
+ const data = handler.copy(getClipboardDataPositions(sheetId, target), "shiftCells");
66261
66298
  if (!data) {
66262
66299
  continue;
66263
66300
  }
@@ -73996,7 +74033,7 @@ class Model extends EventBus {
73996
74033
  handlers = [];
73997
74034
  uiHandlers = [];
73998
74035
  coreHandlers = [];
73999
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
74036
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
74000
74037
  const start = performance.now();
74001
74038
  console.debug("##### Model creation #####");
74002
74039
  super();
@@ -74666,6 +74703,6 @@ const constants = {
74666
74703
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
74667
74704
 
74668
74705
 
74669
- __info__.version = "18.0.43";
74670
- __info__.date = "2025-09-05T07:38:36.406Z";
74671
- __info__.hash = "0f02dde";
74706
+ __info__.version = "18.0.45";
74707
+ __info__.date = "2025-09-19T07:24:19.143Z";
74708
+ __info__.hash = "54e799a";