@odoo/o-spreadsheet 17.4.5 → 17.4.7

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.5
6
- * @date 2024-08-19T08:12:00.492Z
7
- * @hash 28579ad
5
+ * @version 17.4.7
6
+ * @date 2024-09-05T09:32:00.461Z
7
+ * @hash c14a4c9
8
8
  */
9
9
 
10
10
  'use strict';
@@ -242,6 +242,7 @@ const PIVOT_TABLE_CONFIG = {
242
242
  bandedRows: true,
243
243
  bandedColumns: false,
244
244
  styleId: "TableStyleMedium5",
245
+ automaticAutofill: true,
245
246
  };
246
247
 
247
248
  //------------------------------------------------------------------------------
@@ -4560,6 +4561,17 @@ function reorderZone(zone) {
4560
4561
  }
4561
4562
  return zone;
4562
4563
  }
4564
+ function aggregatePositionsToZones(positions) {
4565
+ const result = {};
4566
+ for (const position of positions) {
4567
+ result[position.sheetId] ??= [];
4568
+ result[position.sheetId].push(positionToZone(position));
4569
+ }
4570
+ for (const sheetId in result) {
4571
+ result[sheetId] = recomputeZones(result[sheetId]);
4572
+ }
4573
+ return result;
4574
+ }
4563
4575
  /**
4564
4576
  * This function returns a zone with coordinates modified according to the change
4565
4577
  * applied to the zone. It may be possible to change the zone by resizing or moving
@@ -6775,9 +6787,11 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6775
6787
  const targetCell = this.getters.getEvaluatedCell(target);
6776
6788
  const originFormat = origin.cell?.format ?? origin.evaluatedCell.format;
6777
6789
  if (clipboardOption?.pasteOption === "asValue") {
6778
- const locale = this.getters.getLocale();
6779
- const content = formatValue(origin.evaluatedCell.value, { locale });
6780
- this.dispatch("UPDATE_CELL", { ...target, content, format: originFormat });
6790
+ this.dispatch("UPDATE_CELL", {
6791
+ ...target,
6792
+ content: origin.evaluatedCell.value?.toString() || "",
6793
+ format: originFormat,
6794
+ });
6781
6795
  return;
6782
6796
  }
6783
6797
  if (clipboardOption?.pasteOption === "onlyFormat") {
@@ -28379,8 +28393,26 @@ const CREATE_PIVOT = (env) => {
28379
28393
  env.openSidePanel("PivotSidePanel", { pivotId });
28380
28394
  }
28381
28395
  };
28382
- const REINSERT_PIVOT_CHILDREN = (env) => env.model.getters.getPivotIds().map((pivotId, index) => ({
28383
- id: `reinsert_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
28396
+ const REINSERT_DYNAMIC_PIVOT_CHILDREN = (env) => env.model.getters.getPivotIds().map((pivotId, index) => ({
28397
+ id: `reinsert_dynamic_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
28398
+ name: env.model.getters.getPivotDisplayName(pivotId),
28399
+ sequence: index,
28400
+ execute: (env) => {
28401
+ const zone = env.model.getters.getSelectedZone();
28402
+ const table = env.model.getters.getPivot(pivotId).getTableStructure().export();
28403
+ env.model.dispatch("INSERT_PIVOT_WITH_TABLE", {
28404
+ pivotId,
28405
+ table,
28406
+ col: zone.left,
28407
+ row: zone.top,
28408
+ sheetId: env.model.getters.getActiveSheetId(),
28409
+ pivotMode: "dynamic",
28410
+ });
28411
+ env.model.dispatch("REFRESH_PIVOT", { id: pivotId });
28412
+ },
28413
+ }));
28414
+ const REINSERT_STATIC_PIVOT_CHILDREN = (env) => env.model.getters.getPivotIds().map((pivotId, index) => ({
28415
+ id: `reinsert_static_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
28384
28416
  name: env.model.getters.getPivotDisplayName(pivotId),
28385
28417
  sequence: index,
28386
28418
  execute: (env) => {
@@ -28392,6 +28424,7 @@ const REINSERT_PIVOT_CHILDREN = (env) => env.model.getters.getPivotIds().map((pi
28392
28424
  col: zone.left,
28393
28425
  row: zone.top,
28394
28426
  sheetId: env.model.getters.getActiveSheetId(),
28427
+ pivotMode: "static",
28395
28428
  });
28396
28429
  env.model.dispatch("REFRESH_PIVOT", { id: pivotId });
28397
28430
  },
@@ -29260,12 +29293,20 @@ const splitToColumns = {
29260
29293
  isEnabled: (env) => env.model.getters.isSingleColSelected(),
29261
29294
  icon: "o-spreadsheet-Icon.SPLIT_TEXT",
29262
29295
  };
29263
- const reinsertPivotMenu = {
29264
- id: "reinsert_pivot",
29265
- name: _t("Re-insert pivot"),
29296
+ const reinsertDynamicPivotMenu = {
29297
+ id: "reinsert_dynamic_pivot",
29298
+ name: _t("Re-insert dynamic pivot"),
29299
+ sequence: 1020,
29300
+ icon: "o-spreadsheet-Icon.INSERT_PIVOT",
29301
+ children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
29302
+ isVisible: (env) => env.model.getters.getPivotIds().length > 0,
29303
+ };
29304
+ const reinsertStaticPivotMenu = {
29305
+ id: "reinsert_static_pivot",
29306
+ name: _t("Re-insert static pivot"),
29266
29307
  sequence: 1020,
29267
29308
  icon: "o-spreadsheet-Icon.INSERT_PIVOT",
29268
- children: [REINSERT_PIVOT_CHILDREN],
29309
+ children: [REINSERT_STATIC_PIVOT_CHILDREN],
29269
29310
  isVisible: (env) => env.model.getters.getPivotIds().length > 0,
29270
29311
  };
29271
29312
 
@@ -29274,7 +29315,8 @@ var ACTION_DATA = /*#__PURE__*/Object.freeze({
29274
29315
  createRemoveFilter: createRemoveFilter,
29275
29316
  createRemoveFilterTool: createRemoveFilterTool,
29276
29317
  dataCleanup: dataCleanup,
29277
- reinsertPivotMenu: reinsertPivotMenu,
29318
+ reinsertDynamicPivotMenu: reinsertDynamicPivotMenu,
29319
+ reinsertStaticPivotMenu: reinsertStaticPivotMenu,
29278
29320
  removeDuplicates: removeDuplicates,
29279
29321
  sortAscending: sortAscending,
29280
29322
  sortDescending: sortDescending,
@@ -30756,7 +30798,8 @@ topbarMenuRegistry
30756
30798
  };
30757
30799
  });
