@odoo/o-spreadsheet 17.3.6 → 17.3.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.
@@ -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.3.6
7
- * @date 2024-07-02T09:04:06.235Z
8
- * @hash 979c0b1
6
+ * @version 17.3.8
7
+ * @date 2024-07-08T05:43:16.647Z
8
+ * @hash e1e7bae
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -1831,7 +1831,7 @@
1831
1831
  });
1832
1832
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1833
1833
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1834
- const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1834
+ const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
1835
1835
  const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1836
1836
  const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1837
1837
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -1858,7 +1858,7 @@
1858
1858
  return getNumberRegex(locale).test(value.trim());
1859
1859
  }
1860
1860
  const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
1861
- return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
1861
+ return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
1862
1862
  });
1863
1863
  /**
1864
1864
  * Convert a string into a number. It assumes that the string actually represents
@@ -5895,19 +5895,22 @@
5895
5895
  }
5896
5896
 
5897
5897
  function isValidLocale(locale) {
5898
- if (!(locale &&
5899
- typeof locale === "object" &&
5900
- typeof locale.name === "string" &&
5901
- typeof locale.code === "string" &&
5902
- typeof locale.thousandsSeparator === "string" &&
5903
- typeof locale.decimalSeparator === "string" &&
5904
- typeof locale.dateFormat === "string" &&
5905
- typeof locale.timeFormat === "string" &&
5906
- typeof locale.formulaArgSeparator === "string")) {
5898
+ if (!locale ||
5899
+ typeof locale !== "object" ||
5900
+ !(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
5907
5901
  return false;
5908
5902
  }
5909
- if (!Object.values(locale).every((v) => v)) {
5910
- return false;
5903
+ for (const property of [
5904
+ "code",
5905
+ "name",
5906
+ "decimalSeparator",
5907
+ "dateFormat",
5908
+ "timeFormat",
5909
+ "formulaArgSeparator",
5910
+ ]) {
5911
+ if (!locale[property] || typeof locale[property] !== "string") {
5912
+ return false;
5913
+ }
5911
5914
  }
5912
5915
  if (locale.formulaArgSeparator === locale.decimalSeparator) {
5913
5916
  return false;
@@ -6005,7 +6008,10 @@
6005
6008
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
6006
6009
  return content;
6007
6010
  }
6008
- return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
6011
+ if (locale.thousandsSeparator) {
6012
+ content = content.replaceAll(locale.thousandsSeparator, "");
6013
+ }
6014
+ return content.replace(locale.decimalSeparator, ".");
6009
6015
  }
6010
6016
  /**
6011
6017
  * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
@@ -6994,6 +7000,146 @@
6994
7000
  return undefined;
6995
7001
  }
6996
7002
 
7003
+ var State;
7004
+ (function (State) {
7005
+ /**
7006
+ * Initial state.
7007
+ * Expecting any reference for the left part of a range
7008
+ * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
7009
+ */
7010
+ State[State["LeftRef"] = 0] = "LeftRef";
7011
+ /**
7012
+ * Expecting any reference for the right part of a range
7013
+ * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
7014
+ */
7015
+ State[State["RightRef"] = 1] = "RightRef";
7016
+ /**
7017
+ * Expecting the separator without any constraint on the right part
7018
+ */
7019
+ State[State["Separator"] = 2] = "Separator";
7020
+ /**
7021
+ * Expecting the separator for a full column range
7022
+ */
7023
+ State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
7024
+ /**
7025
+ * Expecting the separator for a full row range
7026
+ */
7027
+ State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
7028
+ /**
7029
+ * Expecting the right part of a full column range
7030
+ * e.g. "1", "A1"
7031
+ */
7032
+ State[State["RightColumnRef"] = 5] = "RightColumnRef";
7033
+ /**
7034
+ * Expecting the right part of a full row range
7035
+ * e.g. "A", "A1"
7036
+ */
7037
+ State[State["RightRowRef"] = 6] = "RightRowRef";
7038
+ /**
7039
+ * Final state. A range has been matched
7040
+ */
7041
+ State[State["Found"] = 7] = "Found";
7042
+ })(State || (State = {}));
7043
+ const goTo = (state, guard = () => true) => [
7044
+ {
7045
+ goTo: state,
7046
+ guard,
7047
+ },
7048
+ ];
7049
+ const goToMulti = (state, guard = () => true) => ({
7050
+ goTo: state,
7051
+ guard,
7052
+ });
7053
+ const machine = {
7054
+ [State.LeftRef]: {
7055
+ REFERENCE: goTo(State.Separator),
7056
+ NUMBER: goTo(State.FullRowSeparator),
7057
+ SYMBOL: [
7058
+ goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
7059
+ goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
7060
+ ],
7061
+ },
7062
+ [State.FullColumnSeparator]: {
7063
+ SPACE: goTo(State.FullColumnSeparator),
7064
+ OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
7065
+ },
7066
+ [State.FullRowSeparator]: {
7067
+ SPACE: goTo(State.FullRowSeparator),
7068
+ OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
7069
+ },
7070
+ [State.Separator]: {
7071
+ SPACE: goTo(State.Separator),
7072
+ OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
7073
+ },
7074
+ [State.RightRef]: {
7075
+ SPACE: goTo(State.RightRef),
7076
+ NUMBER: goTo(State.Found),
7077
+ REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
7078
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
7079
+ },
7080
+ [State.RightColumnRef]: {
7081
+ SPACE: goTo(State.RightColumnRef),
7082
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
7083
+ REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
7084
+ },
7085
+ [State.RightRowRef]: {
7086
+ SPACE: goTo(State.RightRowRef),
7087
+ NUMBER: goTo(State.Found),
7088
+ REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
7089
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
7090
+ },
7091
+ [State.Found]: {},
7092
+ };
7093
+ /**
7094
+ * Check if the list of tokens starts with a sequence of tokens representing
7095
+ * a range.
7096
+ * If a range is found, the sequence is removed from the list and is returned
7097
+ * as a single token.
7098
+ */
7099
+ function matchReference(tokens) {
7100
+ let head = 0;
7101
+ let transitions = machine[State.LeftRef];
7102
+ let matchedTokens = "";
7103
+ while (transitions !== undefined) {
7104
+ const token = tokens[head++];
7105
+ if (!token) {
7106
+ return null;
7107
+ }
7108
+ const transition = transitions[token.type]?.find((transition) => transition.guard(token));
7109
+ const nextState = transition ? transition.goTo : undefined;
7110
+ switch (nextState) {
7111
+ case undefined:
7112
+ return null;
7113
+ case State.Found:
7114
+ matchedTokens += token.value;
7115
+ tokens.splice(0, head);
7116
+ return {
7117
+ type: "REFERENCE",
7118
+ value: matchedTokens,
7119
+ };
7120
+ default:
7121
+ transitions = machine[nextState];
7122
+ matchedTokens += token.value;
7123
+ break;
7124
+ }
7125
+ }
7126
+ return null;
7127
+ }
7128
+ /**
7129
+ * Take the result of the tokenizer and transform it to be usable in the
7130
+ * manipulations of range
7131
+ *
7132
+ * @param formula
7133
+ */
7134
+ function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
7135
+ const tokens = tokenize(formula, locale);
7136
+ const result = [];
7137
+ while (tokens.length) {
7138
+ result.push(matchReference(tokens) || tokens.shift());
7139
+ }
7140
+ return result;
7141
+ }
7142
+
6997
7143
  const functionRegex = /[a-zA-Z0-9\_]+(\.[a-zA-Z0-9\_]+)*/;
