@odoo/o-spreadsheet 18.0.11 → 18.0.12

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.11
6
- * @date 2025-01-27T10:08:13.567Z
7
- * @hash e8c6bd1
5
+ * @version 18.0.12
6
+ * @date 2025-01-29T06:24:22.122Z
7
+ * @hash a881cff
8
8
  */
9
9
 
10
10
  'use strict';
@@ -9457,13 +9457,13 @@ function toExcelDataset(getters, ds) {
9457
9457
  else if (ds.labelCell) {
9458
9458
  label = {
9459
9459
  reference: getters.getRangeString(ds.labelCell, "forceSheetReference", {
9460
- useFixedReference: true,
9460
+ useBoundedReference: true,
9461
9461
  }),
9462
9462
  };
9463
9463
  }
9464
9464
  return {
9465
9465
  label,
9466
- range: getters.getRangeString(dataRange, "forceSheetReference", { useFixedReference: true }),
9466
+ range: getters.getRangeString(dataRange, "forceSheetReference", { useBoundedReference: true }),
9467
9467
  backgroundColor: ds.backgroundColor,
9468
9468
  rightYAxis: ds.rightYAxis,
9469
9469
  };
@@ -9478,7 +9478,7 @@ function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
9478
9478
  zone.top = zone.top + 1;
9479
9479
  }
9480
9480
  const range = labelRange.clone({ zone });
9481
- return getters.getRangeString(range, "forceSheetReference", { useFixedReference: true });
9481
+ return getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
9482
9482
  }
9483
9483
  /**
9484
9484
  * Transform a chart definition which supports dataSets (dataSets and LabelRange)
@@ -9642,11 +9642,7 @@ function interpolateData(config, values, labels, newLabels) {
9642
9642
  if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
9643
9643
  return [];
9644
9644
  }
9645
- const labelMin = Math.min(...labels);
9646
- const labelMax = Math.max(...labels);
9647
- const labelRange = labelMax - labelMin;
9648
- const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
9649
- const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
9645
+ const { normalizedLabels, normalizedNewLabels } = normalizeLabels(labels, newLabels, config);
9650
9646
  try {
9651
9647
  switch (config.type) {
9652
9648
  case "polynomial": {
@@ -9685,6 +9681,30 @@ function interpolateData(config, values, labels, newLabels) {
9685
9681
  return Array.from({ length: newLabels.length }, () => NaN);
9686
9682
  }
9687
9683
  }
9684
+ function normalizeLabels(labels, newLabels, config) {
9685
+ let normalizedLabels = [];
9686
+ let normalizedNewLabels = [];
9687
+ if (config.type === "logarithmic") {
9688
+ // Logarithmic trends in charts are used to visualize proportional growth or
9689
+ // relative changes. Therefore, we change the normalization technique for
9690
+ // logarithmic trend lines for a better fit. The method used here is Max Absolute
9691
+ // Scaling. This Technique is ideal for data spanning several orders of magnitude,
9692
+ // as it balances differences between small and large values by compressing larger
9693
+ // values while preserving proportionality and ensuring all values are scaled relative
9694
+ // to the largest magnitude.
9695
+ const labelMax = Math.max(...labels.map(Math.abs));
9696
+ normalizedLabels = labels.map((l) => l / labelMax);
9697
+ normalizedNewLabels = newLabels.map((l) => l / labelMax);
9698
+ }
9699
+ else {
9700
+ const labelMax = Math.max(...labels);
9701
+ const labelMin = Math.min(...labels);
9702
+ const labelRange = labelMax - labelMin;
9703
+ normalizedLabels = labels.map((l) => (l - labelMax) / labelRange);
9704
+ normalizedNewLabels = newLabels.map((l) => (l - labelMax) / labelRange);
9705
+ }
9706
+ return { normalizedLabels, normalizedNewLabels };
9707
+ }
9688
9708
  function formatTickValue(localeFormat) {
9689
9709
  return (value) => {
9690
9710
  value = Number(value);
@@ -51365,7 +51385,7 @@ class CellPlugin extends CorePlugin {
51365
51385
  /*
51366
51386
  * Reconstructs the original formula string based on new dependencies
51367
51387
  */
