@odoo/o-spreadsheet 16.1.27 → 16.1.31

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.
@@ -306,15 +306,76 @@
306
306
  // -----------------------------------------------------------------------------
307
307
  // Date Type
308
308
  // -----------------------------------------------------------------------------
309
+ /**
310
+ * A DateTime object that can be used to manipulate spreadsheet dates.
311
+ * Conceptually, a spreadsheet date is simply a number with a date format,
312
+ * and it is timezone-agnostic.
313
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
314
+ */
315
+ class DateTime {
316
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
317
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
318
+ }
319
+ static fromTimestamp(timestamp) {
320
+ const date = new Date(timestamp);
321
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
322
+ }
323
+ static now() {
324
+ const now = new Date();
325
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
326
+ }
327
+ toString() {
328
+ return this.jsDate.toString();
329
+ }
330
+ getTime() {
331
+ return this.jsDate.getTime();
332
+ }
333
+ getFullYear() {
334
+ return this.jsDate.getUTCFullYear();
335
+ }
336
+ getMonth() {
337
+ return this.jsDate.getUTCMonth();
338
+ }
339
+ getDate() {
340
+ return this.jsDate.getUTCDate();
341
+ }
342
+ getDay() {
343
+ return this.jsDate.getUTCDay();
344
+ }
345
+ getHours() {
346
+ return this.jsDate.getUTCHours();
347
+ }
348
+ getMinutes() {
349
+ return this.jsDate.getUTCMinutes();
350
+ }
351
+ getSeconds() {
352
+ return this.jsDate.getUTCSeconds();
353
+ }
354
+ setFullYear(year) {
355
+ this.jsDate.setFullYear(year);
356
+ }
357
+ setDate(date) {
358
+ this.jsDate.setUTCDate(date);
359
+ }
360
+ setHours(hours) {
361
+ this.jsDate.setUTCHours(hours);
362
+ }
363
+ setMinutes(minutes) {
364
+ this.jsDate.setUTCMinutes(minutes);
365
+ }
366
+ setSeconds(seconds) {
367
+ this.jsDate.setUTCSeconds(seconds);
368
+ }
369
+ }
309
370
  // -----------------------------------------------------------------------------
310
371
  // Parsing
311
372
  // -----------------------------------------------------------------------------
312
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
373
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
313
374
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
314
375
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
315
- const CURRENT_YEAR = new Date().getFullYear();
316
- const INITIAL_JS_DAY = new Date(0);
317
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
376
+ const CURRENT_YEAR = DateTime.now().getFullYear();
377
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
378
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
318
379
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
319
380
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
320
381
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -363,7 +424,7 @@
363
424
  return {
364
425
  value: date.value + time.value,
365
426
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
366
- jsDate: new Date(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
427
+ jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
367
428
  };
368
429
  }
369
430
  return date || time;
@@ -380,13 +441,13 @@
380
441
  const day = Number(parts[dayIndex]);
381
442
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
382
443
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
383
- const jsDate = new Date(year, month - 1, day);
444
+ const jsDate = new DateTime(year, month - 1, day);
384
445
  const sep = str.match(/\/|-|\s/)[0];
385
446
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
386
447
  // invalid date
387
448
  return null;
388
449
  }
