@odoo/o-spreadsheet 16.5.0-alpha.7 → 16.5.0-alpha.8

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.
@@ -1,3 +1,12 @@
1
+
2
+ /**
3
+ * This file is generated by o-spreadsheet build tools. Do not edit it.
4
+ * @see https://github.com/odoo/o-spreadsheet
5
+ * @version 16.5.0-alpha.8
6
+ * @date 2023-09-21T15:59:10.959Z
7
+ * @hash 0b7527d
8
+ */
9
+
1
10
  import { Component, useRef, onMounted, onPatched, onWillPatch, useState, onWillUpdateProps, useComponent, useEffect, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
2
11
 
3
12
  // define a mock translation function, when o-spreadsheet runs in standalone it doesn't translate any string
@@ -231,13 +240,26 @@ const MENU_ITEM_PADDING_HORIZONTAL = 11;
231
240
  const MENU_ITEM_PADDING_VERTICAL = 4;
232
241
  const MENU_SEPARATOR_BORDER_WIDTH = 1;
233
242
  const MENU_SEPARATOR_PADDING = 5;
243
+ // Style
244
+ const DEFAULT_STYLE = {
245
+ align: "left",
246
+ verticalAlign: "bottom",
247
+ wrapping: "overflow",
248
+ bold: false,
249
+ italic: false,
250
+ strikethrough: false,
251
+ underline: false,
252
+ fontSize: 10,
253
+ fillColor: "",
254
+ textColor: "#000000",
255
+ };
256
+ const DEFAULT_VERTICAL_ALIGN = DEFAULT_STYLE.verticalAlign;
257
+ const DEFAULT_WRAPPING_MODE = DEFAULT_STYLE.wrapping;
234
258
  // Fonts
235
259
  const DEFAULT_FONT_WEIGHT = "400";
236
- const DEFAULT_FONT_SIZE = 10;
260
+ const DEFAULT_FONT_SIZE = DEFAULT_STYLE.fontSize;
237
261
  const HEADER_FONT_SIZE = 11;
238
262
  const DEFAULT_FONT = "'Roboto', arial";
239
- const DEFAULT_VERTICAL_ALIGN = "bottom";
240
- const DEFAULT_WRAPPING_MODE = "overflow";
241
263
  // Borders
242
264
  const DEFAULT_BORDER_DESC = { style: "thin", color: "#000000" };
243
265
  const DEFAULT_FILTER_BORDER_DESC = { style: "thin", color: FILTERS_COLOR };
@@ -615,13 +637,17 @@ function getAddHeaderStartIndex(position, base) {
615
637
  return position === "after" ? base + 1 : base;
616
638
  }
617
639
  /**
618
- * Compare two objects.
640
+ * Compares two objects.
619
641
  */
620
642
  function deepEquals(o1, o2) {
621
643
  if (o1 === o2)
622
644
  return true;
623
645
  if ((o1 && !o2) || (o2 && !o1))
624
646
  return false;
647
+ if (typeof o1 !== typeof o2)
648
+ return false;
649
+ if (typeof o1 !== "object")
650
+ return o1 === o2;
625
651
  // Objects can have different keys if the values are undefined
626
652
  const keys = new Set();
627
653
  Object.keys(o1).forEach((key) => keys.add(key));
@@ -737,6 +763,10 @@ function insertItemsAtIndex(array, items, index) {
737
763
  newArray.splice(index, 0, ...items);
738
764
  return newArray;
739
765
  }
766
+ function trimContent(content) {
767
+ const contentLines = content.split("\n");
768
+ return contentLines.map((line) => line.replace(/\s+/g, " ").trim()).join("\n");
769
+ }
740
770
 
741
771
  const RBA_REGEX = /rgba?\(|\s+|\)/gi;
742
772
  const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/;
@@ -4403,6 +4433,16 @@ function toNumber(value, locale) {
4403
4433
  return 0;
4404
4434
  }
4405
4435
  }
4436
+ function tryCastAsNumberMatrix(data, argName) {
4437
+ data.forEach((row) => {
4438
+ row.forEach((cell) => {
4439
+ if (typeof cell !== "number") {
4440
+ throw new Error(_t("Function [[FUNCTION_NAME]] expects number values for %s, but got a %s.", typeof cell, argName));
4441
+ }
4442
+ });
4443
+ });
4444
+ return data;
4445
+ }
4406
4446
  function strictToNumber(value, locale) {
4407
4447
  if (value === "") {
4408
4448
  throw new Error(expectNumberValueError(value));
@@ -5347,6 +5387,7 @@ css /* scss */ `
5347
5387
  padding: 10px;
5348
5388
  width: ${ERROR_TOOLTIP_WIDTH}px;
5349
5389
  box-sizing: border-box !important;
5390
+ overflow-wrap: break-word;
5350
5391
  }
5351
5392
  `;
5352
5393
  class ErrorToolTip extends Component {
@@ -8352,43 +8393,53 @@ var math = /*#__PURE__*/Object.freeze({
8352
8393
  TRUNC: TRUNC
8353
8394
  });
8354
8395
 
8355
- // Note: dataY and dataX may not have the same dimension
8356
- function covariance(dataY, dataX, isSample) {
8357
- let flatDataY = [];
8358
- let flatDataX = [];
8396
+ function assertSameNumberOfElements(...args) {
8397
+ const dims = args[0].length;
8398
+ args.forEach((arg, i) => assert(() => arg.length === dims, _t("[[FUNCTION_NAME]] has mismatched dimensions for argument %s (%s vs %s).", i.toString(), dims.toString(), arg.length.toString())));
8399
+ }
8400
+
8401
+ function filterAndFlatData(dataY, dataX) {
8402
+ const _flatDataY = [];
8403
+ const _flatDataX = [];
8359
8404
  let lenY = 0;
8360
8405
  let lenX = 0;
8361
8406
  visitAny([dataY], (y) => {
8362
- flatDataY.push(y);
8407
+ _flatDataY.push(y);
8363
8408
  lenY += 1;
8364
8409
  });
8365
8410
  visitAny([dataX], (x) => {
8366
- flatDataX.push(x);
8411
+ _flatDataX.push(x);
8367
8412
  lenX += 1;
8368
8413
  });
8369
- assert(() => lenY === lenX, _t("[[FUNCTION_NAME]] has mismatched argument count %s vs %s.", lenY.toString(), lenX.toString()));
8370
- let count = 0;
8371
- let sumY = 0;
8372
- let sumX = 0;
8414
+ assert(() => lenY === lenX, _t("[[FUNCTION_NAME]] has mismatched argument count %s vs %s.", lenY, lenX));
8415
+ const flatDataX = [];
8416
+ const flatDataY = [];
8373
8417
  for (let i = 0; i < lenY; i++) {
8374
- const valueY = flatDataY[i];
8375
- const valueX = flatDataX[i];
8418
+ const valueY = _flatDataY[i];
8419
+ const valueX = _flatDataX[i];
8376
8420
  if (typeof valueY === "number" && typeof valueX === "number") {
8377
- count += 1;
8378
- sumY += valueY;
8379
- sumX += valueX;
8421
+ flatDataY.push(valueY);
8422
+ flatDataX.push(valueX);
8380
8423
  }
8381
8424
  }
8425
+ return { flatDataX, flatDataY };
8426
+ }
8427
+ // Note: dataY and dataX may not have the same dimension
8428
+ function covariance(dataY, dataX, isSample) {
8429
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
8430
+ const count = flatDataY.length;
8382
8431
  assert(() => count !== 0 && (!isSample || count !== 1), _t(`Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error.`));
8432
+ let sumY = 0;
8433
+ let sumX = 0;
8434
+ for (let i = 0; i < count; i++) {
8435
+ sumY += flatDataY[i];
8436
+ sumX += flatDataX[i];
8437
+ }
8383
8438
  const averageY = sumY / count;
8384
8439
  const averageX = sumX / count;
8385
8440
  let acc = 0;
8386
- for (let i = 0; i < lenY; i++) {
8387
- const valueY = flatDataY[i];
8388
- const valueX = flatDataX[i];
8389
- if (typeof valueY === "number" && typeof valueX === "number") {
8390
- acc += (valueY - averageY) * (valueX - averageX);
8391
- }
8441
+ for (let i = 0; i < count; i++) {
8442
+ acc += (flatDataY[i] - averageY) * (flatDataX[i] - averageX);
8392
8443
  }
8393
8444
  return acc / (count - (isSample ? 1 : 0));
8394
8445
  }
@@ -8425,6 +8476,161 @@ function centile(data, percent, isInclusive, locale) {
8425
8476
  }
8426
8477
  return percentile(sortedArray, _percent, isInclusive);
8427
8478
  }
8479
+ function prepareDataForRegression(X, Y, newX) {
8480
+ const _X = X.length ? X : [range(1, Y.flat().length + 1)];
8481
+ const nVar = _X.length;
8482
+ let _newX = newX.length ? newX : _X;
8483
+ _newX = _newX.length === nVar ? transposeMatrix(_newX) : _newX;
8484
+ return { _X, _newX };
8485
+ }
8486
+ /*
8487
+ * This function performs a linear regression on the data set. It returns an array with two elements.
8488
+ * The first element is the slope, and the second element is the intercept.
8489
+ * The linear regression line is: y = slope*x + intercept
8490
+ * The function use the least squares method to find the best fit for the data set :
8491
+ * see https://www.mathsisfun.com/data/least-squares-regression.html
8492
+ * https://www.statology.org/standard-error-of-estimate/
8493
+ * https://agronomy4future.org/?p=16670
8494
+ * https://vitalflux.com/interpreting-f-statistics-in-linear-regression-formula-examples/
8495
+ * https://web.ist.utl.pt/~ist11038/compute/errtheory/,regression/regrthroughorigin.pdf
8496
+ */
8497
+ function fullLinearRegression(X, Y, computeIntercept = true, verbose = false) {
8498
+ const y = Y.flat();
8499
+ const n = y.length;
8500
+ let { _X } = prepareDataForRegression(X, Y, []);
8501
+ _X = _X.length === n ? transposeMatrix(_X) : _X.slice();
8502
+ assertSameNumberOfElements(_X[0], y);
8503
+ const nVar = _X.length;
8504
+ const nDeg = n - nVar - (computeIntercept ? 1 : 0);
8505
+ const yMatrix = [y];
8506
+ const xMatrix = transposeMatrix(_X.reverse());
8507
+ let avgX = [];
8508
+ for (let i = 0; i < nVar; i++) {
8509
+ avgX.push(0);
8510
+ if (computeIntercept) {
8511
+ for (const xij of _X[i]) {
8512
+ avgX[i] += xij;
8513
+ }
8514
+ avgX[i] /= n;
8515
+ }
8516
+ }
8517
+ let avgY = 0;
8518
+ if (computeIntercept) {
8519
+ for (const yi of y) {
8520
+ avgY += yi;
8521
+ }
8522
+ avgY /= n;
8523
+ }
8524
+ const redX = xMatrix.map((row) => row.map((value, i) => value - avgX[i]));
8525
+ if (computeIntercept) {
8526
+ xMatrix.forEach((row) => row.push(1));
8527
+ }
8528
+ const coeffs = getLMSCoefficients(xMatrix, yMatrix);
8529
+ if (!computeIntercept) {
8530
+ coeffs.push([0]);
8531
+ }
8532
+ if (!verbose) {
8533
+ return coeffs;
8534
+ }
8535
+ const dot1 = multiplyMatrices(redX, transposeMatrix(redX));
8536
+ const { inverted: dotInv } = invertMatrix(dot1);
8537
+ if (dotInv === undefined) {
8538
+ throw new Error(_t("Matrix is not invertible"));
8539
+ }
8540
+ let SSE = 0, SSR = 0;
8541
+ for (let i = 0; i < n; i++) {
8542
+ const yi = y[i] - avgY;
8543
+ let temp = 0;
8544
+ for (let j = 0; j < nVar; j++) {
8545
+ const xi = redX[i][j];
8546
+ temp += xi * coeffs[j][0];
8547
+ }
8548
+ const ei = yi - temp;
8549
+ SSE += ei * ei;
8550
+ SSR += temp * temp;
8551
+ }
8552
+ const RMSE = Math.sqrt(SSE / nDeg);
8553
+ const r2 = SSR / (SSR + SSE);
8554
+ const f_stat = SSR / nVar / (SSE / nDeg);
8555
+ const deltaCoeffs = [];
8556
+ for (let i = 0; i < nVar; i++) {
8557
+ deltaCoeffs.push(RMSE * Math.sqrt(dotInv[i][i]));
8558
+ }
8559
+ if (computeIntercept) {
8560
+ const dot2 = multiplyMatrices(dotInv, [avgX]);
8561
+ const dot3 = multiplyMatrices(transposeMatrix([avgX]), dot2);
8562
+ deltaCoeffs.push(RMSE * Math.sqrt(dot3[0][0] + 1 / y.length));
8563
+ }
8564
+ const returned = [
8565
+ [coeffs[0][0], deltaCoeffs[0], r2, f_stat, SSR],
8566
+ [coeffs[1][0], deltaCoeffs[1], RMSE, nDeg, SSE],
8567
+ ];
8568
+ for (let i = 2; i < nVar; i++) {
8569
+ returned.push([coeffs[i][0], deltaCoeffs[i], "", "", ""]);
8570
+ }
8571
+ if (computeIntercept) {
8572
+ returned.push([coeffs[nVar][0], deltaCoeffs[nVar], "", "", ""]);
8573
+ }
8574
+ else {
8575
+ returned.push([0, "", "", "", ""]);
8576
+ }
8577
+ return returned;
8578
+ }
8579
+ /*
8580
+ This function performs a polynomial regression on the data set. It returns the coefficients of
8581
+ the polynomial function that best fits the data set.
8582
+ The polynomial function is: y = c0 + c1*x + c2*x^2 + ... + cn*x^n, where n is the order (degree)
8583
+ of the polynomial. The returned coefficients are then in the form: [c0, c1, c2, ..., cn]
8584
+ The function is based on the method of least squares :
8585
+ see: https://mathworld.wolfram.com/LeastSquaresFittingPolynomial.html
8586
+ */
8587
+ function polynomialRegression(flatY, flatX, order, intercept) {
8588
+ assertSameNumberOfElements(flatX, flatY);
8589
+ assert(() => order >= 1, _t(`Function [[FUNCTION_NAME]] A regression of order less than 1 cannot be possible.`));
8590
+ const yMatrix = [flatY];
8591
+ const xMatrix = flatX.map((x) => range(0, order).map((i) => Math.pow(x, order - i)));
8592
+ if (intercept) {
8593
+ xMatrix.forEach((row) => row.push(1));
8594
+ }
8595
+ const coeffs = getLMSCoefficients(xMatrix, yMatrix);
8596
+ if (!intercept) {
8597
+ coeffs.push([0]);
8598
+ }
8599
+ return coeffs;
8600
+ }
8601
+ function getLMSCoefficients(xMatrix, yMatrix) {
8602
+ const xMatrixT = transposeMatrix(xMatrix);
8603
+ const dot1 = multiplyMatrices(xMatrix, xMatrixT);
8604
+ const { inverted: dotInv } = invertMatrix(dot1);
8605
+ if (dotInv === undefined) {
8606
+ throw new Error(_t("Matrix is not invertible"));
8607
+ }
8608
+ const dot2 = multiplyMatrices(xMatrix, yMatrix);
8609
+ return transposeMatrix(multiplyMatrices(dotInv, dot2));
8610
+ }
8611
+ function evaluatePolynomial(coeffs, x, order) {
8612
+ return coeffs.reduce((acc, coeff, i) => acc + coeff * Math.pow(x, order - i), 0);
8613
+ }
8614
+ function expM(M) {
8615
+ return M.map((col) => col.map((cell) => Math.exp(cell)));
8616
+ }
8617
+ function logM(M) {
8618
+ return M.map((col) => col.map((cell) => Math.log(cell)));
8619
+ }
8620
+ function predictLinearValues(Y, X, newX, computeIntercept) {
8621
+ const { _X, _newX } = prepareDataForRegression(X, Y, newX);
8622
+ const coeffs = fullLinearRegression(_X, Y, computeIntercept, false);
8623
+ const nVar = coeffs.length - 1;
8624
+ const newY = _newX.map((col) => {
8625
+ let value = 0;
8626
+ for (let i = 0; i < nVar; i++) {
8627
+ value += coeffs[i][0] * col[nVar - i - 1];
8628
+ }
8629
+ value += coeffs[nVar][0];
8630
+ return [value];
8631
+ });
8632
+ return newY.length === newX.length ? newY : transposeMatrix(newY);
8633
+ }
8428
8634
  // -----------------------------------------------------------------------------
8429
8635
  // AVEDEV
8430
8636
  // -----------------------------------------------------------------------------
@@ -8709,6 +8915,56 @@ const COVARIANCE_S = {
8709
8915
  isExported: true,
8710
8916
  };
8711
8917
  // -----------------------------------------------------------------------------
8918
+ // FORECAST
8919
+ // -----------------------------------------------------------------------------
8920
+ const FORECAST = {
8921
+ description: _t("Calculates the expected y-value for a specified x based on a linear regression of a dataset."),
8922
+ args: [
8923
+ arg("x (number, range<number>)", _t("The value(s) on the x-axis to forecast.")),
8924
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
8925
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
8926
+ ],
8927
+ returns: ["NUMBER"],
8928
+ compute: function (x, dataY, dataX) {
8929
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
8930
+ return predictLinearValues([flatDataY], [flatDataX], matrixMap(toMatrix(x), (value) => toNumber(value, this.locale)), true);
8931
+ },
8932
+ isExported: true,
8933
+ };
8934
+ // -----------------------------------------------------------------------------
8935
+ // GROWTH
8936
+ // -----------------------------------------------------------------------------
8937
+ const GROWTH = {
8938
+ description: _t("Fits points to exponential growth trend."),
8939
+ args: [
8940
+ arg("known_data_y (range<number>)", _t("The array or range containing dependent (y) values that are already known, used to curve fit an ideal exponential growth curve.")),
8941
+ arg("known_data_x (range<number>, default={1;2;3;...})", _t("The values of the independent variable(s) corresponding with known_data_y.")),
8942
+ 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.")),
8943
+ 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.")),
8944
+ ],
8945
+ returns: ["NUMBER"],
8946
+ compute: function (knownDataY, knownDataX = [], newDataX = [], b = true) {
8947
+ return expM(predictLinearValues(logM(tryCastAsNumberMatrix(knownDataY, "the first argument (known_data_y)")), tryCastAsNumberMatrix(knownDataX, "the second argument (known_data_x)"), tryCastAsNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b)));
8948
+ },
8949
+ };
8950
+ // -----------------------------------------------------------------------------
8951
+ // INTERCEPT
8952
+ // -----------------------------------------------------------------------------
8953
+ const INTERCEPT = {
8954
+ description: _t("Compute the intercept of the linear regression."),
8955
+ args: [
8956
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
8957
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
8958
+ ],
8959
+ returns: ["NUMBER"],
8960
+ compute: function (dataY, dataX) {
8961
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
8962
+ const [[], [intercept]] = fullLinearRegression([flatDataX], [flatDataY]);
8963
+ return intercept;
8964
+ },
8965
+ isExported: true,
8966
+ };
8967
+ // -----------------------------------------------------------------------------
8712
8968
  // LARGE
8713
8969
  // -----------------------------------------------------------------------------
8714
8970
  const LARGE = {
@@ -8736,12 +8992,94 @@ const LARGE = {
8736
8992
  });
8737
8993
  const result = largests.shift();
8738
8994
  assert(() => result !== undefined, _t(`[[FUNCTION_NAME]] has no valid input data.`));
8739
- assert(() => count >= _n, _t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n.toString()));
8995
+ assert(() => count >= _n, _t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
8740
8996
  return result;
8741
8997
  },
8742
8998
  isExported: true,
8743
8999
  };
8744
9000
  // -----------------------------------------------------------------------------
9001
+ // LINEST
9002
+ // -----------------------------------------------------------------------------
9003
+ const LINEST = {
9004
+ description: _t("Compute the intercept of the linear regression."),
9005
+ args: [
9006
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9007
+ arg("data_x (range<number>, default={1;2;3;...})", _t("The range representing the array or matrix of independent data.")),
9008
+ arg("calculate_b (boolean, default=TRUE)", _t("A flag specifying wheter to compute the slope or not")),
9009
+ arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
9010
+ ],
9011
+ returns: ["NUMBER"],
9012
+ compute: function (dataY, dataX = [], calculateB = true, verbose = false) {
9013
+ return fullLinearRegression(tryCastAsNumberMatrix(dataX, "the first argument (data_y)"), tryCastAsNumberMatrix(dataY, "the second argument (data_x)"), toBoolean(calculateB), toBoolean(verbose));
9014
+ },
9015
+ isExported: true,
9016
+ };
9017
+ // -----------------------------------------------------------------------------
9018
+ // LOGEST
9019
+ // -----------------------------------------------------------------------------
9020
+ const LOGEST = {
9021
+ description: _t("Compute the intercept of the linear regression."),
9022
+ args: [
9023
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9024
+ arg("data_x (range<number>, optional, default={1;2;3;...})", _t("The range representing the array or matrix of independent data.")),
9025
+ arg("calculate_b (boolean, default=TRUE)", _t("A flag specifying wheter to compute the slope or not")),
9026
+ arg("verbose (boolean, default=FALSE)", _t("A flag specifying whether to return additional regression statistics or only the linear coefficients and the y-intercept")),
9027
+ ],
9028
+ returns: ["NUMBER"],
9029
+ compute: function (dataY, dataX = [], calculateB = true, verbose = false) {
9030
+ const coeffs = fullLinearRegression(tryCastAsNumberMatrix(dataX, "the second argument (data_x)"), logM(tryCastAsNumberMatrix(dataY, "the first argument (data_y)")), toBoolean(calculateB), toBoolean(verbose));
9031
+ for (let i = 0; i < coeffs.length; i++) {
9032
+ coeffs[i][0] = Math.exp(coeffs[i][0]);
9033
+ }
9034
+ return coeffs;
9035
+ },
9036
+ isExported: true,
9037
+ };
9038
+ // -----------------------------------------------------------------------------
9039
+ // MATTHEWS
9040
+ // -----------------------------------------------------------------------------
9041
+ const MATTHEWS = {
9042
+ description: _t("Compute the Matthews correlation coefficient of a dataset."),
9043
+ args: [
9044
+ arg("data_x (range)", _t("The range representing the array or matrix of observed data.")),
9045
+ arg("data_y (range)", _t("The range representing the array or matrix of predicted data.")),
9046
+ ],
9047
+ returns: ["NUMBER"],
9048
+ compute: function (dataX, dataY) {
9049
+ const flatX = dataX.flat();
9050
+ const flatY = dataY.flat();
9051
+ assertSameNumberOfElements(flatX, flatY);
9052
+ if (flatX.length === 0) {
9053
+ throw new Error(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
9054
+ }
9055
+ const n = flatX.length;
9056
+ let trueN = 0, trueP = 0, falseP = 0, falseN = 0;
9057
+ for (let i = 0; i < n; ++i) {
9058
+ const isTrue1 = toBoolean(flatX[i]);
9059
+ const isTrue2 = toBoolean(flatY[i]);
9060
+ if (isTrue1 === isTrue2) {
9061
+ if (isTrue1) {
9062
+ trueP++;
9063
+ }
9064
+ else {
9065
+ trueN++;
9066
+ }
9067
+ }
9068
+ else {
9069
+ if (isTrue1) {
9070
+ falseN++;
9071
+ }
9072
+ else {
9073
+ falseP++;
9074
+ }
9075
+ }
9076
+ }
9077
+ return ((trueP * trueN - falseP * falseN) /
9078
+ Math.sqrt((trueP + falseP) * (trueP + falseN) * (trueN + falseP) * (trueN + falseN)));
9079
+ },
9080
+ isExported: false,
9081
+ };
9082
+ // -----------------------------------------------------------------------------
8745
9083
  // MAX
8746
9084
  // -----------------------------------------------------------------------------
8747
9085
  const MAX = {
@@ -8896,6 +9234,41 @@ const MINIFS = {
8896
9234
  isExported: true,
8897
9235
  };
8898
9236
  // -----------------------------------------------------------------------------
9237
+ // PEARSON
9238
+ // -----------------------------------------------------------------------------
9239
+ const PEARSON = {
9240
+ description: _t("Compute the Pearson product-moment correlation coefficient of a dataset."),
9241
+ args: [
9242
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9243
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9244
+ ],
9245
+ returns: ["NUMBER"],
9246
+ compute: function (dataY, dataX) {
9247
+ const { flatDataX, flatDataY } = filterAndFlatData(dataX, dataY);
9248
+ if (flatDataX.length === 0) {
9249
+ throw new Error(_t("[[FUNCTION_NAME]] expects non-empty ranges for both parameters."));
9250
+ }
9251
+ if (flatDataX.length < 2) {
9252
+ throw new Error(_t("[[FUNCTION_NAME]] needs at least two values for both parameters"));
9253
+ }
9254
+ const n = flatDataX.length;
9255
+ let sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0;
9256
+ for (let i = 0; i < n; i++) {
9257
+ const xij = flatDataX[i];
9258
+ const yij = flatDataY[i];
9259
+ sumX += xij;
9260
+ sumY += yij;
9261
+ sumXY += xij * yij;
9262
+ sumXX += xij * xij;
9263
+ sumYY += yij * yij;
9264
+ }
9265
+ return ((n * sumXY - sumX * sumY) / Math.sqrt((n * sumXX - sumX * sumX) * (n * sumYY - sumY * sumY)));
9266
+ },
9267
+ isExported: true,
9268
+ };
9269
+ // In GSheet, CORREL is just an alias to PEARSON
9270
+ const CORREL = PEARSON;
9271
+ // -----------------------------------------------------------------------------
8899
9272
  // PERCENTILE
8900
9273
  // -----------------------------------------------------------------------------
8901
9274
  const PERCENTILE = {
@@ -8950,6 +9323,45 @@ const PERCENTILE_INC = {
8950
9323
  isExported: true,
8951
9324
  };
8952
9325
  // -----------------------------------------------------------------------------
9326
+ // POLYFIT
9327
+ // -----------------------------------------------------------------------------
9328
+ const POLYFIT_COEFFS = {
9329
+ description: _t("Compute the coefficients of polynomial regression of the dataset."),
9330
+ args: [
9331
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9332
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9333
+ arg("order (number)", _t("The order of the polynomial to fit the data, between 1 and 6.")),
9334
+ arg("intercept (boolean, default=TRUE)", _t("A flag specifying whether to compute the intercept or not.")),
9335
+ ],
9336
+ returns: ["RANGE<NUMBER>"],
9337
+ compute: function (dataY, dataX, order, intercept = true) {
9338
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
9339
+ return polynomialRegression(flatDataY, flatDataX, toNumber(order, this.locale), toBoolean(intercept));
9340
+ },
9341
+ isExported: false,
9342
+ };
9343
+ // -----------------------------------------------------------------------------
9344
+ // POLYFIT.FORECAST
9345
+ // -----------------------------------------------------------------------------
9346
+ const POLYFIT_FORECAST = {
9347
+ description: _t("Predict value by computing a polynomial regression of the dataset."),
9348
+ args: [
9349
+ arg("x (number, range<number>)", _t("The value(s) on the x-axis to forecast.")),
9350
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9351
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9352
+ arg("order (number)", _t("The order of the polynomial to fit the data, between 1 and 6.")),
9353
+ arg("intercept (boolean, default=TRUE)", _t("A flag specifying whether to compute the intercept or not.")),
9354
+ ],
9355
+ returns: ["NUMBER"],
9356
+ compute: function (x, dataY, dataX, order, intercept = true) {
9357
+ const _order = toNumber(order, this.locale);
9358
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
9359
+ const coeffs = polynomialRegression(flatDataY, flatDataX, _order, toBoolean(intercept)).flat();
9360
+ return matrixMap(toMatrix(x), (xij) => evaluatePolynomial(coeffs, toNumber(xij, this.locale), _order));
9361
+ },
9362
+ isExported: false,
9363
+ };
9364
+ // -----------------------------------------------------------------------------
8953
9365
  // QUARTILE
8954
9366
  // -----------------------------------------------------------------------------
8955
9367
  const QUARTILE = {
@@ -9006,6 +9418,39 @@ const QUARTILE_INC = {
9006
9418
  isExported: true,
9007
9419
  };
9008
9420
  // -----------------------------------------------------------------------------
9421
+ // RSQ
9422
+ // -----------------------------------------------------------------------------
9423
+ const RSQ = {
9424
+ description: _t("Compute the square of r, the Pearson product-moment correlation coefficient of a dataset."),
9425
+ args: [
9426
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9427
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9428
+ ],
9429
+ returns: ["NUMBER"],
9430
+ compute: function (dataY, dataX) {
9431
+ const pearson = PEARSON.compute.bind(this);
9432
+ return Math.pow(pearson(dataX, dataY), 2.0);
9433
+ },
9434
+ isExported: true,
9435
+ };
9436
+ // -----------------------------------------------------------------------------
9437
+ // SLOPE
9438
+ // -----------------------------------------------------------------------------
9439
+ const SLOPE = {
9440
+ description: _t("Compute the slope of the linear regression."),
9441
+ args: [
9442
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9443
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9444
+ ],
9445
+ returns: ["NUMBER"],
9446
+ compute: function (dataY, dataX) {
9447
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
9448
+ const [[slope]] = fullLinearRegression([flatDataX], [flatDataY]);
9449
+ return slope;
9450
+ },
9451
+ isExported: true,
9452
+ };
9453
+ // -----------------------------------------------------------------------------
9009
9454
  // SMALL
9010
9455
  // -----------------------------------------------------------------------------
9011
9456
  const SMALL = {
@@ -9033,12 +9478,39 @@ const SMALL = {
9033
9478
  });
9034
9479
  const result = largests.pop();
9035
9480
  assert(() => result !== undefined, _t(`[[FUNCTION_NAME]] has no valid input data.`));
9036
- assert(() => count >= _n, _t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n.toString()));
9481
+ assert(() => count >= _n, _t("Function [[FUNCTION_NAME]] parameter 2 value (%s) is out of range.", _n));
9037
9482
  return result;
9038
9483
  },
9039
9484
  isExported: true,
9040
9485
  };
9041
9486
  // -----------------------------------------------------------------------------
9487
+ // SPEARMAN
9488
+ // -----------------------------------------------------------------------------
9489
+ const SPEARMAN = {
9490
+ description: _t("Compute the Spearman rank correlation coefficient of a dataset."),
9491
+ args: [
9492
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9493
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9494
+ ],
9495
+ returns: ["NUMBER"],
9496
+ compute: function (dataX, dataY) {
9497
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
9498
+ const n = flatDataX.length;
9499
+ const order = flatDataX.map((e, i) => [e, flatDataY[i]]);
9500
+ order.sort((a, b) => a[0] - b[0]);
9501
+ for (let i = 0; i < n; ++i) {
9502
+ order[i][0] = i;
9503
+ }
9504
+ order.sort((a, b) => a[1] - b[1]);
9505
+ let sum = 0.0;
9506
+ for (let i = 0; i < n; ++i) {
9507
+ sum += (order[i][0] - i) ** 2;
9508
+ }
9509
+ return 1 - (6 * sum) / (n ** 3 - n);
9510
+ },
9511
+ isExported: false,
9512
+ };
9513
+ // -----------------------------------------------------------------------------
9042
9514
  // STDEV
9043
9515
  // -----------------------------------------------------------------------------
9044
9516
  const STDEV = {
@@ -9129,6 +9601,39 @@ const STDEVPA = {
9129
9601
  isExported: true,
9130
9602
  };
9131
9603
  // -----------------------------------------------------------------------------
9604
+ // STEYX
9605
+ // -----------------------------------------------------------------------------
9606
+ const STEYX = {
9607
+ description: _t("Calculates the standard error of the predicted y-value for each x in the regression of a dataset."),
9608
+ args: [
9609
+ arg("data_y (range<number>)", _t("The range representing the array or matrix of dependent data.")),
9610
+ arg("data_x (range<number>)", _t("The range representing the array or matrix of independent data.")),
9611
+ ],
9612
+ returns: ["NUMBER"],
9613
+ compute: function (dataY, dataX) {
9614
+ const { flatDataX, flatDataY } = filterAndFlatData(dataY, dataX);
9615
+ const data = fullLinearRegression([flatDataX], [flatDataY], true, true);
9616
+ return data[1][2];
9617
+ },
9618
+ isExported: true,
9619
+ };
9620
+ // -----------------------------------------------------------------------------
9621
+ // TREND
9622
+ // -----------------------------------------------------------------------------
9623
+ const TREND = {
9624
+ description: _t("Fits points to linear trend derived via least-squares."),
9625
+ args: [
9626
+ arg("known_data_y (number, range<number>)", _t("The array or range containing dependent (y) values that are already known, used to curve fit an ideal linear trend.")),
9627
+ arg("known_data_x (number, range<number>, optional, default={1;2;3;...})", _t("The values of the independent variable(s) corresponding with known_data_y.")),
9628
+ 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.")),
9629
+ 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.")),
9630
+ ],
9631
+ returns: ["NUMBER"],
9632
+ compute: function (knownDataY, knownDataX = [], newDataX = [], b = true) {
9633
+ return predictLinearValues(tryCastAsNumberMatrix(knownDataY, "the first argument (known_data_y)"), tryCastAsNumberMatrix(knownDataX, "the second argument (known_data_x)"), tryCastAsNumberMatrix(newDataX, "the third argument (new_data_y)"), toBoolean(b));
9634
+ },
9635
+ };
9636
+ // -----------------------------------------------------------------------------
9132
9637
  // VAR
9133
9638
  // -----------------------------------------------------------------------------
9134
9639
  const VAR = {
@@ -9227,12 +9732,19 @@ var statistical = /*#__PURE__*/Object.freeze({
9227
9732
  AVERAGEIF: AVERAGEIF,
9228
9733
  AVERAGEIFS: AVERAGEIFS,
9229
9734
  AVERAGE_WEIGHTED: AVERAGE_WEIGHTED,
9735
+ CORREL: CORREL,
9230
9736
  COUNT: COUNT,
9231
9737
  COUNTA: COUNTA,
9232
9738
  COVAR: COVAR,
9233
9739
  COVARIANCE_P: COVARIANCE_P,
9234
9740
  COVARIANCE_S: COVARIANCE_S,
9741
+ FORECAST: FORECAST,
9742
+ GROWTH: GROWTH,
9743
+ INTERCEPT: INTERCEPT,
9235
9744
  LARGE: LARGE,
9745
+ LINEST: LINEST,
9746
+ LOGEST: LOGEST,
9747
+ MATTHEWS: MATTHEWS,
9236
9748
  MAX: MAX,
9237
9749
  MAXA: MAXA,
9238
9750
  MAXIFS: MAXIFS,
@@ -9240,19 +9752,27 @@ var statistical = /*#__PURE__*/Object.freeze({
9240
9752
  MIN: MIN,
9241
9753
  MINA: MINA,
9242
9754
  MINIFS: MINIFS,
9755
+ PEARSON: PEARSON,
9243
9756
  PERCENTILE: PERCENTILE,
9244
9757
  PERCENTILE_EXC: PERCENTILE_EXC,
9245
9758
  PERCENTILE_INC: PERCENTILE_INC,
9759
+ POLYFIT_COEFFS: POLYFIT_COEFFS,
9760
+ POLYFIT_FORECAST: POLYFIT_FORECAST,
9246
9761
  QUARTILE: QUARTILE,
9247
9762
  QUARTILE_EXC: QUARTILE_EXC,
9248
9763
  QUARTILE_INC: QUARTILE_INC,
9764
+ RSQ: RSQ,
9765
+ SLOPE: SLOPE,
9249
9766
  SMALL: SMALL,
9767
+ SPEARMAN: SPEARMAN,
9250
9768
  STDEV: STDEV,
9251
9769
  STDEVA: STDEVA,
9252
9770
  STDEVP: STDEVP,
9253
9771
  STDEVPA: STDEVPA,
9254
9772
  STDEV_P: STDEV_P,
9255
9773
  STDEV_S: STDEV_S,
9774
+ STEYX: STEYX,
9775
+ TREND: TREND,
9256
9776
  VAR: VAR,
9257
9777
  VARA: VARA,
9258
9778
  VARP: VARP,
@@ -13887,7 +14407,7 @@ const TRIM = {
13887
14407
  ],
13888
14408
  returns: ["STRING"],
13889
14409
  compute: function (text) {
13890
- return toString(text).trim();
14410
+ return trimContent(toString(text));
13891
14411
  },
13892
14412
  isExported: true,
13893
14413
  };
@@ -19436,6 +19956,12 @@ const removeDuplicates = {
19436
19956
  env.openSidePanel("RemoveDuplicates", {});
19437
19957
  },
19438
19958
  };
19959
+ const trimWhitespace = {
19960
+ name: _t("Trim whitespace"),
19961
+ execute: (env) => {
19962
+ env.model.dispatch("TRIM_WHITESPACE");
19963
+ },
19964
+ };
19439
19965
  const sortDescending = {
19440
19966
  name: _t("Descending (Z ⟶ A)"),
19441
19967
  execute: (env) => {
@@ -20795,6 +21321,10 @@ topbarMenuRegistry
20795
21321
  .addChild("remove_duplicates", ["data", "data_cleanup"], {
20796
21322
  ...removeDuplicates,
20797
21323
  sequence: 10,
21324
+ })
21325
+ .addChild("trim_whitespace", ["data", "data_cleanup"], {
21326
+ ...trimWhitespace,
21327
+ sequence: 20,
20798
21328
  })
20799
21329
  .addChild("split_to_columns", ["data"], {
20800
21330
  ...splitToColumns,
@@ -25970,9 +26500,11 @@ function useCellHovered(env, gridRef, callback) {
25970
26500
  }
25971
26501
  }
25972
26502
  function updateMousePosition(e) {
25973
- x = e.offsetX;
25974
- y = e.offsetY;
25975
- lastMoved = Date.now();
26503
+ if (gridRef.el === e.target) {
26504
+ x = e.offsetX;
26505
+ y = e.offsetY;
26506
+ lastMoved = Date.now();
26507
+ }
25976
26508
  }
25977
26509
  function recompute() {
25978
26510
  const { col, row } = getPosition();
@@ -32454,8 +32986,9 @@ class CellPlugin extends CorePlugin {
32454
32986
  for (const position of positions) {
32455
32987
  const cell = this.getters.getCell(position);
32456
32988
  const xc = toXC(position.col, position.row);
32989
+ const style = this.removeDefaultStyleValues(cell.style);
32457
32990
  cells[xc] = {
32458
- style: cell.style ? getItemId(cell.style, styles) : undefined,
32991
+ style: Object.keys(style).length ? getItemId(style, styles) : undefined,
32459
32992
  format: cell.format ? getItemId(cell.format, formats) : undefined,
32460
32993
  content: cell.content || undefined,
32461
32994
  };
@@ -32474,6 +33007,15 @@ class CellPlugin extends CorePlugin {
32474
33007
  exportForExcel(data) {
32475
33008
  this.export(data);
32476
33009
  }
33010
+ removeDefaultStyleValues(style) {
33011
+ const cleanedStyle = { ...style };
33012
+ for (const [property, defaultValue] of Object.entries(DEFAULT_STYLE)) {
33013
+ if (cleanedStyle[property] === defaultValue) {
33014
+ delete cleanedStyle[property];
33015
+ }
33016
+ }
33017
+ return cleanedStyle;
33018
+ }
32477
33019
  // ---------------------------------------------------------------------------
32478
33020
  // GETTERS
32479
33021
  // ---------------------------------------------------------------------------
@@ -39812,6 +40354,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
39812
40354
  cells;
39813
40355
  copiedTables;
39814
40356
  zones;
40357
+ uuidGenerator = new UuidGenerator();
39815
40358
  constructor(zones, operation, getters, dispatch, selection) {
39816
40359
  super(operation, getters, dispatch, selection);
39817
40360
  if (!zones.length) {
@@ -40264,8 +40807,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
40264
40807
  this.adaptCFRules(origin.sheetId, cf, [xc], toRemoveRange);
40265
40808
  }
40266
40809
  else {
40267
- this.adaptCFRules(target.sheetId, cf, [xc], []);
40268
40810
  this.adaptCFRules(origin.sheetId, cf, [], toRemoveRange);
40811
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
40812
+ this.adaptCFRules(target.sheetId, cfToCopyTo, [xc], []);
40269
40813
  }
40270
40814
  }
40271
40815
  }
@@ -40289,6 +40833,12 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
40289
40833
  sheetId,
40290
40834
  });
40291
40835
  }
40836
+ getCFToCopyTo(targetSheetId, originCF) {
40837
+ const cfInTarget = this.getters
40838
+ .getConditionalFormats(targetSheetId)
40839
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
40840
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
40841
+ }
40292
40842
  }
40293
40843
 
40294
40844
  class DataCleanupPlugin extends UIPlugin {
@@ -40307,6 +40857,9 @@ class DataCleanupPlugin extends UIPlugin {
40307
40857
  case "REMOVE_DUPLICATES":
40308
40858
  this.removeDuplicates(cmd.columns, cmd.hasHeader);
40309
40859
  break;
40860
+ case "TRIM_WHITESPACE":
40861
+ this.trimWhitespace();
40862
+ break;
40310
40863
  }
40311
40864
  }
40312
40865
  // ---------------------------------------------------------------------------
@@ -40427,6 +40980,35 @@ class DataCleanupPlugin extends UIPlugin {
40427
40980
  }
40428
40981
  return "Success" /* CommandResult.Success */;
40429
40982
  }
40983
+ trimWhitespace() {
40984
+ const zones = this.getters.getSelectedZones();
40985
+ const sheetId = this.getters.getActiveSheetId();
40986
+ let count = 0;
40987
+ for (const { col, row } of zones.map(positions).flat()) {
40988
+ const cell = this.getters.getCell({ col, row, sheetId });
40989
+ if (!cell) {
40990
+ continue;
40991
+ }
40992
+ const trimmedContent = trimContent(cell.content);
40993
+ if (trimmedContent !== cell.content) {
40994
+ count += 1;
40995
+ this.dispatch("UPDATE_CELL", {
40996
+ sheetId,
40997
+ col,
40998
+ row,
40999
+ content: trimmedContent,
41000
+ });
41001
+ }
41002
+ }
41003
+ const text = count
41004
+ ? _t("Trimmed whitespace from %s cells.", count)
41005
+ : _t("No selected cells had whitespace trimmed.");
41006
+ this.ui.notifyUI({
41007
+ type: "info",
41008
+ text: text,
41009
+ sticky: false,
41010
+ });
41011
+ }
40430
41012
  }
40431
41013
 
40432
41014
  const BORDER_COLOR = "#8B008B";
@@ -43225,7 +43807,7 @@ class ClipboardPlugin extends UIPlugin {
43225
43807
  allowDispatch(cmd) {
43226
43808
  switch (cmd.type) {
43227
43809
  case "CUT":
43228
- const zones = cmd.cutTarget || this.getters.getSelectedZones();
43810
+ const zones = this.getters.getSelectedZones();
43229
43811
  const state = this.getClipboardState(zones, cmd.type);
43230
43812
  return state.isCutAllowed(zones);
43231
43813
  case "PASTE":
@@ -43260,7 +43842,7 @@ class ClipboardPlugin extends UIPlugin {
43260
43842
  switch (cmd.type) {
43261
43843
  case "COPY":
43262
43844
  case "CUT":
43263
- const zones = ("cutTarget" in cmd && cmd.cutTarget) || this.getters.getSelectedZones();
43845
+ const zones = this.getters.getSelectedZones();
43264
43846
  this.state = this.getClipboardState(zones, cmd.type);
43265
43847
  this.status = "visible";
43266
43848
  this.originSheetId = this.getters.getActiveSheetId();
@@ -44924,26 +45506,24 @@ class GridSelectionPlugin extends UIPlugin {
44924
45506
  const isBasedBefore = cmd.base < start;
44925
45507
  const deltaCol = isBasedBefore && isCol ? thickness : 0;
44926
45508
  const deltaRow = isBasedBefore && !isCol ? thickness : 0;
44927
- this.dispatch("CUT", {
44928
- cutTarget: [
44929
- {
44930
- left: isCol ? start + deltaCol : 0,
44931
- right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
44932
- top: !isCol ? start + deltaRow : 0,
44933
- bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
44934
- },
44935
- ],
44936
- });
44937
- this.dispatch("PASTE", {
44938
- target: [
44939
- {
44940
- left: isCol ? cmd.base : 0,
44941
- right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
44942
- top: !isCol ? cmd.base : 0,
44943
- bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
44944
- },
44945
- ],
44946
- });
45509
+ const target = [
45510
+ {
45511
+ left: isCol ? start + deltaCol : 0,
45512
+ right: isCol ? end + deltaCol : this.getters.getNumberCols(cmd.sheetId) - 1,
45513
+ top: !isCol ? start + deltaRow : 0,
45514
+ bottom: !isCol ? end + deltaRow : this.getters.getNumberRows(cmd.sheetId) - 1,
45515
+ },
45516
+ ];
45517
+ const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
45518
+ const pasteTarget = [
45519
+ {
45520
+ left: isCol ? cmd.base : 0,
45521
+ right: isCol ? cmd.base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
45522
+ top: !isCol ? cmd.base : 0,
45523
+ bottom: !isCol ? cmd.base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
45524
+ },
45525
+ ];
45526
+ state.paste(pasteTarget, { selectTarget: true });
44947
45527
  const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
44948
45528
  let currentIndex = cmd.base;
44949
45529
  for (const element of toRemove) {
@@ -52260,6 +52840,6 @@ const constants = {
52260
52840
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
52261
52841
 
52262
52842
 
52263
- __info__.version = '16.5.0-alpha.7';
52264
- __info__.date = '2023-09-12T11:43:41.584Z';
52265
- __info__.hash = '';
52843
+ __info__.version = "16.5.0-alpha.8";
52844
+ __info__.date = "2023-09-21T15:59:10.959Z";
52845
+ __info__.hash = "0b7527d";