51368
- getFormulaString(sheetId, tokens, dependencies, useFixedReference = false) {
51388
+ getFormulaString(sheetId, tokens, dependencies, useBoundedReference = false) {
51369
51389
  if (!dependencies.length) {
51370
51390
  return concat(tokens.map((token) => token.value));
51371
51391
  }
@@ -51373,7 +51393,7 @@ class CellPlugin extends CorePlugin {
51373
51393
  return concat(tokens.map((token) => {
51374
51394
  if (token.type === "REFERENCE") {
51375
51395
  const range = dependencies[rangeIndex++];
51376
- return this.getters.getRangeString(range, sheetId, { useFixedReference });
51396
+ return this.getters.getRangeString(range, sheetId, { useBoundedReference });
51377
51397
  }
51378
51398
  return token.value;
51379
51399
  }));
@@ -51653,7 +51673,7 @@ class FormulaCellWithDependencies {
51653
51673
  if (token.type === "REFERENCE") {
51654
51674
  const index = rangeIndex++;
51655
51675
  return this.getRangeString(this.compiledFormula.dependencies[index], this.sheetId, {
51656
- useFixedReference: true,
51676
+ useBoundedReference: true,
51657
51677
  });
51658
51678
  }
51659
51679
  return token.value;
@@ -51990,7 +52010,7 @@ class ConditionalFormatPlugin extends CorePlugin {
51990
52010
  if (data.sheets) {
51991
52011
  for (let sheet of data.sheets) {
51992
52012
  if (this.cfRules[sheet.id]) {
51993
- sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useFixedReference: true }));
52013
+ sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useBoundedReference: true }));
51994
52014
  }
51995
52015
  }
51996
52016
  }
