@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
  import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, useState, onPatched, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
@@ -1826,22 +1826,28 @@ function isDateAfter(date, dateAfter) {
1826
1826
  */
1827
1827
  const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSeparator) {
1828
1828
  decimalSeparator = escapeRegExp(decimalSeparator);
1829
- return new RegExp(`(^-?\\d+(${decimalSeparator}?\\d*(e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1829
+ return new RegExp(`(?:^-?\\d+(?:${decimalSeparator}?\\d*(?:e\\d+)?)?|^-?${decimalSeparator}\\d+)(?!\\w|!)`);
1830
1830
  });
1831
1831
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1832
1832
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1833
1833
  const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1834
- const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1835
- const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1836
- const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
1837
- const pPercentFormat = "(\\s*%)?"; // pattern that match percent symbol between zero and one time
1838
- const pNumber = "(\\s*" + pIntegerAndDecimals + "|" + pOnlyDecimals + ")" + pScientificFormat + pPercentFormat;
1839
- const pMinus = "(\\s*-)?"; // pattern that match negative symbol between zero and one time
1840
- const pCurrencyFormat = "(\\s*[\\$€])?";
1834
+ const pIntegerAndDecimals = `(?:\\d+(?:${thousandsSeparator}\\d{3,})*(?:${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1835
+ const pOnlyDecimals = `(?:${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1836
+ const pScientificFormat = "(?:e(?:\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
1837
+ const pPercentFormat = "(?:\\s*%)?"; // pattern that match percent symbol between zero and one time
1838
+ const pNumber = "(?:\\s*" +
1839
+ pIntegerAndDecimals +
1840
+ "|" +
1841
+ pOnlyDecimals +
1842
+ ")" +
1843
+ pScientificFormat +
1844
+ pPercentFormat;
1845
+ const pMinus = "(?:\\s*-)?"; // pattern that match negative symbol between zero and one time
1846
+ const pCurrencyFormat = "(?:\\s*[\\$€])?";
1841
1847
  const p1 = pMinus + pCurrencyFormat + pNumber;
1842
1848
  const p2 = pMinus + pNumber + pCurrencyFormat;
1843
1849
  const p3 = pCurrencyFormat + pMinus + pNumber;
1844
- const pNumberExp = "^((" + [p1, p2, p3].join(")|(") + "))$";
1850
+ const pNumberExp = "^(?:(?:" + [p1, p2, p3].join(")|(?:") + "))$";
1845
1851
  const numberRegexp = new RegExp(pNumberExp, "i");
1846
1852
  return numberRegexp;
1847
1853
  });
@@ -2779,7 +2785,7 @@ function evaluatePredicate(value, criterion) {
2779
2785
  return false;
2780
2786
  }
2781
2787
  if (typeof operand === "number" && operator === "=") {
2782
- return toString(value) === toString(operand);
2788
+ return value.toString() === operand.toString();
2783
2789
  }
2784
2790
  if (operator === "<>" || operator === "=") {
2785
2791
  let result;
@@ -2839,14 +2845,13 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2839
2845
  if (countArg % 2 === 1) {
2840
2846
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range and criterion to be in pairs."));
2841
2847
  }
2842
- const dimRow = args[0].length;
2843
- const dimCol = args[0][0].length;
2848
+ const firstArg = toMatrix(args[0]);
2849
+ const dimRow = firstArg.length;
2850
+ const dimCol = firstArg[0].length;
2844
2851
  let predicates = [];
2845
2852
  for (let i = 0; i < countArg - 1; i += 2) {
2846
- const criteriaRange = args[i];
2847
- if (!isMatrix(criteriaRange) ||
2848
- criteriaRange.length !== dimRow ||
2849
- criteriaRange[0].length !== dimCol) {
2853
+ const criteriaRange = toMatrix(args[i]);
2854
+ if (criteriaRange.length !== dimRow || criteriaRange[0].length !== dimCol) {
2850
2855
  throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects criteria_range to have the same dimension"));
2851
2856
  }
2852
2857
  const description = toString(args[i + 1]);
@@ -2860,7 +2865,7 @@ function visitMatchingRanges(args, cb, locale, isQuery = false) {
2860
2865
  for (let j = 0; j < dimCol; j++) {
2861
2866
  let validatedPredicates = true;
2862
2867
  for (let k = 0; k < countArg - 1; k += 2) {
2863
- const criteriaValue = args[k][i][j].value;
2868
+ const criteriaValue = toMatrix(args[k])[i][j].value;
2864
2869
  const criterion = predicates[k / 2];
2865
2870
  validatedPredicates = evaluatePredicate(criteriaValue ?? undefined, criterion);
2866
2871
  if (!validatedPredicates) {
@@ -3525,10 +3530,8 @@ function detectDateFormat(content, locale) {
3525
3530
  const internalDate = parseDateTime(content, locale);
3526
3531
  return internalDate.format;
3527
3532
  }
3533
+ /** use this function only if the content corresponds to a number (means that isNumber(content) return true */
3528
3534
  function detectNumberFormat(content) {
3529
- if (!isNumber(content, DEFAULT_LOCALE)) {
3530
- return undefined;
3531
- }
3532
3535
  const digitBase = content.includes(".") ? "0.00" : "0";
3533
3536
  const matchedCurrencies = content.match(/[\$€]/);
3534
3537
  if (matchedCurrencies) {
@@ -4731,21 +4734,16 @@ function unionPositionsToZone(positions) {
4731
4734
  * Check if two zones are contiguous, ie. that they share a border
4732
4735
  */
4733
4736
  function areZoneContiguous(zone1, zone2) {
4734
- const u = union(zone1, zone2);
4735
4737
  if (zone1.right + 1 === zone2.left || zone1.left === zone2.right + 1) {
4736
- return getZoneHeight(u) <= getZoneHeight(zone1) + getZoneHeight(zone2);
4738
+ return ((zone1.top <= zone2.bottom && zone1.top >= zone2.top) ||
4739
+ (zone2.top <= zone1.bottom && zone2.top >= zone1.top));
4737
4740
  }
4738
4741
  if (zone1.bottom + 1 === zone2.top || zone1.top === zone2.bottom + 1) {
4739
- return getZoneWidth(u) <= getZoneWidth(zone1) + getZoneWidth(zone2);
4742
+ return ((zone1.left <= zone2.right && zone1.left >= zone2.left) ||
4743
+ (zone2.left <= zone1.right && zone2.left >= zone1.left));
4740
4744
  }
4741
4745
  return false;
4742
4746
  }
4743
- function getZoneHeight(zone) {
4744
- return zone.bottom - zone.top + 1;
4745
- }
4746
- function getZoneWidth(zone) {
4747
- return zone.right - zone.left + 1;
4748
- }
4749
4747
  /**
4750
4748
  * Merge contiguous and overlapping zones that are in the array into bigger zones
4751
4749
  */
@@ -5501,7 +5499,7 @@ class Registry {
5501
5499
  }
5502
5500
  }
5503
5501
 
5504
- function getClipboardDataPositions(zones) {
5502
+ function getClipboardDataPositions(sheetId, zones) {
5505
5503
  const lefts = new Set(zones.map((z) => z.left));
5506
5504
  const rights = new Set(zones.map((z) => z.right));
5507
5505
  const tops = new Set(zones.map((z) => z.top));
@@ -5515,7 +5513,7 @@ function getClipboardDataPositions(zones) {
5515
5513
  const cellsPosition = clippedZones.map((zone) => positions(zone)).flat();
5516
5514
  const columnsIndexes = [...new Set(cellsPosition.map((p) => p.col))].sort((a, b) => a - b);
5517
5515
  const rowsIndexes = [...new Set(cellsPosition.map((p) => p.row))].sort((a, b) => a - b);
5518
- return { zones, clippedZones, columnsIndexes, rowsIndexes };
5516
+ return { sheetId, zones, clippedZones, columnsIndexes, rowsIndexes };
5519
5517
  }
5520
5518
  /**
5521
5519
  * The clipped zone is copied as many times as it fits in the target.
@@ -5565,8 +5563,8 @@ class ClipboardHandler {
5565
5563
  isCutAllowed(data) {
5566
5564
  return "Success" /* CommandResult.Success */;
5567
5565
  }
5568
- getPasteTarget(target, content, options) {
5569
- return { zones: [] };
5566
+ getPasteTarget(sheetId, target, content, options) {
5567
+ return { zones: [], sheetId };
5570
5568
  }
5571
5569
  convertOSClipboardData(data) {
5572
5570
  return;
@@ -5604,7 +5602,7 @@ class AbstractCellClipboardHandler extends ClipboardHandler {
5604
5602
 
5605
5603
  class BorderClipboardHandler extends AbstractCellClipboardHandler {
5606
5604
  copy(data) {
5607
- const sheetId = this.getters.getActiveSheetId();
5605
+ const sheetId = data.sheetId;
5608
5606
  if (data.zones.length === 0) {
5609
5607
  return;
5610
5608
  }
@@ -5624,7 +5622,7 @@ class BorderClipboardHandler extends AbstractCellClipboardHandler {
5624
5622
  if (!content) {
5625
5623
  return;
5626
5624
  }
5627
- const sheetId = this.getters.getActiveSheetId();
5625
+ const sheetId = target.sheetId;
5628
5626
  if (options?.pasteOption === "asValue") {
5629
5627
  return;
5630
5628
  }
@@ -6154,7 +6152,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6154
6152
  if (!("zones" in data) || !data.zones.length) {
6155
6153
  return;
6156
6154
  }
6157
- const sheetId = this.getters.getActiveSheetId();
6155
+ const sheetId = data.sheetId;
6158
6156
  const zones = data.zones;
6159
6157
  if (!zones.length) {
6160
6158
  return {
@@ -6183,6 +6181,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6183
6181
  format: evaluatedCell.format,
6184
6182
  content,
6185
6183
  isFormula: false,
6184
+ parsedValue: evaluatedCell.value,
6186
6185
  };
6187
6186
  }
6188
6187
  cellsInRow.push({
@@ -6197,7 +6196,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6197
6196
  return {
6198
6197
  cells: clippedCells,
6199
6198
  zones: clippedZones,
6200
- sheetId: this.getters.getActiveSheetId(),
6199
+ sheetId: data.sheetId,
6201
6200
  };
6202
6201
  }
6203
6202
  isPasteAllowed(sheetId, target, content, clipboardOptions) {
@@ -6225,7 +6224,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6225
6224
  return;
6226
6225
  }
6227
6226
  const zones = target.zones;
6228
- const sheetId = this.getters.getActiveSheetId();
6227
+ const sheetId = target.sheetId;
6229
6228
  if (!options?.isCutOperation) {
6230
6229
  this.pasteFromCopy(sheetId, zones, content.cells, options);
6231
6230
  }
@@ -6233,11 +6232,12 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6233
6232
  this.pasteFromCut(sheetId, zones, content, options);
6234
6233
  }
6235
6234
  }
6236
- getPasteTarget(target, content, options) {
6235
+ getPasteTarget(sheetId, target, content, options) {
6237
6236
  const width = content.cells[0].length;
6238
6237
  const height = content.cells.length;
6239
6238
  if (options?.isCutOperation) {
6240
6239
  return {
6240
+ sheetId,
6241
6241
  zones: [
6242
6242
  {
6243
6243
  left: target[0].left,
@@ -6249,11 +6249,9 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
6249
6249
  };
6250
6250
  }
6251
6251
  if (width === 1 && height === 1) {
6252
- return { zones: [] };
6252
+ return { zones: [], sheetId };
6253
6253
  }
6254
- return {
6255
- zones: getPasteZones(target, content.cells),
6256
- };
6254
+ return { sheetId, zones: getPasteZones(target, content.cells) };
6257
6255
  }
6258
6256
  pasteFromCut(sheetId, target, content, options) {
6259
6257
  this.clearClippedZones(content);
@@ -6376,7 +6374,7 @@ class AbstractFigureClipboardHandler extends ClipboardHandler {
6376
6374
 
6377
6375
  class ChartClipboardHandler extends AbstractFigureClipboardHandler {
6378
6376
  copy(data) {
6379
- const sheetId = this.getters.getActiveSheetId();
6377
+ const sheetId = data.sheetId;
6380
6378
  const figure = this.getters.getFigure(sheetId, data.figureId);
6381
6379
  if (!figure) {
6382
6380
  throw new Error(`No figure for the given id: ${data.figureId}`);
@@ -6396,22 +6394,19 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
6396
6394
  copiedChart,
6397
6395
  };
6398
6396
  }
6399
- getPasteTarget(target, content, options) {
6397
+ getPasteTarget(sheetId, target, content, options) {
6400
6398
  if (!content?.copiedFigure || !content?.copiedChart) {
6401
- return { zones: [] };
6399
+ return { zones: [], sheetId };
6402
6400
  }
6403
6401
  const newId = new UuidGenerator().uuidv4();
6404
- return {
6405
- zones: [],
6406
- figureId: newId,
6407
- };
6402
+ return { zones: [], figureId: newId, sheetId };
6408
6403
  }
6409
6404
  paste(target, clippedContent, options) {
6410
6405
  if (!clippedContent?.copiedFigure || !clippedContent?.copiedChart || !target.figureId) {
6411
6406
  return;
6412
6407
  }
6413
6408
  const { zones, figureId } = target;
6414
- const sheetId = this.getters.getActiveSheetId();
6409
+ const sheetId = target.sheetId;
6415
6410
  const numCols = this.getters.getNumberCols(sheetId);
6416
6411
  const numRows = this.getters.getNumberRows(sheetId);
6417
6412
  const targetX = this.getters.getColDimensions(sheetId, zones[0].left).start;
@@ -6457,7 +6452,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6457
6452
  return;
6458
6453
  }
6459
6454
  const { rowsIndexes, columnsIndexes } = data;
6460
- const sheetId = this.getters.getActiveSheetId();
6455
+ const sheetId = data.sheetId;
6461
6456
  const cellPositions = rowsIndexes.map((row) => columnsIndexes.map((col) => ({ col, row, sheetId })));
6462
6457
  return {
6463
6458
  cellPositions,
@@ -6471,7 +6466,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
6471
6466
  return;
6472
6467
  }
6473
6468
  const zones = target.zones;
6474
- const sheetId = this.getters.getActiveSheetId();
6469
+ const sheetId = target.sheetId;
6475
6470
  if (!options?.isCutOperation) {
6476
6471
  this.pasteFromCopy(sheetId, zones, clippedContent.cellPositions);
6477
6472
  }
@@ -6552,7 +6547,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
6552
6547
  return;
6553
6548
  }
6554
6549
  const { rowsIndexes, columnsIndexes } = data;
6555
- const sheetId = this.getters.getActiveSheetId();
6550
+ const sheetId = data.sheetId;
6556
6551
  const cellPositions = rowsIndexes.map((row) => columnsIndexes.map((col) => ({ col, row, sheetId })));
6557
6552
  return {
6558
6553
  cellPositions,
@@ -6569,7 +6564,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
6569
6564
  return;
6570
6565
  }
6571
6566
  const zones = target.zones;
6572
- const sheetId = this.getters.getActiveSheetId();
6567
+ const sheetId = target.sheetId;
6573
6568
  if (!options?.isCutOperation) {
6574
6569
  this.pasteFromCopy(sheetId, zones, clippedContent.cellPositions);
6575
6570
  }
@@ -6648,7 +6643,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
6648
6643
 
6649
6644
  class ImageClipboardHandler extends AbstractFigureClipboardHandler {
6650
6645
  copy(data) {
6651
- const sheetId = this.getters.getActiveSheetId();
6646
+ const sheetId = data.sheetId;
6652
6647
  const figure = this.getters.getFigure(sheetId, data.figureId);
6653
6648
  if (!figure) {
6654
6649
  throw new Error(`No figure for the given id: ${data.figureId}`);
@@ -6666,15 +6661,12 @@ class ImageClipboardHandler extends AbstractFigureClipboardHandler {
6666
6661
  sheetId,
6667
6662
  };
6668
6663
  }
6669
- getPasteTarget(target, content, options) {
6664
+ getPasteTarget(sheetId, target, content, options) {
6670
6665
  if (!content?.copiedFigure || !content?.copiedImage) {
6671
- return { zones: [] };
6666
+ return { zones: [], sheetId };
6672
6667
  }
6673
6668
  const newId = new UuidGenerator().uuidv4();
6674
- return {
6675
- zones: [],
6676
- figureId: newId,
6677
- };
6669
+ return { sheetId, zones: [], figureId: newId };
6678
6670
  }
6679
6671
  paste(target, clippedContent, options) {
6680
6672
  if (!clippedContent?.copiedFigure || !clippedContent?.copiedImage || !target.figureId) {
@@ -6745,8 +6737,7 @@ class MergeClipboardHandler extends AbstractCellClipboardHandler {
6745
6737
  if (options?.isCutOperation || !("zones" in target) || !target.zones.length) {
6746
6738
  return;
6747
6739
  }
6748
- const sheetId = this.getters.getActiveSheetId();
6749
- this.pasteFromCopy(sheetId, target.zones, content.cells, options);
6740
+ this.pasteFromCopy(target.sheetId, target.zones, content.cells, options);
6750
6741
  }
6751
6742
  pasteZone(sheetId, col, row, cells) {
6752
6743
  for (const [r, rowCells] of cells.entries()) {
@@ -6806,7 +6797,7 @@ class SheetClipboardHandler extends AbstractCellClipboardHandler {
6806
6797
 
6807
6798
  class TableClipboardHandler extends AbstractCellClipboardHandler {
6808
6799
  copy(data) {
6809
- const sheetId = this.getters.getActiveSheetId();
6800
+ const sheetId = data.sheetId;
6810
6801
  const { rowsIndexes, columnsIndexes, zones } = data;
6811
6802
  if (!zones || !rowsIndexes.length || !columnsIndexes.length) {
6812
6803
  return { tableCells: [[]], sheetId };
@@ -6848,7 +6839,7 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
6848
6839
  }
6849
6840
  return {
6850
6841
  tableCells,
6851
- sheetId: this.getters.getActiveSheetId(),
6842
+ sheetId: data.sheetId,
6852
6843
  };
6853
6844
  }
6854
6845
  /**
@@ -6870,7 +6861,7 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
6870
6861
  return;
6871
6862
  }
6872
6863
  const zones = target.zones;
6873
- const sheetId = this.getters.getActiveSheetId();
6864
+ const sheetId = target.sheetId;
6874
6865
  if (!options?.isCutOperation) {
6875
6866
  this.pasteFromCopy(sheetId, zones, content.tableCells, options);
6876
6867
  }
@@ -7632,10 +7623,8 @@ function detectLink(value) {
7632
7623
  return undefined;
7633
7624
  }
7634
7625
 
7635
- function evaluateLiteral(content = "", localeFormat) {
7636
- const value = localeFormat.format === PLAIN_TEXT_FORMAT
7637
- ? content
7638
- : parseLiteral(content, localeFormat.locale);
7626
+ function evaluateLiteral(literalCell, localeFormat) {
7627
+ const value = localeFormat.format === PLAIN_TEXT_FORMAT ? literalCell.content : literalCell.parsedValue;
7639
7628
  const fPayload = { value, format: localeFormat.format };
7640
7629
  return createEvaluatedCell(fPayload, localeFormat.locale);
7641
7630
  }
@@ -7647,10 +7636,11 @@ function parseLiteral(content, locale) {
7647
7636
  return null;
7648
7637
  }
7649
7638
  if (isNumber(content, DEFAULT_LOCALE)) {
7650
- return toNumber(content, DEFAULT_LOCALE);
7639
+ return parseNumber(content, DEFAULT_LOCALE);
7651
7640
  }
7652
- if (isDateTime(content, locale)) {
7653
- return toNumber(content, locale);
7641
+ const internalDate = parseDateTime(content, locale);
7642
+ if (internalDate) {
7643
+ return internalDate.value;
7654
7644
  }
7655
7645
  if (isBoolean(content)) {
7656
7646
  return content.toUpperCase() === "TRUE" ? true : false;
@@ -7662,9 +7652,14 @@ function createEvaluatedCell(fPayload, locale = DEFAULT_LOCALE, cell) {
7662
7652
  if (!link) {
7663
7653
  return _createEvaluatedCell(fPayload, locale, cell);
7664
7654
  }
7655
+ const value = parseLiteral(link.label, locale);
7656
+ const format = fPayload.format ||
7657
+ (typeof value === "number"
7658
+ ? detectDateFormat(link.label, locale) || detectNumberFormat(link.label)
7659
+ : undefined);
7665
7660
  const linkPayload = {
7666
- value: parseLiteral(link.label, locale),
7667
- format: fPayload.format || detectDateFormat(link.label, locale) || detectNumberFormat(link.label),
7661
+ value,
7662
+ format,
7668
7663
  };
7669
7664
  return {
7670
7665
  ..._createEvaluatedCell(linkPayload, locale, cell),
@@ -10988,6 +10983,9 @@ function makeArg(str, description) {
10988
10983
  if (types.some((t) => t.startsWith("RANGE"))) {
10989
10984
  result.acceptMatrix = true;
10990
10985
  }
10986
+ if (types.every((t) => t.startsWith("RANGE"))) {
10987
+ result.acceptMatrixOnly = true;
10988
+ }
10991
10989
  return result;
10992
10990
  }
10993
10991
  /**
@@ -11242,7 +11240,6 @@ const ARRAY_CONSTRAIN = {
11242
11240
  arg("rows (number)", _t("The number of rows in the constrained array.")),
11243
11241
  arg("columns (number)", _t("The number of columns in the constrained array.")),
11244
11242
  ],
11245
- returns: ["RANGE<ANY>"],
11246
11243
  compute: function (array, rows, columns) {
11247
11244
  const _array = toMatrix(array);
11248
11245
  const _rowsArg = toInteger(rows?.value, this.locale);
@@ -11265,15 +11262,19 @@ const CHOOSECOLS = {
11265
11262
  arg("col_num (number, range<number>)", _t("The first column index of the columns to be returned.")),
11266
11263
  arg("col_num2 (number, range<number>, repeating)", _t("The columns indexes of the columns to be returned.")),
11267
11264
  ],
11268
- returns: ["RANGE<ANY>"],
11269
11265
  compute: function (array, ...columns) {
11270
11266
  const _array = toMatrix(array);
11271
11267
  const _columns = flattenRowFirst(columns, (item) => toInteger(item?.value, this.locale));
11272
- 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()));
11268
+ const argOutOfRange = _columns.filter((col) => col === 0 || _array.length < Math.abs(col));
11269
+ 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(",")));
11273
11270
  const result = Array(_columns.length);
11274
11271
  for (let col = 0; col < _columns.length; col++) {
11275
- const colIndex = _columns[col] - 1; // -1 because columns arguments are 1-indexed
11276
- result[col] = _array[colIndex];
11272
+ if (_columns[col] > 0) {
11273
+ result[col] = _array[_columns[col] - 1]; // -1 because columns arguments are 1-indexed
11274
+ }
11275
+ else {
11276
+ result[col] = _array[_array.length + _columns[col]];
11277
+ }
11277
11278
  }
11278
11279
  return result;
11279
11280
  },
@@ -11289,13 +11290,18 @@ const CHOOSEROWS = {
11289
11290
  arg("row_num (number, range<number>)", _t("The first row index of the rows to be returned.")),
11290
11291
  arg("row_num2 (number, range<number>, repeating)", _t("The rows indexes of the rows to be returned.")),
11291
11292
  ],
11292
- returns: ["RANGE<ANY>"],
11293
11293
  compute: function (array, ...rows) {
11294
11294
  const _array = toMatrix(array);
11295
11295
  const _rows = flattenRowFirst(rows, (item) => toInteger(item?.value, this.locale));
11296
11296
  const _nbColumns = _array.length;
11297
- 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()));
11298
- return generateMatrix(_nbColumns, _rows.length, (col, row) => _array[col][_rows[row] - 1]); // -1 because rows arguments are 1-indexed
11297
+ const argOutOfRange = _rows.filter((row) => row === 0 || _array[0].length < Math.abs(row));
11298
+ 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(",")));
11299
+ return generateMatrix(_nbColumns, _rows.length, (col, row) => {
11300
+ if (_rows[row] > 0) {
11301
+ return _array[col][_rows[row] - 1]; // -1 because columns arguments are 1-indexed
11302
+ }
11303
+ return _array[col][_array[col].length + _rows[row]];
11304
+ });
11299
11305
  },
11300
11306
  isExported: true,
11301
11307
  };
@@ -11310,7 +11316,6 @@ const EXPAND = {
11310
11316
  arg("columns (number, optional)", _t("The number of columns in the expanded array. If missing, columns will not be expanded.")),
11311
11317
  arg("pad_with (any, default=0)", _t("The value with which to pad.")), // @compatibility: on Excel, pad with #N/A
11312
11318
  ],
11313
- returns: ["RANGE<ANY>"],
11314
11319
  compute: function (arg, rows, columns, padWith = { value: 0 } // TODO : Replace with #N/A errors once it's supported
11315
11320
  ) {
11316
11321
  const _array = toMatrix(arg);
@@ -11331,7 +11336,6 @@ const FLATTEN = {
11331
11336
  arg("range (any, range<any>)", _t("The first range to flatten.")),
11332
11337
  arg("range2 (any, range<any>, repeating)", _t("Additional ranges to flatten.")),
11333
11338
  ],
11334
- returns: ["RANGE<ANY>"],
11335
11339
  compute: function (...ranges) {
11336
11340
  return [flattenRowFirst(ranges, (val) => (val === undefined ? { value: "" } : val))];
11337
11341
  },
@@ -11346,7 +11350,6 @@ const FREQUENCY = {
11346
11350
  arg("data (range<number>)", _t("The array of ranges containing the values to be counted.")),
11347
11351
  arg("classes (number, range<number>)", _t("The range containing the set of classes.")),
11348
11352
  ],
11349
- returns: ["RANGE<NUMBER>"],
11350
11353
  compute: function (data, classes) {
11351
11354
  const _data = flattenRowFirst([data], (data) => data.value).filter((val) => typeof val === "number");
11352
11355
  const _classes = flattenRowFirst([classes], (data) => data.value).filter((val) => typeof val === "number");
@@ -11394,7 +11397,6 @@ const HSTACK = {
11394
11397
  arg("range1 (any, range<any>)", _t("The first range to be appended.")),
11395
11398
  arg("range2 (any, range<any>, repeating)", _t("Additional ranges to add to range1.")),
11396
11399
  ],
11397
- returns: ["RANGE<ANY>"],
11398
11400
  compute: function (...ranges) {
11399
11401
  const nbRows = Math.max(...ranges.map((r) => r?.[0]?.length ?? 0));
11400
11402
  const result = [];
@@ -11421,7 +11423,6 @@ const MDETERM = {
11421
11423
  args: [
11422
11424
  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.")),
11423
11425
  ],
11424
- returns: ["NUMBER"],
11425
11426
  compute: function (matrix) {
11426
11427
  const _matrix = toNumberMatrix(matrix, "square_matrix");
11427
11428
  assertSquareMatrix(_t("The argument square_matrix must have the same number of columns and rows."), _matrix);
@@ -11437,7 +11438,6 @@ const MINVERSE = {
11437
11438
  args: [
11438
11439
  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.")),
11439
11440
  ],
11440
- returns: ["RANGE<NUMBER>"],
11441
11441
  compute: function (matrix) {
11442
11442
  const _matrix = toNumberMatrix(matrix, "square_matrix");
11443
11443
  assertSquareMatrix(_t("The argument square_matrix must have the same number of columns and rows."), _matrix);
@@ -11458,7 +11458,6 @@ const MMULT = {
11458
11458
  arg("matrix1 (number, range<number>)", _t("The first matrix in the matrix multiplication operation.")),
11459
11459
  arg("matrix2 (number, range<number>)", _t("The second matrix in the matrix multiplication operation.")),
11460
11460
  ],
11461
- returns: ["RANGE<NUMBER>"],
11462
11461
  compute: function (matrix1, matrix2) {
11463
11462
  const _matrix1 = toNumberMatrix(matrix1, "matrix1");
11464
11463
  const _matrix2 = toNumberMatrix(matrix2, "matrix2");
@@ -11477,7 +11476,6 @@ const SUMPRODUCT = {
11477
11476
  arg("range1 (number, range<number>)", _t("The first range whose entries will be multiplied with corresponding entries in the other ranges.")),
11478
11477
  arg("range2 (number, range<number>, repeating)", _t("The other range whose entries will be multiplied with corresponding entries in the other ranges.")),
11479
11478
  ],
11480
- returns: ["NUMBER"],
11481
11479
  compute: function (...args) {
11482
11480
  assertSameDimensions(_t("All the ranges must have the same dimensions."), ...args);
11483
11481
  const _args = args.map(toMatrix);
@@ -11534,7 +11532,6 @@ const SUMX2MY2 = {
11534
11532
  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.")),
11535
11533
  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.")),
11536
11534
  ],
11537
- returns: ["NUMBER"],
11538
11535
  compute: function (arrayX, arrayY) {
11539
11536
  return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 - y ** 2);
11540
11537
  },
@@ -11549,7 +11546,6 @@ const SUMX2PY2 = {
11549
11546
  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.")),
11550
11547
  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.")),
11551
11548
  ],
11552
- returns: ["NUMBER"],
11553
11549
  compute: function (arrayX, arrayY) {
11554
11550
  return getSumXAndY(arrayX, arrayY, (x, y) => x ** 2 + y ** 2);
11555
11551
  },
@@ -11564,7 +11560,6 @@ const SUMXMY2 = {
11564
11560
  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.")),
11565
11561
  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.")),
11566
11562
  ],
11567
- returns: ["NUMBER"],
11568
11563
  compute: function (arrayX, arrayY) {
11569
11564
  return getSumXAndY(arrayX, arrayY, (x, y) => (x - y) ** 2);
11570
11565
  },
@@ -11600,7 +11595,6 @@ function shouldKeepValue(ignore) {
11600
11595
  const TOCOL = {
11601
11596
  description: _t("Transforms a range of cells into a single column."),
11602
11597
  args: TO_COL_ROW_ARGS,
11603
- returns: ["RANGE<ANY>"],
11604
11598
  compute: function (array, ignore = { value: TO_COL_ROW_DEFAULT_IGNORE }, scanByColumn = { value: TO_COL_ROW_DEFAULT_SCAN }) {
11605
11599
  const _array = toMatrix(array);
11606
11600
  const _ignore = toNumber(ignore.value, this.locale);
@@ -11621,7 +11615,6 @@ const TOCOL = {
11621
11615
  const TOROW = {
11622
11616
  description: _t("Transforms a range of cells into a single row."),
11623
11617
  args: TO_COL_ROW_ARGS,
11624
- returns: ["RANGE<ANY>"],
11625
11618
  compute: function (array, ignore = { value: TO_COL_ROW_DEFAULT_IGNORE }, scanByColumn = { value: TO_COL_ROW_DEFAULT_SCAN }) {
11626
11619
  const _array = toMatrix(array);
11627
11620
  const _ignore = toNumber(ignore.value, this.locale);
@@ -11643,7 +11636,6 @@ const TOROW = {
11643
11636
  const TRANSPOSE = {
11644
11637
  description: _t("Transposes the rows and columns of a range."),
11645
11638
  args: [arg("range (any, range<any>)", _t("The range to be transposed."))],
11646
- returns: ["RANGE"],
11647
11639
  compute: function (arg) {
11648
11640
  const _array = toMatrix(arg);
11649
11641
  const nbColumns = _array[0].length;
@@ -11661,7 +11653,6 @@ const VSTACK = {
11661
11653
  arg("range1 (any, range<any>)", _t("The first range to be appended.")),
11662
11654
  arg("range2 (any, range<any>, repeating)", _t("Additional ranges to add to range1.")),
11663
11655
  ],
11664
- returns: ["RANGE<ANY>"],
11665
11656
  compute: function (...ranges) {
11666
11657
  const nbColumns = Math.max(...ranges.map((range) => toMatrix(range).length));
11667
11658
  const nbRows = ranges.reduce((acc, range) => acc + toMatrix(range)[0].length, 0);
@@ -11693,7 +11684,6 @@ const WRAPCOLS = {
11693
11684
  arg("pad_with (any, default=0)", // TODO : replace with #N/A
11694
11685
  _t("The value with which to fill the extra cells in the range.")),
11695
11686
  ],
11696
- returns: ["RANGE<ANY>"],
11697
11687
  compute: function (range, wrapCount, padWith = { value: 0 }) {
11698
11688
  const _array = toMatrix(range);
11699
11689
  const nbRows = toInteger(wrapCount?.value, this.locale);
@@ -11718,7 +11708,6 @@ const WRAPROWS = {
11718
11708
  arg("pad_with (any, default=0)", // TODO : replace with #N/A
11719
11709
  _t("The value with which to fill the extra cells in the range.")),
11720
11710
  ],
11721
- returns: ["RANGE<ANY>"],
11722
11711
  compute: function (range, wrapCount, padWith = { value: 0 }) {
11723
11712
  const _array = toMatrix(range);
11724
11713
  const nbColumns = toInteger(wrapCount?.value, this.locale);
@@ -11766,7 +11755,6 @@ const FORMAT_LARGE_NUMBER = {
11766
11755
  arg("value (number)", _t("The number.")),
11767
11756
  arg("unit (string, optional)", _t("The formatting unit. Use 'k', 'm', or 'b' to force the unit")),
11768
11757
  ],
11769
- returns: ["NUMBER"],
11770
11758
  compute: function (value, unite) {
11771
11759
  return {
11772
11760
  value: toNumber(value, this.locale),
@@ -11798,7 +11786,6 @@ const DECIMAL_REPRESENTATION = /^-?[a-z0-9]+$/i;
11798
11786
  const ABS = {
11799
11787
  description: _t("Absolute value of a number."),
11800
11788
  args: [arg("value (number)", _t("The number of which to return the absolute value."))],
11801
- returns: ["NUMBER"],
11802
11789
  compute: function (value) {
11803
11790
  return Math.abs(toNumber(value, this.locale));
11804
11791
  },
@@ -11812,7 +11799,6 @@ const ACOS = {
11812
11799
  args: [
11813
11800
  arg("value (number)", _t("The value for which to calculate the inverse cosine. Must be between -1 and 1, inclusive.")),
11814
11801
  ],
11815
- returns: ["NUMBER"],
11816
11802
  compute: function (value) {
11817
11803
  const _value = toNumber(value, this.locale);
11818
11804
  assert(() => Math.abs(_value) <= 1, _t("The value (%s) must be between -1 and 1 inclusive.", _value.toString()));
@@ -11828,7 +11814,6 @@ const ACOSH = {
11828
11814
  args: [
11829
11815
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic cosine. Must be greater than or equal to 1.")),
11830
11816
  ],
11831
- returns: ["NUMBER"],
11832
11817
  compute: function (value) {
11833
11818
  const _value = toNumber(value, this.locale);
11834
11819
  assert(() => _value >= 1, _t("The value (%s) must be greater than or equal to 1.", _value.toString()));
@@ -11842,7 +11827,6 @@ const ACOSH = {
11842
11827
  const ACOT = {
11843
11828
  description: _t("Inverse cotangent of a value."),
11844
11829
  args: [arg("value (number)", _t("The value for which to calculate the inverse cotangent."))],
11845
- returns: ["NUMBER"],
11846
11830
  compute: function (value) {
11847
11831
  const _value = toNumber(value, this.locale);
11848
11832
  const sign = Math.sign(_value) || 1;
@@ -11861,7 +11845,6 @@ const ACOTH = {
11861
11845
  args: [
11862
11846
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic cotangent. Must not be between -1 and 1, inclusive.")),
11863
11847
  ],
11864
- returns: ["NUMBER"],
11865
11848
  compute: function (value) {
11866
11849
  const _value = toNumber(value, this.locale);
11867
11850
  assert(() => Math.abs(_value) > 1, _t("The value (%s) cannot be between -1 and 1 inclusive.", _value.toString()));
@@ -11877,7 +11860,6 @@ const ASIN = {
11877
11860
  args: [
11878
11861
  arg("value (number)", _t("The value for which to calculate the inverse sine. Must be between -1 and 1, inclusive.")),
11879
11862
  ],
11880
- returns: ["NUMBER"],
11881
11863
  compute: function (value) {
11882
11864
  const _value = toNumber(value, this.locale);
11883
11865
  assert(() => Math.abs(_value) <= 1, _t("The value (%s) must be between -1 and 1 inclusive.", _value.toString()));
@@ -11893,7 +11875,6 @@ const ASINH = {
11893
11875
  args: [
11894
11876
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic sine.")),
11895
11877
  ],
11896
- returns: ["NUMBER"],
11897
11878
  compute: function (value) {
11898
11879
  return Math.asinh(toNumber(value, this.locale));
11899
11880
  },
@@ -11905,7 +11886,6 @@ const ASINH = {
11905
11886
  const ATAN = {
11906
11887
  description: _t("Inverse tangent of a value, in radians."),
11907
11888
  args: [arg("value (number)", _t("The value for which to calculate the inverse tangent."))],
11908
- returns: ["NUMBER"],
11909
11889
  compute: function (value) {
11910
11890
  return Math.atan(toNumber(value, this.locale));
11911
11891
  },
@@ -11920,7 +11900,6 @@ const ATAN2 = {
11920
11900
  arg("x (number)", _t("The x coordinate of the endpoint of the line segment for which to calculate the angle from the x-axis.")),
11921
11901
  arg("y (number)", _t("The y coordinate of the endpoint of the line segment for which to calculate the angle from the x-axis.")),
11922
11902
  ],
11923
- returns: ["NUMBER"],
11924
11903
  compute: function (x, y) {
11925
11904
  const _x = toNumber(x, this.locale);
11926
11905
  const _y = toNumber(y, this.locale);
@@ -11937,7 +11916,6 @@ const ATANH = {
11937
11916
  args: [
11938
11917
  arg("value (number)", _t("The value for which to calculate the inverse hyperbolic tangent. Must be between -1 and 1, exclusive.")),
11939
11918
  ],
11940
- returns: ["NUMBER"],
11941
11919
  compute: function (value) {
11942
11920
  const _value = toNumber(value, this.locale);
11943
11921
  assert(() => Math.abs(_value) < 1, _t("The value (%s) must be between -1 and 1 exclusive.", _value.toString()));
@@ -11954,7 +11932,6 @@ const CEILING = {
11954
11932
  arg("value (number)", _t("The value to round up to the nearest integer multiple of factor.")),
11955
11933
  arg(`factor (number, default=${DEFAULT_FACTOR})`, _t("The number to whose multiples value will be rounded.")),
11956
11934
  ],
11957
- returns: ["NUMBER"],
11958
11935
  compute: function (value, factor = { value: DEFAULT_FACTOR }) {
11959
11936
  const _value = toNumber(value, this.locale);
11960
11937
  const _factor = toNumber(factor, this.locale);
@@ -11989,7 +11966,6 @@ const CEILING_MATH = {
11989
11966
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded. The sign of significance will be ignored.")),
11990
11967
  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.")),
11991
11968
  ],
11992
- returns: ["NUMBER"],
11993
11969
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }, mode = { value: DEFAULT_MODE }) {
11994
11970
  const _significance = toNumber(significance, this.locale);
11995
11971
  const _number = toNumber(number, this.locale);
@@ -12010,7 +11986,6 @@ const CEILING_PRECISE = {
12010
11986
  arg("number (number)", _t("The value to round up to the nearest integer multiple of significance.")),
12011
11987
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded.")),
12012
11988
  ],
12013
- returns: ["NUMBER"],
12014
11989
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }) {
12015
11990
  const _significance = toNumber(significance, this.locale);
12016
11991
  const _number = toNumber(number, this.locale);
@@ -12027,7 +12002,6 @@ const CEILING_PRECISE = {
12027
12002
  const COS = {
12028
12003
  description: _t("Cosine of an angle provided in radians."),
12029
12004
  args: [arg("angle (number)", _t("The angle to find the cosine of, in radians."))],
12030
- returns: ["NUMBER"],
12031
12005
  compute: function (angle) {
12032
12006
  return Math.cos(toNumber(angle, this.locale));
12033
12007
  },
@@ -12039,7 +12013,6 @@ const COS = {
12039
12013
  const COSH = {
12040
12014
  description: _t("Hyperbolic cosine of any real number."),
12041
12015
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic cosine of."))],
12042
- returns: ["NUMBER"],
12043
12016
  compute: function (value) {
12044
12017
  return Math.cosh(toNumber(value, this.locale));
12045
12018
  },
@@ -12051,7 +12024,6 @@ const COSH = {
12051
12024
  const COT = {
12052
12025
  description: _t("Cotangent of an angle provided in radians."),
12053
12026
  args: [arg("angle (number)", _t("The angle to find the cotangent of, in radians."))],
12054
- returns: ["NUMBER"],
12055
12027
  compute: function (angle) {
12056
12028
  const _angle = toNumber(angle, this.locale);
12057
12029
  assertNotZero(_angle);
@@ -12065,7 +12037,6 @@ const COT = {
12065
12037
  const COTH = {
12066
12038
  description: _t("Hyperbolic cotangent of any real number."),
12067
12039
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic cotangent of."))],
12068
- returns: ["NUMBER"],
12069
12040
  compute: function (value) {
12070
12041
  const _value = toNumber(value, this.locale);
12071
12042
  assertNotZero(_value);
@@ -12082,7 +12053,6 @@ const COUNTBLANK = {
12082
12053
  arg("value1 (any, range)", _t("The first value or range in which to count the number of blanks.")),
12083
12054
  arg("value2 (any, range, repeating)", _t("Additional values or ranges in which to count the number of blanks.")),
12084
12055
  ],
12085
- returns: ["NUMBER"],
12086
12056
  compute: function (...args) {
12087
12057
  return reduceAny(args, (acc, a) => {
12088
12058
  if (a === undefined) {
@@ -12108,7 +12078,6 @@ const COUNTIF = {
12108
12078
  arg("range (range)", _t("The range that is tested against criterion.")),
12109
12079
  arg("criterion (string)", _t("The pattern or test to apply to range.")),
12110
12080
  ],
12111
- returns: ["NUMBER"],
12112
12081
  compute: function (...args) {
12113
12082
  let count = 0;
12114
12083
  visitMatchingRanges(args, (i, j) => {
@@ -12129,7 +12098,6 @@ const COUNTIFS = {
12129
12098
  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.")),
12130
12099
  arg("criterion2 (string, repeating)", _t("Additional criteria to check.")),
12131
12100
  ],
12132
- returns: ["NUMBER"],
12133
12101
  compute: function (...args) {
12134
12102
  let count = 0;
12135
12103
  visitMatchingRanges(args, (i, j) => {
@@ -12148,7 +12116,6 @@ const COUNTUNIQUE = {
12148
12116
  arg("value1 (any, range)", _t("The first value or range to consider for uniqueness.")),
12149
12117
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider for uniqueness.")),
12150
12118
  ],
12151
- returns: ["NUMBER"],
12152
12119
  compute: function (...args) {
12153
12120
  return countUnique(args);
12154
12121
  },
@@ -12165,7 +12132,6 @@ const COUNTUNIQUEIFS = {
12165
12132
  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.")),
12166
12133
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
12167
12134
  ],
12168
- returns: ["NUMBER"],
12169
12135
  compute: function (range, ...args) {
12170
12136
  let uniqueValues = new Set();
12171
12137
  visitMatchingRanges(args, (i, j) => {
@@ -12183,7 +12149,6 @@ const COUNTUNIQUEIFS = {
12183
12149
  const CSC = {
12184
12150
  description: _t("Cosecant of an angle provided in radians."),
12185
12151
  args: [arg("angle (number)", _t("The angle to find the cosecant of, in radians."))],
12186
- returns: ["NUMBER"],
12187
12152
  compute: function (angle) {
12188
12153
  const _angle = toNumber(angle, this.locale);
12189
12154
  assertNotZero(_angle);
@@ -12197,7 +12162,6 @@ const CSC = {
12197
12162
  const CSCH = {
12198
12163
  description: _t("Hyperbolic cosecant of any real number."),
12199
12164
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic cosecant of."))],
12200
- returns: ["NUMBER"],
12201
12165
  compute: function (value) {
12202
12166
  const _value = toNumber(value, this.locale);
12203
12167
  assertNotZero(_value);
@@ -12214,7 +12178,6 @@ const DECIMAL = {
12214
12178
  arg("value (string)", _t("The number to convert.")),
12215
12179
  arg("base (number)", _t("The base to convert the value from.")),
12216
12180
  ],
12217
- returns: ["NUMBER"],
12218
12181
  compute: function (value, base) {
12219
12182
  let _base = toNumber(base, this.locale);
12220
12183
  _base = Math.floor(_base);
@@ -12241,7 +12204,6 @@ const DECIMAL = {
12241
12204
  const DEGREES = {
12242
12205
  description: _t("Converts an angle value in radians to degrees."),
12243
12206
  args: [arg("angle (number)", _t("The angle to convert from radians to degrees."))],
12244
- returns: ["NUMBER"],
12245
12207
  compute: function (angle) {
12246
12208
  return (toNumber(angle, this.locale) * 180) / Math.PI;
12247
12209
  },
@@ -12253,7 +12215,6 @@ const DEGREES = {
12253
12215
  const EXP = {
12254
12216
  description: _t("Euler's number, e (~2.718) raised to a power."),
12255
12217
  args: [arg("value (number)", _t("The exponent to raise e."))],
12256
- returns: ["NUMBER"],
12257
12218
  compute: function (value) {
12258
12219
  return Math.exp(toNumber(value, this.locale));
12259
12220
  },
@@ -12268,7 +12229,6 @@ const FLOOR = {
12268
12229
  arg("value (number)", _t("The value to round down to the nearest integer multiple of factor.")),
12269
12230
  arg(`factor (number, default=${DEFAULT_FACTOR})`, _t("The number to whose multiples value will be rounded.")),
12270
12231
  ],
12271
- returns: ["NUMBER"],
12272
12232
  compute: function (value, factor = { value: DEFAULT_FACTOR }) {
12273
12233
  const _value = toNumber(value, this.locale);
12274
12234
  const _factor = toNumber(factor, this.locale);
@@ -12303,7 +12263,6 @@ const FLOOR_MATH = {
12303
12263
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded. The sign of significance will be ignored.")),
12304
12264
  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.")),
12305
12265
  ],
12306
- returns: ["NUMBER"],
12307
12266
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }, mode = { value: DEFAULT_MODE }) {
12308
12267
  const _significance = toNumber(significance, this.locale);
12309
12268
  const _number = toNumber(number, this.locale);
@@ -12324,7 +12283,6 @@ const FLOOR_PRECISE = {
12324
12283
  arg("number (number)", _t("The value to round down to the nearest integer multiple of significance.")),
12325
12284
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded.")),
12326
12285
  ],
12327
- returns: ["NUMBER"],
12328
12286
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }) {
12329
12287
  const _significance = toNumber(significance, this.locale);
12330
12288
  const _number = toNumber(number, this.locale);
@@ -12341,7 +12299,6 @@ const FLOOR_PRECISE = {
12341
12299
  const ISEVEN = {
12342
12300
  description: _t("Whether the provided value is even."),
12343
12301
  args: [arg("value (number)", _t("The value to be verified as even."))],
12344
- returns: ["BOOLEAN"],
12345
12302
  compute: function (value) {
12346
12303
  const _value = strictToNumber(value, this.locale);
12347
12304
  return Math.floor(Math.abs(_value)) & 1 ? false : true;
@@ -12357,7 +12314,6 @@ const ISO_CEILING = {
12357
12314
  arg("number (number)", _t("The value to round up to the nearest integer multiple of significance.")),
12358
12315
  arg(`significance (number, default=${DEFAULT_SIGNIFICANCE})`, _t("The number to whose multiples number will be rounded.")),
12359
12316
  ],
12360
- returns: ["NUMBER"],
12361
12317
  compute: function (number, significance = { value: DEFAULT_SIGNIFICANCE }) {
12362
12318
  const _number = toNumber(number, this.locale);
12363
12319
  const _significance = toNumber(significance, this.locale);
@@ -12374,7 +12330,6 @@ const ISO_CEILING = {
12374
12330
  const ISODD = {
12375
12331
  description: _t("Whether the provided value is even."),
12376
12332
  args: [arg("value (number)", _t("The value to be verified as even."))],
12377
- returns: ["BOOLEAN"],
12378
12333
  compute: function (value) {
12379
12334
  const _value = strictToNumber(value, this.locale);
12380
12335
  return Math.floor(Math.abs(_value)) & 1 ? true : false;
@@ -12387,7 +12342,6 @@ const ISODD = {
12387
12342
  const LN = {
12388
12343
  description: _t("The logarithm of a number, base e (euler's number)."),
12389
12344
  args: [arg("value (number)", _t("The value for which to calculate the logarithm, base e."))],
12390
- returns: ["NUMBER"],
12391
12345
  compute: function (value) {
12392
12346
  const _value = toNumber(value, this.locale);
12393
12347
  assert(() => _value > 0, _t("The value (%s) must be strictly positive.", _value.toString()));
@@ -12413,7 +12367,6 @@ const MOD = {
12413
12367
  arg("dividend (number)", _t("The number to be divided to find the remainder.")),
12414
12368
  arg("divisor (number)", _t("The number to divide by.")),
12415
12369
  ],
12416
- returns: ["NUMBER"],
12417
12370
  compute: function (dividend, divisor) {
12418
12371
  const _divisor = toNumber(divisor, this.locale);
12419
12372
  const _dividend = toNumber(dividend, this.locale);
@@ -12432,7 +12385,6 @@ const MUNIT = {
12432
12385
  args: [
12433
12386
  arg("dimension (number)", _t("An integer specifying the dimension size of the unit matrix. It must be positive.")),
12434
12387
  ],
12435
- returns: ["RANGE<NUMBER>"],
12436
12388
  compute: function (n) {
12437
12389
  const _n = toInteger(n, this.locale);
12438
12390
  assertPositive(_t("The argument dimension must be positive"), _n);
@@ -12446,7 +12398,6 @@ const MUNIT = {
12446
12398
  const ODD = {
12447
12399
  description: _t("Rounds a number up to the nearest odd integer."),
12448
12400
  args: [arg("value (number)", _t("The value to round to the next greatest odd number."))],
12449
- returns: ["NUMBER"],
12450
12401
  compute: function (value) {
12451
12402
  const _value = toNumber(value, this.locale);
12452
12403
  let temp = Math.ceil(Math.abs(_value));
@@ -12464,7 +12415,6 @@ const ODD = {
12464
12415
  const PI = {
12465
12416
  description: _t("The number pi."),
12466
12417
  args: [],
12467
- returns: ["NUMBER"],
12468
12418
  compute: function () {
12469
12419
  return Math.PI;
12470
12420
  },
@@ -12479,7 +12429,6 @@ const POWER = {
12479
12429
  arg("base (number)", _t("The number to raise to the exponent power.")),
12480
12430
  arg("exponent (number)", _t("The exponent to raise base to.")),
12481
12431
  ],
12482
- returns: ["NUMBER"],
12483
12432
  compute: function (base, exponent) {
12484
12433
  const _base = toNumber(base, this.locale);
12485
12434
  const _exponent = toNumber(exponent, this.locale);
@@ -12497,7 +12446,6 @@ const PRODUCT = {
12497
12446
  arg("factor1 (number, range<number>)", _t("The first number or range to calculate for the product.")),
12498
12447
  arg("factor2 (number, range<number>, repeating)", _t("More numbers or ranges to calculate for the product.")),
12499
12448
  ],
12500
- returns: ["NUMBER"],
12501
12449
  compute: function (...factors) {
12502
12450
  let count = 0;
12503
12451
  let acc = 1;
@@ -12534,7 +12482,6 @@ const PRODUCT = {
12534
12482
  const RAND = {
12535
12483
  description: _t("A random number between 0 inclusive and 1 exclusive."),
12536
12484
  args: [],
12537
- returns: ["NUMBER"],
12538
12485
  compute: function () {
12539
12486
  return Math.random();
12540
12487
  },
@@ -12552,7 +12499,6 @@ const RANDARRAY = {
12552
12499
  arg("max (number, default=1)", _t("The maximum number you would like returned.")),
12553
12500
  arg("whole_number (number, default=FALSE)", _t("Return a whole number or a decimal value.")),
12554
12501
  ],
12555
- returns: ["RANGE<NUMBER>"],
12556
12502
  compute: function (rows = { value: 1 }, columns = { value: 1 }, min = { value: 0 }, max = { value: 1 }, wholeNumber = { value: false }) {
12557
12503
  const _cols = toInteger(columns, this.locale);
12558
12504
  const _rows = toInteger(rows, this.locale);
@@ -12590,7 +12536,6 @@ const RANDBETWEEN = {
12590
12536
  arg("low (number)", _t("The low end of the random range.")),
12591
12537
  arg("high (number)", _t("The high end of the random range.")),
12592
12538
  ],
12593
- returns: ["NUMBER"],
12594
12539
  compute: function (low, high) {
12595
12540
  let _low = toNumber(low, this.locale);
12596
12541
  if (!Number.isInteger(_low)) {
@@ -12617,7 +12562,6 @@ const ROUND = {
12617
12562
  arg("value (number)", _t("The value to round to places number of places.")),
12618
12563
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of decimal places to which to round.")),
12619
12564
  ],
12620
- returns: ["NUMBER"],
12621
12565
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12622
12566
  const _value = toNumber(value, this.locale);
12623
12567
  let _places = toNumber(places, this.locale);
@@ -12648,7 +12592,6 @@ const ROUNDDOWN = {
12648
12592
  arg("value (number)", _t("The value to round to places number of places, always rounding down.")),
12649
12593
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of decimal places to which to round.")),
12650
12594
  ],
12651
- returns: ["NUMBER"],
12652
12595
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12653
12596
  const _value = toNumber(value, this.locale);
12654
12597
  let _places = toNumber(places, this.locale);
@@ -12679,7 +12622,6 @@ const ROUNDUP = {
12679
12622
  arg("value (number)", _t("The value to round to places number of places, always rounding up.")),
12680
12623
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of decimal places to which to round.")),
12681
12624
  ],
12682
- returns: ["NUMBER"],
12683
12625
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12684
12626
  const _value = toNumber(value, this.locale);
12685
12627
  let _places = toNumber(places, this.locale);
@@ -12707,7 +12649,6 @@ const ROUNDUP = {
12707
12649
  const SEC = {
12708
12650
  description: _t("Secant of an angle provided in radians."),
12709
12651
  args: [arg("angle (number)", _t("The angle to find the secant of, in radians."))],
12710
- returns: ["NUMBER"],
12711
12652
  compute: function (angle) {
12712
12653
  return 1 / Math.cos(toNumber(angle, this.locale));
12713
12654
  },
@@ -12719,7 +12660,6 @@ const SEC = {
12719
12660
  const SECH = {
12720
12661
  description: _t("Hyperbolic secant of any real number."),
12721
12662
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic secant of."))],
12722
- returns: ["NUMBER"],
12723
12663
  compute: function (value) {
12724
12664
  return 1 / Math.cosh(toNumber(value, this.locale));
12725
12665
  },
@@ -12731,7 +12671,6 @@ const SECH = {
12731
12671
  const SIN = {
12732
12672
  description: _t("Sine of an angle provided in radians."),
12733
12673
  args: [arg("angle (number)", _t("The angle to find the sine of, in radians."))],
12734
- returns: ["NUMBER"],
12735
12674
  compute: function (angle) {
12736
12675
  return Math.sin(toNumber(angle, this.locale));
12737
12676
  },
@@ -12743,7 +12682,6 @@ const SIN = {
12743
12682
  const SINH = {
12744
12683
  description: _t("Hyperbolic sine of any real number."),
12745
12684
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic sine of."))],
12746
- returns: ["NUMBER"],
12747
12685
  compute: function (value) {
12748
12686
  return Math.sinh(toNumber(value, this.locale));
12749
12687
  },
@@ -12755,7 +12693,6 @@ const SINH = {
12755
12693
  const SQRT = {
12756
12694
  description: _t("Positive square root of a positive number."),
12757
12695
  args: [arg("value (number)", _t("The number for which to calculate the positive square root."))],
12758
- returns: ["NUMBER"],
12759
12696
  compute: function (value) {
12760
12697
  const _value = toNumber(value, this.locale);
12761
12698
  assert(() => _value >= 0, _t("The value (%s) must be positive or null.", _value.toString()));
@@ -12772,7 +12709,6 @@ const SUM = {
12772
12709
  arg("value1 (number, range<number>)", _t("The first number or range to add together.")),
12773
12710
  arg("value2 (number, range<number>, repeating)", _t("Additional numbers or ranges to add to value1.")),
12774
12711
  ],
12775
- returns: ["NUMBER"],
12776
12712
  compute: function (...values) {
12777
12713
  const v1 = values[0];
12778
12714
  return {
@@ -12792,7 +12728,6 @@ const SUMIF = {
12792
12728
  arg("criterion (string)", _t("The pattern or test to apply to range.")),
12793
12729
  arg("sum_range (range, default=criteria_range)", _t("The range to be summed, if different from range.")),
12794
12730
  ],
12795
- returns: ["NUMBER"],
12796
12731
  compute: function (criteriaRange, criterion, sumRange) {
12797
12732
  if (sumRange === undefined) {
12798
12733
  sumRange = criteriaRange;
@@ -12820,7 +12755,6 @@ const SUMIFS = {
12820
12755
  arg("criteria_range2 (any, range, repeating)", _t("Additional ranges to check.")),
12821
12756
  arg("criterion2 (string, repeating)", _t("Additional criteria to check.")),
12822
12757
  ],
12823
- returns: ["NUMBER"],
12824
12758
  compute: function (sumRange, ...criters) {
12825
12759
  let sum = 0;
12826
12760
  visitMatchingRanges(criters, (i, j) => {
@@ -12839,7 +12773,6 @@ const SUMIFS = {
12839
12773
  const TAN = {
12840
12774
  description: _t("Tangent of an angle provided in radians."),
12841
12775
  args: [arg("angle (number)", _t("The angle to find the tangent of, in radians."))],
12842
- returns: ["NUMBER"],
12843
12776
  compute: function (angle) {
12844
12777
  return Math.tan(toNumber(angle, this.locale));
12845
12778
  },
@@ -12851,7 +12784,6 @@ const TAN = {
12851
12784
  const TANH = {
12852
12785
  description: _t("Hyperbolic tangent of any real number."),
12853
12786
  args: [arg("value (number)", _t("Any real value to calculate the hyperbolic tangent of."))],
12854
- returns: ["NUMBER"],
12855
12787
  compute: function (value) {
12856
12788
  return Math.tanh(toNumber(value, this.locale));
12857
12789
  },
@@ -12875,7 +12807,6 @@ const TRUNC = {
12875
12807
  arg("value (number)", _t("The value to be truncated.")),
12876
12808
  arg(`places (number, default=${DEFAULT_PLACES})`, _t("The number of significant digits to the right of the decimal point to retain.")),
12877
12809
  ],
12878
- returns: ["NUMBER"],
12879
12810
  compute: function (value, places = { value: DEFAULT_PLACES }) {
12880
12811
  const _value = toNumber(value, this.locale);
12881
12812
  const _places = toNumber(places, this.locale);
@@ -12889,7 +12820,6 @@ const TRUNC = {
12889
12820
  const INT = {
12890
12821
  description: _t("Rounds a number down to the nearest integer that is less than or equal to it."),
12891
12822
  args: [arg("value (number)", _t("The number to round down to the nearest integer."))],
12892
- returns: ["NUMBER"],
12893
12823
  compute: function (value) {
12894
12824
  return Math.floor(toNumber(value, this.locale));
12895
12825
  },
@@ -13248,7 +13178,6 @@ const AVEDEV = {
13248
13178
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
13249
13179
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
13250
13180
  ],
13251
- returns: ["NUMBER"],
13252
13181
  compute: function (...values) {
13253
13182
  let count = 0;
13254
13183
  const sum = reduceNumbers(values, (acc, a) => {
@@ -13270,7 +13199,6 @@ const AVERAGE = {
13270
13199
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the average value.")),
13271
13200
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the average value.")),
13272
13201
  ],
13273
- returns: ["NUMBER"],
13274
13202
  compute: function (...values) {
13275
13203
  return {
13276
13204
  value: average(values, this.locale),
@@ -13292,7 +13220,6 @@ const AVERAGE_WEIGHTED = {
13292
13220
  arg("additional_values (number, range<number>, repeating)", _t("Additional values to average.")),
13293
13221
  arg("additional_weights (number, range<number>, repeating)", _t("Additional weights.")),
13294
13222
  ],
13295
- returns: ["NUMBER"],
13296
13223
  compute: function (...args) {
13297
13224
  let sum = 0;
13298
13225
  let count = 0;
@@ -13340,7 +13267,6 @@ const AVERAGEA = {
13340
13267
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the average value.")),
13341
13268
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the average value.")),
13342
13269
  ],
13343
- returns: ["NUMBER"],
13344
13270
  compute: function (...args) {
13345
13271
  let count = 0;
13346
13272
  const sum = reduceNumbersTextAs0(args, (acc, a) => {
@@ -13365,7 +13291,6 @@ const AVERAGEIF = {
13365
13291
  arg("criterion (string)", _t("The pattern or test to apply to criteria_range.")),
13366
13292
  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.")),
13367
13293
  ],
13368
- returns: ["NUMBER"],
13369
13294
  compute: function (criteriaRange, criterion, averageRange) {
13370
13295
  const _averageRange = averageRange === undefined ? toMatrix(criteriaRange) : toMatrix(averageRange);
13371
13296
  let count = 0;
@@ -13394,7 +13319,6 @@ const AVERAGEIFS = {
13394
13319
  arg("criteria_range2 (any, range, repeating)", _t("Additional criteria_range and criterion to check.")),
13395
13320
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
13396
13321
  ],
13397
- returns: ["NUMBER"],
13398
13322
  compute: function (averageRange, ...args) {
13399
13323
  const _averageRange = toMatrix(averageRange);
13400
13324
  let count = 0;
@@ -13420,7 +13344,6 @@ const COUNT = {
13420
13344
  arg("value1 (number, range<number>)", _t("The first value or range to consider when counting.")),
13421
13345
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when counting.")),
13422
13346
  ],
13423
- returns: ["NUMBER"],
13424
13347
  compute: function (...values) {
13425
13348
  return countNumbers(values, this.locale);
13426
13349
  },
@@ -13435,7 +13358,6 @@ const COUNTA = {
13435
13358
  arg("value1 (any, range)", _t("The first value or range to consider when counting.")),
13436
13359
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider when counting.")),
13437
13360
  ],
13438
- returns: ["NUMBER"],
13439
13361
  compute: function (...values) {
13440
13362
  return countAny(values);
13441
13363
  },
@@ -13452,7 +13374,6 @@ const COVAR = {
13452
13374
  arg("data_y (any, range)", _t("The range representing the array or matrix of dependent data.")),
13453
13375
  arg("data_x (any, range)", _t("The range representing the array or matrix of independent data.")),
13454
13376
  ],
13455
- returns: ["NUMBER"],
13456
13377
  compute: function (dataY, dataX) {
13457
13378
  return covariance(dataY, dataX, false);
13458
13379
  },
@@ -13467,7 +13388,6 @@ const COVARIANCE_P = {
13467
13388
  arg("data_y (any, range)", _t("The range representing the array or matrix of dependent data.")),
13468
13389
  arg("data_x (any, range)", _t("The range representing the array or matrix of independent data.")),
13469
13390
  ],
13470
- returns: ["NUMBER"],
13471
13391
  compute: function (dataY, dataX) {
13472
13392
  return covariance(dataY, dataX, false);
13473
13393
  },
@@ -13482,7 +13402,6 @@ const COVARIANCE_S = {
13482
13402
  arg("data_y (any, range)", _t("The range representing the array or matrix of dependent data.")),
13483
13403
  arg("data_x (any, range)", _t("The range representing the array or matrix of independent data.")),
13484
13404
  ],
13485
- returns: ["NUMBER"],
13486
13405
  compute: function (dataY, dataX) {
13487
13406
  return covariance(dataY, dataX, true);
13488
13407
  },
@@ -13498,7 +13417,6 @@ const FORECAST = {
13498
13417
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
13499
13418
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13500
13419
  ],
13501
- returns: ["NUMBER"],
13502
13420
  compute: function (x, dataY, dataX) {
13503
13421
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13504
13422
  return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
@@ -13516,7 +13434,6 @@ const GROWTH = {
13516
13434
  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.")),
13517
13435
  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.")),
13518
13436
  ],
13519
- returns: ["NUMBER"],
13520
13437
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
13521
13438
  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)));
13522
13439
  },
@@ -13530,7 +13447,6 @@ const INTERCEPT = {
13530
13447
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
13531
13448
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13532
13449
  ],
13533
- returns: ["NUMBER"],
13534
13450
  compute: function (dataY, dataX) {
13535
13451
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13536
13452
  const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
@@ -13547,7 +13463,6 @@ const LARGE = {
13547
13463
  arg("data (any, range)", _t("Array or range containing the dataset to consider.")),
13548
13464
  arg("n (number)", _t("The rank from largest to smallest of the element to return.")),
13549
13465
  ],
13550
- returns: ["NUMBER"],
13551
13466
  compute: function (data, n) {
13552
13467
  const _n = Math.trunc(toNumber(n?.value, this.locale));
13553
13468
  let largests = [];
@@ -13582,7 +13497,6 @@ const LINEST = {
13582
13497
  arg("calculate_b (boolean, default=TRUE)", _t("A flag specifying wheter to compute the slope or not")),
13583
13498
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13584
13499
  ],
13585
- returns: ["NUMBER"],
13586
13500
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13587
13501
  return fullLinearRegression(toNumberMatrix(dataX, "the first argument (data_y)"), toNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
13588
13502
  },
@@ -13599,7 +13513,6 @@ const LOGEST = {
13599
13513
  arg("calculate_b (boolean, default=TRUE)", _t("A flag specifying wheter to compute the slope or not")),
13600
13514
  arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
13601
13515
  ],
13602
- returns: ["NUMBER"],
13603
13516
  compute: function (dataY, dataX = [[]], calculateB = { value: true }, verbose = { value: false }) {
13604
13517
  const coeffs = fullLinearRegression(toNumberMatrix(dataX, "the second argument (data_x)"), logM(toNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
13605
13518
  for (let i = 0; i < coeffs.length; i++) {
@@ -13618,7 +13531,6 @@ const MATTHEWS = {
13618
13531
  arg("data_x (range)", _t("The range representing the array or matrix of observed data.")),
13619
13532
  arg("data_y (range)", _t("The range representing the array or matrix of predicted data.")),
13620
13533
  ],
13621
- returns: ["NUMBER"],
13622
13534
  compute: function (dataX, dataY) {
13623
13535
  const flatX = dataX.flat();
13624
13536
  const flatY = dataY.flat();
@@ -13662,7 +13574,6 @@ const MAX = {
13662
13574
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the maximum value.")),
13663
13575
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the maximum value.")),
13664
13576
  ],
13665
- returns: ["NUMBER"],
13666
13577
  compute: function (...values) {
13667
13578
  return {
13668
13579
  value: max(values, this.locale),
@@ -13680,7 +13591,6 @@ const MAXA = {
13680
13591
  arg("value1 (any, range)", _t("The first value or range to consider when calculating the maximum value.")),
13681
13592
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider when calculating the maximum value.")),
13682
13593
  ],
13683
- returns: ["NUMBER"],
13684
13594
  compute: function (...args) {
13685
13595
  const maxa = reduceNumbersTextAs0(args, (acc, a) => {
13686
13596
  return Math.max(a, acc);
@@ -13701,7 +13611,6 @@ const MAXIFS = {
13701
13611
  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.")),
13702
13612
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
13703
13613
  ],
13704
- returns: ["NUMBER"],
13705
13614
  compute: function (range, ...args) {
13706
13615
  let result = -Infinity;
13707
13616
  visitMatchingRanges(args, (i, j) => {
@@ -13723,7 +13632,6 @@ const MEDIAN = {
13723
13632
  arg("value1 (any, range)", _t("The first value or range to consider when calculating the median value.")),
13724
13633
  arg("value2 (any, range, repeating)", _t("Additional values or ranges to consider when calculating the median value.")),
13725
13634
  ],
13726
- returns: ["NUMBER"],
13727
13635
  compute: function (...values) {
13728
13636
  let data = [];
13729
13637
  visitNumbers(values, (value) => {
@@ -13745,7 +13653,6 @@ const MIN = {
13745
13653
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the minimum value.")),
13746
13654
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the minimum value.")),
13747
13655
  ],
13748
- returns: ["NUMBER"],
13749
13656
  compute: function (...values) {
13750
13657
  return {
13751
13658
  value: min(values, this.locale),
@@ -13763,7 +13670,6 @@ const MINA = {
13763
13670
  arg("value1 (number, range<number>)", _t("The first value or range to consider when calculating the minimum value.")),
13764
13671
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when calculating the minimum value.")),
13765
13672
  ],
13766
- returns: ["NUMBER"],
13767
13673
  compute: function (...args) {
13768
13674
  const mina = reduceNumbersTextAs0(args, (acc, a) => {
13769
13675
  return Math.min(a, acc);
@@ -13784,7 +13690,6 @@ const MINIFS = {
13784
13690
  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.")),
13785
13691
  arg("criterion2 (string, repeating)", _t("The pattern or test to apply to criteria_range2.")),
13786
13692
  ],
13787
- returns: ["NUMBER"],
13788
13693
  compute: function (range, ...args) {
13789
13694
  let result = Infinity;
13790
13695
  visitMatchingRanges(args, (i, j) => {
@@ -13827,7 +13732,6 @@ const PEARSON = {
13827
13732
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
13828
13733
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
13829
13734
  ],
13830
- returns: ["NUMBER"],
13831
13735
  compute: function (dataY, dataX) {
13832
13736
  return pearson(dataY, dataX);
13833
13737
  },
@@ -13844,7 +13748,6 @@ const PERCENTILE = {
13844
13748
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13845
13749
  arg("percentile (number)", _t("The percentile whose value within data will be calculated and returned.")),
13846
13750
  ],
13847
- returns: ["NUMBER"],
13848
13751
  compute: function (data, percentile) {
13849
13752
  return PERCENTILE_INC.compute.bind(this)(data, percentile);
13850
13753
  },
@@ -13859,7 +13762,6 @@ const PERCENTILE_EXC = {
13859
13762
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13860
13763
  arg("percentile (number)", _t("The percentile, exclusive of 0 and 1, whose value within 'data' will be calculated and returned.")),
13861
13764
  ],
13862
- returns: ["NUMBER"],
13863
13765
  compute: function (data, percentile) {
13864
13766
  return {
13865
13767
  value: centile([data], percentile, false, this.locale),
@@ -13877,7 +13779,6 @@ const PERCENTILE_INC = {
13877
13779
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13878
13780
  arg("percentile (number)", _t("The percentile whose value within data will be calculated and returned.")),
13879
13781
  ],
13880
- returns: ["NUMBER"],
13881
13782
  compute: function (data, percentile) {
13882
13783
  return {
13883
13784
  value: centile([data], percentile, true, this.locale),
@@ -13897,7 +13798,6 @@ const POLYFIT_COEFFS = {
13897
13798
  arg("order (number)", _t("The order of the polynomial to fit the data, between 1 and 6.")),
13898
13799
  arg("intercept (boolean, default=TRUE)", _t("A flag specifying whether to compute the intercept or not.")),
13899
13800
  ],
13900
- returns: ["RANGE<NUMBER>"],
13901
13801
  compute: function (dataY, dataX, order, intercept = { value: true }) {
13902
13802
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
13903
13803
  return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
@@ -13916,7 +13816,6 @@ const POLYFIT_FORECAST = {
13916
13816
  arg("order (number)", _t("The order of the polynomial to fit the data, between 1 and 6.")),
13917
13817
  arg("intercept (boolean, default=TRUE)", _t("A flag specifying whether to compute the intercept or not.")),
13918
13818
  ],
13919
- returns: ["NUMBER"],
13920
13819
  compute: function (x, dataY, dataX, order, intercept = { value: true }) {
13921
13820
  const _order = toNumber(order, this.locale);
13922
13821
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
@@ -13934,7 +13833,6 @@ const QUARTILE = {
13934
13833
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13935
13834
  arg("quartile_number (number)", _t("Which quartile value to return.")),
13936
13835
  ],
13937
- returns: ["NUMBER"],
13938
13836
  compute: function (data, quartileNumber) {
13939
13837
  return QUARTILE_INC.compute.bind(this)(data, quartileNumber);
13940
13838
  },
@@ -13949,7 +13847,6 @@ const QUARTILE_EXC = {
13949
13847
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13950
13848
  arg("quartile_number (number)", _t("Which quartile value, exclusive of 0 and 4, to return.")),
13951
13849
  ],
13952
- returns: ["NUMBER"],
13953
13850
  compute: function (data, quartileNumber) {
13954
13851
  const _quartileNumber = Math.trunc(toNumber(quartileNumber, this.locale));
13955
13852
  const percent = { value: 0.25 * _quartileNumber };
@@ -13969,7 +13866,6 @@ const QUARTILE_INC = {
13969
13866
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
13970
13867
  arg("quartile_number (number)", _t("Which quartile value to return.")),
13971
13868
  ],
13972
- returns: ["NUMBER"],
13973
13869
  compute: function (data, quartileNumber) {
13974
13870
  const percent = { value: 0.25 * Math.trunc(toNumber(quartileNumber, this.locale)) };
13975
13871
  return {
@@ -13988,7 +13884,6 @@ const RANK = {
13988
13884
  arg("data (range)", _t("The range containing the dataset to consider.")),
13989
13885
  arg("is_ascending (boolean, default=FALSE)", _t("Whether to consider the values in data in descending or ascending order.")),
13990
13886
  ],
13991
- returns: ["ANY"],
13992
13887
  compute: function (value, data, isAscending = { value: false }) {
13993
13888
  const _isAscending = toBoolean(isAscending);
13994
13889
  const _value = toNumber(value, this.locale);
@@ -14024,7 +13919,6 @@ const RSQ = {
14024
13919
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14025
13920
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14026
13921
  ],
14027
- returns: ["NUMBER"],
14028
13922
  compute: function (dataY, dataX) {
14029
13923
  return Math.pow(pearson(dataX, dataY), 2.0);
14030
13924
  },
@@ -14039,7 +13933,6 @@ const SLOPE = {
14039
13933
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14040
13934
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14041
13935
  ],
14042
- returns: ["NUMBER"],
14043
13936
  compute: function (dataY, dataX) {
14044
13937
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
14045
13938
  const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
@@ -14056,7 +13949,6 @@ const SMALL = {
14056
13949
  arg("data (any, range)", _t("The array or range containing the dataset to consider.")),
14057
13950
  arg("n (number)", _t("The rank from smallest to largest of the element to return.")),
14058
13951
  ],
14059
- returns: ["NUMBER"],
14060
13952
  compute: function (data, n) {
14061
13953
  const _n = Math.trunc(toNumber(n?.value, this.locale));
14062
13954
  let largests = [];
@@ -14089,7 +13981,6 @@ const SPEARMAN = {
14089
13981
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14090
13982
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14091
13983
  ],
14092
- returns: ["NUMBER"],
14093
13984
  compute: function (dataX, dataY) {
14094
13985
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
14095
13986
  const n = flatDataX.length;
@@ -14116,7 +14007,6 @@ const STDEV = {
14116
14007
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14117
14008
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14118
14009
  ],
14119
- returns: ["NUMBER"],
14120
14010
  compute: function (...args) {
14121
14011
  return Math.sqrt(VAR.compute.bind(this)(...args));
14122
14012
  },
@@ -14131,7 +14021,6 @@ const STDEV_P = {
14131
14021
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14132
14022
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14133
14023
  ],
14134
- returns: ["NUMBER"],
14135
14024
  compute: function (...args) {
14136
14025
  return Math.sqrt(VAR_P.compute.bind(this)(...args));
14137
14026
  },
@@ -14146,7 +14035,6 @@ const STDEV_S = {
14146
14035
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14147
14036
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14148
14037
  ],
14149
- returns: ["NUMBER"],
14150
14038
  compute: function (...args) {
14151
14039
  return Math.sqrt(VAR_S.compute.bind(this)(...args));
14152
14040
  },
@@ -14161,7 +14049,6 @@ const STDEVA = {
14161
14049
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14162
14050
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14163
14051
  ],
14164
- returns: ["NUMBER"],
14165
14052
  compute: function (...args) {
14166
14053
  return Math.sqrt(VARA.compute.bind(this)(...args));
14167
14054
  },
@@ -14176,7 +14063,6 @@ const STDEVP = {
14176
14063
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14177
14064
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14178
14065
  ],
14179
- returns: ["NUMBER"],
14180
14066
  compute: function (...args) {
14181
14067
  return Math.sqrt(VARP.compute.bind(this)(...args));
14182
14068
  },
@@ -14191,7 +14077,6 @@ const STDEVPA = {
14191
14077
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14192
14078
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14193
14079
  ],
14194
- returns: ["NUMBER"],
14195
14080
  compute: function (...args) {
14196
14081
  return Math.sqrt(VARPA.compute.bind(this)(...args));
14197
14082
  },
@@ -14206,7 +14091,6 @@ const STEYX = {
14206
14091
  arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
14207
14092
  arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
14208
14093
  ],
14209
- returns: ["NUMBER"],
14210
14094
  compute: function (dataY, dataX) {
14211
14095
  const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
14212
14096
  const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
@@ -14225,7 +14109,6 @@ const TREND = {
14225
14109
  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.")),
14226
14110
  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.")),
14227
14111
  ],
14228
- returns: ["NUMBER"],
14229
14112
  compute: function (knownDataY, knownDataX = [[]], newDataX = [[]], b = { value: true }) {
14230
14113
  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));
14231
14114
  },
@@ -14239,7 +14122,6 @@ const VAR = {
14239
14122
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14240
14123
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14241
14124
  ],
14242
- returns: ["NUMBER"],
14243
14125
  compute: function (...args) {
14244
14126
  return variance(args, true, false, this.locale);
14245
14127
  },
@@ -14254,7 +14136,6 @@ const VAR_P = {
14254
14136
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14255
14137
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14256
14138
  ],
14257
- returns: ["NUMBER"],
14258
14139
  compute: function (...args) {
14259
14140
  return variance(args, false, false, this.locale);
14260
14141
  },
@@ -14269,7 +14150,6 @@ const VAR_S = {
14269
14150
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14270
14151
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14271
14152
  ],
14272
- returns: ["NUMBER"],
14273
14153
  compute: function (...args) {
14274
14154
  return variance(args, true, false, this.locale);
14275
14155
  },
@@ -14284,7 +14164,6 @@ const VARA = {
14284
14164
  arg("value1 (number, range<number>)", _t("The first value or range of the sample.")),
14285
14165
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the sample.")),
14286
14166
  ],
14287
- returns: ["NUMBER"],
14288
14167
  compute: function (...args) {
14289
14168
  return variance(args, true, true, this.locale);
14290
14169
  },
@@ -14299,7 +14178,6 @@ const VARP = {
14299
14178
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14300
14179
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14301
14180
  ],
14302
- returns: ["NUMBER"],
14303
14181
  compute: function (...args) {
14304
14182
  return variance(args, false, false, this.locale);
14305
14183
  },
@@ -14314,7 +14192,6 @@ const VARPA = {
14314
14192
  arg("value1 (number, range<number>)", _t("The first value or range of the population.")),
14315
14193
  arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to include in the population.")),
14316
14194
  ],
14317
- returns: ["NUMBER"],
14318
14195
  compute: function (...args) {
14319
14196
  return variance(args, false, true, this.locale);
14320
14197
  },
@@ -14480,7 +14357,6 @@ const databaseArgs = [
14480
14357
  const DAVERAGE = {
14481
14358
  description: _t("Average of a set of values from a table-like range."),
14482
14359
  args: databaseArgs,
14483
- returns: ["NUMBER"],
14484
14360
  compute: function (database, field, criteria) {
14485
14361
  const cells = getMatchingCells(database, field, criteria, this.locale);
14486
14362
  return AVERAGE.compute.bind(this)([cells]);
@@ -14493,7 +14369,6 @@ const DAVERAGE = {
14493
14369
  const DCOUNT = {
14494
14370
  description: _t("Counts values from a table-like range."),
14495
14371
  args: databaseArgs,
14496
- returns: ["NUMBER"],
14497
14372
  compute: function (database, field, criteria) {
14498
14373
  const cells = getMatchingCells(database, field, criteria, this.locale);
14499
14374
  return COUNT.compute.bind(this)([cells]);
@@ -14506,7 +14381,6 @@ const DCOUNT = {
14506
14381
  const DCOUNTA = {
14507
14382
  description: _t("Counts values and text from a table-like range."),
14508
14383
  args: databaseArgs,
14509
- returns: ["NUMBER"],
14510
14384
  compute: function (database, field, criteria) {
14511
14385
  const cells = getMatchingCells(database, field, criteria, this.locale);
14512
14386
  return COUNTA.compute.bind(this)([cells]);
@@ -14519,7 +14393,6 @@ const DCOUNTA = {
14519
14393
  const DGET = {
14520
14394
  description: _t("Single value from a table-like range."),
14521
14395
  args: databaseArgs,
14522
- returns: ["NUMBER"],
14523
14396
  compute: function (database, field, criteria) {
14524
14397
  const cells = getMatchingCells(database, field, criteria, this.locale);
14525
14398
  assert(() => cells.length === 1, _t("More than one match found in DGET evaluation."));
@@ -14533,7 +14406,6 @@ const DGET = {
14533
14406
  const DMAX = {
14534
14407
  description: _t("Maximum of values from a table-like range."),
14535
14408
  args: databaseArgs,
14536
- returns: ["NUMBER"],
14537
14409
  compute: function (database, field, criteria) {
14538
14410
  const cells = getMatchingCells(database, field, criteria, this.locale);
14539
14411
  return MAX.compute.bind(this)([cells]);
@@ -14546,7 +14418,6 @@ const DMAX = {
14546
14418
  const DMIN = {
14547
14419
  description: _t("Minimum of values from a table-like range."),
14548
14420
  args: databaseArgs,
14549
- returns: ["NUMBER"],
14550
14421
  compute: function (database, field, criteria) {
14551
14422
  const cells = getMatchingCells(database, field, criteria, this.locale);
14552
14423
  return MIN.compute.bind(this)([cells]);
@@ -14559,7 +14430,6 @@ const DMIN = {
14559
14430
  const DPRODUCT = {
14560
14431
  description: _t("Product of values from a table-like range."),
14561
14432
  args: databaseArgs,
14562
- returns: ["NUMBER"],
14563
14433
  compute: function (database, field, criteria) {
14564
14434
  const cells = getMatchingCells(database, field, criteria, this.locale);
14565
14435
  return PRODUCT.compute.bind(this)([cells]);
@@ -14572,7 +14442,6 @@ const DPRODUCT = {
14572
14442
  const DSTDEV = {
14573
14443
  description: _t("Standard deviation of population sample from table."),
14574
14444
  args: databaseArgs,
14575
- returns: ["NUMBER"],
14576
14445
  compute: function (database, field, criteria) {
14577
14446
  const cells = getMatchingCells(database, field, criteria, this.locale);
14578
14447
  return STDEV.compute.bind(this)([cells]);
@@ -14585,7 +14454,6 @@ const DSTDEV = {
14585
14454
  const DSTDEVP = {
14586
14455
  description: _t("Standard deviation of entire population from table."),
14587
14456
  args: databaseArgs,
14588
- returns: ["NUMBER"],
14589
14457
  compute: function (database, field, criteria) {
14590
14458
  const cells = getMatchingCells(database, field, criteria, this.locale);
14591
14459
  return STDEVP.compute.bind(this)([cells]);
@@ -14598,7 +14466,6 @@ const DSTDEVP = {
14598
14466
  const DSUM = {
14599
14467
  description: _t("Sum of values from a table-like range."),
14600
14468
  args: databaseArgs,
14601
- returns: ["NUMBER"],
14602
14469
  compute: function (database, field, criteria) {
14603
14470
  const cells = getMatchingCells(database, field, criteria, this.locale);
14604
14471
  return SUM.compute.bind(this)([cells]);
@@ -14611,7 +14478,6 @@ const DSUM = {
14611
14478
  const DVAR = {
14612
14479
  description: _t("Variance of population sample from table-like range."),
14613
14480
  args: databaseArgs,
14614
- returns: ["NUMBER"],
14615
14481
  compute: function (database, field, criteria) {
14616
14482
  const cells = getMatchingCells(database, field, criteria, this.locale);
14617
14483
  return VAR.compute.bind(this)([cells]);
@@ -14624,7 +14490,6 @@ const DVAR = {
14624
14490
  const DVARP = {
14625
14491
  description: _t("Variance of a population from a table-like range."),
14626
14492
  args: databaseArgs,
14627
- returns: ["NUMBER"],
14628
14493
  compute: function (database, field, criteria) {
14629
14494
  const cells = getMatchingCells(database, field, criteria, this.locale);
14630
14495
  return VARP.compute.bind(this)([cells]);
@@ -14669,7 +14534,6 @@ const DATE = {
14669
14534
  arg("month (number)", _t("The month component of the date.")),
14670
14535
  arg("day (number)", _t("The day component of the date.")),
14671
14536
  ],
14672
- returns: ["DATE"],
14673
14537
  compute: function (year, month, day) {
14674
14538
  let _year = Math.trunc(toNumber(year, this.locale));
14675
14539
  const _month = Math.trunc(toNumber(month, this.locale));
@@ -14700,7 +14564,6 @@ const DATEDIF = {
14700
14564
  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.")),
14701
14565
  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).')),
14702
14566
  ],
14703
- returns: ["NUMBER"],
14704
14567
  compute: function (startDate, endDate, unit) {
14705
14568
  const _unit = toString(unit).toUpperCase();
14706
14569
  assert(() => Object.values(TIME_UNIT).includes(_unit), expectStringSetError(Object.values(TIME_UNIT), toString(unit)));
@@ -14753,7 +14616,6 @@ const DATEDIF = {
14753
14616
  const DATEVALUE = {
14754
14617
  description: _t("Converts a date string to a date value."),
14755
14618
  args: [arg("date_string (string)", _t("The string representing the date."))],
14756
- returns: ["NUMBER"],
14757
14619
  compute: function (dateString) {
14758
14620
  const _dateString = toString(dateString);
14759
14621
  const internalDate = parseDateTime(_dateString, this.locale);
@@ -14768,7 +14630,6 @@ const DATEVALUE = {
14768
14630
  const DAY = {
14769
14631
  description: _t("Day of the month that a specific date falls on."),
14770
14632
  args: [arg("date (string)", _t("The date from which to extract the day."))],
14771
- returns: ["NUMBER"],
14772
14633
  compute: function (date) {
14773
14634
  return toJsDate(date, this.locale).getDate();
14774
14635
  },
@@ -14783,7 +14644,6 @@ const DAYS = {
14783
14644
  arg("end_date (date)", _t("The end of the date range.")),
14784
14645
  arg("start_date (date)", _t("The start of the date range.")),
14785
14646
  ],
14786
- returns: ["NUMBER"],
14787
14647
  compute: function (endDate, startDate) {
14788
14648
  const _endDate = toJsDate(endDate, this.locale);
14789
14649
  const _startDate = toJsDate(startDate, this.locale);
@@ -14803,7 +14663,6 @@ const DAYS360 = {
14803
14663
  arg("end_date (date)", _t("The end date to consider in the calculation.")),
14804
14664
  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")),
14805
14665
  ],
14806
- returns: ["NUMBER"],
14807
14666
  compute: function (startDate, endDate, method = { value: DEFAULT_DAY_COUNT_METHOD }) {
14808
14667
  const _startDate = Math.trunc(toNumber(startDate, this.locale));
14809
14668
  const _endDate = Math.trunc(toNumber(endDate, this.locale));
@@ -14822,7 +14681,6 @@ const EDATE = {
14822
14681
  arg("start_date (date)", _t("The date from which to calculate the result.")),
14823
14682
  arg("months (number)", _t("The number of months before (negative) or after (positive) 'start_date' to calculate.")),
14824
14683
  ],
14825
- returns: ["DATE"],
14826
14684
  compute: function (startDate, months) {
14827
14685
  const _startDate = toJsDate(startDate, this.locale);
14828
14686
  const _months = Math.trunc(toNumber(months, this.locale));
@@ -14843,7 +14701,6 @@ const EOMONTH = {
14843
14701
  arg("start_date (date)", _t("The date from which to calculate the result.")),
14844
14702
  arg("months (number)", _t("The number of months before (negative) or after (positive) 'start_date' to consider.")),
14845
14703
  ],
14846
- returns: ["DATE"],
14847
14704
  compute: function (startDate, months) {
14848
14705
  const _startDate = toJsDate(startDate, this.locale);
14849
14706
  const _months = Math.trunc(toNumber(months, this.locale));
@@ -14863,7 +14720,6 @@ const EOMONTH = {
14863
14720
  const HOUR = {
14864
14721
  description: _t("Hour component of a specific time."),
14865
14722
  args: [arg("time (date)", _t("The time from which to calculate the hour component."))],
14866
- returns: ["NUMBER"],
14867
14723
  compute: function (date) {
14868
14724
  return toJsDate(date, this.locale).getHours();
14869
14725
  },
@@ -14877,7 +14733,6 @@ const ISOWEEKNUM = {
14877
14733
  args: [
14878
14734
  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.")),
14879
14735
  ],
14880
- returns: ["NUMBER"],
14881
14736
  compute: function (date) {
14882
14737
  const _date = toJsDate(date, this.locale);
14883
14738
  const y = _date.getFullYear();
@@ -14949,7 +14804,6 @@ const ISOWEEKNUM = {
14949
14804
  const MINUTE = {
14950
14805
  description: _t("Minute component of a specific time."),
14951
14806
  args: [arg("time (date)", _t("The time from which to calculate the minute component."))],
14952
- returns: ["NUMBER"],
14953
14807
  compute: function (date) {
14954
14808
  return toJsDate(date, this.locale).getMinutes();
14955
14809
  },
@@ -14961,7 +14815,6 @@ const MINUTE = {
14961
14815
  const MONTH = {
14962
14816
  description: _t("Month of the year a specific date falls in"),
14963
14817
  args: [arg("date (date)", _t("The date from which to extract the month."))],
14964
- returns: ["NUMBER"],
14965
14818
  compute: function (date) {
14966
14819
  return toJsDate(date, this.locale).getMonth() + 1;
14967
14820
  },
@@ -14977,7 +14830,6 @@ const NETWORKDAYS = {
14977
14830
  arg("end_date (date)", _t("The end date of the period from which to calculate the number of net working days.")),
14978
14831
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the date serial numbers to consider holidays.")),
14979
14832
  ],
14980
- returns: ["NUMBER"],
14981
14833
  compute: function (startDate, endDate, holidays) {
14982
14834
  return NETWORKDAYS_INTL.compute.bind(this)(startDate, endDate, { value: 1 }, holidays);
14983
14835
  },
@@ -15058,7 +14910,6 @@ const NETWORKDAYS_INTL = {
15058
14910
  arg(`weekend (any, default=${DEFAULT_WEEKEND})`, _t("A number or string representing which days of the week are considered weekends.")),
15059
14911
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the dates to consider as holidays.")),
15060
14912
  ],
15061
- returns: ["NUMBER"],
15062
14913
  compute: function (startDate, endDate, weekend = { value: DEFAULT_WEEKEND }, holidays) {
15063
14914
  const _startDate = toJsDate(startDate, this.locale);
15064
14915
  const _endDate = toJsDate(endDate, this.locale);
@@ -15093,7 +14944,6 @@ const NETWORKDAYS_INTL = {
15093
14944
  const NOW = {
15094
14945
  description: _t("Current date and time as a date value."),
15095
14946
  args: [],
15096
- returns: ["DATE"],
15097
14947
  compute: function () {
15098
14948
  const today = DateTime.now();
15099
14949
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
@@ -15111,7 +14961,6 @@ const NOW = {
15111
14961
  const SECOND = {
15112
14962
  description: _t("Minute component of a specific time."),
15113
14963
  args: [arg("time (date)", _t("The time from which to calculate the second component."))],
15114
- returns: ["NUMBER"],
15115
14964
  compute: function (date) {
15116
14965
  return toJsDate(date, this.locale).getSeconds();
15117
14966
  },
@@ -15127,7 +14976,6 @@ const TIME = {
15127
14976
  arg("minute (number)", _t("The minute component of the time.")),
15128
14977
  arg("second (number)", _t("The second component of the time.")),
15129
14978
  ],
15130
- returns: ["DATE"],
15131
14979
  compute: function (hour, minute, second) {
15132
14980
  let _hour = Math.trunc(toNumber(hour, this.locale));
15133
14981
  let _minute = Math.trunc(toNumber(minute, this.locale));
@@ -15151,7 +14999,6 @@ const TIME = {
15151
14999
  const TIMEVALUE = {
15152
15000
  description: _t("Converts a time string into its serial number representation."),
15153
15001
  args: [arg("time_string (string)", _t("The string that holds the time representation."))],
15154
- returns: ["NUMBER"],
15155
15002
  compute: function (timeString) {
15156
15003
  const _timeString = toString(timeString);
15157
15004
  const internalDate = parseDateTime(_timeString, this.locale);
@@ -15167,7 +15014,6 @@ const TIMEVALUE = {
15167
15014
  const TODAY = {
15168
15015
  description: _t("Current date as a date value."),
15169
15016
  args: [],
15170
- returns: ["DATE"],
15171
15017
  compute: function () {
15172
15018
  const today = DateTime.now();
15173
15019
  const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
@@ -15187,7 +15033,6 @@ const WEEKDAY = {
15187
15033
  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.")),
15188
15034
  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.")),
15189
15035
  ],
15190
- returns: ["NUMBER"],
15191
15036
  compute: function (date, type = { value: DEFAULT_TYPE }) {
15192
15037
  const _date = toJsDate(date, this.locale);
15193
15038
  const _type = Math.round(toNumber(type, this.locale));
@@ -15210,7 +15055,6 @@ const WEEKNUM = {
15210
15055
  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.")),
15211
15056
  arg(`type (number, default=${DEFAULT_TYPE})`, _t("A number representing the day that a week starts on. Sunday = 1.")),
15212
15057
  ],
15213
- returns: ["NUMBER"],
15214
15058
  compute: function (date, type = { value: DEFAULT_TYPE }) {
15215
15059
  const _date = toJsDate(date, this.locale);
15216
15060
  const _type = Math.round(toNumber(type, this.locale));
@@ -15251,7 +15095,6 @@ const WORKDAY = {
15251
15095
  arg("num_days (number)", _t("The number of working days to advance from start_date. If negative, counts backwards.")),
15252
15096
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the dates to consider holidays.")),
15253
15097
  ],
15254
- returns: ["NUMBER"],
15255
15098
  compute: function (startDate, numDays, holidays = { value: null }) {
15256
15099
  return WORKDAY_INTL.compute.bind(this)(startDate, numDays, { value: 1 }, holidays);
15257
15100
  },
@@ -15268,7 +15111,6 @@ const WORKDAY_INTL = {
15268
15111
  arg(`weekend (any, default=${DEFAULT_WEEKEND})`, _t("A number or string representing which days of the week are considered weekends.")),
15269
15112
  arg("holidays (date, range<date>, optional)", _t("A range or array constant containing the dates to consider holidays.")),
15270
15113
  ],
15271
- returns: ["DATE"],
15272
15114
  compute: function (startDate, numDays, weekend = { value: DEFAULT_WEEKEND }, holidays) {
15273
15115
  let _startDate = toJsDate(startDate, this.locale);
15274
15116
  let _numDays = Math.trunc(toNumber(numDays, this.locale));
@@ -15308,7 +15150,6 @@ const WORKDAY_INTL = {
15308
15150
  const YEAR = {
15309
15151
  description: _t("Year specified by a given date."),
15310
15152
  args: [arg("date (date)", _t("The date from which to extract the year."))],
15311
- returns: ["NUMBER"],
15312
15153
  compute: function (date) {
15313
15154
  return toJsDate(date, this.locale).getFullYear();
15314
15155
  },
@@ -15325,7 +15166,6 @@ const YEARFRAC = {
15325
15166
  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.")),
15326
15167
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION$1})`, _t("An indicator of what day count method to use.")),
15327
15168
  ],
15328
- returns: ["NUMBER"],
15329
15169
  compute: function (startDate, endDate, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION$1 }) {
15330
15170
  let _startDate = Math.trunc(toNumber(startDate, this.locale));
15331
15171
  let _endDate = Math.trunc(toNumber(endDate, this.locale));
@@ -15342,7 +15182,6 @@ const YEARFRAC = {
15342
15182
  const MONTH_START = {
15343
15183
  description: _t("First day of the month preceding a date."),
15344
15184
  args: [arg("date (date)", _t("The date from which to calculate the result."))],
15345
- returns: ["DATE"],
15346
15185
  compute: function (date) {
15347
15186
  const _startDate = toJsDate(date, this.locale);
15348
15187
  const yStart = _startDate.getFullYear();
@@ -15360,7 +15199,6 @@ const MONTH_START = {
15360
15199
  const MONTH_END = {
15361
15200
  description: _t("Last day of the month following a date."),
15362
15201
  args: [arg("date (date)", _t("The date from which to calculate the result."))],
15363
- returns: ["DATE"],
15364
15202
  compute: function (date) {
15365
15203
  return EOMONTH.compute.bind(this)(date, { value: 0 });
15366
15204
  },
@@ -15371,7 +15209,6 @@ const MONTH_END = {
15371
15209
  const QUARTER = {
15372
15210
  description: _t("Quarter of the year a specific date falls in"),
15373
15211
  args: [arg("date (date)", _t("The date from which to extract the quarter."))],
15374
- returns: ["NUMBER"],
15375
15212
  compute: function (date) {
15376
15213
  return Math.ceil((toJsDate(date, this.locale).getMonth() + 1) / 3);
15377
15214
  },
@@ -15382,7 +15219,6 @@ const QUARTER = {
15382
15219
  const QUARTER_START = {
15383
15220
  description: _t("First day of the quarter of the year a specific date falls in."),
15384
15221
  args: [arg("date (date)", _t("The date from which to calculate the start of quarter."))],
15385
- returns: ["DATE"],
15386
15222
  compute: function (date) {
15387
15223
  const quarter = QUARTER.compute.bind(this)(date);
15388
15224
  const year = YEAR.compute.bind(this)(date);
@@ -15399,7 +15235,6 @@ const QUARTER_START = {
15399
15235
  const QUARTER_END = {
15400
15236
  description: _t("Last day of the quarter of the year a specific date falls in."),
15401
15237
  args: [arg("date (date)", _t("The date from which to calculate the end of quarter."))],
15402
- returns: ["DATE"],
15403
15238
  compute: function (date) {
15404
15239
  const quarter = QUARTER.compute.bind(this)(date);
15405
15240
  const year = YEAR.compute.bind(this)(date);
@@ -15416,7 +15251,6 @@ const QUARTER_END = {
15416
15251
  const YEAR_START = {
15417
15252
  description: _t("First day of the year a specific date falls in."),
15418
15253
  args: [arg("date (date)", _t("The date from which to calculate the start of the year."))],
15419
- returns: ["DATE"],
15420
15254
  compute: function (date) {
15421
15255
  const year = YEAR.compute.bind(this)(date);
15422
15256
  const jsDate = new DateTime(year, 0, 1);
@@ -15432,7 +15266,6 @@ const YEAR_START = {
15432
15266
  const YEAR_END = {
15433
15267
  description: _t("Last day of the year a specific date falls in."),
15434
15268
  args: [arg("date (date)", _t("The date from which to calculate the end of the year."))],
15435
- returns: ["DATE"],
15436
15269
  compute: function (date) {
15437
15270
  const year = YEAR.compute.bind(this)(date);
15438
15271
  const jsDate = new DateTime(year + 1, 0, 0);
@@ -15489,7 +15322,6 @@ const DELTA = {
15489
15322
  arg("number1 (number)", _t("The first number to compare.")),
15490
15323
  arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _t("The second number to compare.")),
15491
15324
  ],
15492
- returns: ["NUMBER"],
15493
15325
  compute: function (number1, number2 = { value: DEFAULT_DELTA_ARG }) {
15494
15326
  const _number1 = toNumber(number1, this.locale);
15495
15327
  const _number2 = toNumber(number2, this.locale);
@@ -15680,7 +15512,6 @@ const FILTER = {
15680
15512
  arg("condition1 (boolean, range<boolean>)", _t("A column or row containing true or false values corresponding to the first column or row of range.")),
15681
15513
  arg("condition2 (boolean, range<boolean>, repeating)", _t("Additional column or row containing true or false values.")),
15682
15514
  ],
15683
- returns: ["RANGE<ANY>"],
15684
15515
  compute: function (range, ...conditions) {
15685
15516
  let _array = toMatrix(range);
15686
15517
  const _conditionsMatrices = conditions.map((cond) => matrixMap(toMatrix(cond), (data) => data.value));
@@ -15714,7 +15545,6 @@ const SORT = {
15714
15545
  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.")),
15715
15546
  arg("is_ascending (boolean, repeating)", _t("TRUE or FALSE indicating whether to sort sort_column in ascending order. FALSE sorts in descending order.")),
15716
15547
  ],
15717
- returns: ["RANGE"],
15718
15548
  compute: function (range, ...sortingCriteria) {
15719
15549
  const _range = transposeMatrix(range);
15720
15550
  return transposeMatrix(sortMatrix(_range, this.locale, ...sortingCriteria));
@@ -15733,7 +15563,6 @@ const SORTN = {
15733
15563
  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.")),
15734
15564
  arg("is_ascending (boolean, repeating)", _t("TRUE or FALSE indicating whether to sort sort_column in ascending order. FALSE sorts in descending order.")),
15735
15565
  ],
15736
- returns: ["RANGE"],
15737
15566
  compute: function (range, n, displayTiesMode, ...sortingCriteria) {
15738
15567
  const _n = toNumber(n?.value ?? 1, this.locale);
15739
15568
  assert(() => _n >= 0, _t("Wrong value of 'n'. Expected a positive number. Got %s.", _n));
@@ -15801,7 +15630,6 @@ const UNIQUE = {
15801
15630
  arg("by_column (boolean, default=FALSE)", _t("Whether to filter the data by columns or by rows.")),
15802
15631
  arg("exactly_once (boolean, default=FALSE)", _t("Whether to return only entries with no duplicates.")),
15803
15632
  ],
15804
- returns: ["RANGE<NUMBER>"],
15805
15633
  compute: function (range = { value: "" }, byColumn, exactlyOnce) {
15806
15634
  if (!isMatrix(range)) {
15807
15635
  return [[range]];
@@ -16026,7 +15854,6 @@ const ACCRINTM = {
16026
15854
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
16027
15855
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16028
15856
  ],
16029
- returns: ["NUMBER"],
16030
15857
  compute: function (issue, maturity, rate, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16031
15858
  const start = Math.trunc(toNumber(issue, this.locale));
16032
15859
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -16057,7 +15884,6 @@ const AMORLINC = {
16057
15884
  arg("rate (number)", _t("The deprecation rate.")),
16058
15885
  arg("day_count_convention (number, optional)", _t("An indicator of what day count method to use.")),
16059
15886
  ],
16060
- returns: ["NUMBER"],
16061
15887
  compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16062
15888
  dayCountConvention = dayCountConvention || 0;
16063
15889
  const _cost = toNumber(cost, this.locale);
@@ -16106,7 +15932,6 @@ const AMORLINC = {
16106
15932
  const COUPDAYS = {
16107
15933
  description: _t("Days in coupon period containing settlement date."),
16108
15934
  args: COUPON_FUNCTION_ARGS,
16109
- returns: ["NUMBER"],
16110
15935
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16111
15936
  dayCountConvention = dayCountConvention || 0;
16112
15937
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16133,7 +15958,6 @@ const COUPDAYS = {
16133
15958
  const COUPDAYBS = {
16134
15959
  description: _t("Days from settlement until next coupon."),
16135
15960
  args: COUPON_FUNCTION_ARGS,
16136
- returns: ["NUMBER"],
16137
15961
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16138
15962
  dayCountConvention = dayCountConvention || 0;
16139
15963
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16190,7 +16014,6 @@ const COUPDAYBS = {
16190
16014
  const COUPDAYSNC = {
16191
16015
  description: _t("Days from settlement until next coupon."),
16192
16016
  args: COUPON_FUNCTION_ARGS,
16193
- returns: ["NUMBER"],
16194
16017
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16195
16018
  dayCountConvention = dayCountConvention || 0;
16196
16019
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16220,7 +16043,6 @@ const COUPDAYSNC = {
16220
16043
  const COUPNCD = {
16221
16044
  description: _t("Next coupon date after the settlement date."),
16222
16045
  args: COUPON_FUNCTION_ARGS,
16223
- returns: ["NUMBER"],
16224
16046
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16225
16047
  dayCountConvention = dayCountConvention || 0;
16226
16048
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16246,7 +16068,6 @@ const COUPNCD = {
16246
16068
  const COUPNUM = {
16247
16069
  description: _t("Number of coupons between settlement and maturity."),
16248
16070
  args: COUPON_FUNCTION_ARGS,
16249
- returns: ["NUMBER"],
16250
16071
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16251
16072
  dayCountConvention = dayCountConvention || 0;
16252
16073
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16273,7 +16094,6 @@ const COUPNUM = {
16273
16094
  const COUPPCD = {
16274
16095
  description: _t("Last coupon date prior to or on the settlement date."),
16275
16096
  args: COUPON_FUNCTION_ARGS,
16276
- returns: ["NUMBER"],
16277
16097
  compute: function (settlement, maturity, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16278
16098
  dayCountConvention = dayCountConvention || 0;
16279
16099
  const start = Math.trunc(toNumber(settlement, this.locale));
@@ -16306,7 +16126,6 @@ const CUMIPMT = {
16306
16126
  arg("last_period (number)", _t("The number of the payment period to end the cumulative calculation.")),
16307
16127
  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.")),
16308
16128
  ],
16309
- returns: ["NUMBER"],
16310
16129
  compute: function (rate, numberOfPeriods, presentValue, firstPeriod, lastPeriod, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16311
16130
  const first = toNumber(firstPeriod, this.locale);
16312
16131
  const last = toNumber(lastPeriod, this.locale);
@@ -16338,7 +16157,6 @@ const CUMPRINC = {
16338
16157
  arg("last_period (number)", _t("The number of the payment period to end the cumulative calculation.")),
16339
16158
  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.")),
16340
16159
  ],
16341
- returns: ["NUMBER"],
16342
16160
  compute: function (rate, numberOfPeriods, presentValue, firstPeriod, lastPeriod, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16343
16161
  const first = toNumber(firstPeriod, this.locale);
16344
16162
  const last = toNumber(lastPeriod, this.locale);
@@ -16369,7 +16187,6 @@ const DB = {
16369
16187
  arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
16370
16188
  arg("month (number, optional)", _t("The number of months in the first year of depreciation.")),
16371
16189
  ],
16372
- returns: ["NUMBER"],
16373
16190
  // to do: replace by dollar format
16374
16191
  compute: function (cost, salvage, life, period, ...args) {
16375
16192
  const _cost = toNumber(cost, this.locale);
@@ -16438,7 +16255,6 @@ const DDB = {
16438
16255
  arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
16439
16256
  arg(`factor (number, default=${DEFAULT_DDB_DEPRECIATION_FACTOR})`, _t("The factor by which depreciation decreases.")),
16440
16257
  ],
16441
- returns: ["NUMBER"],
16442
16258
  compute: function (cost, salvage, life, period, factor = { value: DEFAULT_DDB_DEPRECIATION_FACTOR }) {
16443
16259
  const _cost = toNumber(cost, this.locale);
16444
16260
  const _salvage = toNumber(salvage, this.locale);
@@ -16464,7 +16280,6 @@ const DISC = {
16464
16280
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
16465
16281
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16466
16282
  ],
16467
- returns: ["NUMBER"],
16468
16283
  compute: function (settlement, maturity, price, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16469
16284
  dayCountConvention = dayCountConvention || 0;
16470
16285
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -16500,7 +16315,6 @@ const DOLLARDE = {
16500
16315
  arg("fractional_price (number)", _t("The price quotation given using fractional decimal conventions.")),
16501
16316
  arg("unit (number)", _t("The units of the fraction, e.g. 8 for 1/8ths or 32 for 1/32nds.")),
16502
16317
  ],
16503
- returns: ["NUMBER"],
16504
16318
  compute: function (fractionalPrice, unit) {
16505
16319
  const price = toNumber(fractionalPrice, this.locale);
16506
16320
  const _unit = Math.trunc(toNumber(unit, this.locale));
@@ -16521,7 +16335,6 @@ const DOLLARFR = {
16521
16335
  arg("decimal_price (number)", _t("The price quotation given as a decimal value.")),
16522
16336
  arg("unit (number)", _t("The units of the desired fraction, e.g. 8 for 1/8ths or 32 for 1/32nds.")),
16523
16337
  ],
16524
- returns: ["NUMBER"],
16525
16338
  compute: function (decimalPrice, unit) {
16526
16339
  const price = toNumber(decimalPrice, this.locale);
16527
16340
  const _unit = Math.trunc(toNumber(unit, this.locale));
@@ -16546,7 +16359,6 @@ const DURATION = {
16546
16359
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
16547
16360
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16548
16361
  ],
16549
- returns: ["NUMBER"],
16550
16362
  compute: function (settlement, maturity, rate, securityYield, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16551
16363
  const start = Math.trunc(toNumber(settlement, this.locale));
16552
16364
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -16587,7 +16399,6 @@ const EFFECT = {
16587
16399
  arg("nominal_rate (number)", _t("The nominal interest rate per year.")),
16588
16400
  arg("periods_per_year (number)", _t("The number of compounding periods per year.")),
16589
16401
  ],
16590
- returns: ["NUMBER"],
16591
16402
  compute: function (nominal_rate, periods_per_year) {
16592
16403
  const nominal = toNumber(nominal_rate, this.locale);
16593
16404
  const periods = Math.trunc(toNumber(periods_per_year, this.locale));
@@ -16617,7 +16428,6 @@ const FV = {
16617
16428
  arg(`present_value (number, default=${DEFAULT_PRESENT_VALUE})`, _t("The current value of the annuity.")),
16618
16429
  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.")),
16619
16430
  ],
16620
- returns: ["NUMBER"],
16621
16431
  // to do: replace by dollar format
16622
16432
  compute: function (rate, numberOfPeriods, paymentAmount, presentValue = { value: DEFAULT_PRESENT_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16623
16433
  presentValue = presentValue || 0;
@@ -16643,7 +16453,6 @@ const FVSCHEDULE = {
16643
16453
  arg("principal (number)", _t("The amount of initial capital or value to compound against.")),
16644
16454
  arg("rate_schedule (number, range<number>)", _t("A series of interest rates to compound against the principal.")),
16645
16455
  ],
16646
- returns: ["NUMBER"],
16647
16456
  compute: function (principalAmount, rateSchedule) {
16648
16457
  const principal = toNumber(principalAmount, this.locale);
16649
16458
  return reduceAny([rateSchedule], (acc, rate) => acc * (1 + toNumber(rate, this.locale)), principal);
@@ -16662,7 +16471,6 @@ const INTRATE = {
16662
16471
  arg("redemption (number)", _t("The amount to be received at maturity.")),
16663
16472
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16664
16473
  ],
16665
- returns: ["NUMBER"],
16666
16474
  compute: function (settlement, maturity, investment, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16667
16475
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
16668
16476
  const _maturity = Math.trunc(toNumber(maturity, this.locale));
@@ -16701,7 +16509,6 @@ const IPMT = {
16701
16509
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
16702
16510
  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.")),
16703
16511
  ],
16704
- returns: ["NUMBER"],
16705
16512
  compute: function (rate, currentPeriod, numberOfPeriods, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16706
16513
  const r = toNumber(rate, this.locale);
16707
16514
  const period = toNumber(currentPeriod, this.locale);
@@ -16726,7 +16533,6 @@ const IRR = {
16726
16533
  arg("cashflow_amounts (number, range<number>)", _t("An array or range containing the income or payments associated with the investment.")),
16727
16534
  arg(`rate_guess (number, default=${DEFAULT_RATE_GUESS})`, _t("An estimate for what the internal rate of return will be.")),
16728
16535
  ],
16729
- returns: ["NUMBER"],
16730
16536
  compute: function (cashFlowAmounts, rateGuess = { value: DEFAULT_RATE_GUESS }) {
16731
16537
  const _rateGuess = toNumber(rateGuess, this.locale);
16732
16538
  assertRateGuessStrictlyGreaterThanMinusOne(_rateGuess);
@@ -16788,7 +16594,6 @@ const ISPMT = {
16788
16594
  arg("number_of_periods (number)", _t("The number of payments to be made.")),
16789
16595
  arg("present_value (number)", _t("The current value of the annuity.")),
16790
16596
  ],
16791
- returns: ["NUMBER"],
16792
16597
  compute: function (rate, currentPeriod, numberOfPeriods, presentValue) {
16793
16598
  const interestRate = toNumber(rate, this.locale);
16794
16599
  const period = toNumber(currentPeriod, this.locale);
@@ -16813,7 +16618,6 @@ const MDURATION = {
16813
16618
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
16814
16619
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
16815
16620
  ],
16816
- returns: ["NUMBER"],
16817
16621
  compute: function (settlement, maturity, rate, securityYield, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
16818
16622
  const duration = DURATION.compute.bind(this)(settlement, maturity, rate, securityYield, frequency, dayCountConvention);
16819
16623
  const y = toNumber(securityYield, this.locale);
@@ -16832,7 +16636,6 @@ const MIRR = {
16832
16636
  arg("financing_rate (number)", _t("The interest rate paid on funds invested.")),
16833
16637
  arg("reinvestment_return_rate (number)", _t("The return (as a percentage) earned on reinvestment of income received from the investment.")),
16834
16638
  ],
16835
- returns: ["NUMBER"],
16836
16639
  compute: function (cashflowAmount, financingRate, reinvestmentRate) {
16837
16640
  const fRate = toNumber(financingRate, this.locale);
16838
16641
  const rRate = toNumber(reinvestmentRate, this.locale);
@@ -16884,7 +16687,6 @@ const NOMINAL = {
16884
16687
  arg("effective_rate (number)", _t("The effective interest rate per year.")),
16885
16688
  arg("periods_per_year (number)", _t("The number of compounding periods per year.")),
16886
16689
  ],
16887
- returns: ["NUMBER"],
16888
16690
  compute: function (effective_rate, periods_per_year) {
16889
16691
  const effective = toNumber(effective_rate, this.locale);
16890
16692
  const periods = Math.trunc(toNumber(periods_per_year, this.locale));
@@ -16907,7 +16709,6 @@ const NPER = {
16907
16709
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
16908
16710
  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.")),
16909
16711
  ],
16910
- returns: ["NUMBER"],
16911
16712
  compute: function (rate, paymentAmount, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
16912
16713
  futureValue = futureValue || 0;
16913
16714
  endOrBeginning = endOrBeginning || 0;
@@ -16955,7 +16756,6 @@ const NPV = {
16955
16756
  arg("cashflow1 (number, range<number>)", _t("The first future cash flow.")),
16956
16757
  arg("cashflow2 (number, range<number>, repeating)", _t("Additional future cash flows.")),
16957
16758
  ],
16958
- returns: ["NUMBER"],
16959
16759
  // to do: replace by dollar format
16960
16760
  compute: function (discount, ...values) {
16961
16761
  const _discount = toNumber(discount, this.locale);
@@ -16977,7 +16777,6 @@ const PDURATION = {
16977
16777
  arg("present_value (number)", _t("The investment's current value.")),
16978
16778
  arg("future_value (number)", _t("The investment's desired future value.")),
16979
16779
  ],
16980
- returns: ["NUMBER"],
16981
16780
  compute: function (rate, presentValue, futureValue) {
16982
16781
  const _rate = toNumber(rate, this.locale);
16983
16782
  const _presentValue = toNumber(presentValue, this.locale);
@@ -17017,7 +16816,6 @@ const PMT = {
17017
16816
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
17018
16817
  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.")),
17019
16818
  ],
17020
- returns: ["NUMBER"],
17021
16819
  compute: function (rate, numberOfPeriods, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
17022
16820
  const n = toNumber(numberOfPeriods, this.locale);
17023
16821
  const r = toNumber(rate, this.locale);
@@ -17053,7 +16851,6 @@ const PPMT = {
17053
16851
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
17054
16852
  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.")),
17055
16853
  ],
17056
- returns: ["NUMBER"],
17057
16854
  compute: function (rate, currentPeriod, numberOfPeriods, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
17058
16855
  const n = toNumber(numberOfPeriods, this.locale);
17059
16856
  const r = toNumber(rate, this.locale);
@@ -17080,7 +16877,6 @@ const PV = {
17080
16877
  arg(`future_value (number, default=${DEFAULT_FUTURE_VALUE})`, _t("The future value remaining after the final payment has been made.")),
17081
16878
  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.")),
17082
16879
  ],
17083
- returns: ["NUMBER"],
17084
16880
  // to do: replace by dollar format
17085
16881
  compute: function (rate, numberOfPeriods, paymentAmount, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }) {
17086
16882
  futureValue = futureValue || 0;
@@ -17114,7 +16910,6 @@ const PRICE = {
17114
16910
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
17115
16911
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17116
16912
  ],
17117
- returns: ["NUMBER"],
17118
16913
  compute: function (settlement, maturity, rate, securityYield, redemption, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17119
16914
  dayCountConvention = dayCountConvention || 0;
17120
16915
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17162,7 +16957,6 @@ const PRICEDISC = {
17162
16957
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
17163
16958
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17164
16959
  ],
17165
- returns: ["NUMBER"],
17166
16960
  compute: function (settlement, maturity, discount, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17167
16961
  dayCountConvention = dayCountConvention || 0;
17168
16962
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17200,7 +16994,6 @@ const PRICEMAT = {
17200
16994
  arg("yield (number)", _t("The expected annual yield of the security.")),
17201
16995
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17202
16996
  ],
17203
- returns: ["NUMBER"],
17204
16997
  compute: function (settlement, maturity, issue, rate, securityYield, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17205
16998
  dayCountConvention = dayCountConvention || 0;
17206
16999
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17264,7 +17057,6 @@ const RATE = {
17264
17057
  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.")),
17265
17058
  arg(`rate_guess (number, default=${RATE_GUESS_DEFAULT})`, _t("An estimate for what the interest rate will be.")),
17266
17059
  ],
17267
- returns: ["NUMBER"],
17268
17060
  compute: function (numberOfPeriods, paymentPerPeriod, presentValue, futureValue = { value: DEFAULT_FUTURE_VALUE }, endOrBeginning = { value: DEFAULT_END_OR_BEGINNING }, rateGuess = { value: RATE_GUESS_DEFAULT }) {
17269
17061
  const n = toNumber(numberOfPeriods, this.locale);
17270
17062
  const payment = toNumber(paymentPerPeriod, this.locale);
@@ -17310,7 +17102,6 @@ const RECEIVED = {
17310
17102
  arg("discount (number)", _t("The discount rate of the security invested in.")),
17311
17103
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17312
17104
  ],
17313
- returns: ["NUMBER"],
17314
17105
  compute: function (settlement, maturity, investment, discount, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17315
17106
  dayCountConvention = dayCountConvention || 0;
17316
17107
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17348,7 +17139,6 @@ const RRI = {
17348
17139
  arg("present_value (number)", _t("The present value of the investment.")),
17349
17140
  arg("future_value (number)", _t("The future value of the investment.")),
17350
17141
  ],
17351
- returns: ["NUMBER"],
17352
17142
  compute: function (numberOfPeriods, presentValue, futureValue) {
17353
17143
  const n = toNumber(numberOfPeriods, this.locale);
17354
17144
  const pv = toNumber(presentValue, this.locale);
@@ -17373,7 +17163,6 @@ const SLN = {
17373
17163
  arg("salvage (number)", _t("The value of the asset at the end of depreciation.")),
17374
17164
  arg("life (number)", _t("The number of periods over which the asset is depreciated.")),
17375
17165
  ],
17376
- returns: ["NUMBER"],
17377
17166
  compute: function (cost, salvage, life) {
17378
17167
  const _cost = toNumber(cost, this.locale);
17379
17168
  const _salvage = toNumber(salvage, this.locale);
@@ -17398,7 +17187,6 @@ const SYD = {
17398
17187
  arg("life (number)", _t("The number of periods over which the asset is depreciated.")),
17399
17188
  arg("period (number)", _t("The single period within life for which to calculate depreciation.")),
17400
17189
  ],
17401
- returns: ["NUMBER"],
17402
17190
  compute: function (cost, salvage, life, period) {
17403
17191
  const _cost = toNumber(cost, this.locale);
17404
17192
  const _salvage = toNumber(salvage, this.locale);
@@ -17447,7 +17235,6 @@ const TBILLPRICE = {
17447
17235
  arg("maturity (date)", _t("The maturity or end date of the security, when it can be redeemed at face, or par value.")),
17448
17236
  arg("discount (number)", _t("The discount rate of the bill at time of purchase.")),
17449
17237
  ],
17450
- returns: ["NUMBER"],
17451
17238
  compute: function (settlement, maturity, discount) {
17452
17239
  const start = Math.trunc(toNumber(settlement, this.locale));
17453
17240
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -17470,7 +17257,6 @@ const TBILLEQ = {
17470
17257
  arg("maturity (date)", _t("The maturity or end date of the security, when it can be redeemed at face, or par value.")),
17471
17258
  arg("discount (number)", _t("The discount rate of the bill at time of purchase.")),
17472
17259
  ],
17473
- returns: ["NUMBER"],
17474
17260
  compute: function (settlement, maturity, discount) {
17475
17261
  const start = Math.trunc(toNumber(settlement, this.locale));
17476
17262
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -17528,7 +17314,6 @@ const TBILLYIELD = {
17528
17314
  arg("maturity (date)", _t("The maturity or end date of the security, when it can be redeemed at face, or par value.")),
17529
17315
  arg("price (number)", _t("The price at which the security is bought per 100 face value.")),
17530
17316
  ],
17531
- returns: ["NUMBER"],
17532
17317
  compute: function (settlement, maturity, price) {
17533
17318
  const start = Math.trunc(toNumber(settlement, this.locale));
17534
17319
  const end = Math.trunc(toNumber(maturity, this.locale));
@@ -17568,7 +17353,6 @@ const VDB = {
17568
17353
  arg(`factor (number, default=${DEFAULT_DDB_DEPRECIATION_FACTOR})`, _t("The number of months in the first year of depreciation.")),
17569
17354
  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.")),
17570
17355
  ],
17571
- returns: ["NUMBER"],
17572
17356
  compute: function (cost, salvage, life, startPeriod, endPeriod, factor = { value: DEFAULT_DDB_DEPRECIATION_FACTOR }, noSwitch = { value: DEFAULT_VDB_NO_SWITCH }) {
17573
17357
  factor = factor || 0;
17574
17358
  const _cost = toNumber(cost, this.locale);
@@ -17633,7 +17417,6 @@ const XIRR = {
17633
17417
  arg("cashflow_dates (range<number>)", _t("An range with dates corresponding to the cash flows in cashflow_amounts.")),
17634
17418
  arg(`rate_guess (number, default=${RATE_GUESS_DEFAULT})`, _t("An estimate for what the internal rate of return will be.")),
17635
17419
  ],
17636
- returns: ["NUMBER"],
17637
17420
  compute: function (cashflowAmounts, cashflowDates, rateGuess = { value: RATE_GUESS_DEFAULT }) {
17638
17421
  const guess = toNumber(rateGuess, this.locale);
17639
17422
  const _cashFlows = cashflowAmounts.flat().map((val) => toNumber(val, this.locale));
@@ -17704,7 +17487,6 @@ const XNPV = {
17704
17487
  arg("cashflow_amounts (number, range<number>)", _t("An range containing the income or payments associated with the investment.")),
17705
17488
  arg("cashflow_dates (number, range<number>)", _t("An range with dates corresponding to the cash flows in cashflow_amounts.")),
17706
17489
  ],
17707
- returns: ["NUMBER"],
17708
17490
  compute: function (discount, cashflowAmounts, cashflowDates) {
17709
17491
  const rate = toNumber(discount, this.locale);
17710
17492
  const _cashFlows = isMatrix(cashflowAmounts)
@@ -17771,7 +17553,6 @@ const YIELD = {
17771
17553
  arg("frequency (number)", _t("The number of interest or coupon payments per year (1, 2, or 4).")),
17772
17554
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17773
17555
  ],
17774
- returns: ["NUMBER"],
17775
17556
  compute: function (settlement, maturity, rate, price, redemption, frequency, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17776
17557
  dayCountConvention = dayCountConvention || 0;
17777
17558
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17846,7 +17627,6 @@ const YIELDDISC = {
17846
17627
  arg("redemption (number)", _t("The redemption amount per 100 face value, or par.")),
17847
17628
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17848
17629
  ],
17849
- returns: ["NUMBER"],
17850
17630
  compute: function (settlement, maturity, price, redemption, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17851
17631
  dayCountConvention = dayCountConvention || 0;
17852
17632
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17883,7 +17663,6 @@ const YIELDMAT = {
17883
17663
  arg("price (number)", _t("The price at which the security is bought.")),
17884
17664
  arg(`day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} )`, _t("An indicator of what day count method to use.")),
17885
17665
  ],
17886
- returns: ["NUMBER"],
17887
17666
  compute: function (settlement, maturity, issue, rate, price, dayCountConvention = { value: DEFAULT_DAY_COUNT_CONVENTION }) {
17888
17667
  dayCountConvention = dayCountConvention || 0;
17889
17668
  const _settlement = Math.trunc(toNumber(settlement, this.locale));
@@ -17970,7 +17749,6 @@ const CELL = {
17970
17749
  arg("info_type (string)", _t("The type of information requested. Can be one of %s", CELL_INFO_TYPES.join(", "))),
17971
17750
  arg("reference (meta)", _t("The reference to the cell.")),
17972
17751
  ],
17973
- returns: ["ANY"],
17974
17752
  compute: function (info, reference) {
17975
17753
  const _info = toString(info).toLowerCase();
17976
17754
  assert(() => CELL_INFO_TYPES.includes(_info), _t("The info_type should be one of %s.", CELL_INFO_TYPES.join(", ")));
@@ -18021,7 +17799,6 @@ const CELL = {
18021
17799
  const ISERR = {
18022
17800
  description: _t("Whether a value is an error other than #N/A."),
18023
17801
  args: [arg("value (any)", _t("The value to be verified as an error type."))],
18024
- returns: ["BOOLEAN"],
18025
17802
  compute: function (data) {
18026
17803
  const value = data?.value;
18027
17804
  return isEvaluationError(value) && value !== CellErrorType.NotAvailable;
@@ -18034,7 +17811,6 @@ const ISERR = {
18034
17811
  const ISERROR = {
18035
17812
  description: _t("Whether a value is an error."),
18036
17813
  args: [arg("value (any)", _t("The value to be verified as an error type."))],
18037
- returns: ["BOOLEAN"],
18038
17814
  compute: function (data) {
18039
17815
  const value = data?.value;
18040
17816
  return isEvaluationError(value);
@@ -18047,7 +17823,6 @@ const ISERROR = {
18047
17823
  const ISLOGICAL = {
18048
17824
  description: _t("Whether a value is `true` or `false`."),
18049
17825
  args: [arg("value (any)", _t("The value to be verified as a logical TRUE or FALSE."))],
18050
- returns: ["BOOLEAN"],
18051
17826
  compute: function (value) {
18052
17827
  return typeof value?.value === "boolean";
18053
17828
  },
@@ -18059,7 +17834,6 @@ const ISLOGICAL = {
18059
17834
  const ISNA = {
18060
17835
  description: _t("Whether a value is the error #N/A."),
18061
17836
  args: [arg("value (any)", _t("The value to be verified as an error type."))],
18062
- returns: ["BOOLEAN"],
18063
17837
  compute: function (data) {
18064
17838
  return data?.value === CellErrorType.NotAvailable;
18065
17839
  },
@@ -18071,7 +17845,6 @@ const ISNA = {
18071
17845
  const ISNONTEXT = {
18072
17846
  description: _t("Whether a value is non-textual."),
18073
17847
  args: [arg("value (any)", _t("The value to be checked."))],
18074
- returns: ["BOOLEAN"],
18075
17848
  compute: function (value) {
18076
17849
  return !ISTEXT.compute.bind(this)(value);
18077
17850
  },
@@ -18083,7 +17856,6 @@ const ISNONTEXT = {
18083
17856
  const ISNUMBER = {
18084
17857
  description: _t("Whether a value is a number."),
18085
17858
  args: [arg("value (any)", _t("The value to be verified as a number."))],
18086
- returns: ["BOOLEAN"],
18087
17859
  compute: function (value) {
18088
17860
  return typeof value?.value === "number";
18089
17861
  },
@@ -18095,7 +17867,6 @@ const ISNUMBER = {
18095
17867
  const ISTEXT = {
18096
17868
  description: _t("Whether a value is text."),
18097
17869
  args: [arg("value (any)", _t("The value to be verified as text."))],
18098
- returns: ["BOOLEAN"],
18099
17870
  compute: function (value) {
18100
17871
  return typeof value?.value === "string" && isEvaluationError(value?.value) === false;
18101
17872
  },
@@ -18107,7 +17878,6 @@ const ISTEXT = {
18107
17878
  const ISBLANK = {
18108
17879
  description: _t("Whether the referenced cell is empty"),
18109
17880
  args: [arg("value (any)", _t("Reference to the cell that will be checked for emptiness."))],
18110
- returns: ["BOOLEAN"],
18111
17881
  compute: function (value) {
18112
17882
  return value?.value === null;
18113
17883
  },
@@ -18119,7 +17889,6 @@ const ISBLANK = {
18119
17889
  const NA = {
18120
17890
  description: _t("Returns the error value #N/A."),
18121
17891
  args: [],
18122
- returns: ["BOOLEAN"],
18123
17892
  compute: function () {
18124
17893
  return { value: CellErrorType.NotAvailable };
18125
17894
  },
@@ -18176,7 +17945,6 @@ const AND = {
18176
17945
  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.")),
18177
17946
  arg("logical_expression2 (boolean, range<boolean>, repeating)", _t("More expressions that represent logical values.")),
18178
17947
  ],
18179
- returns: ["BOOLEAN"],
18180
17948
  compute: function (...logicalExpressions) {
18181
17949
  const { result, foundBoolean } = boolAnd(logicalExpressions);
18182
17950
  assert(() => foundBoolean, _t("[[FUNCTION_NAME]] has no valid input data."));
@@ -18190,7 +17958,6 @@ const AND = {
18190
17958
  const FALSE = {
18191
17959
  description: _t("Logical value `false`."),
18192
17960
  args: [],
18193
- returns: ["BOOLEAN"],
18194
17961
  compute: function () {
18195
17962
  return false;
18196
17963
  },
@@ -18206,7 +17973,6 @@ const IF = {
18206
17973
  arg("value_if_true (any)", _t("The value the function returns if logical_expression is TRUE.")),
18207
17974
  arg("value_if_false (any, default=FALSE)", _t("The value the function returns if logical_expression is FALSE.")),
18208
17975
  ],
18209
- returns: ["ANY"],
18210
17976
  compute: function (logicalExpression, valueIfTrue, valueIfFalse) {
18211
17977
  const result = toBoolean(logicalExpression?.value) ? valueIfTrue : valueIfFalse;
18212
17978
  if (result === undefined) {
@@ -18228,7 +17994,6 @@ const IFERROR = {
18228
17994
  arg("value (any)", _t("The value to return if value itself is not an error.")),
18229
17995
  arg(`value_if_error (any, default="empty")`, _t("The value the function returns if value is an error.")),
18230
17996
  ],
18231
- returns: ["ANY"],
18232
17997
  compute: function (value, valueIfError = { value: "" }) {
18233
17998
  const result = isEvaluationError(value?.value) ? valueIfError : value;
18234
17999
  if (result === undefined) {
@@ -18250,7 +18015,6 @@ const IFNA = {
18250
18015
  arg("value (any)", _t("The value to return if value itself is not #N/A an error.")),
18251
18016
  arg(`value_if_error (any, default="empty")`, _t("The value the function returns if value is an #N/A error.")),
18252
18017
  ],
18253
- returns: ["ANY"],
18254
18018
  compute: function (value, valueIfError = { value: "" }) {
18255
18019
  const result = value?.value === CellErrorType.NotAvailable ? valueIfError : value;
18256
18020
  if (result === undefined) {
@@ -18274,7 +18038,6 @@ const IFS = {
18274
18038
  arg("condition2 (boolean, repeating)", _t("Additional conditions to be evaluated if the previous ones are FALSE.")),
18275
18039
  arg("value2 (any, repeating)", _t("Additional values to be returned if their corresponding conditions are TRUE.")),
18276
18040
  ],
18277
- returns: ["ANY"],
18278
18041
  compute: function (...values) {
18279
18042
  assert(() => values.length % 2 === 0, _t("Wrong number of arguments. Expected an even number of arguments."));
18280
18043
  for (let n = 0; n < values.length - 1; n += 2) {
@@ -18301,7 +18064,6 @@ const NOT = {
18301
18064
  args: [
18302
18065
  arg("logical_expression (boolean)", _t("An expression or reference to a cell holding an expression that represents some logical value.")),
18303
18066
  ],
18304
- returns: ["BOOLEAN"],
18305
18067
  compute: function (logicalExpression) {
18306
18068
  return !toBoolean(logicalExpression);
18307
18069
  },
@@ -18316,7 +18078,6 @@ const OR = {
18316
18078
  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.")),
18317
18079
  arg("logical_expression2 (boolean, range<boolean>, repeating)", _t("More expressions that evaluate to logical values.")),
18318
18080
  ],
18319
- returns: ["BOOLEAN"],
18320
18081
  compute: function (...logicalExpressions) {
18321
18082
  const { result, foundBoolean } = boolOr(logicalExpressions);
18322
18083
  assert(() => foundBoolean, _t("[[FUNCTION_NAME]] has no valid input data."));
@@ -18330,7 +18091,6 @@ const OR = {
18330
18091
  const TRUE = {
18331
18092
  description: _t("Logical value `true`."),
18332
18093
  args: [],
18333
- returns: ["BOOLEAN"],
18334
18094
  compute: function () {
18335
18095
  return true;
18336
18096
  },
@@ -18345,7 +18105,6 @@ const XOR = {
18345
18105
  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.")),
18346
18106
  arg("logical_expression2 (boolean, range<boolean>, repeating)", _t("More expressions that evaluate to logical values.")),
18347
18107
  ],
18348
- returns: ["BOOLEAN"],
18349
18108
  compute: function (...logicalExpressions) {
18350
18109
  let foundBoolean = false;
18351
18110
  let acc = false;
@@ -18374,9 +18133,229 @@ var logical = /*#__PURE__*/Object.freeze({
18374
18133
  XOR: XOR
18375
18134
  });
18376
18135
 
18377
- //TODO This registry is only used to disable the support of exploded pivot for spreadsheet
18378
- const supportedPivotExplodedFormulaRegistry = new Registry();
18379
- supportedPivotExplodedFormulaRegistry.add("SPREADSHEET", false);
18136
+ const pivotTimeAdapterRegistry = new Registry();
18137
+ function pivotTimeAdapter(granularity) {
18138
+ return pivotTimeAdapterRegistry.get(granularity);
18139
+ }
18140
+ /**
18141
+ * The Time Adapter: Managing Time Periods for Pivot Functions
18142
+ *
18143
+ * Overview:
18144
+ * A time adapter is responsible for managing time periods associated with pivot functions.
18145
+ * Each type of period (day, week, month, quarter, etc.) has its own dedicated adapter.
18146
+ * The adapter's primary role is to normalize period values between spreadsheet functions,
18147
+ * and the pivot.
18148
+ * By normalizing the period value, it can be stored consistently in the pivot.
18149
+ *
18150
+ * Normalization Process:
18151
+ * When working with functions in the spreadsheet, the time adapter normalizes
18152
+ * the provided period to facilitate accurate lookup of values in the pivot.
18153
+ * For instance, if the spreadsheet function represents a day period as a number generated
18154
+ * by the DATE function (DATE(2023, 12, 25)), the time adapter will normalize it accordingly.
18155
+ *
18156
+ */
18157
+ /**
18158
+ * Normalized value: "12/25/2023"
18159
+ *
18160
+ * Note: Those two format are equivalent:
18161
+ * - "MM/dd/yyyy" (luxon format)
18162
+ * - "mm/dd/yyyy" (spreadsheet format)
18163
+ **/
18164
+ const dayAdapter = {
18165
+ normalizeFunctionValue(value) {
18166
+ const date = toNumber(value, DEFAULT_LOCALE);
18167
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/dd/yyyy" });
18168
+ },
18169
+ getFormat(locale) {
18170
+ return (locale ?? DEFAULT_LOCALE).dateFormat;
18171
+ },
18172
+ formatValue(normalizedValue, locale) {
18173
+ locale = locale ?? DEFAULT_LOCALE;
18174
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18175
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18176
+ },
18177
+ toCellValue(normalizedValue) {
18178
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18179
+ },
18180
+ };
18181
+ /**
18182
+ * normalizes day of month number
18183
+ */
18184
+ const dayOfMonthAdapter = {
18185
+ normalizeFunctionValue(value) {
18186
+ const day = toNumber(value, DEFAULT_LOCALE);
18187
+ if (day < 1 || day > 31) {
18188
+ throw new EvaluationError(_t("%s is not a valid day of month (it should be a number between 1 and 31)", day));
18189
+ }
18190
+ return day;
18191
+ },
18192
+ getFormat() {
18193
+ return "0";
18194
+ },
18195
+ formatValue(normalizedValue, locale) {
18196
+ locale = locale ?? DEFAULT_LOCALE;
18197
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18198
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18199
+ },
18200
+ toCellValue(normalizedValue) {
18201
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18202
+ },
18203
+ };
18204
+ /**
18205
+ * Normalized value: "2/2023" for week 2 of 2023
18206
+ */
18207
+ const weekAdapter = {
18208
+ normalizeFunctionValue(value) {
18209
+ const [week, year] = value.split("/");
18210
+ return `${Number(week)}/${Number(year)}`;
18211
+ },
18212
+ getFormat() {
18213
+ return undefined;
18214
+ },
18215
+ formatValue(normalizedValue) {
18216
+ const [week, year] = normalizedValue.split("/");
18217
+ return _t("W%(week)s %(year)s", { week, year });
18218
+ },
18219
+ toCellValue(normalizedValue) {
18220
+ return this.formatValue(normalizedValue);
18221
+ },
18222
+ };
18223
+ /**
18224
+ * normalizes iso week number
18225
+ */
18226
+ const isoWeekNumberAdapter = {
18227
+ normalizeFunctionValue(value) {
18228
+ const isoWeek = toNumber(value, DEFAULT_LOCALE);
18229
+ if (isoWeek < 0 || isoWeek > 53) {
18230
+ throw new EvaluationError(_t("%s is not a valid week (it should be a number between 0 and 53)", isoWeek));
18231
+ }
18232
+ return isoWeek;
18233
+ },
18234
+ getFormat() {
18235
+ return "0";
18236
+ },
18237
+ formatValue(normalizedValue, locale) {
18238
+ locale = locale ?? DEFAULT_LOCALE;
18239
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18240
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18241
+ },
18242
+ toCellValue(normalizedValue) {
18243
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18244
+ },
18245
+ };
18246
+ /**
18247
+ * normalized month value is a string formatted as "MM/yyyy" (luxon format)
18248
+ * e.g. "01/2020" for January 2020
18249
+ */
18250
+ const monthAdapter = {
18251
+ normalizeFunctionValue(value) {
18252
+ const date = toNumber(value, DEFAULT_LOCALE);
18253
+ return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
18254
+ },
18255
+ getFormat() {
18256
+ return "mmmm yyyy";
18257
+ },
18258
+ formatValue(normalizedValue, locale) {
18259
+ locale = locale ?? DEFAULT_LOCALE;
18260
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18261
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18262
+ },
18263
+ toCellValue(normalizedValue) {
18264
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18265
+ },
18266
+ };
18267
+ /**
18268
+ * normalizes month number
18269
+ */
18270
+ const monthNumberAdapter = {
18271
+ normalizeFunctionValue(value) {
18272
+ const month = toNumber(value, DEFAULT_LOCALE);
18273
+ if (month < 1 || month > 12) {
18274
+ throw new EvaluationError(_t("%s is not a valid month (it should be a number between 1 and 12)", month));
18275
+ }
18276
+ return month;
18277
+ },
18278
+ getFormat() {
18279
+ return "0";
18280
+ },
18281
+ formatValue(normalizedValue, locale) {
18282
+ locale = locale ?? DEFAULT_LOCALE;
18283
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18284
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18285
+ },
18286
+ toCellValue(normalizedValue) {
18287
+ return MONTHS[toNumber(normalizedValue, DEFAULT_LOCALE) - 1].toString();
18288
+ },
18289
+ };
18290
+ /**
18291
+ * normalized quarter value is "quarter/year"
18292
+ * e.g. "1/2020" for Q1 2020
18293
+ */
18294
+ const quarterAdapter = {
18295
+ normalizeFunctionValue(value) {
18296
+ const [quarter, year] = value.split("/");
18297
+ return `${quarter}/${year}`;
18298
+ },
18299
+ getFormat() {
18300
+ return undefined;
18301
+ },
18302
+ formatValue(normalizedValue) {
18303
+ const [quarter, year] = normalizedValue.split("/");
18304
+ return _t("Q%(quarter)s %(year)s", { quarter, year });
18305
+ },
18306
+ toCellValue(normalizedValue) {
18307
+ return this.formatValue(normalizedValue);
18308
+ },
18309
+ };
18310
+ /**
18311
+ * normalizes quarter number
18312
+ */
18313
+ const quarterNumberAdapter = {
18314
+ normalizeFunctionValue(value) {
18315
+ const quarter = toNumber(value, DEFAULT_LOCALE);
18316
+ if (quarter < 1 || quarter > 4) {
18317
+ throw new EvaluationError(_t("%s is not a valid quarter (it should be a number between 1 and 4)", quarter));
18318
+ }
18319
+ return quarter;
18320
+ },
18321
+ getFormat() {
18322
+ return "0";
18323
+ },
18324
+ formatValue(normalizedValue, locale) {
18325
+ locale = locale ?? DEFAULT_LOCALE;
18326
+ const value = toNumber(normalizedValue, DEFAULT_LOCALE);
18327
+ return formatValue(value, { locale, format: this.getFormat(locale) });
18328
+ },
18329
+ toCellValue(normalizedValue) {
18330
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18331
+ },
18332
+ };
18333
+ const yearAdapter = {
18334
+ normalizeFunctionValue(value) {
18335
+ return toNumber(value, DEFAULT_LOCALE);
18336
+ },
18337
+ getFormat() {
18338
+ return "0";
18339
+ },
18340
+ formatValue(normalizedValue, locale) {
18341
+ locale = locale ?? DEFAULT_LOCALE;
18342
+ return formatValue(normalizedValue, { locale, format: "0" });
18343
+ },
18344
+ toCellValue(normalizedValue) {
18345
+ return toNumber(normalizedValue, DEFAULT_LOCALE);
18346
+ },
18347
+ };
18348
+ pivotTimeAdapterRegistry
18349
+ .add("day", dayAdapter)
18350
+ .add("week", weekAdapter)
18351
+ .add("month", monthAdapter)
18352
+ .add("quarter", quarterAdapter)
18353
+ .add("year", yearAdapter)
18354
+ .add("day_of_month", dayOfMonthAdapter)
18355
+ .add("iso_week_number", isoWeekNumberAdapter)
18356
+ .add("month_number", monthNumberAdapter)
18357
+ .add("quarter_number", quarterNumberAdapter)
18358
+ .add("year_number", yearAdapter);
18380
18359
 
18381
18360
  const AGGREGATOR_NAMES = {
18382
18361
  count: _t("Count"),
@@ -18392,7 +18371,7 @@ const NUMBER_CHAR_AGGREGATORS = ["max", "min", "avg", "sum", "count_distinct", "
18392
18371
  const AGGREGATORS_BY_FIELD_TYPE = {
18393
18372
  integer: NUMBER_CHAR_AGGREGATORS,
18394
18373
  char: NUMBER_CHAR_AGGREGATORS,
18395
- //TODO Support for date and boolean
18374
+ boolean: ["count_distinct", "count", "bool_and", "bool_or"],
18396
18375
  };
18397
18376
  const AGGREGATORS = {};
18398
18377
  for (const type in AGGREGATORS_BY_FIELD_TYPE) {
@@ -18502,6 +18481,44 @@ function toPivotDomain(domainStr) {
18502
18481
  function flatPivotDomain(domain) {
18503
18482
  return domain.flatMap((arg) => [arg.field, arg.value]);
18504
18483
  }
18484
+ /**
18485
+ * Parses the value defining a pivot group in a PIVOT formula
18486
+ * e.g. given the following formula PIVOT.VALUE("1", "stage_id", "42", "status", "won"),
18487
+ * the two group values are "42" and "won".
18488
+ */
18489
+ function toNormalizedPivotValue(dimension, groupValue) {
18490
+ if (groupValue === null || groupValue === "null") {
18491
+ return null;
18492
+ }
18493
+ const groupValueString = typeof groupValue === "boolean"
18494
+ ? toString(groupValue).toLocaleLowerCase()
18495
+ : toString(groupValue);
18496
+ if (!pivotNormalizationValueRegistry.contains(dimension.type)) {
18497
+ throw new EvaluationError(_t("Field %(field)s is not supported because of its type (%(type)s)", {
18498
+ field: dimension.displayName,
18499
+ type: dimension.type,
18500
+ }));
18501
+ }
18502
+ // represents a field which is not set (=False server side)
18503
+ if (groupValueString === "false") {
18504
+ return false;
18505
+ }
18506
+ const normalizer = pivotNormalizationValueRegistry.get(dimension.type);
18507
+ return normalizer(groupValueString, dimension.granularity);
18508
+ }
18509
+ function normalizeDateTime(value, granularity) {
18510
+ if (!granularity) {
18511
+ throw "";
18512
+ }
18513
+ return pivotTimeAdapter(granularity).normalizeFunctionValue(value);
18514
+ }
18515
+ const pivotNormalizationValueRegistry = new Registry();
18516
+ pivotNormalizationValueRegistry
18517
+ .add("date", normalizeDateTime)
18518
+ .add("datetime", normalizeDateTime)
18519
+ .add("integer", (value) => toNumber(value, DEFAULT_LOCALE))
18520
+ .add("boolean", (value) => toBoolean(value))
18521
+ .add("char", (value) => toString(value));
18505
18522
 
18506
18523
  /**
18507
18524
  * Get the pivot ID from the formula pivot ID.
@@ -18578,7 +18595,6 @@ const ADDRESS = {
18578
18595
  arg("use_a1_notation (boolean, default=TRUE)", _t("A boolean indicating whether to use A1 style notation (TRUE) or R1C1 style notation (FALSE).")),
18579
18596
  arg("sheet (string, optional)", _t("A string indicating the name of the sheet into which the address points.")),
18580
18597
  ],
18581
- returns: ["STRING"],
18582
18598
  compute: function (row, column, absoluteRelativeMode = { value: DEFAULT_ABSOLUTE_RELATIVE_MODE }, useA1Notation = { value: true }, sheet) {
18583
18599
  const rowNumber = strictToInteger(row, this.locale);
18584
18600
  const colNumber = strictToInteger(column, this.locale);
@@ -18615,7 +18631,6 @@ const COLUMN = {
18615
18631
  args: [
18616
18632
  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.")),
18617
18633
  ],
18618
- returns: ["NUMBER"],
18619
18634
  compute: function (cellReference) {
18620
18635
  if (isEvaluationError(cellReference?.value)) {
18621
18636
  throw cellReference;
@@ -18633,7 +18648,6 @@ const COLUMN = {
18633
18648
  const COLUMNS = {
18634
18649
  description: _t("Number of columns in a specified array or range."),
18635
18650
  args: [arg("range (meta)", _t("The range whose column count will be returned."))],
18636
- returns: ["NUMBER"],
18637
18651
  compute: function (range) {
18638
18652
  if (isEvaluationError(range?.value)) {
18639
18653
  throw range;
@@ -18654,7 +18668,6 @@ const HLOOKUP = {
18654
18668
  arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
18655
18669
  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.")),
18656
18670
  ],
18657
- returns: ["ANY"],
18658
18671
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18659
18672
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18660
18673
  assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
@@ -18684,7 +18697,6 @@ const INDEX = {
18684
18697
  arg("row (number, default=0)", _t("The index of the row to be returned from within the reference range of cells.")),
18685
18698
  arg("column (number, default=0)", _t("The index of the column to be returned from within the reference range of cells.")),
18686
18699
  ],
18687
- returns: ["ANY"],
18688
18700
  compute: function (reference, row = { value: 0 }, column = { value: 0 }) {
18689
18701
  const _reference = toMatrix(reference);
18690
18702
  const _row = toNumber(row.value, this.locale);
@@ -18715,7 +18727,6 @@ const INDIRECT = {
18715
18727
  arg("reference (string)", _t("The range of cells from which the values are returned.")),
18716
18728
  arg("use_a1_notation (boolean, default=TRUE)", _t("A boolean indicating whether to use A1 style notation (TRUE) or R1C1 style notation (FALSE).")),
18717
18729
  ],
18718
- returns: ["ANY"],
18719
18730
  compute: function (reference, useA1Notation = { value: true }) {
18720
18731
  let _reference = reference?.value?.toString();
18721
18732
  if (!_reference) {
@@ -18770,7 +18781,6 @@ const LOOKUP = {
18770
18781
  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.")),
18771
18782
  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.")),
18772
18783
  ],
18773
- returns: ["ANY"],
18774
18784
  compute: function (searchKey, searchArray, resultRange) {
18775
18785
  let nbCol = searchArray.length;
18776
18786
  let nbRow = searchArray[0].length;
@@ -18811,7 +18821,6 @@ const MATCH = {
18811
18821
  arg("range (any, range)", _t("The one-dimensional array to be searched.")),
18812
18822
  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.")),
18813
18823
  ],
18814
- returns: ["NUMBER"],
18815
18824
  compute: function (searchKey, range, searchType = { value: DEFAULT_SEARCH_TYPE }) {
18816
18825
  let _searchType = toNumber(searchType, this.locale);
18817
18826
  const nbCol = range.length;
@@ -18850,7 +18859,6 @@ const ROW = {
18850
18859
  args: [
18851
18860
  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.")),
18852
18861
  ],
18853
- returns: ["NUMBER"],
18854
18862
  compute: function (cellReference) {
18855
18863
  if (isEvaluationError(cellReference?.value)) {
18856
18864
  throw cellReference;
@@ -18868,7 +18876,6 @@ const ROW = {
18868
18876
  const ROWS = {
18869
18877
  description: _t("Number of rows in a specified array or range."),
18870
18878
  args: [arg("range (meta)", _t("The range whose row count will be returned."))],
18871
- returns: ["NUMBER"],
18872
18879
  compute: function (range) {
18873
18880
  if (isEvaluationError(range?.value)) {
18874
18881
  throw range;
@@ -18889,7 +18896,6 @@ const VLOOKUP = {
18889
18896
  arg("index (number)", _t("The column index of the value to be returned, where the first column in range is numbered 1.")),
18890
18897
  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.")),
18891
18898
  ],
18892
- returns: ["ANY"],
18893
18899
  compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
18894
18900
  const _index = Math.trunc(toNumber(index?.value, this.locale));
18895
18901
  assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
@@ -18935,7 +18941,6 @@ const XLOOKUP = {
18935
18941
  (-2) Perform a binary search that relies on lookup_array being sorted in descending order. If not sorted, invalid results will be returned.\
18936
18942
  ")),
18937
18943
  ],
18938
- returns: ["ANY"],
18939
18944
  compute: function (searchKey, lookupRange, returnRange, defaultValue, matchMode = { value: DEFAULT_MATCH_MODE }, searchMode = { value: DEFAULT_SEARCH_MODE }) {
18940
18945
  const _matchMode = Math.trunc(toNumber(matchMode.value, this.locale));
18941
18946
  const _searchMode = Math.trunc(toNumber(searchMode.value, this.locale));
@@ -18991,12 +18996,6 @@ const PIVOT_VALUE = {
18991
18996
  assertDomainLength(_domainArgs);
18992
18997
  const pivot = this.getters.getPivot(pivotId);
18993
18998
  const coreDefinition = this.getters.getPivotCoreDefinition(pivotId);
18994
- if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
18995
- return {
18996
- value: CellErrorType.GenericError,
18997
- message: _t("This pivot does not support PIVOT.VALUE formula"),
18998
- };
18999
- }
19000
18999
  addPivotDependencies(this, coreDefinition);
19001
19000
  const error = pivot.assertIsValid({ throwOnError: false });
19002
19001
  if (error) {
@@ -19012,7 +19011,6 @@ const PIVOT_VALUE = {
19012
19011
  }
19013
19012
  return { value, format };
19014
19013
  },
19015
- returns: ["NUMBER", "STRING"],
19016
19014
  };
19017
19015
  const PIVOT_HEADER = {
19018
19016
  description: _t("Get the header of a pivot."),
@@ -19028,12 +19026,6 @@ const PIVOT_HEADER = {
19028
19026
  assertDomainLength(_domainArgs);
19029
19027
  const pivot = this.getters.getPivot(_pivotId);
19030
19028
  const coreDefinition = this.getters.getPivotCoreDefinition(_pivotId);
19031
- if (!supportedPivotExplodedFormulaRegistry.get(coreDefinition.type)) {
19032
- return {
19033
- value: CellErrorType.GenericError,
19034
- message: _t("This pivot does not support PIVOT.VALUE formula"),
19035
- };
19036
- }
19037
19029
  addPivotDependencies(this, coreDefinition);
19038
19030
  const error = pivot.assertIsValid({ throwOnError: false });
19039
19031
  if (error) {
@@ -19058,7 +19050,6 @@ const PIVOT_HEADER = {
19058
19050
  : format,
19059
19051
  };
19060
19052
  },
19061
- returns: ["NUMBER", "STRING"],
19062
19053
  };
19063
19054
  const PIVOT = {
19064
19055
  description: _t("Get a pivot table."),
@@ -19125,7 +19116,6 @@ const PIVOT = {
19125
19116
  }
19126
19117
  return result;
19127
19118
  },
19128
- returns: ["RANGE<ANY>"],
19129
19119
  };
19130
19120
 
19131
19121
  var lookup = /*#__PURE__*/Object.freeze({
@@ -19156,7 +19146,6 @@ const ADD = {
19156
19146
  arg("value1 (number)", _t("The first addend.")),
19157
19147
  arg("value2 (number)", _t("The second addend.")),
19158
19148
  ],
19159
- returns: ["NUMBER"],
19160
19149
  compute: function (value1, value2) {
19161
19150
  return {
19162
19151
  value: toNumber(value1, this.locale) + toNumber(value2, this.locale),
@@ -19173,7 +19162,6 @@ const CONCAT = {
19173
19162
  arg("value1 (string)", _t("The value to which value2 will be appended.")),
19174
19163
  arg("value2 (string)", _t("The value to append to value1.")),
19175
19164
  ],
19176
- returns: ["STRING"],
19177
19165
  compute: function (value1, value2) {
19178
19166
  return toString(value1) + toString(value2);
19179
19167
  },
@@ -19188,7 +19176,6 @@ const DIVIDE = {
19188
19176
  arg("dividend (number)", _t("The number to be divided.")),
19189
19177
  arg("divisor (number)", _t("The number to divide by.")),
19190
19178
  ],
19191
- returns: ["NUMBER"],
19192
19179
  compute: function (dividend, divisor) {
19193
19180
  const _divisor = toNumber(divisor, this.locale);
19194
19181
  assert(() => _divisor !== 0, _t("The divisor must be different from zero."), CellErrorType.DivisionByZero);
@@ -19211,7 +19198,6 @@ const EQ = {
19211
19198
  arg("value1 (any)", _t("The first value.")),
19212
19199
  arg("value2 (any)", _t("The value to test against value1 for equality.")),
19213
19200
  ],
19214
- returns: ["BOOLEAN"],
19215
19201
  compute: function (value1, value2) {
19216
19202
  let _value1 = isEmpty(value1) ? getNeutral[typeof value2?.value] : value1?.value;
19217
19203
  let _value2 = isEmpty(value2) ? getNeutral[typeof value1?.value] : value2?.value;
@@ -19264,7 +19250,6 @@ const GT = {
19264
19250
  arg("value1 (any)", _t("The value to test as being greater than value2.")),
19265
19251
  arg("value2 (any)", _t("The second value.")),
19266
19252
  ],
19267
- returns: ["BOOLEAN"],
19268
19253
  compute: function (value1, value2) {
19269
19254
  return applyRelationalOperator(value1, value2, (v1, v2) => {
19270
19255
  return v1 > v2;
@@ -19280,7 +19265,6 @@ const GTE = {
19280
19265
  arg("value1 (any)", _t("The value to test as being greater than or equal to value2.")),
19281
19266
  arg("value2 (any)", _t("The second value.")),
19282
19267
  ],
19283
- returns: ["BOOLEAN"],
19284
19268
  compute: function (value1, value2) {
19285
19269
  return applyRelationalOperator(value1, value2, (v1, v2) => {
19286
19270
  return v1 >= v2;
@@ -19296,7 +19280,6 @@ const LT = {
19296
19280
  arg("value1 (any)", _t("The value to test as being less than value2.")),
19297
19281
  arg("value2 (any)", _t("The second value.")),
19298
19282
  ],
19299
- returns: ["BOOLEAN"],
19300
19283
  compute: function (value1, value2) {
19301
19284
  return !GTE.compute.bind(this)(value1, value2);
19302
19285
  },
@@ -19310,7 +19293,6 @@ const LTE = {
19310
19293
  arg("value1 (any)", _t("The value to test as being less than or equal to value2.")),
19311
19294
  arg("value2 (any)", _t("The second value.")),
19312
19295
  ],
19313
- returns: ["BOOLEAN"],
19314
19296
  compute: function (value1, value2) {
19315
19297
  return !GT.compute.bind(this)(value1, value2);
19316
19298
  },
@@ -19324,7 +19306,6 @@ const MINUS = {
19324
19306
  arg("value1 (number)", _t("The minuend, or number to be subtracted from.")),
19325
19307
  arg("value2 (number)", _t("The subtrahend, or number to subtract from value1.")),
19326
19308
  ],
19327
- returns: ["NUMBER"],
19328
19309
  compute: function (value1, value2) {
19329
19310
  return {
19330
19311
  value: toNumber(value1, this.locale) - toNumber(value2, this.locale),
@@ -19341,7 +19322,6 @@ const MULTIPLY = {
19341
19322
  arg("factor1 (number)", _t("The first multiplicand.")),
19342
19323
  arg("factor2 (number)", _t("The second multiplicand.")),
19343
19324
  ],
19344
- returns: ["NUMBER"],
19345
19325
  compute: function (factor1, factor2) {
19346
19326
  return {
19347
19327
  value: toNumber(factor1, this.locale) * toNumber(factor2, this.locale),
@@ -19358,7 +19338,6 @@ const NE = {
19358
19338
  arg("value1 (any)", _t("The first value.")),
19359
19339
  arg("value2 (any)", _t("The value to test against value1 for inequality.")),
19360
19340
  ],
19361
- returns: ["BOOLEAN"],
19362
19341
  compute: function (value1, value2) {
19363
19342
  return !EQ.compute.bind(this)(value1, value2);
19364
19343
  },
@@ -19372,7 +19351,6 @@ const POW = {
19372
19351
  arg("base (number)", _t("The number to raise to the exponent power.")),
19373
19352
  arg("exponent (number)", _t("The exponent to raise base to.")),
19374
19353
  ],
19375
- returns: ["NUMBER"],
19376
19354
  compute: function (base, exponent) {
19377
19355
  return POWER.compute.bind(this)(base, exponent);
19378
19356
  },
@@ -19385,7 +19363,6 @@ const UMINUS = {
19385
19363
  args: [
19386
19364
  arg("value (number)", _t("The number to have its sign reversed. Equivalently, the number to multiply by -1.")),
19387
19365
  ],
19388
- returns: ["NUMBER"],
19389
19366
  compute: function (value) {
19390
19367
  return {
19391
19368
  value: -toNumber(value, this.locale),
@@ -19399,7 +19376,6 @@ const UMINUS = {
19399
19376
  const UNARY_PERCENT = {
19400
19377
  description: _t("Value interpreted as a percentage."),
19401
19378
  args: [arg("percentage (number)", _t("The value to interpret as a percentage."))],
19402
- returns: ["NUMBER"],
19403
19379
  compute: function (percentage) {
19404
19380
  return toNumber(percentage, this.locale) / 100;
19405
19381
  },
@@ -19410,7 +19386,6 @@ const UNARY_PERCENT = {
19410
19386
  const UPLUS = {
19411
19387
  description: _t("A specified number, unchanged."),
19412
19388
  args: [arg("value (any)", _t("The number to return."))],
19413
- returns: ["ANY"],
19414
19389
  compute: function (value = { value: null }) {
19415
19390
  return value;
19416
19391
  },
@@ -19446,7 +19421,6 @@ const CHAR = {
19446
19421
  args: [
19447
19422
  arg("table_number (number)", _t("The number of the character to look up from the current Unicode table in decimal format.")),
19448
19423
  ],
19449
- returns: ["STRING"],
19450
19424
  compute: function (tableNumber) {
19451
19425
  const _tableNumber = Math.trunc(toNumber(tableNumber, this.locale));
19452
19426
  assert(() => _tableNumber >= 1, _t("The table_number (%s) is out of range.", _tableNumber.toString()));
@@ -19460,7 +19434,6 @@ const CHAR = {
19460
19434
  const CLEAN = {
19461
19435
  description: _t("Remove non-printable characters from a piece of text."),
19462
19436
  args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
19463
- returns: ["STRING"],
19464
19437
  compute: function (text) {
19465
19438
  const _text = toString(text);
19466
19439
  let cleanedStr = "";
@@ -19482,7 +19455,6 @@ const CONCATENATE = {
19482
19455
  arg("string1 (string, range<string>)", _t("The initial string.")),
19483
19456
  arg("string2 (string, range<string>, repeating)", _t("More strings to append in sequence.")),
19484
19457
  ],
19485
- returns: ["STRING"],
19486
19458
  compute: function (...datas) {
19487
19459
  return reduceAny(datas, (acc, a) => acc + toString(a), "");
19488
19460
  },
@@ -19497,7 +19469,6 @@ const EXACT = {
19497
19469
  arg("string1 (string)", _t("The first string to compare.")),
19498
19470
  arg("string2 (string)", _t("The second string to compare.")),
19499
19471
  ],
19500
- returns: ["BOOLEAN"],
19501
19472
  compute: function (string1, string2) {
19502
19473
  return toString(string1) === toString(string2);
19503
19474
  },
@@ -19513,7 +19484,6 @@ const FIND = {
19513
19484
  arg("text_to_search (string)", _t("The text to search for the first occurrence of search_for.")),
19514
19485
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search.")),
19515
19486
  ],
19516
- returns: ["NUMBER"],
19517
19487
  compute: function (searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
19518
19488
  const _searchFor = toString(searchFor);
19519
19489
  const _textToSearch = toString(textToSearch);
@@ -19536,7 +19506,6 @@ const JOIN = {
19536
19506
  arg("value_or_array1 (string, range<string>)", _t("The value or values to be appended using delimiter.")),
19537
19507
  arg("value_or_array2 (string, range<string>, repeating)", _t("More values to be appended using delimiter.")),
19538
19508
  ],
19539
- returns: ["STRING"],
19540
19509
  compute: function (delimiter, ...valuesOrArrays) {
19541
19510
  const _delimiter = toString(delimiter);
19542
19511
  return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toString(a), "");
@@ -19551,7 +19520,6 @@ const LEFT = {
19551
19520
  arg("text (string)", _t("The string from which the left portion will be returned.")),
19552
19521
  arg("number_of_characters (number, optional)", _t("The number of characters to return from the left side of string.")),
19553
19522
  ],
19554
- returns: ["STRING"],
19555
19523
  compute: function (text, ...args) {
19556
19524
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
19557
19525
  assert(() => _numberOfCharacters >= 0, _t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters.toString()));
@@ -19565,7 +19533,6 @@ const LEFT = {
19565
19533
  const LEN = {
19566
19534
  description: _t("Length of a string."),
19567
19535
  args: [arg("text (string)", _t("The string whose length will be returned."))],
19568
- returns: ["NUMBER"],
19569
19536
  compute: function (text) {
19570
19537
  return toString(text).length;
19571
19538
  },
@@ -19577,7 +19544,6 @@ const LEN = {
19577
19544
  const LOWER = {
19578
19545
  description: _t("Converts a specified string to lowercase."),
19579
19546
  args: [arg("text (string)", _t("The string to convert to lowercase."))],
19580
- returns: ["STRING"],
19581
19547
  compute: function (text) {
19582
19548
  return toString(text).toLowerCase();
19583
19549
  },
@@ -19593,7 +19559,6 @@ const MID = {
19593
19559
  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.")),
19594
19560
  arg("extract_length (number)", _t("The length of the segment to extract.")),
19595
19561
  ],
19596
- returns: ["STRING"],
19597
19562
  compute: function (text, starting_at, extract_length) {
19598
19563
  const _text = toString(text);
19599
19564
  const _starting_at = toNumber(starting_at, this.locale);
@@ -19612,7 +19577,6 @@ const PROPER = {
19612
19577
  args: [
19613
19578
  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.")),
19614
19579
  ],
19615
- returns: ["STRING"],
19616
19580
  compute: function (text) {
19617
19581
  const _text = toString(text);
19618
19582
  return _text.replace(wordRegex, (word) => {
@@ -19632,7 +19596,6 @@ const REPLACE = {
19632
19596
  arg("length (number)", _t("The number of characters in the text to be replaced.")),
19633
19597
  arg("new_text (string)", _t("The text which will be inserted into the original text.")),
19634
19598
  ],
19635
- returns: ["STRING"],
19636
19599
  compute: function (text, position, length, newText) {
19637
19600
  const _position = toNumber(position, this.locale);
19638
19601
  assert(() => _position >= 1, _t("The position (%s) must be greater than or equal to 1.", _position.toString()));
@@ -19652,7 +19615,6 @@ const RIGHT = {
19652
19615
  arg("text (string)", _t("The string from which the right portion will be returned.")),
19653
19616
  arg("number_of_characters (number, optional)", _t("The number of characters to return from the right side of string.")),
19654
19617
  ],
19655
- returns: ["STRING"],
19656
19618
  compute: function (text, ...args) {
19657
19619
  const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
19658
19620
  assert(() => _numberOfCharacters >= 0, _t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters.toString()));
@@ -19672,7 +19634,6 @@ const SEARCH = {
19672
19634
  arg("text_to_search (string)", _t("The text to search for the first occurrence of search_for.")),
19673
19635
  arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search.")),
19674
19636
  ],
19675
- returns: ["NUMBER"],
19676
19637
  compute: function (searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
19677
19638
  const _searchFor = toString(searchFor).toLowerCase();
19678
19639
  const _textToSearch = toString(textToSearch).toLowerCase();
@@ -19699,7 +19660,6 @@ const SPLIT = {
19699
19660
  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 \
19700
19661
  consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters.")),
19701
19662
  ],
19702
- returns: ["RANGE<STRING>"],
19703
19663
  compute: function (text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
19704
19664
  const _text = toString(text);
19705
19665
  const _delimiter = escapeRegExp(toString(delimiter));
@@ -19726,7 +19686,6 @@ const SUBSTITUTE = {
19726
19686
  arg("replace_with (string)", _t("The string that will replace search_for.")),
19727
19687
  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.")),
19728
19688
  ],
19729
- returns: ["NUMBER"],
19730
19689
  compute: function (textToSearch, searchFor, replaceWith, occurrenceNumber) {
19731
19690
  const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
19732
19691
  assert(() => _occurrenceNumber >= 0, _t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber.toString()));
@@ -19756,7 +19715,6 @@ const TEXTJOIN = {
19756
19715
  arg("text1 (string, range<string>)", _t("Any text item. This could be a string, or an array of strings in a range.")),
19757
19716
  arg("text2 (string, range<string>, repeating)", _t("Additional text item(s).")),
19758
19717
  ],
19759
- returns: ["STRING"],
19760
19718
  compute: function (delimiter, ignoreEmpty, ...textsOrArrays) {
19761
19719
  const _delimiter = toString(delimiter);
19762
19720
  const _ignoreEmpty = toBoolean(ignoreEmpty);
@@ -19773,7 +19731,6 @@ const TRIM = {
19773
19731
  args: [
19774
19732
  arg("text (string)", _t("The text or reference to a cell containing text to be trimmed.")),
19775
19733
  ],
19776
- returns: ["STRING"],
19777
19734
  compute: function (text) {
19778
19735
  return trimContent(toString(text));
19779
19736
  },
@@ -19785,7 +19742,6 @@ const TRIM = {
19785
19742
  const UPPER = {
19786
19743
  description: _t("Converts a specified string to uppercase."),
19787
19744
  args: [arg("text (string)", _t("The string to convert to uppercase."))],
19788
- returns: ["STRING"],
19789
19745
  compute: function (text) {
19790
19746
  return toString(text).toUpperCase();
19791
19747
  },
@@ -19800,7 +19756,6 @@ const TEXT = {
19800
19756
  arg("number (number)", _t("The number, date or time to format.")),
19801
19757
  arg("format (string)", _t("The pattern by which to format the number, enclosed in quotation marks.")),
19802
19758
  ],
19803
- returns: ["STRING"],
19804
19759
  compute: function (number, format) {
19805
19760
  const _number = toNumber(number, this.locale);
19806
19761
  return formatValue(_number, { format: toString(format), locale: this.locale });
@@ -19841,7 +19796,6 @@ const HYPERLINK = {
19841
19796
  arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")),
19842
19797
  arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks.")),
19843
19798
  ],
19844
- returns: ["STRING"],
19845
19799
  compute: function (url, linkLabel) {
19846
19800
  const processedUrl = toString(url).trim();
19847
19801
  const processedLabel = toString(linkLabel) || processedUrl;
@@ -19900,6 +19854,9 @@ function addInputHandling(descr) {
19900
19854
  }
19901
19855
  args[i] = arg[0][0];
19902
19856
  }
19857
+ if (!isMatrix(arg) && argDefinition.acceptMatrixOnly) {
19858
+ throw new BadExpressionError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be reference to a cell or range.", (i + 1).toString()));
19859
+ }
19903
19860
  }
19904
19861
  return descr.compute.apply(this, args);
19905
19862
  }
@@ -21494,12 +21451,6 @@ function compileTokens(tokens) {
21494
21451
  // detect when an argument need to be evaluated as a meta argument
21495
21452
  const isMeta = argTypes.includes("META");
21496
21453
  const hasRange = argTypes.some((t) => isRangeType(t));
21497
- const isRangeOnly = argTypes.every((t) => isRangeType(t));
21498
- if (isRangeOnly) {
21499
- if (!isRangeInput(currentArg)) {
21500
- 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 }));
21501
- }
21502
- }
21503
21454
  compiledArgs.push(compileAST(currentArg, isMeta, hasRange));
21504
21455
  }
21505
21456
  return compiledArgs;
@@ -21664,16 +21615,6 @@ function assertEnoughArgs(ast) {
21664
21615
  function isRangeType(type) {
21665
21616
  return type.startsWith("RANGE");
21666
21617
  }
21667
- function isRangeInput(arg) {
21668
- if (arg.type === "REFERENCE") {
21669
- return true;
21670
- }
21671
- if (arg.type === "FUNCALL") {
21672
- const fnDef = functions$1[arg.value.toUpperCase()];
21673
- return fnDef && isRangeType(fnDef.returns[0]);
21674
- }
21675
- return false;
21676
- }
21677
21618
 
21678
21619
  const functions = functionRegistry.content;
21679
21620
  function isExportableToExcel(tokens) {
@@ -21717,11 +21658,14 @@ const PIVOT_FUNCTIONS = ["PIVOT.VALUE", "PIVOT.HEADER", "PIVOT"];
21717
21658
  function makeFieldProposal(field, granularity) {
21718
21659
  const groupBy = granularity ? `${field.name}:${granularity}` : field.name;
21719
21660
  const quotedGroupBy = `"${groupBy}"`;
21661
+ const fuzzySearchKey = field.string !== field.name
21662
+ ? field.string + quotedGroupBy // search on translated name and on technical name
21663
+ : quotedGroupBy;
21720
21664
  return {
21721
21665
  text: quotedGroupBy,
21722
21666
  description: field.string + (field.help ? ` (${field.help})` : ""),
21723
21667
  htmlContent: [{ value: quotedGroupBy, color: tokenColors.STRING }],
21724
- fuzzySearchKey: field.string + quotedGroupBy, // search on translated name and on technical name
21668
+ fuzzySearchKey,
21725
21669
  };
21726
21670
  }
21727
21671
  /**
@@ -21781,6 +21725,14 @@ function getNumberOfPivotFunctions(tokens) {
21781
21725
  return getFunctionsFromTokens(tokens, PIVOT_FUNCTIONS).length;
21782
21726
  }
21783
21727
 
21728
+ /**
21729
+ * Registry to enable or disable the support of positional arguments
21730
+ * (with a leading #) in pivot functions
21731
+ * e.g. =PIVOT.VALUE(1,"probability","#stage",1)
21732
+ */
21733
+ const supportedPivotPositionalFormulaRegistry = new Registry();
21734
+ supportedPivotPositionalFormulaRegistry.add("SPREADSHEET", false);
21735
+
21784
21736
  autoCompleteProviders.add("pivot_ids", {
21785
21737
  sequence: 50,
21786
21738
  autoSelectFirstProposal: true,
@@ -21799,10 +21751,6 @@ autoCompleteProviders.add("pivot_ids", {
21799
21751
  return pivotIds
21800
21752
  .map((pivotId) => {
21801
21753
  const definition = this.getters.getPivotCoreDefinition(pivotId);
21802
- if (functionContext.parent.toUpperCase() !== "PIVOT" &&
21803
- !supportedPivotExplodedFormulaRegistry.get(definition.type)) {
21804
- return undefined;
21805
- }
21806
21754
  const formulaId = this.getters.getPivotFormulaId(pivotId);
21807
21755
  const str = `${formulaId}`;
21808
21756
  return {
@@ -21830,15 +21778,13 @@ autoCompleteProviders.add("pivot_measures", {
21830
21778
  if (!pivotId || !this.getters.isExistingPivot(pivotId)) {
21831
21779
  return [];
21832
21780
  }
21833
- const dataSource = this.getters.getPivot(pivotId);
21834
- const fields = dataSource.getFields();
21781
+ const pivot = this.getters.getPivot(pivotId);
21782
+ pivot.init();
21783
+ const fields = pivot.getFields();
21835
21784
  if (!fields) {
21836
21785
  return [];
21837
21786
  }
21838
21787
  const definition = this.getters.getPivotCoreDefinition(pivotId);
21839
- if (!supportedPivotExplodedFormulaRegistry.get(definition.type)) {
21840
- return [];
21841
- }
21842
21788
  return definition.measures
21843
21789
  .map((measure) => {
21844
21790
  if (measure.name === "__count") {
@@ -21874,16 +21820,13 @@ autoCompleteProviders.add("pivot_group_fields", {
21874
21820
  if (!pivotId || !this.getters.isExistingPivot(pivotId)) {
21875
21821
  return;
21876
21822
  }
21877
- const dataSource = this.getters.getPivot(pivotId);
21878
- const fields = dataSource.getFields();
21823
+ const pivot = this.getters.getPivot(pivotId);
21824
+ pivot.init();
21825
+ const fields = pivot.getFields();
21879
21826
  if (!fields) {
21880
21827
  return;
21881
21828
  }
21882
- const { type } = this.getters.getPivotCoreDefinition(pivotId);
21883
- const { columns, rows } = dataSource.definition;
21884
- if (!supportedPivotExplodedFormulaRegistry.get(type)) {
21885
- return [];
21886
- }
21829
+ const { columns, rows } = pivot.definition;
21887
21830
  let args = functionContext.args;
21888
21831
  if (functionContext?.parent.toUpperCase() === "PIVOT.VALUE") {
21889
21832
  args = args.filter((ast, index) => index % 2 === 0); // keep only the field names
@@ -21920,6 +21863,9 @@ autoCompleteProviders.add("pivot_group_fields", {
21920
21863
  return field ? makeFieldProposal(field, granularity) : undefined;
21921
21864
  })
21922
21865
  .concat(groupBys.map((groupBy) => {
21866
+ if (!supportedPivotPositionalFormulaRegistry.get(pivot.type)) {
21867
+ return undefined;
21868
+ }
21923
21869
  const fieldName = groupBy.split(":")[0];
21924
21870
  const field = fields[fieldName];
21925
21871
  if (!field) {
@@ -21968,12 +21914,8 @@ autoCompleteProviders.add("pivot_group_values", {
21968
21914
  if (!pivotId || !this.getters.isExistingPivot(pivotId)) {
21969
21915
  return;
21970
21916
  }
21971
- const { type } = this.getters.getPivotCoreDefinition(pivotId);
21972
- if (!supportedPivotExplodedFormulaRegistry.get(type)) {
21973
- return [];
21974
- }
21975
- const dataSource = this.getters.getPivot(pivotId);
21976
- if (!dataSource.isValid()) {
21917
+ const pivot = this.getters.getPivot(pivotId);
21918
+ if (!pivot.isValid()) {
21977
21919
  return;
21978
21920
  }
21979
21921
  const argPosition = functionContext.argPosition;
@@ -21981,7 +21923,46 @@ autoCompleteProviders.add("pivot_group_values", {
21981
21923
  if (!groupByField) {
21982
21924
  return;
21983
21925
  }
21984
- return dataSource.getPossibleFieldValues(groupByField.split(":")[0]).map(({ value, label }) => {
21926
+ let dimension;
21927
+ try {
21928
+ dimension = pivot.definition.getDimension(groupByField);
21929
+ }
21930
+ catch (error) {
21931
+ return undefined;
21932
+ }
21933
+ if (dimension.granularity === "month_number") {
21934
+ return Object.values(MONTHS).map((monthDisplayName, index) => ({
21935
+ text: `${index + 1}`,
21936
+ fuzzySearchKey: monthDisplayName.toString(),
21937
+ description: monthDisplayName.toString(),
21938
+ htmlContent: [{ value: `${index + 1}`, color: tokenColors.NUMBER }],
21939
+ }));
21940
+ }
21941
+ else if (dimension.granularity === "quarter_number") {
21942
+ return [1, 2, 3, 4].map((quarter) => ({
21943
+ text: `${quarter}`,
21944
+ fuzzySearchKey: `${quarter}`,
21945
+ description: _t("Quarter %s", quarter),
21946
+ htmlContent: [{ value: `${quarter}`, color: tokenColors.NUMBER }],
21947
+ }));
21948
+ }
21949
+ else if (dimension.granularity === "day_of_month") {
21950
+ return range(1, 32).map((dayOfMonth) => ({
21951
+ text: `${dayOfMonth}`,
21952
+ fuzzySearchKey: `${dayOfMonth}`,
21953
+ description: "",
21954
+ htmlContent: [{ value: `${dayOfMonth}`, color: tokenColors.NUMBER }],
21955
+ }));
21956
+ }
21957
+ else if (dimension.granularity === "iso_week_number") {
21958
+ return range(0, 54).map((isoWeekNumber) => ({
21959
+ text: `${isoWeekNumber}`,
21960
+ fuzzySearchKey: `${isoWeekNumber}`,
21961
+ description: "",
21962
+ htmlContent: [{ value: `${isoWeekNumber}`, color: tokenColors.NUMBER }],
21963
+ }));
21964
+ }
21965
+ return pivot.getPossibleFieldValues(dimension).map(({ value, label }) => {
21985
21966
  const isString = typeof value === "string";
21986
21967
  const text = isString ? `"${value}"` : value.toString();
21987
21968
  const color = isString ? tokenColors.STRING : tokenColors.NUMBER;
@@ -22088,7 +22069,9 @@ autofillModifiersRegistry
22088
22069
  tooltip: content
22089
22070
  ? {
22090
22071
  props: {
22091
- content: evaluateLiteral(data.cell?.content, localeFormat).formattedValue,
22072
+ content: data.cell
22073
+ ? evaluateLiteral(data.cell, localeFormat).formattedValue
22074
+ : "",
22092
22075
  },
22093
22076
  }
22094
22077
  : undefined,
@@ -22151,9 +22134,7 @@ function getGroup(cell, cells, filter) {
22151
22134
  if (x === cell) {
22152
22135
  found = true;
22153
22136
  }
22154
- const cellValue = x?.isFormula
22155
- ? undefined
22156
- : evaluateLiteral(x?.content, { locale: DEFAULT_LOCALE });
22137
+ const cellValue = x === undefined || x.isFormula ? undefined : evaluateLiteral(x, { locale: DEFAULT_LOCALE });
22157
22138
  if (cellValue && filter(cellValue)) {
22158
22139
  group.push(cellValue);
22159
22140
  }
@@ -22201,7 +22182,7 @@ autofillRulesRegistry
22201
22182
  })
22202
22183
  .add("increment_alphanumeric_value", {
22203
22184
  condition: (cell) => !cell.isFormula &&
22204
- evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.text &&
22185
+ evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.text &&
22205
22186
  alphaNumericValueRegExp.test(cell.content),
22206
22187
  generateRule: (cell, cells) => {
22207
22188
  const numberPostfix = parseInt(cell.content.match(numberPostfixRegExp)[0]);
@@ -22224,7 +22205,7 @@ autofillRulesRegistry
22224
22205
  })
22225
22206
  .add("copy_text", {
22226
22207
  condition: (cell) => !cell.isFormula &&
22227
- evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.text,
22208
+ evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.text,
22228
22209
  generateRule: () => {
22229
22210
  return { type: "COPY_MODIFIER" };
22230
22211
  },
@@ -22239,11 +22220,11 @@ autofillRulesRegistry
22239
22220
  })
22240
22221
  .add("increment_number", {
22241
22222
  condition: (cell) => !cell.isFormula &&
22242
- evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
22223
+ evaluateLiteral(cell, { locale: DEFAULT_LOCALE }).type === CellValueType.number,
22243
22224
  generateRule: (cell, cells) => {
22244
22225
  const group = getGroup(cell, cells, (evaluatedCell) => evaluatedCell.type === CellValueType.number).map((cell) => Number(cell.value));
22245
22226
  const increment = calculateIncrementBasedOnGroup(group);
22246
- const evaluation = evaluateLiteral(cell.content, { locale: DEFAULT_LOCALE });
22227
+ const evaluation = evaluateLiteral(cell, { locale: DEFAULT_LOCALE });
22247
22228
  return {
22248
22229
  type: "INCREMENT_MODIFIER",
22249
22230
  increment,
@@ -25467,7 +25448,7 @@ class Popover extends Component {
25467
25448
  if (!anchor)
25468
25449
  return;
25469
25450
  const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
25470
- const elDims = {
25451
+ let elDims = {
25471
25452
  width: el.getBoundingClientRect().width,
25472
25453
  height: el.getBoundingClientRect().height,
25473
25454
  };
@@ -25475,7 +25456,14 @@ class Popover extends Component {
25475
25456
  const popoverPositionHelper = this.props.positioning === "BottomLeft"
25476
25457
  ? new BottomLeftPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect)
25477
25458
  : new TopRightPopoverContext(anchor, this.containerRect, propsMaxSize, spreadsheetRect);
25478
- const style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
25459
+ el.style["max-height"] = popoverPositionHelper.getMaxHeight(elDims.height) + "px";
25460
+ el.style["max-width"] = popoverPositionHelper.getMaxWidth(elDims.width) + "px";
25461
+ // Re-compute the dimensions after setting the max-width and max-height
25462
+ elDims = {
25463
+ width: el.getBoundingClientRect().width,
25464
+ height: el.getBoundingClientRect().height,
25465
+ };
25466
+ let style = popoverPositionHelper.getCss(elDims, this.props.verticalOffset);
25479
25467
  for (const property of Object.keys(style)) {
25480
25468
  el.style[property] = style[property];
25481
25469
  }
@@ -25538,8 +25526,6 @@ class PopoverPositionContext {
25538
25526
  const shouldRenderAtRight = this.shouldRenderAtRight(elDims.width);
25539
25527
  verticalOffset = shouldRenderAtBottom ? verticalOffset : -verticalOffset;
25540
25528
  const cssProperties = {
25541
- "max-height": maxHeight + "px",
25542
- "max-width": maxWidth + "px",
25543
25529
  top: this.getTopCoordinate(actualHeight, shouldRenderAtBottom) -
25544
25530
  this.spreadsheetOffset.y -
25545
25531
  verticalOffset +
@@ -31353,10 +31339,8 @@ class ChartTitle extends Component {
31353
31339
 
31354
31340
  class AxisDesignEditor extends Component {
31355
31341
  static template = "o-spreadsheet-AxisDesignEditor";
31356
- static components = {
31357
- Section,
31358
- ChartTitle,
31359
- };
31342
+ static components = { Section, ChartTitle };
31343
+ static props = { figureId: String, definition: Object, updateChart: Function, axesList: Array };
31360
31344
  state = useState({ currentAxis: "x" });
31361
31345
  get axisTitleStyle() {
31362
31346
  const axisDesign = this.props.definition.axesDesign?.[this.state.currentAxis] ?? {};
@@ -31507,6 +31491,12 @@ class ChartWithAxisDesignPanel extends Component {
31507
31491
  AxisDesignEditor,
31508
31492
  RoundColorPicker,
31509
31493
  };
31494
+ static props = {
31495
+ figureId: String,
31496
+ definition: Object,
31497
+ canUpdateChart: Function,
31498
+ updateChart: Function,
31499
+ };
31510
31500
  state = useState({ index: 0 });
31511
31501
  get axesList() {
31512
31502
  const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
@@ -33451,13 +33441,17 @@ class SelectMenu extends Component {
33451
33441
  class: { type: String, optional: true },
33452
33442
  };
33453
33443
  static components = { Menu };
33444
+ menuId = new UuidGenerator().uuidv4();
33454
33445
  selectRef = useRef("select");
33455
33446
  selectRect = useAbsoluteBoundingRect(this.selectRef);
33456
33447
  state = useState({
33457
33448
  isMenuOpen: false,
33458
33449
  });
33459
- onClick() {
33460
- this.state.isMenuOpen = true;
33450
+ onClick(ev) {
33451
+ if (ev.closedMenuId === this.menuId) {
33452
+ return;
33453
+ }
33454
+ this.state.isMenuOpen = !this.state.isMenuOpen;
33461
33455
  }
33462
33456
  onMenuClosed() {
33463
33457
  this.state.isMenuOpen = false;
@@ -33465,7 +33459,7 @@ class SelectMenu extends Component {
33465
33459
  get menuPosition() {
33466
33460
  return {
33467
33461
  x: this.selectRect.x,
33468
- y: this.selectRect.y,
33462
+ y: this.selectRect.y + this.selectRect.height,
33469
33463
  };
33470
33464
  }
33471
33465
  }
@@ -34405,9 +34399,9 @@ class FindAndReplacePanel extends Component {
34405
34399
  static props = {
34406
34400
  onCloseSidePanel: Function,
34407
34401
  };
34408
- dataRange = "";
34409
34402
  searchInput = useRef("searchInput");
34410
34403
  store;
34404
+ state;
34411
34405
  get hasSearchResult() {
34412
34406
  return this.store.selectedMatchIndex !== null;
34413
34407
  }
@@ -34437,6 +34431,7 @@ class FindAndReplacePanel extends Component {
34437
34431
  }
34438
34432
  setup() {
34439
34433
  this.store = useLocalStore(FindAndReplaceStore);
34434
+ this.state = useState({ dataRange: "" });
34440
34435
  onMounted(() => this.searchInput.el?.focus());
34441
34436
  }
34442
34437
  onFocusSearch() {
@@ -34473,13 +34468,13 @@ class FindAndReplacePanel extends Component {
34473
34468
  this.store.updateSearchOptions({ searchScope });
34474
34469
  }
34475
34470
  onSearchRangeChanged(ranges) {
34476
- this.dataRange = ranges[0];
34471
+ this.state.dataRange = ranges[0];
34477
34472
  }
34478
34473
  updateDataRange() {
34479
- if (!this.dataRange || this.searchOptions.searchScope !== "specificRange") {
34474
+ if (!this.state.dataRange || this.searchOptions.searchScope !== "specificRange") {
34480
34475
  return;
34481
34476
  }
34482
- const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.dataRange);
34477
+ const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.state.dataRange);
34483
34478
  this.store.updateSearchOptions({ specificRange });
34484
34479
  }
34485
34480
  }
@@ -34524,31 +34519,6 @@ class MoreFormatsPanel extends Component {
34524
34519
  }
34525
34520
  }
34526
34521
 
34527
- /** @odoo-module */
34528
- class EditableName extends Component {
34529
- static template = "o-spreadsheet-EditableName";
34530
- static props = {
34531
- name: String,
34532
- displayName: String,
34533
- onChanged: Function,
34534
- };
34535
- state;
34536
- setup() {
34537
- this.state = useState({
34538
- isEditing: false,
34539
- name: "",
34540
- });
34541
- }
34542
- rename() {
34543
- this.state.isEditing = true;
34544
- this.state.name = this.props.name;
34545
- }
34546
- save() {
34547
- this.props.onChanged(this.state.name.trim());
34548
- this.state.isEditing = false;
34549
- }
34550
- }
34551
-
34552
34522
  css /* scss */ `
34553
34523
  .pivot-defer-update {
34554
34524
  min-height: 35px;
@@ -34914,6 +34884,135 @@ class PivotLayoutConfigurator extends Component {
34914
34884
  }
34915
34885
  }
34916
34886
 
34887
+ css /* scss */ `
34888
+ .os-cog-wheel-menu-icon {
34889
+ cursor: pointer;
34890
+ }
34891
+
34892
+ .os-cog-wheel-menu {
34893
+ background: white;
34894
+ .btn-link {
34895
+ text-decoration: none;
34896
+ color: #017e84;
34897
+ font-weight: 500;
34898
+ &:hover {
34899
+ color: #01585c;
34900
+ }
34901
+ }
34902
+ }
34903
+ `;
34904
+ class CogWheelMenu extends Component {
34905
+ static template = "o-spreadsheet-CogWheelMenu";
34906
+ static components = { Popover };
34907
+ static props = {
34908
+ items: Array,
34909
+ };
34910
+ buttonRef = useRef("button");
34911
+ popover = useState({ isOpen: false });
34912
+ setup() {
34913
+ useExternalListener(window, "click", (ev) => {
34914
+ if (ev.target !== this.buttonRef.el) {
34915
+ this.popover.isOpen = false;
34916
+ }
34917
+ });
34918
+ }
34919
+ get popoverProps() {
34920
+ const { x, y, width, height } = this.buttonRef.el.getBoundingClientRect();
34921
+ return {
34922
+ anchorRect: { x, y, width, height },
34923
+ positioning: "BottomLeft",
34924
+ };
34925
+ }
34926
+ togglePopover() {
34927
+ this.popover.isOpen = !this.popover.isOpen;
34928
+ }
34929
+ }
34930
+
34931
+ /** @odoo-module */
34932
+ class EditableName extends Component {
34933
+ static template = "o-spreadsheet-EditableName";
34934
+ static props = {
34935
+ name: String,
34936
+ displayName: String,
34937
+ onChanged: Function,
34938
+ };
34939
+ state;
34940
+ setup() {
34941
+ this.state = useState({
34942
+ isEditing: false,
34943
+ name: "",
34944
+ });
34945
+ }
34946
+ rename() {
34947
+ this.state.isEditing = true;
34948
+ this.state.name = this.props.name;
34949
+ }
34950
+ save() {
34951
+ this.props.onChanged(this.state.name.trim());
34952
+ this.state.isEditing = false;
34953
+ }
34954
+ }
34955
+
34956
+ class PivotTitleSection extends Component {
34957
+ static template = "o-spreadsheet-PivotTitleSection";
34958
+ static components = { CogWheelMenu, Section, EditableName };
34959
+ static props = {
34960
+ pivotId: String,
34961
+ };
34962
+ get cogWheelMenuItems() {
34963
+ return [
34964
+ {
34965
+ name: "Duplicate",
34966
+ icon: "fa-copy",
34967
+ onClick: () => this.duplicatePivot(),
34968
+ },
34969
+ {
34970
+ name: "Delete",
34971
+ icon: "fa-trash",
34972
+ onClick: () => this.delete(),
34973
+ },
34974
+ ];
34975
+ }
34976
+ get name() {
34977
+ return this.env.model.getters.getPivotName(this.props.pivotId);
34978
+ }
34979
+ get displayName() {
34980
+ return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
34981
+ }
34982
+ duplicatePivot() {
34983
+ const newPivotId = this.env.model.uuidGenerator.uuidv4();
34984
+ const result = this.env.model.dispatch("DUPLICATE_PIVOT", {
34985
+ pivotId: this.props.pivotId,
34986
+ newPivotId,
34987
+ });
34988
+ const text = result.isSuccessful ? _t("Pivot duplicated.") : _t("Pivot duplication failed");
34989
+ const type = result.isSuccessful ? "success" : "danger";
34990
+ this.env.notifyUser({
34991
+ text,
34992
+ sticky: false,
34993
+ type,
34994
+ });
34995
+ if (result.isSuccessful) {
34996
+ this.env.openSidePanel("PivotSidePanel", { pivotId: newPivotId });
34997
+ }
34998
+ }
34999
+ delete() {
35000
+ this.env.askConfirmation(_t("Are you sure you want to delete this pivot?"), () => {
35001
+ this.env.model.dispatch("REMOVE_PIVOT", { pivotId: this.props.pivotId });
35002
+ });
35003
+ }
35004
+ onNameChanged(name) {
35005
+ const pivot = this.env.model.getters.getPivotCoreDefinition(this.props.pivotId);
35006
+ this.env.model.dispatch("UPDATE_PIVOT", {
35007
+ pivotId: this.props.pivotId,
35008
+ pivot: {
35009
+ ...pivot,
35010
+ name,
35011
+ },
35012
+ });
35013
+ }
35014
+ }
35015
+
34917
35016
  /**
34918
35017
  * Represent a pivot runtime definition. A pivot runtime definition is a pivot
34919
35018
  * definition that has been enriched to include the display name of its attributes
@@ -35218,7 +35317,7 @@ function dataEntriesToRows(dataEntries, index, rows, fields, values) {
35218
35317
  }
35219
35318
  const row = rows[index];
35220
35319
  const rowName = row.nameWithGranularity;
35221
- const groups = groupBy(dataEntries, row);
35320
+ const groups = groupPivotDataEntriesBy(dataEntries, row);
35222
35321
  const orderedKeys = orderDataEntriesKeys(groups, row);
35223
35322
  const pivotTableRows = [];
35224
35323
  const _fields = fields.concat(rowName);
@@ -35248,7 +35347,7 @@ function dataEntriesToColumnsTree(dataEntries, columns, index) {
35248
35347
  }
35249
35348
  const column = columns[index];
35250
35349
  const colName = columns[index].nameWithGranularity;
35251
- const groups = groupBy(dataEntries, column);
35350
+ const groups = groupPivotDataEntriesBy(dataEntries, column);
35252
35351
  const orderedKeys = orderDataEntriesKeys(groups, columns[index]);
35253
35352
  return orderedKeys.map((value) => {
35254
35353
  return {
@@ -35346,7 +35445,7 @@ function columnsTreeToColumns(mainTree, definition) {
35346
35445
  /**
35347
35446
  * Group the dataEntries based on the given dimension
35348
35447
  */
35349
- function groupBy(dataEntries, dimension) {
35448
+ function groupPivotDataEntriesBy(dataEntries, dimension) {
35350
35449
  return Object.groupBy(dataEntries, keySelector(dimension));
35351
35450
  }
35352
35451
  /**
@@ -35396,7 +35495,7 @@ function createDate(dimension, value, locale) {
35396
35495
  number = Math.floor(date.getMonth() / 3) + 1;
35397
35496
  break;
35398
35497
  case "month_number":
35399
- number = date.getMonth();
35498
+ number = date.getMonth() + 1;
35400
35499
  break;
35401
35500
  case "iso_week_number":
35402
35501
  number = date.getIsoWeek();
@@ -35408,7 +35507,7 @@ function createDate(dimension, value, locale) {
35408
35507
  number = Math.floor(toNumber(value, locale));
35409
35508
  break;
35410
35509
  }
35411
- MAP_VALUE_DIMENSION_DATE[granularity].values[`${value}`] = number;
35510
+ MAP_VALUE_DIMENSION_DATE[granularity].values[`${value}`] = toNormalizedPivotValue(dimension, number);
35412
35511
  }
35413
35512
  return MAP_VALUE_DIMENSION_DATE[granularity].values[`${value}`];
35414
35513
  }
@@ -35554,7 +35653,7 @@ class SpreadsheetPivot {
35554
35653
  return this._definition;
35555
35654
  }
35556
35655
  isValid() {
35557
- if (this.invalidRangeError || !this._definition) {
35656
+ if (this.invalidRangeError || !this.definition) {
35558
35657
  return false;
35559
35658
  }
35560
35659
  for (const measure of this.definition.measures) {
@@ -35611,25 +35710,19 @@ class SpreadsheetPivot {
35611
35710
  const dimension = this.getDimension(lastNode.field);
35612
35711
  const cells = this.filterDataEntriesFromDomain(this.dataEntries, domain);
35613
35712
  const finalCell = cells[0]?.[dimension.nameWithGranularity];
35713
+ if (dimension.type === "date") {
35714
+ const adapter = pivotTimeAdapter(dimension.granularity);
35715
+ return {
35716
+ value: adapter.toCellValue(toNormalizedPivotValue(dimension, lastNode.value)),
35717
+ format: adapter.getFormat(this.getters.getLocale()),
35718
+ };
35719
+ }
35614
35720
  if (!finalCell) {
35615
35721
  return { value: "" };
35616
35722
  }
35617
35723
  if (finalCell.value === null) {
35618
35724
  return { value: _t("(Undefined)") };
35619
35725
  }
35620
- if (dimension.type === "date") {
35621
- if (dimension.granularity === "day") {
35622
- return {
35623
- value: toNumber(finalCell.value, this.getters.getLocale()),
35624
- format: this.getters.getLocale().dateFormat,
35625
- };
35626
- }
35627
- if (dimension.granularity === "month_number") {
35628
- return {
35629
- value: MONTHS[toNumber(finalCell.value, this.getters.getLocale())].toString(),
35630
- };
35631
- }
35632
- }
35633
35726
  return {
35634
35727
  value: finalCell.value,
35635
35728
  format: finalCell.format,
@@ -35654,9 +35747,12 @@ class SpreadsheetPivot {
35654
35747
  format: operator.format(values[0]),
35655
35748
  };
35656
35749
  }
35657
- getPossibleFieldValues(groupBy) {
35658
- //TODO This method should be implemented for the autocomplete feature
35659
- throw new Error("Method not implemented.");
35750
+ getPossibleFieldValues(dimension) {
35751
+ const values = [];
35752
+ for (const value in groupPivotDataEntriesBy(this.dataEntries, dimension)) {
35753
+ values.push({ value, label: "" });
35754
+ }
35755
+ return values;
35660
35756
  }
35661
35757
  getTableStructure() {
35662
35758
  if (!this.isValid()) {
@@ -35676,7 +35772,8 @@ class SpreadsheetPivot {
35676
35772
  filterDataEntriesFromDomainNode(dataEntries, domain) {
35677
35773
  const { field, value } = domain;
35678
35774
  const dimension = this.getDimension(field);
35679
- return dataEntries.filter((entry) => `${entry[dimension.nameWithGranularity]?.value}` === value);
35775
+ return dataEntries.filter((entry) => `${entry[dimension.nameWithGranularity]?.value}` ===
35776
+ `${toNormalizedPivotValue(dimension, value)}`);
35680
35777
  }
35681
35778
  getDimension(nameWithGranularity) {
35682
35779
  return this.definition.getDimension(nameWithGranularity);
@@ -35812,15 +35909,8 @@ pivotRegistry.add("SPREADSHEET", {
35812
35909
 
35813
35910
  class PivotSidePanelStore extends SpreadsheetStore {
35814
35911
  pivotId;
35815
- mutators = [
35816
- "reset",
35817
- "deferUpdates",
35818
- "applyUpdate",
35819
- "discardPendingUpdate",
35820
- "renamePivot",
35821
- "update",
35822
- ];
35823
- updatesAreDeferred = true;
35912
+ mutators = ["reset", "deferUpdates", "applyUpdate", "discardPendingUpdate", "update"];
35913
+ updatesAreDeferred = false;
35824
35914
  draft = null;
35825
35915
  constructor(get, pivotId) {
35826
35916
  super(get);
@@ -35937,16 +36027,6 @@ class PivotSidePanelStore extends SpreadsheetStore {
35937
36027
  discardPendingUpdate() {
35938
36028
  this.draft = null;
35939
36029
  }
35940
- renamePivot(name) {
35941
- const pivot = this.getters.getPivotCoreDefinition(this.pivotId);
35942
- this.model.dispatch("UPDATE_PIVOT", {
35943
- pivotId: this.pivotId,
35944
- pivot: {
35945
- ...pivot,
35946
- name,
35947
- },
35948
- });
35949
- }
35950
36030
  update(definitionUpdate) {
35951
36031
  const coreDefinition = this.getters.getPivotCoreDefinition(this.pivotId);
35952
36032
  const definition = { ...coreDefinition, ...this.draft, ...definitionUpdate };
@@ -36029,9 +36109,9 @@ class PivotSpreadsheetSidePanel extends Component {
36029
36109
  PivotLayoutConfigurator,
36030
36110
  Section,
36031
36111
  SelectionInput,
36032
- EditableName,
36033
36112
  Checkbox,
36034
36113
  PivotDeferUpdate,
36114
+ PivotTitleSection,
36035
36115
  };
36036
36116
  store;
36037
36117
  state;
@@ -36060,12 +36140,6 @@ class PivotSpreadsheetSidePanel extends Component {
36060
36140
  get pivot() {
36061
36141
  return this.store.pivot;
36062
36142
  }
36063
- get name() {
36064
- return this.env.model.getters.getPivotName(this.props.pivotId);
36065
- }
36066
- get displayName() {
36067
- return this.env.model.getters.getPivotDisplayName(this.props.pivotId);
36068
- }
36069
36143
  get definition() {
36070
36144
  return this.store.definition;
36071
36145
  }
@@ -36089,35 +36163,9 @@ class PivotSpreadsheetSidePanel extends Component {
36089
36163
  this.store.applyUpdate();
36090
36164
  }
36091
36165
  }
36092
- duplicatePivot() {
36093
- const newPivotId = this.env.model.uuidGenerator.uuidv4();
36094
- const result = this.env.model.dispatch("DUPLICATE_PIVOT", {
36095
- pivotId: this.props.pivotId,
36096
- newPivotId,
36097
- });
36098
- const text = result.isSuccessful ? _t("Pivot duplicated.") : _t("Pivot duplication failed");
36099
- const type = result.isSuccessful ? "success" : "danger";
36100
- this.env.notifyUser({
36101
- text,
36102
- sticky: false,
36103
- type,
36104
- });
36105
- if (result.isSuccessful) {
36106
- this.env.openSidePanel("PivotSidePanel", { pivotId: newPivotId });
36107
- }
36108
- }
36109
- onNameChanged(name) {
36110
- this.store.renamePivot(name);
36111
- }
36112
36166
  onDimensionsUpdated(definition) {
36113
36167
  this.store.update(definition);
36114
36168
  }
36115
- back() {
36116
- this.env.openSidePanel("PivotSidePanel", {});
36117
- }
36118
- delete() {
36119
- this.env.model.dispatch("REMOVE_PIVOT", { pivotId: this.props.pivotId });
36120
- }
36121
36169
  }
36122
36170
 
36123
36171
  const pivotSidePanelRegistry = new Registry();
@@ -36125,44 +36173,17 @@ pivotSidePanelRegistry.add("SPREADSHEET", {
36125
36173
  editor: PivotSpreadsheetSidePanel,
36126
36174
  });
36127
36175
 
36128
- css /* scss */ `
36129
- .o_pivot_list_item {
36130
- cursor: pointer;
36131
- &:hover {
36132
- background-color: #f1f3f4;
36133
- }
36134
- }
36135
- `;
36136
- class PivotListItem extends Component {
36137
- static template = "o-spreadsheet-PivotListItem";
36138
- static props = { pivotId: String };
36139
- setup() {
36140
- const previewRef = useRef("pivotListItem");
36141
- useHighlightsOnHover(previewRef, this);
36142
- }
36143
- selectPivot() {
36144
- this.env.openSidePanel("PivotSidePanel", { pivotId: this.props.pivotId });
36145
- }
36146
- get highlights() {
36147
- return getPivotHighlights(this.env.model.getters, this.props.pivotId);
36148
- }
36149
- }
36150
-
36151
36176
  class PivotSidePanel extends Component {
36152
36177
  static template = "o-spreadsheet-PivotSidePanel";
36153
36178
  static props = {
36154
- pivotId: { type: String, optional: true },
36179
+ pivotId: String,
36155
36180
  onCloseSidePanel: Function,
36156
36181
  };
36157
36182
  static components = {
36158
36183
  PivotLayoutConfigurator,
36159
36184
  Section,
36160
- PivotListItem,
36161
36185
  };
36162
36186
  get sidePanelEditor() {
36163
- if (!this.props.pivotId) {
36164
- throw new Error("pivotId is required to call this function.");
36165
- }
36166
36187
  const pivot = this.env.model.getters.getPivotCoreDefinition(this.props.pivotId);
36167
36188
  if (!pivot) {
36168
36189
  throw new Error("pivotId does not correspond to a pivot.");
@@ -36179,6 +36200,7 @@ css /* scss */ `
36179
36200
  class RemoveDuplicatesPanel extends Component {
36180
36201
  static template = "o-spreadsheet-RemoveDuplicatesPanel";
36181
36202
  static components = { ValidationMessages, Section, Checkbox };
36203
+ static props = { onCloseSidePanel: Function };
36182
36204
  state = useState({
36183
36205
  hasHeader: false,
36184
36206
  columns: {},
@@ -37321,21 +37343,15 @@ sidePanelRegistry.add("TableStyleEditorPanel", {
37321
37343
  });
37322
37344
  sidePanelRegistry.add("PivotSidePanel", {
37323
37345
  title: (env, props) => {
37324
- if (props.pivotId) {
37325
- return _t("Pivot #%s", env.model.getters.getPivotFormulaId(props.pivotId));
37326
- }
37327
- return _t("List of Pivots");
37346
+ return _t("Pivot #%s", env.model.getters.getPivotFormulaId(props.pivotId));
37328
37347
  },
37329
37348
  Body: PivotSidePanel,
37330
- computeState: (getters, initialProps) => {
37331
- if (!getters.getPivotIds().length) {
37332
- return { isOpen: false };
37333
- }
37334
- let { pivotId } = initialProps;
37335
- if (pivotId && !getters.isExistingPivot(pivotId)) {
37336
- pivotId = undefined;
37337
- }
37338
- return { isOpen: true, props: { pivotId }, key: `pivot_key_${pivotId}` };
37349
+ computeState: (getters, props) => {
37350
+ return {
37351
+ isOpen: getters.isExistingPivot(props.pivotId),
37352
+ props,
37353
+ key: `pivot_key_${props.pivotId}`,
37354
+ };
37339
37355
  },
37340
37356
  });
37341
37357
 
@@ -41593,133 +41609,6 @@ class Grid extends Component {
41593
41609
  }
41594
41610
  }
41595
41611
 
41596
- const pivotTimeAdapterRegistry = new Registry();
41597
- function pivotTimeAdapter(granularity) {
41598
- return pivotTimeAdapterRegistry.get(granularity);
41599
- }
41600
- /**
41601
- * The Time Adapter: Managing Time Periods for Pivot Functions
41602
- *
41603
- * Overview:
41604
- * A time adapter is responsible for managing time periods associated with pivot functions.
41605
- * Each type of period (day, week, month, quarter, etc.) has its own dedicated adapter.
41606
- * The adapter's primary role is to normalize period values between spreadsheet functions,
41607
- * and the pivot.
41608
- * By normalizing the period value, it can be stored consistently in the pivot.
41609
- *
41610
- * Normalization Process:
41611
- * When working with functions in the spreadsheet, the time adapter normalizes
41612
- * the provided period to facilitate accurate lookup of values in the pivot.
41613
- * For instance, if the spreadsheet function represents a day period as a number generated
41614
- * by the DATE function (DATE(2023, 12, 25)), the time adapter will normalize it accordingly.
41615
- *
41616
- */
41617
- /**
41618
- * Normalized value: "12/25/2023"
41619
- *
41620
- * Note: Those two format are equivalent:
41621
- * - "MM/dd/yyyy" (luxon format)
41622
- * - "mm/dd/yyyy" (spreadsheet format)
41623
- **/
41624
- const dayAdapter = {
41625
- normalizeFunctionValue(value) {
41626
- const date = toNumber(value, DEFAULT_LOCALE);
41627
- return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/dd/yyyy" });
41628
- },
41629
- getFormat(locale) {
41630
- return (locale ?? DEFAULT_LOCALE).dateFormat;
41631
- },
41632
- formatValue(normalizedValue, locale) {
41633
- locale = locale ?? DEFAULT_LOCALE;
41634
- const value = toNumber(normalizedValue, DEFAULT_LOCALE);
41635
- return formatValue(value, { locale, format: this.getFormat(locale) });
41636
- },
41637
- toCellValue(normalizedValue) {
41638
- return toNumber(normalizedValue, DEFAULT_LOCALE);
41639
- },
41640
- };
41641
- /**
41642
- * Normalized value: "2/2023" for week 2 of 2023
41643
- */
41644
- const weekAdapter = {
41645
- normalizeFunctionValue(value) {
41646
- const [week, year] = value.split("/");
41647
- return `${Number(week)}/${Number(year)}`;
41648
- },
41649
- getFormat() {
41650
- return undefined;
41651
- },
41652
- formatValue(normalizedValue) {
41653
- const [week, year] = normalizedValue.split("/");
41654
- return _t("W%(week)s %(year)s", { week, year });
41655
- },
41656
- toCellValue(normalizedValue) {
41657
- return this.formatValue(normalizedValue);
41658
- },
41659
- };
41660
- /**
41661
- * normalized month value is a string formatted as "MM/yyyy" (luxon format)
41662
- * e.g. "01/2020" for January 2020
41663
- */
41664
- const monthAdapter = {
41665
- normalizeFunctionValue(value) {
41666
- const date = toNumber(value, DEFAULT_LOCALE);
41667
- return formatValue(date, { locale: DEFAULT_LOCALE, format: "mm/yyyy" });
41668
- },
41669
- getFormat() {
41670
- return "mmmm yyyy";
41671
- },
41672
- formatValue(normalizedValue, locale) {
41673
- locale = locale ?? DEFAULT_LOCALE;
41674
- const value = toNumber(normalizedValue, DEFAULT_LOCALE);
41675
- return formatValue(value, { locale, format: this.getFormat(locale) });
41676
- },
41677
- toCellValue(normalizedValue) {
41678
- return toNumber(normalizedValue, DEFAULT_LOCALE);
41679
- },
41680
- };
41681
- /**
41682
- * normalized quarter value is "quarter/year"
41683
- * e.g. "1/2020" for Q1 2020
41684
- */
41685
- const quarterAdapter = {
41686
- normalizeFunctionValue(value) {
41687
- const [quarter, year] = value.split("/");
41688
- return `${quarter}/${year}`;
41689
- },
41690
- getFormat() {
41691
- return undefined;
41692
- },
41693
- formatValue(normalizedValue) {
41694
- const [quarter, year] = normalizedValue.split("/");
41695
- return _t("Q%(quarter)s %(year)s", { quarter, year });
41696
- },
41697
- toCellValue(normalizedValue) {
41698
- return this.formatValue(normalizedValue);
41699
- },
41700
- };
41701
- const yearAdapter = {
41702
- normalizeFunctionValue(value) {
41703
- return toNumber(value, DEFAULT_LOCALE);
41704
- },
41705
- getFormat() {
41706
- return "0";
41707
- },
41708
- formatValue(normalizedValue, locale) {
41709
- locale = locale ?? DEFAULT_LOCALE;
41710
- return formatValue(normalizedValue, { locale, format: "0" });
41711
- },
41712
- toCellValue(normalizedValue) {
41713
- return normalizedValue;
41714
- },
41715
- };
41716
- pivotTimeAdapterRegistry
41717
- .add("day", dayAdapter)
41718
- .add("week", weekAdapter)
41719
- .add("month", monthAdapter)
41720
- .add("quarter", quarterAdapter)
41721
- .add("year", yearAdapter);
41722
-
41723
41612
  /**
41724
41613
  * Represent a raw XML string
41725
41614
  */
@@ -46918,9 +46807,14 @@ class CellPlugin extends CorePlugin {
46918
46807
  }
46919
46808
  createLiteralCell(id, content, format, style) {
46920
46809
  const locale = this.getters.getLocale();
46921
- format = format || detectDateFormat(content, locale) || detectNumberFormat(content);
46810
+ const parsedValue = parseLiteral(content, locale);
46811
+ format =
46812
+ format ||
46813
+ (typeof parsedValue === "number"
46814
+ ? detectDateFormat(content, locale) || detectNumberFormat(content)
46815
+ : undefined);
46922
46816
  if (format !== PLAIN_TEXT_FORMAT && !isEvaluationError(content)) {
46923
- content = toString(parseLiteral(content, locale));
46817
+ content = toString(parsedValue);
46924
46818
  }
46925
46819
  return {
46926
46820
  id,
@@ -46928,6 +46822,7 @@ class CellPlugin extends CorePlugin {
46928
46822
  style,
46929
46823
  format,
46930
46824
  isFormula: false,
46825
+ parsedValue,
46931
46826
  };
46932
46827
  }
46933
46828
  createFormulaCell(id, content, format, style, sheetId) {
@@ -51670,6 +51565,9 @@ class PositionMap {
51670
51565
  get({ sheetId, col, row }) {
51671
51566
  return this.map[sheetId]?.[col]?.[row];
51672
51567
  }
51568
+ getSheet(sheetId) {
51569
+ return this.map[sheetId];
51570
+ }
51673
51571
  has({ sheetId, col, row }) {
51674
51572
  return this.map[sheetId]?.[col]?.[row] !== undefined;
51675
51573
  }
@@ -51688,6 +51586,19 @@ class PositionMap {
51688
51586
  }
51689
51587
  return keys;
51690
51588
  }
51589
+ keysForSheet(sheetId) {
51590
+ const map = this.map[sheetId];
51591
+ if (!map) {
51592
+ return [];
51593
+ }
51594
+ const keys = [];
51595
+ for (const col in map) {
51596
+ for (const row in map[col]) {
51597
+ keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
51598
+ }
51599
+ }
51600
+ return keys;
51601
+ }
51691
51602
  }
51692
51603
 
51693
51604
  function quickselect(arr, k, left, right, compare) {
@@ -52766,6 +52677,9 @@ class Evaluator {
52766
52677
  getEvaluatedPositions() {
52767
52678
  return this.evaluatedCells.keys();
52768
52679
  }
52680
+ getEvaluatedPositionsInSheet(sheetId) {
52681
+ return this.evaluatedCells.keysForSheet(sheetId);
52682
+ }
52769
52683
  getArrayFormulaSpreadingOn(position) {
52770
52684
  if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
52771
52685
  return this.spreadingRelations.isArrayFormula(position) ? position : undefined;
@@ -52774,6 +52688,9 @@ class Evaluator {
52774
52688
  return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
52775
52689
  }
52776
52690
  updateDependencies(position) {
52691
+ // removing dependencies is slow because it requires
52692
+ // to traverse the entire r-tree.
52693
+ // The data structure is optimized for searches the other way around
52777
52694
  this.formulaDependencies().removeAllDependencies(position);
52778
52695
  const dependencies = this.getDirectDependencies(position);
52779
52696
  this.formulaDependencies().addDependencies(position, dependencies);
@@ -52939,7 +52856,7 @@ class Evaluator {
52939
52856
  this.cellsBeingComputed.add(cellId);
52940
52857
  return cell.isFormula
52941
52858
  ? this.computeFormulaCell(position.sheetId, cell)
52942
- : evaluateLiteral(cell.content, localeFormat);
52859
+ : evaluateLiteral(cell, localeFormat);
52943
52860
  }
52944
52861
  catch (e) {
52945
52862
  e.value = e?.value || CellErrorType.GenericError;
@@ -53209,6 +53126,7 @@ class EvaluationPlugin extends UIPlugin {
53209
53126
  "getEvaluatedCell",
53210
53127
  "getEvaluatedCells",
53211
53128
  "getEvaluatedCellsInZone",
53129
+ "getEvaluatedCellsPositions",
53212
53130
  "getSpreadZone",
53213
53131
  "getArrayFormulaSpreadingOn",
53214
53132
  "isEmpty",
@@ -53300,13 +53218,12 @@ class EvaluationPlugin extends UIPlugin {
53300
53218
  return this.evaluator.getEvaluatedCell(position);
53301
53219
  }
53302
53220
  getEvaluatedCells(sheetId) {
53303
- const rawCells = this.getters.getCells(sheetId) || {};
53304
- const record = {};
53305
- for (let cellId of Object.keys(rawCells)) {
53306
- const position = this.getters.getCellPosition(cellId);
53307
- record[cellId] = this.getEvaluatedCell(position);
53308
- }
53309
- return record;
53221
+ return this.evaluator
53222
+ .getEvaluatedPositionsInSheet(sheetId)
53223
+ .map((position) => this.getEvaluatedCell(position));
53224
+ }
53225
+ getEvaluatedCellsPositions(sheetId) {
53226
+ return this.evaluator.getEvaluatedPositionsInSheet(sheetId);
53310
53227
  }
53311
53228
  getEvaluatedCellsInZone(sheetId, zone) {
53312
53229
  return positions(zone).map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId, col, row }));
@@ -55974,7 +55891,10 @@ class Session extends EventBus {
55974
55891
  /**
55975
55892
  * Notify the server that the user client left the collaborative session
55976
55893
  */
55977
- leave() {
55894
+ leave(data) {
55895
+ if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
55896
+ this.snapshot(data);
55897
+ }
55978
55898
  delete this.clients[this.clientId];
55979
55899
  this.transportService.leave(this.clientId);
55980
55900
  this.transportService.sendMessage({
@@ -56388,7 +56308,7 @@ class DataCleanupPlugin extends UIPlugin {
56388
56308
  bottom: rowIndex,
56389
56309
  }));
56390
56310
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
56391
- const data = handler.copy(getClipboardDataPositions(rowsToKeep));
56311
+ const data = handler.copy(getClipboardDataPositions(sheetId, rowsToKeep));
56392
56312
  if (!data) {
56393
56313
  return;
56394
56314
  }
@@ -56401,7 +56321,7 @@ class DataCleanupPlugin extends UIPlugin {
56401
56321
  right: zone.left,
56402
56322
  bottom: zone.top,
56403
56323
  };
56404
- handler.paste({ zones: [zonePasted] }, data, { isCutOperation: false });
56324
+ handler.paste({ zones: [zonePasted], sheetId }, data, { isCutOperation: false });
56405
56325
  const remainingZone = {
56406
56326
  left: zone.left,
56407
56327
  top: zone.top - (hasHeader ? 1 : 0),
@@ -58275,12 +58195,14 @@ class ClipboardPlugin extends UIPlugin {
58275
58195
  }
58276
58196
  let zone = undefined;
58277
58197
  let selectedZones = [];
58198
+ const sheetId = this.getters.getActiveSheetId();
58278
58199
  let target = {
58200
+ sheetId,
58279
58201
  zones,
58280
58202
  };
58281
58203
  const handlers = this.selectClipboardHandlers(copiedData);
58282
58204
  for (const handler of handlers) {
58283
- const currentTarget = handler.getPasteTarget(zones, copiedData, options);
58205
+ const currentTarget = handler.getPasteTarget(sheetId, zones, copiedData, options);
58284
58206
  if (currentTarget.figureId) {
58285
58207
  target.figureId = currentTarget.figureId;
58286
58208
  }
@@ -58449,11 +58371,12 @@ class ClipboardPlugin extends UIPlugin {
58449
58371
  return { cut: [cut], paste: [paste] };
58450
58372
  }
58451
58373
  getClipboardData(zones) {
58374
+ const sheetId = this.getters.getActiveSheetId();
58452
58375
  const selectedFigureId = this.getters.getSelectedFigureId();
58453
58376
  if (selectedFigureId) {
58454
- return { figureId: selectedFigureId };
58377
+ return { figureId: selectedFigureId, sheetId };
58455
58378
  }
58456
- return getClipboardDataPositions(zones);
58379
+ return getClipboardDataPositions(sheetId, zones);
58457
58380
  }
58458
58381
  // ---------------------------------------------------------------------------
58459
58382
  // Grid rendering
@@ -59119,8 +59042,9 @@ class GridSelectionPlugin extends UIPlugin {
59119
59042
  bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
59120
59043
  },
59121
59044
  ];
59045
+ const sheetId = this.getActiveSheetId();
59122
59046
  const handler = new CellClipboardHandler(this.getters, this.dispatch);
59123
- const data = handler.copy(getClipboardDataPositions(target));
59047
+ const data = handler.copy(getClipboardDataPositions(sheetId, target));
59124
59048
  if (!data) {
59125
59049
  return;
59126
59050
  }
@@ -59133,7 +59057,7 @@ class GridSelectionPlugin extends UIPlugin {
59133
59057
  bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
59134
59058
  },
59135
59059
  ];
59136
- handler.paste({ zones: pasteTarget }, data, { isCutOperation: true });
59060
+ handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
59137
59061
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
59138
59062
  let currentIndex = cmd.base;
59139
59063
  for (const element of toRemove) {
@@ -66497,7 +66421,7 @@ class Model extends EventBus {
66497
66421
  this.session.join(this.config.client);
66498
66422
  }
66499
66423
  leaveSession() {
66500
- this.session.leave();
66424
+ this.session.leave(this.exportData());
66501
66425
  }
66502
66426
  setupUiPlugin(Plugin) {
66503
66427
  const plugin = new Plugin(this.uiPluginConfig);
@@ -66904,7 +66828,8 @@ const registries = {
66904
66828
  pivotRegistry,
66905
66829
  pivotTimeAdapterRegistry,
66906
66830
  pivotSidePanelRegistry,
66907
- supportedPivotExplodedFormulaRegistry,
66831
+ pivotNormalizationValueRegistry,
66832
+ supportedPivotPositionalFormulaRegistry,
66908
66833
  };
66909
66834
  const helpers = {
66910
66835
  arg,
@@ -66913,6 +66838,7 @@ const helpers = {
66913
66838
  toJsDate,
66914
66839
  toNumber,
66915
66840
  toString,
66841
+ toNormalizedPivotValue,
66916
66842
  toXC,
66917
66843
  toZone,
66918
66844
  toUnboundedZone,
@@ -67008,6 +66934,8 @@ const components = {
67008
66934
  PivotLayoutConfigurator,
67009
66935
  EditableName,
67010
66936
  PivotDeferUpdate,
66937
+ PivotTitleSection,
66938
+ CogWheelMenu,
67011
66939
  };
67012
66940
  const hooks = {
67013
66941
  useDragAndDropListItems,
@@ -67048,6 +66976,6 @@ const constants = {
67048
66976
  export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, PivotRuntimeDefinition, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
67049
66977
 
67050
66978
 
67051
- __info__.version = "17.4.0-alpha.3";
67052
- __info__.date = "2024-06-10T09:38:53.982Z";
67053
- __info__.hash = "a45ed6a";
66979
+ __info__.version = "17.4.0-alpha.4";
66980
+ __info__.date = "2024-06-12T14:00:22.046Z";
66981
+ __info__.hash = "cefb0e4";