@odoo/o-spreadsheet 17.4.0-alpha.3 → 17.4.0-alpha.4

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.4.0-alpha.3
7
- * @date 2024-06-10T09:38:53.982Z
8
- * @hash a45ed6a
6
+ * @version 17.4.0-alpha.4
7
+ * @date 2024-06-12T14:00:22.046Z
8
+ * @hash cefb0e4
9
9
  */
10
10
 
11
11
  'use strict';
@@ -1828,22 +1828,28 @@ function isDateAfter(date, dateAfter) {
1828
1828
  */
1829
1829
  const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
1830
1830
  decimalSeparator = escapeRegExp(decimalSeparator);
1831
- return new RegExp(`(^-?\\d+(${decimalSeparator}?\\d*(e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1831
+ return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1832
1832
  });
1833
1833
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1834
1834
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1835
1835
  const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1836
- const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1837
- const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1838
- const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
1839
- const pPercentFormat = "(\\s*%)?"; // pattern that match percent symbol between zero and one time
1840
- const pNumber = "(\\s*" + pIntegerAndDecimals + "|" + pOnlyDecimals + ")" + pScientificFormat + pPercentFormat;
1841
- const pMinus = "(\\s*-)?"; // pattern that match negative symbol between zero and one time
1842
- const pCurrencyFormat = "(\\s*[\\$€])?";
1836
+ const pIntegerAndDecimals = `(?:\\d+(?:${thousandsSeparator}\\d{3,})*(?:${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1837
+ const pOnlyDecimals = `(?:${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1838
+ const pScientificFormat = "(?:e(?:\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
1839
+ const pPercentFormat = "(?:\\s*%)?"; // pattern that match percent symbol between zero and one time
1840
+ const pNumber = "(?:\\s*" +
1841
+ pIntegerAndDecimals +
1842
+ "|" +
1843
+ pOnlyDecimals +
1844
+ ")" +
1845
+ pScientificFormat +
1846
+ pPercentFormat;
1847
+ const pMinus = "(?:\\s*-)?"; // pattern that match negative symbol between zero and one time
1848
+ const pCurrencyFormat = "(?:\\s*[\\$€])?";
1843
1849
  const p1 = pMinus + pCurrencyFormat + pNumber;
1844
1850
  const p2 = pMinus + pNumber + pCurrencyFormat;
1845
1851
  const p3 = pCurrencyFormat + pMinus + pNumber;
1846
- const pNumberExp = "^((" + [p1, p2, p3].join(")|(") + "))$";
1852
+ const pNumberExp = "^(?:(?:" + [p1, p2, p3].join(")|(?:") + "))$";
1847
1853
  const numberRegexp = new RegExp(pNumberExp, "i");
1848
1854
  return numberRegexp;
1849
1855
  });
@@ -2781,7 +2787,7 @@ function evaluatePredicate(value, criterion) {
2781
2787
  return false;
2782
2788
  }
2783
2789
  if (typeof operand === "number" && operator === "=") {
2784
- return toString(value) === toString(operand);
2790
+ return value.toString() === operand.toString();
2785
2791
  }
2786
2792
  if (operator === "<>" || operator === "=") {
2787
2793
  let result;
@@ -2841,14 +2847,13 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2841
2847
  if (countArg % 2 === 1) {
2842
2848
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range and criterion to be in pairs."));
2843
2849
  }
2844
- const dimRow = args[0].length;
2845
- const dimCol = args[0][0].length;
2850
+ const firstArg = toMatrix(args[0]);
2851
+ const dimRow = firstArg.length;
2852
+ const dimCol = firstArg[0].length;
2846
2853
  let predicates = [];
2847
2854
  for (let i = 0; i < countArg - 1; i += 2) {
2848
- const criteriaRange = args[i];
2849
- if (!isMatrix(criteriaRange) ||
2850
- criteriaRange.length !== dimRow ||
2851
- criteriaRange[0].length !== dimCol) {
2855
+ const criteriaRange = toMatrix(args[i]);
2856
+ if (criteriaRange.length !== dimRow || criteriaRange[0].length !== dimCol) {
2852
2857
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range to have the same dimension"));
2853
2858
  }
2854
2859
  const description = toString(args[i + 1]);
@@ -2862,7 +2867,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2862
2867
  for (let j = 0; j < dimCol; j++) {
2863
2868
  let validatedPredicates = true;
2864
2869
  for (let k = 0; k < countArg - 1; k += 2) {
2865
- const criteriaValue = args[k][i][j].value;
2870
+ const criteriaValue = toMatrix(args[k])[i][j].value;
2866
2871
  const criterion = predicates[k / 2];
2867
2872
  validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
2868
2873
  if (!validatedPredicates) {
@@ -3527,10 +3532,8 @@ function detectDateFormat(content, locale) {
3527
3532
  const internalDate = parseDateTime(content, locale);
3528
3533
  return internalDate.format;
3529
3534
  }
3535
+ /** use this function only if the content corresponds to a number (means that isNumber(content) return true */
3530
3536
  function detectNumberFormat(content) {
3531
- if (!isNumber(content, DEFAULT_LOCALE)) {
3532
- return undefined;
3533
- }
3534
3537
  const digitBase = content.includes(".") ? "0.00" : "0";
3535
3538
  const matchedCurrencies = content.match(/[\$€]/);
3536
3539
  if (matchedCurrencies) {
@@ -4733,21 +4736,16 @@ function unionPositionsToZone(positions) {
4733
4736
  * Check if two zones are contiguous, ie. that they share a border
4734
4737
  */
4735
4738
  function areZoneContiguous(zone1, zone2) {
4736
- const u = union(zone1, zone2);
4737
4739
  if (zone1.right + 1 === zone2.left || zone1.left === zone2.right + 1) {
4738
- return getZoneHeight(u) <= getZoneHeight(zone1) + getZoneHeight(zone2);
4740
+ return ((zone1.top <= zone2.bottom && zone1.top >= zone2.top) ||
4741
+ (zone2.top <= zone1.bottom && zone2.top >= zone1.top));
4739
4742
  }
4740
4743
  if (zone1.bottom + 1 === zone2.top || zone1.top === zone2.bottom + 1) {
4741
- return getZoneWidth(u) <= getZoneWidth(zone1) + getZoneWidth(zone2);
4744
+ return ((zone1.left <= zone2.right && zone1.left >= zone2.left) ||
4745
+ (zone2.left <= zone1.right && zone2.left >= zone1.left));
4742
4746
  }
4743
4747
  return false;
4744
4748
  }
4745
- function getZoneHeight(zone) {
4746
- return zone.bottom - zone.top + 1;
4747
- }
4748
- function getZoneWidth(zone) {
4749
- return zone.right - zone.left + 1;
4750
- }
4751
4749
  /**
4752
4750
  * Merge contiguous and overlapping zones that are in the array into bigger zones
4753
4751
  */
@@ -5503,7 +5501,7 @@ class Registry {
5503
5501
  }
5504
5502
  }
5505
5503
 
5506
- function getClipboardDataPositions(zones) {
5504
+ function getClipboardDataPositions(sheetId, zones) {
5507
5505
  const lefts = new Set(zones.map((z) => z.left));
5508
5506
  const rights = new Set(zones.map((z) => z.right));
5509
5507
  const tops = new Set(zones.map((z) => z.top));
@@ -5517,7 +5515,7 @@ function getClipboardDataPositions(zones) {
5517
5515
  const cellsPosition = clippedZones.map((zone) => positions(zone)).flat();
5518
5516
  const columnsIndexes = [...new Set(cellsPosition.map((p) => p.col))].sort((a, b) => a - b);
5519
5517
  const rowsIndexes = [...new Set(cellsPosition.map((p) => p.row))].sort((a, b) => a - b);
5520
- return { zones, clippedZones, columnsIndexes, rowsIndexes };
5518
+ return { sheetId, zones, clippedZones, columnsIndexes, rowsIndexes };
5521
5519
  }
5522
5520
  /**
5523
5521
  * The clipped zone is copied as many times as it fits in the target.
@@ -5567,8 +5565,8 @@ class ClipboardHandler {
5567
5565
  isCutAllowed(data) {
5568
5566
  return "Success" /* CommandResult.Success */;
5569
5567
  }
5570
- getPasteTarget(target, content, options) {
5571
- return { zones: [] };
5568
+ getPasteTarget(sheetId, target, content, options) {
5569
+ return { zones: [], sheetId };
5572
5570
  }
5573
5571
  convertOSClipboardData(data) {
5574
5572
  return;
@@ -5606,7 +5604,7 @@ class AbstractCellClipboardHandler extends ClipboardHandler {
5606
5604
 
5607
5605
  class BorderClipboardHandler extends AbstractCellClipboardHandler {
5608
5606
  copy(data) {
5609
- const sheetId = this.getters.getActiveSheetId();
5607
+ const sheetId = data.sheetId;
5610
5608
  if (data.zones.length === 0) {
5611
5609
  return;
5612
5610
  }
@@ -5626,7 +5624,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5626
5624
  if (!content) {
5627
5625
  return;
5628
5626
  }
5629
- const sheetId = this.getters.getActiveSheetId();
5627
+ const sheetId = target.sheetId;
5630
5628
  if (options?.pasteOption === "asValue") {
5631
5629
  return;
5632
5630
  }
@@ -6156,7 +6154,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6156
6154
  if (!("zones" in data) || !data.zones.length) {
6157
6155
  return;
6158
6156
  }
6159
- const sheetId = this.getters.getActiveSheetId();
6157
+ const sheetId = data.sheetId;
6160
6158
  const zones = data.zones;
6161
6159
  if (!zones.length) {
6162
6160
  return {
@@ -6185,6 +6183,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6185
6183
  format: evaluatedCell.format,
6186
6184
  content,
6187
6185
  isFormula: false,
6186
+ parsedValue: evaluatedCell.value,
6188
6187
  };
6189
6188
  }
6190
6189
  cellsInRow.push({
@@ -6199,7 +6198,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6199
6198
  return {
6200
6199
  cells: clippedCells,
6201
6200
  zones: clippedZones,
6202
- sheetId: this.getters.getActiveSheetId(),
6201
+ sheetId: data.sheetId,
6203
6202
  };
6204
6203
  }
6205
6204
  isPasteAllowed(sheetId, target, content, clipboardOptions) {
@@ -6227,7 +6226,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6227
6226
  return;
6228
6227
  }
6229
6228
  const zones = target.zones;
6230
- const sheetId = this.getters.getActiveSheetId();
6229
+ const sheetId = target.sheetId;
6231
6230
  if (!options?.isCutOperation) {
6232
6231
  this.pasteFromCopy(sheetId, zones, content.cells, options);
6233
6232
  }
@@ -6235,11 +6234,12 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6235
6234
  this.pasteFromCut(sheetId, zones, content, options);
6236
6235
  }
6237
6236
  }
6238
- getPasteTarget(target, content, options) {
6237
+ getPasteTarget(sheetId, target, content, options) {
6239
6238
  const width = content.cells[0].length;
6240
6239
  const height = content.cells.length;
6241
6240
  if (options?.isCutOperation) {
6242
6241
  return {
6242
+ sheetId,
6243
6243
  zones: [
6244
6244
  {
6245
6245
  left: target[0].left,
@@ -6251,11 +6251,9 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6251
6251
  };
6252
6252
  }
6253
6253
  if (width === 1 && height === 1) {
6254
- return { zones: [] };
6254
+ return { zones: [], sheetId };
6255
6255
  }
6256
- return {
6257
- zones: getPasteZones(target, content.cells),
6258
- };
6256
+ return { sheetId, zones: getPasteZones(target, content.cells) };
6259
6257
  }
6260
6258
  pasteFromCut(sheetId, target, content, options) {
6261
6259
  this.clearClippedZones(content);
@@ -6378,7 +6376,7 @@ class AbstractFigureClipboardHandler extends ClipboardHandler {
6378
6376
 
6379
6377
  class ChartClipboardHandler extends AbstractFigureClipboardHandler {
6380
6378
  copy(data) {
6381
- const sheetId = this.getters.getActiveSheetId();
6379
+ const sheetId = data.sheetId;
6382
6380
  const figure = this.getters.getFigure(sheetId, data.figureId);
6383
6381
  if (!figure) {
6384
6382
  throw new Error(`No figure for the given id: ${data.figureId}`);
@@ -6398,22 +6396,19 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
6398
6396
  copiedChart,
6399
6397
  };
6400
6398
  }
6401
- getPasteTarget(target, content, options) {
6399
+ getPasteTarget(sheetId, target, content, options) {
6402
6400
  if (!content?.copiedFigure || !content?.copiedChart) {
6403
- return { zones: [] };
6401
+ return { zones: [], sheetId };
6404
6402
  }
6405
6403
  const newId = new UuidGenerator().uuidv4();
6406
- return {
6407
- zones: [],
6408
- figureId: newId,
6409
- };
6404
+ return { zones: [], figureId: newId, sheetId };
6410
6405
  }
6411
6406
  paste(target, clippedContent, options) {
6412
6407
  if (!clippedContent?.copiedFigure || !clippedContent?.copiedChart || !target.figureId) {
6413
6408
  return;
6414
6409
  }
6415
6410
  const { zones, figureId } = target;
6416
- const sheetId = this.getters.getActiveSheetId();
6411
+ const sheetId = target.sheetId;
6417
6412
  const numCols = this.getters.getNumberCols(sheetId);
6418
6413
  const numRows = this.getters.getNumberRows(sheetId);
6419
6414
  const targetX = this.getters.getColDimensions(sheetId, zones[0].left).start;
@@ -6459,7 +6454,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6459
6454
  return;
6460
6455
  }
6461
6456
  const { rowsIndexes, columnsIndexes } = data;
6462
- const sheetId = this.getters.getActiveSheetId();
6457
+ const sheetId = data.sheetId;
6463
6458
  const cellPositions = rowsIndexes.map((row) => columnsIndexes.map((col) => ({ col, row, sheetId })));
6464
6459
  return {
6465
6460
  cellPositions,
@@ -6473,7 +6468,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6473
6468
  return;
6474
6469
  }
6475
6470
  const zones = target.zones;
6476
- const sheetId = this.getters.getActiveSheetId();
6471
+ const sheetId = target.sheetId;
6477
6472
  if (!options?.isCutOperation) {
6478
6473
  this.pasteFromCopy(sheetId, zones, clippedContent.cellPositions);
6479
6474
  }
@@ -6554,7 +6549,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
6554
6549
  return;
6555
6550
  }
6556
6551
  const { rowsIndexes, columnsIndexes } = data;
6557
- const sheetId = this.getters.getActiveSheetId();
6552
+ const sheetId = data.sheetId;
6558
6553
  const cellPositions = rowsIndexes.map((row) => columnsIndexes.map((col) => ({ col, row, sheetId })));
6559
6554
  return {
6560
6555
  cellPositions,
@@ -6571,7 +6566,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
6571
6566
  return;
6572
6567
  }
6573
6568
  const zones = target.zones;
6574
- const sheetId = this.getters.getActiveSheetId();
6569
+ const sheetId = target.sheetId;
6575
6570
  if (!options?.isCutOperation) {
6576
6571
  this.pasteFromCopy(sheetId, zones, clippedContent.cellPositions);
6577
6572
  }
@@ -6650,7 +6645,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
6650
6645
 
6651
6646
  class ImageClipboardHandler extends AbstractFigureClipboardHandler {
6652
6647
  copy(data) {
6653
- const sheetId = this.getters.getActiveSheetId();
6648
+ const sheetId = data.sheetId;
6654
6649
  const figure = this.getters.getFigure(sheetId, data.figureId);
6655
6650
  if (!figure) {
6656
6651
  throw new Error(`No figure for the given id: ${data.figureId}`);
@@ -6668,15 +6663,12 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
6668
6663
  sheetId,
6669
6664
  };
6670
6665
  }
6671
- getPasteTarget(target, content, options) {
6666
+ getPasteTarget(sheetId, target, content, options) {
6672
6667
  if (!content?.copiedFigure || !content?.copiedImage) {
6673
- return { zones: [] };
6668
+ return { zones: [], sheetId };
6674
6669
  }
6675
6670
  const newId = new UuidGenerator().uuidv4();
6676
- return {
6677
- zones: [],
6678
- figureId: newId,
6679
- };
6671
+ return { sheetId, zones: [], figureId: newId };
6680
6672
  }
6681
6673
  paste(target, clippedContent, options) {
6682
6674
  if (!clippedContent?.copiedFigure || !clippedContent?.copiedImage || !target.figureId) {
@@ -6747,8 +6739,7 @@ class MergeClipboardHandler extends AbstractCellClipboardHandler {
6747
6739
  if (options?.isCutOperation || !("zones" in target) || !target.zones.length) {
6748
6740
  return;
6749
6741
  }
6750
- const sheetId = this.getters.getActiveSheetId();
6751
- this.pasteFromCopy(sheetId, target.zones, content.cells, options);
6742
+ this.pasteFromCopy(target.sheetId, target.zones, content.cells, options);
6752
6743
  }
6753
6744
  pasteZone(sheetId, col, row, cells) {
6754
6745
  for (const [r, rowCells] of cells.entries()) {
@@ -6808,7 +6799,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
6808
6799
 
6809
6800
  class TableClipboardHandler extends AbstractCellClipboardHandler {
6810
6801
  copy(data) {
6811
- const sheetId = this.getters.getActiveSheetId();
6802
+ const sheetId = data.sheetId;
6812
6803
  const { rowsIndexes, columnsIndexes, zones } = data;
6813
6804
  if (!zones || !rowsIndexes.length || !columnsIndexes.length) {
6814
6805
  return { tableCells: [[]], sheetId };
@@ -6850,7 +6841,7 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
6850
6841
  }
6851
6842
  return {
6852
6843
  tableCells,
6853
- sheetId: this.getters.getActiveSheetId(),
6844
+ sheetId: data.sheetId,
6854
6845
  };
6855
6846
  }
6856
6847
  /**
@@ -6872,7 +6863,7 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
6872
6863
  return;
6873
6864
  }
6874
6865
  const zones = target.zones;
6875
- const sheetId = this.getters.getActiveSheetId();
6866
+ const sheetId = target.sheetId;
6876
6867
  if (!options?.isCutOperation) {
6877
6868
  this.pasteFromCopy(sheetId, zones, content.tableCells, options);
6878
6869
  }
@@ -7634,10 +7625,8 @@ function detectLink(value) {
7634
7625
  return undefined;
7635
7626
  }
7636
7627
 
7637
- function evaluateLiteral(content = "", localeFormat) {
7638
- const value = localeFormat.format === PLAIN_TEXT_FORMAT
7639
- ? content
7640
- : parseLiteral(content, localeFormat.locale);
7628
+ function evaluateLiteral(literalCell, localeFormat) {
7629
+ const value = localeFormat.format === PLAIN_TEXT_FORMAT ? literalCell.content : literalCell.parsedValue;
7641
7630
  const fPayload = { value, format: localeFormat.format };
7642
7631
  return createEvaluatedCell(fPayload, localeFormat.locale);
7643
7632
  }
@@ -7649,10 +7638,11 @@ function parseLiteral(content, locale) {
7649
7638
  return null;
7650
7639
  }
7651
7640
  if (isNumber(content, DEFAULT_LOCALE)) {
7652
- return toNumber(content, DEFAULT_LOCALE);
7641
+ return parseNumber(content, DEFAULT_LOCALE);
7653
7642
  }
7654
- if (isDateTime(content, locale)) {
7655
- return toNumber(content, locale);
7643
+ const internalDate = parseDateTime(content, locale);
7644
+ if (internalDate) {
7645
+ return internalDate.value;
7656
7646
  }
7657
7647
  if (isBoolean(content)) {
7658
7648
  return content.toUpperCase() === "TRUE" ? true : false;
@@ -7664,9 +7654,14 @@ function createEvaluatedCell(fPayload, locale = DEFAULT_LOCALE, cell) {
7664
7654
  if (!link) {
7665
7655
  return _createEvaluatedCell(fPayload, locale, cell);
7666
7656
  }
7657
+ const value = parseLiteral(link.label, locale);
7658
+ const format = fPayload.format ||
7659
+ (typeof value === "number"
7660
+ ? detectDateFormat(link.label, locale) || detectNumberFormat(link.label)
7661
+ : undefined);
7667
7662
  const linkPayload = {
7668
- value: parseLiteral(link.label, locale),
7669
- format: fPayload.format || detectDateFormat(link.label, locale) || detectNumberFormat(link.label),
7663
+ value,
7664
+ format,
7670
7665
  };
7671
7666
  return {
7672
7667
  ..._createEvaluatedCell(linkPayload, locale, cell),
@@ -10990,6 +10985,9 @@ function makeArg(str, description) {
10990
10985
  if (types.some((t) => t.startsWith("RANGE"))) {
10991
10986
  result.acceptMatrix = true;
10992
10987
  }
10988
+ if (types.every((t) => t.startsWith("RANGE"))) {
10989
+ result.acceptMatrixOnly = true;
10990
+ }
10993
10991
  return result;
10994
10992
  }
10995
10993
  /**
@@ -11244,7 +11242,6 @@ const ARRAY_CONSTRAIN = {
11244
11242
  arg("rows (number)", _t("The number of rows in the constrained array.")),
11245
11243
  arg("columns (number)", _t("The number of columns in the constrained array.")),
11246
11244
  ],
11247
- returns: ["RANGE<ANY>"],
11248
11245
  compute: function (array, rows, columns) {
11249
11246
  const _array = toMatrix(array);
11250
11247
  const _rowsArg = toInteger(rows?.value, this.locale);
@@ -11267,15 +11264,19 @@ const CHOOSECOLS = {
11267
11264
  arg("col_num (number, range<number>)", _t("The first column index of the columns to be returned.")),
11268
11265
  arg("col_num2 (number, range<number>, repeating)", _t("The columns indexes of the columns to be returned.")),
11269
11266
  ],
11270
- returns: ["RANGE<ANY>"],
11271
11267
  compute: function (array, ...columns) {
11272
11268
  const _array = toMatrix(array);
11273
11269
  const _columns = flattenRowFirst(columns, (item) => toInteger(item?.value, this.locale));
11274
- assert(() => _columns.every((col) => col > 0 && col <= _array.length), _t("The columns arguments must be between 1 and %s (got %s).", _array.length.toString(), (_columns.find((col) => col <= 0 || col > _array.length) || 0).toString()));
11270
+ const argOutOfRange = _columns.filter((col) => col === 0 || _array.length < Math.abs(col));
11271
+ assert(() => argOutOfRange.length === 0, _t("The columns arguments must be between -%s and %s (got %s), excluding 0.", _array.length.toString(), _array.length.toString(), argOutOfRange.join(",")));
11275
11272
  const result = Array(_columns.length);
11276
11273
  for (let col = 0; col < _columns.length; col++) {
11277
- const colIndex = _columns[col] - 1; // -1 because columns arguments are 1-indexed
11278
- result[col] = _array[colIndex];
11274
+ if (_columns[col] > 0) {
11275
+ result[col] = _array[_columns[col] - 1]; // -1 because columns arguments are 1-indexed
11276
+ }
11277
+ else {
11278
+ result[col] = _array[_array.length + _columns[col]];
11279
+ }
11279
11280
  }
11280
11281
  return result;
11281
11282
  },
@@ -11291,13 +11292,18 @@ const CHOOSEROWS = {
11291
11292
  arg("row_num (number, range<number>)", _t("The first row index of the rows to be returned.")),
11292
11293
  arg("row_num2 (number, range<number>, repeating)", _t("The rows indexes of the rows to be returned.")),
11293
11294
  ],
11294
- returns: ["RANGE<ANY>"],
11295
11295
  compute: function (array, ...rows) {
11296
11296
  const _array = toMatrix(array);
11297
11297
  const _rows = flattenRowFirst(rows, (item) => toInteger(item?.value, this.locale));
11298
11298
  const _nbColumns = _array.length;
11299
- assert(() => _rows.every((row) => row > 0 && row <= _array[0].length), _t("The rows arguments must be between 1 and %s (got %s).", _array[0].length.toString(), (_rows.find((row) => row <= 0 || row > _array[0].length) || 0).toString()));
11300
- return generateMatrix(_nbColumns, _rows.length, (col, row) => _array[col][_rows[row] - 1]); // -1 because rows arguments are 1-indexed
11299
+ const argOutOfRange = _rows.filter((row) => row === 0 || _array[0].length < Math.abs(row));
11300
+ assert(() => argOutOfRange.length === 0, _t("The rows arguments must be between -%s and %s (got %s), excluding 0.", _array[0].length.toString(), _array[0].length.toString(), argOutOfRange.join(",")));
11301
+ return generateMatrix(_nbColumns, _rows.length, (col, row) => {
11302
+ if (_rows[row] > 0) {
11303
+ return _array[col][_rows[row] - 1]; // -1 because columns arguments are 1-indexed
11304
+ }
11305
+ return _array[col][_array[col].length + _rows[row]];
11306
+ });
11301
11307
  },
11302
11308
  isExported: true,
11303
11309
  };
@@ -11312,7 +11318,6 @@ const EXPAND = {
11312
11318
  arg("columns (number, optional)", _t("The number of columns in the expanded array. If missing, columns will not be expanded.")),
11313
11319
  arg("pad_with (any, default=0)", _t("The value with which to pad.")), // @compatibility: on Excel, pad with #N/A
11314
11320
  ],
11315
- returns: ["RANGE<ANY>"],
11316
11321
  compute: function (arg, rows, columns, padWith = { value: 0 } // TODO : Replace with #N/A errors once it's supported
11317
11322
  ) {
11318
11323
  const _array = toMatrix(arg);
@@ -11333,7 +11338,6 @@ const FLATTEN = {
11333
11338
  arg("range (any, range<any>)", _t("The first range to flatten.")),
11334
11339
  arg("range2 (any, range<any>, repeating)", _t("Additional ranges to flatten.")),
11335
11340
  ],
11336
- returns: ["RANGE<ANY>"],
11337
11341
  compute: function (...ranges) {
11338
11342
  return [flattenRowFirst(ranges, (val) => (val === undefined ? { value: "" } : val))];
11339
11343
  },
@@ -11348,7 +11352,6 @@ const FREQUENCY = {
11348
11352
  arg("data (range<number>)", _t("The array of ranges containing the values to be counted.")),
11349
11353
  arg("classes (number, range<number>)", _t("The range containing the set of classes.")),
11350
11354
  ],
11351
- returns: ["RANGE<NUMBER>"],
11352
11355
  compute: function (data, classes) {
11353
11356
  const _data = flattenRowFirst([data], (data) => data.value).filter((val) => typeof val === "number");
11354
11357
  const _classes = flattenRowFirst([classes], (data) => data.value).filter((val) => typeof val === "number");
@@ -11396,7 +11399,6 @@ const HSTACK = {
11396
11399
  arg("range1 (any, range<any>)", _t("The first range to be appended.")),
11397
11400
  arg("range2 (any, range<any>, repeating)", _t("Additional ranges to add to range1.")),
11398
11401
  ],
11399
- returns: ["RANGE<ANY>"],
11400
11402
  compute: function (...ranges) {
11401
11403
  const nbRows = Math.max(...ranges.map((r) => r?.[0]?.length ?? 0));
11402
11404
  const result = [];
@@ -11423,7 +11425,6 @@ const MDETERM = {
11423
11425
  args: [
11424
11426
  arg("square_matrix (number, range<number>)", _t("An range with an equal number of rows and columns representing a matrix whose determinant will be calculated.")),
11425
11427
  ],
11426
- returns: ["NUMBER"],
11427
11428
  compute: function (matrix) {
11428
11429
  const _matrix = toNumberMatrix(matrix, "square_matrix");
11429
11430
  assertSquareMatrix(_t("The argument square_matrix must have the same number of columns and rows."), _matrix);
@@ -11439,7 +11440,6 @@ const MINVERSE = {
11439
11440
  args: [
11440
11441
  arg("square_matrix (number, range<number>)", _t("An range with an equal number of rows and columns representing a matrix whose multiplicative inverse will be calculated.")),
11441
11442
  ],
11442
- returns: ["RANGE<NUMBER>"],
11443
11443
  compute: function (matrix) {
11444
11444
  const _matrix = toNumberMatrix(matrix, "square_matrix");
11445
11445
  assertSquareMatrix(_t("The argument square_matrix must have the same number of columns and rows."), _matrix);
@@ -11460,7 +11460,6 @@ const MMULT = {
11460
11460
  arg("matrix1 (number, range<number>)", _t("The first matrix in the matrix multiplication operation.")),
11461
11461
  arg("matrix2 (number, range<number>)", _t("The second matrix in the matrix multiplication operation.")),
11462
11462
  ],
11463
- returns: ["RANGE<NUMBER>"],
11464
11463
  compute: function (matrix1, matrix2) {
11465
11464
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
11466
11465
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
@@ -11479,7 +11478,6 @@ const SUMPRODUCT = {
11479
11478
  arg("range1 (number, range<number>)", _t("The first range whose entries will be multiplied with corresponding entries in the other ranges.")),
11480
11479
  arg("range2 (number, range<number>, repeating)", _t("The other range whose entries will be multiplied with corresponding entries in the other ranges.")),
11481
11480
  ],
11482
- returns: ["NUMBER"],
11483
11481
  compute: function (...args) {
11484
11482
  assertSameDimensions(_t("All the ranges must have the same dimensions."), ...args);
11485
11483
  const _args = args.map(toMatrix);
@@ -11536,7 +11534,6 @@ const SUMX2MY2 = {
11536
11534
  arg("array_x (number, range<number>)", _t("The array or range of values whose squares will be reduced by the squares of corresponding entries in array_y and added together.")),
11537
11535
  arg("array_y (number, range<number>)", _t("The array or range of values whose squares will be subtracted from the squares of corresponding entries in array_x and added together.")),
11538
11536
  ],
11539
- returns: ["NUMBER"],
11540
11537
  compute: function (arrayX, arrayY) {
11541
11538
  return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 - y ** 2);
11542
11539
  },
@@ -11551,7 +11548,6 @@ const SUMX2PY2 = {
11551
11548
  arg("array_x (number, range<number>)", _t("The array or range of values whose squares will be added to the squares of corresponding entries in array_y and added together.")),
11552
11549
  arg("array_y (number, range<number>)", _t("The array or range of values whose squares will be added to the squares of corresponding entries in array_x and added together.")),
11553
11550
  ],
11554
- returns: ["NUMBER"],
11555
11551
  compute: function (arrayX, arrayY) {
11556
11552
  return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 + y ** 2);
11557
11553
  },
@@ -11566,7 +11562,6 @@ const SUMXMY2 = {
11566
11562
  arg("array_x (number, range<number>)", _t("The array or range of values that will be reduced by corresponding entries in array_y, squared, and added together.")),
11567
11563
  arg("array_y (number, range<number>)", _t("The array or range of values that will be subtracted from corresponding entries in array_x, the result squared, and all such results added together.")),
11568
11564
  ],
11569
- returns: ["NUMBER"],
11570
11565
  compute: function (arrayX, arrayY) {
11571
11566
  return getSumXAndY(arrayX, arrayY, (x, y) => (x - y) ** 2);
11572
11567
  },
@@ -11602,7 +11597,6 @@ function shouldKeepValue(ignore) {
11602
11597
  const TOCOL = {
11603
11598
  description: _t("Transforms a range of cells into a single column."),
11604
11599
  args: TO_COL_ROW_ARGS,
11605
- returns: ["RANGE<ANY>"],
11606
11600
  compute: function (array, ignore = { value: TO_COL_ROW_DEFAULT_IGNORE }, scanByColumn = { value: TO_COL_ROW_DEFAULT_SCAN }) {
11607
11601
  const _array = toMatrix(array);
11608
11602
  const _ignore = toNumber(ignore.value, this.locale);
@@ -11623,7 +11617,6 @@ const TOCOL = {
11623
11617
  const TOROW = {
11624
11618
  description: _t("Transforms a range of cells into a single row."),
11625
11619
  args: TO_COL_ROW_ARGS,
11626
- returns: ["RANGE<ANY>"],
11627
11620
  compute: function (array, ignore = { value: TO_COL_ROW_DEFAULT_IGNORE }, scanByColumn = { value: TO_COL_ROW_DEFAULT_SCAN }) {
11628
11621
  const _array = toMatrix(array);
11629
11622
  const _ignore = toNumber(ignore.value, this.locale);
@@ -11645,7 +11638,6 @@ const TOROW = {
11645
11638
  const TRANSPOSE = {
11646
11639
  description: _t("Transposes the rows and columns of a range."),
11647
11640
  args: [arg("range (any, range<any>)", _t("The range to be transposed."))],
11648
- returns: ["RANGE"],
11649
11641
  compute: function (arg) {
11650
11642
  const _array = toMatrix(arg);
11651
11643
  const nbColumns = _array[0].length;
@@ -11663,7 +11655,6 @@ const VSTACK = {
11663
11655
  arg("range1 (any, range<any>)", _t("The first range to be appended.")),
11664
11656
  arg("range2 (any, range<any>, repeating)", _t("Additional ranges to add to range1.")),
11665
11657
  ],
11666
- returns: ["RANGE<ANY>"],
11667
11658
  compute: function (...ranges) {
11668
11659
  const nbColumns = Math.max(...ranges.map((range) => toMatrix(range).length));
11669
11660
  const nbRows = ranges.reduce((acc, range) => acc + toMatrix(range)[0].length, 0);
@@ -11695,7 +11686,6 @@ const WRAPCOLS = {
11695
11686
  arg("pad_with (any, default=0)", // TODO : replace with #N/A
11696
11687
  _t("The value with which to fill the extra cells in the range.")),
11697
11688
  ],
11698
- returns: ["RANGE<ANY>"],
11699
11689
  compute: function (range, wrapCount, padWith = { value: 0 }) {
11700
11690
  const _array = toMatrix(range);
11701
11691
  const nbRows = toInteger(wrapCount?.value, this.locale);
@@ -11720,7 +11710,6 @@ const WRAPROWS = {
11720
11710
  arg("pad_with (any, default=0)", // TODO : replace with #N/A
11721
11711
  _t("The value with which to fill the extra cells in the range.")),
11722
11712
  ],
11723
- returns: ["RANGE<ANY>"],
11724
11713
  compute: function (range, wrapCount, padWith = { value: 0 }) {
11725
11714
  const _array = toMatrix(range);
11726
11715
  const nbColumns = toInteger(wrapCount?.value, this.locale);
@@ -11768,7 +11757,6 @@ const FORMAT_LARGE_NUMBER = {
11768
11757
  arg("value (number)", _t("The number.")),
11769
11758
  arg("unit (string, optional)", _t("The formatting unit. Use 'k', 'm', or 'b' to force the unit")),
11770
11759
  ],
11771
- returns: ["NUMBER"],
11772
11760
  compute: function (value, unite) {
11773
11761
  return {
11774
11762
  value: toNumber(value, this.locale),
@@ -11800,7 +11788,6 @@ const DECIMAL_REPRESENTATION = /^-?[a-z0-9]+$/i;
11800
11788
  const ABS = {
11801
11789
  description: _t("Absolute value of a number."),
11802
11790
  args: [arg("value (number)", _t("The number of which to return the absolute value."))],
11803
- returns: ["NUMBER"],
11804
11791
  compute: function (value) {
11805
11792
  return Math.abs(toNumber(value, this.locale));
11806
11793
  },
@@ -11814,7 +11801,6 @@ const ACOS = {
11814
11801
  args: [
11815
11802
  arg("value (number)", _t("The value for which to calculate the inverse cosine. Must be between -1 and 1, inclusive.")),
11816
11803
  ],
11817
- returns: ["NUMBER"],
11818
11804
  compute: function (value) {
11819
11805
  const _value = toNumber(value, this.locale);
11820
11806
  assert(() => Math.abs(_value) <= 1, _t("The value (%s) must be between -1 and 1 inclusive.", _value.toString()));
@@ -11830,7 +11816,6 @@ const ACOSH = {
11830
11816
  args: [
11831
11817
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic cosine. Must be greater than or equal to 1.")),
11832
11818
  ],
11833
- returns: ["NUMBER"],
11834
11819
  compute: function (value) {
11835
11820
  const _value = toNumber(value, this.locale);
11836
11821
  assert(() => _value >= 1, _t("The value (%s) must be greater than or equal to 1.", _value.toString()));
@@ -11844,7 +11829,6 @@ const ACOSH = {
11844
11829
  const ACOT = {
11845
11830
  description: _t("Inverse cotangent of a value."),
11846
11831
  args: [arg("value (number)", _t("The value for which to calculate the inverse cotangent."))],
11847
- returns: ["NUMBER"],
11848
11832
  compute: function (value) {
11849
11833
  const _value = toNumber(value, this.locale);
11850
11834
  const sign = Math.sign(_value) || 1;
@@ -11863,7 +11847,6 @@ const ACOTH = {
11863
11847
  args: [
11864
11848
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic cotangent. Must not be between -1 and 1, inclusive.")),
11865
11849
  ],
11866
- returns: ["NUMBER"],
11867
11850
  compute: function (value) {
11868
11851
  const _value = toNumber(value, this.locale);
11869
11852
  assert(() => Math.abs(_value) > 1, _t("The value (%s) cannot be between -1 and 1 inclusive.", _value.toString()));
@@ -11879,7 +11862,6 @@ const ASIN = {
11879
11862
  args: [
11880
11863
  arg("value (number)", _t("The value for which to calculate the inverse sine. Must be between -1 and 1, inclusive.")),
11881
11864
  ],
11882
- returns: ["NUMBER"],
11883
11865
  compute: function (value) {
11884
11866
  const _value = toNumber(value, this.locale);
11885
11867
  assert(() => Math.abs(_value) <= 1, _t("The value (%s) must be between -1 and 1 inclusive.", _value.toString()));
@@ -11895,7 +11877,6 @@ const ASINH = {
11895
11877
  args: [
11896
11878
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic sine.")),
11897
11879
  ],
11898
- returns: ["NUMBER"],
11899
11880
  compute: function (value) {
11900
11881
  return Math.asinh(toNumber(value, this.locale));
11901
11882
  },
@@ -11907,7 +11888,6 @@ const ASINH = {
11907
11888
  const ATAN = {
11908
11889
  description: _t("Inverse tangent of a value, in radians."),
11909
11890
  args: [arg("value (number)", _t("The value for which to calculate the inverse tangent."))],
11910
- returns: ["NUMBER"],
11911
11891
  compute: function (value) {
11912
11892
  return Math.atan(toNumber(value, this.locale));
11913
11893
  },
@@ -11922,7 +11902,6 @@ const ATAN2 = {
11922
11902
  arg("x (number)", _t("The x coordinate of the endpoint of the line segment for which to calculate the angle from the x-axis.")),
11923
11903
  arg("y (number)", _t("The y coordinate of the endpoint of the line segment for which to calculate the angle from the x-axis.")),
11924
11904
  ],
11925
- returns: ["NUMBER"],
11926
11905
  compute: function (x, y) {
11927
11906
  const _x = toNumber(x, this.locale);
11928
11907
  const _y = toNumber(y, this.locale);
@@ -11939,7 +11918,6 @@ const ATANH = {
11939
11918
  args: [
11940
11919
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic tangent. Must be between -1 and 1, exclusive.")),
11941
11920
  ],
11942
- returns: ["NUMBER"],
11943
11921
  compute: function (value) {
11944
11922
  const _value = toNumber(value, this.locale);
11945
11923
  assert(() => Math.abs(_value) < 1, _t("The value (%s) must be between -1 and 1 exclusive.", _value.toString()));
@@ -11956,7 +11934,6 @@ const CEILING = {
11956
11934
  arg("value (number)", _t("The value to round up to the nearest integer multiple of factor.")),
11957
11935
  arg(`factor (number, default=${DEFAULT_FACTOR})`, _t("The number to whose multiples value will be rounded.")),
11958
11936
  ],
11959
- returns: ["NUMBER"],
11960
11937
  compute: function (value, factor = { value: DEFAULT_FACTOR }) {
11961
11938
  const _value = toNumber(value, this.locale);
11962
11939
  const _factor = toNumber(factor, this.locale);
@@ -11991,7 +11968,6 @@ const CEILING_MATH = {
11991
11968
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded. The sign of significance will be ignored.")),
11992
11969
  arg(`mode (number, default=${DEFAULT_MODE})`, _t("If number is negative, specifies the rounding direction. If 0 or blank, it is rounded towards zero. Otherwise, it is rounded away from zero.")),
11993
11970
  ],
11994
- returns: ["NUMBER"],
11995
11971
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }, mode = { value: DEFAULT_MODE }) {
11996
11972
  const _significance = toNumber(significance, this.locale);
11997
11973
  const _number = toNumber(number, this.locale);
@@ -12012,7 +11988,6 @@ const CEILING_PRECISE = {
12012
11988
  arg("number (number)", _t("The value to round up to the nearest integer multiple of significance.")),
12013
11989
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded.")),
12014
11990
  ],
12015
- returns: ["NUMBER"],
12016
11991
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }) {
12017
11992
  const _significance = toNumber(significance, this.locale);
12018
11993
  const _number = toNumber(number, this.locale);
@@ -12029,7 +12004,6 @@ const CEILING_PRECISE = {
12029
12004
  const COS = {
12030
12005
  description: _t("Cosine of an angle provided in radians."),
12031
12006
  args: [arg("angle (number)", _t("The angle to find the cosine of, in radians."))],
12032
- returns: ["NUMBER"],
12033
12007
  compute: function (angle) {
12034
12008
  return Math.cos(toNumber(angle, this.locale));
12035
12009
  },
@@ -12041,7 +12015,6 @@ const COS = {
12041
12015
  const COSH = {
12042
12016
  description: _t("Hyperbolic cosine of any real number."),
12043
12017
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic cosine of."))],
12044
- returns: ["NUMBER"],
12045
12018
  compute: function (value) {
12046
12019
  return Math.cosh(toNumber(value, this.locale));
12047
12020
  },
@@ -12053,7 +12026,6 @@ const COSH = {
12053
12026
  const COT = {
12054
12027
  description: _t("Cotangent of an angle provided in radians."),
12055
12028
  args: [arg("angle (number)", _t("The angle to find the cotangent of, in radians."))],
12056
- returns: ["NUMBER"],
12057
12029
  compute: function (angle) {
12058
12030
  const _angle = toNumber(angle, this.locale);
12059
12031
  assertNotZero(_angle);
@@ -12067,7 +12039,6 @@ const COT = {
12067
12039
  const COTH = {
12068
12040
  description: _t("Hyperbolic cotangent of any real number."),
12069
12041
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic cotangent of."))],
12070
- returns: ["NUMBER"],
12071
12042
  compute: function (value) {
12072
12043
  const _value = toNumber(value, this.locale);
12073
12044
  assertNotZero(_value);
@@ -12084,7 +12055,6 @@ const COUNTBLANK = {
12084
12055
  arg("value1 (any, range)", _t("The first value or range in which to count the number of blanks.")),
12085
12056
  arg("value2 (any, range, repeating)", _t("Additional values or ranges in which to count the number of blanks.")),
12086
12057
  ],
12087
- returns: ["NUMBER"],
12088
12058
  compute: function (...args) {
12089
12059
  return reduceAny(args, (acc, a) => {
12090
12060
  if (a === undefined) {
@@ -12110,7 +12080,6 @@ const COUNTIF = {
12110
12080
  arg("range (range)", _t("The range that is tested against criterion.")),
12111
12081
  arg("criterion (string)", _t("The pattern or test to apply to range.")),
12112
12082
  ],
12113
- returns: ["NUMBER"],
12114
12083
  compute: function (...args) {
12115
12084
  let count = 0;
12116
12085
  visitMatchingRanges(args, (i, j) => {
@@ -12131,7 +12100,6 @@ const COUNTIFS = {
12131
12100
  arg("criteria_range2 (any, range, repeating)", _t("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
12132
12101
  arg("criterion2 (string, repeating)", _t("Additional criteria to check.")),
12133
12102
  ],
12134
- returns: ["NUMBER"],
12135
12103
  compute: function (...args) {
12136
12104
  let count = 0;
12137
12105
  visitMatchingRanges(args, (i, j) => {
@@ -12150,7 +12118,6 @@ const COUNTUNIQUE = {
12150
12118
  arg("value1 (any, range)", _t("The first value or range to consider for uniqueness.")),
12151
12119
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider for uniqueness.")),
12152
12120
  ],
12153
- returns: ["NUMBER"],
12154
12121
  compute: function (...args) {
12155
12122
  return countUnique(args);
12156
12123
  },
@@ -12167,7 +12134,6 @@ const COUNTUNIQUEIFS = {
12167
12134
  arg("criteria_range2 (any, range, repeating)", _t("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
12168
12135
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
12169
12136
  ],
12170
- returns: ["NUMBER"],
12171
12137
  compute: function (range, ...args) {
12172
12138
  let uniqueValues = new Set();
12173
12139
  visitMatchingRanges(args, (i, j) => {
@@ -12185,7 +12151,6 @@ const COUNTUNIQUEIFS = {
12185
12151
  const CSC = {
12186
12152
  description: _t("Cosecant of an angle provided in radians."),
12187
12153
  args: [arg("angle (number)", _t("The angle to find the cosecant of, in radians."))],
12188
- returns: ["NUMBER"],
12189
12154
  compute: function (angle) {
12190
12155
  const _angle = toNumber(angle, this.locale);
12191
12156
  assertNotZero(_angle);
@@ -12199,7 +12164,6 @@ const CSC = {
12199
12164
  const CSCH = {
12200
12165
  description: _t("Hyperbolic cosecant of any real number."),
12201
12166
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic cosecant of."))],
12202
- returns: ["NUMBER"],
12203
12167
  compute: function (value) {
12204
12168
  const _value = toNumber(value, this.locale);
12205
12169
  assertNotZero(_value);
@@ -12216,7 +12180,6 @@ const DECIMAL = {
12216
12180
  arg("value (string)", _t("The number to convert.")),
12217
12181
  arg("base (number)", _t("The base to convert the value from.")),
12218
12182
  ],
12219
- returns: ["NUMBER"],
12220
12183
  compute: function (value, base) {
12221
12184
  let _base = toNumber(base, this.locale);
12222
12185
  _base = Math.floor(_base);
@@ -12243,7 +12206,6 @@ const DECIMAL = {
12243
12206
  const DEGREES = {
12244
12207
  description: _t("Converts an angle value in radians to degrees."),
12245
12208
  args: [arg("angle (number)", _t("The angle to convert from radians to degrees."))],
12246
- returns: ["NUMBER"],
12247
12209
  compute: function (angle) {
12248
12210
  return (toNumber(angle, this.locale) * 180) / Math.PI;
12249
12211
  },
@@ -12255,7 +12217,6 @@ const DEGREES = {
12255
12217
  const EXP = {
12256
12218
  description: _t("Euler's number, e (~2.718) raised to a power."),
12257
12219
  args: [arg("value (number)", _t("The exponent to raise e."))],
12258
- returns: ["NUMBER"],
12259
12220
  compute: function (value) {
12260
12221
  return Math.exp(toNumber(value, this.locale));
12261
12222
  },
@@ -12270,7 +12231,6 @@ const FLOOR = {
12270
12231
  arg("value (number)", _t("The value to round down to the nearest integer multiple of factor.")),
12271
12232
  arg(`factor (number, default=${DEFAULT_FACTOR})`, _t("The number to whose multiples value will be rounded.")),
12272
12233
  ],
12273
- returns: ["NUMBER"],
12274
12234
  compute: function (value, factor = { value: DEFAULT_FACTOR }) {
12275
12235
  const _value = toNumber(value, this.locale);
12276
12236
  const _factor = toNumber(factor, this.locale);
@@ -12305,7 +12265,6 @@ const FLOOR_MATH = {
12305
12265
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded. The sign of significance will be ignored.")),
12306
12266
  arg(`mode (number, default=${DEFAULT_MODE})`, _t("If number is negative, specifies the rounding direction. If 0 or blank, it is rounded away from zero. Otherwise, it is rounded towards zero.")),
12307
12267
  ],
12308
- returns: ["NUMBER"],
12309
12268
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }, mode = { value: DEFAULT_MODE }) {
12310
12269
  const _significance = toNumber(significance, this.locale);
12311
12270
  const _number = toNumber(number, this.locale);
@@ -12326,7 +12285,6 @@ const FLOOR_PRECISE = {
12326
12285
  arg("number (number)", _t("The value to round down to the nearest integer multiple of significance.")),
12327
12286
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded.")),
12328
12287
  ],
12329
- returns: ["NUMBER"],
12330
12288
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }) {
12331
12289
  const _significance = toNumber(significance, this.locale);
12332
12290
  const _number = toNumber(number, this.locale);
@@ -12343,7 +12301,6 @@ const FLOOR_PRECISE = {
12343
12301
  const ISEVEN = {
12344
12302
  description: _t("Whether the provided value is even."),
12345
12303
  args: [arg("value (number)", _t("The value to be verified as even."))],
12346
- returns: ["BOOLEAN"],
12347
12304
  compute: function (value) {
12348
12305
  const _value = strictToNumber(value, this.locale);
12349
12306
  return Math.floor(Math.abs(_value)) & 1 ? false : true;
@@ -12359,7 +12316,6 @@ const ISO_CEILING = {
12359
12316
  arg("number (number)", _t("The value to round up to the nearest integer multiple of significance.")),
12360
12317
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded.")),
12361
12318
  ],
12362
- returns: ["NUMBER"],
12363
12319
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }) {
12364
12320
  const _number = toNumber(number, this.locale);
12365
12321
  const _significance = toNumber(significance, this.locale);
@@ -12376,7 +12332,6 @@ const ISO_CEILING = {
12376
12332
  const ISODD = {
12377
12333
  description: _t("Whether the provided value is even."),
12378
12334
  args: [arg("value (number)", _t("The value to be verified as even."))],
12379
- returns: ["BOOLEAN"],
12380
12335
  compute: function (value) {
12381
12336
  const _value = strictToNumber(value, this.locale);
12382
12337
  return Math.floor(Math.abs(_value)) & 1 ? true : false;
@@ -12389,7 +12344,6 @@ const ISODD = {
12389
12344
  const LN = {
12390
12345
  description: _t("The logarithm of a number, base e (euler's number)."),
12391
12346
  args: [arg("value (number)", _t("The value for which to calculate the logarithm, base e."))],
12392
- returns: ["NUMBER"],
12393
12347
  compute: function (value) {
12394
12348
  const _value = toNumber(value, this.locale);
12395
12349
  assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
@@ -12415,7 +12369,6 @@ const MOD = {
12415
12369
  arg("dividend (number)", _t("The number to be divided to find the remainder.")),
12416
12370
  arg("divisor (number)", _t("The number to divide by.")),
12417
12371
  ],
12418
- returns: ["NUMBER"],
12419
12372
  compute: function (dividend, divisor) {
12420
12373
  const _divisor = toNumber(divisor, this.locale);
12421
12374
  const _dividend = toNumber(dividend, this.locale);
@@ -12434,7 +12387,6 @@ const MUNIT = {
12434
12387
  args: [
12435
12388
  arg("dimension (number)", _t("An integer specifying the dimension size of the unit matrix. It must be positive.")),
12436
12389
  ],
12437
- returns: ["RANGE<NUMBER>"],
12438
12390
  compute: function (n) {
12439
12391
  const _n = toInteger(n, this.locale);
12440
12392
  assertPositive(_t("The argument dimension must be positive"), _n);
@@ -12448,7 +12400,6 @@ const MUNIT = {
12448
12400
  const ODD = {
12449
12401
  description: _t("Rounds a number up to the nearest odd integer."),
12450
12402
  args: [arg("value (number)", _t("The value to round to the next greatest odd number."))],
12451
- returns: ["NUMBER"],
12452
12403
  compute: function (value) {
12453
12404
  const _value = toNumber(value, this.locale);
12454
12405
  let temp = Math.ceil(Math.abs(_value));
@@ -12466,7 +12417,6 @@ const ODD = {
12466
12417
  const PI = {
12467
12418
  description: _t("The number pi."),
12468
12419
  args: [],
12469
- returns: ["NUMBER"],
12470
12420
  compute: function () {
12471
12421
  return Math.PI;
12472
12422
  },
@@ -12481,7 +12431,6 @@ const POWER = {
12481
12431
  arg("base (number)", _t("The number to raise to the exponent power.")),
12482
12432
  arg("exponent (number)", _t("The exponent to raise base to.")),
12483
12433
  ],
12484
- returns: ["NUMBER"],
12485
12434
  compute: function (base, exponent) {
12486
12435
  const _base = toNumber(base, this.locale);
12487
12436
  const _exponent = toNumber(exponent, this.locale);
@@ -12499,7 +12448,6 @@ const PRODUCT = {
12499
12448
  arg("factor1 (number, range<number>)", _t("The first number or range to calculate for the product.")),
12500
12449
  arg("factor2 (number, range<number>, repeating)", _t("More numbers or ranges to calculate for the product.")),
12501
12450
  ],
12502
- returns: ["NUMBER"],
12503
12451
  compute: function (...factors) {
12504
12452
  let count = 0;
12505
12453
  let acc = 1;
@@ -12536,7 +12484,6 @@ const PRODUCT = {
12536
12484
  const RAND = {
12537
12485
  description: _t("A random number between 0 inclusive and 1 exclusive."),
12538
12486
  args: [],
12539
- returns: ["NUMBER"],
12540
12487
  compute: function () {
12541
12488
  return Math.random();
12542
12489
  },
@@ -12554,7 +12501,6 @@ const RANDARRAY = {
12554
12501
  arg("max (number, default=1)", _t("The maximum number you would like returned.")),
12555
12502
  arg("whole_number (number, default=FALSE)", _t("Return a whole number or a decimal value.")),
12556
12503
  ],
12557
- returns: ["RANGE<NUMBER>"],
12558
12504
  compute: function (rows = { value: 1 }, columns = { value: 1 }, min = { value: 0 }, max = { value: 1 }, wholeNumber = { value: false }) {
12559
12505
  const _cols = toInteger(columns, this.locale);
12560
12506
  const _rows = toInteger(rows, this.locale);
@@ -12592,7 +12538,6 @@ const RANDBETWEEN = {
12592
12538
  arg("low (number)", _t("The low end of the random range.")),
12593
12539
  arg("high (number)", _t("The high end of the random range.")),
12594
12540
  ],
12595
- returns: ["NUMBER"],
12596
12541
  compute: function (low, high) {
12597
12542
  let _low = toNumber(low, this.locale);
12598
12543
  if (!Number.isInteger(_low)) {
@@ -12619,7 +12564,6 @@ const ROUND = {
12619
12564
  arg("value (number)", _t("The value to round to places number of places.")),
12620
12565
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of decimal places to which to round.")),
12621
12566
  ],
12622
- returns: ["NUMBER"],
12623
12567
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12624
12568
  const _value = toNumber(value, this.locale);
12625
12569
  let _places = toNumber(places, this.locale);
@@ -12650,7 +12594,6 @@ const ROUNDDOWN = {
12650
12594
  arg("value (number)", _t("The value to round to places number of places, always rounding down.")),
12651
12595
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of decimal places to which to round.")),
12652
12596
  ],
12653
- returns: ["NUMBER"],
12654
12597
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12655
12598
  const _value = toNumber(value, this.locale);
12656
12599
  let _places = toNumber(places, this.locale);
@@ -12681,7 +12624,6 @@ const ROUNDUP = {
12681
12624
  arg("value (number)", _t("The value to round to places number of places, always rounding up.")),
12682
12625
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of decimal places to which to round.")),
12683
12626
  ],
12684
- returns: ["NUMBER"],
12685
12627
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12686
12628
  const _value = toNumber(value, this.locale);
12687
12629
  let _places = toNumber(places, this.locale);
@@ -12709,7 +12651,6 @@ const ROUNDUP = {
12709
12651
  const SEC = {
12710
12652
  description: _t("Secant of an angle provided in radians."),
12711
12653
  args: [arg("angle (number)", _t("The angle to find the secant of, in radians."))],
12712
- returns: ["NUMBER"],
12713
12654
  compute: function (angle) {
12714
12655
  return 1 / Math.cos(toNumber(angle, this.locale));
12715
12656
  },
@@ -12721,7 +12662,6 @@ const SEC = {
12721
12662
  const SECH = {
12722
12663
  description: _t("Hyperbolic secant of any real number."),
12723
12664
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic secant of."))],
12724
- returns: ["NUMBER"],
12725
12665
  compute: function (value) {
12726
12666
  return 1 / Math.cosh(toNumber(value, this.locale));
12727
12667
  },
@@ -12733,7 +12673,6 @@ const SECH = {
12733
12673
  const SIN = {
12734
12674
  description: _t("Sine of an angle provided in radians."),
12735
12675
  args: [arg("angle (number)", _t("The angle to find the sine of, in radians."))],
12736
- returns: ["NUMBER"],
12737
12676
  compute: function (angle) {
12738
12677
  return Math.sin(toNumber(angle, this.locale));
12739
12678
  },
@@ -12745,7 +12684,6 @@ const SIN = {
12745
12684
  const SINH = {
12746
12685
  description: _t("Hyperbolic sine of any real number."),
12747
12686
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic sine of."))],
12748
- returns: ["NUMBER"],
12749
12687
  compute: function (value) {
12750
12688
  return Math.sinh(toNumber(value, this.locale));
12751
12689
  },
@@ -12757,7 +12695,6 @@ const SINH = {
12757
12695
  const SQRT = {
12758
12696
  description: _t("Positive square root of a positive number."),
12759
12697
  args: [arg("value (number)", _t("The number for which to calculate the positive square root."))],
12760
- returns: ["NUMBER"],
12761
12698
  compute: function (value) {
12762
12699
  const _value = toNumber(value, this.locale);
12763
12700
  assert(() => _value >= 0, _t("The value (%s) must be positive or null.", _value.toString()));
@@ -12774,7 +12711,6 @@ const SUM = {
12774
12711
  arg("value1 (number, range<number>)", _t("The first number or range to add together.")),
12775
12712
  arg("value2 (number, range<number>, repeating)", _t("Additional numbers or ranges to add to value1.")),
12776
12713
  ],
12777
- returns: ["NUMBER"],
12778
12714
  compute: function (...values) {
12779
12715
  const v1 = values[0];
12780
12716
  return {
@@ -12794,7 +12730,6 @@ const SUMIF = {
12794
12730
  arg("criterion (string)", _t("The pattern or test to apply to range.")),
12795
12731
  arg("sum_range (range, default=criteria_range)", _t("The range to be summed, if different from range.")),
12796
12732
  ],
12797
- returns: ["NUMBER"],
12798
12733
  compute: function (criteriaRange, criterion, sumRange) {
12799
12734
  if (sumRange === undefined) {
12800
12735
  sumRange = criteriaRange;
@@ -12822,7 +12757,6 @@ const SUMIFS = {
12822
12757
  arg("criteria_range2 (any, range, repeating)", _t("Additional ranges to check.")),
12823
12758
  arg("criterion2 (string, repeating)", _t("Additional criteria to check.")),
12824
12759
  ],
12825
- returns: ["NUMBER"],
12826
12760
  compute: function (sumRange, ...criters) {
12827
12761
  let sum = 0;
12828
12762
  visitMatchingRanges(criters, (i, j) => {
@@ -12841,7 +12775,6 @@ const SUMIFS = {
12841
12775
  const TAN = {
12842
12776
  description: _t("Tangent of an angle provided in radians."),
12843
12777
  args: [arg("angle (number)", _t("The angle to find the tangent of, in radians."))],
12844
- returns: ["NUMBER"],
12845
12778
  compute: function (angle) {
12846
12779
  return Math.tan(toNumber(angle, this.locale));
12847
12780
  },
@@ -12853,7 +12786,6 @@ const TAN = {
12853
12786
  const TANH = {
12854
12787
  description: _t("Hyperbolic tangent of any real number."),
12855
12788
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic tangent of."))],
12856
- returns: ["NUMBER"],
12857
12789
  compute: function (value) {
12858
12790
  return Math.tanh(toNumber(value, this.locale));
12859
12791
  },
@@ -12877,7 +12809,6 @@ const TRUNC = {
12877
12809
  arg("value (number)", _t("The value to be truncated.")),
12878
12810
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of significant digits to the right of the decimal point to retain.")),
12879
12811
  ],
12880
- returns: ["NUMBER"],
12881
12812
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12882
12813
  const _value = toNumber(value, this.locale);
12883
12814
  const _places = toNumber(places, this.locale);
@@ -12891,7 +12822,6 @@ const TRUNC = {
12891
12822
  const INT = {
12892
12823
  description: _t("Rounds a number down to the nearest integer that is less than or equal to it."),
12893
12824
  args: [arg("value (number)", _t("The number to round down to the nearest integer."))],
12894
- returns: ["NUMBER"],
12895
12825
  compute: function (value) {
12896
12826
  return Math.floor(toNumber(value, this.locale));
12897
12827
  },
@@ -13250,7 +13180,6 @@ const AVEDEV = {
13250
13180
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
13251
13181
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
13252
13182
  ],
13253
- returns: ["NUMBER"],
13254
13183
  compute: function (...values) {
13255
13184
  let count = 0;
13256
13185
  const sum = reduceNumbers(values, (acc, a) => {
@@ -13272,7 +13201,6 @@ const AVERAGE = {
13272
13201
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the average value.")),
13273
13202
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the average value.")),
13274
13203
  ],
13275
- returns: ["NUMBER"],
13276
13204
  compute: function (...values) {
13277
13205
  return {
13278
13206
  value: average(values, this.locale),
@@ -13294,7 +13222,6 @@ const AVERAGE_WEIGHTED = {
13294
13222
  arg("additional_values (number, range<number>, repeating)", _t("Additional values to average.")),
13295
13223
  arg("additional_weights (number, range<number>, repeating)", _t("Additional weights.")),
13296
13224
  ],
13297
- returns: ["NUMBER"],
13298
13225
  compute: function (...args) {
13299
13226
  let sum = 0;
13300
13227
  let count = 0;
@@ -13342,7 +13269,6 @@ const AVERAGEA = {
13342
13269
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the average value.")),
13343
13270
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the average value.")),
13344
13271
  ],
13345
- returns: ["NUMBER"],
13346
13272
  compute: function (...args) {
13347
13273
  let count = 0;
13348
13274
  const sum = reduceNumbersTextAs0(args, (acc, a) => {
@@ -13367,7 +13293,6 @@ const AVERAGEIF = {
13367
13293
  arg("criterion (string)", _t("The pattern or test to apply to criteria_range.")),
13368
13294
  arg("average_range (number, range<number>, default=criteria_range)", _t("The range to average. If not included, criteria_range is used for the average instead.")),
13369
13295
  ],
13370
- returns: ["NUMBER"],
13371
13296
  compute: function (criteriaRange, criterion, averageRange) {
13372
13297
  const _averageRange = averageRange === undefined ? toMatrix(criteriaRange) : toMatrix(averageRange);
13373
13298
  let count = 0;
@@ -13396,7 +13321,6 @@ const AVERAGEIFS = {
13396
13321
  arg("criteria_range2 (any, range, repeating)", _t("Additional criteria_range and criterion to check.")),
13397
13322
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
13398
13323
  ],
13399
- returns: ["NUMBER"],
13400
13324
  compute: function (averageRange, ...args) {
13401
13325
  const _averageRange = toMatrix(averageRange);
13402
13326
  let count = 0;
@@ -13422,7 +13346,6 @@ const COUNT = {
13422
13346
  arg("value1 (number, range<number>)", _t("The first value or range to consider when counting.")),
13423
13347
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when counting.")),
13424
13348
  ],
13425
- returns: ["NUMBER"],
13426
13349
  compute: function (...values) {
13427
13350
  return countNumbers(values, this.locale);
13428
13351
  },
@@ -13437,7 +13360,6 @@ const COUNTA = {
13437
13360
  arg("value1 (any, range)", _t("The first value or range to consider when counting.")),
13438
13361
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider when counting.")),
13439
13362
  ],
13440
- returns: ["NUMBER"],
13441
13363
  compute: function (...values) {
13442
13364
  return countAny(values);
13443
13365
  },
@@ -13454,7 +13376,6 @@ const COVAR = {
13454
13376
  arg("data_y (any, range)", _t("The range representing the array or matrix of dependent data.")),
13455
13377
  arg("data_x (any, range)", _t("The range representing the array or matrix of independent data.")),
13456
13378
  ],
13457
- returns: ["NUMBER"],
13458
13379
  compute: function (dataY, dataX) {
13459
13380
  return covariance(dataY, dataX, false);
13460
13381
  },
@@ -13469,7 +13390,6 @@ const COVARIANCE_P = {
13469
13390
  arg("data_y (any, range)", _t("The range representing the array or matrix of dependent data.")),
13470
13391
  arg("data_x (any, range)", _t("The range representing the array or matrix of independent data.")),
13471
13392
  ],
13472
- returns: ["NUMBER"],
13473
13393
  compute: function (dataY, dataX) {
13474
13394
  return covariance(dataY, dataX, false);
13475
13395
  },
@@ -13484,7 +13404,6 @@ const COVARIANCE_S = {
13484
13404
  arg("data_y (any, range)", _t("The range representing the array or matrix of dependent data.")),
13485
13405
  arg("data_x (any, range)", _t("The range representing the array or matrix of independent data.")),
13486
13406
  ],
13487
- returns: ["NUMBER"],
13488
13407
  compute: function (dataY, dataX) {
13489
13408
  return covariance(dataY, dataX, true);
13490
13409
  },
@@ -13500,7 +13419,6 @@ const FORECAST = {
13500
13419
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
13501
13420
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13502
13421
  ],
13503
- returns: ["NUMBER"],
13504
13422
  compute: function (x, dataY, dataX) {
13505
13423
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13506
13424
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
@@ -13518,7 +13436,6 @@ const GROWTH = {
13518
13436
  arg("new_data_x (any, range, default=known_data_x)", _t("The data points to return the y values for on the ideal curve fit.")),
13519
13437
  arg("b (boolean, default=TRUE)", _t("Given a general exponential form of y = b*m^x for a curve fit, calculates b if TRUE or forces b to be 1 and only calculates the m values if FALSE.")),
13520
13438
  ],
13521
- returns: ["NUMBER"],
13522
13439
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13523
13440
  return expM(predictLinearValues(logM(toNumberMatrix(knownDataY, "the first argument (known_data_y)")), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
13524
13441
  },
@@ -13532,7 +13449,6 @@ const INTERCEPT = {
13532
13449
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
13533
13450
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13534
13451
  ],
13535
- returns: ["NUMBER"],
13536
13452
  compute: function (dataY, dataX) {
13537
13453
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13538
13454
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
@@ -13549,7 +13465,6 @@ const LARGE = {
13549
13465
  arg("data (any, range)", _t("Array or range containing the dataset to consider.")),
13550
13466
  arg("n (number)", _t("The rank from largest to smallest of the element to return.")),
13551
13467
  ],
13552
- returns: ["NUMBER"],
13553
13468
  compute: function (data, n) {
13554
13469
  const _n = Math.trunc(toNumber(n?.value, this.locale));
13555
13470
  let largests = [];
@@ -13584,7 +13499,6 @@ const LINEST = {
13584
13499
  arg("calculate_b (boolean, default=TRUE)", _t("A flag specifying wheter to compute the slope or not")),
13585
13500
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13586
13501
  ],
13587
- returns: ["NUMBER"],
13588
13502
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13589
13503
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
13590
13504
  },
@@ -13601,7 +13515,6 @@ const LOGEST = {
13601
13515
  arg("calculate_b (boolean, default=TRUE)", _t("A flag specifying wheter to compute the slope or not")),
13602
13516
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13603
13517
  ],
13604
- returns: ["NUMBER"],
13605
13518
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13606
13519
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
13607
13520
  for (let i = 0; i < coeffs.length; i++) {
@@ -13620,7 +13533,6 @@ const MATTHEWS = {
13620
13533
  arg("data_x (range)", _t("The range representing the array or matrix of observed data.")),
13621
13534
  arg("data_y (range)", _t("The range representing the array or matrix of predicted data.")),
13622
13535
  ],
13623
- returns: ["NUMBER"],
13624
13536
  compute: function (dataX, dataY) {
13625
13537
  const flatX = dataX.flat();
13626
13538
  const flatY = dataY.flat();
@@ -13664,7 +13576,6 @@ const MAX = {
13664
13576
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the maximum value.")),
13665
13577
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the maximum value.")),
13666
13578
  ],
13667
- returns: ["NUMBER"],
13668
13579
  compute: function (...values) {
13669
13580
  return {
13670
13581
  value: max(values, this.locale),
@@ -13682,7 +13593,6 @@ const MAXA = {
13682
13593
  arg("value1 (any, range)", _t("The first value or range to consider when calculating the maximum value.")),
13683
13594
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider when calculating the maximum value.")),
13684
13595
  ],
13685
- returns: ["NUMBER"],
13686
13596
  compute: function (...args) {
13687
13597
  const maxa = reduceNumbersTextAs0(args, (acc, a) => {
13688
13598
  return Math.max(a, acc);
@@ -13703,7 +13613,6 @@ const MAXIFS = {
13703
13613
  arg("criteria_range2 (any, range, repeating)", _t("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
13704
13614
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
13705
13615
  ],
13706
- returns: ["NUMBER"],
13707
13616
  compute: function (range, ...args) {
13708
13617
  let result = -Infinity;
13709
13618
  visitMatchingRanges(args, (i, j) => {
@@ -13725,7 +13634,6 @@ const MEDIAN = {
13725
13634
  arg("value1 (any, range)", _t("The first value or range to consider when calculating the median value.")),
13726
13635
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider when calculating the median value.")),
13727
13636
  ],
13728
- returns: ["NUMBER"],
13729
13637
  compute: function (...values) {
13730
13638
  let data = [];
13731
13639
  visitNumbers(values, (value) => {
@@ -13747,7 +13655,6 @@ const MIN = {
13747
13655
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the minimum value.")),
13748
13656
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the minimum value.")),
13749
13657
  ],
13750
- returns: ["NUMBER"],
13751
13658
  compute: function (...values) {
13752
13659
  return {
13753
13660
  value: min(values, this.locale),
@@ -13765,7 +13672,6 @@ const MINA = {
13765
13672
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the minimum value.")),
13766
13673
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the minimum value.")),
13767
13674
  ],
13768
- returns: ["NUMBER"],
13769
13675
  compute: function (...args) {
13770
13676
  const mina = reduceNumbersTextAs0(args, (acc, a) => {
13771
13677
  return Math.min(a, acc);
@@ -13786,7 +13692,6 @@ const MINIFS = {
13786
13692
  arg("criteria_range2 (any, range, repeating)", _t("Additional ranges over which to evaluate the additional criteria. The filtered set will be the intersection of the sets produced by each criterion-range pair.")),
13787
13693
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
13788
13694
  ],
13789
- returns: ["NUMBER"],
13790
13695
  compute: function (range, ...args) {
13791
13696
  let result = Infinity;
13792
13697
  visitMatchingRanges(args, (i, j) => {
@@ -13829,7 +13734,6 @@ const PEARSON = {
13829
13734
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
13830
13735
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13831
13736
  ],
13832
- returns: ["NUMBER"],
13833
13737
  compute: function (dataY, dataX) {
13834
13738
  return pearson(dataY, dataX);
13835
13739
  },
@@ -13846,7 +13750,6 @@ const PERCENTILE = {
13846
13750
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13847
13751
  arg("percentile (number)", _t("The percentile whose value within data will be calculated and returned.")),
13848
13752
  ],
13849
- returns: ["NUMBER"],
13850
13753
  compute: function (data, percentile) {
13851
13754
  return PERCENTILE_INC.compute.bind(this)(data, percentile);
13852
13755
  },
@@ -13861,7 +13764,6 @@ const PERCENTILE_EXC = {
13861
13764
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13862
13765
  arg("percentile (number)", _t("The percentile, exclusive of 0 and 1, whose value within 'data' will be calculated and returned.")),
13863
13766
  ],
13864
- returns: ["NUMBER"],
13865
13767
  compute: function (data, percentile) {
13866
13768
  return {
13867
13769
  value: centile([data], percentile, false, this.locale),
@@ -13879,7 +13781,6 @@ const PERCENTILE_INC = {
13879
13781
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13880
13782
  arg("percentile (number)", _t("The percentile whose value within data will be calculated and returned.")),
13881
13783
  ],
13882
- returns: ["NUMBER"],
13883
13784
  compute: function (data, percentile) {
13884
13785
  return {
13885
13786
  value: centile([data], percentile, true, this.locale),
@@ -13899,7 +13800,6 @@ const POLYFIT_COEFFS = {
13899
13800
  arg("order (number)", _t("The order of the polynomial to fit the data, between 1 and 6.")),
13900
13801
  arg("intercept (boolean, default=TRUE)", _t("A flag specifying whether to compute the intercept or not.")),
13901
13802
  ],
13902
- returns: ["RANGE<NUMBER>"],
13903
13803
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13904
13804
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13905
13805
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
@@ -13918,7 +13818,6 @@ const POLYFIT_FORECAST = {
13918
13818
  arg("order (number)", _t("The order of the polynomial to fit the data, between 1 and 6.")),
13919
13819
  arg("intercept (boolean, default=TRUE)", _t("A flag specifying whether to compute the intercept or not.")),
13920
13820
  ],
13921
- returns: ["NUMBER"],
13922
13821
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13923
13822
  const _order = toNumber(order, this.locale);
13924
13823
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
@@ -13936,7 +13835,6 @@ const QUARTILE = {
13936
13835
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13937
13836
  arg("quartile_number (number)", _t("Which quartile value to return.")),
13938
13837
  ],
13939
- returns: ["NUMBER"],
13940
13838
  compute: function (data, quartileNumber) {
13941
13839
  return QUARTILE_INC.compute.bind(this)(data, quartileNumber);
13942
13840
  },
@@ -13951,7 +13849,6 @@ const QUARTILE_EXC = {
13951
13849
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13952
13850
  arg("quartile_number (number)", _t("Which quartile value, exclusive of 0 and 4, to return.")),
13953
13851
  ],
13954
- returns: ["NUMBER"],
13955
13852
  compute: function (data, quartileNumber) {
13956
13853
  const _quartileNumber = Math.trunc(toNumber(quartileNumber, this.locale));
13957
13854
  const percent = { value: 0.25 * _quartileNumber };
@@ -13971,7 +13868,6 @@ const QUARTILE_INC = {
13971
13868
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13972
13869
  arg("quartile_number (number)", _t("Which quartile value to return.")),
13973
13870
  ],
13974
- returns: ["NUMBER"],
13975
13871
  compute: function (data, quartileNumber) {
13976
13872
  const percent = { value: 0.25 * Math.trunc(toNumber(quartileNumber, this.locale)) };
13977
13873
  return {
@@ -13990,7 +13886,6 @@ const RANK = {
13990
13886
  arg("data (range)", _t("The range containing the dataset to consider.")),
13991
13887
  arg("is_ascending (boolean, default=FALSE)", _t("Whether to consider the values in data in descending or ascending order.")),
13992
13888
  ],
13993
- returns: ["ANY"],
13994
13889
  compute: function (value, data, isAscending = { value: false }) {
13995
13890
  const _isAscending = toBoolean(isAscending);
13996
13891
  const _value = toNumber(value, this.locale);
@@ -14026,7 +13921,6 @@ const RSQ = {
14026
13921
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14027
13922
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14028
13923
  ],
14029
- returns: ["NUMBER"],
14030
13924
  compute: function (dataY, dataX) {
14031
13925
  return Math.pow(pearson(dataX, dataY), 2.0);
14032
13926
  },
@@ -14041,7 +13935,6 @@ const SLOPE = {
14041
13935
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14042
13936
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14043
13937
  ],
14044
- returns: ["NUMBER"],
14045
13938
  compute: function (dataY, dataX) {
14046
13939
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
14047
13940
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
@@ -14058,7 +13951,6 @@ const SMALL = {
14058
13951
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
14059
13952
  arg("n (number)", _t("The rank from smallest to largest of the element to return.")),
14060
13953
  ],
14061
- returns: ["NUMBER"],
14062
13954
  compute: function (data, n) {
14063
13955
  const _n = Math.trunc(toNumber(n?.value, this.locale));
14064
13956
  let largests = [];
@@ -14091,7 +13983,6 @@ const SPEARMAN = {
14091
13983
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14092
13984
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14093
13985
  ],
14094
- returns: ["NUMBER"],
14095
13986
  compute: function (dataX, dataY) {
14096
13987
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
14097
13988
  const n = flatDataX.length;
@@ -14118,7 +14009,6 @@ const STDEV = {
14118
14009
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14119
14010
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14120
14011
  ],
14121
- returns: ["NUMBER"],
14122
14012
  compute: function (...args) {
14123
14013
  return Math.sqrt(VAR.compute.bind(this)(...args));
14124
14014
  },
@@ -14133,7 +14023,6 @@ const STDEV_P = {
14133
14023
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14134
14024
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14135
14025
  ],
14136
- returns: ["NUMBER"],
14137
14026
  compute: function (...args) {
14138
14027
  return Math.sqrt(VAR_P.compute.bind(this)(...args));
14139
14028
  },
@@ -14148,7 +14037,6 @@ const STDEV_S = {
14148
14037
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14149
14038
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14150
14039
  ],
14151
- returns: ["NUMBER"],
14152
14040
  compute: function (...args) {
14153
14041
  return Math.sqrt(VAR_S.compute.bind(this)(...args));
14154
14042
  },
@@ -14163,7 +14051,6 @@ const STDEVA = {
14163
14051
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14164
14052
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14165
14053
  ],
14166
- returns: ["NUMBER"],
14167
14054
  compute: function (...args) {
14168
14055
  return Math.sqrt(VARA.compute.bind(this)(...args));
14169
14056
  },
@@ -14178,7 +14065,6 @@ const STDEVP = {
14178
14065
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14179
14066
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14180
14067
  ],
14181
- returns: ["NUMBER"],
14182
14068
  compute: function (...args) {
14183
14069
  return Math.sqrt(VARP.compute.bind(this)(...args));
14184
14070
  },
@@ -14193,7 +14079,6 @@ const STDEVPA = {
14193
14079
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14194
14080
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14195
14081
  ],
14196
- returns: ["NUMBER"],
14197
14082
  compute: function (...args) {
14198
14083
  return Math.sqrt(VARPA.compute.bind(this)(...args));
14199
14084
  },
@@ -14208,7 +14093,6 @@ const STEYX = {
14208
14093
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14209
14094
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14210
14095
  ],
14211
- returns: ["NUMBER"],
14212
14096
  compute: function (dataY, dataX) {
14213
14097
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
14214
14098
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
@@ -14227,7 +14111,6 @@ const TREND = {
14227
14111
  arg("new_data_x (number, range<number>, optional, default=known_data_x)", _t("The data points to return the y values for on the ideal curve fit.")),
14228
14112
  arg("b (boolean, optional, default=TRUE)", _t("Given a general linear form of y = m*x+b for a curve fit, calculates b if TRUE or forces b to be 0 and only calculates the m values if FALSE, i.e. forces the curve fit to pass through the origin.")),
14229
14113
  ],
14230
- returns: ["NUMBER"],
14231
14114
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
14232
14115
  return predictLinearValues(toNumberMatrix(knownDataY, "the first argument (known_data_y)"), toNumberMatrix(knownDataX, "the second argument (known_data_x)"), toNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
14233
14116
  },
@@ -14241,7 +14124,6 @@ const VAR = {
14241
14124
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14242
14125
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14243
14126
  ],
14244
- returns: ["NUMBER"],
14245
14127
  compute: function (...args) {
14246
14128
  return variance(args, true, false, this.locale);
14247
14129
  },
@@ -14256,7 +14138,6 @@ const VAR_P = {
14256
14138
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14257
14139
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14258
14140
  ],
14259
- returns: ["NUMBER"],
14260
14141
  compute: function (...args) {
14261
14142
  return variance(args, false, false, this.locale);
14262
14143
  },
@@ -14271,7 +14152,6 @@ const VAR_S = {
14271
14152
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14272
14153
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14273
14154
  ],
14274
- returns: ["NUMBER"],
14275
14155
  compute: function (...args) {
14276
14156
  return variance(args, true, false, this.locale);
14277
14157
  },
@@ -14286,7 +14166,6 @@ const VARA = {
14286
14166
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14287
14167
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14288
14168
  ],
14289
- returns: ["NUMBER"],
14290
14169
  compute: function (...args) {
14291
14170
  return variance(args, true, true, this.locale);
14292
14171
  },
@@ -14301,7 +14180,6 @@ const VARP = {
14301
14180
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14302
14181
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14303
14182
  ],
14304
- returns: ["NUMBER"],
14305
14183
  compute: function (...args) {
14306
14184
  return variance(args, false, false, this.locale);
14307
14185
  },
@@ -14316,7 +14194,6 @@ const VARPA = {
14316
14194
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14317
14195
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14318
14196
  ],
14319
- returns: ["NUMBER"],
14320
14197
  compute: function (...args) {
14321
14198
  return variance(args, false, true, this.locale);
14322
14199
  },
@@ -14482,7 +14359,6 @@ const databaseArgs = [
14482
14359
  const DAVERAGE = {
14483
14360
  description: _t("Average of a set of values from a table-like range."),
14484
14361
  args: databaseArgs,
14485
- returns: ["NUMBER"],
14486
14362
  compute: function (database, field, criteria) {
14487
14363
  const cells = getMatchingCells(database, field, criteria, this.locale);
14488
14364
  return AVERAGE.compute.bind(this)([cells]);
@@ -14495,7 +14371,6 @@ const DAVERAGE = {
14495
14371
  const DCOUNT = {
14496
14372
  description: _t("Counts values from a table-like range."),
14497
14373
  args: databaseArgs,
14498
- returns: ["NUMBER"],
14499
14374
  compute: function (database, field, criteria) {
14500
14375
  const cells = getMatchingCells(database, field, criteria, this.locale);
14501
14376
  return COUNT.compute.bind(this)([cells]);
@@ -14508,7 +14383,6 @@ const DCOUNT = {
14508
14383
  const DCOUNTA = {
14509
14384
  description: _t("Counts values and text from a table-like range."),
14510
14385
  args: databaseArgs,
14511
- returns: ["NUMBER"],
14512
14386
  compute: function (database, field, criteria) {
14513
14387
  const cells = getMatchingCells(database, field, criteria, this.locale);
14514
14388
  return COUNTA.compute.bind(this)([cells]);
@@ -14521,7 +14395,6 @@ const DCOUNTA = {
14521
14395
  const DGET = {
14522
14396
  description: _t("Single value from a table-like range."),
14523
14397
  args: databaseArgs,
14524
- returns: ["NUMBER"],
14525
14398
  compute: function (database, field, criteria) {
14526
14399
  const cells = getMatchingCells(database, field, criteria, this.locale);
14527
14400
  assert(() => cells.length === 1, _t("More than one match found in DGET evaluation."));
@@ -14535,7 +14408,6 @@ const DGET = {
14535
14408
  const DMAX = {
14536
14409
  description: _t("Maximum of values from a table-like range."),
14537
14410
  args: databaseArgs,
14538
- returns: ["NUMBER"],
14539
14411
  compute: function (database, field, criteria) {
14540
14412
  const cells = getMatchingCells(database, field, criteria, this.locale);
14541
14413
  return MAX.compute.bind(this)([cells]);
@@ -14548,7 +14420,6 @@ const DMAX = {
14548
14420
  const DMIN = {
14549
14421
  description: _t("Minimum of values from a table-like range."),
14550
14422
  args: databaseArgs,
14551
- returns: ["NUMBER"],
14552
14423
  compute: function (database, field, criteria) {
14553
14424
  const cells = getMatchingCells(database, field, criteria, this.locale);
14554
14425
  return MIN.compute.bind(this)([cells]);
@@ -14561,7 +14432,6 @@ const DMIN = {
14561
14432
  const DPRODUCT = {
14562
14433
  description: _t("Product of values from a table-like range."),
14563
14434
  args: databaseArgs,
14564
- returns: ["NUMBER"],
14565
14435
  compute: function (database, field, criteria) {
14566
14436
  const cells = getMatchingCells(database, field, criteria, this.locale);
14567
14437
  return PRODUCT.compute.bind(this)([cells]);
@@ -14574,7 +14444,6 @@ const DPRODUCT = {
14574
14444
  const DSTDEV = {
14575
14445
  description: _t("Standard deviation of population sample from table."),
14576
14446
  args: databaseArgs,
14577
- returns: ["NUMBER"],
14578
14447
  compute: function (database, field, criteria) {
14579
14448
  const cells = getMatchingCells(database, field, criteria, this.locale);
14580
14449
  return STDEV.compute.bind(this)([cells]);
@@ -14587,7 +14456,6 @@ const DSTDEV = {
14587
14456
  const DSTDEVP = {
14588
14457
  description: _t("Standard deviation of entire population from table."),
14589
14458
  args: databaseArgs,
14590
- returns: ["NUMBER"],
14591
14459
  compute: function (database, field, criteria) {
14592
14460
  const cells = getMatchingCells(database, field, criteria, this.locale);
14593
14461
  return STDEVP.compute.bind(this)([cells]);
@@ -14600,7 +14468,6 @@ const DSTDEVP = {
14600
14468
  const DSUM = {
14601
14469
  description: _t("Sum of values from a table-like range."),
14602
14470
  args: databaseArgs,
14603
- returns: ["NUMBER"],
14604
14471
  compute: function (database, field, criteria) {
14605
14472
  const cells = getMatchingCells(database, field, criteria, this.locale);
14606
14473
  return SUM.compute.bind(this)([cells]);
@@ -14613,7 +14480,6 @@ const DSUM = {
14613
14480
  const DVAR = {
14614
14481
  description: _t("Variance of population sample from table-like range."),
14615
14482
  args: databaseArgs,
14616
- returns: ["NUMBER"],
14617
14483
  compute: function (database, field, criteria) {
14618
14484
  const cells = getMatchingCells(database, field, criteria, this.locale);
14619
14485
  return VAR.compute.bind(this)([cells]);
@@ -14626,7 +14492,6 @@ const DVAR = {
14626
14492
  const DVARP = {
14627
14493
  description: _t("Variance of a population from a table-like range."),
14628
14494
  args: databaseArgs,
14629
- returns: ["NUMBER"],
14630
14495
  compute: function (database, field, criteria) {
14631
14496
  const cells = getMatchingCells(database, field, criteria, this.locale);
14632
14497
  return VARP.compute.bind(this)([cells]);
@@ -14671,7 +14536,6 @@ const DATE = {
14671
14536
  arg("month (number)", _t("The month component of the date.")),
14672
14537
  arg("day (number)", _t("The day component of the date.")),
14673
14538
  ],
14674
- returns: ["DATE"],
14675
14539
  compute: function (year, month, day) {
14676
14540
  let _year = Math.trunc(toNumber(year, this.locale));
14677
14541
  const _month = Math.trunc(toNumber(month, this.locale));
@@ -14702,7 +14566,6 @@ const DATEDIF = {
14702
14566
  arg("end_date (date)", _t("The end date to consider in the calculation. Must be a reference to a cell containing a DATE, a function returning a DATE type, or a number.")),
14703
14567
  arg("unit (string)", _t('A text abbreviation for unit of time. Accepted values are "Y" (the number of whole years between start_date and end_date), "M" (the number of whole months between start_date and end_date), "D" (the number of days between start_date and end_date), "MD" (the number of days between start_date and end_date after subtracting whole months), "YM" (the number of whole months between start_date and end_date after subtracting whole years), "YD" (the number of days between start_date and end_date, assuming start_date and end_date were no more than one year apart).')),
14704
14568
  ],
14705
- returns: ["NUMBER"],
14706
14569
  compute: function (startDate, endDate, unit) {
14707
14570
  const _unit = toString(unit).toUpperCase();
14708
14571
  assert(() => Object.values(TIME_UNIT).includes(_unit), expectStringSetError(Object.values(TIME_UNIT), toString(unit)));
@@ -14755,7 +14618,6 @@ const DATEDIF = {
14755
14618
  const DATEVALUE = {
14756
14619
  description: _t("Converts a date string to a date value."),
14757
14620
  args: [arg("date_string (string)", _t("The string representing the date."))],
14758
- returns: ["NUMBER"],
14759
14621
  compute: function (dateString) {
14760
14622
  const _dateString = toString(dateString);
14761
14623
  const internalDate = parseDateTime(_dateString, this.locale);
@@ -14770,7 +14632,6 @@ const DATEVALUE = {
14770
14632
  const DAY = {
14771
14633
  description: _t("Day of the month that a specific date falls on."),
14772
14634
  args: [arg("date (string)", _t("The date from which to extract the day."))],
14773
- returns: ["NUMBER"],
14774
14635
  compute: function (date) {
14775
14636
  return toJsDate(date, this.locale).getDate();
14776
14637
  },
@@ -14785,7 +14646,6 @@ const DAYS = {
14785
14646
  arg("end_date (date)", _t("The end of the date range.")),
14786
14647
  arg("start_date (date)", _t("The start of the date range.")),
14787
14648
  ],
14788
- returns: ["NUMBER"],
14789
14649
  compute: function (endDate, startDate) {
14790
14650
  const _endDate = toJsDate(endDate, this.locale);
14791
14651
  const _startDate = toJsDate(startDate, this.locale);
@@ -14805,7 +14665,6 @@ const DAYS360 = {
14805
14665
  arg("end_date (date)", _t("The end date to consider in the calculation.")),
14806
14666
  arg(`method (number, default=${DEFAULT_DAY_COUNT_METHOD})`, _t("An indicator of what day count method to use. (0) US NASD method (1) European method")),
14807
14667
  ],
14808
- returns: ["NUMBER"],
14809
14668
  compute: function (startDate, endDate, method = { value: DEFAULT_DAY_COUNT_METHOD }) {
14810
14669
  const _startDate = Math.trunc(toNumber(startDate, this.locale));
14811
14670
  const _endDate = Math.trunc(toNumber(endDate, this.locale));
@@ -14824,7 +14683,6 @@ const EDATE = {
14824
14683
  arg("start_date (date)", _t("The date from which to calculate the result.")),
14825
14684
  arg("months (number)", _t("The number of months before (negative) or after (positive) 'start_date' to calculate.")),
14826
14685
  ],
14827
- returns: ["DATE"],
14828
14686
  compute: function (startDate, months) {
14829
14687
  const _startDate = toJsDate(startDate, this.locale);
14830
14688
  const _months = Math.trunc(toNumber(months, this.locale));
@@ -14845,7 +14703,6 @@ const EOMONTH = {
14845
14703
  arg("start_date (date)", _t("The date from which to calculate the result.")),
14846
14704
  arg("months (number)", _t("The number of months before (negative) or after (positive) 'start_date' to consider.")),
14847
14705
  ],
14848
- returns: ["DATE"],
14849
14706
  compute: function (startDate, months) {
14850
14707
  const _startDate = toJsDate(startDate, this.locale);
14851
14708
  const _months = Math.trunc(toNumber(months, this.locale));
@@ -14865,7 +14722,6 @@ const EOMONTH = {
14865
14722
  const HOUR = {
14866
14723
  description: _t("Hour component of a specific time."),
14867
14724
  args: [arg("time (date)", _t("The time from which to calculate the hour component."))],
14868
- returns: ["NUMBER"],
14869
14725
  compute: function (date) {
14870
14726
  return toJsDate(date, this.locale).getHours();
14871
14727
  },
@@ -14879,7 +14735,6 @@ const ISOWEEKNUM = {
14879
14735
  args: [
14880
14736
  arg("date (date)", _t("The date for which to determine the ISO week number. Must be a reference to a cell containing a date, a function returning a date type, or a number.")),
14881
14737
  ],
14882
- returns: ["NUMBER"],
14883
14738
  compute: function (date) {
14884
14739
  const _date = toJsDate(date, this.locale);
14885
14740
  const y = _date.getFullYear();
@@ -14951,7 +14806,6 @@ const ISOWEEKNUM = {
14951
14806
  const MINUTE = {
14952
14807
  description: _t("Minute component of a specific time."),
14953
14808
  args: [arg("time (date)", _t("The time from which to calculate the minute component."))],
14954
- returns: ["NUMBER"],
14955
14809
  compute: function (date) {
14956
14810
  return toJsDate(date, this.locale).getMinutes();
14957
14811
  },
@@ -14963,7 +14817,6 @@ const MINUTE = {
14963
14817
  const MONTH = {
14964
14818
  description: _t("Month of the year a specific date falls in"),
14965
14819
  args: [arg("date (date)", _t("The date from which to extract the month."))],
14966
- returns: ["NUMBER"],
14967
14820
  compute: function (date) {
14968
14821
  return toJsDate(date, this.locale).getMonth() + 1;
14969
14822
  },
@@ -14979,7 +14832,6 @@ const NETWORKDAYS = {
14979
14832
  arg("end_date (date)", _t("The end date of the period from which to calculate the number of net working days.")),
14980
14833
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the date serial numbers to consider holidays.")),
14981
14834
  ],
14982
- returns: ["NUMBER"],
14983
14835
  compute: function (startDate, endDate, holidays) {
14984
14836
  return NETWORKDAYS_INTL.compute.bind(this)(startDate, endDate, { value: 1 }, holidays);
14985
14837
  },
@@ -15060,7 +14912,6 @@ const NETWORKDAYS_INTL = {
15060
14912
  arg(`weekend (any, default=${DEFAULT_WEEKEND})`, _t("A number or string representing which days of the week are considered weekends.")),
15061
14913
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the dates to consider as holidays.")),
15062
14914
  ],
15063
- returns: ["NUMBER"],
15064
14915
  compute: function (startDate, endDate, weekend = { value: DEFAULT_WEEKEND }, holidays) {
15065
14916
  const _startDate = toJsDate(startDate, this.locale);
15066
14917
  const _endDate = toJsDate(endDate, this.locale);
@@ -15095,7 +14946,6 @@ const NETWORKDAYS_INTL = {
15095
14946
  const NOW = {
15096
14947
  description: _t("Current date and time as a date value."),
15097
14948
  args: [],
15098
- returns: ["DATE"],
15099
14949
  compute: function () {
15100
14950
  const today = DateTime.now();
15101
14951
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
@@ -15113,7 +14963,6 @@ const NOW = {
15113
14963
  const SECOND = {
15114
14964
  description: _t("Minute component of a specific time."),
15115
14965
  args: [arg("time (date)", _t("The time from which to calculate the second component."))],
15116
- returns: ["NUMBER"],
15117
14966
  compute: function (date) {
15118
14967
  return toJsDate(date, this.locale).getSeconds();
15119
14968
  },
@@ -15129,7 +14978,6 @@ const TIME = {
15129
14978
  arg("minute (number)", _t("The minute component of the time.")),
15130
14979
  arg("second (number)", _t("The second component of the time.")),
15131
14980
  ],
15132
- returns: ["DATE"],
15133
14981
  compute: function (hour, minute, second) {
15134
14982
  let _hour = Math.trunc(toNumber(hour, this.locale));
15135
14983
  let _minute = Math.trunc(toNumber(minute, this.locale));
@@ -15153,7 +15001,6 @@ const TIME = {
15153
15001
  const TIMEVALUE = {
15154
15002
  description: _t("Converts a time string into its serial number representation."),
15155
15003
  args: [arg("time_string (string)", _t("The string that holds the time representation."))],
15156
- returns: ["NUMBER"],
15157
15004
  compute: function (timeString) {
15158
15005
  const _timeString = toString(timeString);
15159
15006
  const internalDate = parseDateTime(_timeString, this.locale);
@@ -15169,7 +15016,6 @@ const TIMEVALUE = {
15169
15016
  const TODAY = {
15170
15017
  description: _t("Current date as a date value."),
15171
15018
  args: [],
15172
- returns: ["DATE"],
15173
15019
  compute: function () {
15174
15020
  const today = DateTime.now();
15175
15021
  const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
@@ -15189,7 +15035,6 @@ const WEEKDAY = {
15189
15035
  arg("date (date)", _t("The date for which to determine the day of the week. Must be a reference to a cell containing a date, a function returning a date type, or a number.")),
15190
15036
  arg(`type (number, default=${DEFAULT_TYPE})`, _t("A number indicating which numbering system to use to represent weekdays. By default, counts starting with Sunday = 1.")),
15191
15037
  ],
15192
- returns: ["NUMBER"],
15193
15038
  compute: function (date, type = { value: DEFAULT_TYPE }) {
15194
15039
  const _date = toJsDate(date, this.locale);
15195
15040
  const _type = Math.round(toNumber(type, this.locale));
@@ -15212,7 +15057,6 @@ const WEEKNUM = {
15212
15057
  arg("date (date)", _t("The date for which to determine the week number. Must be a reference to a cell containing a date, a function returning a date type, or a number.")),
15213
15058
  arg(`type (number, default=${DEFAULT_TYPE})`, _t("A number representing the day that a week starts on. Sunday = 1.")),
15214
15059
  ],
15215
- returns: ["NUMBER"],
15216
15060
  compute: function (date, type = { value: DEFAULT_TYPE }) {
15217
15061
  const _date = toJsDate(date, this.locale);
15218
15062
  const _type = Math.round(toNumber(type, this.locale));
@@ -15253,7 +15097,6 @@ const WORKDAY = {
15253
15097
  arg("num_days (number)", _t("The number of working days to advance from start_date. If negative, counts backwards.")),
15254
15098
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the dates to consider holidays.")),
15255
15099
  ],
15256
- returns: ["NUMBER"],
15257
15100
  compute: function (startDate, numDays, holidays = { value: null }) {
15258
15101
  return WORKDAY_INTL.compute.bind(this)(startDate, numDays, { value: 1 }, holidays);
15259
15102
  },
@@ -15270,7 +15113,6 @@ const WORKDAY_INTL = {
15270
15113
  arg(`weekend (any, default=${DEFAULT_WEEKEND})`, _t("A number or string representing which days of the week are considered weekends.")),
15271
15114
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the dates to consider holidays.")),
15272
15115
  ],
15273
- returns: ["DATE"],
15274
15116
  compute: function (startDate, numDays, weekend = { value: DEFAULT_WEEKEND }, holidays) {
15275
15117
  let _startDate = toJsDate(startDate, this.locale);
15276
15118
  let _numDays = Math.trunc(toNumber(numDays, this.locale));
@@ -15310,7 +15152,6 @@ const WORKDAY_INTL = {
15310
15152
  const YEAR = {
15311
15153
  description: _t("Year specified by a given date."),
15312
15154
  args: [arg("date (date)", _t("The date from which to extract the year."))],
15313
- returns: ["NUMBER"],
15314
15155
  compute: function (date) {
15315
15156
  return toJsDate(date, this.locale).getFullYear();
15316
15157
  },
@@ -15327,7 +15168,6 @@ const YEARFRAC = {
15327
15168
  arg("end_date (date)", _t("The end date to consider in the calculation. Must be a reference to a cell containing a date, a function returning a date type, or a number.")),
15328
15169
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION$1})`, _t("An indicator of what day count method to use.")),
15329
15170
  ],
15330
- returns: ["NUMBER"],
15331
15171
  compute: function (startDate, endDate, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION$1 }) {
15332
15172
  let _startDate = Math.trunc(toNumber(startDate, this.locale));
15333
15173
  let _endDate = Math.trunc(toNumber(endDate, this.locale));
@@ -15344,7 +15184,6 @@ const YEARFRAC = {
15344
15184
  const MONTH_START = {
15345
15185
  description: _t("First day of the month preceding a date."),
15346
15186
  args: [arg("date (date)", _t("The date from which to calculate the result."))],
15347
- returns: ["DATE"],
15348
15187
  compute: function (date) {
15349
15188
  const _startDate = toJsDate(date, this.locale);
15350
15189
  const yStart = _startDate.getFullYear();
@@ -15362,7 +15201,6 @@ const MONTH_START = {
15362
15201
  const MONTH_END = {
15363
15202
  description: _t("Last day of the month following a date."),
15364
15203
  args: [arg("date (date)", _t("The date from which to calculate the result."))],
15365
- returns: ["DATE"],
15366
15204
  compute: function (date) {
15367
15205
  return EOMONTH.compute.bind(this)(date, { value: 0 });
15368
15206
  },
@@ -15373,7 +15211,6 @@ const MONTH_END = {
15373
15211
  const QUARTER = {
15374
15212
  description: _t("Quarter of the year a specific date falls in"),
15375
15213
  args: [arg("date (date)", _t("The date from which to extract the quarter."))],
15376
- returns: ["NUMBER"],
15377
15214
  compute: function (date) {
15378
15215
  return Math.ceil((toJsDate(date, this.locale).getMonth() + 1) / 3);
15379
15216
  },
@@ -15384,7 +15221,6 @@ const QUARTER = {
15384
15221
  const QUARTER_START = {
15385
15222
  description: _t("First day of the quarter of the year a specific date falls in."),
15386
15223
  args: [arg("date (date)", _t("The date from which to calculate the start of quarter."))],
15387
- returns: ["DATE"],
15388
15224
  compute: function (date) {
15389
15225
  const quarter = QUARTER.compute.bind(this)(date);
15390
15226
  const year = YEAR.compute.bind(this)(date);
@@ -15401,7 +15237,6 @@ const QUARTER_START = {
15401
15237
  const QUARTER_END = {
15402
15238
  description: _t("Last day of the quarter of the year a specific date falls in."),
15403
15239
  args: [arg("date (date)", _t("The date from which to calculate the end of quarter."))],
15404
- returns: ["DATE"],
15405
15240
  compute: function (date) {
15406
15241
  const quarter = QUARTER.compute.bind(this)(date);
15407
15242
  const year = YEAR.compute.bind(this)(date);
@@ -15418,7 +15253,6 @@ const QUARTER_END = {
15418
15253
  const YEAR_START = {
15419
15254
  description: _t("First day of the year a specific date falls in."),
15420
15255
  args: [arg("date (date)", _t("The date from which to calculate the start of the year."))],
15421
- returns: ["DATE"],
15422
15256
  compute: function (date) {
15423
15257
  const year = YEAR.compute.bind(this)(date);
15424
15258
  const jsDate = new DateTime(year, 0, 1);
@@ -15434,7 +15268,6 @@ const YEAR_START = {
15434
15268
  const YEAR_END = {
15435
15269
  description: _t("Last day of the year a specific date falls in."),
15436
15270
  args: [arg("date (date)", _t("The date from which to calculate the end of the year."))],
15437
- returns: ["DATE"],
15438
15271
  compute: function (date) {
15439
15272
  const year = YEAR.compute.bind(this)(date);
15440
15273
  const jsDate = new DateTime(year + 1, 0, 0);
@@ -15491,7 +15324,6 @@ const DELTA = {
15491
15324
  arg("number1 (number)", _t("The first number to compare.")),
15492
15325
  arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _t("The second number to compare.")),
15493
15326
  ],
15494
- returns: ["NUMBER"],
15495
15327
  compute: function (number1, number2 = { value: DEFAULT_DELTA_ARG }) {
15496
15328
  const _number1 = toNumber(number1, this.locale);
15497
15329
  const _number2 = toNumber(number2, this.locale);
@@ -15682,7 +15514,6 @@ const FILTER = {
15682
15514
  arg("condition1 (boolean, range<boolean>)", _t("A column or row containing true or false values corresponding to the first column or row of range.")),
15683
15515
  arg("condition2 (boolean, range<boolean>, repeating)", _t("Additional column or row containing true or false values.")),
15684
15516
  ],
15685
- returns: ["RANGE<ANY>"],
15686
15517
  compute: function (range, ...conditions) {
15687
15518
  let _array = toMatrix(range);
15688
15519
  const _conditionsMatrices = conditions.map((cond) => matrixMap(toMatrix(cond), (data) => data.value));
@@ -15716,7 +15547,6 @@ const SORT = {
15716
15547
  arg("sort_column (any, range<number>, repeating)", _t("The index of the column in range or a range outside of range containing the values by which to sort.")),
15717
15548
  arg("is_ascending (boolean, repeating)", _t("TRUE or FALSE indicating whether to sort sort_column in ascending order. FALSE sorts in descending order.")),
15718
15549
  ],
15719
- returns: ["RANGE"],
15720
15550
  compute: function (range, ...sortingCriteria) {
15721
15551
  const _range = transposeMatrix(range);
15722
15552
  return transposeMatrix(sortMatrix(_range, this.locale, ...sortingCriteria));
@@ -15735,7 +15565,6 @@ const SORTN = {
15735
15565
  arg("sort_column (number, range<number>, repeating)", _t("The index of the column in range or a range outside of range containing the values by which to sort.")),
15736
15566
  arg("is_ascending (boolean, repeating)", _t("TRUE or FALSE indicating whether to sort sort_column in ascending order. FALSE sorts in descending order.")),
15737
15567
  ],
15738
- returns: ["RANGE"],
15739
15568
  compute: function (range, n, displayTiesMode, ...sortingCriteria) {
15740
15569
  const _n = toNumber(n?.value ?? 1, this.locale);
15741
15570
  assert(() => _n >= 0, _t("Wrong value of 'n'. Expected a positive number. Got %s.", _n));
@@ -15803,7 +15632,6 @@ const UNIQUE = {
15803
15632
  arg("by_column (boolean, default=FALSE)", _t("Whether to filter the data by columns or by rows.")),
15804
15633
  arg("exactly_once (boolean, default=FALSE)", _t("Whether to return only entries with no duplicates.")),
15805
15634
  ],
15806
- returns: ["RANGE<NUMBER>"],
15807
15635
  compute: function (range = { value: "" }, byColumn, exactlyOnce) {
15808
15636
  if (!isMatrix(range)) {
15809
15637
  return [[range]];
@@ -16028,7 +15856,6 @@ const ACCRINTM = {
16028
15856
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
16029
15857
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16030
15858
  ],
16031
- returns: ["NUMBER"],
16032
15859
  compute: function (issue, maturity, rate, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16033
15860
  const start = Math.trunc(toNumber(issue, this.locale));
16034
15861
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -16059,7 +15886,6 @@ const AMORLINC = {
16059
15886
  arg("rate (number)", _t("The deprecation rate.")),
16060
15887
  arg("day_count_convention (number, optional)", _t("An indicator of what day count method to use.")),
16061
15888
  ],
16062
- returns: ["NUMBER"],
16063
15889
  compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16064
15890
  dayCountConvention = dayCountConvention || 0;
16065
15891
  const _cost = toNumber(cost, this.locale);
@@ -16108,7 +15934,6 @@ const AMORLINC = {
16108
15934
  const COUPDAYS = {
16109
15935
  description: _t("Days in coupon period containing settlement date."),
16110
15936
  args: COUPON_FUNCTION_ARGS,
16111
- returns: ["NUMBER"],
16112
15937
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16113
15938
  dayCountConvention = dayCountConvention || 0;
16114
15939
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16135,7 +15960,6 @@ const COUPDAYS = {
16135
15960
  const COUPDAYBS = {
16136
15961
  description: _t("Days from settlement until next coupon."),
16137
15962
  args: COUPON_FUNCTION_ARGS,
16138
- returns: ["NUMBER"],
16139
15963
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16140
15964
  dayCountConvention = dayCountConvention || 0;
16141
15965
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16192,7 +16016,6 @@ const COUPDAYBS = {
16192
16016
  const COUPDAYSNC = {
16193
16017
  description: _t("Days from settlement until next coupon."),
16194
16018
  args: COUPON_FUNCTION_ARGS,
16195
- returns: ["NUMBER"],
16196
16019
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16197
16020
  dayCountConvention = dayCountConvention || 0;
16198
16021
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16222,7 +16045,6 @@ const COUPDAYSNC = {
16222
16045
  const COUPNCD = {
16223
16046
  description: _t("Next coupon date after the settlement date."),
16224
16047
  args: COUPON_FUNCTION_ARGS,
16225
- returns: ["NUMBER"],
16226
16048
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16227
16049
  dayCountConvention = dayCountConvention || 0;
16228
16050
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16248,7 +16070,6 @@ const COUPNCD = {
16248
16070
  const COUPNUM = {
16249
16071
  description: _t("Number of coupons between settlement and maturity."),
16250
16072
  args: COUPON_FUNCTION_ARGS,
16251
- returns: ["NUMBER"],
16252
16073
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16253
16074
  dayCountConvention = dayCountConvention || 0;
16254
16075
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16275,7 +16096,6 @@ const COUPNUM = {
16275
16096
  const COUPPCD = {
16276
16097
  description: _t("Last coupon date prior to or on the settlement date."),
16277
16098
  args: COUPON_FUNCTION_ARGS,
16278
- returns: ["NUMBER"],
16279
16099
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16280
16100
  dayCountConvention = dayCountConvention || 0;
16281
16101
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16308,7 +16128,6 @@ const CUMIPMT = {
16308
16128
  arg("last_period (number)", _t("The number of the payment period to end the cumulative calculation.")),
16309
16129
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
16310
16130
  ],
16311
- returns: ["NUMBER"],
16312
16131
  compute: function (rate, numberOfPeriods, presentValue, firstPeriod, lastPeriod, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16313
16132
  const first = toNumber(firstPeriod, this.locale);
16314
16133
  const last = toNumber(lastPeriod, this.locale);
@@ -16340,7 +16159,6 @@ const CUMPRINC = {
16340
16159
  arg("last_period (number)", _t("The number of the payment period to end the cumulative calculation.")),
16341
16160
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
16342
16161
  ],
16343
- returns: ["NUMBER"],
16344
16162
  compute: function (rate, numberOfPeriods, presentValue, firstPeriod, lastPeriod, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16345
16163
  const first = toNumber(firstPeriod, this.locale);
16346
16164
  const last = toNumber(lastPeriod, this.locale);
@@ -16371,7 +16189,6 @@ const DB = {
16371
16189
  arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
16372
16190
  arg("month (number, optional)", _t("The number of months in the first year of depreciation.")),
16373
16191
  ],
16374
- returns: ["NUMBER"],
16375
16192
  // to do: replace by dollar format
16376
16193
  compute: function (cost, salvage, life, period, ...args) {
16377
16194
  const _cost = toNumber(cost, this.locale);
@@ -16440,7 +16257,6 @@ const DDB = {
16440
16257
  arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
16441
16258
  arg(`factor (number, default=${DEFAULT_DDB_DEPRECIATION_FACTOR})`, _t("The factor by which depreciation decreases.")),
16442
16259
  ],
16443
- returns: ["NUMBER"],
16444
16260
  compute: function (cost, salvage, life, period, factor = { value: DEFAULT_DDB_DEPRECIATION_FACTOR }) {
16445
16261
  const _cost = toNumber(cost, this.locale);
16446
16262
  const _salvage = toNumber(salvage, this.locale);
@@ -16466,7 +16282,6 @@ const DISC = {
16466
16282
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
16467
16283
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16468
16284
  ],
16469
- returns: ["NUMBER"],
16470
16285
  compute: function (settlement, maturity, price, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16471
16286
  dayCountConvention = dayCountConvention || 0;
16472
16287
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -16502,7 +16317,6 @@ const DOLLARDE = {
16502
16317
  arg("fractional_price (number)", _t("The price quotation given using fractional decimal conventions.")),
16503
16318
  arg("unit (number)", _t("The units of the fraction, e.g. 8 for 1/8ths or 32 for 1/32nds.")),
16504
16319
  ],
16505
- returns: ["NUMBER"],
16506
16320
  compute: function (fractionalPrice, unit) {
16507
16321
  const price = toNumber(fractionalPrice, this.locale);
16508
16322
  const _unit = Math.trunc(toNumber(unit, this.locale));
@@ -16523,7 +16337,6 @@ const DOLLARFR = {
16523
16337
  arg("decimal_price (number)", _t("The price quotation given as a decimal value.")),
16524
16338
  arg("unit (number)", _t("The units of the desired fraction, e.g. 8 for 1/8ths or 32 for 1/32nds.")),
16525
16339
  ],
16526
- returns: ["NUMBER"],
16527
16340
  compute: function (decimalPrice, unit) {
16528
16341
  const price = toNumber(decimalPrice, this.locale);
16529
16342
  const _unit = Math.trunc(toNumber(unit, this.locale));
@@ -16548,7 +16361,6 @@ const DURATION = {
16548
16361
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
16549
16362
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16550
16363
  ],
16551
- returns: ["NUMBER"],
16552
16364
  compute: function (settlement, maturity, rate, securityYield, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16553
16365
  const start = Math.trunc(toNumber(settlement, this.locale));
16554
16366
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -16589,7 +16401,6 @@ const EFFECT = {
16589
16401
  arg("nominal_rate (number)", _t("The nominal interest rate per year.")),
16590
16402
  arg("periods_per_year (number)", _t("The number of compounding periods per year.")),
16591
16403
  ],
16592
- returns: ["NUMBER"],
16593
16404
  compute: function (nominal_rate, periods_per_year) {
16594
16405
  const nominal = toNumber(nominal_rate, this.locale);
16595
16406
  const periods = Math.trunc(toNumber(periods_per_year, this.locale));
@@ -16619,7 +16430,6 @@ const FV = {
16619
16430
  arg(`present_value (number, default=${DEFAULT_PRESENT_VALUE})`, _t("The current value of the annuity.")),
16620
16431
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
16621
16432
  ],
16622
- returns: ["NUMBER"],
16623
16433
  // to do: replace by dollar format
16624
16434
  compute: function (rate, numberOfPeriods, paymentAmount, presentValue = { value: DEFAULT_PRESENT_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16625
16435
  presentValue = presentValue || 0;
@@ -16645,7 +16455,6 @@ const FVSCHEDULE = {
16645
16455
  arg("principal (number)", _t("The amount of initial capital or value to compound against.")),
16646
16456
  arg("rate_schedule (number, range<number>)", _t("A series of interest rates to compound against the principal.")),
16647
16457
  ],
16648
- returns: ["NUMBER"],
16649
16458
  compute: function (principalAmount, rateSchedule) {
16650
16459
  const principal = toNumber(principalAmount, this.locale);
16651
16460
  return reduceAny([rateSchedule], (acc, rate) => acc * (1 + toNumber(rate, this.locale)), principal);
@@ -16664,7 +16473,6 @@ const INTRATE = {
16664
16473
  arg("redemption (number)", _t("The amount to be received at maturity.")),
16665
16474
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16666
16475
  ],
16667
- returns: ["NUMBER"],
16668
16476
  compute: function (settlement, maturity, investment, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16669
16477
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
16670
16478
  const _maturity = Math.trunc(toNumber(maturity, this.locale));
@@ -16703,7 +16511,6 @@ const IPMT = {
16703
16511
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
16704
16512
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
16705
16513
  ],
16706
- returns: ["NUMBER"],
16707
16514
  compute: function (rate, currentPeriod, numberOfPeriods, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16708
16515
  const r = toNumber(rate, this.locale);
16709
16516
  const period = toNumber(currentPeriod, this.locale);
@@ -16728,7 +16535,6 @@ const IRR = {
16728
16535
  arg("cashflow_amounts (number, range<number>)", _t("An array or range containing the income or payments associated with the investment.")),
16729
16536
  arg(`rate_guess (number, default=${DEFAULT_RATE_GUESS})`, _t("An estimate for what the internal rate of return will be.")),
16730
16537
  ],
16731
- returns: ["NUMBER"],
16732
16538
  compute: function (cashFlowAmounts, rateGuess = { value: DEFAULT_RATE_GUESS }) {
16733
16539
  const _rateGuess = toNumber(rateGuess, this.locale);
16734
16540
  assertRateGuessStrictlyGreaterThanMinusOne(_rateGuess);
@@ -16790,7 +16596,6 @@ const ISPMT = {
16790
16596
  arg("number_of_periods (number)", _t("The number of payments to be made.")),
16791
16597
  arg("present_value (number)", _t("The current value of the annuity.")),
16792
16598
  ],
16793
- returns: ["NUMBER"],
16794
16599
  compute: function (rate, currentPeriod, numberOfPeriods, presentValue) {
16795
16600
  const interestRate = toNumber(rate, this.locale);
16796
16601
  const period = toNumber(currentPeriod, this.locale);
@@ -16815,7 +16620,6 @@ const MDURATION = {
16815
16620
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
16816
16621
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16817
16622
  ],
16818
- returns: ["NUMBER"],
16819
16623
  compute: function (settlement, maturity, rate, securityYield, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16820
16624
  const duration = DURATION.compute.bind(this)(settlement, maturity, rate, securityYield, frequency, dayCountConvention);
16821
16625
  const y = toNumber(securityYield, this.locale);
@@ -16834,7 +16638,6 @@ const MIRR = {
16834
16638
  arg("financing_rate (number)", _t("The interest rate paid on funds invested.")),
16835
16639
  arg("reinvestment_return_rate (number)", _t("The return (as a percentage) earned on reinvestment of income received from the investment.")),
16836
16640
  ],
16837
- returns: ["NUMBER"],
16838
16641
  compute: function (cashflowAmount, financingRate, reinvestmentRate) {
16839
16642
  const fRate = toNumber(financingRate, this.locale);
16840
16643
  const rRate = toNumber(reinvestmentRate, this.locale);
@@ -16886,7 +16689,6 @@ const NOMINAL = {
16886
16689
  arg("effective_rate (number)", _t("The effective interest rate per year.")),
16887
16690
  arg("periods_per_year (number)", _t("The number of compounding periods per year.")),
16888
16691
  ],
16889
- returns: ["NUMBER"],
16890
16692
  compute: function (effective_rate, periods_per_year) {
16891
16693
  const effective = toNumber(effective_rate, this.locale);
16892
16694
  const periods = Math.trunc(toNumber(periods_per_year, this.locale));
@@ -16909,7 +16711,6 @@ const NPER = {
16909
16711
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
16910
16712
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
16911
16713
  ],
16912
- returns: ["NUMBER"],
16913
16714
  compute: function (rate, paymentAmount, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16914
16715
  futureValue = futureValue || 0;
16915
16716
  endOrBeginning = endOrBeginning || 0;
@@ -16957,7 +16758,6 @@ const NPV = {
16957
16758
  arg("cashflow1 (number, range<number>)", _t("The first future cash flow.")),
16958
16759
  arg("cashflow2 (number, range<number>, repeating)", _t("Additional future cash flows.")),
16959
16760
  ],
16960
- returns: ["NUMBER"],
16961
16761
  // to do: replace by dollar format
16962
16762
  compute: function (discount, ...values) {
16963
16763
  const _discount = toNumber(discount, this.locale);
@@ -16979,7 +16779,6 @@ const PDURATION = {
16979
16779
  arg("present_value (number)", _t("The investment's current value.")),
16980
16780
  arg("future_value (number)", _t("The investment's desired future value.")),
16981
16781
  ],
16982
- returns: ["NUMBER"],
16983
16782
  compute: function (rate, presentValue, futureValue) {
16984
16783
  const _rate = toNumber(rate, this.locale);
16985
16784
  const _presentValue = toNumber(presentValue, this.locale);
@@ -17019,7 +16818,6 @@ const PMT = {
17019
16818
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
17020
16819
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
17021
16820
  ],
17022
- returns: ["NUMBER"],
17023
16821
  compute: function (rate, numberOfPeriods, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
17024
16822
  const n = toNumber(numberOfPeriods, this.locale);
17025
16823
  const r = toNumber(rate, this.locale);
@@ -17055,7 +16853,6 @@ const PPMT = {
17055
16853
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
17056
16854
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
17057
16855
  ],
17058
- returns: ["NUMBER"],
17059
16856
  compute: function (rate, currentPeriod, numberOfPeriods, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
17060
16857
  const n = toNumber(numberOfPeriods, this.locale);
17061
16858
  const r = toNumber(rate, this.locale);
@@ -17082,7 +16879,6 @@ const PV = {
17082
16879
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
17083
16880
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
17084
16881
  ],
17085
- returns: ["NUMBER"],
17086
16882
  // to do: replace by dollar format
17087
16883
  compute: function (rate, numberOfPeriods, paymentAmount, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
17088
16884
  futureValue = futureValue || 0;
@@ -17116,7 +16912,6 @@ const PRICE = {
17116
16912
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
17117
16913
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17118
16914
  ],
17119
- returns: ["NUMBER"],
17120
16915
  compute: function (settlement, maturity, rate, securityYield, redemption, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17121
16916
  dayCountConvention = dayCountConvention || 0;
17122
16917
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17164,7 +16959,6 @@ const PRICEDISC = {
17164
16959
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
17165
16960
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17166
16961
  ],
17167
- returns: ["NUMBER"],
17168
16962
  compute: function (settlement, maturity, discount, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17169
16963
  dayCountConvention = dayCountConvention || 0;
17170
16964
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17202,7 +16996,6 @@ const PRICEMAT = {
17202
16996
  arg("yield (number)", _t("The expected annual yield of the security.")),
17203
16997
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17204
16998
  ],
17205
- returns: ["NUMBER"],
17206
16999
  compute: function (settlement, maturity, issue, rate, securityYield, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17207
17000
  dayCountConvention = dayCountConvention || 0;
17208
17001
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17266,7 +17059,6 @@ const RATE = {
17266
17059
  arg(`end_or_beginning (number, default=${DEFAULT_END_OR_BEGINNING})`, _t("Whether payments are due at the end (0) or beginning (1) of each period.")),
17267
17060
  arg(`rate_guess (number, default=${RATE_GUESS_DEFAULT})`, _t("An estimate for what the interest rate will be.")),
17268
17061
  ],
17269
- returns: ["NUMBER"],
17270
17062
  compute: function (numberOfPeriods, paymentPerPeriod, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }, rateGuess = { value: RATE_GUESS_DEFAULT }) {
17271
17063
  const n = toNumber(numberOfPeriods, this.locale);
17272
17064
  const payment = toNumber(paymentPerPeriod, this.locale);
@@ -17312,7 +17104,6 @@ const RECEIVED = {
17312
17104
  arg("discount (number)", _t("The discount rate of the security invested in.")),
17313
17105
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17314
17106
  ],
17315
- returns: ["NUMBER"],
17316
17107
  compute: function (settlement, maturity, investment, discount, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17317
17108
  dayCountConvention = dayCountConvention || 0;
17318
17109
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17350,7 +17141,6 @@ const RRI = {
17350
17141
  arg("present_value (number)", _t("The present value of the investment.")),
17351
17142
  arg("future_value (number)", _t("The future value of the investment.")),
17352
17143
  ],
17353
- returns: ["NUMBER"],
17354
17144
  compute: function (numberOfPeriods, presentValue, futureValue) {
17355
17145
  const n = toNumber(numberOfPeriods, this.locale);
17356
17146
  const pv = toNumber(presentValue, this.locale);
@@ -17375,7 +17165,6 @@ const SLN = {
17375
17165
  arg("salvage (number)", _t("The value of the asset at the end of depreciation.")),
17376
17166
  arg("life (number)", _t("The number of periods over which the asset is depreciated.")),
17377
17167
  ],
17378
- returns: ["NUMBER"],
17379
17168
  compute: function (cost, salvage, life) {
17380
17169
  const _cost = toNumber(cost, this.locale);
17381
17170
  const _salvage = toNumber(salvage, this.locale);
@@ -17400,7 +17189,6 @@ const SYD = {
17400
17189
  arg("life (number)", _t("The number of periods over which the asset is depreciated.")),
17401
17190
  arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
17402
17191
  ],
17403
- returns: ["NUMBER"],
17404
17192
  compute: function (cost, salvage, life, period) {
17405
17193
  const _cost = toNumber(cost, this.locale);
17406
17194
  const _salvage = toNumber(salvage, this.locale);
@@ -17449,7 +17237,6 @@ const TBILLPRICE = {
17449
17237
  arg("maturity (date)", _t("The maturity or end date of the security, when it can be redeemed at face, or par value.")),
17450
17238
  arg("discount (number)", _t("The discount rate of the bill at time of purchase.")),
17451
17239
  ],
17452
- returns: ["NUMBER"],
17453
17240
  compute: function (settlement, maturity, discount) {
17454
17241
  const start = Math.trunc(toNumber(settlement, this.locale));
17455
17242
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -17472,7 +17259,6 @@ const TBILLEQ = {
17472
17259
  arg("maturity (date)", _t("The maturity or end date of the security, when it can be redeemed at face, or par value.")),
17473
17260
  arg("discount (number)", _t("The discount rate of the bill at time of purchase.")),
17474
17261
  ],
17475
- returns: ["NUMBER"],
17476
17262
  compute: function (settlement, maturity, discount) {
17477
17263
  const start = Math.trunc(toNumber(settlement, this.locale));
17478
17264
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -17530,7 +17316,6 @@ const TBILLYIELD = {
17530
17316
  arg("maturity (date)", _t("The maturity or end date of the security, when it can be redeemed at face, or par value.")),
17531
17317
  arg("price (number)", _t("The price at which the security is bought per 100 face value.")),
17532
17318
  ],
17533
- returns: ["NUMBER"],
17534
17319
  compute: function (settlement, maturity, price) {
17535
17320
  const start = Math.trunc(toNumber(settlement, this.locale));
17536
17321
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -17570,7 +17355,6 @@ const VDB = {
17570
17355
  arg(`factor (number, default=${DEFAULT_DDB_DEPRECIATION_FACTOR})`, _t("The number of months in the first year of depreciation.")),
17571
17356
  arg(`no_switch (number, default=${DEFAULT_VDB_NO_SWITCH})`, _t("Whether to switch to straight-line depreciation when the depreciation is greater than the declining balance calculation.")),
17572
17357
  ],
17573
- returns: ["NUMBER"],
17574
17358
  compute: function (cost, salvage, life, startPeriod, endPeriod, factor = { value: DEFAULT_DDB_DEPRECIATION_FACTOR }, noSwitch = { value: DEFAULT_VDB_NO_SWITCH }) {
17575
17359
  factor = factor || 0;
17576
17360
  const _cost = toNumber(cost, this.locale);
@@ -17635,7 +17419,6 @@ const XIRR = {
17635
17419
  arg("cashflow_dates (range<number>)", _t("An range with dates corresponding to the cash flows in cashflow_amounts.")),
17636
17420
  arg(`rate_guess (number, default=${RATE_GUESS_DEFAULT})`, _t("An estimate for what the internal rate of return will be.")),
17637
17421
  ],
17638
- returns: ["NUMBER"],
17639
17422
  compute: function (cashflowAmounts, cashflowDates, rateGuess = { value: RATE_GUESS_DEFAULT }) {
17640
17423
  const guess = toNumber(rateGuess, this.locale);
17641
17424
  const _cashFlows = cashflowAmounts.flat().map((val) => toNumber(val, this.locale));
@@ -17706,7 +17489,6 @@ const XNPV = {
17706
17489
  arg("cashflow_amounts (number, range<number>)", _t("An range containing the income or payments associated with the investment.")),
17707
17490
  arg("cashflow_dates (number, range<number>)", _t("An range with dates corresponding to the cash flows in cashflow_amounts.")),
17708
17491
  ],
17709
- returns: ["NUMBER"],
17710
17492
  compute: function (discount, cashflowAmounts, cashflowDates) {
17711
17493
  const rate = toNumber(discount, this.locale);
17712
17494
  const _cashFlows = isMatrix(cashflowAmounts)
@@ -17773,7 +17555,6 @@ const YIELD = {
17773
17555
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
17774
17556
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17775
17557
  ],
17776
- returns: ["NUMBER"],
17777
17558
  compute: function (settlement, maturity, rate, price, redemption, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17778
17559
  dayCountConvention = dayCountConvention || 0;
17779
17560
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17848,7 +17629,6 @@ const YIELDDISC = {
17848
17629
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
17849
17630
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17850
17631
  ],
17851
- returns: ["NUMBER"],
17852
17632
  compute: function (settlement, maturity, price, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17853
17633
  dayCountConvention = dayCountConvention || 0;
17854
17634
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17885,7 +17665,6 @@ const YIELDMAT = {
17885
17665
  arg("price (number)", _t("The price at which the security is bought.")),
17886
17666
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17887
17667
  ],
17888
- returns: ["NUMBER"],
17889
17668
  compute: function (settlement, maturity, issue, rate, price, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17890
17669
  dayCountConvention = dayCountConvention || 0;
17891
17670
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17972,7 +17751,6 @@ const CELL = {
17972
17751
  arg("info_type (string)", _t("The type of information requested. Can be one of %s", CELL_INFO_TYPES.join(", "))),
17973
17752
  arg("reference (meta)", _t("The reference to the cell.")),
17974
17753
  ],
17975
- returns: ["ANY"],
17976
17754
  compute: function (info, reference) {
17977
17755
  const _info = toString(info).toLowerCase();
17978
17756
  assert(() => CELL_INFO_TYPES.includes(_info), _t("The info_type should be one of %s.", CELL_INFO_TYPES.join(", ")));
@@ -18023,7 +17801,6 @@ const CELL = {
18023
17801
  const ISERR = {
18024
17802
  description: _t("Whether a value is an error other than #N/A."),
18025
17803
  args: [arg("value (any)", _t("The value to be verified as an error type."))],
18026
- returns: ["BOOLEAN"],
18027
17804
  compute: function (data) {
18028
17805
  const value = data?.value;
18029
17806
  return isEvaluationError(value) && value !== CellErrorType.NotAvailable;
@@ -18036,7 +17813,6 @@ const ISERR = {
18036
17813
  const ISERROR = {
18037
17814
  description: _t("Whether a value is an error."),
18038
17815
  args: [arg("value (any)", _t("The value to be verified as an error type."))],
18039
- returns: ["BOOLEAN"],
18040
17816
  compute: function (data) {
18041
17817
  const value = data?.value;
18042
17818
  return isEvaluationError(value);
@@ -18049,7 +17825,6 @@ const ISERROR = {
18049
17825
  const ISLOGICAL = {
18050
17826
  description: _t("Whether a value is `true` or `false`."),
18051
17827
  args: [arg("value (any)", _t("The value to be verified as a logical TRUE or FALSE."))],
18052
- returns: ["BOOLEAN"],
18053
17828
  compute: function (value) {
18054
17829
  return typeof value?.value === "boolean";
18055
17830
  },
@@ -18061,7 +17836,6 @@ const ISLOGICAL = {
18061
17836
  const ISNA = {
18062
17837
  description: _t("Whether a value is the error #N/A."),
18063
17838
  args: [arg("value (any)", _t("The value to be verified as an error type."))],
18064
- returns: ["BOOLEAN"],
18065
17839
  compute: function (data) {
18066
17840
  return data?.value === CellErrorType.NotAvailable;
18067
17841
  },
@@ -18073,7 +17847,6 @@ const ISNA = {
18073
17847
  const ISNONTEXT = {
18074
17848
  description: _t("Whether a value is non-textual."),
18075
17849
  args: [arg("value (any)", _t("The value to be checked."))],
18076
- returns: ["BOOLEAN"],
18077
17850
  compute: function (value) {
18078
17851
  return !ISTEXT.compute.bind(this)(value);
18079
17852
  },
@@ -18085,7 +17858,6 @@ const ISNONTEXT = {
18085
17858
  const ISNUMBER = {
18086
17859
  description: _t("Whether a value is a number."),
18087
17860
  args: [arg("value (any)", _t("The value to be verified as a number."))],
18088
- returns: ["BOOLEAN"],
18089
17861
  compute: function (value) {
18090
17862
  return typeof value?.value === "number";
18091
17863
  },
@@ -18097,7 +17869,6 @@ const ISNUMBER = {
18097
17869
  const ISTEXT = {
18098
17870
  description: _t("Whether a value is text."),
18099
17871
  args: [arg("value (any)", _t("The value to be verified as text."))],
18100
- returns: ["BOOLEAN"],
18101
17872
  compute: function (value) {
18102
17873
  return typeof value?.value === "string" && isEvaluationError(value?.value) === false;
18103
17874
  },
@@ -18109,7 +17880,6 @@ const ISTEXT = {
18109
17880
  const ISBLANK = {
18110
17881
  description: _t("Whether the referenced cell is empty"),
18111
17882
  args: [arg("value (any)", _t("Reference to the cell that will be checked for emptiness."))],
18112
- returns: ["BOOLEAN"],
18113
17883
  compute: function (value) {
18114
17884
  return value?.value === null;
18115
17885
  },
@@ -18121,7 +17891,6 @@ const ISBLANK = {
18121
17891
  const NA = {
18122
17892
  description: _t("Returns the error value #N/A."),
18123
17893
  args: [],
18124
- returns: ["BOOLEAN"],
18125
17894
  compute: function () {
18126
17895
  return { value: CellErrorType.NotAvailable };
18127
17896
  },
@@ -18178,7 +17947,6 @@ const AND = {
18178
17947
  arg("logical_expression1 (boolean, range<boolean>)", _t("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.")),
18179
17948
  arg("logical_expression2 (boolean, range<boolean>, repeating)", _t("More expressions that represent logical values.")),
18180
17949
  ],
18181
- returns: ["BOOLEAN"],
18182
17950
  compute: function (...logicalExpressions) {
18183
17951
  const { result, foundBoolean } = boolAnd(logicalExpressions);
18184
17952
  assert(() => foundBoolean, _t("[[FUNCTION_NAME]] has no valid input data."));
@@ -18192,7 +17960,6 @@ const AND = {
18192
17960
  const FALSE = {
18193
17961
  description: _t("Logical value `false`."),
18194
17962
  args: [],
18195
- returns: ["BOOLEAN"],
18196
17963
  compute: function () {
18197
17964
  return false;
18198
17965
  },
@@ -18208,7 +17975,6 @@ const IF = {
18208
17975
  arg("value_if_true (any)", _t("The value the function returns if logical_expression is TRUE.")),
18209
17976
  arg("value_if_false (any, default=FALSE)", _t("The value the function returns if logical_expression is FALSE.")),
18210
17977
  ],
18211
- returns: ["ANY"],
18212
17978
  compute: function (logicalExpression, valueIfTrue, valueIfFalse) {
18213
17979
  const result = toBoolean(logicalExpression?.value) ? valueIfTrue : valueIfFalse;
18214
17980
  if (result === undefined) {
@@ -18230,7 +17996,6 @@ const IFERROR = {
18230
17996
  arg("value (any)", _t("The value to return if value itself is not an error.")),
18231
17997
  arg(`value_if_error (any, default="empty")`, _t("The value the function returns if value is an error.")),
18232
17998
  ],
18233
- returns: ["ANY"],
18234
17999
  compute: function (value, valueIfError = { value: "" }) {
18235
18000
  const result = isEvaluationError(value?.value) ? valueIfError : value;
18236
18001
  if (result === undefined) {
@@ -18252,7 +18017,6 @@ const IFNA = {
18252
18017
  arg("value (any)", _t("The value to return if value itself is not #N/A an error.")),
18253
18018
  arg(`value_if_error (any, default="empty")`, _t("The value the function returns if value is an #N/A error.")),
18254
18019
  ],
18255
- returns: ["ANY"],
18256
18020
  compute: function (value, valueIfError = { value: "" }) {
18257
18021
  const result = value?.value === CellErrorType.NotAvailable ? valueIfError : value;
18258
18022
  if (result === undefined) {
@@ -18276,7 +18040,6 @@ const IFS = {
18276
18040
  arg("condition2 (boolean, repeating)", _t("Additional conditions to be evaluated if the previous ones are FALSE.")),
18277
18041
  arg("value2 (any, repeating)", _t("Additional values to be returned if their corresponding conditions are TRUE.")),
18278
18042
  ],
18279
- returns: ["ANY"],
18280
18043
  compute: function (...values) {
18281
18044
  assert(() => values.length % 2 === 0, _t("Wrong number of arguments. Expected an even number of arguments."));
18282
18045
  for (let n = 0; n < values.length - 1; n += 2) {
@@ -18303,7 +18066,6 @@ const NOT = {
18303
18066
  args: [
18304
18067
  arg("logical_expression (boolean)", _t("An expression or reference to a cell holding an expression that represents some logical value.")),
18305
18068
  ],
18306
- returns: ["BOOLEAN"],
18307
18069
  compute: function (logicalExpression) {
18308
18070
  return !toBoolean(logicalExpression);
18309
18071
  },
@@ -18318,7 +18080,6 @@ const OR = {
18318
18080
  arg("logical_expression1 (boolean, range<boolean>)", _t("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.")),
18319
18081
  arg("logical_expression2 (boolean, range<boolean>, repeating)", _t("More expressions that evaluate to logical values.")),
18320
18082
  ],
18321
- returns: ["BOOLEAN"],
18322
18083
  compute: function (...logicalExpressions) {
18323
18084
  const { result, foundBoolean } = boolOr(logicalExpressions);
18324
18085
  assert(() => foundBoolean, _t("[[FUNCTION_NAME]] has no valid input data."));
@@ -18332,7 +18093,6 @@ const OR = {
18332
18093
  const TRUE = {
18333
18094
  description: _t("Logical value `true`."),
18334
18095
  args: [],
18335
- returns: ["BOOLEAN"],
18336
18096
  compute: function () {
18337
18097
  return true;
18338
18098
  },
@@ -18347,7 +18107,6 @@ const XOR = {
18347
18107
  arg("logical_expression1 (boolean, range<boolean>)", _t("An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.")),
18348
18108
  arg("logical_expression2 (boolean, range<boolean>, repeating)", _t("More expressions that evaluate to logical values.")),
18349
18109
  ],
18350
- returns: ["BOOLEAN"],
18351
18110
  compute: function (...logicalExpressions) {
18352
18111
  let foundBoolean = false;
18353
18112
  let acc = false;
@@ -18376,9 +18135,229 @@ var logical = /*#__PURE__*/Object.freeze({
18376
18135
  XOR: XOR
18377
18136
  });
18378
18137
 
18379
- //TODO This registry is only used to disable the support of exploded pivot for spreadsheet
18380
- const supportedPivotExplodedFormulaRegistry = new Registry();
18381
- supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
18138
+ const pivotTimeAdapterRegistry = new Registry();
18139
+ function pivotTimeAdapter(granularity) {
18140
+ return pivotTimeAdapterRegistry.get(granularity);
18141
+ }
18142
+ /**
18143
+ * The Time Adapter: Managing Time Periods for Pivot Functions
18144
+ *
18145
+ * Overview:
18146
+ * A time adapter is responsible for managing time periods associated with pivot functions.
18147
+ * Each type of period (day, week, month, quarter, etc.) has its own dedicated adapter.
18148
+ * The adapter's primary role is to normalize period values between spreadsheet functions,
18149
+ * and the pivot.
18150
+ * By normalizing the period value, it can be stored consistently in the pivot.
18151
+ *
18152
+ * Normalization Process:
18153
+ * When working with functions in the spreadsheet, the time adapter normalizes
18154
+ * the provided period to facilitate accurate lookup of values in the pivot.
18155
+ * For instance, if the spreadsheet function represents a day period as a number generated
18156
+ * by the DATE function (DATE(2023, 12, 25)), the time adapter will normalize it accordingly.
18157
+ *
18158
+ */
18159
+ /**
18160
+ * Normalized value: "12/25/2023"
18161
+ *
18162
+ * Note: Those two format are equivalent:
18163
+ * - "MM/dd/yyyy" (luxon format)
18164
+ * - "mm/dd/yyyy" (spreadsheet format)
18165
+ **/
18166
+ const dayAdapter = {
18167
+ normalizeFunctionValue(value) {
18168
+ const date = toNumber(value, DEFAULT_LOCALE);
18169
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/dd/yyyy" });
18170
+ },
18171
+ getFormat(locale) {
18172
+ return (locale ?? DEFAULT_LOCALE).dateFormat;
18173
+ },
18174
+ formatValue(normalizedValue, locale) {
18175
+ locale = locale ?? DEFAULT_LOCALE;
18176
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18177
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18178
+ },
18179
+ toCellValue(normalizedValue) {
18180
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18181
+ },
18182
+ };
18183
+ /**
18184
+ * normalizes day of month number
18185
+ */
18186
+ const dayOfMonthAdapter = {
18187
+ normalizeFunctionValue(value) {
18188
+ const day = toNumber(value, DEFAULT_LOCALE);
18189
+ if (day < 1 || day > 31) {
18190
+ throw new EvaluationError(_t("%s is not a valid day of month (it should be a number between 1 and 31)", day));
18191
+ }
18192
+ return day;
18193
+ },
18194
+ getFormat() {
18195
+ return "0";
18196
+ },
18197
+ formatValue(normalizedValue, locale) {
18198
+ locale = locale ?? DEFAULT_LOCALE;
18199
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18200
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18201
+ },
18202
+ toCellValue(normalizedValue) {
18203
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18204
+ },
18205
+ };
18206
+ /**
18207
+ * Normalized value: "2/2023" for week 2 of 2023
18208
+ */
18209
+ const weekAdapter = {
18210
+ normalizeFunctionValue(value) {
18211
+ const [week, year] = value.split("/");
18212
+ return `${Number(week)}/${Number(year)}`;
18213
+ },
18214
+ getFormat() {
18215
+ return undefined;
18216
+ },
18217
+ formatValue(normalizedValue) {
18218
+ const [week, year] = normalizedValue.split("/");
18219
+ return _t("W%(week)s %(year)s", { week, year });
18220
+ },
18221
+ toCellValue(normalizedValue) {
18222
+ return this.formatValue(normalizedValue);
18223
+ },
18224
+ };
18225
+ /**
18226
+ * normalizes iso week number
18227
+ */
18228
+ const isoWeekNumberAdapter = {
18229
+ normalizeFunctionValue(value) {
18230
+ const isoWeek = toNumber(value, DEFAULT_LOCALE);
18231
+ if (isoWeek < 0 || isoWeek > 53) {
18232
+ throw new EvaluationError(_t("%s is not a valid week (it should be a number between 0 and 53)", isoWeek));
18233
+ }
18234
+ return isoWeek;
18235
+ },
18236
+ getFormat() {
18237
+ return "0";
18238
+ },
18239
+ formatValue(normalizedValue, locale) {
18240
+ locale = locale ?? DEFAULT_LOCALE;
18241
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18242
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18243
+ },
18244
+ toCellValue(normalizedValue) {
18245
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18246
+ },
18247
+ };
18248
+ /**
18249
+ * normalized month value is a string formatted as "MM/yyyy" (luxon format)
18250
+ * e.g. "01/2020" for January 2020
18251
+ */
18252
+ const monthAdapter = {
18253
+ normalizeFunctionValue(value) {
18254
+ const date = toNumber(value, DEFAULT_LOCALE);
18255
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
18256
+ },
18257
+ getFormat() {
18258
+ return "mmmm yyyy";
18259
+ },
18260
+ formatValue(normalizedValue, locale) {
18261
+ locale = locale ?? DEFAULT_LOCALE;
18262
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18263
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18264
+ },
18265
+ toCellValue(normalizedValue) {
18266
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18267
+ },
18268
+ };
18269
+ /**
18270
+ * normalizes month number
18271
+ */
18272
+ const monthNumberAdapter = {
18273
+ normalizeFunctionValue(value) {
18274
+ const month = toNumber(value, DEFAULT_LOCALE);
18275
+ if (month < 1 || month > 12) {
18276
+ throw new EvaluationError(_t("%s is not a valid month (it should be a number between 1 and 12)", month));
18277
+ }
18278
+ return month;
18279
+ },
18280
+ getFormat() {
18281
+ return "0";
18282
+ },
18283
+ formatValue(normalizedValue, locale) {
18284
+ locale = locale ?? DEFAULT_LOCALE;
18285
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18286
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18287
+ },
18288
+ toCellValue(normalizedValue) {
18289
+ return MONTHS[toNumber(normalizedValue, DEFAULT_LOCALE) - 1].toString();
18290
+ },
18291
+ };
18292
+ /**
18293
+ * normalized quarter value is "quarter/year"
18294
+ * e.g. "1/2020" for Q1 2020
18295
+ */
18296
+ const quarterAdapter = {
18297
+ normalizeFunctionValue(value) {
18298
+ const [quarter, year] = value.split("/");
18299
+ return `${quarter}/${year}`;
18300
+ },
18301
+ getFormat() {
18302
+ return undefined;
18303
+ },
18304
+ formatValue(normalizedValue) {
18305
+ const [quarter, year] = normalizedValue.split("/");
18306
+ return _t("Q%(quarter)s %(year)s", { quarter, year });
18307
+ },
18308
+ toCellValue(normalizedValue) {
18309
+ return this.formatValue(normalizedValue);
18310
+ },
18311
+ };
18312
+ /**
18313
+ * normalizes quarter number
18314
+ */
18315
+ const quarterNumberAdapter = {
18316
+ normalizeFunctionValue(value) {
18317
+ const quarter = toNumber(value, DEFAULT_LOCALE);
18318
+ if (quarter < 1 || quarter > 4) {
18319
+ throw new EvaluationError(_t("%s is not a valid quarter (it should be a number between 1 and 4)", quarter));
18320
+ }
18321
+ return quarter;
18322
+ },
18323
+ getFormat() {
18324
+ return "0";
18325
+ },
18326
+ formatValue(normalizedValue, locale) {
18327
+ locale = locale ?? DEFAULT_LOCALE;
18328
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18329
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18330
+ },
18331
+ toCellValue(normalizedValue) {
18332
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18333
+ },
18334
+ };
18335
+ const yearAdapter = {
18336
+ normalizeFunctionValue(value) {
18337
+ return toNumber(value, DEFAULT_LOCALE);
18338
+ },
18339
+ getFormat() {
18340
+ return "0";
18341
+ },
18342
+ formatValue(normalizedValue, locale) {
18343
+ locale = locale ?? DEFAULT_LOCALE;
18344
+ return formatValue(normalizedValue, { locale, format: "0" });
18345
+ },
18346
+ toCellValue(normalizedValue) {
18347
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18348
+ },
18349
+ };
18350
+ pivotTimeAdapterRegistry
18351
+ .add("day", dayAdapter)
18352
+ .add("week", weekAdapter)
18353
+ .add("month", monthAdapter)
18354
+ .add("quarter", quarterAdapter)
18355
+ .add("year", yearAdapter)
18356
+ .add("day_of_month", dayOfMonthAdapter)
18357
+ .add("iso_week_number", isoWeekNumberAdapter)
18358
+ .add("month_number", monthNumberAdapter)
18359
+ .add("quarter_number", quarterNumberAdapter)
18360
+ .add("year_number", yearAdapter);
18382
18361
 
18383
18362
  const AGGREGATOR_NAMES = {
18384
18363
  count: _t("Count"),
@@ -18394,7 +18373,7 @@ const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "
18394
18373
  const AGGREGATORS_BY_FIELD_TYPE = {
18395
18374
  integer: NUMBER_CHAR_AGGREGATORS,
18396
18375
  char: NUMBER_CHAR_AGGREGATORS,
18397
- //TODO Support for date and boolean
18376
+ boolean: ["count_distinct", "count", "bool_and", "bool_or"],
18398
18377
  };
18399
18378
  const AGGREGATORS = {};
18400
18379
  for (const type in AGGREGATORS_BY_FIELD_TYPE) {
@@ -18504,6 +18483,44 @@ function toPivotDomain(domainStr) {
18504
18483
  function flatPivotDomain(domain) {
18505
18484
  return domain.flatMap((arg) => [arg.field, arg.value]);
18506
18485
  }
18486
+ /**
18487
+ * Parses the value defining a pivot group in a PIVOT formula
18488
+ * e.g. given the following formula PIVOT.VALUE("1", "stage_id", "42", "status", "won"),
18489
+ * the two group values are "42" and "won".
18490
+ */
18491
+ function toNormalizedPivotValue(dimension, groupValue) {
18492
+ if (groupValue === null || groupValue === "null") {
18493
+ return null;
18494
+ }
18495
+ const groupValueString = typeof groupValue === "boolean"
18496
+ ? toString(groupValue).toLocaleLowerCase()
18497
+ : toString(groupValue);
18498
+ if (!pivotNormalizationValueRegistry.contains(dimension.type)) {
18499
+ throw new EvaluationError(_t("Field %(field)s is not supported because of its type (%(type)s)", {
18500
+ field: dimension.displayName,
18501
+ type: dimension.type,
18502
+ }));
18503
+ }
18504
+ // represents a field which is not set (=False server side)
18505
+ if (groupValueString === "false") {
18506
+ return false;
18507
+ }
18508
+ const normalizer = pivotNormalizationValueRegistry.get(dimension.type);
18509
+ return normalizer(groupValueString, dimension.granularity);
18510
+ }
18511
+ function normalizeDateTime(value, granularity) {
18512
+ if (!granularity) {
18513
+ throw "";
18514
+ }
18515
+ return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
18516
+ }
18517
+ const pivotNormalizationValueRegistry = new Registry();
18518
+ pivotNormalizationValueRegistry
18519
+ .add("date", normalizeDateTime)
18520
+ .add("datetime", normalizeDateTime)
18521
+ .add("integer", (value) => toNumber(value, DEFAULT_LOCALE))
18522
+ .add("boolean", (value) => toBoolean(value))
18523
+ .add("char", (value) => toString(value));
18507
18524
 
18508
18525
  /**
18509
18526
  * Get the pivot ID from the formula pivot ID.
@@ -18580,7 +18597,6 @@ const ADDRESS = {
18580
18597
  arg("use_a1_notation (boolean, default=TRUE)", _t("A boolean indicating whether to use A1 style notation (TRUE) or R1C1 style notation (FALSE).")),
18581
18598
  arg("sheet (string, optional)", _t("A string indicating the name of the sheet into which the address points.")),
18582
18599
  ],
18583
- returns: ["STRING"],
18584
18600
  compute: function (row, column, absoluteRelativeMode = { value: DEFAULT_ABSOLUTE_RELATIVE_MODE }, useA1Notation = { value: true }, sheet) {
18585
18601
  const rowNumber = strictToInteger(row, this.locale);
18586
18602
  const colNumber = strictToInteger(column, this.locale);
@@ -18617,7 +18633,6 @@ const COLUMN = {
18617
18633
  args: [
18618
18634
  arg("cell_reference (meta, default='this cell')", _t("The cell whose column number will be returned. Column A corresponds to 1. By default, the function use the cell in which the formula is entered.")),
18619
18635
  ],
18620
- returns: ["NUMBER"],
18621
18636
  compute: function (cellReference) {
18622
18637
  if (isEvaluationError(cellReference?.value)) {
18623
18638
  throw cellReference;
@@ -18635,7 +18650,6 @@ const COLUMN = {
18635
18650
  const COLUMNS = {
18636
18651
  description: _t("Number of columns in a specified array or range."),
18637
18652
  args: [arg("range (meta)", _t("The range whose column count will be returned."))],
18638
- returns: ["NUMBER"],
18639
18653
  compute: function (range) {
18640
18654
  if (isEvaluationError(range?.value)) {
18641
18655
  throw range;
@@ -18656,7 +18670,6 @@ const HLOOKUP = {
18656
18670
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18657
18671
  arg(`is_sorted (boolean, default=${DEFAULT_IS_SORTED})`, _t("Indicates whether the row to be searched (the first row of the specified range) is sorted, in which case the closest match for search_key will be returned.")),
18658
18672
  ],
18659
- returns: ["ANY"],
18660
18673
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18661
18674
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18662
18675
  assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
@@ -18686,7 +18699,6 @@ const INDEX = {
18686
18699
  arg("row (number, default=0)", _t("The index of the row to be returned from within the reference range of cells.")),
18687
18700
  arg("column (number, default=0)", _t("The index of the column to be returned from within the reference range of cells.")),
18688
18701
  ],
18689
- returns: ["ANY"],
18690
18702
  compute: function (reference, row = { value: 0 }, column = { value: 0 }) {
18691
18703
  const _reference = toMatrix(reference);
18692
18704
  const _row = toNumber(row.value, this.locale);
@@ -18717,7 +18729,6 @@ const INDIRECT = {
18717
18729
  arg("reference (string)", _t("The range of cells from which the values are returned.")),
18718
18730
  arg("use_a1_notation (boolean, default=TRUE)", _t("A boolean indicating whether to use A1 style notation (TRUE) or R1C1 style notation (FALSE).")),
18719
18731
  ],
18720
- returns: ["ANY"],
18721
18732
  compute: function (reference, useA1Notation = { value: true }) {
18722
18733
  let _reference = reference?.value?.toString();
18723
18734
  if (!_reference) {
@@ -18772,7 +18783,6 @@ const LOOKUP = {
18772
18783
  arg("search_array (range)", _t("One method of using this function is to provide a single sorted row or column search_array to look through for the search_key with a second argument result_range. The other way is to combine these two arguments into one search_array where the first row or column is searched and a value is returned from the last row or column in the array. If search_key is not found, a non-exact match may be returned.")),
18773
18784
  arg("result_range (range, optional)", _t("The range from which to return a result. The value returned corresponds to the location where search_key is found in search_range. This range must be only a single row or column and should not be used if using the search_result_array method.")),
18774
18785
  ],
18775
- returns: ["ANY"],
18776
18786
  compute: function (searchKey, searchArray, resultRange) {
18777
18787
  let nbCol = searchArray.length;
18778
18788
  let nbRow = searchArray[0].length;
@@ -18813,7 +18823,6 @@ const MATCH = {
18813
18823
  arg("range (any, range)", _t("The one-dimensional array to be searched.")),
18814
18824
  arg(`search_type (number, default=${DEFAULT_SEARCH_TYPE})`, _t("The search method. 1 (default) finds the largest value less than or equal to search_key when range is sorted in ascending order. 0 finds the exact value when range is unsorted. -1 finds the smallest value greater than or equal to search_key when range is sorted in descending order.")),
18815
18825
  ],
18816
- returns: ["NUMBER"],
18817
18826
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
18818
18827
  let _searchType = toNumber(searchType, this.locale);
18819
18828
  const nbCol = range.length;
@@ -18852,7 +18861,6 @@ const ROW = {
18852
18861
  args: [
18853
18862
  arg("cell_reference (meta, default='this cell')", _t("The cell whose row number will be returned. By default, this function uses the cell in which the formula is entered.")),
18854
18863
  ],
18855
- returns: ["NUMBER"],
18856
18864
  compute: function (cellReference) {
18857
18865
  if (isEvaluationError(cellReference?.value)) {
18858
18866
  throw cellReference;
@@ -18870,7 +18878,6 @@ const ROW = {
18870
18878
  const ROWS = {
18871
18879
  description: _t("Number of rows in a specified array or range."),
18872
18880
  args: [arg("range (meta)", _t("The range whose row count will be returned."))],
18873
- returns: ["NUMBER"],
18874
18881
  compute: function (range) {
18875
18882
  if (isEvaluationError(range?.value)) {
18876
18883
  throw range;
@@ -18891,7 +18898,6 @@ const VLOOKUP = {
18891
18898
  arg("index (number)", _t("The column index of the value to be returned, where the first column in range is numbered 1.")),
18892
18899
  arg(`is_sorted (boolean, default=${DEFAULT_IS_SORTED})`, _t("Indicates whether the column to be searched (the first column of the specified range) is sorted, in which case the closest match for search_key will be returned.")),
18893
18900
  ],
18894
- returns: ["ANY"],
18895
18901
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18896
18902
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18897
18903
  assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
@@ -18937,7 +18943,6 @@ const XLOOKUP = {
18937
18943
  (-2) Perform a binary search that relies on lookup_array being sorted in descending order. If not sorted, invalid results will be returned.\
18938
18944
  ")),
18939
18945
  ],
18940
- returns: ["ANY"],
18941
18946
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18942
18947
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18943
18948
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
@@ -18993,12 +18998,6 @@ const PIVOT_VALUE = {
18993
18998
  assertDomainLength(_domainArgs);
18994
18999
  const pivot = this.getters.getPivot(pivotId);
18995
19000
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
18996
- if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
18997
- return {
18998
- value: CellErrorType.GenericError,
18999
- message: _t("This pivot does not support PIVOT.VALUE formula"),
19000
- };
19001
- }
19002
19001
  addPivotDependencies(this, coreDefinition);
19003
19002
  const error = pivot.assertIsValid({ throwOnError: false });
19004
19003
  if (error) {
@@ -19014,7 +19013,6 @@ const PIVOT_VALUE = {
19014
19013
  }
19015
19014
  return { value, format };
19016
19015
  },
19017
- returns: ["NUMBER", "STRING"],
19018
19016
  };
19019
19017
  const PIVOT_HEADER = {
19020
19018
  description: _t("Get the header of a pivot."),
@@ -19030,12 +19028,6 @@ const PIVOT_HEADER = {
19030
19028
  assertDomainLength(_domainArgs);
19031
19029
  const pivot = this.getters.getPivot(_pivotId);
19032
19030
  const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19033
- if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
19034
- return {
19035
- value: CellErrorType.GenericError,
19036
- message: _t("This pivot does not support PIVOT.VALUE formula"),
19037
- };
19038
- }
19039
19031
  addPivotDependencies(this, coreDefinition);
19040
19032
  const error = pivot.assertIsValid({ throwOnError: false });
19041
19033
  if (error) {
@@ -19060,7 +19052,6 @@ const PIVOT_HEADER = {
19060
19052
  : format,
19061
19053
  };
19062
19054
  },
19063
- returns: ["NUMBER", "STRING"],
19064
19055
  };
19065
19056
  const PIVOT = {
19066
19057
  description: _t("Get a pivot table."),
@@ -19127,7 +19118,6 @@ const PIVOT = {
19127
19118
  }
19128
19119
  return result;
19129
19120
  },
19130
- returns: ["RANGE<ANY>"],
19131
19121
  };
19132
19122
 
19133
19123
  var lookup = /*#__PURE__*/Object.freeze({
@@ -19158,7 +19148,6 @@ const ADD = {
19158
19148
  arg("value1 (number)", _t("The first addend.")),
19159
19149
  arg("value2 (number)", _t("The second addend.")),
19160
19150
  ],
19161
- returns: ["NUMBER"],
19162
19151
  compute: function (value1, value2) {
19163
19152
  return {
19164
19153
  value: toNumber(value1, this.locale) + toNumber(value2, this.locale),
@@ -19175,7 +19164,6 @@ const CONCAT = {
19175
19164
  arg("value1 (string)", _t("The value to which value2 will be appended.")),
19176
19165
  arg("value2 (string)", _t("The value to append to value1.")),
19177
19166
  ],
19178
- returns: ["STRING"],
19179
19167
  compute: function (value1, value2) {
19180
19168
  return toString(value1) + toString(value2);
19181
19169
  },
@@ -19190,7 +19178,6 @@ const DIVIDE = {
19190
19178
  arg("dividend (number)", _t("The number to be divided.")),
19191
19179
  arg("divisor (number)", _t("The number to divide by.")),
19192
19180
  ],
19193
- returns: ["NUMBER"],
19194
19181
  compute: function (dividend, divisor) {
19195
19182
  const _divisor = toNumber(divisor, this.locale);
19196
19183
  assert(() => _divisor !== 0, _t("The divisor must be different from zero."), CellErrorType.DivisionByZero);
@@ -19213,7 +19200,6 @@ const EQ = {
19213
19200
  arg("value1 (any)", _t("The first value.")),
19214
19201
  arg("value2 (any)", _t("The value to test against value1 for equality.")),
19215
19202
  ],
19216
- returns: ["BOOLEAN"],
19217
19203
  compute: function (value1, value2) {
19218
19204
  let _value1 = isEmpty(value1) ? getNeutral[typeof value2?.value] : value1?.value;
19219
19205
  let _value2 = isEmpty(value2) ? getNeutral[typeof value1?.value] : value2?.value;
@@ -19266,7 +19252,6 @@ const GT = {
19266
19252
  arg("value1 (any)", _t("The value to test as being greater than value2.")),
19267
19253
  arg("value2 (any)", _t("The second value.")),
19268
19254
  ],
19269
- returns: ["BOOLEAN"],
19270
19255
  compute: function (value1, value2) {
19271
19256
  return applyRelationalOperator(value1, value2, (v1, v2) => {
19272
19257
  return v1 > v2;
@@ -19282,7 +19267,6 @@ const GTE = {
19282
19267
  arg("value1 (any)", _t("The value to test as being greater than or equal to value2.")),
19283
19268
  arg("value2 (any)", _t("The second value.")),
19284
19269
  ],
19285
- returns: ["BOOLEAN"],
19286
19270
  compute: function (value1, value2) {
19287
19271
  return applyRelationalOperator(value1, value2, (v1, v2) => {
19288
19272
  return v1 >= v2;
@@ -19298,7 +19282,6 @@ const LT = {
19298
19282
  arg("value1 (any)", _t("The value to test as being less than value2.")),
19299
19283
  arg("value2 (any)", _t("The second value.")),
19300
19284
  ],
19301
- returns: ["BOOLEAN"],
19302
19285
  compute: function (value1, value2) {
19303
19286
  return !GTE.compute.bind(this)(value1, value2);
19304
19287
  },
@@ -19312,7 +19295,6 @@ const LTE = {
19312
19295
  arg("value1 (any)", _t("The value to test as being less than or equal to value2.")),
19313
19296
  arg("value2 (any)", _t("The second value.")),
19314
19297
  ],
19315
- returns: ["BOOLEAN"],
19316
19298
  compute: function (value1, value2) {
19317
19299
  return !GT.compute.bind(this)(value1, value2);
19318
19300
  },
@@ -19326,7 +19308,6 @@ const MINUS = {
19326
19308
  arg("value1 (number)", _t("The minuend, or number to be subtracted from.")),
19327
19309
  arg("value2 (number)", _t("The subtrahend, or number to subtract from value1.")),
19328
19310
  ],
19329
- returns: ["NUMBER"],
19330
19311
  compute: function (value1, value2) {
19331
19312
  return {
19332
19313
  value: toNumber(value1, this.locale) - toNumber(value2, this.locale),
@@ -19343,7 +19324,6 @@ const MULTIPLY = {
19343
19324
  arg("factor1 (number)", _t("The first multiplicand.")),
19344
19325
  arg("factor2 (number)", _t("The second multiplicand.")),
19345
19326
  ],
19346
- returns: ["NUMBER"],
19347
19327
  compute: function (factor1, factor2) {
19348
19328
  return {
19349
19329
  value: toNumber(factor1, this.locale) * toNumber(factor2, this.locale),
@@ -19360,7 +19340,6 @@ const NE = {
19360
19340
  arg("value1 (any)", _t("The first value.")),
19361
19341
  arg("value2 (any)", _t("The value to test against value1 for inequality.")),
19362
19342
  ],
19363
- returns: ["BOOLEAN"],
19364
19343
  compute: function (value1, value2) {
19365
19344
  return !EQ.compute.bind(this)(value1, value2);
19366
19345
  },
@@ -19374,7 +19353,6 @@ const POW = {
19374
19353
  arg("base (number)", _t("The number to raise to the exponent power.")),
19375
19354
  arg("exponent (number)", _t("The exponent to raise base to.")),
19376
19355
  ],
19377
- returns: ["NUMBER"],
19378
19356
  compute: function (base, exponent) {
19379
19357
  return POWER.compute.bind(this)(base, exponent);
19380
19358
  },
@@ -19387,7 +19365,6 @@ const UMINUS = {
19387
19365
  args: [
19388
19366
  arg("value (number)", _t("The number to have its sign reversed. Equivalently, the number to multiply by -1.")),
19389
19367
  ],
19390
- returns: ["NUMBER"],
19391
19368
  compute: function (value) {
19392
19369
  return {
19393
19370
  value: -toNumber(value, this.locale),
@@ -19401,7 +19378,6 @@ const UMINUS = {
19401
19378
  const UNARY_PERCENT = {
19402
19379
  description: _t("Value interpreted as a percentage."),
19403
19380
  args: [arg("percentage (number)", _t("The value to interpret as a percentage."))],
19404
- returns: ["NUMBER"],
19405
19381
  compute: function (percentage) {
19406
19382
  return toNumber(percentage, this.locale) / 100;
19407
19383
  },
@@ -19412,7 +19388,6 @@ const UNARY_PERCENT = {
19412
19388
  const UPLUS = {
19413
19389
  description: _t("A specified number, unchanged."),
19414
19390
  args: [arg("value (any)", _t("The number to return."))],
19415
- returns: ["ANY"],
19416
19391
  compute: function (value = { value: null }) {
19417
19392
  return value;
19418
19393
  },
@@ -19448,7 +19423,6 @@ const CHAR = {
19448
19423
  args: [
19449
19424
  arg("table_number (number)", _t("The number of the character to look up from the current Unicode table in decimal format.")),
19450
19425
  ],
19451
- returns: ["STRING"],
19452
19426
  compute: function (tableNumber) {
19453
19427
  const _tableNumber = Math.trunc(toNumber(tableNumber, this.locale));
19454
19428
  assert(() => _tableNumber >= 1, _t("The table_number (%s) is out of range.", _tableNumber.toString()));
@@ -19462,7 +19436,6 @@ const CHAR = {
19462
19436
  const CLEAN = {
19463
19437
  description: _t("Remove non-printable characters from a piece of text."),
19464
19438
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
19465
- returns: ["STRING"],
19466
19439
  compute: function (text) {
19467
19440
  const _text = toString(text);
19468
19441
  let cleanedStr = "";
@@ -19484,7 +19457,6 @@ const CONCATENATE = {
19484
19457
  arg("string1 (string, range<string>)", _t("The initial string.")),
19485
19458
  arg("string2 (string, range<string>, repeating)", _t("More strings to append in sequence.")),
19486
19459
  ],
19487
- returns: ["STRING"],
19488
19460
  compute: function (...datas) {
19489
19461
  return reduceAny(datas, (acc, a) => acc + toString(a), "");
19490
19462
  },
@@ -19499,7 +19471,6 @@ const EXACT = {
19499
19471
  arg("string1 (string)", _t("The first string to compare.")),
19500
19472
  arg("string2 (string)", _t("The second string to compare.")),
19501
19473
  ],
19502
- returns: ["BOOLEAN"],
19503
19474
  compute: function (string1, string2) {
19504
19475
  return toString(string1) === toString(string2);
19505
19476
  },
@@ -19515,7 +19486,6 @@ const FIND = {
19515
19486
  arg("text_to_search (string)", _t("The text to search for the first occurrence of search_for.")),
19516
19487
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search.")),
19517
19488
  ],
19518
- returns: ["NUMBER"],
19519
19489
  compute: function (searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
19520
19490
  const _searchFor = toString(searchFor);
19521
19491
  const _textToSearch = toString(textToSearch);
@@ -19538,7 +19508,6 @@ const JOIN = {
19538
19508
  arg("value_or_array1 (string, range<string>)", _t("The value or values to be appended using delimiter.")),
19539
19509
  arg("value_or_array2 (string, range<string>, repeating)", _t("More values to be appended using delimiter.")),
19540
19510
  ],
19541
- returns: ["STRING"],
19542
19511
  compute: function (delimiter, ...valuesOrArrays) {
19543
19512
  const _delimiter = toString(delimiter);
19544
19513
  return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
@@ -19553,7 +19522,6 @@ const LEFT = {
19553
19522
  arg("text (string)", _t("The string from which the left portion will be returned.")),
19554
19523
  arg("number_of_characters (number, optional)", _t("The number of characters to return from the left side of string.")),
19555
19524
  ],
19556
- returns: ["STRING"],
19557
19525
  compute: function (text, ...args) {
19558
19526
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
19559
19527
  assert(() => _numberOfCharacters >= 0, _t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters.toString()));
@@ -19567,7 +19535,6 @@ const LEFT = {
19567
19535
  const LEN = {
19568
19536
  description: _t("Length of a string."),
19569
19537
  args: [arg("text (string)", _t("The string whose length will be returned."))],
19570
- returns: ["NUMBER"],
19571
19538
  compute: function (text) {
19572
19539
  return toString(text).length;
19573
19540
  },
@@ -19579,7 +19546,6 @@ const LEN = {
19579
19546
  const LOWER = {
19580
19547
  description: _t("Converts a specified string to lowercase."),
19581
19548
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
19582
- returns: ["STRING"],
19583
19549
  compute: function (text) {
19584
19550
  return toString(text).toLowerCase();
19585
19551
  },
@@ -19595,7 +19561,6 @@ const MID = {
19595
19561
  arg("starting_at (number)", _t("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
19596
19562
  arg("extract_length (number)", _t("The length of the segment to extract.")),
19597
19563
  ],
19598
- returns: ["STRING"],
19599
19564
  compute: function (text, starting_at, extract_length) {
19600
19565
  const _text = toString(text);
19601
19566
  const _starting_at = toNumber(starting_at, this.locale);
@@ -19614,7 +19579,6 @@ const PROPER = {
19614
19579
  args: [
19615
19580
  arg("text_to_capitalize (string)", _t("The text which will be returned with the first letter of each word in uppercase and all other letters in lowercase.")),
19616
19581
  ],
19617
- returns: ["STRING"],
19618
19582
  compute: function (text) {
19619
19583
  const _text = toString(text);
19620
19584
  return _text.replace(wordRegex, (word) => {
@@ -19634,7 +19598,6 @@ const REPLACE = {
19634
19598
  arg("length (number)", _t("The number of characters in the text to be replaced.")),
19635
19599
  arg("new_text (string)", _t("The text which will be inserted into the original text.")),
19636
19600
  ],
19637
- returns: ["STRING"],
19638
19601
  compute: function (text, position, length, newText) {
19639
19602
  const _position = toNumber(position, this.locale);
19640
19603
  assert(() => _position >= 1, _t("The position (%s) must be greater than or equal to 1.", _position.toString()));
@@ -19654,7 +19617,6 @@ const RIGHT = {
19654
19617
  arg("text (string)", _t("The string from which the right portion will be returned.")),
19655
19618
  arg("number_of_characters (number, optional)", _t("The number of characters to return from the right side of string.")),
19656
19619
  ],
19657
- returns: ["STRING"],
19658
19620
  compute: function (text, ...args) {
19659
19621
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
19660
19622
  assert(() => _numberOfCharacters >= 0, _t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters.toString()));
@@ -19674,7 +19636,6 @@ const SEARCH = {
19674
19636
  arg("text_to_search (string)", _t("The text to search for the first occurrence of search_for.")),
19675
19637
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search.")),
19676
19638
  ],
19677
- returns: ["NUMBER"],
19678
19639
  compute: function (searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
19679
19640
  const _searchFor = toString(searchFor).toLowerCase();
19680
19641
  const _textToSearch = toString(textToSearch).toLowerCase();
@@ -19701,7 +19662,6 @@ const SPLIT = {
19701
19662
  arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _t("Whether or not to remove empty text messages from the split results. The default behavior is to treat \
19702
19663
  consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters.")),
19703
19664
  ],
19704
- returns: ["RANGE<STRING>"],
19705
19665
  compute: function (text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
19706
19666
  const _text = toString(text);
19707
19667
  const _delimiter = escapeRegExp(toString(delimiter));
@@ -19728,7 +19688,6 @@ const SUBSTITUTE = {
19728
19688
  arg("replace_with (string)", _t("The string that will replace search_for.")),
19729
19689
  arg("occurrence_number (number, optional)", _t("The instance of search_for within text_to_search to replace with replace_with. By default, all occurrences of search_for are replaced; however, if occurrence_number is specified, only the indicated instance of search_for is replaced.")),
19730
19690
  ],
19731
- returns: ["NUMBER"],
19732
19691
  compute: function (textToSearch, searchFor, replaceWith, occurrenceNumber) {
19733
19692
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
19734
19693
  assert(() => _occurrenceNumber >= 0, _t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber.toString()));
@@ -19758,7 +19717,6 @@ const TEXTJOIN = {
19758
19717
  arg("text1 (string, range<string>)", _t("Any text item. This could be a string, or an array of strings in a range.")),
19759
19718
  arg("text2 (string, range<string>, repeating)", _t("Additional text item(s).")),
19760
19719
  ],
19761
- returns: ["STRING"],
19762
19720
  compute: function (delimiter, ignoreEmpty, ...textsOrArrays) {
19763
19721
  const _delimiter = toString(delimiter);
19764
19722
  const _ignoreEmpty = toBoolean(ignoreEmpty);
@@ -19775,7 +19733,6 @@ const TRIM = {
19775
19733
  args: [
19776
19734
  arg("text (string)", _t("The text or reference to a cell containing text to be trimmed.")),
19777
19735
  ],
19778
- returns: ["STRING"],
19779
19736
  compute: function (text) {
19780
19737
  return trimContent(toString(text));
19781
19738
  },
@@ -19787,7 +19744,6 @@ const TRIM = {
19787
19744
  const UPPER = {
19788
19745
  description: _t("Converts a specified string to uppercase."),
19789
19746
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
19790
- returns: ["STRING"],
19791
19747
  compute: function (text) {
19792
19748
  return toString(text).toUpperCase();
19793
19749
  },
@@ -19802,7 +19758,6 @@ const TEXT = {
19802
19758
  arg("number (number)", _t("The number, date or time to format.")),
19803
19759
  arg("format (string)", _t("The pattern by which to format the number, enclosed in quotation marks.")),
19804
19760
  ],
19805
- returns: ["STRING"],
19806
19761
  compute: function (number, format) {
19807
19762
  const _number = toNumber(number, this.locale);
19808
19763
  return formatValue(_number, { format: toString(format), locale: this.locale });
@@ -19843,7 +19798,6 @@ const HYPERLINK = {
19843
19798
  arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")),
19844
19799
  arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks.")),
19845
19800
  ],
19846
- returns: ["STRING"],
19847
19801
  compute: function (url, linkLabel) {
19848
19802
  const processedUrl = toString(url).trim();
19849
19803
  const processedLabel = toString(linkLabel) || processedUrl;
@@ -19902,6 +19856,9 @@ function addInputHandling(descr) {
19902
19856
  }
19903
19857
  args[i] = arg[0][0];
19904
19858
  }
19859
+ if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
19860
+ throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
19861
+ }
19905
19862
  }
19906
19863
  return descr.compute.apply(this, args);
19907
19864
  }
@@ -21496,12 +21453,6 @@ function compileTokens(tokens) {
21496
21453
  // detect when an argument need to be evaluated as a meta argument
21497
21454
  const isMeta = argTypes.includes("META");
21498
21455
  const hasRange = argTypes.some((t) => isRangeType(t));
21499
- const isRangeOnly = argTypes.every((t) => isRangeType(t));
21500
- if (isRangeOnly) {
21501
- if (!isRangeInput(currentArg)) {
21502
- throw new BadExpressionError(_t("Function %(function_name)s expects the parameter %(arg_index)s to be a reference to a cell or a range.", { function_name: functionName, arg_index: i + 1 }));
21503
- }
21504
- }
21505
21456
  compiledArgs.push(compileAST(currentArg, isMeta, hasRange));
21506
21457
  }
21507
21458
  return compiledArgs;
@@ -21666,16 +21617,6 @@ function assertEnoughArgs(ast) {
21666
21617
  function isRangeType(type) {
21667
21618
  return type.startsWith("RANGE");
21668
21619
  }
21669
- function isRangeInput(arg) {
21670
- if (arg.type === "REFERENCE") {
21671
- return true;
21672
- }
21673
- if (arg.type === "FUNCALL") {
21674
- const fnDef = functions$1[arg.value.toUpperCase()];
21675
- return fnDef && isRangeType(fnDef.returns[0]);
21676
- }
21677
- return false;
21678
- }
21679
21620
 
21680
21621
  const functions = functionRegistry.content;
21681
21622
  function isExportableToExcel(tokens) {
@@ -21719,11 +21660,14 @@ const PIVOT_FUNCTIONS = ["PIVOT.VALUE", "PIVOT.HEADER", "PIVOT"];
21719
21660
  function makeFieldProposal(field, granularity) {
21720
21661
  const groupBy = granularity ? `${field.name}:${granularity}` : field.name;
21721
21662
  const quotedGroupBy = `"${groupBy}"`;
21663
+ const fuzzySearchKey = field.string !== field.name
21664
+ ? field.string + quotedGroupBy // search on translated name and on technical name
21665
+ : quotedGroupBy;
21722
21666
  return {
21723
21667
  text: quotedGroupBy,
21724
21668
  description: field.string + (field.help ? ` (${field.help})` : ""),
21725
21669
  htmlContent: [{ value: quotedGroupBy, color: tokenColors.STRING }],
21726
- fuzzySearchKey: field.string + quotedGroupBy, // search on translated name and on technical name
21670
+ fuzzySearchKey,
21727
21671
  };
21728
21672
  }
21729
21673
  /**
@@ -21783,6 +21727,14 @@ function getNumberOfPivotFunctions(tokens) {
21783
21727
  return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
21784
21728
  }
21785
21729
 
21730
+ /**
21731
+ * Registry to enable or disable the support of positional arguments
21732
+ * (with a leading #) in pivot functions
21733
+ * e.g. =PIVOT.VALUE(1,"probability","#stage",1)
21734
+ */
21735
+ const supportedPivotPositionalFormulaRegistry = new Registry();
21736
+ supportedPivotPositionalFormulaRegistry.add("SPREADSHEET", false);
21737
+
21786
21738
  autoCompleteProviders.add("pivot_ids", {
21787
21739
  sequence: 50,
21788
21740
  autoSelectFirstProposal: true,
@@ -21801,10 +21753,6 @@ autoCompleteProviders.add("pivot_ids", {
21801
21753
  return pivotIds
21802
21754
  .map((pivotId) => {
21803
21755
  const definition = this.getters.getPivotCoreDefinition(pivotId);
21804
- if (functionContext.parent.toUpperCase() !== "PIVOT" &&
21805
- !supportedPivotExplodedFormulaRegistry.get(definition.type)) {
21806
- return undefined;
21807
- }
21808
21756
  const formulaId = this.getters.getPivotFormulaId(pivotId);
21809
21757
  const str = `${formulaId}`;
21810
21758
  return {
@@ -21832,15 +21780,13 @@ autoCompleteProviders.add("pivot_measures", {
21832
21780
  if (!pivotId || !this.getters.isExistingPivot(pivotId)) {
21833
21781
  return [];
21834
21782
  }
21835
- const dataSource = this.getters.getPivot(pivotId);
21836
- const fields = dataSource.getFields();
21783
+ const pivot = this.getters.getPivot(pivotId);
21784
+ pivot.init();
21785
+ const fields = pivot.getFields();
21837
21786
  if (!fields) {
21838
21787
  return [];
21839
21788
  }
21840
21789
  const definition = this.getters.getPivotCoreDefinition(pivotId);
21841
- if (!supportedPivotExplodedFormulaRegistry.get(definition.type)) {
21842
- return [];
21843
- }
21844
21790
  return definition.measures
21845
21791
  .map((measure) => {
21846
21792
  if (measure.name === "__count") {
@@ -21876,16 +21822,13 @@ autoCompleteProviders.add("pivot_group_fields", {
21876
21822
  if (!pivotId || !this.getters.isExistingPivot(pivotId)) {
21877
21823
  return;
21878
21824
  }
21879
- const dataSource = this.getters.getPivot(pivotId);
21880
- const fields = dataSource.getFields();
21825
+ const pivot = this.getters.getPivot(pivotId);
21826
+ pivot.init();
21827
+ const fields = pivot.getFields();
21881
21828
  if (!fields) {
21882
21829
  return;
21883
21830
  }
21884
- const { type } = this.getters.getPivotCoreDefinition(pivotId);
21885
- const { columns, rows } = dataSource.definition;
21886
- if (!supportedPivotExplodedFormulaRegistry.get(type)) {
21887
- return [];
21888
- }
21831
+ const { columns, rows } = pivot.definition;
21889
21832
  let args = functionContext.args;
21890
21833
  if (functionContext?.parent.toUpperCase() === "PIVOT.VALUE") {
21891
21834
  args = args.filter((ast, index) => index % 2 === 0); // keep only the field names
@@ -21922,6 +21865,9 @@ autoCompleteProviders.add("pivot_group_fields", {
21922
21865
  return field ? makeFieldProposal(field, granularity) : undefined;
21923
21866
  })
21924
21867
  .concat(groupBys.map((groupBy) => {
21868
+ if (!supportedPivotPositionalFormulaRegistry.get(pivot.type)) {
21869
+ return undefined;
21870
+ }
21925
21871
  const fieldName = groupBy.split(":")[0];
21926
21872
  const field = fields[fieldName];
21927
21873
  if (!field) {
@@ -21970,12 +21916,8 @@ autoCompleteProviders.add("pivot_group_values", {
21970
21916
  if (!pivotId || !this.getters.isExistingPivot(pivotId)) {
21971
21917
  return;
21972
21918
  }
21973
- const { type } = this.getters.getPivotCoreDefinition(pivotId);
21974
- if (!supportedPivotExplodedFormulaRegistry.get(type)) {
21975
- return [];
21976
- }
21977
- const dataSource = this.getters.getPivot(pivotId);
21978
- if (!dataSource.isValid()) {
21919
+ const pivot = this.getters.getPivot(pivotId);
21920
+ if (!pivot.isValid()) {
21979
21921
  return;
21980
21922
  }
21981
21923
  const argPosition = functionContext.argPosition;
@@ -21983,7 +21925,46 @@ autoCompleteProviders.add("pivot_group_values", {
21983
21925
  if (!groupByField) {
21984
21926
  return;
21985
21927
  }
21986
- return dataSource.getPossibleFieldValues(groupByField.split(":")[0]).map(({ value, label }) => {
21928
+ let dimension;
21929
+ try {
21930
+ dimension = pivot.definition.getDimension(groupByField);
21931
+ }
21932
+ catch (error) {
21933
+ return undefined;
21934
+ }
21935
+ if (dimension.granularity === "month_number") {
21936
+ return Object.values(MONTHS).map((monthDisplayName, index) => ({
21937
+ text: `${index + 1}`,
21938
+ fuzzySearchKey: monthDisplayName.toString(),
21939
+ description: monthDisplayName.toString(),
21940
+ htmlContent: [{ value: `${index + 1}`, color: tokenColors.NUMBER }],
21941
+ }));
21942
+ }
21943
+ else if (dimension.granularity === "quarter_number") {
21944
+ return [1, 2, 3, 4].map((quarter) => ({
21945
+ text: `${quarter}`,
21946
+ fuzzySearchKey: `${quarter}`,
21947
+ description: _t("Quarter %s", quarter),
21948
+ htmlContent: [{ value: `${quarter}`, color: tokenColors.NUMBER }],
21949
+ }));
21950
+ }
21951
+ else if (dimension.granularity === "day_of_month") {
21952
+ return range(1, 32).map((dayOfMonth) => ({
21953
+ text: `${dayOfMonth}`,
21954
+ fuzzySearchKey: `${dayOfMonth}`,
21955
+ description: "",
21956
+ htmlContent: [{ value: `${dayOfMonth}`, color: tokenColors.NUMBER }],
21957
+ }));
21958
+ }
21959
+ else if (dimension.granularity === "iso_week_number") {
21960
+ return range(0, 54).map((isoWeekNumber) => ({
21961
+ text: `${isoWeekNumber}`,
21962
+ fuzzySearchKey: `${isoWeekNumber}`,
21963
+ description: "",
21964
+ htmlContent: [{ value: `${isoWeekNumber}`, color: tokenColors.NUMBER }],
21965
+ }));
21966
+ }
21967
+ return pivot.getPossibleFieldValues(dimension).map(({ value, label }) => {
21987
21968
  const isString = typeof value === "string";
21988
21969
  const text = isString ? `"${value}"` : value.toString();
21989
21970
  const color = isString ? tokenColors.STRING : tokenColors.NUMBER;
@@ -22090,7 +22071,9 @@ autofillModifiersRegistry
22090
22071
  tooltip: content
22091
22072
  ? {
22092
22073
  props: {
22093
- content: evaluateLiteral(data.cell?.content, localeFormat).formattedValue,
22074
+ content: data.cell
22075
+ ? evaluateLiteral(data.cell, localeFormat).formattedValue
22076
+ : "",
22094
22077
  },
22095
22078
  }
22096
22079
  : undefined,
@@ -22153,9 +22136,7 @@ function getGroup(cell, cells, filter) {
22153
22136
  if (x === cell) {
22154
22137
  found = true;
22155
22138
  }
22156
- const cellValue = x?.isFormula
22157
- ? undefined
22158
- : evaluateLiteral(x?.content, { locale: DEFAULT_LOCALE });
22139
+ const cellValue = x === undefined || x.isFormula ? undefined : evaluateLiteral(x, { locale: DEFAULT_LOCALE });
22159
22140
  if (cellValue && filter(cellValue)) {
22160
22141
  group.push(cellValue);
22161
22142
  }
@@ -22203,7 +22184,7 @@ autofillRulesRegistry
22203
22184
  })
22204
22185
  .add("increment_alphanumeric_value", {
22205
22186
  condition: (cell) => !cell.isFormula &&
22206
- evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.text &&
22187
+ evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.text &&
22207
22188
  alphaNumericValueRegExp.test(cell.content),
22208
22189
  generateRule: (cell, cells) => {
22209
22190
  const numberPostfix = parseInt(cell.content.match(numberPostfixRegExp)[0]);
@@ -22226,7 +22207,7 @@ autofillRulesRegistry
22226
22207
  })
22227
22208
  .add("copy_text", {
22228
22209
  condition: (cell) => !cell.isFormula &&
22229
- evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.text,
22210
+ evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.text,
22230
22211
  generateRule: () => {
22231
22212
  return { type: "COPY_MODIFIER" };
22232
22213
  },
@@ -22241,11 +22222,11 @@ autofillRulesRegistry
22241
22222
  })
22242
22223
  .add("increment_number", {
22243
22224
  condition: (cell) => !cell.isFormula &&
22244
- evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
22225
+ evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
22245
22226
  generateRule: (cell, cells) => {
22246
22227
  const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number).map((cell) => Number(cell.value));
22247
22228
  const increment = calculateIncrementBasedOnGroup(group);
22248
- const evaluation = evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE });
22229
+ const evaluation = evaluateLiteral(cell, { locale: DEFAULT_LOCALE });
22249
22230
  return {
22250
22231
  type: "INCREMENT_MODIFIER",
22251
22232
  increment,
@@ -25469,7 +25450,7 @@ class Popover extends owl.Component {
25469
25450
  if (!anchor)
25470
25451
  return;
25471
25452
  const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
25472
- const elDims = {
25453
+ let elDims = {
25473
25454
  width: el.getBoundingClientRect().width,
25474
25455
  height: el.getBoundingClientRect().height,
25475
25456
  };
@@ -25477,7 +25458,14 @@ class Popover extends owl.Component {
25477
25458
  const popoverPositionHelper = this.props.positioning === "BottomLeft"
25478
25459
  ? new BottomLeftPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect)
25479
25460
  : new TopRightPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect);
25480
- const style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
25461
+ el.style["max-height"] = popoverPositionHelper.getMaxHeight(elDims.height) + "px";
25462
+ el.style["max-width"] = popoverPositionHelper.getMaxWidth(elDims.width) + "px";
25463
+ // Re-compute the dimensions after setting the max-width and max-height
25464
+ elDims = {
25465
+ width: el.getBoundingClientRect().width,
25466
+ height: el.getBoundingClientRect().height,
25467
+ };
25468
+ let style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
25481
25469
  for (const property of Object.keys(style)) {
25482
25470
  el.style[property] = style[property];
25483
25471
  }
@@ -25540,8 +25528,6 @@ class PopoverPositionContext {
25540
25528
  const shouldRenderAtRight = this.shouldRenderAtRight(elDims.width);
25541
25529
  verticalOffset = shouldRenderAtBottom ? verticalOffset : -verticalOffset;
25542
25530
  const cssProperties = {
25543
- "max-height": maxHeight + "px",
25544
- "max-width": maxWidth + "px",
25545
25531
  top: this.getTopCoordinate(actualHeight, shouldRenderAtBottom) -
25546
25532
  this.spreadsheetOffset.y -
25547
25533
  verticalOffset +
@@ -31355,10 +31341,8 @@ class ChartTitle extends owl.Component {
31355
31341
 
31356
31342
  class AxisDesignEditor extends owl.Component {
31357
31343
  static template = "o-spreadsheet-AxisDesignEditor";
31358
- static components = {
31359
- Section,
31360
- ChartTitle,
31361
- };
31344
+ static components = { Section, ChartTitle };
31345
+ static props = { figureId: String, definition: Object, updateChart: Function, axesList: Array };
31362
31346
  state = owl.useState({ currentAxis: "x" });
31363
31347
  get axisTitleStyle() {
31364
31348
  const axisDesign = this.props.definition.axesDesign?.[this.state.currentAxis] ?? {};
@@ -31509,6 +31493,12 @@ class ChartWithAxisDesignPanel extends owl.Component {
31509
31493
  AxisDesignEditor,
31510
31494
  RoundColorPicker,
31511
31495
  };
31496
+ static props = {
31497
+ figureId: String,
31498
+ definition: Object,
31499
+ canUpdateChart: Function,
31500
+ updateChart: Function,
31501
+ };
31512
31502
  state = owl.useState({ index: 0 });
31513
31503
  get axesList() {
31514
31504
  const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
@@ -33453,13 +33443,17 @@ class SelectMenu extends owl.Component {
33453
33443
  class: { type: String, optional: true },
33454
33444
  };
33455
33445
  static components = { Menu };
33446
+ menuId = new UuidGenerator().uuidv4();
33456
33447
  selectRef = owl.useRef("select");
33457
33448
  selectRect = useAbsoluteBoundingRect(this.selectRef);
33458
33449
  state = owl.useState({
33459
33450
  isMenuOpen: false,
33460
33451
  });
33461
- onClick() {
33462
- this.state.isMenuOpen = true;
33452
+ onClick(ev) {
33453
+ if (ev.closedMenuId === this.menuId) {
33454
+ return;
33455
+ }
33456
+ this.state.isMenuOpen = !this.state.isMenuOpen;
33463
33457
  }
33464
33458
  onMenuClosed() {
33465
33459
  this.state.isMenuOpen = false;
@@ -33467,7 +33461,7 @@ class SelectMenu extends owl.Component {
33467
33461
  get menuPosition() {
33468
33462
  return {
33469
33463
  x: this.selectRect.x,
33470
- y: this.selectRect.y,
33464
+ y: this.selectRect.y + this.selectRect.height,
33471
33465
  };
33472
33466
  }
33473
33467
  }
@@ -34407,9 +34401,9 @@ class FindAndReplacePanel extends owl.Component {
34407
34401
  static props = {
34408
34402
  onCloseSidePanel: Function,
34409
34403
  };
34410
- dataRange = "";
34411
34404
  searchInput = owl.useRef("searchInput");
34412
34405
  store;
34406
+ state;
34413
34407
  get hasSearchResult() {
34414
34408
  return this.store.selectedMatchIndex !== null;
34415
34409
  }
@@ -34439,6 +34433,7 @@ class FindAndReplacePanel extends owl.Component {
34439
34433
  }
34440
34434
  setup() {
34441
34435
  this.store = useLocalStore(FindAndReplaceStore);
34436
+ this.state = owl.useState({ dataRange: "" });
34442
34437
  owl.onMounted(() => this.searchInput.el?.focus());
34443
34438
  }
34444
34439
  onFocusSearch() {
@@ -34475,13 +34470,13 @@ class FindAndReplacePanel extends owl.Component {
34475
34470
  this.store.updateSearchOptions({ searchScope });
34476
34471
  }
34477
34472
  onSearchRangeChanged(ranges) {
34478
- this.dataRange = ranges[0];
34473
+ this.state.dataRange = ranges[0];
34479
34474
  }
34480
34475
  updateDataRange() {
34481
- if (!this.dataRange || this.searchOptions.searchScope !== "specificRange") {
34476
+ if (!this.state.dataRange || this.searchOptions.searchScope !== "specificRange") {
34482
34477
  return;
34483
34478
  }
34484
- const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.dataRange);
34479
+ const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
34485
34480
  this.store.updateSearchOptions({ specificRange });
34486
34481
  }
34487
34482
  }
@@ -34526,31 +34521,6 @@ class MoreFormatsPanel extends owl.Component {
34526
34521
  }
34527
34522
  }
34528
34523
 
34529
- /** @odoo-module */
34530
- class EditableName extends owl.Component {
34531
- static template = "o-spreadsheet-EditableName";
34532
- static props = {
34533
- name: String,
34534
- displayName: String,
34535
- onChanged: Function,
34536
- };
34537
- state;
34538
- setup() {
34539
- this.state = owl.useState({
34540
- isEditing: false,
34541
- name: "",
34542
- });
34543
- }
34544
- rename() {
34545
- this.state.isEditing = true;
34546
- this.state.name = this.props.name;
34547
- }
34548
- save() {
34549
- this.props.onChanged(this.state.name.trim());
34550
- this.state.isEditing = false;
34551
- }
34552
- }
34553
-
34554
34524
  css /* scss */ `
34555
34525
  .pivot-defer-update {
34556
34526
  min-height: 35px;
@@ -34916,6 +34886,135 @@ class PivotLayoutConfigurator extends owl.Component {
34916
34886
  }
34917
34887
  }
34918
34888
 
34889
+ css /* scss */ `
34890
+ .os-cog-wheel-menu-icon {
34891
+ cursor: pointer;
34892
+ }
34893
+
34894
+ .os-cog-wheel-menu {
34895
+ background: white;
34896
+ .btn-link {
34897
+ text-decoration: none;
34898
+ color: #017e84;
34899
+ font-weight: 500;
34900
+ &:hover {
34901
+ color: #01585c;
34902
+ }
34903
+ }
34904
+ }
34905
+ `;
34906
+ class CogWheelMenu extends owl.Component {
34907
+ static template = "o-spreadsheet-CogWheelMenu";
34908
+ static components = { Popover };
34909
+ static props = {
34910
+ items: Array,
34911
+ };
34912
+ buttonRef = owl.useRef("button");
34913
+ popover = owl.useState({ isOpen: false });
34914
+ setup() {
34915
+ owl.useExternalListener(window, "click", (ev) => {
34916
+ if (ev.target !== this.buttonRef.el) {
34917
+ this.popover.isOpen = false;
34918
+ }
34919
+ });
34920
+ }
34921
+ get popoverProps() {
34922
+ const { x, y, width, height } = this.buttonRef.el.getBoundingClientRect();
34923
+ return {
34924
+ anchorRect: { x, y, width, height },
34925
+ positioning: "BottomLeft",
34926
+ };
34927
+ }
34928
+ togglePopover() {
34929
+ this.popover.isOpen = !this.popover.isOpen;
34930
+ }
34931
+ }
34932
+
34933
+ /** @odoo-module */
34934
+ class EditableName extends owl.Component {
34935
+ static template = "o-spreadsheet-EditableName";
34936
+ static props = {
34937
+ name: String,
34938
+ displayName: String,
34939
+ onChanged: Function,
34940
+ };
34941
+ state;
34942
+ setup() {
34943
+ this.state = owl.useState({
34944
+ isEditing: false,
34945
+ name: "",
34946
+ });
34947
+ }
34948
+ rename() {
34949
+ this.state.isEditing = true;
34950
+ this.state.name = this.props.name;
34951
+ }
34952
+ save() {
34953
+ this.props.onChanged(this.state.name.trim());
34954
+ this.state.isEditing = false;
34955
+ }
34956
+ }
34957
+
34958
+ class PivotTitleSection extends owl.Component {
34959
+ static template = "o-spreadsheet-PivotTitleSection";
34960
+ static components = { CogWheelMenu, Section, EditableName };
34961
+ static props = {
34962
+ pivotId: String,
34963
+ };
34964
+ get cogWheelMenuItems() {
34965
+ return [
34966
+ {
34967
+ name: "Duplicate",
34968
+ icon: "fa-copy",
34969
+ onClick: () => this.duplicatePivot(),
34970
+ },
34971
+ {
34972
+ name: "Delete",
34973
+ icon: "fa-trash",
34974
+ onClick: () => this.delete(),
34975
+ },
34976
+ ];
34977
+ }
34978
+ get name() {
34979
+ return this.env.model.getters.getPivotName(this.props.pivotId);
34980
+ }
34981
+ get displayName() {
34982
+ return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
34983
+ }
34984
+ duplicatePivot() {
34985
+ const newPivotId = this.env.model.uuidGenerator.uuidv4();
34986
+ const result = this.env.model.dispatch("DUPLICATE_PIVOT", {
34987
+ pivotId: this.props.pivotId,
34988
+ newPivotId,
34989
+ });
34990
+ const text = result.isSuccessful ? _t("Pivot duplicated.") : _t("Pivot duplication failed");
34991
+ const type = result.isSuccessful ? "success" : "danger";
34992
+ this.env.notifyUser({
34993
+ text,
34994
+ sticky: false,
34995
+ type,
34996
+ });
34997
+ if (result.isSuccessful) {
34998
+ this.env.openSidePanel("PivotSidePanel", { pivotId: newPivotId });
34999
+ }
35000
+ }
35001
+ delete() {
35002
+ this.env.askConfirmation(_t("Are you sure you want to delete this pivot?"), () => {
35003
+ this.env.model.dispatch("REMOVE_PIVOT", { pivotId: this.props.pivotId });
35004
+ });
35005
+ }
35006
+ onNameChanged(name) {
35007
+ const pivot = this.env.model.getters.getPivotCoreDefinition(this.props.pivotId);
35008
+ this.env.model.dispatch("UPDATE_PIVOT", {
35009
+ pivotId: this.props.pivotId,
35010
+ pivot: {
35011
+ ...pivot,
35012
+ name,
35013
+ },
35014
+ });
35015
+ }
35016
+ }
35017
+
34919
35018
  /**
34920
35019
  * Represent a pivot runtime definition. A pivot runtime definition is a pivot
34921
35020
  * definition that has been enriched to include the display name of its attributes
@@ -35220,7 +35319,7 @@ function dataEntriesToRows(dataEntries, index, rows, fields, values) {
35220
35319
  }
35221
35320
  const row = rows[index];
35222
35321
  const rowName = row.nameWithGranularity;
35223
- const groups = groupBy(dataEntries, row);
35322
+ const groups = groupPivotDataEntriesBy(dataEntries, row);
35224
35323
  const orderedKeys = orderDataEntriesKeys(groups, row);
35225
35324
  const pivotTableRows = [];
35226
35325
  const _fields = fields.concat(rowName);
@@ -35250,7 +35349,7 @@ function dataEntriesToColumnsTree(dataEntries, columns, index) {
35250
35349
  }
35251
35350
  const column = columns[index];
35252
35351
  const colName = columns[index].nameWithGranularity;
35253
- const groups = groupBy(dataEntries, column);
35352
+ const groups = groupPivotDataEntriesBy(dataEntries, column);
35254
35353
  const orderedKeys = orderDataEntriesKeys(groups, columns[index]);
35255
35354
  return orderedKeys.map((value) => {
35256
35355
  return {
@@ -35348,7 +35447,7 @@ function columnsTreeToColumns(mainTree, definition) {
35348
35447
  /**
35349
35448
  * Group the dataEntries based on the given dimension
35350
35449
  */
35351
- function groupBy(dataEntries, dimension) {
35450
+ function groupPivotDataEntriesBy(dataEntries, dimension) {
35352
35451
  return Object.groupBy(dataEntries, keySelector(dimension));
35353
35452
  }
35354
35453
  /**
@@ -35398,7 +35497,7 @@ function createDate(dimension, value, locale) {
35398
35497
  number = Math.floor(date.getMonth() / 3) + 1;
35399
35498
  break;
35400
35499
  case "month_number":
35401
- number = date.getMonth();
35500
+ number = date.getMonth() + 1;
35402
35501
  break;
35403
35502
  case "iso_week_number":
35404
35503
  number = date.getIsoWeek();
@@ -35410,7 +35509,7 @@ function createDate(dimension, value, locale) {
35410
35509
  number = Math.floor(toNumber(value, locale));
35411
35510
  break;
35412
35511
  }
35413
- MAP_VALUE_DIMENSION_DATE[granularity].values[`${value}`] = number;
35512
+ MAP_VALUE_DIMENSION_DATE[granularity].values[`${value}`] = toNormalizedPivotValue(dimension, number);
35414
35513
  }
35415
35514
  return MAP_VALUE_DIMENSION_DATE[granularity].values[`${value}`];
35416
35515
  }
@@ -35556,7 +35655,7 @@ class SpreadsheetPivot {
35556
35655
  return this._definition;
35557
35656
  }
35558
35657
  isValid() {
35559
- if (this.invalidRangeError || !this._definition) {
35658
+ if (this.invalidRangeError || !this.definition) {
35560
35659
  return false;
35561
35660
  }
35562
35661
  for (const measure of this.definition.measures) {
@@ -35613,25 +35712,19 @@ class SpreadsheetPivot {
35613
35712
  const dimension = this.getDimension(lastNode.field);
35614
35713
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
35615
35714
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
35715
+ if (dimension.type === "date") {
35716
+ const adapter = pivotTimeAdapter(dimension.granularity);
35717
+ return {
35718
+ value: adapter.toCellValue(toNormalizedPivotValue(dimension, lastNode.value)),
35719
+ format: adapter.getFormat(this.getters.getLocale()),
35720
+ };
35721
+ }
35616
35722
  if (!finalCell) {
35617
35723
  return { value: "" };
35618
35724
  }
35619
35725
  if (finalCell.value === null) {
35620
35726
  return { value: _t("(Undefined)") };
35621
35727
  }
35622
- if (dimension.type === "date") {
35623
- if (dimension.granularity === "day") {
35624
- return {
35625
- value: toNumber(finalCell.value, this.getters.getLocale()),
35626
- format: this.getters.getLocale().dateFormat,
35627
- };
35628
- }
35629
- if (dimension.granularity === "month_number") {
35630
- return {
35631
- value: MONTHS[toNumber(finalCell.value, this.getters.getLocale())].toString(),
35632
- };
35633
- }
35634
- }
35635
35728
  return {
35636
35729
  value: finalCell.value,
35637
35730
  format: finalCell.format,
@@ -35656,9 +35749,12 @@ class SpreadsheetPivot {
35656
35749
  format: operator.format(values[0]),
35657
35750
  };
35658
35751
  }
35659
- getPossibleFieldValues(groupBy) {
35660
- //TODO This method should be implemented for the autocomplete feature
35661
- throw new Error("Method not implemented.");
35752
+ getPossibleFieldValues(dimension) {
35753
+ const values = [];
35754
+ for (const value in groupPivotDataEntriesBy(this.dataEntries, dimension)) {
35755
+ values.push({ value, label: "" });
35756
+ }
35757
+ return values;
35662
35758
  }
35663
35759
  getTableStructure() {
35664
35760
  if (!this.isValid()) {
@@ -35678,7 +35774,8 @@ class SpreadsheetPivot {
35678
35774
  filterDataEntriesFromDomainNode(dataEntries, domain) {
35679
35775
  const { field, value } = domain;
35680
35776
  const dimension = this.getDimension(field);
35681
- return dataEntries.filter((entry) => `${entry[dimension.nameWithGranularity]?.value}` === value);
35777
+ return dataEntries.filter((entry) => `${entry[dimension.nameWithGranularity]?.value}` ===
35778
+ `${toNormalizedPivotValue(dimension, value)}`);
35682
35779
  }
35683
35780
  getDimension(nameWithGranularity) {
35684
35781
  return this.definition.getDimension(nameWithGranularity);
@@ -35814,15 +35911,8 @@ pivotRegistry.add("SPREADSHEET", {
35814
35911
 
35815
35912
  class PivotSidePanelStore extends SpreadsheetStore {
35816
35913
  pivotId;
35817
- mutators = [
35818
- "reset",
35819
- "deferUpdates",
35820
- "applyUpdate",
35821
- "discardPendingUpdate",
35822
- "renamePivot",
35823
- "update",
35824
- ];
35825
- updatesAreDeferred = true;
35914
+ mutators = ["reset", "deferUpdates", "applyUpdate", "discardPendingUpdate", "update"];
35915
+ updatesAreDeferred = false;
35826
35916
  draft = null;
35827
35917
  constructor(get, pivotId) {
35828
35918
  super(get);
@@ -35939,16 +36029,6 @@ class PivotSidePanelStore extends SpreadsheetStore {
35939
36029
  discardPendingUpdate() {
35940
36030
  this.draft = null;
35941
36031
  }
35942
- renamePivot(name) {
35943
- const pivot = this.getters.getPivotCoreDefinition(this.pivotId);
35944
- this.model.dispatch("UPDATE_PIVOT", {
35945
- pivotId: this.pivotId,
35946
- pivot: {
35947
- ...pivot,
35948
- name,
35949
- },
35950
- });
35951
- }
35952
36032
  update(definitionUpdate) {
35953
36033
  const coreDefinition = this.getters.getPivotCoreDefinition(this.pivotId);
35954
36034
  const definition = { ...coreDefinition, ...this.draft, ...definitionUpdate };
@@ -36031,9 +36111,9 @@ class PivotSpreadsheetSidePanel extends owl.Component {
36031
36111
  PivotLayoutConfigurator,
36032
36112
  Section,
36033
36113
  SelectionInput,
36034
- EditableName,
36035
36114
  Checkbox,
36036
36115
  PivotDeferUpdate,
36116
+ PivotTitleSection,
36037
36117
  };
36038
36118
  store;
36039
36119
  state;
@@ -36062,12 +36142,6 @@ class PivotSpreadsheetSidePanel extends owl.Component {
36062
36142
  get pivot() {
36063
36143
  return this.store.pivot;
36064
36144
  }
36065
- get name() {
36066
- return this.env.model.getters.getPivotName(this.props.pivotId);
36067
- }
36068
- get displayName() {
36069
- return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
36070
- }
36071
36145
  get definition() {
36072
36146
  return this.store.definition;
36073
36147
  }
@@ -36091,35 +36165,9 @@ class PivotSpreadsheetSidePanel extends owl.Component {
36091
36165
  this.store.applyUpdate();
36092
36166
  }
36093
36167
  }
36094
- duplicatePivot() {
36095
- const newPivotId = this.env.model.uuidGenerator.uuidv4();
36096
- const result = this.env.model.dispatch("DUPLICATE_PIVOT", {
36097
- pivotId: this.props.pivotId,
36098
- newPivotId,
36099
- });
36100
- const text = result.isSuccessful ? _t("Pivot duplicated.") : _t("Pivot duplication failed");
36101
- const type = result.isSuccessful ? "success" : "danger";
36102
- this.env.notifyUser({
36103
- text,
36104
- sticky: false,
36105
- type,
36106
- });
36107
- if (result.isSuccessful) {
36108
- this.env.openSidePanel("PivotSidePanel", { pivotId: newPivotId });
36109
- }
36110
- }
36111
- onNameChanged(name) {
36112
- this.store.renamePivot(name);
36113
- }
36114
36168
  onDimensionsUpdated(definition) {
36115
36169
  this.store.update(definition);
36116
36170
  }
36117
- back() {
36118
- this.env.openSidePanel("PivotSidePanel", {});
36119
- }
36120
- delete() {
36121
- this.env.model.dispatch("REMOVE_PIVOT", { pivotId: this.props.pivotId });
36122
- }
36123
36171
  }
36124
36172
 
36125
36173
  const pivotSidePanelRegistry = new Registry();
@@ -36127,44 +36175,17 @@ pivotSidePanelRegistry.add("SPREADSHEET", {
36127
36175
  editor: PivotSpreadsheetSidePanel,
36128
36176
  });
36129
36177
 
36130
- css /* scss */ `
36131
- .o_pivot_list_item {
36132
- cursor: pointer;
36133
- &:hover {
36134
- background-color: #f1f3f4;
36135
- }
36136
- }
36137
- `;
36138
- class PivotListItem extends owl.Component {
36139
- static template = "o-spreadsheet-PivotListItem";
36140
- static props = { pivotId: String };
36141
- setup() {
36142
- const previewRef = owl.useRef("pivotListItem");
36143
- useHighlightsOnHover(previewRef, this);
36144
- }
36145
- selectPivot() {
36146
- this.env.openSidePanel("PivotSidePanel", { pivotId: this.props.pivotId });
36147
- }
36148
- get highlights() {
36149
- return getPivotHighlights(this.env.model.getters, this.props.pivotId);
36150
- }
36151
- }
36152
-
36153
36178
  class PivotSidePanel extends owl.Component {
36154
36179
  static template = "o-spreadsheet-PivotSidePanel";
36155
36180
  static props = {
36156
- pivotId: { type: String, optional: true },
36181
+ pivotId: String,
36157
36182
  onCloseSidePanel: Function,
36158
36183
  };
36159
36184
  static components = {
36160
36185
  PivotLayoutConfigurator,
36161
36186
  Section,
36162
- PivotListItem,
36163
36187
  };
36164
36188
  get sidePanelEditor() {
36165
- if (!this.props.pivotId) {
36166
- throw new Error("pivotId is required to call this function.");
36167
- }
36168
36189
  const pivot = this.env.model.getters.getPivotCoreDefinition(this.props.pivotId);
36169
36190
  if (!pivot) {
36170
36191
  throw new Error("pivotId does not correspond to a pivot.");
@@ -36181,6 +36202,7 @@ css /* scss */ `
36181
36202
  class RemoveDuplicatesPanel extends owl.Component {
36182
36203
  static template = "o-spreadsheet-RemoveDuplicatesPanel";
36183
36204
  static components = { ValidationMessages, Section, Checkbox };
36205
+ static props = { onCloseSidePanel: Function };
36184
36206
  state = owl.useState({
36185
36207
  hasHeader: false,
36186
36208
  columns: {},
@@ -37323,21 +37345,15 @@ sidePanelRegistry.add("TableStyleEditorPanel", {
37323
37345
  });
37324
37346
  sidePanelRegistry.add("PivotSidePanel", {
37325
37347
  title: (env, props) => {
37326
- if (props.pivotId) {
37327
- return _t("Pivot #%s", env.model.getters.getPivotFormulaId(props.pivotId));
37328
- }
37329
- return _t("List of Pivots");
37348
+ return _t("Pivot #%s", env.model.getters.getPivotFormulaId(props.pivotId));
37330
37349
  },
37331
37350
  Body: PivotSidePanel,
37332
- computeState: (getters, initialProps) => {
37333
- if (!getters.getPivotIds().length) {
37334
- return { isOpen: false };
37335
- }
37336
- let { pivotId } = initialProps;
37337
- if (pivotId && !getters.isExistingPivot(pivotId)) {
37338
- pivotId = undefined;
37339
- }
37340
- return { isOpen: true, props: { pivotId }, key: `pivot_key_${pivotId}` };
37351
+ computeState: (getters, props) => {
37352
+ return {
37353
+ isOpen: getters.isExistingPivot(props.pivotId),
37354
+ props,
37355
+ key: `pivot_key_${props.pivotId}`,
37356
+ };
37341
37357
  },
37342
37358
  });
37343
37359
 
@@ -41595,133 +41611,6 @@ class Grid extends owl.Component {
41595
41611
  }
41596
41612
  }
41597
41613
 
41598
- const pivotTimeAdapterRegistry = new Registry();
41599
- function pivotTimeAdapter(granularity) {
41600
- return pivotTimeAdapterRegistry.get(granularity);
41601
- }
41602
- /**
41603
- * The Time Adapter: Managing Time Periods for Pivot Functions
41604
- *
41605
- * Overview:
41606
- * A time adapter is responsible for managing time periods associated with pivot functions.
41607
- * Each type of period (day, week, month, quarter, etc.) has its own dedicated adapter.
41608
- * The adapter's primary role is to normalize period values between spreadsheet functions,
41609
- * and the pivot.
41610
- * By normalizing the period value, it can be stored consistently in the pivot.
41611
- *
41612
- * Normalization Process:
41613
- * When working with functions in the spreadsheet, the time adapter normalizes
41614
- * the provided period to facilitate accurate lookup of values in the pivot.
41615
- * For instance, if the spreadsheet function represents a day period as a number generated
41616
- * by the DATE function (DATE(2023, 12, 25)), the time adapter will normalize it accordingly.
41617
- *
41618
- */
41619
- /**
41620
- * Normalized value: "12/25/2023"
41621
- *
41622
- * Note: Those two format are equivalent:
41623
- * - "MM/dd/yyyy" (luxon format)
41624
- * - "mm/dd/yyyy" (spreadsheet format)
41625
- **/
41626
- const dayAdapter = {
41627
- normalizeFunctionValue(value) {
41628
- const date = toNumber(value, DEFAULT_LOCALE);
41629
- return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/dd/yyyy" });
41630
- },
41631
- getFormat(locale) {
41632
- return (locale ?? DEFAULT_LOCALE).dateFormat;
41633
- },
41634
- formatValue(normalizedValue, locale) {
41635
- locale = locale ?? DEFAULT_LOCALE;
41636
- const value = toNumber(normalizedValue, DEFAULT_LOCALE);
41637
- return formatValue(value, { locale, format: this.getFormat(locale) });
41638
- },
41639
- toCellValue(normalizedValue) {
41640
- return toNumber(normalizedValue, DEFAULT_LOCALE);
41641
- },
41642
- };
41643
- /**
41644
- * Normalized value: "2/2023" for week 2 of 2023
41645
- */
41646
- const weekAdapter = {
41647
- normalizeFunctionValue(value) {
41648
- const [week, year] = value.split("/");
41649
- return `${Number(week)}/${Number(year)}`;
41650
- },
41651
- getFormat() {
41652
- return undefined;
41653
- },
41654
- formatValue(normalizedValue) {
41655
- const [week, year] = normalizedValue.split("/");
41656
- return _t("W%(week)s %(year)s", { week, year });
41657
- },
41658
- toCellValue(normalizedValue) {
41659
- return this.formatValue(normalizedValue);
41660
- },
41661
- };
41662
- /**
41663
- * normalized month value is a string formatted as "MM/yyyy" (luxon format)
41664
- * e.g. "01/2020" for January 2020
41665
- */
41666
- const monthAdapter = {
41667
- normalizeFunctionValue(value) {
41668
- const date = toNumber(value, DEFAULT_LOCALE);
41669
- return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
41670
- },
41671
- getFormat() {
41672
- return "mmmm yyyy";
41673
- },
41674
- formatValue(normalizedValue, locale) {
41675
- locale = locale ?? DEFAULT_LOCALE;
41676
- const value = toNumber(normalizedValue, DEFAULT_LOCALE);
41677
- return formatValue(value, { locale, format: this.getFormat(locale) });
41678
- },
41679
- toCellValue(normalizedValue) {
41680
- return toNumber(normalizedValue, DEFAULT_LOCALE);
41681
- },
41682
- };
41683
- /**
41684
- * normalized quarter value is "quarter/year"
41685
- * e.g. "1/2020" for Q1 2020
41686
- */
41687
- const quarterAdapter = {
41688
- normalizeFunctionValue(value) {
41689
- const [quarter, year] = value.split("/");
41690
- return `${quarter}/${year}`;
41691
- },
41692
- getFormat() {
41693
- return undefined;
41694
- },
41695
- formatValue(normalizedValue) {
41696
- const [quarter, year] = normalizedValue.split("/");
41697
- return _t("Q%(quarter)s %(year)s", { quarter, year });
41698
- },
41699
- toCellValue(normalizedValue) {
41700
- return this.formatValue(normalizedValue);
41701
- },
41702
- };
41703
- const yearAdapter = {
41704
- normalizeFunctionValue(value) {
41705
- return toNumber(value, DEFAULT_LOCALE);
41706
- },
41707
- getFormat() {
41708
- return "0";
41709
- },
41710
- formatValue(normalizedValue, locale) {
41711
- locale = locale ?? DEFAULT_LOCALE;
41712
- return formatValue(normalizedValue, { locale, format: "0" });
41713
- },
41714
- toCellValue(normalizedValue) {
41715
- return normalizedValue;
41716
- },
41717
- };
41718
- pivotTimeAdapterRegistry
41719
- .add("day", dayAdapter)
41720
- .add("week", weekAdapter)
41721
- .add("month", monthAdapter)
41722
- .add("quarter", quarterAdapter)
41723
- .add("year", yearAdapter);
41724
-
41725
41614
  /**
41726
41615
  * Represent a raw XML string
41727
41616
  */
@@ -46920,9 +46809,14 @@ class CellPlugin extends CorePlugin {
46920
46809
  }
46921
46810
  createLiteralCell(id, content, format, style) {
46922
46811
  const locale = this.getters.getLocale();
46923
- format = format || detectDateFormat(content, locale) || detectNumberFormat(content);
46812
+ const parsedValue = parseLiteral(content, locale);
46813
+ format =
46814
+ format ||
46815
+ (typeof parsedValue === "number"
46816
+ ? detectDateFormat(content, locale) || detectNumberFormat(content)
46817
+ : undefined);
46924
46818
  if (format !== PLAIN_TEXT_FORMAT && !isEvaluationError(content)) {
46925
- content = toString(parseLiteral(content, locale));
46819
+ content = toString(parsedValue);
46926
46820
  }
46927
46821
  return {
46928
46822
  id,
@@ -46930,6 +46824,7 @@ class CellPlugin extends CorePlugin {
46930
46824
  style,
46931
46825
  format,
46932
46826
  isFormula: false,
46827
+ parsedValue,
46933
46828
  };
46934
46829
  }
46935
46830
  createFormulaCell(id, content, format, style, sheetId) {
@@ -51672,6 +51567,9 @@ class PositionMap {
51672
51567
  get({ sheetId, col, row }) {
51673
51568
  return this.map[sheetId]?.[col]?.[row];
51674
51569
  }
51570
+ getSheet(sheetId) {
51571
+ return this.map[sheetId];
51572
+ }
51675
51573
  has({ sheetId, col, row }) {
51676
51574
  return this.map[sheetId]?.[col]?.[row] !== undefined;
51677
51575
  }
@@ -51690,6 +51588,19 @@ class PositionMap {
51690
51588
  }
51691
51589
  return keys;
51692
51590
  }
51591
+ keysForSheet(sheetId) {
51592
+ const map = this.map[sheetId];
51593
+ if (!map) {
51594
+ return [];
51595
+ }
51596
+ const keys = [];
51597
+ for (const col in map) {
51598
+ for (const row in map[col]) {
51599
+ keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
51600
+ }
51601
+ }
51602
+ return keys;
51603
+ }
51693
51604
  }
51694
51605
 
51695
51606
  function quickselect(arr, k, left, right, compare) {
@@ -52768,6 +52679,9 @@ class Evaluator {
52768
52679
  getEvaluatedPositions() {
52769
52680
  return this.evaluatedCells.keys();
52770
52681
  }
52682
+ getEvaluatedPositionsInSheet(sheetId) {
52683
+ return this.evaluatedCells.keysForSheet(sheetId);
52684
+ }
52771
52685
  getArrayFormulaSpreadingOn(position) {
52772
52686
  if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
52773
52687
  return this.spreadingRelations.isArrayFormula(position) ? position : undefined;
@@ -52776,6 +52690,9 @@ class Evaluator {
52776
52690
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
52777
52691
  }
52778
52692
  updateDependencies(position) {
52693
+ // removing dependencies is slow because it requires
52694
+ // to traverse the entire r-tree.
52695
+ // The data structure is optimized for searches the other way around
52779
52696
  this.formulaDependencies().removeAllDependencies(position);
52780
52697
  const dependencies = this.getDirectDependencies(position);
52781
52698
  this.formulaDependencies().addDependencies(position, dependencies);
@@ -52941,7 +52858,7 @@ class Evaluator {
52941
52858
  this.cellsBeingComputed.add(cellId);
52942
52859
  return cell.isFormula
52943
52860
  ? this.computeFormulaCell(position.sheetId, cell)
52944
- : evaluateLiteral(cell.content, localeFormat);
52861
+ : evaluateLiteral(cell, localeFormat);
52945
52862
  }
52946
52863
  catch (e) {
52947
52864
  e.value = e?.value || CellErrorType.GenericError;
@@ -53211,6 +53128,7 @@ class EvaluationPlugin extends UIPlugin {
53211
53128
  "getEvaluatedCell",
53212
53129
  "getEvaluatedCells",
53213
53130
  "getEvaluatedCellsInZone",
53131
+ "getEvaluatedCellsPositions",
53214
53132
  "getSpreadZone",
53215
53133
  "getArrayFormulaSpreadingOn",
53216
53134
  "isEmpty",
@@ -53302,13 +53220,12 @@ class EvaluationPlugin extends UIPlugin {
53302
53220
  return this.evaluator.getEvaluatedCell(position);
53303
53221
  }
53304
53222
  getEvaluatedCells(sheetId) {
53305
- const rawCells = this.getters.getCells(sheetId) || {};
53306
- const record = {};
53307
- for (let cellId of Object.keys(rawCells)) {
53308
- const position = this.getters.getCellPosition(cellId);
53309
- record[cellId] = this.getEvaluatedCell(position);
53310
- }
53311
- return record;
53223
+ return this.evaluator
53224
+ .getEvaluatedPositionsInSheet(sheetId)
53225
+ .map((position) => this.getEvaluatedCell(position));
53226
+ }
53227
+ getEvaluatedCellsPositions(sheetId) {
53228
+ return this.evaluator.getEvaluatedPositionsInSheet(sheetId);
53312
53229
  }
53313
53230
  getEvaluatedCellsInZone(sheetId, zone) {
53314
53231
  return positions(zone).map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId, col, row }));
@@ -55976,7 +55893,10 @@ class Session extends EventBus {
55976
55893
  /**
55977
55894
  * Notify the server that the user client left the collaborative session
55978
55895
  */
55979
- leave() {
55896
+ leave(data) {
55897
+ if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
55898
+ this.snapshot(data);
55899
+ }
55980
55900
  delete this.clients[this.clientId];
55981
55901
  this.transportService.leave(this.clientId);
55982
55902
  this.transportService.sendMessage({
@@ -56390,7 +56310,7 @@ class DataCleanupPlugin extends UIPlugin {
56390
56310
  bottom: rowIndex,
56391
56311
  }));
56392
56312
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
56393
- const data = handler.copy(getClipboardDataPositions(rowsToKeep));
56313
+ const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep));
56394
56314
  if (!data) {
56395
56315
  return;
56396
56316
  }
@@ -56403,7 +56323,7 @@ class DataCleanupPlugin extends UIPlugin {
56403
56323
  right: zone.left,
56404
56324
  bottom: zone.top,
56405
56325
  };
56406
- handler.paste({ zones: [zonePasted] }, data, { isCutOperation: false });
56326
+ handler.paste({ zones: [zonePasted], sheetId }, data, { isCutOperation: false });
56407
56327
  const remainingZone = {
56408
56328
  left: zone.left,
56409
56329
  top: zone.top - (hasHeader ? 1 : 0),
@@ -58277,12 +58197,14 @@ class ClipboardPlugin extends UIPlugin {
58277
58197
  }
58278
58198
  let zone = undefined;
58279
58199
  let selectedZones = [];
58200
+ const sheetId = this.getters.getActiveSheetId();
58280
58201
  let target = {
58202
+ sheetId,
58281
58203
  zones,
58282
58204
  };
58283
58205
  const handlers = this.selectClipboardHandlers(copiedData);
58284
58206
  for (const handler of handlers) {
58285
- const currentTarget = handler.getPasteTarget(zones, copiedData, options);
58207
+ const currentTarget = handler.getPasteTarget(sheetId, zones, copiedData, options);
58286
58208
  if (currentTarget.figureId) {
58287
58209
  target.figureId = currentTarget.figureId;
58288
58210
  }
@@ -58451,11 +58373,12 @@ class ClipboardPlugin extends UIPlugin {
58451
58373
  return { cut: [cut], paste: [paste] };
58452
58374
  }
58453
58375
  getClipboardData(zones) {
58376
+ const sheetId = this.getters.getActiveSheetId();
58454
58377
  const selectedFigureId = this.getters.getSelectedFigureId();
58455
58378
  if (selectedFigureId) {
58456
- return { figureId: selectedFigureId };
58379
+ return { figureId: selectedFigureId, sheetId };
58457
58380
  }
58458
- return getClipboardDataPositions(zones);
58381
+ return getClipboardDataPositions(sheetId, zones);
58459
58382
  }
58460
58383
  // ---------------------------------------------------------------------------
58461
58384
  // Grid rendering
@@ -59121,8 +59044,9 @@ class GridSelectionPlugin extends UIPlugin {
59121
59044
  bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
59122
59045
  },
59123
59046
  ];
59047
+ const sheetId = this.getActiveSheetId();
59124
59048
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
59125
- const data = handler.copy(getClipboardDataPositions(target));
59049
+ const data = handler.copy(getClipboardDataPositions(sheetId, target));
59126
59050
  if (!data) {
59127
59051
  return;
59128
59052
  }
@@ -59135,7 +59059,7 @@ class GridSelectionPlugin extends UIPlugin {
59135
59059
  bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
59136
59060
  },
59137
59061
  ];
59138
- handler.paste({ zones: pasteTarget }, data, { isCutOperation: true });
59062
+ handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
59139
59063
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
59140
59064
  let currentIndex = cmd.base;
59141
59065
  for (const element of toRemove) {
@@ -66499,7 +66423,7 @@ class Model extends EventBus {
66499
66423
  this.session.join(this.config.client);
66500
66424
  }
66501
66425
  leaveSession() {
66502
- this.session.leave();
66426
+ this.session.leave(this.exportData());
66503
66427
  }
66504
66428
  setupUiPlugin(Plugin) {
66505
66429
  const plugin = new Plugin(this.uiPluginConfig);
@@ -66906,7 +66830,8 @@ const registries = {
66906
66830
  pivotRegistry,
66907
66831
  pivotTimeAdapterRegistry,
66908
66832
  pivotSidePanelRegistry,
66909
- supportedPivotExplodedFormulaRegistry,
66833
+ pivotNormalizationValueRegistry,
66834
+ supportedPivotPositionalFormulaRegistry,
66910
66835
  };
66911
66836
  const helpers = {
66912
66837
  arg,
@@ -66915,6 +66840,7 @@ const helpers = {
66915
66840
  toJsDate,
66916
66841
  toNumber,
66917
66842
  toString,
66843
+ toNormalizedPivotValue,
66918
66844
  toXC,
66919
66845
  toZone,
66920
66846
  toUnboundedZone,
@@ -67010,6 +66936,8 @@ const components = {
67010
66936
  PivotLayoutConfigurator,
67011
66937
  EditableName,
67012
66938
  PivotDeferUpdate,
66939
+ PivotTitleSection,
66940
+ CogWheelMenu,
67013
66941
  };
67014
66942
  const hooks = {
67015
66943
  useDragAndDropListItems,
@@ -67093,6 +67021,6 @@ exports.tokenColors = tokenColors;
67093
67021
  exports.tokenize = tokenize;
67094
67022
 
67095
67023
 
67096
- __info__.version = "17.4.0-alpha.3";
67097
- __info__.date = "2024-06-10T09:38:53.982Z";
67098
- __info__.hash = "a45ed6a";
67024
+ __info__.version = "17.4.0-alpha.4";
67025
+ __info__.date = "2024-06-12T14:00:22.046Z";
67026
+ __info__.hash = "cefb0e4";