@odoo/o-spreadsheet 16.4.8 → 16.4.10

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.
@@ -1194,7 +1194,17 @@
1194
1194
  function isDateTime(str, locale) {
1195
1195
  return parseDateTime(str, locale) !== null;
1196
1196
  }
1197
+ const CACHE = new Map();
1197
1198
  function parseDateTime(str, locale) {
1199
+ if (!CACHE.has(locale)) {
1200
+ CACHE.set(locale, new Map());
1201
+ }
1202
+ if (!CACHE.get(locale).has(str)) {
1203
+ CACHE.get(locale).set(str, _parseDateTime(str, locale));
1204
+ }
1205
+ return CACHE.get(locale).get(str);
1206
+ }
1207
+ function _parseDateTime(str, locale) {
1198
1208
  str = str.trim();
1199
1209
  let time = null;
1200
1210
  const timeMatch = str.match(timeRegexp);
@@ -3013,8 +3023,9 @@
3013
3023
  }
3014
3024
  get zone() {
3015
3025
  const { left, top, bottom, right } = this._zone;
3016
- if (right !== undefined && bottom !== undefined)
3017
- return { left, top, right, bottom };
3026
+ if (right !== undefined && bottom !== undefined) {
3027
+ return this._zone;
3028
+ }
3018
3029
  else if (bottom === undefined && right !== undefined) {
3019
3030
  return { right, top, left, bottom: this.getSheetSize(this.sheetId).numberOfRows - 1 };
3020
3031
  }
@@ -4284,7 +4295,7 @@
4284
4295
  const SORT_TYPES_ORDER = ["number", "string", "boolean", "undefined"];
4285
4296
  function assert(condition, message) {
4286
4297
  if (!condition()) {
4287
- throw new Error(message);
4298
+ throw new EvaluationError(CellErrorType.GenericError, message);
4288
4299
  }
4289
4300
  }
4290
4301
  // -----------------------------------------------------------------------------
@@ -4929,7 +4940,7 @@
4929
4940
  return textCell((value || "").toString(), localeFormat);
4930
4941
  }
4931
4942
  catch (error) {
4932
- return errorCell((value || "").toString(), new EvaluationError(CellErrorType.GenericError, error.message || DEFAULT_ERROR_MESSAGE));
4943
+ return errorCell(new EvaluationError(CellErrorType.GenericError, error.message || DEFAULT_ERROR_MESSAGE));
4933
4944
  }
4934
4945
  }
4935
4946
  function textCell(value, localeFormat) {
@@ -4996,7 +5007,7 @@
4996
5007
  formattedValue,
4997
5008
  };
4998
5009
  }
4999
- function errorCell(content, error) {
5010
+ function errorCell(error) {
5000
5011
  return {
5001
5012
  type: CellValueType.error,
5002
5013
  value: error.errorType,
@@ -13033,6 +13044,35 @@
13033
13044
  isExported: true,
13034
13045
  };
13035
13046
  // -----------------------------------------------------------------------------
13047
+ // INDEX
13048
+ // -----------------------------------------------------------------------------
13049
+ const INDEX = {
13050
+ description: _lt(`Returns the content of a cell, specified by row and column offset.`),
13051
+ args: [
13052
+ arg("reference (any, range)", _lt("The range of cells from which the values are returned.")),
13053
+ arg("row (number)", _lt("The index of the row to be returned from within the reference range of cells.")),
13054
+ arg("column (number)", _lt("The index of the column to be returned from within the reference range of cells.")),
13055
+ ],
13056
+ returns: ["ANY"],
13057
+ computeFormat: function (reference, row, column) {
13058
+ const _row = toNumber(row.value, this.locale);
13059
+ const _column = toNumber(column.value, this.locale);
13060
+ return reference.format[_column - 1][_row - 1];
13061
+ },
13062
+ compute: function (reference, row, column) {
13063
+ const _reference = isMatrix(reference) ? reference : [[reference]];
13064
+ const _row = toNumber(row, this.locale);
13065
+ const _column = toNumber(column, this.locale);
13066
+ assert(() => _column >= 0 &&
13067
+ _column - 1 < _reference.length &&
13068
+ _row >= 0 &&
13069
+ _row - 1 < _reference[0].length, _lt("Index out of range."));
13070
+ assert(() => row !== 0 && column !== 0, _lt("This function can only return a single cell value, not an array. Provide valid row and column indices."));
13071
+ return _reference[_column - 1][_row - 1];
13072
+ },
13073
+ isExported: true,
13074
+ };
13075
+ // -----------------------------------------------------------------------------
13036
13076
  // LOOKUP
13037
13077
  // -----------------------------------------------------------------------------
13038
13078
  const LOOKUP = {
@@ -13230,6 +13270,7 @@
13230
13270
  COLUMN: COLUMN,
13231
13271
  COLUMNS: COLUMNS,
13232
13272
  HLOOKUP: HLOOKUP,
13273
+ INDEX: INDEX,
13233
13274
  LOOKUP: LOOKUP,
13234
13275
  MATCH: MATCH,
13235
13276
  ROW: ROW,
@@ -21801,7 +21842,7 @@
21801
21842
  });
21802
21843
  }