389
- const delta = jsDate - INITIAL_1900_DAY;
450
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
390
451
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
391
452
  if (parts[yearIndex]) {
392
453
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -446,7 +507,7 @@
446
507
  if (hours >= 24) {
447
508
  format = "hhhh:mm:ss";
448
509
  }
449
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
510
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
450
511
  return {
451
512
  value: hours / 24 + minutes / 1440 + seconds / 86400,
452
513
  format: format,
@@ -460,7 +521,7 @@
460
521
  // -----------------------------------------------------------------------------
461
522
  function numberToJsDate(value) {
462
523
  const truncValue = Math.trunc(value);
463
- let date = new Date(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
524
+ let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
464
525
  let time = value - truncValue;
465
526
  time = time < 0 ? 1 + time : time;
466
527
  const hours = Math.round(time * 24);
@@ -477,7 +538,7 @@
477
538
  }
478
539
  /** Return the number of days in the current month of the given date */
479
540
  function getDaysInMonth(date) {
480
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
541
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
481
542
  }
482
543
  function isLastDayOfMonth(date) {
483
544
  return getDaysInMonth(date) === date.getDate();
@@ -495,7 +556,7 @@
495
556
  const yStart = date.getFullYear();
496
557
  const mStart = date.getMonth();
497
558
  const dStart = date.getDate();
498
- const jsDate = new Date(yStart, mStart + months);
559
+ const jsDate = new DateTime(yStart, mStart + months, 1);
499
560
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
500
561
  jsDate.setDate(getDaysInMonth(jsDate));
501
562
  }
@@ -623,13 +684,6 @@
623
684
  }
624
685
 
625
686
  //------------------------------------------------------------------------------
626
- /**
627
- * Stringify an object, like JSON.stringify, except that the first level of keys
628
- * is ordered.
629
- */
630
- function stringify(obj) {
631
- return JSON.stringify(obj, Object.keys(obj).sort());
632
- }
633
687
  /**
634
688
  * Remove quotes from a quoted string
635
689
  * ```js
@@ -925,7 +979,7 @@
925
979
  */
926
980
  function getItemId(item, itemsDic) {
927
981
  for (let [key, value] of Object.entries(itemsDic)) {
928
- if (stringify(value) === stringify(item)) {
982
+ if (deepEquals(value, item)) {
929
983
  return parseInt(key, 10);
930
984
  }
931
985
  }
@@ -1061,6 +1115,22 @@
1061
1115
  if (!matrix.length)
1062
1116
  return matrix;
1063
1117
  return matrix[0].map((_, i) => matrix.map((row) => row[i]));
1118
+ }
1119
+ /**
1120
+ * Creates a version of the function that's memoized on the value of its first
1121
+ * argument, if any.
1122
+ */
1123
+ function memoize(func) {
1124
+ const cache = new Map();
1125
+ const funcName = func.name ? func.name + " (memoized)" : "memoized";
1126
+ return {
1127
+ [funcName](...args) {
1128
+ if (!cache.has(args[0])) {
1129
+ cache.set(args[0], func(...args));
1130
+ }
1131
+ return cache.get(args[0]);
1132
+ },
1133
+ }[funcName];
1064
1134
  }
1065
1135
 
1066
1136
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
@@ -1335,8 +1405,10 @@
1335
1405
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
1336
1406
  // Same as above, but matches the exact string (nothing before or after)
1337
1407
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
1338
- /** Reference of a column header (eg. A, AB) */
1339
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
1408
+ /** Reference of a column header (eg. A, AB, $A) */
1409
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
1410
+ /** Reference of a row header (eg. 1, $1) */
1411
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
1340
1412
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
1341
1413
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
1342
1414
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -1366,6 +1438,9 @@
1366
1438
  function isColHeader(str) {
1367
1439
  return colHeader.test(str);
1368
1440
  }
1441
+ function isRowHeader(str) {
1442
+ return rowHeader.test(str);
1443
+ }
1369
1444
  /**
1370
1445
  * Return true if the given xc is the reference of a single cell,
1371
1446
  * without any specified sheet (e.g. A1)
@@ -1864,7 +1939,7 @@
1864
1939
  .map((p) => {
1865
1940
  switch (p) {
1866
1941
  case "hhhh":
1867
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
1942
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
1868
1943
  return helapsedHours.toString();
1869
1944
  case "hh":
1870
1945
  return hours.toString().padStart(2, "0");
@@ -2155,18 +2230,10 @@
2155
2230
  if (isFullCol) {
2156
2231
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2157
2232
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2158
- if (zone.left === zone.right) {
2159
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2160
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2161
- }
2162
2233
  }
2163
2234
  if (isFullRow) {
2164
2235
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2165
2236
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2166
- if (zone.top === zone.bottom) {
2167
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2168
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2169
- }
2170
2237
  }
2171
2238
  return parts;
2172
2239
  }
@@ -3657,6 +3724,7 @@
3657
3724
  CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
3658
3725
  CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
3659
3726
  CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
3727
+ CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
3660
3728
  })(exports.CommandResult || (exports.CommandResult = {}));
3661
3729
 
3662
3730
  function isMatrix(x) {
@@ -5692,6 +5760,7 @@
5692
5760
  return node.description ? node.description : "";
5693
5761
  }
5694
5762
 
5763
+ const macRegex = /Mac/i;
5695
5764
  /**
5696
5765
  * Return true if the event was triggered from
5697
5766
  * a child element.
@@ -5709,6 +5778,17 @@
5709
5778
  }
5710
5779
  function getOpenedMenus() {
5711
5780
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5781
+ }
5782
+ function isMacOS() {
5783
+ return Boolean(macRegex.test(navigator.userAgent));
5784
+ }
5785
+ /**
5786
+ * @param {KeyboardEvent | MouseEvent} ev
5787
+ * @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
5788
+ * On Mac, this is the "meta" or "command" key.
5789
+ */
5790
+ function isCtrlKey(ev) {
5791
+ return isMacOS() ? ev.metaKey : ev.ctrlKey;
5712
5792
  }
5713
5793
 
5714
5794
  /**
@@ -8020,12 +8100,12 @@
8020
8100
  }
8021
8101
  }
8022
8102
  /** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
8023
- function normalizeString(str) {
8103
+ const normalizeString = memoize(function normalizeString(str) {
8024
8104
  return str
8025
8105
  .toLowerCase()
8026
8106
  .normalize("NFD")
8027
8107
  .replace(/[\u0300-\u036f]/g, "");
8028
- }
8108
+ });
8029
8109
  /**
8030
8110
  * Normalize a value.
8031
8111
  * If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
@@ -10869,7 +10949,7 @@
10869
10949
  if (_year < 1900) {
10870
10950
  _year += 1900;
10871
10951
  }
10872
- const jsDate = new Date(_year, _month - 1, _day);
10952
+ const jsDate = new DateTime(_year, _month - 1, _day);
10873
10953
  const result = jsDateToRoundNumber(jsDate);
10874
10954
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
10875
10955
  return result;
@@ -10981,7 +11061,7 @@
10981
11061
  const _months = Math.trunc(toNumber(months));
10982
11062
  const yStart = _startDate.getFullYear();
10983
11063
  const mStart = _startDate.getMonth();
10984
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
11064
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
10985
11065
  return jsDateToRoundNumber(jsDate);
10986
11066
  },
10987
11067
  isExported: true,
@@ -11020,17 +11100,17 @@
11020
11100
  // The first week of the year is the week that contains the first
11021
11101
  // Thursday of the year.
11022
11102
  let firstThursday = 1;
11023
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
11103
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
11024
11104
  firstThursday += 1;
11025
11105
  }
11026
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
11106
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
11027
11107
  // The last week of the year is the week that contains the last Thursday of
11028
11108
  // the year.
11029
11109
  let lastThursday = 31;
11030
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
11110
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
11031
11111
  lastThursday -= 1;
11032
11112
  }
11033
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
11113
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
11034
11114
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
11035
11115
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
11036
11116
  let offsetYear;
@@ -11056,17 +11136,17 @@
11056
11136
  case 1:
11057
11137
  // firstDay is the 1st day of the 1st week of the year after
11058
11138
  // firstDay = lastDayOfLastWeek + 1 Day
11059
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
11139
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
11060
11140
  break;
11061
11141
  case -1:
11062
11142
  // firstDay is the 1st day of the 1st week of the previous year.
11063
11143
  // The first week of the previous year is the week that contains the
11064
11144
  // first Thursday of the previous year.
11065
11145
  let firstThursdayPreviousYear = 1;
11066
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
11146
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
11067
11147
  firstThursdayPreviousYear += 1;
11068
11148
  }
11069
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
11149
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
11070
11150
  break;
11071
11151
  }
11072
11152
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -11205,8 +11285,8 @@
11205
11285
  });
11206
11286
  }
11207
11287
  const invertDate = _startDate.getTime() > _endDate.getTime();
11208
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
11209
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
11288
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
11289
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
11210
11290
  const timeStopDate = stopDate.getTime();
11211
11291
  let timeStepDate = stepDate.getTime();
11212
11292
  let netWorkingDay = 0;
@@ -11230,8 +11310,7 @@
11230
11310
  returns: ["DATE"],
11231
11311
  computeFormat: () => "m/d/yyyy hh:mm:ss",
11232
11312
  compute: function () {
11233
- let today = new Date();
11234
- today.setMilliseconds(0);
11313
+ let today = DateTime.now();
11235
11314
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
11236
11315
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
11237
11316
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -11305,8 +11384,8 @@
11305
11384
  returns: ["DATE"],
11306
11385
  computeFormat: () => "m/d/yyyy",
11307
11386
  compute: function () {
11308
- const today = new Date();
11309
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
11387
+ const today = DateTime.now();
11388
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
11310
11389
  return jsDateToRoundNumber(jsDate);
11311
11390
  },
11312
11391
  isExported: true,
@@ -11361,10 +11440,10 @@
11361
11440
  }
11362
11441
  const y = _date.getFullYear();
11363
11442
  let dayStart = 1;
11364
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
11443
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
11365
11444
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
11366
11445
  dayStart += 1;
11367
- startDayOfFirstWeek = new Date(y, 0, dayStart);
11446
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
11368
11447
  }
11369
11448
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
11370
11449
  if (dif < 0) {
@@ -11418,7 +11497,7 @@
11418
11497
  timesHoliday.add(holiday.getTime());
11419
11498
  });
11420
11499
  }
11421
- let stepDate = new Date(_startDate.getTime());
11500
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
11422
11501
  let timeStepDate = stepDate.getTime();
11423
11502
  const unitDay = Math.sign(_numDays);
11424
11503
  let stepDay = Math.abs(_numDays);
@@ -11484,7 +11563,7 @@
11484
11563
  const _startDate = toJsDate(date);
11485
11564
  const yStart = _startDate.getFullYear();
11486
11565
  const mStart = _startDate.getMonth();
11487
- const jsDate = new Date(yStart, mStart, 1);
11566
+ const jsDate = new DateTime(yStart, mStart, 1);
11488
11567
  return jsDateToRoundNumber(jsDate);
11489
11568
  },
11490
11569
  };
@@ -11528,7 +11607,7 @@
11528
11607
  compute: function (date) {
11529
11608
  const quarter = QUARTER.compute(date);
11530
11609
  const year = YEAR.compute(date);
11531
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
11610
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
11532
11611
  return jsDateToRoundNumber(jsDate);
11533
11612
  },
11534
11613
  };
@@ -11545,7 +11624,7 @@
11545
11624
  compute: function (date) {
11546
11625
  const quarter = QUARTER.compute(date);
11547
11626
  const year = YEAR.compute(date);
11548
- const jsDate = new Date(year, quarter * 3, 0);
11627
+ const jsDate = new DateTime(year, quarter * 3, 0);
11549
11628
  return jsDateToRoundNumber(jsDate);
11550
11629
  },
11551
11630
  };
@@ -11561,7 +11640,7 @@
11561
11640
  computeFormat: () => "m/d/yyyy",
11562
11641
  compute: function (date) {
11563
11642
  const year = YEAR.compute(date);
11564
- const jsDate = new Date(year, 0, 1);
11643
+ const jsDate = new DateTime(year, 0, 1);
11565
11644
  return jsDateToRoundNumber(jsDate);
11566
11645
  },
11567
11646
  };
@@ -11577,7 +11656,7 @@
11577
11656
  computeFormat: () => "m/d/yyyy",
11578
11657
  compute: function (date) {
11579
11658
  const year = YEAR.compute(date);
11580
- const jsDate = new Date(year + 1, 0, 0);
11659
+ const jsDate = new DateTime(year + 1, 0, 0);
11581
11660
  return jsDateToRoundNumber(jsDate);
11582
11661
  },
11583
11662
  };
@@ -11711,7 +11790,7 @@
11711
11790
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
11712
11791
  const startDate = toJsDate(settlement);
11713
11792
  const endDate = toJsDate(maturity);
11714
- const startDatePlusOneYear = new Date(startDate);
11793
+ const startDatePlusOneYear = toJsDate(settlement);
11715
11794
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
11716
11795
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
11717
11796
  }
@@ -15637,7 +15716,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
15637
15716
  SPACE: goTo(State.RightRef),
15638
15717
  NUMBER: goTo(State.Found),
15639
15718
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
15640
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
15719
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
15641
15720
  },
15642
15721
  [State.RightColumnRef]: {
15643
15722
  SPACE: goTo(State.RightColumnRef),
@@ -15648,6 +15727,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
15648
15727
  SPACE: goTo(State.RightRowRef),
15649
15728
  NUMBER: goTo(State.Found),
15650
15729
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
15730
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
15651
15731
  },
15652
15732
  [State.Found]: {},
15653
15733
  };
@@ -16157,6 +16237,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
16157
16237
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
16158
16238
  case "colrow":
16159
16239
  indexOfNumber = xc.search(/[0-9]/);
16240
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
16241
+ // no row number (eg. A) or no column (eg. 1)
16242
+ return "$" + xc;
16243
+ }
16160
16244
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
16161
16245
  return "$" + xc;
16162
16246
  case "none":
@@ -16930,10 +17014,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
16930
17014
  function updateSelectionWithArrowKeys(ev, selection) {
16931
17015
  const direction = arrowMap[ev.key];
16932
17016
  if (ev.shiftKey) {
16933
- selection.resizeAnchorZone(direction, ev.ctrlKey ? "end" : 1);
17017
+ selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
16934
17018
  }
16935
17019
  else {
16936
- selection.moveAnchorCell(direction, ev.ctrlKey ? "end" : 1);
17020
+ selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
16937
17021
  }
16938
17022
  }
16939
17023
 
@@ -22590,7 +22674,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22590
22674
  return;
22591
22675
  }
22592
22676
  const [col, row] = this.getCartesianCoordinates(ev);
22593
- this.props.onCellClicked(col, row, { shiftKey: ev.shiftKey, ctrlKey: ev.ctrlKey });
22677
+ this.props.onCellClicked(col, row, {
22678
+ expandZone: ev.shiftKey,
22679
+ addZone: isCtrlKey(ev),
22680
+ });
22594
22681
  }
22595
22682
  onDoubleClick(ev) {
22596
22683
  const [col, row] = this.getCartesianCoordinates(ev);
@@ -22678,6 +22765,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22678
22765
  draggerShadowThickness: 0,
22679
22766
  delta: 0,
22680
22767
  base: 0,
22768
+ position: "before",
22681
22769
  });
22682
22770
  }
22683
22771
  _computeHandleDisplay(ev) {
@@ -22803,11 +22891,13 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22803
22891
  this.state.draggerLinePosition = dimensions.start;
22804
22892
  this.state.draggerShadowPosition = dimensions.start;
22805
22893
  this.state.base = elementIndex;
22894
+ this.state.position = "before";
22806
22895
  }
22807
22896
  else if (this._getSelectedZoneEnd() < elementIndex) {
22808
22897
  this.state.draggerLinePosition = dimensions.end;
22809
22898
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
22810
- this.state.base = elementIndex + 1;
22899
+ this.state.base = elementIndex;
22900
+ this.state.position = "after";
22811
22901
  }
22812
22902
  else {
22813
22903
  this.state.draggerLinePosition = startDimensions.start;
@@ -22831,7 +22921,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22831
22921
  this._increaseSelection(index);
22832
22922
  }
22833
22923
  else {
22834
- this._selectElement(index, ev.ctrlKey);
22924
+ this._selectElement(index, isCtrlKey(ev));
22835
22925
  }
22836
22926
  this.lastSelectedElementIndex = index;
22837
22927
  const mouseMoveSelect = (col, row) => {
@@ -22844,7 +22934,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22844
22934
  const mouseUpSelect = () => {
22845
22935
  this.state.isSelecting = false;
22846
22936
  this.lastSelectedElementIndex = null;
22847
- this.env.model.dispatch(ev.ctrlKey ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
22937
+ this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
22848
22938
  this._computeGrabDisplay(ev);
22849
22939
  };
22850
22940
  dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
@@ -22988,13 +23078,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
22988
23078
  dimension: "COL",
22989
23079
  base: this.state.base,
22990
23080
  elements,
23081
+ position: this.state.position,
22991
23082
  });
22992
23083
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
22993
23084
  this.env.raiseError(MergeErrorMessage);
22994
23085
  }
22995
23086
  }
22996
- _selectElement(index, ctrlKey) {
22997
- this.env.model.selection.selectColumn(index, ctrlKey ? "newAnchor" : "overrideSelection");
23087
+ _selectElement(index, addDistinctHeader) {
23088
+ this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
22998
23089
  }
22999
23090
  _increaseSelection(index) {
23000
23091
  this.env.model.selection.selectColumn(index, "updateAnchor");
@@ -23160,13 +23251,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23160
23251
  dimension: "ROW",
23161
23252
  base: this.state.base,
23162
23253
  elements,
23254
+ position: this.state.position,
23163
23255
  });
23164
23256
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
23165
23257
  this.env.raiseError(MergeErrorMessage);
23166
23258
  }
23167
23259
  }
23168
- _selectElement(index, ctrlKey) {
23169
- this.env.model.selection.selectRow(index, ctrlKey ? "newAnchor" : "overrideSelection");
23260
+ _selectElement(index, addDistinctHeader) {
23261
+ this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
23170
23262
  }
23171
23263
  _increaseSelection(index) {
23172
23264
  this.env.model.selection.selectRow(index, "updateAnchor");
@@ -23268,8 +23360,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23268
23360
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
23269
23361
  }
23270
23362
  const onMouseWheel = (ev) => {
23271
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
23272
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
23363
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
23364
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
23273
23365
  handler(deltaX, deltaY);
23274
23366
  };
23275
23367
  return onMouseWheel;
@@ -23913,8 +24005,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23913
24005
  // ---------------------------------------------------------------------------
23914
24006
  // Zone selection with mouse
23915
24007
  // ---------------------------------------------------------------------------
23916
- onCellClicked(col, row, { ctrlKey, shiftKey }) {
23917
- if (ctrlKey) {
24008
+ onCellClicked(col, row, { addZone, expandZone }) {
24009
+ if (addZone) {
23918
24010
  this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
23919
24011
  }
23920
24012
  if (this.env.model.getters.hasOpenedPopover()) {
@@ -23923,10 +24015,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23923
24015
  if (this.env.model.getters.getEditionMode() === "editing") {
23924
24016
  this.env.model.dispatch("STOP_EDITION");
23925
24017
  }
23926
- if (shiftKey) {
24018
+ if (expandZone) {
23927
24019
  this.env.model.selection.setAnchorCorner(col, row);
23928
24020
  }
23929
- else if (ctrlKey) {
24021
+ else if (addZone) {
23930
24022
  this.env.model.selection.addCellToSelection(col, row);
23931
24023
  }
23932
24024
  else {
@@ -23988,9 +24080,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23988
24080
  return;
23989
24081
  }
23990
24082
  let keyDownString = "";
23991
- if (ev.ctrlKey)
23992
- keyDownString += "CTRL+";
23993
- if (ev.metaKey)
24083
+ if (isCtrlKey(ev))
23994
24084
  keyDownString += "CTRL+";
23995
24085
  if (ev.altKey)
23996
24086
  keyDownString += "ALT+";
@@ -27942,6 +28032,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
27942
28032
  // ---------------------------------------------------------------------------
27943
28033
  // Command Handling
27944
28034
  // ---------------------------------------------------------------------------
28035
+ allowDispatch(cmd) {
28036
+ switch (cmd.type) {
28037
+ case "SET_BORDER":
28038
+ return this.checkBordersUnchanged(cmd);
28039
+ default:
28040
+ return 0 /* CommandResult.Success */;
28041
+ }
28042
+ }
27945
28043
  handle(cmd) {
27946
28044
  switch (cmd.type) {
27947
28045
  case "ADD_MERGE":
@@ -28337,6 +28435,15 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28337
28435
  this.setBorders(sheetId, [{ ...zone, left: right }], "right");
28338
28436
  }
28339
28437
  }
28438
+ checkBordersUnchanged(cmd) {
28439
+ var _a, _b, _c, _d;
28440
+ const currentBorder = this.getCellBorder(cmd);
28441
+ const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
28442
+ if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
28443
+ return 88 /* CommandResult.NoChanges */;
28444
+ }
28445
+ return 0 /* CommandResult.Success */;
28446
+ }
28340
28447
  // ---------------------------------------------------------------------------
