@odoo/o-spreadsheet 16.3.18 → 16.3.24

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.
@@ -302,15 +302,80 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
302
302
  // -----------------------------------------------------------------------------
303
303
  // Date Type
304
304
  // -----------------------------------------------------------------------------
305
+ /**
306
+ * A DateTime object that can be used to manipulate spreadsheet dates.
307
+ * Conceptually, a spreadsheet date is simply a number with a date format,
308
+ * and it is timezone-agnostic.
309
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
310
+ */
311
+ class DateTime {
312
+ jsDate;
313
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
314
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
315
+ }
316
+ static fromTimestamp(timestamp) {
317
+ const date = new Date(timestamp);
318
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
319
+ }
320
+ static now() {
321
+ const now = new Date();
322
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
323
+ }
324
+ toString() {
325
+ return this.jsDate.toString();
326
+ }
327
+ toLocaleDateString() {
328
+ return this.jsDate.toLocaleDateString();
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
+ }
305
370
  // -----------------------------------------------------------------------------
306
371
  // Parsing
307
372
  // -----------------------------------------------------------------------------
308
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
373
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
309
374
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
310
375
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
311
- const CURRENT_YEAR = new Date().getFullYear();
312
- const INITIAL_JS_DAY = new Date(0);
313
- 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();
314
379
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
315
380
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
316
381
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -359,7 +424,7 @@ function _parseDateTime(str) {
359
424
  return {
360
425
  value: date.value + time.value,
361
426
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
362
- 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()),
363
428
  };
364
429
  }
365
430
  return date || time;
@@ -376,13 +441,13 @@ function parseDate(str, dateFormat) {
376
441
  const day = Number(parts[dayIndex]);
377
442
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
378
443
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
379
- const jsDate = new Date(year, month - 1, day);
444
+ const jsDate = new DateTime(year, month - 1, day);
380
445
  const sep = str.match(/\/|-|\s/)[0];
381
446
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
382
447
  // invalid date
383
448
  return null;
384
449
  }
