@odoo/o-spreadsheet 18.2.28 → 18.2.30

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.2.28
6
- * @date 2025-09-05T07:38:26.582Z
7
- * @hash 84335fb
5
+ * @version 18.2.30
6
+ * @date 2025-09-19T07:24:27.894Z
7
+ * @hash 16428fd
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -858,8 +858,19 @@ function memoize(func) {
858
858
  },
859
859
  }[funcName];
860
860
  }
861
+ /**
862
+ * Removes the specified indexes from the array.
863
+ * Sparse (empty) elements are transformed to undefined (unless their index is explicitly removed).
864
+ */
861
865
  function removeIndexesFromArray(array, indexes) {
862
- return array.filter((_, index) => !indexes.includes(index));
866
+ const toRemove = new Set(indexes);
867
+ const newArray = [];
868
+ for (let i = 0; i < array.length; i++) {
869
+ if (!toRemove.has(i)) {
870
+ newArray.push(array[i]);
871
+ }
872
+ }
873
+ return newArray;
863
874
  }
864
875
  function insertItemsAtIndex(array, items, index) {
865
876
  const newArray = [...array];
@@ -6903,7 +6914,7 @@ class ClipboardHandler {
6903
6914
  this.getters = getters;
6904
6915
  this.dispatch = dispatch;
6905
6916
  }
6906
- copy(data) {
6917
+ copy(data, mode = "copyPaste") {
6907
6918
  return;
6908
6919
  }
6909
6920
  paste(target, clippedContent, options) { }
@@ -6922,7 +6933,7 @@ class ClipboardHandler {
6922
6933
  }
6923
6934
 
6924
6935
  class AbstractCellClipboardHandler extends ClipboardHandler {
6925
- copy(data) {
6936
+ copy(data, mode = "copyPaste") {
6926
6937
  return;
6927
6938
  }
6928
6939
  pasteFromCopy(sheetId, target, content, options) {
@@ -8639,7 +8650,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8639
8650
  }
8640
8651
  return "Success" /* CommandResult.Success */;
8641
8652
  }
8642
- copy(data) {
8653
+ copy(data, mode = "copyPaste") {
8643
8654
  const sheetId = data.sheetId;
8644
8655
  const { clippedZones, rowsIndexes, columnsIndexes } = data;
8645
8656
  const clippedCells = [];
@@ -8652,7 +8663,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8652
8663
  const evaluatedCell = this.getters.getEvaluatedCell(position);
8653
8664
  const pivotId = this.getters.getPivotIdFromPosition(position);
8654
8665
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
8655
- if (pivotId && spreader) {
8666
+ if (mode !== "shiftCells" && pivotId && spreader) {
8656
8667
  const pivotZone = this.getters.getSpreadZone(spreader);
8657
8668
  if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
8658
8669
  pivotZone &&
@@ -8670,7 +8681,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8670
8681
  };
8671
8682
  }
8672
8683
  }
8673
- else {
8684
+ else if (mode !== "shiftCells") {
8674
8685
  if (spreader && !deepEquals(spreader, position)) {
8675
8686
  const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
8676
8687
  const content = isSpreaderCopied
@@ -9363,7 +9374,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
9363
9374
  }
9364
9375
 
9365
9376
  class TableClipboardHandler extends AbstractCellClipboardHandler {
9366
- copy(data) {
9377
+ copy(data, mode = "copyPaste") {
9367
9378
  const sheetId = data.sheetId;
9368
9379
  const { rowsIndexes, columnsIndexes, zones } = data;
9369
9380
  const copiedTablesIds = new Set();
@@ -9393,11 +9404,13 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
9393
9404
  type: coreTable.type,
9394
9405
  };
9395
9406
  }
9396
- tableCellsInRow.push({
9397
- table: copiedTable,
9398
- style: this.getTableStyleToCopy(position),
9399
- isWholeTableCopied: copiedTablesIds.has(table.id),
9400
- });
9407
+ if (mode !== "shiftCells") {
9408
+ tableCellsInRow.push({
9409
+ table: copiedTable,
9410
+ style: this.getTableStyleToCopy(position),
9411
+ isWholeTableCopied: copiedTablesIds.has(table.id),
9412
+ });
9413
+ }
9401
9414
  }
9402
9415
  }
9403
9416
  return {
@@ -15616,8 +15629,9 @@ function interactiveSort(env, sheetId, anchor, zone, sortDirection, sortOptions)
15616
15629
  }
15617
15630
 
15618
15631
  function sortMatrix(matrix, locale, ...criteria) {
15619
- for (const [i, value] of criteria.entries()) {
15620
- assert(() => value !== undefined, _t("Value for parameter %d is missing, while the function [[FUNCTION_NAME]] expect a number or a range.", i + 1));
15632
+ for (let i = 0; i < criteria.length; i++) {
15633
+ const param = i % 2 === 0 ? "sort_column" : "is_ascending";
15634
+ assert(() => criteria[i] !== undefined, _t("Value for parameter %s is missing in [[FUNCTION_NAME]].", param));
15621
15635
  }
15622
15636
  const sortingOrders = [];
15623
15637
  const sortColumns = [];
@@ -23793,7 +23807,7 @@ const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
23793
23807
  ];
23794
23808
  const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
23795
23809
  const SUPPORTED_FONTS = ["Arial"];
23796
- const SUPPORTED_FILL_PATTERNS = ["solid"];
23810
+ const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
23797
23811
  const SUPPORTED_CF_TYPES = [
23798
23812
  "expression",
23799
23813
  "cellIs",
@@ -23978,7 +23992,7 @@ const SUBTOTAL_FUNCTION_CONVERSION_MAP = {
23978
23992
  };
23979
23993
  /** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
23980
23994
  const XLSX_FORMATS_CONVERSION_MAP = {
23981
- 0: "",
23995
+ 0: "General",
23982
23996
  1: "0",
23983
23997
  2: "0.00",
23984
23998
  3: "#,#00",
@@ -24304,11 +24318,11 @@ const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/
24304
24318
  * Excel format are defined in openXML §18.8.31
24305
24319
  */
24306
24320
  function convertXlsxFormat(numFmtId, formats, warningManager) {
24307
- if (numFmtId === 0) {
24308
- return undefined;
24309
- }
24310
24321
  // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
24311
24322
  let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
24323
+ if (format === "General") {
24324
+ return undefined;
24325
+ }
24312
24326
  if (format) {
24313
24327
  try {
24314
24328
  let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
@@ -27269,10 +27283,11 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
27269
27283
  });
27270
27284
  }
27271
27285
  extractRows(worksheet) {
27286
+ const spilledCells = new Set();
27272
27287
  return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
27273
27288
  return {
27274
27289
  index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
27275
- cells: this.extractCells(rowElement),
27290
+ cells: this.extractCells(rowElement, spilledCells),
27276
27291
  height: this.extractAttr(rowElement, "ht")?.asNum(),
27277
27292
  customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
27278
27293
  hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
@@ -27282,14 +27297,26 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
27282
27297
  };
27283
27298
  });
27284
27299
  }
27285
- extractCells(row) {
27300
+ extractCells(row, spilledCells) {
27286
27301
  return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
27302
+ const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
27303
+ const formula = this.extractCellFormula(cellElement);
27304
+ if (formula?.ref && formula.sharedIndex === undefined) {
27305
+ const zone = toZone(formula.ref);
27306
+ for (const { col, row } of positions(zone)) {
27307
+ const followerXc = toXC(col, row);
27308
+ if (followerXc !== xc) {
27309
+ spilledCells.add(followerXc);
27310
+ }
27311
+ }
27312
+ }
27313
+ const isSpilled = spilledCells.has(xc);
27287
27314
  return {
27288
- xc: this.extractAttr(cellElement, "r", { required: true })?.asString(),
27315
+ xc,
27289
27316
  styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
27290
27317
  type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
27291
- value: this.extractChildTextContent(cellElement, "v"),
27292
- formula: this.extractCellFormula(cellElement),
27318
+ value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
27319
+ formula: isSpilled ? undefined : formula,
27293
27320
  };
27294
27321
  });
27295
27322
  }
@@ -27297,11 +27324,14 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
27297
27324
  const formulaElement = this.querySelector(cellElement, "f");
27298
27325
  if (!formulaElement)
27299
27326
  return undefined;
27300
- return {
27301
- content: this.extractTextContent(formulaElement),
27302
- sharedIndex: this.extractAttr(formulaElement, "si")?.asNum(),
27303
- ref: this.extractAttr(formulaElement, "ref")?.asString(),
27304
- };
27327
+ const content = this.extractTextContent(formulaElement);
27328
+ const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
27329
+ const ref = this.extractAttr(formulaElement, "ref")?.asString();
27330
+ // This is the case of spilled cells of array formulas where <f> is empty
27331
+ if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
27332
+ return undefined;
27333
+ }
27334
+ return { content, sharedIndex, ref };
27305
27335
  }
27306
27336
  extractHyperLinks(worksheet) {
27307
27337
  return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
@@ -46112,12 +46142,13 @@ class PivotLayoutConfigurator extends Component {
46112
46142
  addCalculatedMeasure() {
46113
46143
  const { measures } = this.props.definition;
46114
46144
  const measureName = this.env.model.getters.generateNewCalculatedMeasureName(measures);
46145
+ const aggregator = "sum";
46115
46146
  this.props.onDimensionsUpdated({
46116
46147
  measures: measures.concat([
46117
46148
  {
46118
- id: this.getMeasureId(measureName),
46149
+ id: this.getMeasureId(measureName, aggregator),
46119
46150
  fieldName: measureName,
46120
- aggregator: "sum",
46151
+ aggregator,
46121
46152
  computedBy: {
46122
46153
  sheetId: this.env.model.getters.getActiveSheetId(),
46123
46154
  formula: "=0",
@@ -63277,7 +63308,7 @@ function withPivotPresentationLayer (PivotClass) {
63277
63308
  return { value: 0 };
63278
63309
  }
63279
63310
  const { columns, rows } = super.definition;
63280
- if (columns.length + rows.length !== domain.length) {
63311
+ if (measure.aggregator && columns.length + rows.length !== domain.length) {
63281
63312
  const values = this.getValuesToAggregate(measure, domain);
63282
63313
  const aggregator = AGGREGATORS_FN[measure.aggregator];
63283
63314
  if (!aggregator) {
@@ -63296,11 +63327,17 @@ function withPivotPresentationLayer (PivotClass) {
63296
63327
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
63297
63328
  const { colDomain } = domainToColRowDomain(this, domain);
63298
63329
  const symbolIndex = colDomain.findIndex((node) => node.field === symbolName);
63330
+ if (symbolIndex === -1) {
63331
+ return new NotAvailableError();
63332
+ }
63299
63333
  return this.getPivotHeaderValueAndFormat(colDomain.slice(0, symbolIndex + 1));
63300
63334
  }
63301
63335
  if (rows.find((row) => row.nameWithGranularity === symbolName)) {
63302
63336
  const { rowDomain } = domainToColRowDomain(this, domain);
63303
63337
  const symbolIndex = rowDomain.findIndex((row) => row.field === symbolName);
63338
+ if (symbolIndex === -1) {
63339
+ return new NotAvailableError();
63340
+ }
63304
63341
  return this.getPivotHeaderValueAndFormat(rowDomain.slice(0, symbolIndex + 1));
63305
63342
  }
63306
63343
  return this.getPivotCellValueAndFormat(symbolName, domain);
@@ -67806,12 +67843,12 @@ class ClipboardPlugin extends UIPlugin {
67806
67843
  }
67807
67844
  case "INSERT_CELL": {
67808
67845
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
67809
- const copiedData = this.copy(cut);
67846
+ const copiedData = this.copy(cut, "shiftCells");
67810
67847
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
67811
67848
  }
67812
67849
  case "DELETE_CELL": {
67813
67850
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
67814
- const copiedData = this.copy(cut);
67851
+ const copiedData = this.copy(cut, "shiftCells");
67815
67852
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
67816
67853
  }
67817
67854
  }
@@ -67901,13 +67938,13 @@ class ClipboardPlugin extends UIPlugin {
67901
67938
  });
67902
67939
  break;
67903
67940
  }
67904
- const copiedData = this.copy(cut);
67941
+ const copiedData = this.copy(cut, "shiftCells");
67905
67942
  this.paste(paste, copiedData, { isCutOperation: true });
67906
67943
  break;
67907
67944
  }
67908
67945
  case "INSERT_CELL": {
67909
67946
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
67910
- const copiedData = this.copy(cut);
67947
+ const copiedData = this.copy(cut, "shiftCells");
67911
67948
  this.paste(paste, copiedData, { isCutOperation: true });
67912
67949
  break;
67913
67950
  }
@@ -68022,11 +68059,11 @@ class ClipboardPlugin extends UIPlugin {
68022
68059
  }
68023
68060
  return false;
68024
68061
  }
68025
- copy(zones) {
68062
+ copy(zones, mode = "copyPaste") {
68026
68063
  let copiedData = {};
68027
68064
  const clipboardData = this.getClipboardData(zones);
68028
68065
  for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
68029
- const data = handler.copy(clipboardData);
68066
+ const data = handler.copy(clipboardData, mode);
68030
68067
  copiedData[handlerName] = data;
68031
68068
  const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
68032
68069
  for (const key of minimalKeys) {
@@ -68863,13 +68900,10 @@ class GridSelectionPlugin extends UIPlugin {
68863
68900
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
68864
68901
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
68865
68902
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
68866
- const originalSize = Object.fromEntries(toRemove.map((element) => {
68867
- const size = isCol
68868
- ? this.getters.getColSize(cmd.sheetId, element)
68869
- : this.getters.getUserRowSize(cmd.sheetId, element);
68870
- const isDefaultCol = isCol && size === DEFAULT_CELL_WIDTH;
68871
- return [element, isDefaultCol ? undefined : size];
68872
- }));
68903
+ const originalSize = {};
68904
+ for (const element of toRemove) {
68905
+ originalSize[element] = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
68906
+ }
68873
68907
  const target = [
68874
68908
  {
68875
68909
  left: isCol ? start + deltaCol : 0,
@@ -68890,7 +68924,7 @@ class GridSelectionPlugin extends UIPlugin {
68890
68924
  ];
68891
68925
  for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
68892
68926
  const handler = new Handler(this.getters, this.dispatch);
68893
- const data = handler.copy(getClipboardDataPositions(sheetId, target));
68927
+ const data = handler.copy(getClipboardDataPositions(sheetId, target), "shiftCells");
68894
68928
  if (!data) {
68895
68929
  continue;
68896
68930
  }
@@ -68905,11 +68939,11 @@ class GridSelectionPlugin extends UIPlugin {
68905
68939
  for (const element of toRemove) {
68906
68940
  const size = originalSize[element];
68907
68941
  const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
68908
- if (size && size != currentSize) {
68942
+ if (size != currentSize) {
68909
68943
  resizingGroups[size] ??= [];
68910
68944
  resizingGroups[size].push(currentIndex);
68911
- currentIndex += 1;
68912
68945
  }
68946
+ currentIndex += 1;
68913
68947
  }
68914
68948
  for (const size in resizingGroups) {
68915
68949
  this.dispatch("RESIZE_COLUMNS_ROWS", {
@@ -76578,7 +76612,7 @@ class Model extends EventBus {
76578
76612
  handlers = [];
76579
76613
  uiHandlers = [];
76580
76614
  coreHandlers = [];
76581
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
76615
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
76582
76616
  const start = performance.now();
76583
76617
  console.debug("##### Model creation #####");
76584
76618
  super();
@@ -77269,6 +77303,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
77269
77303
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, chartHelpers, 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 };
77270
77304
 
77271
77305
 
77272
- __info__.version = "18.2.28";
77273
- __info__.date = "2025-09-05T07:38:26.582Z";
77274
- __info__.hash = "84335fb";
77306
+ __info__.version = "18.2.30";
77307
+ __info__.date = "2025-09-19T07:24:27.894Z";
77308
+ __info__.hash = "16428fd";