28341
28448
  // Import/Export
28342
28449
  // ---------------------------------------------------------------------------
@@ -28372,7 +28479,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28372
28479
  */
28373
28480
  function getBorderId(border) {
28374
28481
  for (let [key, value] of Object.entries(borders)) {
28375
- if (stringify(value) === stringify(border)) {
28482
+ if (deepEquals(value, border)) {
28376
28483
  return parseInt(key, 10);
28377
28484
  }
28378
28485
  }
@@ -28440,8 +28547,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28440
28547
  allowDispatch(cmd) {
28441
28548
  switch (cmd.type) {
28442
28549
  case "UPDATE_CELL":
28550
+ return this.checkCellOutOfSheet(cmd);
28443
28551
  case "CLEAR_CELL":
28444
- return this.checkCellOutOfSheet(cmd.sheetId, cmd.col, cmd.row);
28552
+ return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
28445
28553
  default:
28446
28554
  return 0 /* CommandResult.Success */;
28447
28555
  }
@@ -28600,14 +28708,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28600
28708
  */
28601
28709
  getCellById(cellId) {
28602
28710
  // this must be as fast as possible
28603
- for (const sheetId in this.cells) {
28604
- const sheet = this.cells[sheetId];
28605
- const cell = sheet[cellId];
28606
- if (cell) {
28607
- return cell;
28608
- }
28609
- }
28610
- return undefined;
28711
+ const position = this.getters.getCellPosition(cellId);
28712
+ const sheet = this.cells[position.sheetId];
28713
+ return sheet[cellId];
28611
28714
  }
28612
28715
  /*
28613
28716
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -28848,13 +28951,23 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
28848
28951
  dependencies: [],
28849
28952
  };
28850
28953
  }
28851
- checkCellOutOfSheet(sheetId, col, row) {
28954
+ checkCellOutOfSheet(cmd) {
28955
+ const { sheetId, col, row } = cmd;
28852
28956
  const sheet = this.getters.tryGetSheet(sheetId);
28853
28957
  if (!sheet)
28854
28958
  return 27 /* CommandResult.InvalidSheetId */;
28855
28959
  const sheetZone = this.getters.getSheetZone(sheetId);
28856
28960
  return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
28857
28961
  }
28962
+ checkUselessClearCell(cmd) {
28963
+ const cell = this.getters.getCell(cmd);
28964
+ if (!cell)
28965
+ return 88 /* CommandResult.NoChanges */;
28966
+ if (!cell.content && !cell.style && !cell.format) {
28967
+ return 88 /* CommandResult.NoChanges */;
28968
+ }
28969
+ return 0 /* CommandResult.Success */;
28970
+ }
28858
28971
  }
28859
28972
  CellPlugin.getters = [
28860
28973
  "zoneToXC",
@@ -31315,7 +31428,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31315
31428
  const elements = cmd.dimension === "COL"
31316
31429
  ? this.getNumberCols(cmd.sheetId)
31317
31430
  : this.getNumberRows(cmd.sheetId);
31318
- if (cmd.base < 0 || cmd.base > elements) {
31431
+ if (cmd.base < 0 || cmd.base >= elements) {
31319
31432
  return 86 /* CommandResult.InvalidHeaderIndex */;
31320
31433
  }
31321
31434
  else if (cmd.quantity <= 0) {
@@ -31915,10 +32028,13 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31915
32028
  // begin with the end.
31916
32029
  rows.sort((a, b) => b - a);
31917
32030
  for (let group of groupConsecutive(rows)) {
32031
+ // indexes are sorted in the descending order
32032
+ const from = group[group.length - 1];
32033
+ const to = group[0];
31918
32034
  // Move the cells.
31919
- this.moveCellOnRowsDeletion(sheet, group[group.length - 1], group[0]);
31920
- // Effectively delete the element and recompute the left-right/top-bottom.
31921
- group.map((row) => this.updateRowsStructureOnDeletion(row, sheet));
32035
+ this.moveCellOnRowsDeletion(sheet, from, to);
32036
+ // Effectively delete the rows
32037
+ this.updateRowsStructureOnDeletion(sheet, from, to);
31922
32038
  }
31923
32039
  const count = rows.filter((row) => row < sheet.panes.ySplit).length;
31924
32040
  if (count) {
@@ -31940,8 +32056,6 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
31940
32056
  this.addEmptyRows(sheet, quantity);
31941
32057
  // Move the cells.
31942
32058
  this.moveCellsOnAddition(sheet, index, quantity, "rows");
31943
- // Recompute the left-right/top-bottom.
31944
- this.updateRowsStructureOnAddition(sheet, row, quantity);
31945
32059
  if (index < sheet.panes.ySplit) {
31946
32060
  this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
31947
32061
  }
@@ -32042,35 +32156,20 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32042
32156
  }
32043
32157
  }
32044
32158
  }
32045
- updateRowsStructureOnDeletion(index, sheet) {
32159
+ updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
32046
32160
  const rows = [];
32047
- const cellsQueue = sheet.rows.map((row) => row.cells);
32161
+ const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
32048
32162
  for (let i in sheet.rows) {
32049
- if (Number(i) === index) {
32163
+ const row = Number(i);
32164
+ if (row >= deleteFromRow && row <= deleteToRow) {
32050
32165
  continue;
32051
32166
  }
32052
32167
  rows.push({
32053
- cells: cellsQueue.shift(),
32168
+ cells: cellsQueue.pop(),
32054
32169
  });
32055
32170
  }
32056
32171
  this.history.update("sheets", sheet.id, "rows", rows);
32057
32172
  }
32058
- /**
32059
- * Update the rows of the sheet after an addition:
32060
- * - Rename the rows
32061
- *
32062
- * @param sheet Sheet on which the deletion occurs
32063
- * @param addedRow Index of the added row
32064
- * @param rowsToAdd Number of the rows to add
32065
- */
32066
- updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
32067
- const rows = [];
32068
- const cellsQueue = sheet.rows.map((row) => row.cells);
32069
- sheet.rows.forEach(() => rows.push({
32070
- cells: cellsQueue.shift(),
32071
- }));
32072
- this.history.update("sheets", sheet.id, "rows", rows);
32073
- }
32074
32173
  /**
32075
32174
  * Add empty rows at the end of the rows
32076
32175
  *
@@ -32352,13 +32451,18 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32352
32451
  // Getters
32353
32452
  // ---------------------------------------------------------------------------
32354
32453
  evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
32355
- const compiledFormula = compile(formulaString);
32356
- const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
32357
- const ranges = [];
32358
- for (let xc of compiledFormula.dependencies) {
32359
- ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
32454
+ try {
32455
+ const compiledFormula = compile(formulaString);
32456
+ const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
32457
+ const ranges = [];
32458
+ for (let xc of compiledFormula.dependencies) {
32459
+ ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
32460
+ }
32461
+ return compiledFormula.execute(ranges, ...params).value;
32462
+ }
32463
+ catch (error) {
32464
+ return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
32360
32465
  }
32361
- return compiledFormula.execute(ranges, ...params).value;
32362
32466
  }
32363
32467
  /**
32364
32468
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -32527,6 +32631,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32527
32631
  }
32528
32632
  return evaluatedCell;
32529
32633
  };
32634
+ const rangeCache = {};
32530
32635
  /**
32531
32636
  * Return the values of the cell(s) used in reference, but always in the format of a range even
32532
32637
  * if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
@@ -32543,21 +32648,26 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32543
32648
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
32544
32649
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
32545
32650
  const sheetZone = getters.getSheetZone(sheetId);
32546
- const result = [];
32547
32651
  const zone = intersection(range.zone, sheetZone);
32548
32652
  if (!zone) {
32549
- result.push([]);
32550
- return result;
32653
+ return [[]];
32551
32654
  }
32655
+ const { top, left, bottom, right } = zone;
32656
+ const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
32657
+ if (cacheKey in rangeCache) {
32658
+ return rangeCache[cacheKey];
32659
+ }
32660
+ const result = new Array(right - left + 1);
32552
32661
  // Performance issue: nested loop is faster than a map here
32553
- for (let col = zone.left; col <= zone.right; col++) {
32554
- const rowValues = [];
32555
- for (let row = zone.top; row <= zone.bottom; row++) {
32662
+ for (let col = left; col <= right; col++) {
32663
+ const rowValues = new Array(bottom - top + 1);
32664
+ for (let row = top; row <= bottom; row++) {
32556
32665
  const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
32557
- rowValues.push(cell ? getEvaluatedCell(cell) : undefined);
32666
+ rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
32558
32667
  }
32559
- result.push(rowValues);
32668
+ result[col - left] = rowValues;
32560
32669
  }
32670
+ rangeCache[cacheKey] = result;
32561
32671
  return result;
32562
32672
  }
32563
32673
  /**
@@ -32844,39 +32954,34 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32844
32954
  this.computedIcons[sheetId] = {};
32845
32955
  const computedStyle = this.computedStyles[sheetId];
32846
32956
  for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
32847
- try {
32848
- switch (cf.rule.type) {
32849
- case "ColorScaleRule":
32850
- for (let range of cf.ranges) {
32851
- this.applyColorScale(range, cf.rule);
32852
- }
32853
- break;
32854
- case "IconSetRule":
32855
- for (let range of cf.ranges) {
32856
- this.applyIcon(range, cf.rule);
32857
- }
32858
- break;
32859
- default:
32860
- for (let ref of cf.ranges) {
32861
- const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
32862
- for (let row = zone.top; row <= zone.bottom; row++) {
32863
- for (let col = zone.left; col <= zone.right; col++) {
32864
- const pr = this.rulePredicate[cf.rule.type];
32865
- let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
32866
- if (pr && pr(cell, cf.rule)) {
32867
- if (!computedStyle[col])
32868
- computedStyle[col] = [];
32869
- // we must combine all the properties of all the CF rules applied to the given cell
32870
- computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
32871
- }
32957
+ switch (cf.rule.type) {
32958
+ case "ColorScaleRule":
32959
+ for (let range of cf.ranges) {
32960
+ this.applyColorScale(range, cf.rule);
32961
+ }
32962
+ break;
32963
+ case "IconSetRule":
32964
+ for (let range of cf.ranges) {
32965
+ this.applyIcon(range, cf.rule);
32966
+ }
32967
+ break;
32968
+ default:
32969
+ for (let ref of cf.ranges) {
32970
+ const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
32971
+ for (let row = zone.top; row <= zone.bottom; row++) {
32972
+ for (let col = zone.left; col <= zone.right; col++) {
32973
+ const pr = this.rulePredicate[cf.rule.type];
32974
+ let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
32975
+ if (pr && pr(cell, cf.rule)) {
32976
+ if (!computedStyle[col])
32977
+ computedStyle[col] = [];
32978
+ // we must combine all the properties of all the CF rules applied to the given cell
32979
+ computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
32872
32980
  }
32873
32981
  }
32874
32982
  }
32875
- break;
32876
- }
32877
- }
32878
- catch (_) {
32879
- // we don't care about the errors within the evaluation of a rule
32983
+ }
32984
+ break;
32880
32985
  }
32881
32986
  }
32882
32987
  }
@@ -32901,7 +33006,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
32901
33006
  return percentile(rangeValues, Number(threshold.value) / 100, true);
32902
33007
  case "formula":
32903
33008
  const value = threshold.value && this.getters.evaluateFormula(threshold.value);
32904
- return !(value instanceof Promise) ? value : null;
33009
+ return typeof value === "number" ? value : null;
32905
33010
  default:
32906
33011
  return null;
32907
33012
  }
@@ -34463,24 +34568,27 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
34463
34568
  * autofiller
34464
34569
  */
34465
34570
  autofillAuto() {
34571
+ var _a, _b;
34466
34572
  const zone = this.getters.getSelectedZone();
34467
34573
  const sheetId = this.getters.getActiveSheetId();
34468
34574
  let col = zone.left;
34469
34575
  let row = zone.bottom;
34470
34576
  if (col > 0) {
34471
- let left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
34472
- while (left.type !== CellValueType.empty) {
34577
+ let leftPosition = { sheetId, col: col - 1, row };
34578
+ while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
34579
+ ((_a = this.getters.getCell(leftPosition)) === null || _a === void 0 ? void 0 : _a.content)) {
34473
34580
  row += 1;
34474
- left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
34581
+ leftPosition = { sheetId, col: col - 1, row };
34475
34582
  }
34476
34583
  }
34477
34584
  if (row === zone.bottom) {
34478
34585
  col = zone.right;
34479
34586
  if (col <= this.getters.getNumberCols(sheetId)) {
34480
- let right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
34481
- while (right.type !== CellValueType.empty) {
34587
+ let rightPosition = { sheetId, col: col + 1, row };
34588
+ while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
34589
+ ((_b = this.getters.getCell(rightPosition)) === null || _b === void 0 ? void 0 : _b.content)) {
34482
34590
  row += 1;
34483
- right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
34591
+ rightPosition = { sheetId, col: col + 1, row };
34484
34592
  }
34485
34593
  }
34486
34594
  }
@@ -39212,7 +39320,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
39212
39320
  sheetId: cmd.sheetId,
39213
39321
  base: cmd.base,
39214
39322
  quantity: thickness,
39215
- position: "before",
39323
+ position: cmd.position,
39216
39324
  });
39217
39325
  const isCol = cmd.dimension === "COL";
39218
39326
  const start = cmd.elements[0];
@@ -39229,12 +39337,13 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
39229
39337
  },