@@ -52059,9 +52079,9 @@ class ConditionalFormatPlugin extends CorePlugin {
52059
52079
  // ---------------------------------------------------------------------------
52060
52080
  // Private
52061
52081
  // ---------------------------------------------------------------------------
52062
- mapToConditionalFormat(sheetId, cf, { useFixedReference } = { useFixedReference: false }) {
52082
+ mapToConditionalFormat(sheetId, cf, { useBoundedReference } = { useBoundedReference: false }) {
52063
52083
  const ranges = cf.ranges.map((range) => {
52064
- return this.getters.getRangeString(range, sheetId, { useFixedReference });
52084
+ return this.getters.getRangeString(range, sheetId, { useBoundedReference });
52065
52085
  });
52066
52086
  if (cf.rule.type !== "DataBarRule") {
52067
52087
  return {
@@ -52076,7 +52096,7 @@ class ConditionalFormatPlugin extends CorePlugin {
52076
52096
  ...cf.rule,
52077
52097
  rangeValues: cf.rule.rangeValues &&
52078
52098
  this.getters.getRangeString(cf.rule.rangeValues, sheetId, {
52079
- useFixedReference,
52099
+ useBoundedReference,
52080
52100
  }),
52081
52101
  },
52082
52102
  ranges,
@@ -52506,10 +52526,20 @@ class DataValidationPlugin extends CorePlugin {
52506
52526
  for (const sheet of data.sheets) {
52507
52527
  sheet.dataValidationRules = [];
52508
52528
  for (const rule of this.rules[sheet.id]) {
52509
- sheet.dataValidationRules.push({
52510
- ...rule,
52511
- ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, { useFixedReference: true })),
52512
- });
52529
+ const excelRule = {
52530
+ ...deepCopy(rule),
52531
+ ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, { useBoundedReference: true })),
52532
+ };
52533
+ if (rule.criterion.type === "isValueInRange") {
52534
+ excelRule.criterion.values = rule.criterion.values.map((value) => {
52535
+ const range = this.getters.getRangeFromSheetXC(sheet.id, value);
52536
+ return this.getters.getRangeString(range, sheet.id, {
52537
+ useBoundedReference: true,
52538
+ useFixedReference: true,
52539
+ });
52540
+ });
52541
+ }
52542
+ sheet.dataValidationRules.push(excelRule);
52513
52543
  }
52514
52544
  }
52515
52545
  }
@@ -53923,9 +53953,10 @@ class RangeAdapter {
53923
53953
  * @param range the range (received from getRangeFromXC or getRangeFromZone)
53924
53954
  * @param forSheetId the id of the sheet where the range string is supposed to be used.
53925
53955
  * @param options
53956
+ * @param options.useBoundedReference if true, the range will be returned with bounded row and column
53926
53957
  * @param options.useFixedReference if true, the range will be returned with fixed row and column
53927
53958
  */
53928
- getRangeString(range, forSheetId, options = { useFixedReference: false }) {
53959
+ getRangeString(range, forSheetId, options = { useBoundedReference: false, useFixedReference: false }) {
53929
53960
  if (!range) {
53930
53961
  return CellErrorType.InvalidReference;
53931
53962
  }
@@ -54028,13 +54059,13 @@ class RangeAdapter {
54028
54059
  /**
54029
54060
  * Get a Xc string that represent a part of a range
54030
54061
  */
54031
- getRangePartString(range, part, options = { useFixedReference: false }) {
54032
- const colFixed = range.parts && range.parts[part]?.colFixed ? "$" : "";
54062
+ getRangePartString(range, part, options = { useBoundedReference: false, useFixedReference: false }) {
54063
+ const colFixed = range.parts[part]?.colFixed || options.useFixedReference ? "$" : "";
54033
54064
  const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
54034
- const rowFixed = range.parts && range.parts[part]?.rowFixed ? "$" : "";
54065
+ const rowFixed = range.parts[part]?.rowFixed || options.useFixedReference ? "$" : "";
54035
54066
  const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
54036
54067
  let str = "";
54037
- if (range.isFullCol && !options.useFixedReference) {
54068
+ if (range.isFullCol && !options.useBoundedReference) {
54038
54069
  if (part === 0 && range.unboundedZone.hasHeader) {
54039
54070
  str = colFixed + col + rowFixed + row;
54040
54071
  }
@@ -54042,7 +54073,7 @@ class RangeAdapter {
54042
54073
  str = colFixed + col;
54043
54074
  }
54044
54075
  }
54045
- else if (range.isFullRow && !options.useFixedReference) {
54076
+ else if (range.isFullRow && !options.useBoundedReference) {
54046
54077
  if (part === 0 && range.unboundedZone.hasHeader) {
54047
54078
  str = colFixed + col + rowFixed + row;
54048
54079
  }
@@ -61242,6 +61273,7 @@ class Session extends EventBus {
61242
61273
  waitingUndoRedoAck = false;
61243
61274
  isReplayingInitialRevisions = false;
61244
61275
  processedRevisions = new Set();
61276
+ lastRevisionMessage = undefined;
61245
61277
  uuidGenerator = new UuidGenerator();
61246
61278
  lastLocalOperation;
61247
61279
  /**
@@ -61342,7 +61374,10 @@ class Session extends EventBus {
61342
61374
  * Notify the server that the user client left the collaborative session
61343
61375
  */
61344
61376
  async leave(data) {
61345
- if (data && Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
61377
+ if (data &&
61378
+ Object.keys(this.clients).length === 1 &&
61379
+ this.lastRevisionMessage &&
61380
+ this.lastRevisionMessage?.type !== "SNAPSHOT_CREATED") {
61346
61381
  await this.snapshot(data());
61347
61382
  }
61348
61383
  delete this.clients[this.clientId];
@@ -61563,6 +61598,7 @@ class Session extends EventBus {
61563
61598
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
61564
61599
  this.serverRevisionId = message.nextRevisionId;
61565
61600
  this.processedRevisions.add(message.nextRevisionId);
61601
+ this.lastRevisionMessage = message;
61566
61602
  this.sendPendingMessage();
61567
61603
  break;
61568
61604
  }
@@ -73054,6 +73090,6 @@ exports.tokenColors = tokenColors;
73054
73090
  exports.tokenize = tokenize;
73055
73091
 
73056
73092
 
73057
- __info__.version = "18.0.11";
73058
- __info__.date = "2025-01-27T10:08:13.567Z";
73059
- __info__.hash = "e8c6bd1";
73093
+ __info__.version = "18.0.12";
73094
+ __info__.date = "2025-01-29T06:24:22.122Z";
73095
+ __info__.hash = "a881cff";
@@ -1205,6 +1205,7 @@ declare class Session extends EventBus<CollaborativeEvent> {
1205
1205
  private waitingUndoRedoAck;
1206
1206
  private isReplayingInitialRevisions;
1207
1207
  private processedRevisions;
1208
+ private lastRevisionMessage;
1208
1209
  private uuidGenerator;
1209
1210
  private lastLocalOperation;
1210
1211
  /**
@@ -3463,6 +3464,10 @@ interface SpreadsheetChildEnv extends NotificationStoreMethods {
3463
3464
  getStore: Get;
3464
3465
  }
3465
3466
 
3467
+ interface RangeStringOptions {
3468
+ useBoundedReference?: boolean;
3469
+ useFixedReference?: boolean;
3470
+ }
3466
3471
  declare class RangeAdapter implements CommandHandler<CoreCommand> {
3467
3472
  private getters;
3468
3473
  private providers;
@@ -3510,11 +3515,10 @@ declare class RangeAdapter implements CommandHandler<CoreCommand> {
3510
3515
  * @param range the range (received from getRangeFromXC or getRangeFromZone)
3511
3516
  * @param forSheetId the id of the sheet where the range string is supposed to be used.
3512
3517
  * @param options
3518
+ * @param options.useBoundedReference if true, the range will be returned with bounded row and column
3513
3519
  * @param options.useFixedReference if true, the range will be returned with fixed row and column
3514
3520
  */
3515
- getRangeString(range: Range, forSheetId: UID, options?: {
3516
- useFixedReference: boolean;
3517
- }): string;
3521
+ getRangeString(range: Range, forSheetId: UID, options?: RangeStringOptions): string;
3518
3522
  getRangeDataFromXc(sheetId: UID, xc: string): RangeData;
3519
3523
  getRangeDataFromZone(sheetId: UID, zone: Zone | UnboundedZone): RangeData;
3520
3524
  getRangeFromZone(sheetId: UID, zone: Zone | UnboundedZone): Range;
@@ -3750,7 +3754,7 @@ declare class CellPlugin extends CorePlugin<CoreState$1> implements CoreState$1
3750
3754
  * starting an async evaluation even if it has been moved or re-allocated
3751
3755
  */
3752
3756
  getCellById(cellId: UID): Cell | undefined;
3753
- getFormulaString(sheetId: UID, tokens: Token[], dependencies: Range[], useFixedReference?: boolean): string;
3757
+ getFormulaString(sheetId: UID, tokens: Token[], dependencies: Range[], useBoundedReference?: boolean): string;
3754
3758
  getTranslatedCellFormula(sheetId: UID, offsetX: number, offsetY: number, tokens: Token[]): string;
3755
3759
  getFormulaMovedInSheet(originSheetId: UID, targetSheetId: UID, tokens: Token[]): string;
3756
3760
  getCellStyle(position: CellPosition): Style;
@@ -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.11
6
- * @date 2025-01-27T10:08:13.567Z
7
- * @hash e8c6bd1
5
+ * @version 18.0.12
6
+ * @date 2025-01-29T06:24:22.122Z
7
+ * @hash a881cff
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';
@@ -9455,13 +9455,13 @@ function toExcelDataset(getters, ds) {
9455
9455
  else if (ds.labelCell) {
9456
9456
  label = {
9457
9457
  reference: getters.getRangeString(ds.labelCell, "forceSheetReference", {
9458
- useFixedReference: true,
9458
+ useBoundedReference: true,
9459
9459
  }),
9460
9460
  };
9461
9461
  }
9462
9462
  return {
9463
9463
  label,
9464
- range: getters.getRangeString(dataRange, "forceSheetReference", { useFixedReference: true }),
9464
+ range: getters.getRangeString(dataRange, "forceSheetReference", { useBoundedReference: true }),
9465
9465
  backgroundColor: ds.backgroundColor,
9466
9466
  rightYAxis: ds.rightYAxis,
9467
9467
  };
@@ -9476,7 +9476,7 @@ function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
9476
9476
  zone.top = zone.top + 1;
9477
9477
  }
9478
9478
  const range = labelRange.clone({ zone });
9479
- return getters.getRangeString(range, "forceSheetReference", { useFixedReference: true });
9479
+ return getters.getRangeString(range, "forceSheetReference", { useBoundedReference: true });
9480
9480
  }
9481
9481
  /**
9482
9482
  * Transform a chart definition which supports dataSets (dataSets and LabelRange)
@@ -9640,11 +9640,7 @@ function interpolateData(config, values, labels, newLabels) {
9640
9640
  if (values.length < 2 || labels.length < 2 || newLabels.length === 0) {
9641
9641
  return [];
9642
9642
  }
9643
- const labelMin = Math.min(...labels);
9644
- const labelMax = Math.max(...labels);
9645
- const labelRange = labelMax - labelMin;
9646
- const normalizedLabels = labels.map((v) => (v - labelMin) / labelRange);
9647
- const normalizedNewLabels = newLabels.map((v) => (v - labelMin) / labelRange);
9643
+ const { normalizedLabels, normalizedNewLabels } = normalizeLabels(labels, newLabels, config);
9648
9644
  try {
9649
9645
  switch (config.type) {
9650
9646
  case "polynomial": {
@@ -9683,6 +9679,30 @@ function interpolateData(config, values, labels, newLabels) {
9683
9679
  return Array.from({ length: newLabels.length }, () => NaN);
9684
9680
  }
9685
9681
  }
9682
+ function normalizeLabels(labels, newLabels, config) {
9683
+ let normalizedLabels = [];
9684
+ let normalizedNewLabels = [];
9685
+ if (config.type === "logarithmic") {
9686
+ // Logarithmic trends in charts are used to visualize proportional growth or
9687
+ // relative changes. Therefore, we change the normalization technique for
9688
+ // logarithmic trend lines for a better fit. The method used here is Max Absolute
9689
+ // Scaling. This Technique is ideal for data spanning several orders of magnitude,
9690
+ // as it balances differences between small and large values by compressing larger
9691
+ // values while preserving proportionality and ensuring all values are scaled relative
9692
+ // to the largest magnitude.
9693
+ const labelMax = Math.max(...labels.map(Math.abs));
9694
+ normalizedLabels = labels.map((l) => l / labelMax);
9695
+ normalizedNewLabels = newLabels.map((l) => l / labelMax);
9696
+ }
9697
+ else {
9698
+ const labelMax = Math.max(...labels);
9699
+ const labelMin = Math.min(...labels);
9700
+ const labelRange = labelMax - labelMin;
9701
+ normalizedLabels = labels.map((l) => (l - labelMax) / labelRange);
9702
+ normalizedNewLabels = newLabels.map((l) => (l - labelMax) / labelRange);
9703
+ }
9704
+ return { normalizedLabels, normalizedNewLabels };
9705
+ }
9686
9706
  function formatTickValue(localeFormat) {
9687
9707
  return (value) => {
9688
9708
  value = Number(value);
@@ -51363,7 +51383,7 @@ class CellPlugin extends CorePlugin {
51363
51383
  /*
51364
51384
  * Reconstructs the original formula string based on new dependencies
51365
51385
  */
51366
- getFormulaString(sheetId, tokens, dependencies, useFixedReference = false) {
51386
+ getFormulaString(sheetId, tokens, dependencies, useBoundedReference = false) {
51367
51387
  if (!dependencies.length) {
51368
51388
  return concat(tokens.map((token) => token.value));
51369
51389
  }
@@ -51371,7 +51391,7 @@ class CellPlugin extends CorePlugin {
51371
51391
  return concat(tokens.map((token) => {
51372
51392
  if (token.type === "REFERENCE") {
51373
51393
  const range = dependencies[rangeIndex++];
51374
- return this.getters.getRangeString(range, sheetId, { useFixedReference });
51394
+ return this.getters.getRangeString(range, sheetId, { useBoundedReference });
51375
51395
  }
51376
51396
  return token.value;
51377
51397
  }));
@@ -51651,7 +51671,7 @@ class FormulaCellWithDependencies {
51651
51671
  if (token.type === "REFERENCE") {
51652
51672
  const index = rangeIndex++;
51653
51673
  return this.getRangeString(this.compiledFormula.dependencies[index], this.sheetId, {
51654
- useFixedReference: true,
51674
+ useBoundedReference: true,
51655
51675
  });
51656
51676
  }
51657
51677
  return token.value;
@@ -51988,7 +52008,7 @@ class ConditionalFormatPlugin extends CorePlugin {
51988
52008
  if (data.sheets) {
51989
52009
  for (let sheet of data.sheets) {
51990
52010
  if (this.cfRules[sheet.id]) {
51991
- sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useFixedReference: true }));
52011
+ sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useBoundedReference: true }));
51992
52012
  }
51993
52013
  }
51994
52014
  }
@@ -52057,9 +52077,9 @@ class ConditionalFormatPlugin extends CorePlugin {
52057
52077
  // ---------------------------------------------------------------------------
52058
52078
  // Private
52059
52079
  // ---------------------------------------------------------------------------
52060
- mapToConditionalFormat(sheetId, cf, { useFixedReference } = { useFixedReference: false }) {
52080
+ mapToConditionalFormat(sheetId, cf, { useBoundedReference } = { useBoundedReference: false }) {
52061
52081
  const ranges = cf.ranges.map((range) => {
52062
- return this.getters.getRangeString(range, sheetId, { useFixedReference });
52082
+ return this.getters.getRangeString(range, sheetId, { useBoundedReference });
52063
52083
  });
52064
52084
  if (cf.rule.type !== "DataBarRule") {
52065
52085
  return {
@@ -52074,7 +52094,7 @@ class ConditionalFormatPlugin extends CorePlugin {
52074
52094
  ...cf.rule,
52075
52095
  rangeValues: cf.rule.rangeValues &&
52076
52096
  this.getters.getRangeString(cf.rule.rangeValues, sheetId, {
52077
- useFixedReference,
52097
+ useBoundedReference,
52078
52098
  }),
52079
52099
  },
52080
52100
  ranges,
@@ -52504,10 +52524,20 @@ class DataValidationPlugin extends CorePlugin {
52504
52524
  for (const sheet of data.sheets) {
52505
52525
  sheet.dataValidationRules = [];
52506
52526
  for (const rule of this.rules[sheet.id]) {
52507
- sheet.dataValidationRules.push({
52508
- ...rule,
52509
- ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, { useFixedReference: true })),
52510
- });
52527
+ const excelRule = {
52528
+ ...deepCopy(rule),
52529
+ ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, { useBoundedReference: true })),
52530
+ };
52531
+ if (rule.criterion.type === "isValueInRange") {
52532
+ excelRule.criterion.values = rule.criterion.values.map((value) => {
52533
+ const range = this.getters.getRangeFromSheetXC(sheet.id, value);
52534
+ return this.getters.getRangeString(range, sheet.id, {
52535
+ useBoundedReference: true,
52536
+ useFixedReference: true,
52537
+ });
52538
+ });
52539
+ }
52540
+ sheet.dataValidationRules.push(excelRule);
52511
52541
  }
52512
52542
  }
52513
52543
  }
@@ -53921,9 +53951,10 @@ class RangeAdapter {
53921
53951
  * @param range the range (received from getRangeFromXC or getRangeFromZone)
53922
53952
  * @param forSheetId the id of the sheet where the range string is supposed to be used.
53923
53953
  * @param options
53954
+ * @param options.useBoundedReference if true, the range will be returned with bounded row and column
53924
53955
  * @param options.useFixedReference if true, the range will be returned with fixed row and column
53925
53956
  */
53926
- getRangeString(range, forSheetId, options = { useFixedReference: false }) {
53957
+ getRangeString(range, forSheetId, options = { useBoundedReference: false, useFixedReference: false }) {
53927
53958
  if (!range) {
53928
53959
  return CellErrorType.InvalidReference;
53929
53960
  }
@@ -54026,13 +54057,13 @@ class RangeAdapter {
54026
54057
  /**
54027
54058
  * Get a Xc string that represent a part of a range
54028
54059
  */
54029
- getRangePartString(range, part, options = { useFixedReference: false }) {
54030
- const colFixed = range.parts && range.parts[part]?.colFixed ? "$" : "";
54060
+ getRangePartString(range, part, options = { useBoundedReference: false, useFixedReference: false }) {
54061
+ const colFixed = range.parts[part]?.colFixed || options.useFixedReference ? "$" : "";
54031
54062
  const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
54032
- const rowFixed = range.parts && range.parts[part]?.rowFixed ? "$" : "";
54063
+ const rowFixed = range.parts[part]?.rowFixed || options.useFixedReference ? "$" : "";
54033
54064
  const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
54034
54065
  let str = "";
54035
- if (range.isFullCol && !options.useFixedReference) {
54066
+ if (range.isFullCol && !options.useBoundedReference) {
54036
54067
  if (part === 0 && range.unboundedZone.hasHeader) {
54037
54068
  str = colFixed + col + rowFixed + row;
54038
54069
  }
@@ -54040,7 +54071,7 @@ class RangeAdapter {
54040
54071
  str = colFixed + col;
54041
54072
  }
54042
54073
  }
54043
- else if (range.isFullRow && !options.useFixedReference) {
54074
+ else if (range.isFullRow && !options.useBoundedReference) {
54044
54075
  if (part === 0 && range.unboundedZone.hasHeader) {
54045
54076
  str = colFixed + col + rowFixed + row;
54046
54077
  }
@@ -61240,6 +61271,7 @@ class Session extends EventBus {
61240
61271
  waitingUndoRedoAck = false;
61241
61272
  isReplayingInitialRevisions = false;
61242
61273
  processedRevisions = new Set();
61274
+ lastRevisionMessage = undefined;
61243
61275
  uuidGenerator = new UuidGenerator();
61244
61276
  lastLocalOperation;
61245
61277
  /**
@@ -61340,7 +61372,10 @@ class Session extends EventBus {
61340
61372
  * Notify the server that the user client left the collaborative session
61341
61373
  */
61342
61374
  async leave(data) {
61343
- if (data && Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
61375
+ if (data &&
61376
+ Object.keys(this.clients).length === 1 &&
61377
+ this.lastRevisionMessage &&
61378
+ this.lastRevisionMessage?.type !== "SNAPSHOT_CREATED") {
61344
61379
  await this.snapshot(data());
61345
61380
  }
61346
61381
  delete this.clients[this.clientId];
@@ -61561,6 +61596,7 @@ class Session extends EventBus {
61561
61596
  this.pendingMessages = this.pendingMessages.filter((msg) => msg.nextRevisionId !== message.nextRevisionId);
61562
61597
  this.serverRevisionId = message.nextRevisionId;
61563
61598
  this.processedRevisions.add(message.nextRevisionId);
61599
+ this.lastRevisionMessage = message;
61564
61600
  this.sendPendingMessage();
61565
61601
  break;
61566
61602
  }
@@ -73009,6 +73045,6 @@ const constants = {
73009
73045
  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 };
73010
73046
 
73011
73047
 
73012
- __info__.version = "18.0.11";
73013
- __info__.date = "2025-01-27T10:08:13.567Z";
73014
- __info__.hash = "e8c6bd1";
73048
+ __info__.version = "18.0.12";
73049
+ __info__.date = "2025-01-29T06:24:22.122Z";
73050
+ __info__.hash = "a881cff";