30758
30800
  })
30759
- .addChild("reinsert_pivot", ["data"], reinsertPivotMenu);
30801
+ .addChild("reinsert_dynamic_pivot", ["data"], reinsertDynamicPivotMenu)
30802
+ .addChild("reinsert_static_pivot", ["data"], reinsertStaticPivotMenu);
30760
30803
 
30761
30804
  class OTRegistry extends Registry {
30762
30805
  /**
@@ -35173,7 +35216,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
35173
35216
  searchScope: "activeSheet",
35174
35217
  specificRange: undefined,
35175
35218
  };
35176
- updateSearchContent = debounce(this._updateSearchContent.bind(this), 200);
35177
35219
  constructor(get) {
35178
35220
  super(get);
35179
35221
  this.initialShowFormulaState = this.model.getters.shouldShowFormulas();
@@ -35182,7 +35224,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
35182
35224
  highlightStore.register(this);
35183
35225
  this.onDispose(() => {
35184
35226
  this.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
35185
- this.updateSearchContent.stopDebounce();
35186
35227
  highlightStore.unRegister(this);
35187
35228
  });
35188
35229
  }
@@ -35196,7 +35237,7 @@ class FindAndReplaceStore extends SpreadsheetStore {
35196
35237
  return this.specificRangeMatches;
35197
35238
  }
35198
35239
  }
35199
- _updateSearchContent(toSearch) {
35240
+ updateSearchContent(toSearch) {
35200
35241
  this._updateSearch(toSearch, this.searchOptions);
35201
35242
  }
35202
35243
  updateSearchOptions(searchOptions) {
@@ -35212,9 +35253,6 @@ class FindAndReplaceStore extends SpreadsheetStore {
35212
35253
  selectNextMatch() {
35213
35254
  this.selectNextCell(Direction.next);
35214
35255
  }
35215
- get pendingSearch() {
35216
- return this.updateSearchContent.isDebouncePending();
35217
- }
35218
35256
  handle(cmd) {
35219
35257
  switch (cmd.type) {
35220
35258
  case "SET_FORMULA_VISIBILITY":
@@ -35540,6 +35578,7 @@ class FindAndReplacePanel extends owl.Component {
35540
35578
  searchInput = owl.useRef("searchInput");
35541
35579
  store;
35542
35580
  state;
35581
+ updateSearchContent;
35543
35582
  get hasSearchResult() {
35544
35583
  return this.store.selectedMatchIndex !== null;
35545
35584
  }
@@ -35571,12 +35610,14 @@ class FindAndReplacePanel extends owl.Component {
35571
35610
  this.store = useLocalStore(FindAndReplaceStore);
35572
35611
  this.state = owl.useState({ dataRange: "" });
35573
35612
  owl.onMounted(() => this.searchInput.el?.focus());
35613
+ owl.onWillUnmount(() => this.updateSearchContent.stopDebounce());
35614
+ this.updateSearchContent = debounce(this.store.updateSearchContent, 200);
35574
35615
  }
35575
35616
  onFocusSearch() {
35576
35617
  this.updateDataRange();
35577
35618
  }
35578
35619
  onSearchInput(ev) {
35579
- this.store.updateSearchContent(ev.target?.value || "");
35620
+ this.updateSearchContent(ev.target.value);
35580
35621
  }
35581
35622
  onKeydownSearch(ev) {
35582
35623
  if (ev.key === "Enter") {
@@ -35615,6 +35656,9 @@ class FindAndReplacePanel extends owl.Component {
35615
35656
  const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
35616
35657
  this.store.updateSearchOptions({ specificRange });
35617
35658
  }
35659
+ get pendingSearch() {
35660
+ return this.updateSearchContent.isDebouncePending();
35661
+ }
35618
35662
  }
35619
35663
 
35620
35664
  css /* scss */ `
@@ -36668,6 +36712,12 @@ function orderDataEntriesKeys(groups, dimension) {
36668
36712
  * Used to order two values
36669
36713
  */
36670
36714
  function compareDimensionValues(dimension, a, b) {
36715
+ if (a === "null") {
36716
+ return dimension.order === "asc" ? 1 : -1;
36717
+ }
36718
+ if (b === "null") {
36719
+ return dimension.order === "asc" ? -1 : 1;
36720
+ }
36671
36721
  if (dimension.type === "integer" || dimension.type === "date") {
36672
36722
  return dimension.order === "asc" ? Number(a) - Number(b) : Number(b) - Number(a);
36673
36723
  }
@@ -37030,7 +37080,7 @@ class SpreadsheetPivot {
37030
37080
  if (cell.type === CellValueType.error) {
37031
37081
  throw new EvaluationError(_t("The pivot cannot be created because cell %s contains an error", toXC(col, row)));
37032
37082
  }
37033
- if (cell.type === CellValueType.empty) {
37083
+ if (cell.type === CellValueType.empty || cell.value === "") {
37034
37084
  throw new EvaluationError(_t("The pivot cannot be created because cell %s is empty", toXC(col, row)));
37035
37085
  }
37036
37086
  if (cell.value === "__count") {
@@ -37376,15 +37426,11 @@ class PivotSpreadsheetSidePanel extends owl.Component {
37376
37426
  }
37377
37427
  onSelectionConfirmed() {
37378
37428
  if (this.state.range) {
37379
- const { sheetName, xc } = splitReference(this.state.range);
37380
- const sheetId = sheetName
37381
- ? this.env.model.getters.getSheetIdByName(sheetName)
37382
- : this.env.model.getters.getActiveSheetId();
37383
- if (!sheetId) {
37429
+ const range = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.range);
37430
+ if (range.invalidSheetName || range.invalidXc) {
37384
37431
  return;
37385
37432
  }
37386
- const zone = toZone(xc);
37387
- const dataSet = { sheetId, zone };
37433
+ const dataSet = { sheetId: range.sheetId, zone: range.zone };
37388
37434
  this.store.update({ dataSet });
37389
37435
  // Immediately apply the update to recompute the pivot fields
37390
37436
  this.store.applyUpdate();
@@ -38317,10 +38363,6 @@ class TablePanel extends owl.Component {
38317
38363
  });
38318
38364
  }
38319
38365
  onRangeChanged(ranges) {
38320
- if (!ranges[0] || !ranges[0].match(rangeReference)) {
38321
- this.state.tableZoneErrors = ["InvalidRange" /* CommandResult.InvalidRange */];
38322
- return;
38323
- }
38324
38366
  const sheetId = this.env.model.getters.getActiveSheetId();
38325
38367
  this.state.tableXc = ranges[0];
38326
38368
  const newTableRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
@@ -38360,11 +38402,6 @@ class TablePanel extends owl.Component {
38360
38402
  const newTableRange = updatedTable.range;
38361
38403
  this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
38362
38404
  }
38363
- else {
38364
- const oldTableRange = this.props.table.range;
38365
- this.state.tableXc = this.env.model.getters.getRangeString(oldTableRange, sheetId);
38366
- }
38367
- this.state.tableZoneErrors = [];
38368
38405
  }
38369
38406
  deleteTable() {
38370
38407
  const sheetId = this.env.model.getters.getActiveSheetId();
@@ -44072,6 +44109,18 @@ function convertOperator(operator) {
44072
44109
  // -------------------------------------
44073
44110
  // WORKSHEET HELPERS
44074
44111
  // -------------------------------------
44112
+ function getCellType(value) {
44113
+ switch (typeof value) {
44114
+ case "boolean":
44115
+ return "b";
44116
+ case "string":
44117
+ return "str";
44118
+ case "number":
44119
+ return "n";
44120
+ default:
44121
+ return undefined;
44122
+ }
44123
+ }
44075
44124
  function convertHeightToExcel(height) {
44076
44125
  return Math.round(HEIGHT_FACTOR * height * 100) / 100;
44077
44126
  }
@@ -49251,7 +49300,10 @@ class HeaderSizePlugin extends CorePlugin {
49251
49300
  handle(cmd) {
49252
49301
  switch (cmd.type) {
49253
49302
  case "CREATE_SHEET": {
49254
- this.history.update("sizes", cmd.sheetId, { COL: [], ROW: [] });
49303
+ this.history.update("sizes", cmd.sheetId, {
49304
+ COL: Array(this.getters.getNumberCols(cmd.sheetId)).fill(undefined),
49305
+ ROW: Array(this.getters.getNumberRows(cmd.sheetId)).fill(undefined),
49306
+ });
49255
49307
  break;
49256
49308
  }
49257
49309
  case "DUPLICATE_SHEET":
@@ -54319,8 +54371,9 @@ class Evaluator {
54319
54371
  }
54320
54372
  getCellsDependingOn(positions) {
54321
54373
  const ranges = [];
54322
- for (const position of positions) {
54323
- ranges.push({ sheetId: position.sheetId, zone: positionToZone(position) });
54374
+ const zonesBySheetIds = aggregatePositionsToZones(positions);
54375
+ for (const sheetId in zonesBySheetIds) {
54376
+ ranges.push(...zonesBySheetIds[sheetId].map((zone) => ({ sheetId, zone })));
54324
54377
  }
54325
54378
  return this.formulaDependencies().getCellsDependingOn(ranges);
54326
54379
  }
@@ -55795,10 +55848,6 @@ class PivotUIPlugin extends UIPlugin {
55795
55848
  this.setupPivot(cmd.pivotId, { recreate: true });
55796
55849
  break;
55797
55850
  }
55798
- case "REMOVE_PIVOT": {
55799
- delete this.pivots[cmd.pivotId];
55800
- break;
55801
- }
55802
55851
  case "DELETE_SHEET":
55803
55852
  case "UPDATE_CELL": {
55804
55853
  this.unusedPivots = undefined;
@@ -55940,6 +55989,9 @@ class PivotUIPlugin extends UIPlugin {
55940
55989
  }
55941
55990
  }
55942
55991
  getPivot(pivotId) {
55992
+ if (!this.getters.isExistingPivot(pivotId)) {
55993
+ throw new Error(`pivot ${pivotId} not found`);
55994
+ }
55943
55995
  return this.pivots[pivotId];
55944
55996
  }
55945
55997
  isPivotUnused(pivotId) {
@@ -57231,9 +57283,9 @@ class Session extends EventBus {
57231
57283
  /**
57232
57284
  * Notify the server that the user client left the collaborative session
57233
57285
  */
57234
- leave(data) {
57286
+ async leave(data) {
57235
57287
  if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
57236
- this.snapshot(data());
57288
+ await this.snapshot(data());
57237
57289
  }
57238
57290
  delete this.clients[this.clientId];
57239
57291
  this.transportService.leave(this.clientId);
@@ -57246,12 +57298,12 @@ class Session extends EventBus {
57246
57298
  /**
57247
57299
  * Send a snapshot of the spreadsheet to the collaboration server
57248
57300
  */
57249
- snapshot(data) {
57301
+ async snapshot(data) {
57250
57302
  if (this.pendingMessages.length !== 0) {
57251
57303
  return;
57252
57304
  }
57253
57305
  const snapshotId = this.uuidGenerator.uuidv4();
57254
- this.transportService.sendMessage({
57306
+ await this.transportService.sendMessage({
57255
57307
  type: "SNAPSHOT",
57256
57308
  nextRevisionId: snapshotId,
57257
57309
  serverRevisionId: this.serverRevisionId,
@@ -57935,7 +57987,7 @@ class InsertPivotPlugin extends UIPlugin {
57935
57987
  this.duplicatePivotInNewSheet(cmd.pivotId, cmd.newPivotId, cmd.newSheetId);
57936
57988
  break;
57937
57989
  case "INSERT_PIVOT_WITH_TABLE":
57938
- this.insertPivotWithTable(cmd.sheetId, cmd.col, cmd.row, cmd.pivotId, cmd.table);
57990
+ this.insertPivotWithTable(cmd.sheetId, cmd.col, cmd.row, cmd.pivotId, cmd.table, cmd.pivotMode);
57939
57991
  break;
57940
57992
  }
57941
57993
  }
@@ -58011,26 +58063,44 @@ class InsertPivotPlugin extends UIPlugin {
58011
58063
  }
58012
58064
  return name;
58013
58065
  }
58014
- insertPivotWithTable(sheetId, col, row, pivotId, table) {
58066
+ insertPivotWithTable(sheetId, col, row, pivotId, table, mode) {
58015
58067
  const { cols, rows, measures, fieldsType } = table;
58016
58068
  const pivotTable = new SpreadsheetPivotTable(cols, rows, measures, fieldsType || {});
58069
+ const numberOfHeaders = pivotTable.columns.length - 1;
58017
58070
  this.resizeSheet(sheetId, col, row, pivotTable);
58018
58071
  const pivotFormulaId = this.getters.getPivotFormulaId(pivotId);
58019
- this.dispatch("UPDATE_CELL", {
58020
- sheetId,
58021
- col,
58022
- row,
58023
- content: `=PIVOT("${pivotFormulaId}")`,
58024
- });
58025
- const zone = {
58026
- left: col,
58027
- right: col,
58028
- top: row,
58029
- bottom: row,
58030
- };
58031
- const numberOfHeaders = pivotTable.columns.length - 1;
58072
+ let zone;
58073
+ if (mode === "dynamic") {
58074
+ this.dispatch("UPDATE_CELL", {
58075
+ sheetId,
58076
+ col,
58077
+ row,
58078
+ content: `=PIVOT(${pivotFormulaId})`,
58079
+ });
58080
+ zone = {
58081
+ left: col,
58082
+ right: col,
58083
+ top: row,
58084
+ bottom: row,
58085
+ };
58086
+ }
58087
+ else {
58088
+ this.dispatch("INSERT_PIVOT", {
58089
+ sheetId,
58090
+ col,
58091
+ row,
58092
+ pivotId,
58093
+ table: pivotTable.export(),
58094
+ });
58095
+ zone = {
58096
+ left: col,
58097
+ right: col + pivotTable.getNumberOfDataColumns(),
58098
+ top: row,
58099
+ bottom: row + numberOfHeaders + pivotTable.rows.length,
58100
+ };
58101
+ }
58032
58102
  this.dispatch("CREATE_TABLE", {
58033
- tableType: "dynamic",
58103
+ tableType: mode,
58034
58104
  sheetId,
58035
58105
  ranges: [this.getters.getRangeDataFromZone(sheetId, zone)],
58036
58106
  config: { ...PIVOT_TABLE_CONFIG, numberOfHeaders },
@@ -59411,6 +59481,7 @@ class ClipboardPlugin extends UIPlugin {
59411
59481
  this.status = "invisible";
59412
59482
  if (this._isCutOperation) {
59413
59483
  this.copiedData = undefined;
59484
+ this._isCutOperation = false;
59414
59485
  }
59415
59486
  break;
59416
59487
  }
@@ -59508,6 +59579,7 @@ class ClipboardPlugin extends UIPlugin {
59508
59579
  }
59509
59580
  case "ACTIVATE_PAINT_FORMAT": {
59510
59581
  const zones = this.getters.getSelectedZones();
59582
+ this._isCutOperation = false;
59511
59583
  this.copiedData = this.copy(zones);
59512
59584
  this.status = "visible";
59513
59585
  if (cmd.persistent) {
@@ -60230,6 +60302,8 @@ class GridSelectionPlugin extends UIPlugin {
60230
60302
  this.selectedFigureId = null;
60231
60303
  break;
60232
60304
  }
60305
+ }
60306
+ finalize() {
60233
60307
  /** Any change to the selection has to be reflected in the selection processor. */
60234
60308
  this.selection.resetDefaultAnchor(this, deepCopy(this.gridSelection.anchor));
60235
60309
  }
@@ -61011,7 +61085,6 @@ class SheetViewPlugin extends UIPlugin {
61011
61085
  }
61012
61086
  }
61013
61087
  handle(cmd) {
61014
- this.cleanViewports();
61015
61088
  // changing the evaluation can hide/show rows because of data filters
61016
61089
  if (invalidateEvaluationCommands.has(cmd.type)) {
61017
61090
  for (const sheetId of this.getters.getSheetIds()) {
@@ -61027,6 +61100,7 @@ class SheetViewPlugin extends UIPlugin {
61027
61100
  break;
61028
61101
  case "UNDO":
61029
61102
  case "REDO":
61103
+ this.cleanViewports();
61030
61104
  for (const sheetId of this.getters.getSheetIds()) {
61031
61105
  this.sheetsWithDirtyViewports.add(sheetId);
61032
61106
  }
@@ -61081,6 +61155,9 @@ class SheetViewPlugin extends UIPlugin {
61081
61155
  }
61082
61156
  }
61083
61157
  break;
61158
+ case "DELETE_SHEET":
61159
+ this.cleanViewports();
61160
+ break;
61084
61161
  case "ACTIVATE_SHEET":
61085
61162
  this.sheetsWithDirtyViewports.add(cmd.sheetIdTo);
61086
61163
  break;
@@ -62368,6 +62445,17 @@ css /* scss */ `
62368
62445
  .o-bottom-bar-fade-in {
62369
62446
  background-image: linear-gradient(90deg, #cfcfcf, transparent 1%);
62370
62447
  }
62448
+
62449
+ .o-sheet-list {
62450
+ overflow-y: hidden;
62451
+ overflow-x: auto;
62452
+
62453
+ &::-webkit-scrollbar {
62454
+ display: none; /* Chrome */
62455
+ }
62456
+ -ms-overflow-style: none; /* IE and Edge */
62457
+ scrollbar-width: none; /* Firefox */
62458
+ }
62371
62459
  }
62372
62460
 
62373
62461
  .o-bottom-bar-arrows {
@@ -64341,7 +64429,7 @@ class Spreadsheet extends owl.Component {
64341
64429
 
64342
64430
  class LocalTransportService {
64343
64431
  listeners = [];
64344
- sendMessage(message) {
64432
+ async sendMessage(message) {
64345
64433
  for (const { callback } of this.listeners) {
64346
64434
  callback(message);
64347
64435
  }
@@ -66434,17 +66522,13 @@ function addFormula(cell) {
66434
66522
  if (!formula) {
66435
66523
  return { attrs: [], node: escapeXml `` };
66436
66524
  }
66437
- const attrs = [];
66438
- let node = escapeXml ``;
66439
- let cycle = escapeXml ``;
66440
- const XlsxFormula = adaptFormulaToExcel(formula);
66441
- // hack for cycles : if we don't set a value (be it 0 or #VALUE!), it will appear as invisible on excel,
66442
- // Making it very hard for the client to find where the recursion is.
66443
- if (cell.value === CellErrorType.CircularDependency) {
66444
- attrs.push(["t", "str"]);
66445
- cycle = escapeXml /*xml*/ `<v>${cell.value}</v>`;
66525
+ const type = getCellType(cell.value);
66526
+ if (type === undefined) {
66527
+ return { attrs: [], node: escapeXml `` };
66446
66528
  }
66447
- node = escapeXml /*xml*/ `<f>${XlsxFormula}</f>${cycle}`;
66529
+ const attrs = [["t", type]];
66530
+ const XlsxFormula = adaptFormulaToExcel(formula);
66531
+ const node = escapeXml /*xml*/ `<f>${XlsxFormula}</f><v>${cell.value}</v>`;
66448
66532
  return { attrs, node };
66449
66533
  }
66450
66534
  function addContent(content, sharedStrings, forceString = false) {
@@ -67858,8 +67942,8 @@ class Model extends EventBus {
67858
67942
  joinSession() {
67859
67943
  this.session.join(this.config.client);
67860
67944
  }
67861
- leaveSession() {
67862
- this.session.leave(lazy(() => this.exportData()));
67945
+ async leaveSession() {
67946
+ await this.session.leave(lazy(() => this.exportData()));
67863
67947
  }
67864
67948
  setupUiPlugin(Plugin) {
67865
67949
  const plugin = new Plugin(this.uiPluginConfig);
@@ -68461,6 +68545,6 @@ exports.tokenColors = tokenColors;
68461
68545
  exports.tokenize = tokenize;
68462
68546
 
68463
68547
 
68464
- __info__.version = "17.4.5";
68465
- __info__.date = "2024-08-19T08:12:00.492Z";
68466
- __info__.hash = "28579ad";
68548
+ __info__.version = "17.4.7";
68549
+ __info__.date = "2024-09-05T09:32:00.461Z";
68550
+ __info__.hash = "c14a4c9";
@@ -1283,6 +1283,7 @@ interface InsertPivotWithTableCommand {
1283
1283
  row: HeaderIndex;
1284
1284
  pivotId: UID;
1285
1285
  table: PivotTableData;
1286
+ pivotMode: "static" | "dynamic";
1286
1287
  }
1287
1288
  type CoreCommand =
1288
1289
  /** CELLS */
@@ -3769,7 +3770,7 @@ interface TransportService<T = any> {
3769
3770
  /**
3770
3771
  * Send a message to all clients
3771
3772
  */
3772
- sendMessage: (message: T) => void;
3773
+ sendMessage: (message: T) => Promise<void>;
3773
3774
  /**
3774
3775
  * Register a callback function which will be called each time
3775
3776
  * a new message is received.
@@ -3866,11 +3867,11 @@ declare class Session extends EventBus<CollaborativeEvent> {
3866
3867
  /**
3867
3868
  * Notify the server that the user client left the collaborative session
3868
3869
  */
3869
- leave(data: Lazy<WorkbookData>): void;
3870
+ leave(data: Lazy<WorkbookData>): Promise<void>;
3870
3871
  /**
3871
3872
  * Send a snapshot of the spreadsheet to the collaboration server
3872
3873
  */
3873
- snapshot(data: WorkbookData): void;
3874
+ snapshot(data: WorkbookData): Promise<void>;
3874
3875
  getClient(): Client;
3875
3876
  getConnectedClients(): Set<Client>;
3876
3877
  getRevisionId(): UID;
@@ -4829,6 +4830,7 @@ declare class GridSelectionPlugin extends UIPlugin {
4829
4830
  allowDispatch(cmd: LocalCommand): CommandResult;
4830
4831
  private handleEvent;
4831
4832
  handle(cmd: Command): void;
4833
+ finalize(): void;
4832
4834
  isGridSelectionActive(): boolean;
4833
4835
  getActiveSheet(): Readonly<Sheet>;
4834
4836
  getActiveSheetId(): UID;
@@ -5780,7 +5782,7 @@ declare class Model extends EventBus<any> implements CommandDispatcher {
5780
5782
  private readonly coreHandlers;
5781
5783
  constructor(data?: any, config?: Partial<ModelConfig>, stateUpdateMessages?: StateUpdateMessage[], uuidGenerator?: UuidGenerator, verboseImport?: boolean);
5782
5784
  joinSession(): void;
5783
- leaveSession(): void;
5785
+ leaveSession(): Promise<void>;
5784
5786
  private setupUiPlugin;
5785
5787
  /**
5786
5788
  * Initialize and properly configure a plugin.
@@ -9102,15 +9104,13 @@ declare class FindAndReplaceStore extends SpreadsheetStore implements HighlightP
9102
9104
  toSearch: string;
9103
9105
  toReplace: string;
9104
9106
  searchOptions: SearchOptions;
9105
- updateSearchContent: DebouncedFunction<(toSearch: string) => void>;
9106
9107
  constructor(get: Get);
9107
9108
  get searchMatches(): CellPosition[];
9108
- private _updateSearchContent;
9109
+ updateSearchContent(toSearch: string): void;
9109
9110
  updateSearchOptions(searchOptions: Partial<SearchOptions>): void;
9110
9111
  searchFormulas(showFormula: boolean): void;
9111
9112
  selectPreviousMatch(): void;
9112
9113
  selectNextMatch(): void;
9113
- get pendingSearch(): boolean;
9114
9114
  handle(cmd: Command): void;
9115
9115
  finalize(): void;
9116
9116
  get allSheetMatchesCount(): number;
@@ -9931,12 +9931,14 @@ declare const sortDescending: ActionSpec;
9931
9931
  declare const createRemoveFilter: ActionSpec;
9932
9932
  declare const createRemoveFilterTool: ActionSpec;
9933
9933
  declare const splitToColumns: ActionSpec;
9934
- declare const reinsertPivotMenu: ActionSpec;
9934
+ declare const reinsertDynamicPivotMenu: ActionSpec;
9935
+ declare const reinsertStaticPivotMenu: ActionSpec;
9935
9936
 
9936
9937
  declare const ACTION_DATA_createRemoveFilter: typeof createRemoveFilter;
9937
9938
  declare const ACTION_DATA_createRemoveFilterTool: typeof createRemoveFilterTool;
9938
9939
  declare const ACTION_DATA_dataCleanup: typeof dataCleanup;
9939
- declare const ACTION_DATA_reinsertPivotMenu: typeof reinsertPivotMenu;
9940
+ declare const ACTION_DATA_reinsertDynamicPivotMenu: typeof reinsertDynamicPivotMenu;
9941
+ declare const ACTION_DATA_reinsertStaticPivotMenu: typeof reinsertStaticPivotMenu;
9940
9942
  declare const ACTION_DATA_removeDuplicates: typeof removeDuplicates;
9941
9943
  declare const ACTION_DATA_sortAscending: typeof sortAscending;
9942
9944
  declare const ACTION_DATA_sortDescending: typeof sortDescending;
@@ -9948,7 +9950,8 @@ declare namespace ACTION_DATA {
9948
9950
  ACTION_DATA_createRemoveFilter as createRemoveFilter,
9949
9951
  ACTION_DATA_createRemoveFilterTool as createRemoveFilterTool,
9950
9952
  ACTION_DATA_dataCleanup as dataCleanup,
9951
- ACTION_DATA_reinsertPivotMenu as reinsertPivotMenu,
9953
+ ACTION_DATA_reinsertDynamicPivotMenu as reinsertDynamicPivotMenu,
9954
+ ACTION_DATA_reinsertStaticPivotMenu as reinsertStaticPivotMenu,
9952
9955
  ACTION_DATA_removeDuplicates as removeDuplicates,
9953
9956
  ACTION_DATA_sortAscending as sortAscending,
9954
9957
  ACTION_DATA_sortDescending as sortDescending,
@@ -11598,6 +11601,7 @@ declare const constants: {
11598
11601
  bandedRows: boolean;
11599
11602
  bandedColumns: boolean;
11600
11603
  styleId: string;
11604
+ automaticAutofill: boolean;
11601
11605
  };
11602
11606
  ChartTerms: {
11603
11607
  Series: string;