@odoo/o-spreadsheet 19.3.10 → 19.3.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 19.3.10
6
- * @date 2026-07-01T05:04:42.999Z
7
- * @hash 040ae04
5
+ * @version 19.3.12
6
+ * @date 2026-07-20T11:02:44.416Z
7
+ * @hash 2b42707
8
8
  */
9
9
 
10
10
  (function(exports, _odoo_owl) {
@@ -5569,7 +5569,7 @@ stores.inject(MyMetaStore, storeInstance);
5569
5569
  if (prefixSheet && !sheetName) return CellErrorType.InvalidReference;
5570
5570
  let rangeString = getRangePartString(range, 0, options);
5571
5571
  if (range.parts && range.parts.length === 2) {
5572
- if (range.zone.top !== range.zone.bottom || range.zone.left !== range.zone.right || range.parts[0].rowFixed || range.parts[0].colFixed || range.parts[1].rowFixed || range.parts[1].colFixed) {
5572
+ if (range.zone.top !== range.zone.bottom || range.zone.left !== range.zone.right || range.parts[0].rowFixed || range.parts[0].colFixed || range.parts[1].rowFixed || range.parts[1].colFixed || options.doNotSimplifyRange) {
5573
5573
  rangeString += ":";
5574
5574
  rangeString += getRangePartString(range, 1, options);
5575
5575
  }
@@ -6291,6 +6291,11 @@ stores.inject(MyMetaStore, storeInstance);
6291
6291
  const params = compileTokens(rangeTokenize(formula));
6292
6292
  return new CompiledFormula(sheetId, params.tokens, params.literalValues, params.symbols, params.dependencies.map((xc) => getters.getRangeFromSheetXC(sheetId, xc)), params.isBadExpression, params.normalizedFormula, params.execute);
6293
6293
  }
6294
+ areRangeShapesInLineWithNormalizedFormula() {
6295
+ return Array.from(this.normalizedFormula.matchAll(/\|C\||\|R\|/g)).every((value, index) => {
6296
+ return this.rangeDependencies[index].parts.length === 1 && value[0] === "|C|" || this.rangeDependencies[index].parts.length === 2 && value[0] === "|R|" || this.rangeDependencies[index].invalidXc || this.rangeDependencies[index].invalidSheetName;
6297
+ });
6298
+ }
6294
6299
  };
6295
6300
  function compileTokens(tokens) {
6296
6301
  try {
@@ -14142,7 +14147,7 @@ stores.inject(MyMetaStore, storeInstance);
14142
14147
  */
14143
14148
  function filterInvalidHierarchicalPoints(values, hierarchy) {
14144
14149
  const numberOfDataPoints = Math.max(values.length, ...hierarchy.map((dataset) => dataset.data?.length || 0));
14145
- const isEmpty = (value) => value === null || value === "";
14150
+ const isEmpty = (value) => value === void 0 || value === null || value === "";
14146
14151
  const dataPointsIndexes = range(0, numberOfDataPoints).filter((dataPointIndex) => {
14147
14152
  const groups = hierarchy.map((dataset) => dataset.data?.[dataPointIndex]);
14148
14153
  if (isEmpty(groups[0]?.value)) return false;
@@ -33916,7 +33921,7 @@ stores.inject(MyMetaStore, storeInstance);
33916
33921
  return !!this.state.keyValueDispatchResult?.isCancelledBecause("InvalidScorecardKeyValue");
33917
33922
  }
33918
33923
  get isBaselineInvalid() {
33919
- return !!this.state.keyValueDispatchResult?.isCancelledBecause("InvalidScorecardBaseline");
33924
+ return !!this.state.baselineDispatchResult?.isCancelledBecause("InvalidScorecardBaseline");
33920
33925
  }
33921
33926
  onKeyValueRangeChanged(ranges) {
33922
33927
  this.keyValue = ranges[0];
@@ -49719,6 +49724,7 @@ stores.inject(MyMetaStore, storeInstance);
49719
49724
  alreadyAppliedNumberOffsets = [];
49720
49725
  previousStrings = [];
49721
49726
  baseFormulaWasTransformed = false;
49727
+ rangeToStringOptions = { doNotSimplifyRange: true };
49722
49728
  baseNumber = void 0;
49723
49729
  constructor(getters) {
49724
49730
  this.getters = getters;
@@ -49774,9 +49780,9 @@ stores.inject(MyMetaStore, storeInstance);
49774
49780
  let references = [];
49775
49781
  if (!this.baseFormula || this.baseFormula.normalizedFormula !== cell.compiledFormula.normalizedFormula) {
49776
49782
  this.resetBaseTo(cell.compiledFormula);
49777
- return cell.compiledFormula.toFormulaString(this.getters);
49783
+ return cell.compiledFormula.toFormulaString(this.getters, this.rangeToStringOptions);
49778
49784
  } else {
49779
- if (!this.baseFormulaWasTransformed && deepEquals(cell.compiledFormula.literalValues, this.baseFormula.literalValues) && deepEquals(cell.compiledFormula.rangeDependencies, this.baseFormula.rangeDependencies)) return cell.compiledFormula.toFormulaString(this.getters);
49785
+ if (!this.baseFormulaWasTransformed && deepEquals(cell.compiledFormula.literalValues, this.baseFormula.literalValues) && deepEquals(cell.compiledFormula.rangeDependencies, this.baseFormula.rangeDependencies)) return cell.compiledFormula.toFormulaString(this.getters, this.rangeToStringOptions);
49780
49786
  numbers = this.squishNumbers(cell.compiledFormula.literalValues.numbers);
49781
49787
  strings = this.squishStrings(cell.compiledFormula.literalValues.strings);
49782
49788
  references = this.squishReferences(cell.compiledFormula.rangeDependencies, forSheetId);
@@ -49853,23 +49859,23 @@ stores.inject(MyMetaStore, storeInstance);
49853
49859
  squishOneReference(reference, previousReferences, index, forSheetId) {
49854
49860
  const previousReference = previousReferences[index];
49855
49861
  if (deepEquals(previousReference, reference)) return "=";
49856
- if (previousReference.sheetId !== reference.sheetId || previousReference.prefixSheet !== reference.prefixSheet || previousReference.invalidSheetName !== reference.invalidSheetName || previousReference.invalidXc !== reference.invalidXc) {
49862
+ if (previousReference.sheetId !== reference.sheetId || previousReference.prefixSheet !== reference.prefixSheet || previousReference.invalidSheetName !== reference.invalidSheetName || previousReference.invalidXc !== reference.invalidXc || previousReference.parts.length !== reference.parts.length) {
49857
49863
  previousReferences[index] = deepCopy(reference);
49858
- return getRangeString(reference, forSheetId, this.getters.getSheetName);
49864
+ return getRangeString(reference, forSheetId, this.getters.getSheetName, this.rangeToStringOptions);
49859
49865
  }
49860
49866
  if (previousReference.unboundedZone.bottom === void 0 || previousReference.unboundedZone.right === void 0 || reference.unboundedZone.bottom === void 0 || reference.unboundedZone.right === void 0) {
49861
49867
  previousReferences[index] = deepCopy(reference);
49862
- return getRangeString(reference, forSheetId, this.getters.getSheetName);
49868
+ return getRangeString(reference, forSheetId, this.getters.getSheetName, this.rangeToStringOptions);
49863
49869
  }
49864
49870
  for (let i = 0; i < reference.parts.length; i++) if (previousReference.parts[i].colFixed !== reference.parts[i].colFixed || previousReference.parts[i].rowFixed !== reference.parts[i].rowFixed) {
49865
49871
  previousReferences[index] = deepCopy(reference);
49866
- return getRangeString(reference, forSheetId, this.getters.getSheetName);
49872
+ return getRangeString(reference, forSheetId, this.getters.getSheetName, this.rangeToStringOptions);
49867
49873
  }
49868
49874
  const currentZone = reference.zone;
49869
49875
  const previousZone = previousReference.zone;
49870
49876
  if (currentZone.top !== currentZone.bottom || currentZone.left !== currentZone.right || previousZone.top !== previousZone.bottom || previousZone.left !== previousZone.right) {
49871
49877
  previousReferences[index] = deepCopy(reference);
49872
- return getRangeString(reference, forSheetId, this.getters.getSheetName);
49878
+ return getRangeString(reference, forSheetId, this.getters.getSheetName, this.rangeToStringOptions);
49873
49879
  }
49874
49880
  const diffCol = reference.zone.left - previousReference.zone.left;
49875
49881
  const diffRow = reference.zone.top - previousReference.zone.top;
@@ -49877,7 +49883,7 @@ stores.inject(MyMetaStore, storeInstance);
49877
49883
  previousReference.unboundedZone = deepCopy(reference.unboundedZone);
49878
49884
  if (diffCol !== 0 && diffRow === 0) return `${diffCol > 0 ? "+" : "-"}C${Math.abs(diffCol)}`;
49879
49885
  else if (diffRow !== 0 && diffCol === 0) return `${diffRow > 0 ? "+" : "-"}R${Math.abs(diffRow)}`;
49880
- return getRangeString(reference, forSheetId, this.getters.getSheetName);
49886
+ return getRangeString(reference, forSheetId, this.getters.getSheetName, this.rangeToStringOptions);
49881
49887
  }
49882
49888
  /**
49883
49889
  * Squish the number parameters. Result for each parameter should be compared the previous formula.
@@ -50086,10 +50092,19 @@ stores.inject(MyMetaStore, storeInstance);
50086
50092
  case "FIRST_OFFSET": {
50087
50093
  const currentOffset = current;
50088
50094
  this.previousOffset = currentOffset;
50089
- for (const position of targetPositions) yield {
50090
- position,
50091
- compiled: this.unsquishFormula(currentOffset, sheetId, getters)
50092
- };
50095
+ for (const position of targetPositions) {
50096
+ const result = this.unsquishFormula(currentOffset, sheetId, getters);
50097
+ if (!result.areRangeShapesInLineWithNormalizedFormula()) {
50098
+ const formulaString = result.toFormulaString(getters);
50099
+ yield {
50100
+ position,
50101
+ compiled: CompiledFormula.Compile(formulaString, sheetId, getters)
50102
+ };
50103
+ } else yield {
50104
+ position,
50105
+ compiled: result
50106
+ };
50107
+ }
50093
50108
  break;
50094
50109
  }
50095
50110
  case "COMBINE_OFFSET": {
@@ -50098,10 +50113,19 @@ stores.inject(MyMetaStore, storeInstance);
50098
50113
  this.previousOffset.N = currentOffset.N ?? this.previousOffset.N;
50099
50114
  this.previousOffset.S = currentOffset.S ?? this.previousOffset.S;
50100
50115
  this.previousOffset.R = currentOffset.R ?? this.previousOffset.R;
50101
- for (const position of targetPositions) yield {
50102
- position,
50103
- compiled: this.unsquishFormula(this.previousOffset, sheetId, getters)
50104
- };
50116
+ for (const position of targetPositions) {
50117
+ const result = this.unsquishFormula(this.previousOffset, sheetId, getters);
50118
+ if (!result.areRangeShapesInLineWithNormalizedFormula()) {
50119
+ const formulaString = result.toFormulaString(getters);
50120
+ yield {
50121
+ position,
50122
+ compiled: CompiledFormula.Compile(formulaString, sheetId, getters)
50123
+ };
50124
+ } else yield {
50125
+ position,
50126
+ compiled: result
50127
+ };
50128
+ }
50105
50129
  break;
50106
50130
  }
50107
50131
  case "NEW_NUMBER":
@@ -56943,13 +56967,13 @@ stores.inject(MyMetaStore, storeInstance);
56943
56967
  const minValue = this.parsePoint(sheetId, range, rule.minimum, "min");
56944
56968
  const midValue = rule.midpoint ? this.parsePoint(sheetId, range, rule.midpoint) : null;
56945
56969
  const maxValue = this.parsePoint(sheetId, range, rule.maximum, "max");
56946
- if (minValue === null || maxValue === null || minValue >= maxValue || midValue && (minValue >= midValue || midValue >= maxValue)) return;
56970
+ if (minValue === null || maxValue === null || minValue >= maxValue || midValue !== null && (minValue >= midValue || midValue >= maxValue)) return;
56947
56971
  const zone = this.getters.getRangeFromSheetXC(sheetId, range).zone;
56948
56972
  const colorThresholds = [{
56949
56973
  value: minValue,
56950
56974
  color: rule.minimum.color
56951
56975
  }];
56952
- if (rule.midpoint && midValue) colorThresholds.push({
56976
+ if (rule.midpoint && midValue !== null) colorThresholds.push({
56953
56977
  value: midValue,
56954
56978
  color: rule.midpoint.color
56955
56979
  });
@@ -57862,6 +57886,8 @@ stores.inject(MyMetaStore, storeInstance);
57862
57886
  pivots = {};
57863
57887
  unusedPivotsInFormulas;
57864
57888
  custom;
57889
+ pivotPositionCache = new PositionMap();
57890
+ shouldInvalidateCache = false;
57865
57891
  constructor(config) {
57866
57892
  super(config);
57867
57893
  this.custom = config.custom;
@@ -57872,7 +57898,11 @@ stores.inject(MyMetaStore, storeInstance);
57872
57898
  }
57873
57899
  }
57874
57900
  handle(cmd) {
57875
- if (invalidateEvaluationCommands.has(cmd.type)) for (const pivotId of this.getters.getPivotIds()) this.setupPivot(pivotId, { recreate: true });
57901
+ if (invalidateEvaluationCommands.has(cmd.type)) {
57902
+ this.shouldInvalidateCache = true;
57903
+ for (const pivotId of this.getters.getPivotIds()) this.setupPivot(pivotId, { recreate: true });
57904
+ }
57905
+ if (cmd.type === "UPDATE_CELL") this.shouldInvalidateCache = true;
57876
57906
  switch (cmd.type) {
57877
57907
  case "REFRESH_PIVOT":
57878
57908
  this.refreshPivot(cmd.id);
@@ -57912,6 +57942,12 @@ stores.inject(MyMetaStore, storeInstance);
57912
57942
  break;
57913
57943
  }
57914
57944
  }
57945
+ finalize() {
57946
+ if (this.shouldInvalidateCache) {
57947
+ this.pivotPositionCache = new PositionMap();
57948
+ this.shouldInvalidateCache = false;
57949
+ }
57950
+ }
57915
57951
  /**
57916
57952
  * Get the id of the first pivot in the formula at the given position. Returns undefined if there
57917
57953
  * is no pivot at this position
@@ -57923,9 +57959,14 @@ stores.inject(MyMetaStore, storeInstance);
57923
57959
  * Get all of the ids of the pivot present in the formula at the given position.
57924
57960
  */
57925
57961
  getPivotIdsFromPosition(position) {
57926
- const cell = this.getters.getCorrespondingFormulaCell(position);
57927
- if (cell && cell.isFormula) return this.getPivotIdsFromFormula(position.sheetId, cell.compiledFormula);
57928
- return [];
57962
+ if (!this.pivotPositionCache.has(position)) {
57963
+ const cell = this.getters.getCorrespondingFormulaCell(position);
57964
+ if (cell && cell.isFormula) {
57965
+ const pivotIds = this.getPivotIdsFromFormula(position.sheetId, cell.compiledFormula);
57966
+ this.pivotPositionCache.set(position, pivotIds);
57967
+ }
57968
+ }
57969
+ return this.pivotPositionCache.get(position) || [];
57929
57970
  }
57930
57971
  getPivotIdsFromFormula(sheetId, formula) {
57931
57972
  return this.getPivotFunctions(sheetId, formula).map((pivotFunction) => {
@@ -59680,7 +59721,12 @@ stores.inject(MyMetaStore, storeInstance);
59680
59721
  computeTableStyle(sheetId, table) {
59681
59722
  return lazy(() => {
59682
59723
  const style = this.getters.getTableStyle(table.config.styleId);
59683
- const { tableMetaData, config } = this.getTableMetaData(sheetId, table);
59724
+ const tableMetaDataAndConfig = this.getTableMetaData(sheetId, table);
59725
+ if (!tableMetaDataAndConfig) return {
59726
+ borders: {},
59727
+ styles: {}
59728
+ };
59729
+ const { tableMetaData, config } = tableMetaDataAndConfig;
59684
59730
  const relativeTableStyle = getComputedTableStyle(config, style, tableMetaData);
59685
59731
  const mapping = this.getTableMapping(sheetId, table);
59686
59732
  const absoluteTableStyle = {
@@ -59718,6 +59764,7 @@ stores.inject(MyMetaStore, storeInstance);
59718
59764
  const pivotInfo = this.getters.getPivotStyleAtPosition(mainPosition);
59719
59765
  if (!pivotInfo) throw new Error("No dynamic pivot info found at pivot table position");
59720
59766
  const pivot = this.getters.getPivot(pivotInfo.pivotId);
59767
+ if (!pivot.isValid()) return;
59721
59768
  const pivotStyle = pivotInfo.pivotStyle;
59722
59769
  const maxRowDepth = pivot.getExpandedTableStructure().getNumberOfRowGroupBys();
59723
59770
  const pivotTable = pivot.getCollapsedTableStructure();
@@ -64262,11 +64309,23 @@ stores.inject(MyMetaStore, storeInstance);
64262
64309
  ctx.strokeStyle = SELECTION_BORDER_COLOR;
64263
64310
  ctx.lineWidth = 1.5 * thinLineWidth;
64264
64311
  for (const zone of zones) {
64312
+ if (!viewports.isZoneVisibleInViewport(sheetId, zone)) continue;
64265
64313
  const { x, y, width, height } = viewports.getVisibleRect(sheetId, zone);
64266
64314
  ctx.globalCompositeOperation = "multiply";
64267
- ctx.fillRect(x, y, width, height);
64268
- ctx.globalCompositeOperation = "source-over";
64269
- ctx.strokeRect(x, y, width, height);
64315
+ const currentLineWidth = ctx.lineWidth;
64316
+ if (height === 0 || width === 0) ctx.lineWidth = 3 * thinLineWidth;
64317
+ if (height === 0 && width === 0) {
64318
+ ctx.beginPath();
64319
+ ctx.arc(x, y, 3, 0, 2 * Math.PI);
64320
+ ctx.fill();
64321
+ ctx.globalCompositeOperation = "source-over";
64322
+ ctx.stroke();
64323
+ } else {
64324
+ ctx.fillRect(x, y, width, height);
64325
+ ctx.globalCompositeOperation = "source-over";
64326
+ ctx.strokeRect(x, y, width, height);
64327
+ }
64328
+ ctx.lineWidth = currentLineWidth;
64270
64329
  }
64271
64330
  ctx.globalCompositeOperation = "source-over";
64272
64331
  const position = renderingContext.activePosition;
@@ -64413,6 +64472,9 @@ stores.inject(MyMetaStore, storeInstance);
64413
64472
  this.adjustViewportZoneX();
64414
64473
  this.adjustViewportZoneY();
64415
64474
  }
64475
+ isZoneVisible(zone) {
64476
+ return intersection(zone, this) !== void 0;
64477
+ }
64416
64478
  /**
64417
64479
  *
64418
64480
  * Computes the visible coordinates & dimensions of a given zone inside the viewport
@@ -64693,6 +64755,9 @@ stores.inject(MyMetaStore, storeInstance);
64693
64755
  isVisibleInViewport({ sheetId, col, row }) {
64694
64756
  return this.getSubViewports(sheetId).some((pane) => pane.isVisible(col, row));
64695
64757
  }
64758
+ isZoneVisibleInViewport(sheetId, zone) {
64759
+ return this.getSubViewports(sheetId).some((pane) => pane.isZoneVisible(zone));
64760
+ }
64696
64761
  getScrollBarWidth() {
64697
64762
  return 15 / this.zoomLevel;
64698
64763
  }
@@ -69224,18 +69289,28 @@ stores.inject(MyMetaStore, storeInstance);
69224
69289
  return;
69225
69290
  }
69226
69291
  const activeSheetId = this.env.model.getters.getActiveSheetId();
69227
- if (activeSheetId !== sheetId) this.env.model.dispatch("ACTIVATE_SHEET", {
69228
- sheetIdFrom: activeSheetId,
69229
- sheetIdTo: sheetId
69230
- });
69231
- this.env.model.selection.selectCell(zone.right, zone.bottom);
69292
+ if (activeSheetId !== sheetId) {
69293
+ if (!this.env.model.getters.getSheet(sheetId).isVisible) {
69294
+ this.env.notifyUser({
69295
+ text: _t("The sheet on which the range is defined is hidden."),
69296
+ type: "info",
69297
+ sticky: false
69298
+ });
69299
+ return;
69300
+ }
69301
+ this.env.model.dispatch("ACTIVATE_SHEET", {
69302
+ sheetIdFrom: activeSheetId,
69303
+ sheetIdTo: sheetId
69304
+ });
69305
+ }
69306
+ this.env.model.selection.selectCell(zone.right, zone.bottom, { allowsHiddenSelection: true });
69232
69307
  this.env.model.selection.selectZone({
69233
69308
  cell: {
69234
69309
  col: zone.left,
69235
69310
  row: zone.top
69236
69311
  },
69237
69312
  zone
69238
- });
69313
+ }, { allowsHiddenSelection: true });
69239
69314
  }
69240
69315
  get selectionKey() {
69241
69316
  return `${this.env.model.getters.getActiveSheetId()}-${zoneToXc(this.selectedZone)}`;
@@ -71644,7 +71719,7 @@ stores.inject(MyMetaStore, storeInstance);
71644
71719
  /**
71645
71720
  * Select a single cell as the new anchor.
71646
71721
  */
71647
- selectCell(col, row) {
71722
+ selectCell(col, row, options) {
71648
71723
  const zone = positionToZone({
71649
71724
  col,
71650
71725
  row
@@ -71655,7 +71730,10 @@ stores.inject(MyMetaStore, storeInstance);
71655
71730
  col,
71656
71731
  row
71657
71732
  }
71658
- }, { scrollIntoView: true });
71733
+ }, {
71734
+ scrollIntoView: true,
71735
+ ...options
71736
+ });
71659
71737
  }
71660
71738
  /**
71661
71739
  * Set the selection to one of the cells adjacent to the current anchor cell.
@@ -72010,15 +72088,21 @@ stores.inject(MyMetaStore, storeInstance);
72010
72088
  return DispatchResult.Success;
72011
72089
  }
72012
72090
  checkEventAnchorZone(event) {
72013
- return this.checkAnchorZone(event.anchor);
72091
+ return this.checkAnchorZone(event.anchor, event.options);
72014
72092
  }
72015
- checkAnchorZone(anchor) {
72093
+ checkAnchorZone(anchor, options) {
72016
72094
  const { cell, zone } = anchor;
72017
72095
  if (!isInside(cell.col, cell.row, zone)) return "InvalidAnchorZone";
72018
72096
  const { left, right, top, bottom } = zone;
72019
72097
  const sheetId = this.getters.getActiveSheetId();
72020
- const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
72021
- if (this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) === void 0 || refCol === void 0) return "SelectionOutOfBound";
72098
+ if (!options?.allowsHiddenSelection) {
72099
+ const refCol = this.getters.findVisibleHeader(sheetId, "COL", left, right);
72100
+ if (this.getters.findVisibleHeader(sheetId, "ROW", top, bottom) === void 0 || refCol === void 0) return "SelectionOutOfBound";
72101
+ } else {
72102
+ const numberCols = this.getters.getNumberCols(sheetId);
72103
+ const numberRows = this.getters.getNumberRows(sheetId);
72104
+ if (left < 0 || right > numberCols - 1 || top < 0 || bottom > numberRows - 1) return "SelectionOutOfBound";
72105
+ }
72022
72106
  return "Success";
72023
72107
  }
72024
72108
  checkAnchorZoneOrThrow(anchor) {
@@ -84389,7 +84473,8 @@ stores.inject(MyMetaStore, storeInstance);
84389
84473
  parseFormat,
84390
84474
  isFormula,
84391
84475
  domainToColRowDomain,
84392
- collapseHierarchicalDisplayName
84476
+ collapseHierarchicalDisplayName,
84477
+ PositionMap
84393
84478
  };
84394
84479
  const links = {
84395
84480
  isMarkdownLink,
@@ -84569,8 +84654,8 @@ exports.stores = stores;
84569
84654
  exports.tokenColors = tokenColors;
84570
84655
  exports.tokenize = tokenize;
84571
84656
 
84572
- __info__.version = "19.3.10";
84573
- __info__.date = "2026-07-01T05:04:42.999Z";
84574
- __info__.hash = "040ae04";
84657
+ __info__.version = "19.3.12";
84658
+ __info__.date = "2026-07-20T11:02:44.416Z";
84659
+ __info__.hash = "2b42707";
84575
84660
 
84576
84661
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);