39230
39338
  ];
39231
39339
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
39340
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
39232
39341
  const pasteTarget = [
39233
39342
  {
39234
- left: isCol ? cmd.base : 0,
39235
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39236
- top: !isCol ? cmd.base : 0,
39237
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39343
+ left: isCol ? base : 0,
39344
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
39345
+ top: !isCol ? base : 0,
39346
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
39238
39347
  },
39239
39348
  ];
39240
39349
  state.paste(pasteTarget, { selectTarget: true });
@@ -39271,6 +39380,11 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
39271
39380
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
39272
39381
  return 2 /* CommandResult.WillRemoveExistingMerge */;
39273
39382
  }
39383
+ const headers = [cmd.base, ...cmd.elements];
39384
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
39385
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
39386
+ return 86 /* CommandResult.InvalidHeaderIndex */;
39387
+ }
39274
39388
  return 0 /* CommandResult.Success */;
39275
39389
  }
39276
39390
  //-------------------------------------------
@@ -40824,7 +40938,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
40824
40938
  }
40825
40939
  onKeydown(ev) {
40826
40940
  let keyDownString = "";
40827
- if (ev.ctrlKey || ev.metaKey) {
40941
+ if (isCtrlKey(ev)) {
40828
40942
  keyDownString += "CTRL+";
40829
40943
  }
40830
40944
  keyDownString += ev.key.toUpperCase();
@@ -41671,9 +41785,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
41671
41785
  * Apply the changes of the given HistoryChange to the state
41672
41786
  */
41673
41787
  function applyChange(change, target) {
41674
- let val = change.root;
41675
- let key = change.path[change.path.length - 1];
41676
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41788
+ let val = change.path[0];
41789
+ const key = change.path[change.path.length - 1];
41790
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
41677
41791
  const p = change.path[pathIndex];
41678
41792
  if (val[p] === undefined) {
41679
41793
  const nextPath = change.path[pathIndex + 1];
@@ -42428,13 +42542,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42428
42542
  }
42429
42543
  addChange(...args) {
42430
42544
  const val = args.pop();
42431
- const [root, ...path] = args;
42545
+ const root = args[0];
42432
42546
  let value = root;
42433
- let key = path[path.length - 1];
42434
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
42435
- const p = path[pathIndex];
42547
+ let key = args[args.length - 1];
42548
+ const pathLength = args.length - 2;
42549
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
42550
+ const p = args[pathIndex];
42436
42551
  if (value[p] === undefined) {
42437
- const nextPath = path[pathIndex + 1];
42552
+ const nextPath = args[pathIndex + 1];
42438
42553
  value[p] = createEmptyStructure(nextPath);
42439
42554
  }
42440
42555
  value = value[p];
@@ -42443,8 +42558,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42443
42558
  return;
42444
42559
  }
42445
42560
  this.changes.push({
42446
- root,
42447
- path,
42561
+ path: args,
42448
42562
  before: value[key],
42449
42563
  after: val,
42450
42564
  });
@@ -44218,7 +44332,10 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
44218
44332
  */
44219
44333
  checkDispatchAllowed(command) {
44220
44334
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
44221
- return new DispatchResult(results.flat());
44335
+ if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
44336
+ return new DispatchResult(results.flat());
44337
+ }
44338
+ return DispatchResult.Success;
44222
44339
  }
44223
44340
  finalize() {
44224
44341
  this.status = 3 /* Status.Finalizing */;
@@ -44448,9 +44565,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
44448
44565
  Object.defineProperty(exports, '__esModule', { value: true });
44449
44566
 
44450
44567
 
44451
- __info__.version = '16.1.27';
44452
- __info__.date = '2023-11-16T11:57:02.419Z';
44453
- __info__.hash = '81f7214';
44568
+ __info__.version = '16.1.31';
44569
+ __info__.date = '2024-01-12T13:42:11.001Z';
44570
+ __info__.hash = 'f51befa';
44454
44571
 
44455
44572
 
44456
44573
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);