6998
7144
  const UNARY_OPERATORS_PREFIX = ["-", "+"];
6999
7145
  const UNARY_OPERATORS_POSTFIX = ["%"];
@@ -7142,7 +7288,7 @@
7142
7288
  * Parse an expression (as a string) into an AST.
7143
7289
  */
7144
7290
  function parse(str) {
7145
- return parseTokens(tokenize(str));
7291
+ return parseTokens(rangeTokenize(str));
7146
7292
  }
7147
7293
  function parseTokens(tokens) {
7148
7294
  tokens = tokens.filter((x) => x.type !== "SPACE");
@@ -7278,146 +7424,6 @@
7278
7424
  return needParenthesis ? `(${astToFormula(rightOperation)})` : astToFormula(rightOperation);
7279
7425
  }
7280
7426
 
7281
- var State;
7282
- (function (State) {
7283
- /**
7284
- * Initial state.
7285
- * Expecting any reference for the left part of a range
7286
- * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
7287
- */
7288
- State[State["LeftRef"] = 0] = "LeftRef";
7289
- /**
7290
- * Expecting any reference for the right part of a range
7291
- * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
7292
- */
7293
- State[State["RightRef"] = 1] = "RightRef";
7294
- /**
7295
- * Expecting the separator without any constraint on the right part
7296
- */
7297
- State[State["Separator"] = 2] = "Separator";
7298
- /**
7299
- * Expecting the separator for a full column range
7300
- */
7301
- State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
7302
- /**
7303
- * Expecting the separator for a full row range
7304
- */
7305
- State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
7306
- /**
7307
- * Expecting the right part of a full column range
7308
- * e.g. "1", "A1"
7309
- */
7310
- State[State["RightColumnRef"] = 5] = "RightColumnRef";
7311
- /**
7312
- * Expecting the right part of a full row range
7313
- * e.g. "A", "A1"
7314
- */
7315
- State[State["RightRowRef"] = 6] = "RightRowRef";
7316
- /**
7317
- * Final state. A range has been matched
7318
- */
7319
- State[State["Found"] = 7] = "Found";
7320
- })(State || (State = {}));
7321
- const goTo = (state, guard = () => true) => [
7322
- {
7323
- goTo: state,
7324
- guard,
7325
- },
7326
- ];
7327
- const goToMulti = (state, guard = () => true) => ({
7328
- goTo: state,
7329
- guard,
7330
- });
7331
- const machine = {
7332
- [State.LeftRef]: {
7333
- REFERENCE: goTo(State.Separator),
7334
- NUMBER: goTo(State.FullRowSeparator),
7335
- SYMBOL: [
7336
- goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
7337
- goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
7338
- ],
7339
- },
7340
- [State.FullColumnSeparator]: {
7341
- SPACE: goTo(State.FullColumnSeparator),
7342
- OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
7343
- },
7344
- [State.FullRowSeparator]: {
7345
- SPACE: goTo(State.FullRowSeparator),
7346
- OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
7347
- },
7348
- [State.Separator]: {
7349
- SPACE: goTo(State.Separator),
7350
- OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
7351
- },
7352
- [State.RightRef]: {
7353
- SPACE: goTo(State.RightRef),
7354
- NUMBER: goTo(State.Found),
7355
- REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
7356
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
7357
- },
7358
- [State.RightColumnRef]: {
7359
- SPACE: goTo(State.RightColumnRef),
7360
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
7361
- REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
7362
- },
7363
- [State.RightRowRef]: {
7364
- SPACE: goTo(State.RightRowRef),
7365
- NUMBER: goTo(State.Found),
7366
- REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
7367
- SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
7368
- },
7369
- [State.Found]: {},
7370
- };
7371
- /**
7372
- * Check if the list of tokens starts with a sequence of tokens representing
7373
- * a range.
7374
- * If a range is found, the sequence is removed from the list and is returned
7375
- * as a single token.
7376
- */
7377
- function matchReference(tokens) {
7378
- let head = 0;
7379
- let transitions = machine[State.LeftRef];
7380
- let matchedTokens = "";
7381
- while (transitions !== undefined) {
7382
- const token = tokens[head++];
7383
- if (!token) {
7384
- return null;
7385
- }
7386
- const transition = transitions[token.type]?.find((transition) => transition.guard(token));
7387
- const nextState = transition ? transition.goTo : undefined;
7388
- switch (nextState) {
7389
- case undefined:
7390
- return null;
7391
- case State.Found:
7392
- matchedTokens += token.value;
7393
- tokens.splice(0, head);
7394
- return {
7395
- type: "REFERENCE",
7396
- value: matchedTokens,
7397
- };
7398
- default:
7399
- transitions = machine[nextState];
7400
- matchedTokens += token.value;
7401
- break;
7402
- }
7403
- }
7404
- return null;
7405
- }
7406
- /**
7407
- * Take the result of the tokenizer and transform it to be usable in the
7408
- * manipulations of range
7409
- *
7410
- * @param formula
7411
- */
7412
- function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
7413
- const tokens = tokenize(formula, locale);
7414
- const result = [];
7415
- while (tokens.length) {
7416
- result.push(matchReference(tokens) || tokens.shift());
7417
- }
7418
- return result;
7419
- }
7420
-
7421
7427
  /**
7422
7428
  * Add the following information on tokens:
7423
7429
  * - length
@@ -23926,10 +23932,6 @@ stores.inject(MyMetaStore, storeInstance);
23926
23932
  const colors = new ColorGenerator();
23927
23933
  const definition = chart.getDefinition();
23928
23934
  for (let [index, { label, data }] of dataSetsValues.entries()) {
23929
- if (["linear", "time"].includes(axisType)) {
23930
- // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
23931
- data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
23932
- }
23933
23935
  const color = colors.next();
23934
23936
  let backgroundRGBA = colorToRGBA(color);
23935
23937
  if (stacked) {
@@ -23945,6 +23947,10 @@ stores.inject(MyMetaStore, storeInstance);
23945
23947
  return value;
23946
23948
  });
23947
23949
  }
23950
+ if (["linear", "time"].includes(axisType)) {
23951
+ // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
23952
+ data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
23953
+ }
23948
23954
  const backgroundColor = rgbaToHex(backgroundRGBA);
23949
23955
  const dataset = {
23950
23956
  label,
@@ -36262,7 +36268,13 @@ stores.inject(MyMetaStore, storeInstance);
36262
36268
  }
36263
36269
  async loadLocales() {
36264
36270
  this.loadedLocales = (await this.env.loadLocales())
36265
- .filter(isValidLocale)
36271
+ .filter((locale) => {
36272
+ const isValid = isValidLocale(locale);
36273
+ if (!isValid) {
36274
+ console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
36275
+ }
36276
+ return isValid;
36277
+ })
36266
36278
  .sort((a, b) => a.name.localeCompare(b.name));
36267
36279
  }
36268
36280
  get numberFormatPreview() {
@@ -41414,6 +41426,7 @@ stores.inject(MyMetaStore, storeInstance);
41414
41426
  return;
41415
41427
  }
41416
41428
  if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
41429
+ ev.preventDefault();
41417
41430
  const content = clipboardData.getData(ClipboardMIMEType.PlainText);
41418
41431
  const target = this.env.model.getters.getSelectedZones();
41419
41432
  const clipboardString = this.env.model.getters.getClipboardTextContent();
@@ -41807,6 +41820,8 @@ stores.inject(MyMetaStore, storeInstance);
41807
41820
  "BITOR",
41808
41821
  "BITRSHIFT",
41809
41822
  "BITXOR",
41823
+ "BYCOL",
41824
+ "BYROW",
41810
41825
  "CEILING.MATH",
41811
41826
  "CEILING.PRECISE",
41812
41827
  "CHISQ.DIST",
@@ -41814,6 +41829,8 @@ stores.inject(MyMetaStore, storeInstance);
41814
41829
  "CHISQ.INV",
41815
41830
  "CHISQ.INV.RT",
41816
41831
  "CHISQ.TEST",
41832
+ "CHOOSECOLS",
41833
+ "CHOOSEROWS",
41817
41834
  "COMBINA",
41818
41835
  "CONCAT",
41819
41836
  "CONFIDENCE.NORM",
@@ -41826,14 +41843,17 @@ stores.inject(MyMetaStore, storeInstance);
41826
41843
  "CSCH",
41827
41844
  "DAYS",
41828
41845
  "DECIMAL",
41846
+ "DROP",
41829
41847
  "ERF.PRECISE",
41830
41848
  "ERFC.PRECISE",
41849
+ "EXPAND",
41831
41850
  "EXPON.DIST",
41832
41851
  "F.DIST",
41833
41852
  "F.DIST.RT",
41834
41853
  "F.INV",
41835
41854
  "F.INV.RT",
41836
41855
  "F.TEST",
41856
+ "FIELDVALUE",
41837
41857
  "FILTERXML",
41838
41858
  "FLOOR.MATH",
41839
41859
  "FLOOR.PRECISE",
@@ -41848,6 +41868,7 @@ stores.inject(MyMetaStore, storeInstance);
41848
41868
  "GAMMA.INV",
41849
41869
  "GAMMALN.PRECISE",
41850
41870
  "GAUSS",
41871
+ "HSTACK",
41851
41872
  "HYPGEOM.DIST",
41852
41873
  "IFNA",
41853
41874
  "IFS",
@@ -41860,9 +41881,14 @@ stores.inject(MyMetaStore, storeInstance);
41860
41881
  "IMSINH",
41861
41882
  "IMTAN",
41862
41883
  "ISFORMULA",
41884
+ "ISOMITTED",
41863
41885
  "ISOWEEKNUM",
41886
+ "LAMBDA",
41887
+ "LET",
41864
41888
  "LOGNORM.DIST",
41865
41889
  "LOGNORM.INV",
41890
+ "MAKEARRAY",
41891
+ "MAP",
41866
41892
  "MAXIFS",
41867
41893
  "MINIFS",
41868
41894
  "MODE.MULT",
@@ -41882,17 +41908,26 @@ stores.inject(MyMetaStore, storeInstance);
41882
41908
  "PERMUTATIONA",
41883
41909
  "PHI",
41884
41910
  "POISSON.DIST",
41911
+ "PQSOURCE",
41912
+ "PYTHON_STR",
41913
+ "PYTHON_TYPE",
41914
+ "PYTHON_TYPENAME",
41885
41915
  "QUARTILE.EXC",
41886
41916
  "QUARTILE.INC",
41887
41917
  "QUERYSTRING",
41918
+ "RANDARRAY",
41888
41919
  "RANK.AVG",
41889
41920
  "RANK.EQ",
41921
+ "REDUCE",
41890
41922
  "RRI",
41923
+ "SCAN",
41891
41924
  "SEC",
41892
41925
  "SECH",
41926
+ "SEQUENCE",
41893
41927
  "SHEET",
41894
41928
  "SHEETS",
41895
41929
  "SKEW.P",
41930
+ "SORTBY",
41896
41931
  "STDEV.P",
41897
41932
  "STDEV.S",
41898
41933
  "SWITCH",
@@ -41902,13 +41937,24 @@ stores.inject(MyMetaStore, storeInstance);
41902
41937
  "T.INV",
41903
41938
  "T.INV.2T",
41904
41939
  "T.TEST",
41940
+ "TAKE",
41941
+ "TEXTAFTER",
41942
+ "TEXTBEFORE",
41905
41943
  "TEXTJOIN",
41944
+ "TEXTSPLIT",
41945
+ "TOCOL",
41946
+ "TOROW",
41906
41947
  "UNICHAR",
41907
41948
  "UNICODE",
41949
+ "UNIQUE",
41908
41950
  "VAR.P",
41909
41951
  "VAR.S",
41952
+ "VSTACK",
41910
41953
  "WEBSERVICE",
41911
41954
  "WEIBULL.DIST",
41955
+ "WRAPCOLS",
41956
+ "WRAPROWS",
41957
+ "XLOOKUP",
41912
41958
  "XOR",
41913
41959
  "Z.TEST",
41914
41960
  ];
@@ -46171,6 +46217,21 @@ stores.inject(MyMetaStore, storeInstance);
46171
46217
  return [];
46172
46218
  return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
46173
46219
  }
46220
+ /**
46221
+ * Get all the rows which contains at least a border
46222
+ */
46223
+ getRowsWithBorders(sheetId) {
46224
+ const sheetBorders = this.borders[sheetId]?.filter(isDefined);
46225
+ if (!sheetBorders)
46226
+ return [];
46227
+ const rowsWithBorders = new Set();
46228
+ for (const rowBorders of sheetBorders) {
46229
+ for (const rowBorder in rowBorders) {
46230
+ rowsWithBorders.add(parseInt(rowBorder, 10));
46231
+ }
46232
+ }
46233
+ return Array.from(rowsWithBorders);
46234
+ }
46174
46235
  /**
46175
46236
  * Get the range of all the rows in the sheet
46176
46237
  */
@@ -46220,7 +46281,7 @@ stores.inject(MyMetaStore, storeInstance);
46220
46281
  destructive: false,
46221
46282
  });
46222
46283
  }
46223
- this.getRowsRange(sheetId)
46284
+ this.getRowsWithBorders(sheetId)
46224
46285
  .filter((row) => row >= start)
46225
46286
  .sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
46226
46287
  .forEach((row) => {
@@ -67012,9 +67073,9 @@ stores.inject(MyMetaStore, storeInstance);
67012
67073
  exports.tokenize = tokenize;
67013
67074
 
67014
67075
 
67015
- __info__.version = "17.3.6";
67016
- __info__.date = "2024-07-02T09:04:06.235Z";
67017
- __info__.hash = "979c0b1";
67076
+ __info__.version = "17.3.8";
67077
+ __info__.date = "2024-07-08T05:43:16.647Z";
67078
+ __info__.hash = "e1e7bae";
67018
67079
 
67019
67080
 
67020
67081
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);