385
- const delta = jsDate - INITIAL_1900_DAY;
450
+ const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
386
451
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
387
452
  if (parts[yearIndex]) {
388
453
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -442,7 +507,7 @@ function parseTime(str) {
442
507
  if (hours >= 24) {
443
508
  format = "hhhh:mm:ss";
444
509
  }
445
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
510
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
446
511
  return {
447
512
  value: hours / 24 + minutes / 1440 + seconds / 86400,
448
513
  format: format,
@@ -456,7 +521,7 @@ function parseTime(str) {
456
521
  // -----------------------------------------------------------------------------
457
522
  function numberToJsDate(value) {
458
523
  const truncValue = Math.trunc(value);
459
- 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);
460
525
  let time = value - truncValue;
461
526
  time = time < 0 ? 1 + time : time;
462
527
  const hours = Math.round(time * 24);
@@ -473,7 +538,7 @@ function jsDateToRoundNumber(date) {
473
538
  }
474
539
  /** Return the number of days in the current month of the given date */
475
540
  function getDaysInMonth(date) {
476
- return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
541
+ return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
477
542
  }
478
543
  function isLastDayOfMonth(date) {
479
544
  return getDaysInMonth(date) === date.getDate();
@@ -491,7 +556,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
491
556
  const yStart = date.getFullYear();
492
557
  const mStart = date.getMonth();
493
558
  const dStart = date.getDate();
494
- const jsDate = new Date(yStart, mStart + months);
559
+ const jsDate = new DateTime(yStart, mStart + months, 1);
495
560
  if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
496
561
  jsDate.setDate(getDaysInMonth(jsDate));
497
562
  }
@@ -651,13 +716,6 @@ function areTwoDatesWithinOneYear(startDate, endDate) {
651
716
  }
652
717
 
653
718
  //------------------------------------------------------------------------------
654
- /**
655
- * Stringify an object, like JSON.stringify, except that the first level of keys
656
- * is ordered.
657
- */
658
- function stringify(obj) {
659
- return JSON.stringify(obj, Object.keys(obj).sort());
660
- }
661
719
  /**
662
720
  * Remove quotes from a quoted string
663
721
  * ```js
@@ -887,7 +945,7 @@ function isBoolean(str) {
887
945
  function isDateTime(str) {
888
946
  return parseDateTime(str) !== null;
889
947
  }
890
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
948
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
891
949
  //link must start with http or https
892
950
  //https://stackoverflow.com/a/3809435/4760614
893
951
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -956,7 +1014,7 @@ function isObjectEmptyRecursive(argument) {
956
1014
  */
957
1015
  function getItemId(item, itemsDic) {
958
1016
  for (let [key, value] of Object.entries(itemsDic)) {
959
- if (stringify(value) === stringify(item)) {
1017
+ if (deepEquals(value, item)) {
960
1018
  return parseInt(key, 10);
961
1019
  }
962
1020
  }
@@ -1956,7 +2014,7 @@ function formatJSTime(jsDate, format) {
1956
2014
  .map((p) => {
1957
2015
  switch (p) {
1958
2016
  case "hhhh":
1959
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
2017
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
1960
2018
  return helapsedHours.toString();
1961
2019
  case "hh":
1962
2020
  return hours.toString().padStart(2, "0");
@@ -2019,27 +2077,30 @@ function detectFormat(content) {
2019
2077
  }
2020
2078
  function createLargeNumberFormat(format, magnitude, postFix) {
2021
2079
  const internalFormat = parseFormat(format || "#,##0");
2022
- const largeNumberFormat = internalFormat
2023
- .map((formatPart) => {
2024
- if (formatPart.type === "NUMBER") {
2025
- return [
2026
- {
2027
- ...formatPart,
2028
- format: {
2029
- ...formatPart.format,
2030
- magnitude,
2031
- decimalPart: undefined,
2032
- },
2033
- },
2034
- {
2035
- type: "STRING",
2036
- format: postFix,
2037
- },
2038
- ];
2080
+ const largeNumberFormat = [];
2081
+ for (let i = 0; i < internalFormat.length; i++) {
2082
+ const formatPart = internalFormat[i];
2083
+ if (formatPart.type !== "NUMBER") {
2084
+ largeNumberFormat.push(formatPart);
2085
+ continue;
2039
2086
  }
2040
- return formatPart;
2041
- })
2042
- .flat();
2087
+ largeNumberFormat.push({
2088
+ ...formatPart,
2089
+ format: {
2090
+ ...formatPart.format,
2091
+ magnitude,
2092
+ decimalPart: undefined,
2093
+ },
2094
+ });
2095
+ largeNumberFormat.push({
2096
+ type: "STRING",
2097
+ format: postFix,
2098
+ });
2099
+ const nextFormatPart = internalFormat[i + 1];
2100
+ if (nextFormatPart?.type === "STRING" && ["k", "m", "b"].includes(nextFormatPart.format)) {
2101
+ i++;
2102
+ }
2103
+ }
2043
2104
  return convertInternalFormatToFormat(largeNumberFormat);
2044
2105
  }
2045
2106
  function changeDecimalPlaces(format, step) {
@@ -2203,8 +2264,10 @@ function convertInternalFormatToFormat(internalFormat) {
2203
2264
  const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
2204
2265
  // Same as above, but matches the exact string (nothing before or after)
2205
2266
  const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
2206
- /** Reference of a column header (eg. A, AB) */
2207
- const colHeader = new RegExp(/^([A-Z]{1,3})+$/, "i");
2267
+ /** Reference of a column header (eg. A, AB, $A) */
2268
+ const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
2269
+ /** Reference of a row header (eg. 1, $1) */
2270
+ const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
2208
2271
  /** Reference of a column (eg. A, $CA, Sheet1!B) */
2209
2272
  const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
2210
2273
  /** Reference of a row (eg. 1, 59, Sheet1!9) */
@@ -2234,6 +2297,9 @@ function isRowReference(xc) {
2234
2297
  function isColHeader(str) {
2235
2298
  return colHeader.test(str);
2236
2299
  }
2300
+ function isRowHeader(str) {
2301
+ return rowHeader.test(str);
2302
+ }
2237
2303
  /**
2238
2304
  * Return true if the given xc is the reference of a single cell,
2239
2305
  * without any specified sheet (e.g. A1)
@@ -2300,18 +2366,10 @@ class RangeImpl {
2300
2366
  if (isFullCol) {
2301
2367
  parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2302
2368
  parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2303
- if (zone.left === zone.right) {
2304
- parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2305
- parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2306
- }
2307
2369
  }
2308
2370
  if (isFullRow) {
2309
2371
  parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
2310
2372
  parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
2311
- if (zone.top === zone.bottom) {
2312
- parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2313
- parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
2314
- }
2315
2373
  }
2316
2374
  return parts;
2317
2375
  }
@@ -4384,69 +4442,70 @@ exports.CommandResult = void 0;
4384
4442
  CommandResult[CommandResult["InvalidFigureId"] = 28] = "InvalidFigureId";
4385
4443
  CommandResult[CommandResult["InputAlreadyFocused"] = 29] = "InputAlreadyFocused";
4386
4444
  CommandResult[CommandResult["MaximumRangesReached"] = 30] = "MaximumRangesReached";
4387
- CommandResult[CommandResult["InvalidChartDefinition"] = 31] = "InvalidChartDefinition";
4388
- CommandResult[CommandResult["InvalidDataSet"] = 32] = "InvalidDataSet";
4389
- CommandResult[CommandResult["InvalidLabelRange"] = 33] = "InvalidLabelRange";
4390
- CommandResult[CommandResult["InvalidScorecardKeyValue"] = 34] = "InvalidScorecardKeyValue";
4391
- CommandResult[CommandResult["InvalidScorecardBaseline"] = 35] = "InvalidScorecardBaseline";
4392
- CommandResult[CommandResult["InvalidGaugeDataRange"] = 36] = "InvalidGaugeDataRange";
4393
- CommandResult[CommandResult["EmptyGaugeRangeMin"] = 37] = "EmptyGaugeRangeMin";
4394
- CommandResult[CommandResult["GaugeRangeMinNaN"] = 38] = "GaugeRangeMinNaN";
4395
- CommandResult[CommandResult["EmptyGaugeRangeMax"] = 39] = "EmptyGaugeRangeMax";
4396
- CommandResult[CommandResult["GaugeRangeMaxNaN"] = 40] = "GaugeRangeMaxNaN";
4397
- CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 41] = "GaugeRangeMinBiggerThanRangeMax";
4398
- CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 42] = "GaugeLowerInflectionPointNaN";
4399
- CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 43] = "GaugeUpperInflectionPointNaN";
4400
- CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 44] = "GaugeLowerBiggerThanUpper";
4401
- CommandResult[CommandResult["InvalidAutofillSelection"] = 45] = "InvalidAutofillSelection";
4402
- CommandResult[CommandResult["WrongComposerSelection"] = 46] = "WrongComposerSelection";
4403
- CommandResult[CommandResult["MinBiggerThanMax"] = 47] = "MinBiggerThanMax";
4404
- CommandResult[CommandResult["LowerBiggerThanUpper"] = 48] = "LowerBiggerThanUpper";
4405
- CommandResult[CommandResult["MidBiggerThanMax"] = 49] = "MidBiggerThanMax";
4406
- CommandResult[CommandResult["MinBiggerThanMid"] = 50] = "MinBiggerThanMid";
4407
- CommandResult[CommandResult["FirstArgMissing"] = 51] = "FirstArgMissing";
4408
- CommandResult[CommandResult["SecondArgMissing"] = 52] = "SecondArgMissing";
4409
- CommandResult[CommandResult["MinNaN"] = 53] = "MinNaN";
4410
- CommandResult[CommandResult["MidNaN"] = 54] = "MidNaN";
4411
- CommandResult[CommandResult["MaxNaN"] = 55] = "MaxNaN";
4412
- CommandResult[CommandResult["ValueUpperInflectionNaN"] = 56] = "ValueUpperInflectionNaN";
4413
- CommandResult[CommandResult["ValueLowerInflectionNaN"] = 57] = "ValueLowerInflectionNaN";
4414
- CommandResult[CommandResult["MinInvalidFormula"] = 58] = "MinInvalidFormula";
4415
- CommandResult[CommandResult["MidInvalidFormula"] = 59] = "MidInvalidFormula";
4416
- CommandResult[CommandResult["MaxInvalidFormula"] = 60] = "MaxInvalidFormula";
4417
- CommandResult[CommandResult["ValueUpperInvalidFormula"] = 61] = "ValueUpperInvalidFormula";
4418
- CommandResult[CommandResult["ValueLowerInvalidFormula"] = 62] = "ValueLowerInvalidFormula";
4419
- CommandResult[CommandResult["InvalidSortZone"] = 63] = "InvalidSortZone";
4420
- CommandResult[CommandResult["WaitingSessionConfirmation"] = 64] = "WaitingSessionConfirmation";
4421
- CommandResult[CommandResult["MergeOverlap"] = 65] = "MergeOverlap";
4422
- CommandResult[CommandResult["TooManyHiddenElements"] = 66] = "TooManyHiddenElements";
4423
- CommandResult[CommandResult["Readonly"] = 67] = "Readonly";
4424
- CommandResult[CommandResult["InvalidViewportSize"] = 68] = "InvalidViewportSize";
4425
- CommandResult[CommandResult["InvalidScrollingDirection"] = 69] = "InvalidScrollingDirection";
4426
- CommandResult[CommandResult["FigureDoesNotExist"] = 70] = "FigureDoesNotExist";
4427
- CommandResult[CommandResult["InvalidConditionalFormatId"] = 71] = "InvalidConditionalFormatId";
4428
- CommandResult[CommandResult["InvalidCellPopover"] = 72] = "InvalidCellPopover";
4429
- CommandResult[CommandResult["EmptyTarget"] = 73] = "EmptyTarget";
4430
- CommandResult[CommandResult["InvalidFreezeQuantity"] = 74] = "InvalidFreezeQuantity";
4431
- CommandResult[CommandResult["FrozenPaneOverlap"] = 75] = "FrozenPaneOverlap";
4432
- CommandResult[CommandResult["ValuesNotChanged"] = 76] = "ValuesNotChanged";
4433
- CommandResult[CommandResult["InvalidFilterZone"] = 77] = "InvalidFilterZone";
4434
- CommandResult[CommandResult["FilterOverlap"] = 78] = "FilterOverlap";
4435
- CommandResult[CommandResult["FilterNotFound"] = 79] = "FilterNotFound";
4436
- CommandResult[CommandResult["MergeInFilter"] = 80] = "MergeInFilter";
4437
- CommandResult[CommandResult["NonContinuousTargets"] = 81] = "NonContinuousTargets";
4438
- CommandResult[CommandResult["DuplicatedFigureId"] = 82] = "DuplicatedFigureId";
4439
- CommandResult[CommandResult["InvalidSelectionStep"] = 83] = "InvalidSelectionStep";
4440
- CommandResult[CommandResult["DuplicatedChartId"] = 84] = "DuplicatedChartId";
4441
- CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
4442
- CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
4443
- CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
4444
- CommandResult[CommandResult["MoreThanOneColumnSelected"] = 88] = "MoreThanOneColumnSelected";
4445
- CommandResult[CommandResult["EmptySplitSeparator"] = 89] = "EmptySplitSeparator";
4446
- CommandResult[CommandResult["SplitWillOverwriteContent"] = 90] = "SplitWillOverwriteContent";
4447
- CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 91] = "NoSplitSeparatorInSelection";
4448
- CommandResult[CommandResult["NoActiveSheet"] = 92] = "NoActiveSheet";
4449
- CommandResult[CommandResult["NoChanges"] = 93] = "NoChanges";
4445
+ CommandResult[CommandResult["InvalidInputId"] = 31] = "InvalidInputId";
4446
+ CommandResult[CommandResult["InvalidChartDefinition"] = 32] = "InvalidChartDefinition";
4447
+ CommandResult[CommandResult["InvalidDataSet"] = 33] = "InvalidDataSet";
4448
+ CommandResult[CommandResult["InvalidLabelRange"] = 34] = "InvalidLabelRange";
4449
+ CommandResult[CommandResult["InvalidScorecardKeyValue"] = 35] = "InvalidScorecardKeyValue";
4450
+ CommandResult[CommandResult["InvalidScorecardBaseline"] = 36] = "InvalidScorecardBaseline";
4451
+ CommandResult[CommandResult["InvalidGaugeDataRange"] = 37] = "InvalidGaugeDataRange";
4452
+ CommandResult[CommandResult["EmptyGaugeRangeMin"] = 38] = "EmptyGaugeRangeMin";
4453
+ CommandResult[CommandResult["GaugeRangeMinNaN"] = 39] = "GaugeRangeMinNaN";
4454
+ CommandResult[CommandResult["EmptyGaugeRangeMax"] = 40] = "EmptyGaugeRangeMax";
4455
+ CommandResult[CommandResult["GaugeRangeMaxNaN"] = 41] = "GaugeRangeMaxNaN";
4456
+ CommandResult[CommandResult["GaugeRangeMinBiggerThanRangeMax"] = 42] = "GaugeRangeMinBiggerThanRangeMax";
4457
+ CommandResult[CommandResult["GaugeLowerInflectionPointNaN"] = 43] = "GaugeLowerInflectionPointNaN";
4458
+ CommandResult[CommandResult["GaugeUpperInflectionPointNaN"] = 44] = "GaugeUpperInflectionPointNaN";
4459
+ CommandResult[CommandResult["GaugeLowerBiggerThanUpper"] = 45] = "GaugeLowerBiggerThanUpper";
4460
+ CommandResult[CommandResult["InvalidAutofillSelection"] = 46] = "InvalidAutofillSelection";
4461
+ CommandResult[CommandResult["WrongComposerSelection"] = 47] = "WrongComposerSelection";
4462
+ CommandResult[CommandResult["MinBiggerThanMax"] = 48] = "MinBiggerThanMax";
4463
+ CommandResult[CommandResult["LowerBiggerThanUpper"] = 49] = "LowerBiggerThanUpper";
4464
+ CommandResult[CommandResult["MidBiggerThanMax"] = 50] = "MidBiggerThanMax";
4465
+ CommandResult[CommandResult["MinBiggerThanMid"] = 51] = "MinBiggerThanMid";
4466
+ CommandResult[CommandResult["FirstArgMissing"] = 52] = "FirstArgMissing";
4467
+ CommandResult[CommandResult["SecondArgMissing"] = 53] = "SecondArgMissing";
4468
+ CommandResult[CommandResult["MinNaN"] = 54] = "MinNaN";
4469
+ CommandResult[CommandResult["MidNaN"] = 55] = "MidNaN";
4470
+ CommandResult[CommandResult["MaxNaN"] = 56] = "MaxNaN";
4471
+ CommandResult[CommandResult["ValueUpperInflectionNaN"] = 57] = "ValueUpperInflectionNaN";
4472
+ CommandResult[CommandResult["ValueLowerInflectionNaN"] = 58] = "ValueLowerInflectionNaN";
4473
+ CommandResult[CommandResult["MinInvalidFormula"] = 59] = "MinInvalidFormula";
4474
+ CommandResult[CommandResult["MidInvalidFormula"] = 60] = "MidInvalidFormula";
4475
+ CommandResult[CommandResult["MaxInvalidFormula"] = 61] = "MaxInvalidFormula";
4476
+ CommandResult[CommandResult["ValueUpperInvalidFormula"] = 62] = "ValueUpperInvalidFormula";
4477
+ CommandResult[CommandResult["ValueLowerInvalidFormula"] = 63] = "ValueLowerInvalidFormula";
4478
+ CommandResult[CommandResult["InvalidSortZone"] = 64] = "InvalidSortZone";
4479
+ CommandResult[CommandResult["WaitingSessionConfirmation"] = 65] = "WaitingSessionConfirmation";
4480
+ CommandResult[CommandResult["MergeOverlap"] = 66] = "MergeOverlap";
4481
+ CommandResult[CommandResult["TooManyHiddenElements"] = 67] = "TooManyHiddenElements";
4482
+ CommandResult[CommandResult["Readonly"] = 68] = "Readonly";
4483
+ CommandResult[CommandResult["InvalidViewportSize"] = 69] = "InvalidViewportSize";
4484
+ CommandResult[CommandResult["InvalidScrollingDirection"] = 70] = "InvalidScrollingDirection";
4485
+ CommandResult[CommandResult["FigureDoesNotExist"] = 71] = "FigureDoesNotExist";
4486
+ CommandResult[CommandResult["InvalidConditionalFormatId"] = 72] = "InvalidConditionalFormatId";
4487
+ CommandResult[CommandResult["InvalidCellPopover"] = 73] = "InvalidCellPopover";
4488
+ CommandResult[CommandResult["EmptyTarget"] = 74] = "EmptyTarget";
4489
+ CommandResult[CommandResult["InvalidFreezeQuantity"] = 75] = "InvalidFreezeQuantity";
4490
+ CommandResult[CommandResult["FrozenPaneOverlap"] = 76] = "FrozenPaneOverlap";
4491
+ CommandResult[CommandResult["ValuesNotChanged"] = 77] = "ValuesNotChanged";
4492
+ CommandResult[CommandResult["InvalidFilterZone"] = 78] = "InvalidFilterZone";
4493
+ CommandResult[CommandResult["FilterOverlap"] = 79] = "FilterOverlap";
4494
+ CommandResult[CommandResult["FilterNotFound"] = 80] = "FilterNotFound";
4495
+ CommandResult[CommandResult["MergeInFilter"] = 81] = "MergeInFilter";
4496
+ CommandResult[CommandResult["NonContinuousTargets"] = 82] = "NonContinuousTargets";
4497
+ CommandResult[CommandResult["DuplicatedFigureId"] = 83] = "DuplicatedFigureId";
4498
+ CommandResult[CommandResult["InvalidSelectionStep"] = 84] = "InvalidSelectionStep";
4499
+ CommandResult[CommandResult["DuplicatedChartId"] = 85] = "DuplicatedChartId";
4500
+ CommandResult[CommandResult["ChartDoesNotExist"] = 86] = "ChartDoesNotExist";
4501
+ CommandResult[CommandResult["InvalidHeaderIndex"] = 87] = "InvalidHeaderIndex";
4502
+ CommandResult[CommandResult["InvalidQuantity"] = 88] = "InvalidQuantity";
4503
+ CommandResult[CommandResult["MoreThanOneColumnSelected"] = 89] = "MoreThanOneColumnSelected";
4504
+ CommandResult[CommandResult["EmptySplitSeparator"] = 90] = "EmptySplitSeparator";
4505
+ CommandResult[CommandResult["SplitWillOverwriteContent"] = 91] = "SplitWillOverwriteContent";
4506
+ CommandResult[CommandResult["NoSplitSeparatorInSelection"] = 92] = "NoSplitSeparatorInSelection";
4507
+ CommandResult[CommandResult["NoActiveSheet"] = 93] = "NoActiveSheet";
4508
+ CommandResult[CommandResult["NoChanges"] = 94] = "NoChanges";
4450
4509
  })(exports.CommandResult || (exports.CommandResult = {}));
4451
4510
 
4452
4511
  const borderStyles = ["thin", "medium", "thick", "dashed", "dotted"];
@@ -5171,6 +5230,7 @@ const FilterMenuPopoverBuilder = {
5171
5230
  },
5172
5231
  };
5173
5232
 
5233
+ const macRegex = /Mac/i;
5174
5234
  /**
5175
5235
  * Return true if the event was triggered from
5176
5236
  * a child element.
@@ -5216,6 +5276,17 @@ function setElementScrollTop(el, scroll) {
5216
5276
  }
5217
5277
  function getOpenedMenus() {
5218
5278
  return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
5279
+ }
5280
+ function isMacOS() {
5281
+ return Boolean(macRegex.test(navigator.userAgent));
5282
+ }
5283
+ /**
5284
+ * @param {KeyboardEvent | MouseEvent} ev
5285
+ * @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
5286
+ * On Mac, this is the "meta" or "command" key.
5287
+ */
5288
+ function isCtrlKey(ev) {
5289
+ return isMacOS() ? ev.metaKey : ev.ctrlKey;
5219
5290
  }
5220
5291
 
5221
5292
  /**
@@ -6394,14 +6465,8 @@ function createDataSets(getters, dataSetsString, sheetId, dataSetsHaveTitle) {
6394
6465
  : undefined));
6395
6466
  }
6396
6467
  }
6397
- else if (zone.left === zone.right && zone.top === zone.bottom) {
6398
- // A single cell. If it's only the title, the dataset is not added.
6399
- if (!dataSetsHaveTitle) {
6400
- dataSets.push(createDataSet(getters, dataSetSheetId, zone, undefined));
6401
- }
6402
- }
6403
6468
  else {
6404
- /* 1 row or 1 column */
6469
+ /* 1 cell, 1 row or 1 column */
6405
6470
  dataSets.push(createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
6406
6471
  ? {
6407
6472
  top: zone.top,
@@ -6450,8 +6515,10 @@ function toExcelDataset(getters, ds) {
6450
6515
  }
6451
6516
  const dataRange = ds.dataRange.clone({ zone: dataZone });
6452
6517
  return {
6453
- label: ds.labelCell ? getters.getRangeString(ds.labelCell, "forceSheetReference") : undefined,
6454
- range: getters.getRangeString(dataRange, "forceSheetReference"),
6518
+ label: ds.labelCell
6519
+ ? getters.getRangeString(ds.labelCell, "forceSheetReference", true)
6520
+ : undefined,
6521
+ range: getters.getRangeString(dataRange, "forceSheetReference", true),
6455
6522
  };
6456
6523
  }
6457
6524
  function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
@@ -6464,7 +6531,7 @@ function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
6464
6531
  zone.top = zone.top + 1;
6465
6532
  }
6466
6533
  const range = labelRange.clone({ zone });
6467
- return getters.getRangeString(range, "forceSheetReference");
6534
+ return getters.getRangeString(range, "forceSheetReference", true);
6468
6535
  }
6469
6536
  /**
6470
6537
  * Transform a chart definition which supports dataSets (dataSets and LabelRange)
@@ -6530,11 +6597,11 @@ function checkDataset(definition) {
6530
6597
  if (definition.dataSets) {
6531
6598
  const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range)) !== undefined;
6532
6599
  if (invalidRanges) {
6533
- return 32 /* CommandResult.InvalidDataSet */;
6600
+ return 33 /* CommandResult.InvalidDataSet */;
6534
6601
  }
6535
6602
  const zones = definition.dataSets.map(toUnboundedZone);
6536
6603
  if (zones.some((zone) => zone.top !== zone.bottom && isFullRow(zone))) {
6537
- return 32 /* CommandResult.InvalidDataSet */;
6604
+ return 33 /* CommandResult.InvalidDataSet */;
6538
6605
  }
6539
6606
  }
6540
6607
  return 0 /* CommandResult.Success */;
@@ -6543,7 +6610,7 @@ function checkLabelRange(definition) {
6543
6610
  if (definition.labelRange) {
6544
6611
  const invalidLabels = !rangeReference.test(definition.labelRange || "");
6545
6612
  if (invalidLabels) {
6546
- return 33 /* CommandResult.InvalidLabelRange */;
6613
+ return 34 /* CommandResult.InvalidLabelRange */;
6547
6614
  }
6548
6615
  }
6549
6616
  return 0 /* CommandResult.Success */;
@@ -6630,22 +6697,22 @@ function getChartPositionAtCenterOfViewport(getters, chartSize) {
6630
6697
  const CfTerms = {
6631
6698
  Errors: {
6632
6699
  [25 /* CommandResult.InvalidRange */]: _lt("The range is invalid"),
6633
- [51 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6634
- [52 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6635
- [53 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6636
- [54 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6637
- [55 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6638
- [56 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6639
- [57 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6640
- [47 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6641
- [50 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6642
- [49 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6643
- [48 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6644
- [58 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6645
- [60 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6646
- [59 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6647
- [61 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6648
- [62 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6700
+ [52 /* CommandResult.FirstArgMissing */]: _lt("The argument is missing. Please provide a value"),
6701
+ [53 /* CommandResult.SecondArgMissing */]: _lt("The second argument is missing. Please provide a value"),
6702
+ [54 /* CommandResult.MinNaN */]: _lt("The minpoint must be a number"),
6703
+ [55 /* CommandResult.MidNaN */]: _lt("The midpoint must be a number"),
6704
+ [56 /* CommandResult.MaxNaN */]: _lt("The maxpoint must be a number"),
6705
+ [57 /* CommandResult.ValueUpperInflectionNaN */]: _lt("The first value must be a number"),
6706
+ [58 /* CommandResult.ValueLowerInflectionNaN */]: _lt("The second value must be a number"),
6707
+ [48 /* CommandResult.MinBiggerThanMax */]: _lt("Minimum must be smaller then Maximum"),
6708
+ [51 /* CommandResult.MinBiggerThanMid */]: _lt("Minimum must be smaller then Midpoint"),
6709
+ [50 /* CommandResult.MidBiggerThanMax */]: _lt("Midpoint must be smaller then Maximum"),
6710
+ [49 /* CommandResult.LowerBiggerThanUpper */]: _lt("Lower inflection point must be smaller than upper inflection point"),
6711
+ [59 /* CommandResult.MinInvalidFormula */]: _lt("Invalid Minpoint formula"),
6712
+ [61 /* CommandResult.MaxInvalidFormula */]: _lt("Invalid Maxpoint formula"),
6713
+ [60 /* CommandResult.MidInvalidFormula */]: _lt("Invalid Midpoint formula"),
6714
+ [62 /* CommandResult.ValueUpperInvalidFormula */]: _lt("Invalid upper inflection point formula"),
6715
+ [63 /* CommandResult.ValueLowerInvalidFormula */]: _lt("Invalid lower inflection point formula"),
6649
6716
  [24 /* CommandResult.EmptyRange */]: _lt("A range needs to be defined"),
6650
6717
  Unexpected: _lt("The rule is invalid for an unknown reason"),
6651
6718
  },
@@ -6673,20 +6740,20 @@ const ChartTerms = {
6673
6740
  Errors: {
6674
6741
  Unexpected: _lt("The chart definition is invalid for an unknown reason"),
6675
6742
  // BASIC CHART ERRORS (LINE | BAR | PIE)
6676
- [32 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6677
- [33 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6743
+ [33 /* CommandResult.InvalidDataSet */]: _lt("The dataset is invalid"),
6744
+ [34 /* CommandResult.InvalidLabelRange */]: _lt("Labels are invalid"),
6678
6745
  // SCORECARD CHART ERRORS
6679
- [34 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6680
- [35 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6746
+ [35 /* CommandResult.InvalidScorecardKeyValue */]: _lt("The key value is invalid"),
6747
+ [36 /* CommandResult.InvalidScorecardBaseline */]: _lt("The baseline value is invalid"),
6681
6748
  // GAUGE CHART ERRORS
6682
- [36 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6683
- [37 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6684
- [38 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6685
- [39 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6686
- [40 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6687
- [41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6688
- [42 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6689
- [43 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6749
+ [37 /* CommandResult.InvalidGaugeDataRange */]: _lt("The data range is invalid"),
6750
+ [38 /* CommandResult.EmptyGaugeRangeMin */]: _lt("A minimum range limit value is needed"),
6751
+ [39 /* CommandResult.GaugeRangeMinNaN */]: _lt("The minimum range limit value must be a number"),
6752
+ [40 /* CommandResult.EmptyGaugeRangeMax */]: _lt("A maximum range limit value is needed"),
6753
+ [41 /* CommandResult.GaugeRangeMaxNaN */]: _lt("The maximum range limit value must be a number"),
6754
+ [42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */]: _lt("Minimum range limit must be smaller than maximum range limit"),
6755
+ [43 /* CommandResult.GaugeLowerInflectionPointNaN */]: _lt("The lower inflection point value must be a number"),
6756
+ [44 /* CommandResult.GaugeUpperInflectionPointNaN */]: _lt("The upper inflection point value must be a number"),
6690
6757
  },
6691
6758
  };
6692
6759
  const CustomCurrencyTerms = {
@@ -6696,9 +6763,9 @@ const MergeErrorMessage = _lt("Merged cells are preventing this operation. Unmer
6696
6763
  const SplitToColumnsTerms = {
6697
6764
  Errors: {
6698
6765
  Unexpected: _lt("Cannot split the selection for an unknown reason"),
6699
- [91 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6700
- [88 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6701
- [90 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6766
+ [92 /* CommandResult.NoSplitSeparatorInSelection */]: _lt("There is no match for the selected separator in the selection"),
6767
+ [89 /* CommandResult.MoreThanOneColumnSelected */]: _lt("Only a selection from a single column can be split"),
6768
+ [91 /* CommandResult.SplitWillOverwriteContent */]: _lt("Splitting will overwrite existing content"),
6702
6769
  },
6703
6770
  };
6704
6771
 
@@ -7001,7 +7068,7 @@ class BarChart extends AbstractChart {
7001
7068
  return undefined;
7002
7069
  const dataSets = this.dataSets
7003
7070
  .map((ds) => toExcelDataset(this.getters, ds))
7004
- .filter((ds) => ds.range !== ""); // && range !== INCORRECT_RANGE_STRING ? show incorrect #ref ?
7071
+ .filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
7005
7072
  const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
7006
7073
  return {
7007
7074
  ...this.getDefinition(),
@@ -7102,7 +7169,7 @@ function createBarChartRuntime(chart, getters) {
7102
7169
 
7103
7170
  function isDataRangeValid(definition) {
7104
7171
  return definition.dataRange && !rangeReference.test(definition.dataRange)
7105
- ? 36 /* CommandResult.InvalidGaugeDataRange */
7172
+ ? 37 /* CommandResult.InvalidGaugeDataRange */
7106
7173
  : 0 /* CommandResult.Success */;
7107
7174
  }
7108
7175
  function checkRangeLimits(check, batchValidations) {
@@ -7134,7 +7201,7 @@ function checkInflectionPointsValue(check, batchValidations) {
7134
7201
  function checkRangeMinBiggerThanRangeMax(definition) {
7135
7202
  if (definition.sectionRule) {
7136
7203
  if (Number(definition.sectionRule.rangeMin) >= Number(definition.sectionRule.rangeMax)) {
7137
- return 41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7204
+ return 42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */;
7138
7205
  }
7139
7206
  }
7140
7207
  return 0 /* CommandResult.Success */;
@@ -7143,9 +7210,9 @@ function checkEmpty(value, valueName) {
7143
7210
  if (value === "") {
7144
7211
  switch (valueName) {
7145
7212
  case "rangeMin":
7146
- return 37 /* CommandResult.EmptyGaugeRangeMin */;
7213
+ return 38 /* CommandResult.EmptyGaugeRangeMin */;
7147
7214
  case "rangeMax":
7148
- return 39 /* CommandResult.EmptyGaugeRangeMax */;
7215
+ return 40 /* CommandResult.EmptyGaugeRangeMax */;
7149
7216
  }
7150
7217
  }
7151
7218
  return 0 /* CommandResult.Success */;
@@ -7154,13 +7221,13 @@ function checkNaN(value, valueName) {
7154
7221
  if (isNaN(value)) {
7155
7222
  switch (valueName) {
7156
7223
  case "rangeMin":
7157
- return 38 /* CommandResult.GaugeRangeMinNaN */;
7224
+ return 39 /* CommandResult.GaugeRangeMinNaN */;
7158
7225
  case "rangeMax":
7159
- return 40 /* CommandResult.GaugeRangeMaxNaN */;
7226
+ return 41 /* CommandResult.GaugeRangeMaxNaN */;
7160
7227
  case "lowerInflectionPointValue":
7161
- return 42 /* CommandResult.GaugeLowerInflectionPointNaN */;
7228
+ return 43 /* CommandResult.GaugeLowerInflectionPointNaN */;
7162
7229
  case "upperInflectionPointValue":
7163
- return 43 /* CommandResult.GaugeUpperInflectionPointNaN */;
7230
+ return 44 /* CommandResult.GaugeUpperInflectionPointNaN */;
7164
7231
  }
7165
7232
  }
7166
7233
  return 0 /* CommandResult.Success */;
@@ -7585,7 +7652,7 @@ class LineChart extends AbstractChart {
7585
7652
  return undefined;
7586
7653
  const dataSets = this.dataSets
7587
7654
  .map((ds) => toExcelDataset(this.getters, ds))
7588
- .filter((ds) => ds.range !== ""); // && range !== INCORRECT_RANGE_STRING ? show incorrect #ref ?
7655
+ .filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
7589
7656
  const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
7590
7657
  return {
7591
7658
  ...this.getDefinition(),
@@ -7870,7 +7937,7 @@ class PieChart extends AbstractChart {
7870
7937
  return undefined;
7871
7938
  const dataSets = this.dataSets
7872
7939
  .map((ds) => toExcelDataset(this.getters, ds))
7873
- .filter((ds) => ds.range !== ""); // && range !== INCORRECT_RANGE_STRING ? show incorrect #ref ?
7940
+ .filter((ds) => ds.range !== "" && ds.range !== INCORRECT_RANGE_STRING);
7874
7941
  const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
7875
7942
  return {
7876
7943
  ...this.getDefinition(),
@@ -7950,12 +8017,12 @@ function createPieChartRuntime(chart, getters) {
7950
8017
 
7951
8018
  function checkKeyValue(definition) {
7952
8019
  return definition.keyValue && !rangeReference.test(definition.keyValue)
7953
- ? 34 /* CommandResult.InvalidScorecardKeyValue */
8020
+ ? 35 /* CommandResult.InvalidScorecardKeyValue */
7954
8021
  : 0 /* CommandResult.Success */;
7955
8022
  }
7956
8023
  function checkBaseline(definition) {
7957
8024
  return definition.baseline && !rangeReference.test(definition.baseline)
7958
- ? 35 /* CommandResult.InvalidScorecardBaseline */
8025
+ ? 36 /* CommandResult.InvalidScorecardBaseline */
7959
8026
  : 0 /* CommandResult.Success */;
7960
8027
  }
7961
8028
  class ScorecardChart extends AbstractChart {
@@ -8461,7 +8528,7 @@ const AddMergeInteractiveContent = {
8461
8528
  };
8462
8529
  function interactiveAddMerge(env, sheetId, target) {
8463
8530
  const result = env.model.dispatch("ADD_MERGE", { sheetId, target });
8464
- if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8531
+ if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
8465
8532
  env.raiseError(AddMergeInteractiveContent.MergeInFilter);
8466
8533
  }
8467
8534
  else if (result.isCancelledBecause(3 /* CommandResult.MergeIsDestructive */)) {
@@ -8711,7 +8778,7 @@ function interactiveSortSelection(env, sheetId, anchor, zone, sortDirection) {
8711
8778
  });
8712
8779
  }
8713
8780
  }
8714
- if (result.isCancelledBecause(63 /* CommandResult.InvalidSortZone */)) {
8781
+ if (result.isCancelledBecause(64 /* CommandResult.InvalidSortZone */)) {
8715
8782
  const { col, row } = anchor;
8716
8783
  env.model.selection.selectZone({ cell: { col, row }, zone });
8717
8784
  env.raiseError(_lt("Cannot sort. To sort, select only cells or only merges that have the same size."));
@@ -8734,13 +8801,13 @@ const AddFilterInteractiveContent = {
8734
8801
  };
8735
8802
  function interactiveAddFilter(env, sheetId, target) {
8736
8803
  const result = env.model.dispatch("CREATE_FILTER_TABLE", { target, sheetId });
8737
- if (result.isCancelledBecause(78 /* CommandResult.FilterOverlap */)) {
8804
+ if (result.isCancelledBecause(79 /* CommandResult.FilterOverlap */)) {
8738
8805
  env.raiseError(AddFilterInteractiveContent.filterOverlap);
8739
8806
  }
8740
- else if (result.isCancelledBecause(80 /* CommandResult.MergeInFilter */)) {
8807
+ else if (result.isCancelledBecause(81 /* CommandResult.MergeInFilter */)) {
8741
8808
  env.raiseError(AddFilterInteractiveContent.mergeInFilter);
8742
8809
  }
8743
- else if (result.isCancelledBecause(81 /* CommandResult.NonContinuousTargets */)) {
8810
+ else if (result.isCancelledBecause(82 /* CommandResult.NonContinuousTargets */)) {
8744
8811
  env.raiseError(AddFilterInteractiveContent.nonContinuousTargets);
8745
8812
  }
8746
8813
  }
@@ -8762,7 +8829,7 @@ function handlePasteResult(env, result) {
8762
8829
  else if (result.reasons.includes(22 /* CommandResult.WrongFigurePasteOption */)) {
8763
8830
  env.raiseError(PasteInteractiveContent.wrongFigurePasteOption);
8764
8831
  }
8765
- else if (result.reasons.includes(75 /* CommandResult.FrozenPaneOverlap */)) {
8832
+ else if (result.reasons.includes(76 /* CommandResult.FrozenPaneOverlap */)) {
8766
8833
  env.raiseError(PasteInteractiveContent.frozenPaneOverlap);
8767
8834
  }
8768
8835
  }
@@ -9602,6 +9669,9 @@ function arg(definition, description = "") {
9602
9669
  function makeArg(str, description) {
9603
9670
  let parts = str.match(ARG_REGEXP);
9604
9671
  let name = parts[1].trim();
9672
+ if (!name) {
9673
+ throw new Error(`Function argument definition is missing a name: '${str}'.`);
9674
+ }
9605
9675
  let types = [];
9606
9676
  let isOptional = false;
9607
9677
  let isRepeating = false;
@@ -12055,7 +12125,7 @@ const DATE = {
12055
12125
  if (_year < 1900) {
12056
12126
  _year += 1900;
12057
12127
  }
12058
- const jsDate = new Date(_year, _month - 1, _day);
12128
+ const jsDate = new DateTime(_year, _month - 1, _day);
12059
12129
  const result = jsDateToRoundNumber(jsDate);
12060
12130
  assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
12061
12131
  return result;
@@ -12098,7 +12168,7 @@ const DATEDIF = {
12098
12168
  // See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
12099
12169
  let days = jsEndDate.getDate() - jsStartDate.getDate();
12100
12170
  if (days < 0) {
12101
- const monthBeforeEndMonth = new Date(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
12171
+ const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
12102
12172
  const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
12103
12173
  days = daysInMonthBeforeEndMonth - Math.abs(days);
12104
12174
  }
@@ -12107,7 +12177,7 @@ const DATEDIF = {
12107
12177
  if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
12108
12178
  return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
12109
12179
  }
12110
- const endDateWithinOneYear = new Date(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
12180
+ const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
12111
12181
  let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
12112
12182
  if (days < 0) {
12113
12183
  endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
@@ -12220,7 +12290,7 @@ const EOMONTH = {
12220
12290
  const _months = Math.trunc(toNumber(months));
12221
12291
  const yStart = _startDate.getFullYear();
12222
12292
  const mStart = _startDate.getMonth();
12223
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
12293
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
12224
12294
  return jsDateToRoundNumber(jsDate);
12225
12295
  },
12226
12296
  isExported: true,
@@ -12257,17 +12327,17 @@ const ISOWEEKNUM = {
12257
12327
  // The first week of the year is the week that contains the first
12258
12328
  // Thursday of the year.
12259
12329
  let firstThursday = 1;
12260
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
12330
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
12261
12331
  firstThursday += 1;
12262
12332
  }
12263
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
12333
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
12264
12334
  // The last week of the year is the week that contains the last Thursday of
12265
12335
  // the year.
12266
12336
  let lastThursday = 31;
12267
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
12337
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
12268
12338
  lastThursday -= 1;
12269
12339
  }
12270
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
12340
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
12271
12341
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
12272
12342
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
12273
12343
  let offsetYear;
@@ -12293,17 +12363,17 @@ const ISOWEEKNUM = {
12293
12363
  case 1:
12294
12364
  // firstDay is the 1st day of the 1st week of the year after
12295
12365
  // firstDay = lastDayOfLastWeek + 1 Day
12296
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
12366
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
12297
12367
  break;
12298
12368
  case -1:
12299
12369
  // firstDay is the 1st day of the 1st week of the previous year.
12300
12370
  // The first week of the previous year is the week that contains the
12301
12371
  // first Thursday of the previous year.
12302
12372
  let firstThursdayPreviousYear = 1;
12303
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
12373
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
12304
12374
  firstThursdayPreviousYear += 1;
12305
12375
  }
12306
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
12376
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
12307
12377
  break;
12308
12378
  }
12309
12379
  const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
@@ -12438,8 +12508,8 @@ const NETWORKDAYS_INTL = {
12438
12508
  });
12439
12509
  }
12440
12510
  const invertDate = _startDate.getTime() > _endDate.getTime();
12441
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
12442
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
12511
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
12512
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
12443
12513
  const timeStopDate = stopDate.getTime();
12444
12514
  let timeStepDate = stepDate.getTime();
12445
12515
  let netWorkingDay = 0;
@@ -12463,8 +12533,7 @@ const NOW = {
12463
12533
  returns: ["DATE"],
12464
12534
  computeFormat: () => "m/d/yyyy hh:mm:ss",
12465
12535
  compute: function () {
12466
- let today = new Date();
12467
- today.setMilliseconds(0);
12536
+ let today = DateTime.now();
12468
12537
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
12469
12538
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
12470
12539
  return Math.floor(delta / MS_PER_DAY) + time;
@@ -12534,8 +12603,8 @@ const TODAY = {
12534
12603
  returns: ["DATE"],
12535
12604
  computeFormat: () => "m/d/yyyy",
12536
12605
  compute: function () {
12537
- const today = new Date();
12538
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
12606
+ const today = DateTime.now();
12607
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
12539
12608
  return jsDateToRoundNumber(jsDate);
12540
12609
  },
12541
12610
  isExported: true,
@@ -12590,10 +12659,10 @@ const WEEKNUM = {
12590
12659
  }
12591
12660
  const y = _date.getFullYear();
12592
12661
  let dayStart = 1;
12593
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
12662
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
12594
12663
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
12595
12664
  dayStart += 1;
12596
- startDayOfFirstWeek = new Date(y, 0, dayStart);
12665
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
12597
12666
  }
12598
12667
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
12599
12668
  if (dif < 0) {
@@ -12647,7 +12716,7 @@ const WORKDAY_INTL = {
12647
12716
  timesHoliday.add(holiday.getTime());
12648
12717
  });
12649
12718
  }
12650
- let stepDate = new Date(_startDate.getTime());
12719
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
12651
12720
  let timeStepDate = stepDate.getTime();
12652
12721
  const unitDay = Math.sign(_numDays);
12653
12722
  let stepDay = Math.abs(_numDays);
@@ -12709,7 +12778,7 @@ const MONTH_START = {
12709
12778
  const _startDate = toJsDate(date);
12710
12779
  const yStart = _startDate.getFullYear();
12711
12780
  const mStart = _startDate.getMonth();
12712
- const jsDate = new Date(yStart, mStart, 1);
12781
+ const jsDate = new DateTime(yStart, mStart, 1);
12713
12782
  return jsDateToRoundNumber(jsDate);
12714
12783
  },
12715
12784
  };
@@ -12747,7 +12816,7 @@ const QUARTER_START = {
12747
12816
  compute: function (date) {
12748
12817
  const quarter = QUARTER.compute(date);
12749
12818
  const year = YEAR.compute(date);
12750
- const jsDate = new Date(year, (quarter - 1) * 3, 1);
12819
+ const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
12751
12820
  return jsDateToRoundNumber(jsDate);
12752
12821
  },
12753
12822
  };
@@ -12762,7 +12831,7 @@ const QUARTER_END = {
12762
12831
  compute: function (date) {
12763
12832
  const quarter = QUARTER.compute(date);
12764
12833
  const year = YEAR.compute(date);
12765
- const jsDate = new Date(year, quarter * 3, 0);
12834
+ const jsDate = new DateTime(year, quarter * 3, 0);
12766
12835
  return jsDateToRoundNumber(jsDate);
12767
12836
  },
12768
12837
  };
@@ -12776,7 +12845,7 @@ const YEAR_START = {
12776
12845
  computeFormat: () => "m/d/yyyy",
12777
12846
  compute: function (date) {
12778
12847
  const year = YEAR.compute(date);
12779
- const jsDate = new Date(year, 0, 1);
12848
+ const jsDate = new DateTime(year, 0, 1);
12780
12849
  return jsDateToRoundNumber(jsDate);
12781
12850
  },
12782
12851
  };
@@ -12790,7 +12859,7 @@ const YEAR_END = {
12790
12859
  computeFormat: () => "m/d/yyyy",
12791
12860
  compute: function (date) {
12792
12861
  const year = YEAR.compute(date);
12793
- const jsDate = new Date(year + 1, 0, 0);
12862
+ const jsDate = new DateTime(year + 1, 0, 0);
12794
12863
  return jsDateToRoundNumber(jsDate);
12795
12864
  },
12796
12865
  };
@@ -12838,8 +12907,8 @@ const DEFAULT_DELTA_ARG = 0;
12838
12907
  const DELTA = {
12839
12908
  description: _lt("Compare two numeric values, returning 1 if they're equal."),
12840
12909
  args: [
12841
- arg(" (number)", _lt("The first number to compare.")),
12842
- arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
12910
+ arg("number1 (number)", _lt("The first number to compare.")),
12911
+ arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
12843
12912
  ],
12844
12913
  returns: ["NUMBER"],
12845
12914
  compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
@@ -12925,7 +12994,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
12925
12994
  function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
12926
12995
  const startDate = toJsDate(settlement);
12927
12996
  const endDate = toJsDate(maturity);
12928
- const startDatePlusOneYear = new Date(startDate);
12997
+ const startDatePlusOneYear = toJsDate(settlement);
12929
12998
  startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
12930
12999
  assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
12931
13000
  }
@@ -13060,7 +13129,7 @@ const AMORLINC = {
13060
13129
  arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
13061
13130
  arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
13062
13131
  arg("rate (number)", _lt("The deprecation rate.")),
13063
- arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
13132
+ arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
13064
13133
  ],
13065
13134
  returns: ["NUMBER"],
13066
13135
  compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
@@ -16043,8 +16112,8 @@ const MID = {
16043
16112
  description: _lt("A segment of a string."),
16044
16113
  args: [
16045
16114
  arg("text (string)", _lt("The string to extract a segment from.")),
16046
- arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
16047
- arg(" (number)", _lt("The length of the segment to extract.")),
16115
+ arg("starting_at (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
16116
+ arg("extract_length (number)", _lt("The length of the segment to extract.")),
16048
16117
  ],
16049
16118
  returns: ["STRING"],
16050
16119
  compute: function (text, starting_at, extract_length) {
@@ -16918,7 +16987,7 @@ function interactiveFreezeColumnsRows(env, dimension, base) {
16918
16987
  const sheetId = env.model.getters.getActiveSheetId();
16919
16988
  const cmd = dimension === "COL" ? "FREEZE_COLUMNS" : "FREEZE_ROWS";
16920
16989
  const result = env.model.dispatch(cmd, { sheetId, quantity: base });
16921
- if (result.isCancelledBecause(65 /* CommandResult.MergeOverlap */)) {
16990
+ if (result.isCancelledBecause(66 /* CommandResult.MergeOverlap */)) {
16922
16991
  env.raiseError(MergeErrorMessage);
16923
16992
  }
16924
16993
  }
@@ -17713,10 +17782,10 @@ const arrowMap = {
17713
17782
  function updateSelectionWithArrowKeys(ev, selection) {
17714
17783
  const direction = arrowMap[ev.key];
17715
17784
  if (ev.shiftKey) {
17716
- selection.resizeAnchorZone(direction, ev.ctrlKey ? "end" : 1);
17785
+ selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
17717
17786
  }
17718
17787
  else {
17719
- selection.moveAnchorCell(direction, ev.ctrlKey ? "end" : 1);
17788
+ selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
17720
17789
  }
17721
17790
  }
17722
17791
 
@@ -17941,10 +18010,10 @@ class LineBarPieConfigPanel extends owl.Component {
17941
18010
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
17942
18011
  }
17943
18012
  get isDatasetInvalid() {
17944
- return !!this.state.datasetDispatchResult?.isCancelledBecause(32 /* CommandResult.InvalidDataSet */);
18013
+ return !!this.state.datasetDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidDataSet */);
17945
18014
  }
17946
18015
  get isLabelInvalid() {
17947
- return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
18016
+ return !!this.state.labelsDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidLabelRange */);
17948
18017
  }
17949
18018
  onUpdateDataSetsHaveTitle(ev) {
17950
18019
  this.props.updateChart(this.props.figureId, {
@@ -18386,7 +18455,7 @@ class GaugeChartConfigPanel extends owl.Component {
18386
18455
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18387
18456
  }
18388
18457
  get isDataRangeInvalid() {
18389
- return !!this.state.dataRangeDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidGaugeDataRange */);
18458
+ return !!this.state.dataRangeDispatchResult?.isCancelledBecause(37 /* CommandResult.InvalidGaugeDataRange */);
18390
18459
  }
18391
18460
  onDataRangeChanged(ranges) {
18392
18461
  this.dataRange = ranges[0];
@@ -18460,25 +18529,25 @@ class GaugeChartDesignPanel extends owl.Component {
18460
18529
  });
18461
18530
  }
18462
18531
  isRangeMinInvalid() {
18463
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(37 /* CommandResult.EmptyGaugeRangeMin */) ||
18464
- this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.GaugeRangeMinNaN */) ||
18465
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18532
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(38 /* CommandResult.EmptyGaugeRangeMin */) ||
18533
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.GaugeRangeMinNaN */) ||
18534
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18466
18535
  }
18467
18536
  isRangeMaxInvalid() {
18468
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(39 /* CommandResult.EmptyGaugeRangeMax */) ||
18469
- this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.GaugeRangeMaxNaN */) ||
18470
- this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18537
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(40 /* CommandResult.EmptyGaugeRangeMax */) ||
18538
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(41 /* CommandResult.GaugeRangeMaxNaN */) ||
18539
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeRangeMinBiggerThanRangeMax */));
18471
18540
  }
18472
18541
  // ---------------------------------------------------------------------------
18473
18542
  // COLOR_SECTION_TEMPLATE
18474
18543
  // ---------------------------------------------------------------------------
18475
18544
  get isLowerInflectionPointInvalid() {
18476
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(42 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
18477
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
18545
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeLowerInflectionPointNaN */) ||
18546
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18478
18547
  }
18479
18548
  get isUpperInflectionPointInvalid() {
18480
- return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(43 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
18481
- this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeLowerBiggerThanUpper */));
18549
+ return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause(44 /* CommandResult.GaugeUpperInflectionPointNaN */) ||
18550
+ this.state.sectionRuleDispatchResult?.isCancelledBecause(45 /* CommandResult.GaugeLowerBiggerThanUpper */));
18482
18551
  }
18483
18552
  updateInflectionPointValue(attr, ev) {
18484
18553
  const sectionRule = deepCopy(this.props.definition.sectionRule);
@@ -18586,10 +18655,10 @@ class ScorecardChartConfigPanel extends owl.Component {
18586
18655
  return cancelledReasons.map((error) => ChartTerms.Errors[error] || ChartTerms.Errors.Unexpected);
18587
18656
  }
18588
18657
  get isKeyValueInvalid() {
18589
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(34 /* CommandResult.InvalidScorecardKeyValue */);
18658
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardKeyValue */);
18590
18659
  }
18591
18660
  get isBaselineInvalid() {
18592
- return !!this.state.keyValueDispatchResult?.isCancelledBecause(35 /* CommandResult.InvalidScorecardBaseline */);
18661
+ return !!this.state.keyValueDispatchResult?.isCancelledBecause(36 /* CommandResult.InvalidScorecardBaseline */);
18593
18662
  }
18594
18663
  onKeyValueRangeChanged(ranges) {
18595
18664
  this.keyValue = ranges[0];
@@ -19449,10 +19518,10 @@ class ConditionalFormattingPanel extends owl.Component {
19449
19518
  * Cell Is Rule
19450
19519
  ****************************************************************************/
19451
19520
  get isValue1Invalid() {
19452
- return !!this.state.errors?.includes(51 /* CommandResult.FirstArgMissing */);
19521
+ return !!this.state.errors?.includes(52 /* CommandResult.FirstArgMissing */);
19453
19522
  }
19454
19523
  get isValue2Invalid() {
19455
- return !!this.state.errors?.includes(52 /* CommandResult.SecondArgMissing */);
19524
+ return !!this.state.errors?.includes(53 /* CommandResult.SecondArgMissing */);
19456
19525
  }
19457
19526
  toggleStyle(tool) {
19458
19527
  const style = this.state.rules.cellIs.style;
@@ -19469,17 +19538,17 @@ class ConditionalFormattingPanel extends owl.Component {
19469
19538
  isValueInvalid(threshold) {
19470
19539
  switch (threshold) {
19471
19540
  case "minimum":
19472
- return (this.state.errors.includes(58 /* CommandResult.MinInvalidFormula */) ||
19473
- this.state.errors.includes(50 /* CommandResult.MinBiggerThanMid */) ||
19474
- this.state.errors.includes(47 /* CommandResult.MinBiggerThanMax */) ||
19475
- this.state.errors.includes(53 /* CommandResult.MinNaN */));
19541
+ return (this.state.errors.includes(59 /* CommandResult.MinInvalidFormula */) ||
19542
+ this.state.errors.includes(51 /* CommandResult.MinBiggerThanMid */) ||
19543
+ this.state.errors.includes(48 /* CommandResult.MinBiggerThanMax */) ||
19544
+ this.state.errors.includes(54 /* CommandResult.MinNaN */));
19476
19545
  case "midpoint":
19477
- return (this.state.errors.includes(59 /* CommandResult.MidInvalidFormula */) ||
19478
- this.state.errors.includes(54 /* CommandResult.MidNaN */) ||
19479
- this.state.errors.includes(49 /* CommandResult.MidBiggerThanMax */));
19546
+ return (this.state.errors.includes(60 /* CommandResult.MidInvalidFormula */) ||
19547
+ this.state.errors.includes(55 /* CommandResult.MidNaN */) ||
19548
+ this.state.errors.includes(50 /* CommandResult.MidBiggerThanMax */));
19480
19549
  case "maximum":
19481
- return (this.state.errors.includes(60 /* CommandResult.MaxInvalidFormula */) ||
19482
- this.state.errors.includes(55 /* CommandResult.MaxNaN */));
19550
+ return (this.state.errors.includes(61 /* CommandResult.MaxInvalidFormula */) ||
19551
+ this.state.errors.includes(56 /* CommandResult.MaxNaN */));
19483
19552
  default:
19484
19553
  return false;
19485
19554
  }
@@ -19527,13 +19596,13 @@ class ConditionalFormattingPanel extends owl.Component {
19527
19596
  isInflectionPointInvalid(inflectionPoint) {
19528
19597
  switch (inflectionPoint) {
19529
19598
  case "lowerInflectionPoint":
19530
- return (this.state.errors.includes(57 /* CommandResult.ValueLowerInflectionNaN */) ||
19531
- this.state.errors.includes(62 /* CommandResult.ValueLowerInvalidFormula */) ||
19532
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
19599
+ return (this.state.errors.includes(58 /* CommandResult.ValueLowerInflectionNaN */) ||
19600
+ this.state.errors.includes(63 /* CommandResult.ValueLowerInvalidFormula */) ||
19601
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19533
19602
  case "upperInflectionPoint":
19534
- return (this.state.errors.includes(56 /* CommandResult.ValueUpperInflectionNaN */) ||
19535
- this.state.errors.includes(61 /* CommandResult.ValueUpperInvalidFormula */) ||
19536
- this.state.errors.includes(48 /* CommandResult.LowerBiggerThanUpper */));
19603
+ return (this.state.errors.includes(57 /* CommandResult.ValueUpperInflectionNaN */) ||
19604
+ this.state.errors.includes(62 /* CommandResult.ValueUpperInvalidFormula */) ||
19605
+ this.state.errors.includes(49 /* CommandResult.LowerBiggerThanUpper */));
19537
19606
  default:
19538
19607
  return true;
19539
19608
  }
@@ -19844,7 +19913,7 @@ const SplitToColumnsInteractiveContent = {
19844
19913
  };
19845
19914
  function interactiveSplitToColumns(env, separator, addNewColumns) {
19846
19915
  let result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", { separator, addNewColumns });
19847
- if (result.isCancelledBecause(90 /* CommandResult.SplitWillOverwriteContent */)) {
19916
+ if (result.isCancelledBecause(91 /* CommandResult.SplitWillOverwriteContent */)) {
19848
19917
  env.askConfirmation(SplitToColumnsInteractiveContent.SplitIsDestructive, () => {
19849
19918
  result = env.model.dispatch("SPLIT_TEXT_INTO_COLUMNS", {
19850
19919
  separator,
@@ -19907,8 +19976,8 @@ class SplitIntoColumnsPanel extends owl.Component {
19907
19976
  const errors = new Set();
19908
19977
  for (const reason of cancelledReasons) {
19909
19978
  switch (reason) {
19910
- case 90 /* CommandResult.SplitWillOverwriteContent */:
19911
- case 89 /* CommandResult.EmptySplitSeparator */:
19979
+ case 91 /* CommandResult.SplitWillOverwriteContent */:
19980
+ case 90 /* CommandResult.EmptySplitSeparator */:
19912
19981
  break;
19913
19982
  default:
19914
19983
  errors.add(SplitToColumnsTerms.Errors[reason] || SplitToColumnsTerms.Errors.Unexpected);
@@ -19923,8 +19992,8 @@ class SplitIntoColumnsPanel extends owl.Component {
19923
19992
  addNewColumns: this.state.addNewColumns,
19924
19993
  force: false,
19925
19994
  }).reasons;
19926
- if (cancelledReasons.includes(90 /* CommandResult.SplitWillOverwriteContent */)) {
19927
- warnings.push(SplitToColumnsTerms.Errors[90 /* CommandResult.SplitWillOverwriteContent */]);
19995
+ if (cancelledReasons.includes(91 /* CommandResult.SplitWillOverwriteContent */)) {
19996
+ warnings.push(SplitToColumnsTerms.Errors[91 /* CommandResult.SplitWillOverwriteContent */]);
19928
19997
  }
19929
19998
  return warnings;
19930
19999
  }
@@ -22413,7 +22482,10 @@ class GridOverlay extends owl.Component {
22413
22482
  return;
22414
22483
  }
22415
22484
  const [col, row] = this.getCartesianCoordinates(ev);
22416
- this.props.onCellClicked(col, row, { shiftKey: ev.shiftKey, ctrlKey: ev.ctrlKey });
22485
+ this.props.onCellClicked(col, row, {
22486
+ expandZone: ev.shiftKey,
22487
+ addZone: isCtrlKey(ev),
22488
+ });
22417
22489
  }
22418
22490
  onDoubleClick(ev) {
22419
22491
  const [col, row] = this.getCartesianCoordinates(ev);
@@ -22486,6 +22558,7 @@ class AbstractResizer extends owl.Component {
22486
22558
  draggerShadowThickness: 0,
22487
22559
  delta: 0,
22488
22560
  base: 0,
22561
+ position: "before",
22489
22562
  });
22490
22563
  _computeHandleDisplay(ev) {
22491
22564
  const position = this._getEvOffset(ev);
@@ -22610,11 +22683,13 @@ class AbstractResizer extends owl.Component {
22610
22683
  this.state.draggerLinePosition = dimensions.start;
22611
22684
  this.state.draggerShadowPosition = dimensions.start;
22612
22685
  this.state.base = elementIndex;
22686
+ this.state.position = "before";
22613
22687
  }
22614
22688
  else if (this._getSelectedZoneEnd() < elementIndex) {
22615
22689
  this.state.draggerLinePosition = dimensions.end;
22616
22690
  this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
22617
- this.state.base = elementIndex + 1;
22691
+ this.state.base = elementIndex;
22692
+ this.state.position = "after";
22618
22693
  }
22619
22694
  else {
22620
22695
  this.state.draggerLinePosition = startDimensions.start;
@@ -22638,7 +22713,7 @@ class AbstractResizer extends owl.Component {
22638
22713
  this._increaseSelection(index);
22639
22714
  }
22640
22715
  else {
22641
- this._selectElement(index, ev.ctrlKey);
22716
+ this._selectElement(index, isCtrlKey(ev));
22642
22717
  }
22643
22718
  this.lastSelectedElementIndex = index;
22644
22719
  const mouseMoveSelect = (col, row) => {
@@ -22651,7 +22726,7 @@ class AbstractResizer extends owl.Component {
22651
22726
  const mouseUpSelect = () => {
22652
22727
  this.state.isSelecting = false;
22653
22728
  this.lastSelectedElementIndex = null;
22654
- this.env.model.dispatch(ev.ctrlKey ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
22729
+ this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
22655
22730
  this._computeGrabDisplay(ev);
22656
22731
  };
22657
22732
  dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
@@ -22797,13 +22872,14 @@ class ColResizer extends AbstractResizer {
22797
22872
  dimension: "COL",
22798
22873
  base: this.state.base,
22799
22874
  elements,
22875
+ position: this.state.position,
22800
22876
  });
22801
22877
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
22802
22878
  this.env.raiseError(MergeErrorMessage);
22803
22879
  }
22804
22880
  }
22805
- _selectElement(index, ctrlKey) {
22806
- this.env.model.selection.selectColumn(index, ctrlKey ? "newAnchor" : "overrideSelection");
22881
+ _selectElement(index, addDistinctHeader) {
22882
+ this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
22807
22883
  }
22808
22884
  _increaseSelection(index) {
22809
22885
  this.env.model.selection.selectColumn(index, "updateAnchor");
@@ -22970,13 +23046,14 @@ class RowResizer extends AbstractResizer {
22970
23046
  dimension: "ROW",
22971
23047
  base: this.state.base,
22972
23048
  elements,
23049
+ position: this.state.position,
22973
23050
  });
22974
23051
  if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
22975
23052
  this.env.raiseError(MergeErrorMessage);
22976
23053
  }
22977
23054
  }
22978
- _selectElement(index, ctrlKey) {
22979
- this.env.model.selection.selectRow(index, ctrlKey ? "newAnchor" : "overrideSelection");
23055
+ _selectElement(index, addDistinctHeader) {
23056
+ this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
22980
23057
  }
22981
23058
  _increaseSelection(index) {
22982
23059
  this.env.model.selection.selectRow(index, "updateAnchor");
@@ -23077,8 +23154,8 @@ function useWheelHandler(handler) {
23077
23154
  return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
23078
23155
  }
23079
23156
  const onMouseWheel = (ev) => {
23080
- const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
23081
- const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
23157
+ const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
23158
+ const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
23082
23159
  handler(deltaX, deltaY);
23083
23160
  };
23084
23161
  return onMouseWheel;
@@ -23780,8 +23857,8 @@ class Grid extends owl.Component {
23780
23857
  // ---------------------------------------------------------------------------
23781
23858
  // Zone selection with mouse
23782
23859
  // ---------------------------------------------------------------------------
23783
- onCellClicked(col, row, { ctrlKey, shiftKey }) {
23784
- if (ctrlKey) {
23860
+ onCellClicked(col, row, { addZone, expandZone }) {
23861
+ if (addZone) {
23785
23862
  this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
23786
23863
  }
23787
23864
  if (this.env.model.getters.hasOpenedPopover()) {
@@ -23790,10 +23867,10 @@ class Grid extends owl.Component {
23790
23867
  if (this.env.model.getters.getEditionMode() === "editing") {
23791
23868
  this.env.model.dispatch("STOP_EDITION");
23792
23869
  }
23793
- if (shiftKey) {
23870
+ if (expandZone) {
23794
23871
  this.env.model.selection.setAnchorCorner(col, row);
23795
23872
  }
23796
- else if (ctrlKey) {
23873
+ else if (addZone) {
23797
23874
  this.env.model.selection.addCellToSelection(col, row);
23798
23875
  }
23799
23876
  else {
@@ -23855,9 +23932,7 @@ class Grid extends owl.Component {
23855
23932
  return;
23856
23933
  }
23857
23934
  let keyDownString = "";
23858
- if (ev.ctrlKey)
23859
- keyDownString += "CTRL+";
23860
- if (ev.metaKey)
23935
+ if (isCtrlKey(ev))
23861
23936
  keyDownString += "CTRL+";
23862
23937
  if (ev.altKey)
23863
23938
  keyDownString += "ALT+";
@@ -25765,7 +25840,7 @@ const machine = {
25765
25840
  SPACE: goTo(State.RightRef),
25766
25841
  NUMBER: goTo(State.Found),
25767
25842
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
25768
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
25843
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
25769
25844
  },
25770
25845
  [State.RightColumnRef]: {
25771
25846
  SPACE: goTo(State.RightColumnRef),
@@ -25776,6 +25851,7 @@ const machine = {
25776
25851
  SPACE: goTo(State.RightRowRef),
25777
25852
  NUMBER: goTo(State.Found),
25778
25853
  REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
25854
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
25779
25855
  },
25780
25856
  [State.Found]: {},
25781
25857
  };
@@ -29443,7 +29519,7 @@ class BordersPlugin extends CorePlugin {
29443
29519
  const currentBorder = this.getCellBorder(cmd);
29444
29520
  const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
29445
29521
  if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
29446
- return 93 /* CommandResult.NoChanges */;
29522
+ return 94 /* CommandResult.NoChanges */;
29447
29523
  }
29448
29524
  return 0 /* CommandResult.Success */;
29449
29525
  }
@@ -29483,7 +29559,7 @@ class BordersPlugin extends CorePlugin {
29483
29559
  */
29484
29560
  function getBorderId(border) {
29485
29561
  for (let [key, value] of Object.entries(borders)) {
29486
- if (stringify(value) === stringify(border)) {
29562
+ if (deepEquals(value, border)) {
29487
29563
  return parseInt(key, 10);
29488
29564
  }
29489
29565
  }
@@ -29688,6 +29764,10 @@ class CellPlugin extends CorePlugin {
29688
29764
  format: cell.format ? getItemId(cell.format, formats) : undefined,
29689
29765
  content: cell.content || undefined,
29690
29766
  };
29767
+ // if there is a formula but no dependencies (maybe because the cell is in error), no need to recompute the formula text
29768
+ if (cell.isFormula && cell.dependencies.length) {
29769
+ cells[xc].content = this.buildFormulaContent(_sheet.id, cell, cell.dependencies, true);
29770
+ }
29691
29771
  }
29692
29772
  _sheet.cells = cells;
29693
29773
  }
@@ -29722,13 +29802,13 @@ class CellPlugin extends CorePlugin {
29722
29802
  /*
29723
29803
  * Reconstructs the original formula string based on a normalized form and its dependencies
29724
29804
  */
29725
- buildFormulaContent(sheetId, cell, dependencies) {
29805
+ buildFormulaContent(sheetId, cell, dependencies, useFixedZone = false) {
29726
29806
  const ranges = dependencies || cell.dependencies;
29727
29807
  let rangeIndex = 0;
29728
29808
  return concat(cell.compiledFormula.tokens.map((token) => {
29729
29809
  if (token.type === "REFERENCE") {
29730
29810
  const range = ranges[rangeIndex++];
29731
- return this.getters.getRangeString(range, sheetId);
29811
+ return this.getters.getRangeString(range, sheetId, useFixedZone);
29732
29812
  }
29733
29813
  return token.value;
29734
29814
  }));
@@ -29965,9 +30045,9 @@ class CellPlugin extends CorePlugin {
29965
30045
  checkUselessClearCell(cmd) {
29966
30046
  const cell = this.getters.getCell(cmd);
29967
30047
  if (!cell)
29968
- return 93 /* CommandResult.NoChanges */;
30048
+ return 94 /* CommandResult.NoChanges */;
29969
30049
  if (!cell.content && !cell.style && !cell.format) {
29970
- return 93 /* CommandResult.NoChanges */;
30050
+ return 94 /* CommandResult.NoChanges */;
29971
30051
  }
29972
30052
  return 0 /* CommandResult.Success */;
29973
30053
  }
@@ -30167,13 +30247,13 @@ class ChartPlugin extends CorePlugin {
30167
30247
  }
30168
30248
  checkChartDuplicate(cmd) {
30169
30249
  return this.getters.getFigureSheetId(cmd.id)
30170
- ? 84 /* CommandResult.DuplicatedChartId */
30250
+ ? 85 /* CommandResult.DuplicatedChartId */
30171
30251
  : 0 /* CommandResult.Success */;
30172
30252
  }
30173
30253
  checkChartExists(cmd) {
30174
30254
  return this.getters.getFigureSheetId(cmd.id)
30175
30255
  ? 0 /* CommandResult.Success */
30176
- : 85 /* CommandResult.ChartDoesNotExist */;
30256
+ : 86 /* CommandResult.ChartDoesNotExist */;
30177
30257
  }
30178
30258
  }
30179
30259
 
@@ -30278,7 +30358,13 @@ class ConditionalFormatPlugin extends CorePlugin {
30278
30358
  }
30279
30359
  }
30280
30360
  exportForExcel(data) {
30281
- this.export(data);
30361
+ if (data.sheets) {
30362
+ for (let sheet of data.sheets) {
30363
+ if (this.cfRules[sheet.id]) {
30364
+ sheet.conditionalFormats = this.cfRules[sheet.id].map((rule) => this.mapToConditionalFormat(sheet.id, rule, { useFixedReference: true }));
30365
+ }
30366
+ }
30367
+ }
30282
30368
  }
30283
30369
  // ---------------------------------------------------------------------------
30284
30370
  // Getters
@@ -30327,11 +30413,11 @@ class ConditionalFormatPlugin extends CorePlugin {
30327
30413
  // ---------------------------------------------------------------------------
30328
30414
  // Private
30329
30415
  // ---------------------------------------------------------------------------
30330
- mapToConditionalFormat(sheetId, cf) {
30416
+ mapToConditionalFormat(sheetId, cf, options = { useFixedReference: false }) {
30331
30417
  return {
30332
30418
  ...cf,
30333
30419
  ranges: cf.ranges.map((range) => {
30334
- return this.getters.getRangeString(range, sheetId);
30420
+ return this.getters.getRangeString(range, sheetId, options.useFixedReference);
30335
30421
  }),
30336
30422
  };
30337
30423
  }
@@ -30364,10 +30450,10 @@ class ConditionalFormatPlugin extends CorePlugin {
30364
30450
  return 27 /* CommandResult.InvalidSheetId */;
30365
30451
  const ruleIndex = this.cfRules[sheetId].findIndex((cf) => cf.id === cfId);
30366
30452
  if (ruleIndex === -1)
30367
- return 71 /* CommandResult.InvalidConditionalFormatId */;
30453
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30368
30454
  const cfIndex2 = direction === "up" ? ruleIndex - 1 : ruleIndex + 1;
30369
30455
  if (cfIndex2 < 0 || cfIndex2 >= this.cfRules[sheetId].length) {
30370
- return 71 /* CommandResult.InvalidConditionalFormatId */;
30456
+ return 72 /* CommandResult.InvalidConditionalFormatId */;
30371
30457
  }
30372
30458
  return 0 /* CommandResult.Success */;
30373
30459
  }
@@ -30408,10 +30494,10 @@ class ConditionalFormatPlugin extends CorePlugin {
30408
30494
  const errors = [];
30409
30495
  const isEmpty = (value) => value === undefined || value === "";
30410
30496
  if (expectedNumber >= 1 && isEmpty(rule.values[0])) {
30411
- errors.push(51 /* CommandResult.FirstArgMissing */);
30497
+ errors.push(52 /* CommandResult.FirstArgMissing */);
30412
30498
  }
30413
30499
  if (expectedNumber >= 2 && isEmpty(rule.values[1])) {
30414
- errors.push(52 /* CommandResult.SecondArgMissing */);
30500
+ errors.push(53 /* CommandResult.SecondArgMissing */);
30415
30501
  }
30416
30502
  return errors.length ? errors : 0 /* CommandResult.Success */;
30417
30503
  }
@@ -30423,15 +30509,15 @@ class ConditionalFormatPlugin extends CorePlugin {
30423
30509
  (threshold.value === "" || isNaN(threshold.value))) {
30424
30510
  switch (thresholdName) {
30425
30511
  case "min":
30426
- return 53 /* CommandResult.MinNaN */;
30512
+ return 54 /* CommandResult.MinNaN */;
30427
30513
  case "max":
30428
- return 55 /* CommandResult.MaxNaN */;
30514
+ return 56 /* CommandResult.MaxNaN */;
30429
30515
  case "mid":
30430
- return 54 /* CommandResult.MidNaN */;
30516
+ return 55 /* CommandResult.MidNaN */;
30431
30517
  case "upperInflectionPoint":
30432
- return 56 /* CommandResult.ValueUpperInflectionNaN */;
30518
+ return 57 /* CommandResult.ValueUpperInflectionNaN */;
30433
30519
  case "lowerInflectionPoint":
30434
- return 57 /* CommandResult.ValueLowerInflectionNaN */;
30520
+ return 58 /* CommandResult.ValueLowerInflectionNaN */;
30435
30521
  }
30436
30522
  }
30437
30523
  return 0 /* CommandResult.Success */;
@@ -30445,15 +30531,15 @@ class ConditionalFormatPlugin extends CorePlugin {
30445
30531
  catch (error) {
30446
30532
  switch (thresholdName) {
30447
30533
  case "min":
30448
- return 58 /* CommandResult.MinInvalidFormula */;
30534
+ return 59 /* CommandResult.MinInvalidFormula */;
30449
30535
  case "max":
30450
- return 60 /* CommandResult.MaxInvalidFormula */;
30536
+ return 61 /* CommandResult.MaxInvalidFormula */;
30451
30537
  case "mid":
30452
- return 59 /* CommandResult.MidInvalidFormula */;
30538
+ return 60 /* CommandResult.MidInvalidFormula */;
30453
30539
  case "upperInflectionPoint":
30454
- return 61 /* CommandResult.ValueUpperInvalidFormula */;
30540
+ return 62 /* CommandResult.ValueUpperInvalidFormula */;
30455
30541
  case "lowerInflectionPoint":
30456
- return 62 /* CommandResult.ValueLowerInvalidFormula */;
30542
+ return 63 /* CommandResult.ValueLowerInvalidFormula */;
30457
30543
  }
30458
30544
  }
30459
30545
  return 0 /* CommandResult.Success */;
@@ -30470,7 +30556,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30470
30556
  if (["number", "percentage", "percentile"].includes(rule.lowerInflectionPoint.type) &&
30471
30557
  rule.lowerInflectionPoint.type === rule.upperInflectionPoint.type &&
30472
30558
  Number(minValue) > Number(maxValue)) {
30473
- return 48 /* CommandResult.LowerBiggerThanUpper */;
30559
+ return 49 /* CommandResult.LowerBiggerThanUpper */;
30474
30560
  }
30475
30561
  return 0 /* CommandResult.Success */;
30476
30562
  }
@@ -30480,7 +30566,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30480
30566
  if (["number", "percentage", "percentile"].includes(rule.minimum.type) &&
30481
30567
  rule.minimum.type === rule.maximum.type &&
30482
30568
  stringToNumber(minValue) >= stringToNumber(maxValue)) {
30483
- return 47 /* CommandResult.MinBiggerThanMax */;
30569
+ return 48 /* CommandResult.MinBiggerThanMax */;
30484
30570
  }
30485
30571
  return 0 /* CommandResult.Success */;
30486
30572
  }
@@ -30491,7 +30577,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30491
30577
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30492
30578
  rule.midpoint.type === rule.maximum.type &&
30493
30579
  stringToNumber(midValue) >= stringToNumber(maxValue)) {
30494
- return 49 /* CommandResult.MidBiggerThanMax */;
30580
+ return 50 /* CommandResult.MidBiggerThanMax */;
30495
30581
  }
30496
30582
  return 0 /* CommandResult.Success */;
30497
30583
  }
@@ -30502,7 +30588,7 @@ class ConditionalFormatPlugin extends CorePlugin {
30502
30588
  ["number", "percentage", "percentile"].includes(rule.midpoint.type) &&
30503
30589
  rule.minimum.type === rule.midpoint.type &&
30504
30590
  stringToNumber(minValue) >= stringToNumber(midValue)) {
30505
- return 50 /* CommandResult.MinBiggerThanMid */;
30591
+ return 51 /* CommandResult.MinBiggerThanMid */;
30506
30592
  }
30507
30593
  return 0 /* CommandResult.Success */;
30508
30594
  }
@@ -30632,13 +30718,13 @@ class FigurePlugin extends CorePlugin {
30632
30718
  }
30633
30719
  checkFigureExists(sheetId, figureId) {
30634
30720
  if (this.figures[sheetId]?.[figureId] === undefined) {
30635
- return 70 /* CommandResult.FigureDoesNotExist */;
30721
+ return 71 /* CommandResult.FigureDoesNotExist */;
30636
30722
  }
30637
30723
  return 0 /* CommandResult.Success */;
30638
30724
  }
30639
30725
  checkFigureDuplicate(figureId) {
30640
30726
  if (Object.values(this.figures).find((sheet) => sheet?.[figureId])) {
30641
- return 82 /* CommandResult.DuplicatedFigureId */;
30727
+ return 83 /* CommandResult.DuplicatedFigureId */;
30642
30728
  }
30643
30729
  return 0 /* CommandResult.Success */;
30644
30730
  }
@@ -30748,12 +30834,12 @@ class FiltersPlugin extends CorePlugin {
30748
30834
  switch (cmd.type) {
30749
30835
  case "CREATE_FILTER_TABLE":
30750
30836
  if (!areZonesContinuous(...cmd.target)) {
30751
- return 81 /* CommandResult.NonContinuousTargets */;
30837
+ return 82 /* CommandResult.NonContinuousTargets */;
30752
30838
  }
30753
30839
  const zone = union(...cmd.target);
30754
30840
  const checkFilterOverlap = () => {
30755
30841
  if (this.getFilterTables(cmd.sheetId).some((filter) => overlap(filter.zone, zone))) {
30756
- return 78 /* CommandResult.FilterOverlap */;
30842
+ return 79 /* CommandResult.FilterOverlap */;
30757
30843
  }
30758
30844
  return 0 /* CommandResult.Success */;
30759
30845
  };
@@ -30761,7 +30847,7 @@ class FiltersPlugin extends CorePlugin {
30761
30847
  const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, zone);
30762
30848
  for (let merge of mergesInTarget) {
30763
30849
  if (overlap(zone, merge)) {
30764
- return 80 /* CommandResult.MergeInFilter */;
30850
+ return 81 /* CommandResult.MergeInFilter */;
30765
30851
  }
30766
30852
  }
30767
30853
  return 0 /* CommandResult.Success */;
@@ -30771,7 +30857,7 @@ class FiltersPlugin extends CorePlugin {
30771
30857
  for (let merge of cmd.target) {
30772
30858
  for (let filterTable of this.getFilterTables(cmd.sheetId)) {
30773
30859
  if (overlap(filterTable.zone, merge)) {
30774
- return 80 /* CommandResult.MergeInFilter */;
30860
+ return 81 /* CommandResult.MergeInFilter */;
30775
30861
  }
30776
30862
  }
30777
30863
  }
@@ -31256,10 +31342,10 @@ class HeaderVisibilityPlugin extends CorePlugin {
31256
31342
  : this.getters.getNumberRows(cmd.sheetId);
31257
31343
  const hiddenElements = new Set((hiddenGroup || []).flat().concat(cmd.elements));
31258
31344
  if (hiddenElements.size >= elements) {
31259
- return 66 /* CommandResult.TooManyHiddenElements */;
31345
+ return 67 /* CommandResult.TooManyHiddenElements */;
31260
31346
  }
31261
31347
  else if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
31262
- return 86 /* CommandResult.InvalidHeaderIndex */;
31348
+ return 87 /* CommandResult.InvalidHeaderIndex */;
31263
31349
  }
31264
31350
  else {
31265
31351
  return 0 /* CommandResult.Success */;
@@ -31802,7 +31888,7 @@ class MergePlugin extends CorePlugin {
31802
31888
  for (const zone of target) {
31803
31889
  for (const zone2 of target) {
31804
31890
  if (zone !== zone2 && overlap(zone, zone2)) {
31805
- return 65 /* CommandResult.MergeOverlap */;
31891
+ return 66 /* CommandResult.MergeOverlap */;
31806
31892
  }
31807
31893
  }
31808
31894
  }
@@ -31816,7 +31902,7 @@ class MergePlugin extends CorePlugin {
31816
31902
  for (const zone of target) {
31817
31903
  if ((zone.left < xSplit && zone.right >= xSplit) ||
31818
31904
  (zone.top < ySplit && zone.bottom >= ySplit)) {
31819
- return 75 /* CommandResult.FrozenPaneOverlap */;
31905
+ return 76 /* CommandResult.FrozenPaneOverlap */;
31820
31906
  }
31821
31907
  }
31822
31908
  return 0 /* CommandResult.Success */;
@@ -32274,8 +32360,9 @@ class RangeAdapter {
32274
32360
  *
32275
32361
  * @param range the range (received from getRangeFromXC or getRangeFromZone)
32276
32362
  * @param forSheetId the id of the sheet where the range string is supposed to be used.
32363
+ * @param [useFixedZone=false] if true, the range will be returned with fixed row and column
32277
32364
  */
32278
- getRangeString(range, forSheetId) {
32365
+ getRangeString(range, forSheetId, useFixedZone = false) {
32279
32366
  if (!range) {
32280
32367
  return INCORRECT_RANGE_STRING;
32281
32368
  }
@@ -32302,7 +32389,7 @@ class RangeAdapter {
32302
32389
  if (prefixSheet && !sheetName) {
32303
32390
  return INCORRECT_RANGE_STRING;
32304
32391
  }
32305
- let rangeString = this.getRangePartString(rangeImpl, 0);
32392
+ let rangeString = this.getRangePartString(rangeImpl, 0, useFixedZone);
32306
32393
  if (rangeImpl.parts && rangeImpl.parts.length === 2) {
32307
32394
  // this if converts A2:A2 into A2 except if any part of the original range had fixed row or column (with $)
32308
32395
  if (rangeImpl.zone.top !== rangeImpl.zone.bottom ||
@@ -32312,7 +32399,7 @@ class RangeAdapter {
32312
32399
  rangeImpl.parts[1].rowFixed ||
32313
32400
  rangeImpl.parts[1].colFixed) {
32314
32401
  rangeString += ":";
32315
- rangeString += this.getRangePartString(rangeImpl, 1);
32402
+ rangeString += this.getRangePartString(rangeImpl, 1, useFixedZone);
32316
32403
  }
32317
32404
  }
32318
32405
  return `${prefixSheet ? sheetName + "!" : ""}${rangeString}`;
@@ -32342,13 +32429,13 @@ class RangeAdapter {
32342
32429
  /**
32343
32430
  * Get a Xc string that represent a part of a range
32344
32431
  */
32345
- getRangePartString(range, part) {
32346
- const colFixed = range.parts && range.parts[part].colFixed ? "$" : "";
32432
+ getRangePartString(range, part, useFixedZone = false) {
32433
+ const colFixed = range.parts && range.parts[part]?.colFixed ? "$" : "";
32347
32434
  const col = part === 0 ? numberToLetters(range.zone.left) : numberToLetters(range.zone.right);
32348
- const rowFixed = range.parts && range.parts[part].rowFixed ? "$" : "";
32435
+ const rowFixed = range.parts && range.parts[part]?.rowFixed ? "$" : "";
32349
32436
  const row = part === 0 ? String(range.zone.top + 1) : String(range.zone.bottom + 1);
32350
32437
  let str = "";
32351
- if (range.isFullCol) {
32438
+ if (range.isFullCol && !useFixedZone) {
32352
32439
  if (part === 0 && range.unboundedZone.hasHeader) {
32353
32440
  str = colFixed + col + rowFixed + row;
32354
32441
  }
@@ -32356,7 +32443,7 @@ class RangeAdapter {
32356
32443
  str = colFixed + col;
32357
32444
  }
32358
32445
  }
32359
- else if (range.isFullRow) {
32446
+ else if (range.isFullRow && !useFixedZone) {
32360
32447
  if (part === 0 && range.unboundedZone.hasHeader) {
32361
32448
  str = colFixed + col + rowFixed + row;
32362
32449
  }
@@ -32451,11 +32538,11 @@ class SheetPlugin extends CorePlugin {
32451
32538
  const elements = cmd.dimension === "COL"
32452
32539
  ? this.getNumberCols(cmd.sheetId)
32453
32540
  : this.getNumberRows(cmd.sheetId);
32454
- if (cmd.base < 0 || cmd.base > elements) {
32455
- return 86 /* CommandResult.InvalidHeaderIndex */;
32541
+ if (cmd.base < 0 || cmd.base >= elements) {
32542
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32456
32543
  }
32457
32544
  else if (cmd.quantity <= 0) {
32458
- return 87 /* CommandResult.InvalidQuantity */;
32545
+ return 88 /* CommandResult.InvalidQuantity */;
32459
32546
  }
32460
32547
  return 0 /* CommandResult.Success */;
32461
32548
  case "REMOVE_COLUMNS_ROWS": {
@@ -32463,7 +32550,7 @@ class SheetPlugin extends CorePlugin {
32463
32550
  ? this.getNumberCols(cmd.sheetId)
32464
32551
  : this.getNumberRows(cmd.sheetId);
32465
32552
  if (Math.min(...cmd.elements) < 0 || Math.max(...cmd.elements) > elements) {
32466
- return 86 /* CommandResult.InvalidHeaderIndex */;
32553
+ return 87 /* CommandResult.InvalidHeaderIndex */;
32467
32554
  }
32468
32555
  else if (this.checkElementsIncludeAllNonFrozenHeaders(cmd.sheetId, cmd.dimension, cmd.elements)) {
32469
32556
  return 8 /* CommandResult.NotEnoughElements */;
@@ -32929,18 +33016,18 @@ class SheetPlugin extends CorePlugin {
32929
33016
  checkRowFreezeQuantity(cmd) {
32930
33017
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberRows(cmd.sheetId)
32931
33018
  ? 0 /* CommandResult.Success */
32932
- : 74 /* CommandResult.InvalidFreezeQuantity */;
33019
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
32933
33020
  }
32934
33021
  checkColFreezeQuantity(cmd) {
32935
33022
  return cmd.quantity >= 1 && cmd.quantity < this.getNumberCols(cmd.sheetId)
32936
33023
  ? 0 /* CommandResult.Success */
32937
- : 74 /* CommandResult.InvalidFreezeQuantity */;
33024
+ : 75 /* CommandResult.InvalidFreezeQuantity */;
32938
33025
  }
32939
33026
  checkRowFreezeOverlapMerge(cmd) {
32940
33027
  const merges = this.getters.getMerges(cmd.sheetId);
32941
33028
  for (let merge of merges) {
32942
33029
  if (merge.top < cmd.quantity && cmd.quantity <= merge.bottom) {
32943
- return 65 /* CommandResult.MergeOverlap */;
33030
+ return 66 /* CommandResult.MergeOverlap */;
32944
33031
  }
32945
33032
  }
32946
33033
  return 0 /* CommandResult.Success */;
@@ -32949,7 +33036,7 @@ class SheetPlugin extends CorePlugin {
32949
33036
  const merges = this.getters.getMerges(cmd.sheetId);
32950
33037
  for (let merge of merges) {
32951
33038
  if (merge.left < cmd.quantity && cmd.quantity <= merge.right) {
32952
- return 65 /* CommandResult.MergeOverlap */;
33039
+ return 66 /* CommandResult.MergeOverlap */;
32953
33040
  }
32954
33041
  }
32955
33042
  return 0 /* CommandResult.Success */;
@@ -33484,13 +33571,18 @@ class EvaluationPlugin extends UIPlugin {
33484
33571
  // Getters
33485
33572
  // ---------------------------------------------------------------------------
33486
33573
  evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
33487
- const compiledFormula = compile(formulaString);
33488
- const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
33489
- const ranges = [];
33490
- for (let xc of compiledFormula.dependencies) {
33491
- ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
33574
+ try {
33575
+ const compiledFormula = compile(formulaString);
33576
+ const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
33577
+ const ranges = [];
33578
+ for (let xc of compiledFormula.dependencies) {
33579
+ ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
33580
+ }
33581
+ return compiledFormula.execute(ranges, ...params).value;
33582
+ }
33583
+ catch (error) {
33584
+ return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
33492
33585
  }
33493
- return compiledFormula.execute(ranges, ...params).value;
33494
33586
  }
33495
33587
  /**
33496
33588
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -33675,10 +33767,8 @@ class EvaluationPlugin extends UIPlugin {
33675
33767
  * that are actually present in the grid.
33676
33768
  */
33677
33769
  function range(range) {
33770
+ assertRangeValid(range);
33678
33771
  const sheetId = range.sheetId;
33679
- if (!isZoneValid(range.zone)) {
33680
- throw new InvalidReferenceError();
33681
- }
33682
33772
  // Performance issue: Avoid fetching data on positions that are out of the spreadsheet
33683
33773
  // e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
33684
33774
  const sheetZone = getters.getSheetZone(sheetId);
@@ -33713,23 +33803,26 @@ class EvaluationPlugin extends UIPlugin {
33713
33803
  * The `compute` of the formula's function must process it completely
33714
33804
  */
33715
33805
  function refFn(range, isMeta, functionName, paramNumber) {
33806
+ assertRangeValid(range);
33716
33807
  if (isMeta) {
33717
33808
  // Use zoneToXc of zone instead of getRangeString to avoid sending unbounded ranges
33718
33809
  return { value: zoneToXc(range.zone) };
33719
33810
  }
33720
- if (!isZoneValid(range.zone)) {
33721
- throw new InvalidReferenceError();
33722
- }
33723
33811
  // if the formula definition could have accepted a range, we would pass through the _range function and not here
33724
33812
  if (range.zone.bottom !== range.zone.top || range.zone.left !== range.zone.right) {
33725
33813
  throw new Error(paramNumber
33726
33814
  ? _lt("Function %s expects the parameter %s to be a single value or a single cell reference, not a range.", functionName.toString(), paramNumber.toString())
33727
33815
  : _lt("Function %s expects its parameters to be single values or single cell references, not ranges.", functionName.toString()));
33728
33816
  }
33817
+ return readCell(range);
33818
+ }
33819
+ function assertRangeValid(range) {
33820
+ if (!isZoneValid(range.zone)) {
33821
+ throw new InvalidReferenceError();
33822
+ }
33729
33823
  if (range.invalidSheetName) {
33730
33824
  throw new Error(_lt("Invalid sheet name: %s", range.invalidSheetName));
33731
33825
  }
33732
- return readCell(range);
33733
33826
  }
33734
33827
  return [refFn, range, evalContext];
33735
33828
  }
@@ -33915,39 +34008,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33915
34008
  this.computedIcons[sheetId] = {};
33916
34009
  const computedStyle = this.computedStyles[sheetId];
33917
34010
  for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
33918
- try {
33919
- switch (cf.rule.type) {
33920
- case "ColorScaleRule":
33921
- for (let range of cf.ranges) {
33922
- this.applyColorScale(range, cf.rule);
33923
- }
33924
- break;
33925
- case "IconSetRule":
33926
- for (let range of cf.ranges) {
33927
- this.applyIcon(range, cf.rule);
33928
- }
33929
- break;
33930
- default:
33931
- for (let ref of cf.ranges) {
33932
- const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
33933
- for (let row = zone.top; row <= zone.bottom; row++) {
33934
- for (let col = zone.left; col <= zone.right; col++) {
33935
- const pr = this.rulePredicate[cf.rule.type];
33936
- let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
33937
- if (pr && pr(cell, cf.rule)) {
33938
- if (!computedStyle[col])
33939
- computedStyle[col] = [];
33940
- // we must combine all the properties of all the CF rules applied to the given cell
33941
- computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
33942
- }
34011
+ switch (cf.rule.type) {
34012
+ case "ColorScaleRule":
34013
+ for (let range of cf.ranges) {
34014
+ this.applyColorScale(range, cf.rule);
34015
+ }
34016
+ break;
34017
+ case "IconSetRule":
34018
+ for (let range of cf.ranges) {
34019
+ this.applyIcon(range, cf.rule);
34020
+ }
34021
+ break;
34022
+ default:
34023
+ for (let ref of cf.ranges) {
34024
+ const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
34025
+ for (let row = zone.top; row <= zone.bottom; row++) {
34026
+ for (let col = zone.left; col <= zone.right; col++) {
34027
+ const pr = this.rulePredicate[cf.rule.type];
34028
+ let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
34029
+ if (pr && pr(cell, cf.rule)) {
34030
+ if (!computedStyle[col])
34031
+ computedStyle[col] = [];
34032
+ // we must combine all the properties of all the CF rules applied to the given cell
34033
+ computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
33943
34034
  }
33944
34035
  }
33945
34036
  }
33946
- break;
33947
- }
33948
- }
33949
- catch (_) {
33950
- // we don't care about the errors within the evaluation of a rule
34037
+ }
34038
+ break;
33951
34039
  }
33952
34040
  }
33953
34041
  }
@@ -33972,7 +34060,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
33972
34060
  return percentile(rangeValues, Number(threshold.value) / 100, true);
33973
34061
  case "formula":
33974
34062
  const value = threshold.value && this.getters.evaluateFormula(threshold.value);
33975
- return !(value instanceof Promise) ? value : null;
34063
+ return typeof value === "number" ? value : null;
33976
34064
  default:
33977
34065
  return null;
33978
34066
  }
@@ -34219,7 +34307,7 @@ class FilterEvaluationPlugin extends UIPlugin {
34219
34307
  switch (cmd.type) {
34220
34308
  case "UPDATE_FILTER":
34221
34309
  if (!this.getters.getFilterId(cmd)) {
34222
- return 79 /* CommandResult.FilterNotFound */;
34310
+ return 80 /* CommandResult.FilterNotFound */;
34223
34311
  }
34224
34312
  break;
34225
34313
  }
@@ -35189,7 +35277,7 @@ class SheetViewPlugin extends UIPlugin {
35189
35277
  }
35190
35278
  checkPositiveDimension(cmd) {
35191
35279
  if (cmd.width < 0 || cmd.height < 0) {
35192
- return 68 /* CommandResult.InvalidViewportSize */;
35280
+ return 69 /* CommandResult.InvalidViewportSize */;
35193
35281
  }
35194
35282
  return 0 /* CommandResult.Success */;
35195
35283
  }
@@ -35199,7 +35287,7 @@ class SheetViewPlugin extends UIPlugin {
35199
35287
  cmd.gridOffsetY === this.gridOffsetY &&
35200
35288
  cmd.width === width &&
35201
35289
  cmd.height === height) {
35202
- return 76 /* CommandResult.ValuesNotChanged */;
35290
+ return 77 /* CommandResult.ValuesNotChanged */;
35203
35291
  }
35204
35292
  return 0 /* CommandResult.Success */;
35205
35293
  }
@@ -35207,7 +35295,7 @@ class SheetViewPlugin extends UIPlugin {
35207
35295
  const pane = this.getMainInternalViewport(this.getters.getActiveSheetId());
35208
35296
  if ((!pane.canScrollHorizontally && offsetX > 0) ||
35209
35297
  (!pane.canScrollVertically && offsetY > 0)) {
35210
- return 69 /* CommandResult.InvalidScrollingDirection */;
35298
+ return 70 /* CommandResult.InvalidScrollingDirection */;
35211
35299
  }
35212
35300
  return 0 /* CommandResult.Success */;
35213
35301
  }
@@ -35462,7 +35550,7 @@ class AutofillPlugin extends UIPlugin {
35462
35550
  if (this.lastCellSelected.col !== undefined && this.lastCellSelected.row !== undefined) {
35463
35551
  return 0 /* CommandResult.Success */;
35464
35552
  }
35465
- return 45 /* CommandResult.InvalidAutofillSelection */;
35553
+ return 46 /* CommandResult.InvalidAutofillSelection */;
35466
35554
  case "AUTOFILL_AUTO":
35467
35555
  const zone = this.getters.getSelectedZone();
35468
35556
  return zone.top === zone.bottom
@@ -35621,19 +35709,21 @@ class AutofillPlugin extends UIPlugin {
35621
35709
  let col = zone.left;
35622
35710
  let row = zone.bottom;
35623
35711
  if (col > 0) {
35624
- let left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
35625
- while (left.type !== CellValueType.empty) {
35712
+ let leftPosition = { sheetId, col: col - 1, row };
35713
+ while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
35714
+ this.getters.getCell(leftPosition)?.content) {
35626
35715
  row += 1;
35627
- left = this.getters.getEvaluatedCell({ sheetId, col: col - 1, row });
35716
+ leftPosition = { sheetId, col: col - 1, row };
35628
35717
  }
35629
35718
  }
35630
35719
  if (row === zone.bottom) {
35631
35720
  col = zone.right;
35632
35721
  if (col <= this.getters.getNumberCols(sheetId)) {
35633
- let right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
35634
- while (right.type !== CellValueType.empty) {
35722
+ let rightPosition = { sheetId, col: col + 1, row };
35723
+ while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
35724
+ this.getters.getCell(rightPosition)?.content) {
35635
35725
  row += 1;
35636
- right = this.getters.getEvaluatedCell({ sheetId, col: col + 1, row });
35726
+ rightPosition = { sheetId, col: col + 1, row };
35637
35727
  }
35638
35728
  }
35639
35729
  }
@@ -36064,7 +36154,7 @@ class CellPopoverPlugin extends UIPlugin {
36064
36154
  cellPopoverRegistry.get(cmd.popoverType);
36065
36155
  }
36066
36156
  catch (error) {
36067
- return 72 /* CommandResult.InvalidCellPopover */;
36157
+ return 73 /* CommandResult.InvalidCellPopover */;
36068
36158
  }
36069
36159
  return 0 /* CommandResult.Success */;
36070
36160
  default:
@@ -38200,21 +38290,6 @@ class SelectionInputPlugin extends UIPlugin {
38200
38290
  // ---------------------------------------------------------------------------
38201
38291
  // Command Handling
38202
38292
  // ---------------------------------------------------------------------------
38203
- allowDispatch(cmd) {
38204
- switch (cmd.type) {
38205
- case "ADD_EMPTY_RANGE":
38206
- if (this.inputHasSingleRange && this.ranges.length === 1) {
38207
- return 30 /* CommandResult.MaximumRangesReached */;
38208
- }
38209
- break;
38210
- case "CHANGE_RANGE":
38211
- if (this.inputHasSingleRange && cmd.value.split(",").length > 1) {
38212
- return 30 /* CommandResult.MaximumRangesReached */;
38213
- }
38214
- break;
38215
- }
38216
- return 0 /* CommandResult.Success */;
38217
- }
38218
38293
  handleEvent(event) {
38219
38294
  const xc = zoneToXc(event.anchor.zone);
38220
38295
  const inputSheetId = this.activeSheet;
@@ -38430,6 +38505,15 @@ class SelectionInputsManagerPlugin extends UIPlugin {
38430
38505
  // Command Handling
38431
38506
  // ---------------------------------------------------------------------------
38432
38507
  allowDispatch(cmd) {
38508
+ switch (cmd.type) {
38509
+ case "FOCUS_RANGE":
38510
+ case "CHANGE_RANGE":
38511
+ case "ADD_EMPTY_RANGE":
38512
+ case "REMOVE_RANGE":
38513
+ if (!this.inputs[cmd.id]) {
38514
+ return 31 /* CommandResult.InvalidInputId */;
38515
+ }
38516
+ }
38433
38517
  switch (cmd.type) {
38434
38518
  case "FOCUS_RANGE":
38435
38519
  const index = this.currentInput?.getIndex(cmd.rangeId);
@@ -38437,9 +38521,19 @@ class SelectionInputsManagerPlugin extends UIPlugin {
38437
38521
  return 29 /* CommandResult.InputAlreadyFocused */;
38438
38522
  }
38439
38523
  break;
38440
- }
38441
- if (this.currentInput) {
38442
- return this.currentInput.allowDispatch(cmd);
38524
+ case "ADD_EMPTY_RANGE":
38525
+ const input = this.inputs[cmd.id];
38526
+ if (input.inputHasSingleRange && input.ranges.length === 1) {
38527
+ return 30 /* CommandResult.MaximumRangesReached */;
38528
+ }
38529
+ break;
38530
+ case "CHANGE_RANGE": {
38531
+ const input = this.inputs[cmd.id];
38532
+ if (input.inputHasSingleRange && cmd.value.split(",").length > 1) {
38533
+ return 30 /* CommandResult.MaximumRangesReached */;
38534
+ }
38535
+ break;
38536
+ }
38443
38537
  }
38444
38538
  return 0 /* CommandResult.Success */;
38445
38539
  }
@@ -38563,7 +38657,7 @@ class SortPlugin extends UIPlugin {
38563
38657
  /*Test the presence of single cells*/
38564
38658
  const singleCells = positions(zone).some(({ col, row }) => !this.getters.isInMerge({ sheetId, col, row }));
38565
38659
  if (singleCells) {
38566
- return 63 /* CommandResult.InvalidSortZone */;
38660
+ return 64 /* CommandResult.InvalidSortZone */;
38567
38661
  }
38568
38662
  return 0 /* CommandResult.Success */;
38569
38663
  }
@@ -38582,7 +38676,7 @@ class SortPlugin extends UIPlugin {
38582
38676
  ];
38583
38677
  return widthCurrent === widthFirst && heightCurrent === heightFirst;
38584
38678
  })) {
38585
- return 63 /* CommandResult.InvalidSortZone */;
38679
+ return 64 /* CommandResult.InvalidSortZone */;
38586
38680
  }
38587
38681
  return 0 /* CommandResult.Success */;
38588
38682
  }
@@ -39085,7 +39179,7 @@ class SheetUIPlugin extends UIPlugin {
39085
39179
  const sheetId = "sheetId" in cmd ? cmd.sheetId : this.getters.tryGetActiveSheetId();
39086
39180
  const zones = this.getters.getCommandZones(cmd);
39087
39181
  if (!sheetId && zones.length > 0) {
39088
- return 92 /* CommandResult.NoActiveSheet */;
39182
+ return 93 /* CommandResult.NoActiveSheet */;
39089
39183
  }
39090
39184
  if (sheetId && zones.length > 0) {
39091
39185
  return this.getters.checkZonesExistInSheet(sheetId, zones);
@@ -39567,13 +39661,13 @@ class SplitToColumnsPlugin extends UIPlugin {
39567
39661
  }
39568
39662
  checkSingleColSelected() {
39569
39663
  if (!this.getters.isSingleColSelected()) {
39570
- return 88 /* CommandResult.MoreThanOneColumnSelected */;
39664
+ return 89 /* CommandResult.MoreThanOneColumnSelected */;
39571
39665
  }
39572
39666
  return 0 /* CommandResult.Success */;
39573
39667
  }
39574
39668
  checkNonEmptySelector(cmd) {
39575
39669
  if (cmd.separator === "") {
39576
- return 89 /* CommandResult.EmptySplitSeparator */;
39670
+ return 90 /* CommandResult.EmptySplitSeparator */;
39577
39671
  }
39578
39672
  return 0 /* CommandResult.Success */;
39579
39673
  }
@@ -39584,7 +39678,7 @@ class SplitToColumnsPlugin extends UIPlugin {
39584
39678
  const selection = this.getters.getSelectedZones()[0];
39585
39679
  const splitted = this.getSplittedCols(selection, cmd.separator);
39586
39680
  if (this.willSplittedColsOverwriteContent(selection, splitted)) {
39587
- return 90 /* CommandResult.SplitWillOverwriteContent */;
39681
+ return 91 /* CommandResult.SplitWillOverwriteContent */;
39588
39682
  }
39589
39683
  return 0 /* CommandResult.Success */;
39590
39684
  }
@@ -39595,7 +39689,7 @@ class SplitToColumnsPlugin extends UIPlugin {
39595
39689
  return 0 /* CommandResult.Success */;
39596
39690
  }
39597
39691
  }
39598
- return 91 /* CommandResult.NoSplitSeparatorInSelection */;
39692
+ return 92 /* CommandResult.NoSplitSeparatorInSelection */;
39599
39693
  }
39600
39694
  }
39601
39695
 
@@ -39742,7 +39836,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39742
39836
  for (const zone of this.getPasteZones(target)) {
39743
39837
  if ((zone.left < xSplit && zone.right >= xSplit) ||
39744
39838
  (zone.top < ySplit && zone.bottom >= ySplit)) {
39745
- return 75 /* CommandResult.FrozenPaneOverlap */;
39839
+ return 76 /* CommandResult.FrozenPaneOverlap */;
39746
39840
  }
39747
39841
  }
39748
39842
  return 0 /* CommandResult.Success */;
@@ -40136,7 +40230,7 @@ class ClipboardFigureState {
40136
40230
  }
40137
40231
  isPasteAllowed(target, option) {
40138
40232
  if (target.length === 0) {
40139
- return 73 /* CommandResult.EmptyTarget */;
40233
+ return 74 /* CommandResult.EmptyTarget */;
40140
40234
  }
40141
40235
  if (option?.pasteOption !== undefined) {
40142
40236
  return 22 /* CommandResult.WrongFigurePasteOption */;
@@ -40581,6 +40675,10 @@ function setXcToReferenceType(xc, referenceType) {
40581
40675
  return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
40582
40676
  case "colrow":
40583
40677
  indexOfNumber = xc.search(/[0-9]/);
40678
+ if (indexOfNumber === -1 || indexOfNumber === 0) {
40679
+ // no row number (eg. A) or no column (eg. 1)
40680
+ return "$" + xc;
40681
+ }
40584
40682
  xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
40585
40683
  return "$" + xc;
40586
40684
  case "none":
@@ -40873,7 +40971,7 @@ class EditionPlugin extends UIPlugin {
40873
40971
  validateSelection(length, start, end) {
40874
40972
  return start >= 0 && start <= length && end >= 0 && end <= length
40875
40973
  ? 0 /* CommandResult.Success */
40876
- : 46 /* CommandResult.WrongComposerSelection */;
40974
+ : 47 /* CommandResult.WrongComposerSelection */;
40877
40975
  }
40878
40976
  onColumnsRemoved(cmd) {
40879
40977
  if (cmd.elements.includes(this.col) && this.mode !== "inactive") {
@@ -41184,9 +41282,10 @@ class EditionPlugin extends UIPlugin {
41184
41282
  */
41185
41283
  getReferencedRanges() {
41186
41284
  const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
41187
- return this.currentTokens
41285
+ const referenceRanges = this.currentTokens
41188
41286
  .filter((token) => token.type === "REFERENCE")
41189
41287
  .map((token) => this.getters.getRangeFromSheetXC(editionSheetId, token.value));
41288
+ return referenceRanges.filter((range) => !range.invalidSheetName && !range.invalidXc);
41190
41289
  }
41191
41290
  /**
41192
41291
  * Function used to determine when composer selection can start.
@@ -41762,7 +41861,7 @@ class GridSelectionPlugin extends UIPlugin {
41762
41861
  sheetId: cmd.sheetId,
41763
41862
  base: cmd.base,
41764
41863
  quantity: thickness,
41765
- position: "before",
41864
+ position: cmd.position,
41766
41865
  });
41767
41866
  const isCol = cmd.dimension === "COL";
41768
41867
  const start = cmd.elements[0];
@@ -41779,12 +41878,13 @@ class GridSelectionPlugin extends UIPlugin {
41779
41878
  },
41780
41879
  ];
41781
41880
  const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
41881
+ const base = isBasedBefore ? cmd.base : cmd.base + 1;
41782
41882
  const pasteTarget = [
41783
41883
  {
41784
- left: isCol ? cmd.base : 0,
41785
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
41786
- top: !isCol ? cmd.base : 0,
41787
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
41884
+ left: isCol ? base : 0,
41885
+ right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
41886
+ top: !isCol ? base : 0,
41887
+ bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
41788
41888
  },
41789
41889
  ];
41790
41890
  state.paste(pasteTarget, { selectTarget: true });
@@ -41821,6 +41921,11 @@ class GridSelectionPlugin extends UIPlugin {
41821
41921
  doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
41822
41922
  return 2 /* CommandResult.WillRemoveExistingMerge */;
41823
41923
  }
41924
+ const headers = [cmd.base, ...cmd.elements];
41925
+ const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
41926
+ if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
41927
+ return 87 /* CommandResult.InvalidHeaderIndex */;
41928
+ }
41824
41929
  return 0 /* CommandResult.Success */;
41825
41930
  }
41826
41931
  //-------------------------------------------
@@ -44102,7 +44207,7 @@ class Spreadsheet extends owl.Component {
44102
44207
  }
44103
44208
  onKeydown(ev) {
44104
44209
  let keyDownString = "";
44105
- if (ev.ctrlKey || ev.metaKey) {
44210
+ if (isCtrlKey(ev)) {
44106
44211
  keyDownString += "CTRL+";
44107
44212
  }
44108
44213
  keyDownString += ev.key.toUpperCase();
@@ -45168,7 +45273,7 @@ class SelectionStreamProcessorImpl {
45168
45273
  */
45169
45274
  moveAnchorCell(direction, step = 1) {
45170
45275
  if (step !== "end" && step <= 0) {
45171
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
45276
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45172
45277
  }
45173
45278
  const { col, row } = this.getNextAvailablePosition(direction, step);
45174
45279
  return this.selectCell(col, row);
@@ -45214,7 +45319,7 @@ class SelectionStreamProcessorImpl {
45214
45319
  */
45215
45320
  resizeAnchorZone(direction, step = 1) {
45216
45321
  if (step !== "end" && step <= 0) {
45217
- return new DispatchResult(83 /* CommandResult.InvalidSelectionStep */);
45322
+ return new DispatchResult(84 /* CommandResult.InvalidSelectionStep */);
45218
45323
  }
45219
45324
  const sheetId = this.getters.getActiveSheetId();
45220
45325
  const anchor = this.anchor;
@@ -46041,12 +46146,7 @@ function addFormula(cell) {
46041
46146
  attrs.push(["t", "str"]);
46042
46147
  cycle = escapeXml /*xml*/ `<v>${cell.value}</v>`;
46043
46148
  }
46044
- node = escapeXml /*xml*/ `
46045
- <f>
46046
- ${XlsxFormula}
46047
- </f>
46048
- ${cycle}
46049
- `;
46149
+ node = escapeXml /*xml*/ `<f> ${XlsxFormula} </f> ${cycle}`;
46050
46150
  return { attrs, node };
46051
46151
  }
46052
46152
  else {
@@ -46868,11 +46968,10 @@ function addRows(construct, data, sheet) {
46868
46968
  ({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader));
46869
46969
  }
46870
46970
  attributes.push(...additionalAttrs);
46871
- cellNodes.push(escapeXml /*xml*/ `
46872
- <c ${formatAttributes(attributes)}>
46873
- ${cellNode}
46874
- </c>
46875
- `);
46971
+ // prettier-ignore
46972
+ cellNodes.push(escapeXml /*xml*/ `<c ${formatAttributes(attributes)}>
46973
+ ${cellNode}
46974
+ </c>`);
46876
46975
  }
46877
46976
  }
46878
46977
  if (cellNodes.length || row.size !== DEFAULT_CELL_HEIGHT || row.isHidden) {
@@ -47557,10 +47656,10 @@ class Model extends EventBus {
47557
47656
  const command = createCommand(type, payload);
47558
47657
  let status = this.status;
47559
47658
  if (this.getters.isReadonly() && !canExecuteInReadonly(command)) {
47560
- return new DispatchResult(67 /* CommandResult.Readonly */);
47659
+ return new DispatchResult(68 /* CommandResult.Readonly */);
47561
47660
  }
47562
47661
  if (!this.session.canApplyOptimisticUpdate()) {
47563
- return new DispatchResult(64 /* CommandResult.WaitingSessionConfirmation */);
47662
+ return new DispatchResult(65 /* CommandResult.WaitingSessionConfirmation */);
47564
47663
  }
47565
47664
  switch (status) {
47566
47665
  case 0 /* Status.Ready */:
@@ -47839,6 +47938,6 @@ exports.setTranslationMethod = setTranslationMethod;
47839
47938
  exports.tokenize = tokenize;
47840
47939
 
47841
47940
 
47842
- __info__.version = '16.3.18';
47843
- __info__.date = '2023-11-24T13:10:15.278Z';
47844
- __info__.hash = '45f745e';
47941
+ __info__.version = '16.3.24';
47942
+ __info__.date = '2024-02-02T13:45:48.440Z';
47943
+ __info__.hash = '0bf5f45';