21803
21844
  canUpdateChart(figureId, updateDefinition) {
21804
- if (figureId !== this.figureId) {
21845
+ if (figureId !== this.figureId || !this.env.model.getters.isChartDefined(figureId)) {
21805
21846
  return;
21806
21847
  }
21807
21848
  const definition = {
@@ -25669,7 +25710,14 @@
25669
25710
  return;
25670
25711
  }
25671
25712
  if (this.state.waitingForMove === true) {
25672
- this.startMovement(ev);
25713
+ if (!this.env.model.getters.isGridSelectionActive()) {
25714
+ this._selectElement(index, false);
25715
+ }
25716
+ else {
25717
+ // FIXME: Consider reintroducing this feature for all type of selection if we find
25718
+ // a way to have the grid selection follow the other selections evolution
25719
+ this.startMovement(ev);
25720
+ }
25673
25721
  return;
25674
25722
  }
25675
25723
  if (this.env.model.getters.getEditionMode() === "editing") {
@@ -29095,12 +29143,15 @@
29095
29143
  };
29096
29144
  }
29097
29145
  function xmlEscape(str) {
29098
- return String(str)
29146
+ return (String(str)
29099
29147
  .replace(/\&/g, "&amp;")
29100
29148
  .replace(/\</g, "&lt;")
29101
29149
  .replace(/\>/g, "&gt;")
29102
29150
  .replace(/\"/g, "&quot;")
29103
- .replace(/\'/g, "&apos;");
29151
+ .replace(/\'/g, "&apos;")
29152
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
29153
+ // They are not valid at all in XML 1.0 (even escaped)
29154
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
29104
29155
  }
29105
29156
  function formatAttributes(attrs) {
29106
29157
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -31818,10 +31869,11 @@
31818
31869
  * Reconstructs the original formula string based on a normalized form and its dependencies
31819
31870
  */
31820
31871
  buildFormulaContent(sheetId, cell, dependencies) {
31821
- const ranges = dependencies || [...cell.dependencies];
31872
+ const ranges = dependencies || cell.dependencies;
31873
+ let rangeIndex = 0;
31822
31874
  return concat(cell.compiledFormula.tokens.map((token) => {
31823
31875
  if (token.type === "REFERENCE") {
31824
- const range = ranges.shift();
31876
+ const range = ranges[rangeIndex++];
31825
31877
  return this.getters.getRangeString(range, sheetId);
31826
31878
  }
31827
31879
  return token.value;
@@ -35429,7 +35481,7 @@
35429
35481
  const evaluatedCell = this.getEvaluatedCell(position);
35430
35482
  if (evaluatedCell.type === CellValueType.empty) {
35431
35483
  const cell = this.getters.getCell(position);
35432
- if (!cell || cell.content === "") {
35484
+ if (!cell || (!cell.isFormula && cell.content === "")) {
35433
35485
  return undefined;
35434
35486
  }
35435
35487
  }
@@ -35649,7 +35701,7 @@
35649
35701
  constructor(context, getters) {
35650
35702
  this.context = context;
35651
35703
  this.getters = getters;
35652
- this.compilationParams = buildCompilationParameters(context, getters, (position) => this.computeCell(this.encodePosition(position)));
35704
+ this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
35653
35705
  }
35654
35706
  getEvaluatedCell(position) {
35655
35707
  return (this.evaluatedCells.get(this.encodePosition(position)) ||
@@ -35677,7 +35729,7 @@
35677
35729
  this.formulaDependencies().addDependencies(positionId, dependencies);
35678
35730
  }
35679
35731
  updateCompilationParameters() {
35680
- this.compilationParams = buildCompilationParameters(this.context, this.getters, (position) => this.computeCell(this.encodePosition(position)));
35732
+ this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
35681
35733
  }
35682
35734
  evaluateCells(positions) {
35683
35735
  const cells = positions.map(this.encodePosition.bind(this));
@@ -35793,15 +35845,21 @@
35793
35845
  this.cellsBeingComputed.delete(cellId);
35794
35846
  }
35795
35847
  }
35848
+ computeAndSave(position) {
35849
+ const positionId = this.encodePosition(position);
35850
+ const evaluatedCell = this.computeCell(positionId);
35851
+ if (!this.evaluatedCells.has(positionId)) {
35852
+ this.setEvaluatedCell(positionId, evaluatedCell);
35853
+ }
35854
+ return evaluatedCell;
35855
+ }
35796
35856
  handleError(e, cell) {
35797
- if (!(e instanceof Error)) {
35798
- e = new Error(e);
35857
+ if (!(e instanceof EvaluationError)) {
35858
+ e = new EvaluationError(CellErrorType.GenericError, e.message);
35799
35859
  }
35800
- const msg = e?.errorType || CellErrorType.GenericError;
35801
- // apply function name
35802
35860
  const __lastFnCalled = this.compilationParams[2].__lastFnCalled || "";
35803
- const error = new EvaluationError(msg, e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled), e.logLevel !== undefined ? e.logLevel : CellErrorLevel.error);
35804
- return errorCell(cell.content, error);
35861
+ e.message = e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled);
35862
+ return errorCell(e);
35805
35863
  }
35806
35864
  computeFormulaCell(cellData) {
35807
35865
  const cellId = cellData.id;
@@ -41693,6 +41751,10 @@
41693
41751
  if (!newRangesXC) {
41694
41752
  return;
41695
41753
  }
41754
+ if (newRangesXC.length === 0) {
41755
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
41756
+ return;
41757
+ }
41696
41758
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
41697
41759
  cf: {
41698
41760
  id: cf.id,
@@ -43198,6 +43260,7 @@
43198
43260
  "isSingleColSelected",
43199
43261
  "getElementsFromSelection",
43200
43262
  "tryGetActiveSheetId",
43263
+ "isGridSelectionActive",
43201
43264
  ];
43202
43265
  gridSelection = {
43203
43266
  anchor: {
@@ -43407,6 +43470,9 @@
43407
43470
  // ---------------------------------------------------------------------------
43408
43471
  // Getters
43409
43472
  // ---------------------------------------------------------------------------
43473
+ isGridSelectionActive() {
43474
+ return this.selection.isListening(this);
43475
+ }
43410
43476
  getActiveSheet() {
43411
43477
  return this.activeSheet;
43412
43478
  }
@@ -48222,6 +48288,9 @@
48222
48288
  },
48223
48289
  });
48224
48290
  }
48291
+ isListening(owner) {
48292
+ return this.stream.isListening(owner);
48293
+ }
48225
48294
  /**
48226
48295
  * Process a new anchor selection event. If the new anchor is inside
48227
48296
  * the sheet boundaries, the event is pushed to the event stream to
@@ -50692,9 +50761,9 @@
50692
50761
  Object.defineProperty(exports, '__esModule', { value: true });
50693
50762
 
50694
50763
 
50695
- __info__.version = '16.4.8';
50696
- __info__.date = '2023-10-03T12:45:33.807Z';
50697
- __info__.hash = 'c614d64';
50764
+ __info__.version = '16.4.10';
50765
+ __info__.date = '2023-10-19T14:23:58.054Z';
50766
+ __info__.hash = 'bc7546f';
50698
50767
 
50699
50768
 
50700
50769
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);