@odoo/o-spreadsheet 18.4.9 → 18.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 18.4.9
6
- * @date 2025-09-05T07:38:32.126Z
7
- * @hash a261873
5
+ * @version 18.4.11
6
+ * @date 2025-09-19T07:25:39.033Z
7
+ * @hash c7e71ac
8
8
  */
9
9
 
10
10
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -889,8 +889,19 @@ function memoize(func) {
889
889
  },
890
890
  }[funcName];
891
891
  }
892
+ /**
893
+ * Removes the specified indexes from the array.
894
+ * Sparse (empty) elements are transformed to undefined (unless their index is explicitly removed).
895
+ */
892
896
  function removeIndexesFromArray(array, indexes) {
893
- return array.filter((_, index) => !indexes.includes(index));
897
+ const toRemove = new Set(indexes);
898
+ const newArray = [];
899
+ for (let i = 0; i < array.length; i++) {
900
+ if (!toRemove.has(i)) {
901
+ newArray.push(array[i]);
902
+ }
903
+ }
904
+ return newArray;
894
905
  }
895
906
  function insertItemsAtIndex(array, items, index) {
896
907
  const newArray = [...array];
@@ -7354,7 +7365,7 @@ class ClipboardHandler {
7354
7365
  this.getters = getters;
7355
7366
  this.dispatch = dispatch;
7356
7367
  }
7357
- copy(data, isCutOperation) {
7368
+ copy(data, isCutOperation, mode = "copyPaste") {
7358
7369
  return;
7359
7370
  }
7360
7371
  paste(target, clippedContent, options) { }
@@ -7373,7 +7384,7 @@ class ClipboardHandler {
7373
7384
  }
7374
7385
 
7375
7386
  class AbstractCellClipboardHandler extends ClipboardHandler {
7376
- copy(data) {
7387
+ copy(data, isCutOperation, mode = "copyPaste") {
7377
7388
  return;
7378
7389
  }
7379
7390
  pasteFromCopy(sheetId, target, content, options) {
@@ -8903,7 +8914,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8903
8914
  }
8904
8915
  return "Success" /* CommandResult.Success */;
8905
8916
  }
8906
- copy(data) {
8917
+ copy(data, isCutOperation, mode = "copyPaste") {
8907
8918
  const sheetId = data.sheetId;
8908
8919
  const { clippedZones, rowsIndexes, columnsIndexes } = data;
8909
8920
  const clippedCells = [];
@@ -8916,7 +8927,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8916
8927
  const evaluatedCell = this.getters.getEvaluatedCell(position);
8917
8928
  const pivotId = this.getters.getPivotIdFromPosition(position);
8918
8929
  const spreader = this.getters.getArrayFormulaSpreadingOn(position);
8919
- if (pivotId && spreader) {
8930
+ if (mode !== "shiftCells" && pivotId && spreader) {
8920
8931
  const pivotZone = this.getters.getSpreadZone(spreader);
8921
8932
  if ((!deepEquals(spreader, position) || !isCopyingOneCell) &&
8922
8933
  pivotZone &&
@@ -8934,7 +8945,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
8934
8945
  };
8935
8946
  }
8936
8947
  }
8937
- else {
8948
+ else if (mode !== "shiftCells") {
8938
8949
  if (spreader && !deepEquals(spreader, position)) {
8939
8950
  const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
8940
8951
  const content = isSpreaderCopied
@@ -9632,7 +9643,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
9632
9643
  }
9633
9644
 
9634
9645
  class TableClipboardHandler extends AbstractCellClipboardHandler {
9635
- copy(data, isCutOperation) {
9646
+ copy(data, isCutOperation, mode = "copyPaste") {
9636
9647
  const sheetId = data.sheetId;
9637
9648
  const { rowsIndexes, columnsIndexes, zones } = data;
9638
9649
  const copiedTablesIds = new Set();
@@ -9670,11 +9681,13 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
9670
9681
  type: coreTable.type,
9671
9682
  };
9672
9683
  }
9673
- tableCellsInRow.push({
9674
- table: copiedTable,
9675
- style: this.getTableStyleToCopy(position),
9676
- isWholeTableCopied: copiedTablesIds.has(table.id),
9677
- });
9684
+ if (mode !== "shiftCells") {
9685
+ tableCellsInRow.push({
9686
+ table: copiedTable,
9687
+ style: this.getTableStyleToCopy(position),
9688
+ isWholeTableCopied: copiedTablesIds.has(table.id),
9689
+ });
9690
+ }
9678
9691
  }
9679
9692
  }
9680
9693
  return {
@@ -15201,8 +15214,9 @@ function interactiveSort(env, sheetId, anchor, zone, sortDirection, sortOptions)
15201
15214
  }
15202
15215
 
15203
15216
  function sortMatrix(matrix, locale, ...criteria) {
15204
- for (const [i, value] of criteria.entries()) {
15205
- assert(value !== undefined, _t("Value for parameter %d is missing, while the function [[FUNCTION_NAME]] expect a number or a range.", i + 1));
15217
+ for (let i = 0; i < criteria.length; i++) {
15218
+ const param = i % 2 === 0 ? "sort_column" : "is_ascending";
15219
+ assert(criteria[i] !== undefined, _t("Value for parameter %s is missing in [[FUNCTION_NAME]].", param));
15206
15220
  }
15207
15221
  const sortingOrders = [];
15208
15222
  const sortColumns = [];
@@ -37512,7 +37526,7 @@ const SUPPORTED_HORIZONTAL_ALIGNMENTS = [
37512
37526
  ];
37513
37527
  const SUPPORTED_VERTICAL_ALIGNMENTS = ["top", "center", "bottom"];
37514
37528
  const SUPPORTED_FONTS = ["Arial"];
37515
- const SUPPORTED_FILL_PATTERNS = ["solid"];
37529
+ const SUPPORTED_FILL_PATTERNS = ["solid", "none"];
37516
37530
  const SUPPORTED_CF_TYPES = [
37517
37531
  "expression",
37518
37532
  "cellIs",
@@ -37712,7 +37726,7 @@ const SUBTOTAL_FUNCTION_CONVERSION_MAP = {
37712
37726
  };
37713
37727
  /** Mapping between Excel format indexes (see XLSX_FORMAT_MAP) and some supported formats */
37714
37728
  const XLSX_FORMATS_CONVERSION_MAP = {
37715
- 0: "",
37729
+ 0: "General",
37716
37730
  1: "0",
37717
37731
  2: "0.00",
37718
37732
  3: "#,#00",
@@ -38038,11 +38052,11 @@ const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/
38038
38052
  * Excel format are defined in openXML §18.8.31
38039
38053
  */
38040
38054
  function convertXlsxFormat(numFmtId, formats, warningManager) {
38041
- if (numFmtId === 0) {
38042
- return undefined;
38043
- }
38044
38055
  // Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
38045
38056
  const format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || formats.find((f) => f.id === numFmtId)?.format;
38057
+ if (format === "General") {
38058
+ return undefined;
38059
+ }
38046
38060
  if (format) {
38047
38061
  try {
38048
38062
  let convertedFormat = format.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
@@ -40620,10 +40634,11 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
40620
40634
  });
40621
40635
  }
40622
40636
  extractRows(worksheet) {
40637
+ const spilledCells = new Set();
40623
40638
  return this.mapOnElements({ parent: worksheet, query: "sheetData row" }, (rowElement) => {
40624
40639
  return {
40625
40640
  index: this.extractAttr(rowElement, "r", { required: true })?.asNum(),
40626
- cells: this.extractCells(rowElement),
40641
+ cells: this.extractCells(rowElement, spilledCells),
40627
40642
  height: this.extractAttr(rowElement, "ht")?.asNum(),
40628
40643
  customHeight: this.extractAttr(rowElement, "customHeight")?.asBool(),
40629
40644
  hidden: this.extractAttr(rowElement, "hidden")?.asBool(),
@@ -40633,14 +40648,26 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
40633
40648
  };
40634
40649
  });
40635
40650
  }
40636
- extractCells(row) {
40651
+ extractCells(row, spilledCells) {
40637
40652
  return this.mapOnElements({ parent: row, query: "c" }, (cellElement) => {
40653
+ const xc = this.extractAttr(cellElement, "r", { required: true })?.asString();
40654
+ const formula = this.extractCellFormula(cellElement);
40655
+ if (formula?.ref && formula.sharedIndex === undefined) {
40656
+ const zone = toZone(formula.ref);
40657
+ for (const { col, row } of positions(zone)) {
40658
+ const followerXc = toXC(col, row);
40659
+ if (followerXc !== xc) {
40660
+ spilledCells.add(followerXc);
40661
+ }
40662
+ }
40663
+ }
40664
+ const isSpilled = spilledCells.has(xc);
40638
40665
  return {
40639
- xc: this.extractAttr(cellElement, "r", { required: true })?.asString(),
40666
+ xc,
40640
40667
  styleIndex: this.extractAttr(cellElement, "s")?.asNum(),
40641
40668
  type: CELL_TYPE_CONVERSION_MAP[this.extractAttr(cellElement, "t", { default: "n" })?.asString()],
40642
- value: this.extractChildTextContent(cellElement, "v"),
40643
- formula: this.extractCellFormula(cellElement),
40669
+ value: isSpilled ? undefined : this.extractChildTextContent(cellElement, "v") ?? undefined,
40670
+ formula: isSpilled ? undefined : formula,
40644
40671
  };
40645
40672
  });
40646
40673
  }
@@ -40648,11 +40675,14 @@ class XlsxSheetExtractor extends XlsxBaseExtractor {
40648
40675
  const formulaElement = this.querySelector(cellElement, "f");
40649
40676
  if (!formulaElement)
40650
40677
  return undefined;
40651
- return {
40652
- content: this.extractTextContent(formulaElement),
40653
- sharedIndex: this.extractAttr(formulaElement, "si")?.asNum(),
40654
- ref: this.extractAttr(formulaElement, "ref")?.asString(),
40655
- };
40678
+ const content = this.extractTextContent(formulaElement);
40679
+ const sharedIndex = this.extractAttr(formulaElement, "si")?.asNum();
40680
+ const ref = this.extractAttr(formulaElement, "ref")?.asString();
40681
+ // This is the case of spilled cells of array formulas where <f> is empty
40682
+ if ((content === undefined || content.trim() === "") && sharedIndex === undefined) {
40683
+ return undefined;
40684
+ }
40685
+ return { content, sharedIndex, ref };
40656
40686
  }
40657
40687
  extractHyperLinks(worksheet) {
40658
40688
  return this.mapOnElements({ parent: worksheet, query: "hyperlink" }, (linkElement) => {
@@ -54472,12 +54502,13 @@ class PivotLayoutConfigurator extends Component {
54472
54502
  addCalculatedMeasure() {
54473
54503
  const { measures } = this.props.definition;
54474
54504
  const measureName = this.env.model.getters.generateNewCalculatedMeasureName(measures);
54505
+ const aggregator = "sum";
54475
54506
  this.props.onDimensionsUpdated({
54476
54507
  measures: measures.concat([
54477
54508
  {
54478
- id: this.getMeasureId(measureName),
54509
+ id: this.getMeasureId(measureName, aggregator),
54479
54510
  fieldName: measureName,
54480
- aggregator: "sum",
54511
+ aggregator,
54481
54512
  computedBy: {
54482
54513
  sheetId: this.env.model.getters.getActiveSheetId(),
54483
54514
  formula: "=0",
@@ -67943,7 +67974,7 @@ function withPivotPresentationLayer (PivotClass) {
67943
67974
  return { value: 0 };
67944
67975
  }
67945
67976
  const { columns, rows } = super.definition;
67946
- if (columns.length + rows.length !== domain.length) {
67977
+ if (measure.aggregator && columns.length + rows.length !== domain.length) {
67947
67978
  const values = this.getValuesToAggregate(measure, domain);
67948
67979
  const aggregator = AGGREGATORS_FN[measure.aggregator];
67949
67980
  if (!aggregator) {
@@ -67962,11 +67993,17 @@ function withPivotPresentationLayer (PivotClass) {
67962
67993
  if (columns.find((col) => col.nameWithGranularity === symbolName)) {
67963
67994
  const { colDomain } = domainToColRowDomain(this, domain);
67964
67995
  const symbolIndex = colDomain.findIndex((node) => node.field === symbolName);
67996
+ if (symbolIndex === -1) {
67997
+ return new NotAvailableError();
67998
+ }
67965
67999
  return this.getPivotHeaderValueAndFormat(colDomain.slice(0, symbolIndex + 1));
67966
68000
  }
67967
68001
  if (rows.find((row) => row.nameWithGranularity === symbolName)) {
67968
68002
  const { rowDomain } = domainToColRowDomain(this, domain);
67969
68003
  const symbolIndex = rowDomain.findIndex((row) => row.field === symbolName);
68004
+ if (symbolIndex === -1) {
68005
+ return new NotAvailableError();
68006
+ }
67970
68007
  return this.getPivotHeaderValueAndFormat(rowDomain.slice(0, symbolIndex + 1));
67971
68008
  }
67972
68009
  return this.getPivotCellValueAndFormat(symbolName, domain);
@@ -70990,7 +71027,7 @@ class DataCleanupPlugin extends UIPlugin {
70990
71027
  bottom: rowIndex,
70991
71028
  }));
70992
71029
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
70993
- const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep));
71030
+ const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep), false);
70994
71031
  if (!data) {
70995
71032
  return;
70996
71033
  }
@@ -73075,12 +73112,12 @@ class ClipboardPlugin extends UIPlugin {
73075
73112
  }
73076
73113
  case "INSERT_CELL": {
73077
73114
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
73078
- const copiedData = this.copy(cut);
73115
+ const copiedData = this.copy(cut, "shiftCells");
73079
73116
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
73080
73117
  }
73081
73118
  case "DELETE_CELL": {
73082
73119
  const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
73083
- const copiedData = this.copy(cut);
73120
+ const copiedData = this.copy(cut, "shiftCells");
73084
73121
  return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
73085
73122
  }
73086
73123
  }
@@ -73191,13 +73228,13 @@ class ClipboardPlugin extends UIPlugin {
73191
73228
  });
73192
73229
  break;
73193
73230
  }
73194
- const copiedData = this.copy(cut);
73231
+ const copiedData = this.copy(cut, "shiftCells");
73195
73232
  this.paste(paste, copiedData, { isCutOperation: true });
73196
73233
  break;
73197
73234
  }
73198
73235
  case "INSERT_CELL": {
73199
73236
  const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
73200
- const copiedData = this.copy(cut);
73237
+ const copiedData = this.copy(cut, "shiftCells");
73201
73238
  this.paste(paste, copiedData, { isCutOperation: true });
73202
73239
  break;
73203
73240
  }
@@ -73312,11 +73349,11 @@ class ClipboardPlugin extends UIPlugin {
73312
73349
  }
73313
73350
  return false;
73314
73351
  }
73315
- copy(zones) {
73352
+ copy(zones, mode = "copyPaste") {
73316
73353
  const copiedData = {};
73317
73354
  const clipboardData = this.getClipboardData(zones);
73318
73355
  for (const { handlerName, handler } of this.selectClipboardHandlers(clipboardData)) {
73319
- const data = handler.copy(clipboardData, this._isCutOperation);
73356
+ const data = handler.copy(clipboardData, this._isCutOperation, mode);
73320
73357
  copiedData[handlerName] = data;
73321
73358
  const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
73322
73359
  for (const key of minimalKeys) {
@@ -74303,13 +74340,10 @@ class GridSelectionPlugin extends UIPlugin {
74303
74340
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
74304
74341
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
74305
74342
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
74306
- const originalSize = Object.fromEntries(toRemove.map((element) => {
74307
- const size = isCol
74308
- ? this.getters.getColSize(cmd.sheetId, element)
74309
- : this.getters.getUserRowSize(cmd.sheetId, element);
74310
- const isDefaultCol = isCol && size === DEFAULT_CELL_WIDTH;
74311
- return [element, isDefaultCol ? undefined : size];
74312
- }));
74343
+ const originalSize = {};
74344
+ for (const element of toRemove) {
74345
+ originalSize[element] = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
74346
+ }
74313
74347
  const target = [
74314
74348
  {
74315
74349
  left: isCol ? start + deltaCol : 0,
@@ -74330,7 +74364,7 @@ class GridSelectionPlugin extends UIPlugin {
74330
74364
  ];
74331
74365
  for (const Handler of clipboardHandlersRegistries.cellHandlers.getAll()) {
74332
74366
  const handler = new Handler(this.getters, this.dispatch);
74333
- const data = handler.copy(getClipboardDataPositions(sheetId, target));
74367
+ const data = handler.copy(getClipboardDataPositions(sheetId, target), false, "shiftCells");
74334
74368
  if (!data) {
74335
74369
  continue;
74336
74370
  }
@@ -74345,11 +74379,11 @@ class GridSelectionPlugin extends UIPlugin {
74345
74379
  for (const element of toRemove) {
74346
74380
  const size = originalSize[element];
74347
74381
  const currentSize = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, currentIndex);
74348
- if (size && size !== currentSize) {
74382
+ if (size !== currentSize) {
74349
74383
  resizingGroups[size] ??= [];
74350
74384
  resizingGroups[size].push(currentIndex);
74351
- currentIndex += 1;
74352
74385
  }
74386
+ currentIndex += 1;
74353
74387
  }
74354
74388
  for (const size in resizingGroups) {
74355
74389
  this.dispatch("RESIZE_COLUMNS_ROWS", {
@@ -84070,7 +84104,7 @@ class Model extends EventBus {
84070
84104
  handlers = [];
84071
84105
  uiHandlers = [];
84072
84106
  coreHandlers = [];
84073
- constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = true) {
84107
+ constructor(data = {}, config = {}, stateUpdateMessages = [], uuidGenerator = new UuidGenerator(), verboseImport = false) {
84074
84108
  const start = performance.now();
84075
84109
  console.debug("##### Model creation #####");
84076
84110
  super();
@@ -84772,6 +84806,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
84772
84806
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DispatchResult, EvaluationError, LocalTransportService, 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, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
84773
84807
 
84774
84808
 
84775
- __info__.version = "18.4.9";
84776
- __info__.date = "2025-09-05T07:38:32.126Z";
84777
- __info__.hash = "a261873";
84809
+ __info__.version = "18.4.11";
84810
+ __info__.date = "2025-09-19T07:25:39.033Z";
84811
+ __info__.hash = "c7e71ac";