@odoo/o-spreadsheet 17.1.0-alpha.3 → 17.1.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.
- package/dist/o-spreadsheet.cjs.js +655 -420
- package/dist/o-spreadsheet.d.ts +148 -138
- package/dist/o-spreadsheet.esm.js +655 -420
- package/dist/o-spreadsheet.iife.js +655 -420
- package/dist/o-spreadsheet.iife.min.js +294 -320
- package/dist/o_spreadsheet.xml +99 -61
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 17.1.0-alpha.
|
|
6
|
-
* @date 2023-11-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.1.0-alpha.4
|
|
6
|
+
* @date 2023-11-24T13:12:24.882Z
|
|
7
|
+
* @hash 255821b
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -229,7 +229,6 @@ const DEFAULT_CELL_HEIGHT = 23;
|
|
|
229
229
|
const SCROLLBAR_WIDTH = 15;
|
|
230
230
|
const AUTOFILL_EDGE_LENGTH = 8;
|
|
231
231
|
const ICON_EDGE_LENGTH = 18;
|
|
232
|
-
const UNHIDE_ICON_EDGE_LENGTH = 14;
|
|
233
232
|
const MIN_CF_ICON_MARGIN = 4;
|
|
234
233
|
const MIN_CELL_TEXT_MARGIN = 4;
|
|
235
234
|
const CF_ICON_EDGE_LENGTH = 15;
|
|
@@ -693,8 +692,7 @@ function removeFalsyAttributes(obj) {
|
|
|
693
692
|
*
|
|
694
693
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
695
694
|
*/
|
|
696
|
-
const
|
|
697
|
-
" ",
|
|
695
|
+
const whiteSpaceSpecialCharacters = [
|
|
698
696
|
"\t",
|
|
699
697
|
"\f",
|
|
700
698
|
"\v",
|
|
@@ -709,8 +707,7 @@ const whiteSpaceCharacters = [
|
|
|
709
707
|
String.fromCharCode(parseInt("3000", 16)),
|
|
710
708
|
String.fromCharCode(parseInt("feff", 16)),
|
|
711
709
|
];
|
|
712
|
-
const whiteSpaceRegexp = new RegExp(
|
|
713
|
-
const newLineRegex = /\r\n|\r|\n/g;
|
|
710
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
|
|
714
711
|
/**
|
|
715
712
|
* Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
|
|
716
713
|
* different newlines types by \n.
|
|
@@ -718,9 +715,9 @@ const newLineRegex = /\r\n|\r|\n/g;
|
|
|
718
715
|
function replaceSpecialSpaces(text) {
|
|
719
716
|
if (!text)
|
|
720
717
|
return "";
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
return text;
|
|
718
|
+
if (!whiteSpaceRegexp.test(text))
|
|
719
|
+
return text;
|
|
720
|
+
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
724
721
|
}
|
|
725
722
|
/**
|
|
726
723
|
* Determine if the numbers are consecutive.
|
|
@@ -2062,6 +2059,7 @@ exports.CommandResult = void 0;
|
|
|
2062
2059
|
CommandResult["InvalidNumberOfCriterionValues"] = "InvalidNumberOfCriterionValues";
|
|
2063
2060
|
CommandResult["BlockingValidationRule"] = "BlockingValidationRule";
|
|
2064
2061
|
CommandResult["InvalidCopyPasteSelection"] = "InvalidCopyPasteSelection";
|
|
2062
|
+
CommandResult["NoChanges"] = "NoChanges";
|
|
2065
2063
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
2066
2064
|
|
|
2067
2065
|
const DEFAULT_LOCALES = [
|
|
@@ -2191,12 +2189,12 @@ function toString(value) {
|
|
|
2191
2189
|
}
|
|
2192
2190
|
}
|
|
2193
2191
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
2194
|
-
function normalizeString(str) {
|
|
2192
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
2195
2193
|
return str
|
|
2196
2194
|
.toLowerCase()
|
|
2197
2195
|
.normalize("NFD")
|
|
2198
2196
|
.replace(/[\u0300-\u036f]/g, "");
|
|
2199
|
-
}
|
|
2197
|
+
});
|
|
2200
2198
|
const expectBooleanValueError = (value) => _t("The function [[FUNCTION_NAME]] expects a boolean value, but '%s' is a text, and cannot be coerced to a number.", value);
|
|
2201
2199
|
function toBoolean(value) {
|
|
2202
2200
|
switch (typeof value) {
|
|
@@ -3429,11 +3427,18 @@ function isSingleCellReference(xc) {
|
|
|
3429
3427
|
return singleCellReference.test(xc);
|
|
3430
3428
|
}
|
|
3431
3429
|
function splitReference(ref) {
|
|
3430
|
+
if (!ref.includes("!")) {
|
|
3431
|
+
return { xc: ref };
|
|
3432
|
+
}
|
|
3432
3433
|
const parts = ref.split("!");
|
|
3433
3434
|
const xc = parts.pop();
|
|
3434
3435
|
const sheetName = getUnquotedSheetName(parts.join("!")) || undefined;
|
|
3435
3436
|
return { sheetName, xc };
|
|
3436
3437
|
}
|
|
3438
|
+
/** Return a reference SheetName!xc from the given arguments */
|
|
3439
|
+
function getFullReference(sheetName, xc) {
|
|
3440
|
+
return sheetName !== undefined ? `${getCanonicalSheetName(sheetName)}!${xc}` : xc;
|
|
3441
|
+
}
|
|
3437
3442
|
|
|
3438
3443
|
/**
|
|
3439
3444
|
* Convert from a cartesian reference to a Zone
|
|
@@ -4542,14 +4547,14 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
|
|
|
4542
4547
|
switch (context.textBaseline) {
|
|
4543
4548
|
case "top":
|
|
4544
4549
|
underlineY += boxHeight - 2 * strokeWidth;
|
|
4545
|
-
strikeY += boxHeight -
|
|
4550
|
+
strikeY += boxHeight / 2 - strokeWidth;
|
|
4546
4551
|
break;
|
|
4547
4552
|
case "middle":
|
|
4548
4553
|
underlineY += boxHeight / 2 - strokeWidth;
|
|
4549
4554
|
break;
|
|
4550
4555
|
case "alphabetic":
|
|
4551
4556
|
underlineY += 2 * strokeWidth;
|
|
4552
|
-
strikeY -=
|
|
4557
|
+
strikeY -= 3 * strokeWidth;
|
|
4553
4558
|
break;
|
|
4554
4559
|
case "bottom":
|
|
4555
4560
|
underlineY = y;
|
|
@@ -4612,6 +4617,7 @@ function createAction(item) {
|
|
|
4612
4617
|
const children = item.children;
|
|
4613
4618
|
const description = item.description;
|
|
4614
4619
|
const icon = item.icon;
|
|
4620
|
+
const secondaryIcon = item.secondaryIcon;
|
|
4615
4621
|
return {
|
|
4616
4622
|
id: item.id || uuidGenerator$2.uuidv4(),
|
|
4617
4623
|
name: typeof name === "function" ? name : () => name,
|
|
@@ -4630,6 +4636,7 @@ function createAction(item) {
|
|
|
4630
4636
|
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
4631
4637
|
separator: item.separator || false,
|
|
4632
4638
|
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
4639
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
4633
4640
|
description: typeof description === "function" ? description : () => description || "",
|
|
4634
4641
|
textColor: item.textColor,
|
|
4635
4642
|
sequence: item.sequence || 0,
|
|
@@ -6985,11 +6992,9 @@ css /* scss */ `
|
|
|
6985
6992
|
padding: ${MENU_VERTICAL_PADDING}px 0px;
|
|
6986
6993
|
width: ${MENU_WIDTH}px;
|
|
6987
6994
|
box-sizing: border-box !important;
|
|
6995
|
+
user-select: none;
|
|
6988
6996
|
|
|
6989
6997
|
.o-menu-item {
|
|
6990
|
-
display: flex;
|
|
6991
|
-
justify-content: space-between;
|
|
6992
|
-
align-items: center;
|
|
6993
6998
|
box-sizing: border-box;
|
|
6994
6999
|
height: ${MENU_ITEM_HEIGHT}px;
|
|
6995
7000
|
padding: ${MENU_ITEM_PADDING_VERTICAL}px ${MENU_ITEM_PADDING_HORIZONTAL}px;
|
|
@@ -7000,20 +7005,12 @@ css /* scss */ `
|
|
|
7000
7005
|
min-width: 40%;
|
|
7001
7006
|
}
|
|
7002
7007
|
|
|
7003
|
-
&.o-menu-root {
|
|
7004
|
-
display: flex;
|
|
7005
|
-
justify-content: space-between;
|
|
7006
|
-
}
|
|
7007
|
-
|
|
7008
7008
|
.o-menu-item-icon {
|
|
7009
7009
|
display: inline-block;
|
|
7010
7010
|
margin: 0px 8px 0px 0px;
|
|
7011
7011
|
width: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
7012
7012
|
line-height: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
7013
7013
|
}
|
|
7014
|
-
.o-menu-item-root {
|
|
7015
|
-
width: 10px;
|
|
7016
|
-
}
|
|
7017
7014
|
|
|
7018
7015
|
&:not(.disabled) {
|
|
7019
7016
|
&:hover,
|
|
@@ -7356,7 +7353,7 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
|
7356
7353
|
return result;
|
|
7357
7354
|
}
|
|
7358
7355
|
function tokenizeDebugger(chars) {
|
|
7359
|
-
if (chars.current
|
|
7356
|
+
if (chars.current === "?") {
|
|
7360
7357
|
chars.shift();
|
|
7361
7358
|
return { type: "DEBUGGER", value: "?" };
|
|
7362
7359
|
}
|
|
@@ -7367,7 +7364,7 @@ const misc$1 = {
|
|
|
7367
7364
|
")": "RIGHT_PAREN",
|
|
7368
7365
|
};
|
|
7369
7366
|
function tokenizeMisc(chars) {
|
|
7370
|
-
if (chars.current
|
|
7367
|
+
if (chars.current in misc$1) {
|
|
7371
7368
|
const value = chars.shift();
|
|
7372
7369
|
const type = misc$1[value];
|
|
7373
7370
|
return { type, value };
|
|
@@ -7375,7 +7372,7 @@ function tokenizeMisc(chars) {
|
|
|
7375
7372
|
return null;
|
|
7376
7373
|
}
|
|
7377
7374
|
function tokenizeArgsSeparator(chars, locale) {
|
|
7378
|
-
if (chars.current
|
|
7375
|
+
if (chars.current === locale.formulaArgSeparator) {
|
|
7379
7376
|
const value = chars.shift();
|
|
7380
7377
|
const type = "ARG_SEPARATOR";
|
|
7381
7378
|
return { type, value };
|
|
@@ -7400,14 +7397,13 @@ function tokenizeNumber(chars, locale) {
|
|
|
7400
7397
|
return null;
|
|
7401
7398
|
}
|
|
7402
7399
|
function tokenizeString(chars) {
|
|
7403
|
-
if (chars.current
|
|
7400
|
+
if (chars.current === '"') {
|
|
7404
7401
|
const startChar = chars.shift();
|
|
7405
7402
|
let letters = startChar;
|
|
7406
|
-
while (chars.current()
|
|
7407
|
-
(chars.current() !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7403
|
+
while (chars.current && (chars.current !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7408
7404
|
letters += chars.shift();
|
|
7409
7405
|
}
|
|
7410
|
-
if (chars.current
|
|
7406
|
+
if (chars.current === '"') {
|
|
7411
7407
|
letters += chars.shift();
|
|
7412
7408
|
}
|
|
7413
7409
|
return {
|
|
@@ -7434,14 +7430,14 @@ function tokenizeSymbol(chars) {
|
|
|
7434
7430
|
let result = "";
|
|
7435
7431
|
// there are two main cases to manage: either something which starts with
|
|
7436
7432
|
// a ', like 'Sheet 2'A2, or a word-like element.
|
|
7437
|
-
if (chars.current
|
|
7433
|
+
if (chars.current === "'") {
|
|
7438
7434
|
let lastChar = chars.shift();
|
|
7439
7435
|
result += lastChar;
|
|
7440
|
-
while (chars.current
|
|
7436
|
+
while (chars.current) {
|
|
7441
7437
|
lastChar = chars.shift();
|
|
7442
7438
|
result += lastChar;
|
|
7443
7439
|
if (lastChar === "'") {
|
|
7444
|
-
if (chars.current
|
|
7440
|
+
if (chars.current && chars.current === "'") {
|
|
7445
7441
|
lastChar = chars.shift();
|
|
7446
7442
|
result += lastChar;
|
|
7447
7443
|
}
|
|
@@ -7457,7 +7453,7 @@ function tokenizeSymbol(chars) {
|
|
|
7457
7453
|
};
|
|
7458
7454
|
}
|
|
7459
7455
|
}
|
|
7460
|
-
while (chars.current
|
|
7456
|
+
while (chars.current && separatorRegexp.test(chars.current)) {
|
|
7461
7457
|
result += chars.shift();
|
|
7462
7458
|
}
|
|
7463
7459
|
if (result.length) {
|
|
@@ -7472,14 +7468,14 @@ function tokenizeSymbol(chars) {
|
|
|
7472
7468
|
}
|
|
7473
7469
|
function tokenizeSpace(chars) {
|
|
7474
7470
|
let length = 0;
|
|
7475
|
-
while (chars.current
|
|
7471
|
+
while (chars.current === NEWLINE) {
|
|
7476
7472
|
length++;
|
|
7477
7473
|
chars.shift();
|
|
7478
7474
|
}
|
|
7479
7475
|
if (length) {
|
|
7480
7476
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
7481
7477
|
}
|
|
7482
|
-
while (chars.current
|
|
7478
|
+
while (chars.current === " ") {
|
|
7483
7479
|
length++;
|
|
7484
7480
|
chars.shift();
|
|
7485
7481
|
}
|
|
@@ -7498,17 +7494,20 @@ function tokenizeInvalidRange(chars) {
|
|
|
7498
7494
|
class TokenizingChars {
|
|
7499
7495
|
text;
|
|
7500
7496
|
currentIndex = 0;
|
|
7497
|
+
current;
|
|
7501
7498
|
constructor(text) {
|
|
7502
7499
|
this.text = text;
|
|
7503
|
-
|
|
7504
|
-
current() {
|
|
7505
|
-
return this.text[this.currentIndex];
|
|
7500
|
+
this.current = text[0];
|
|
7506
7501
|
}
|
|
7507
7502
|
shift() {
|
|
7508
|
-
|
|
7503
|
+
const current = this.current;
|
|
7504
|
+
const next = this.text[++this.currentIndex];
|
|
7505
|
+
this.current = next;
|
|
7506
|
+
return current;
|
|
7509
7507
|
}
|
|
7510
7508
|
advanceBy(length) {
|
|
7511
7509
|
this.currentIndex += length;
|
|
7510
|
+
this.current = this.text[this.currentIndex];
|
|
7512
7511
|
}
|
|
7513
7512
|
isOver() {
|
|
7514
7513
|
return this.currentIndex >= this.text.length;
|
|
@@ -11312,7 +11311,7 @@ const EXPAND = {
|
|
|
11312
11311
|
) {
|
|
11313
11312
|
const _array = toMatrix(arg);
|
|
11314
11313
|
const _nbRows = toInteger(rows?.value, this.locale);
|
|
11315
|
-
const _nbColumns = columns !== undefined ? toInteger(columns.value, this.
|
|
11314
|
+
const _nbColumns = columns !== undefined ? toInteger(columns.value, this.locale) : _array.length;
|
|
11316
11315
|
assert(() => _nbRows >= _array[0].length, _t("The rows arguments (%s) must be greater or equal than the number of rows of the array.", _nbRows.toString()));
|
|
11317
11316
|
assert(() => _nbColumns >= _array.length, _t("The columns arguments (%s) must be greater or equal than the number of columns of the array.", _nbColumns.toString()));
|
|
11318
11317
|
return generateMatrix(_nbColumns, _nbRows, (col, row) => col >= _array.length || row >= _array[col].length ? padWith : _array[col][row]);
|
|
@@ -11801,6 +11800,10 @@ var misc = /*#__PURE__*/Object.freeze({
|
|
|
11801
11800
|
FORMAT_LARGE_NUMBER: FORMAT_LARGE_NUMBER
|
|
11802
11801
|
});
|
|
11803
11802
|
|
|
11803
|
+
function sum(values, locale) {
|
|
11804
|
+
return reduceNumbers(values, (acc, a) => acc + a, 0, locale);
|
|
11805
|
+
}
|
|
11806
|
+
|
|
11804
11807
|
const DEFAULT_FACTOR = 1;
|
|
11805
11808
|
const DEFAULT_MODE = 0;
|
|
11806
11809
|
const DEFAULT_PLACES = 0;
|
|
@@ -12752,7 +12755,7 @@ const SUM = {
|
|
|
12752
12755
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
12753
12756
|
},
|
|
12754
12757
|
compute: function (...values) {
|
|
12755
|
-
return
|
|
12758
|
+
return sum(values, this.locale);
|
|
12756
12759
|
},
|
|
12757
12760
|
isExported: true,
|
|
12758
12761
|
};
|
|
@@ -12921,6 +12924,44 @@ function assertSameNumberOfElements(...args) {
|
|
|
12921
12924
|
const dims = args[0].length;
|
|
12922
12925
|
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())));
|
|
12923
12926
|
}
|
|
12927
|
+
function average(values, locale) {
|
|
12928
|
+
let count = 0;
|
|
12929
|
+
const sum = reduceNumbers(values, (acc, a) => {
|
|
12930
|
+
count += 1;
|
|
12931
|
+
return acc + a;
|
|
12932
|
+
}, 0, locale);
|
|
12933
|
+
assert(() => count !== 0, _t("Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error."));
|
|
12934
|
+
return sum / count;
|
|
12935
|
+
}
|
|
12936
|
+
function countNumbers(values, locale) {
|
|
12937
|
+
let count = 0;
|
|
12938
|
+
for (let n of values) {
|
|
12939
|
+
if (isMatrix(n)) {
|
|
12940
|
+
for (let i of n) {
|
|
12941
|
+
for (let j of i) {
|
|
12942
|
+
if (typeof j === "number") {
|
|
12943
|
+
count += 1;
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12946
|
+
}
|
|
12947
|
+
}
|
|
12948
|
+
else if (typeof n !== "string" || isNumber(n, locale) || parseDateTime(n, locale)) {
|
|
12949
|
+
count += 1;
|
|
12950
|
+
}
|
|
12951
|
+
}
|
|
12952
|
+
return count;
|
|
12953
|
+
}
|
|
12954
|
+
function countAny(values) {
|
|
12955
|
+
return reduceAny(values, (acc, a) => (a !== undefined && a !== null ? acc + 1 : acc), 0);
|
|
12956
|
+
}
|
|
12957
|
+
function max(values, locale) {
|
|
12958
|
+
const result = reduceNumbers(values, (acc, a) => (acc < a ? a : acc), -Infinity, locale);
|
|
12959
|
+
return result === -Infinity ? 0 : result;
|
|
12960
|
+
}
|
|
12961
|
+
function min(values, locale) {
|
|
12962
|
+
const result = reduceNumbers(values, (acc, a) => (a < acc ? a : acc), Infinity, locale);
|
|
12963
|
+
return result === Infinity ? 0 : result;
|
|
12964
|
+
}
|
|
12924
12965
|
|
|
12925
12966
|
function filterAndFlatData(dataY, dataX) {
|
|
12926
12967
|
const _flatDataY = [];
|
|
@@ -13191,13 +13232,7 @@ const AVERAGE = {
|
|
|
13191
13232
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13192
13233
|
},
|
|
13193
13234
|
compute: function (...values) {
|
|
13194
|
-
|
|
13195
|
-
const sum = reduceNumbers(values, (acc, a) => {
|
|
13196
|
-
count += 1;
|
|
13197
|
-
return acc + a;
|
|
13198
|
-
}, 0, this.locale);
|
|
13199
|
-
assert(() => count !== 0, _t("Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error."));
|
|
13200
|
-
return sum / count;
|
|
13235
|
+
return average(values, this.locale);
|
|
13201
13236
|
},
|
|
13202
13237
|
isExported: true,
|
|
13203
13238
|
};
|
|
@@ -13355,24 +13390,7 @@ const COUNT = {
|
|
|
13355
13390
|
],
|
|
13356
13391
|
returns: ["NUMBER"],
|
|
13357
13392
|
compute: function (...values) {
|
|
13358
|
-
|
|
13359
|
-
for (let n of values) {
|
|
13360
|
-
if (isMatrix(n)) {
|
|
13361
|
-
for (let i of n) {
|
|
13362
|
-
for (let j of i) {
|
|
13363
|
-
if (typeof j === "number") {
|
|
13364
|
-
count += 1;
|
|
13365
|
-
}
|
|
13366
|
-
}
|
|
13367
|
-
}
|
|
13368
|
-
}
|
|
13369
|
-
else if (typeof n !== "string" ||
|
|
13370
|
-
isNumber(n, this.locale) ||
|
|
13371
|
-
parseDateTime(n, this.locale)) {
|
|
13372
|
-
count += 1;
|
|
13373
|
-
}
|
|
13374
|
-
}
|
|
13375
|
-
return count;
|
|
13393
|
+
return countNumbers(values, this.locale);
|
|
13376
13394
|
},
|
|
13377
13395
|
isExported: true,
|
|
13378
13396
|
};
|
|
@@ -13387,7 +13405,7 @@ const COUNTA = {
|
|
|
13387
13405
|
],
|
|
13388
13406
|
returns: ["NUMBER"],
|
|
13389
13407
|
compute: function (...values) {
|
|
13390
|
-
return
|
|
13408
|
+
return countAny(values);
|
|
13391
13409
|
},
|
|
13392
13410
|
isExported: true,
|
|
13393
13411
|
};
|
|
@@ -13617,8 +13635,7 @@ const MAX = {
|
|
|
13617
13635
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13618
13636
|
},
|
|
13619
13637
|
compute: function (...values) {
|
|
13620
|
-
|
|
13621
|
-
return result === -Infinity ? 0 : result;
|
|
13638
|
+
return max(values, this.locale);
|
|
13622
13639
|
},
|
|
13623
13640
|
isExported: true,
|
|
13624
13641
|
};
|
|
@@ -13705,8 +13722,7 @@ const MIN = {
|
|
|
13705
13722
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13706
13723
|
},
|
|
13707
13724
|
compute: function (...values) {
|
|
13708
|
-
|
|
13709
|
-
return result === Infinity ? 0 : result;
|
|
13725
|
+
return min(values, this.locale);
|
|
13710
13726
|
},
|
|
13711
13727
|
isExported: true,
|
|
13712
13728
|
};
|
|
@@ -17877,6 +17893,149 @@ var financial = /*#__PURE__*/Object.freeze({
|
|
|
17877
17893
|
YIELDMAT: YIELDMAT
|
|
17878
17894
|
});
|
|
17879
17895
|
|
|
17896
|
+
/**
|
|
17897
|
+
* Change the reference types inside the given token, if the token represent a range or a cell
|
|
17898
|
+
*
|
|
17899
|
+
* Eg. :
|
|
17900
|
+
* A1 => $A$1 => A$1 => $A1 => A1
|
|
17901
|
+
* A1:$B$1 => $A$1:B$1 => A$1:$B1 => $A1:B1 => A1:$B$1
|
|
17902
|
+
*/
|
|
17903
|
+
function loopThroughReferenceType(token) {
|
|
17904
|
+
if (token.type !== "REFERENCE")
|
|
17905
|
+
return token;
|
|
17906
|
+
const { xc, sheetName } = splitReference(token.value);
|
|
17907
|
+
const [left, right] = xc.split(":");
|
|
17908
|
+
const updatedLeft = getTokenNextReferenceType(left);
|
|
17909
|
+
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
17910
|
+
return { ...token, value: getFullReference(sheetName, updatedLeft + updatedRight) };
|
|
17911
|
+
}
|
|
17912
|
+
/**
|
|
17913
|
+
* Get a new token with a changed type of reference from the given cell token symbol.
|
|
17914
|
+
* Undefined behavior if given a token other than a cell or if the Xc contains a sheet reference
|
|
17915
|
+
*
|
|
17916
|
+
* A1 => $A$1 => A$1 => $A1 => A1
|
|
17917
|
+
*/
|
|
17918
|
+
function getTokenNextReferenceType(xc) {
|
|
17919
|
+
switch (getReferenceType(xc)) {
|
|
17920
|
+
case "none":
|
|
17921
|
+
xc = setXcToFixedReferenceType(xc, "colrow");
|
|
17922
|
+
break;
|
|
17923
|
+
case "colrow":
|
|
17924
|
+
xc = setXcToFixedReferenceType(xc, "row");
|
|
17925
|
+
break;
|
|
17926
|
+
case "row":
|
|
17927
|
+
xc = setXcToFixedReferenceType(xc, "col");
|
|
17928
|
+
break;
|
|
17929
|
+
case "col":
|
|
17930
|
+
xc = setXcToFixedReferenceType(xc, "none");
|
|
17931
|
+
break;
|
|
17932
|
+
}
|
|
17933
|
+
return xc;
|
|
17934
|
+
}
|
|
17935
|
+
/**
|
|
17936
|
+
* Returns the given XC with the given reference type. The XC string should not contain a sheet name.
|
|
17937
|
+
*/
|
|
17938
|
+
function setXcToFixedReferenceType(xc, referenceType) {
|
|
17939
|
+
if (xc.includes("!")) {
|
|
17940
|
+
throw new Error("The given XC should not contain a sheet name");
|
|
17941
|
+
}
|
|
17942
|
+
xc = xc.replace(/\$/g, "");
|
|
17943
|
+
let indexOfNumber;
|
|
17944
|
+
switch (referenceType) {
|
|
17945
|
+
case "col":
|
|
17946
|
+
return "$" + xc;
|
|
17947
|
+
case "row":
|
|
17948
|
+
indexOfNumber = xc.search(/[0-9]/);
|
|
17949
|
+
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
17950
|
+
case "colrow":
|
|
17951
|
+
indexOfNumber = xc.search(/[0-9]/);
|
|
17952
|
+
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
17953
|
+
return "$" + xc;
|
|
17954
|
+
case "none":
|
|
17955
|
+
return xc;
|
|
17956
|
+
}
|
|
17957
|
+
}
|
|
17958
|
+
/**
|
|
17959
|
+
* Return the type of reference used in the given XC of a cell.
|
|
17960
|
+
* Undefined behavior if the XC have a sheet reference
|
|
17961
|
+
*/
|
|
17962
|
+
function getReferenceType(xcCell) {
|
|
17963
|
+
if (isColAndRowFixed(xcCell)) {
|
|
17964
|
+
return "colrow";
|
|
17965
|
+
}
|
|
17966
|
+
else if (isColFixed(xcCell)) {
|
|
17967
|
+
return "col";
|
|
17968
|
+
}
|
|
17969
|
+
else if (isRowFixed(xcCell)) {
|
|
17970
|
+
return "row";
|
|
17971
|
+
}
|
|
17972
|
+
return "none";
|
|
17973
|
+
}
|
|
17974
|
+
function isColFixed(xc) {
|
|
17975
|
+
return xc.startsWith("$");
|
|
17976
|
+
}
|
|
17977
|
+
function isRowFixed(xc) {
|
|
17978
|
+
return xc.includes("$", 1);
|
|
17979
|
+
}
|
|
17980
|
+
function isColAndRowFixed(xc) {
|
|
17981
|
+
return xc.startsWith("$") && xc.length > 1 && xc.slice(1).includes("$");
|
|
17982
|
+
}
|
|
17983
|
+
|
|
17984
|
+
// -----------------------------------------------------------------------------
|
|
17985
|
+
// CELL
|
|
17986
|
+
// -----------------------------------------------------------------------------
|
|
17987
|
+
// NOTE: missing from Excel: "color", "filename", "parentheses", "prefix", "protect" and "width"
|
|
17988
|
+
const CELL_INFO_TYPES = ["address", "col", "contents", "format", "row", "type"];
|
|
17989
|
+
const CELL = {
|
|
17990
|
+
description: _t("Gets information about a cell."),
|
|
17991
|
+
args: [
|
|
17992
|
+
arg("info_type (string)", _t("The type of information requested. Can be one of %s", CELL_INFO_TYPES.join(", "))),
|
|
17993
|
+
arg("reference (meta)", _t("The reference to the cell.")),
|
|
17994
|
+
],
|
|
17995
|
+
returns: ["ANY"],
|
|
17996
|
+
compute: function (info, reference) {
|
|
17997
|
+
const _info = toString(info).toLowerCase();
|
|
17998
|
+
assert(() => CELL_INFO_TYPES.includes(_info), _t("The info_type should be one of %s.", CELL_INFO_TYPES.join(", ")));
|
|
17999
|
+
const sheetId = this.__originSheetId;
|
|
18000
|
+
const topLeftReference = reference.includes(":") ? reference.split(":")[0] : reference;
|
|
18001
|
+
let { sheetName, xc } = splitReference(topLeftReference);
|
|
18002
|
+
// only put the sheet name if the referenced range is in another sheet than the cell the formula is on
|
|
18003
|
+
sheetName = sheetName === this.getters.getSheetName(sheetId) ? undefined : sheetName;
|
|
18004
|
+
const fixedRef = getFullReference(sheetName, setXcToFixedReferenceType(xc, "colrow"));
|
|
18005
|
+
const range = this.getters.getRangeFromSheetXC(sheetId, fixedRef);
|
|
18006
|
+
switch (_info) {
|
|
18007
|
+
case "address":
|
|
18008
|
+
return this.getters.getRangeString(range, sheetId);
|
|
18009
|
+
case "col":
|
|
18010
|
+
return range.zone.left + 1;
|
|
18011
|
+
case "contents": {
|
|
18012
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18013
|
+
return this.getters.getEvaluatedCell(position).value;
|
|
18014
|
+
}
|
|
18015
|
+
case "format": {
|
|
18016
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18017
|
+
return this.getters.getEvaluatedCell(position).format || "";
|
|
18018
|
+
}
|
|
18019
|
+
case "row":
|
|
18020
|
+
return range.zone.top + 1;
|
|
18021
|
+
case "type": {
|
|
18022
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18023
|
+
const type = this.getters.getEvaluatedCell(position).type;
|
|
18024
|
+
if (type === CellValueType.empty) {
|
|
18025
|
+
return "b"; // blank
|
|
18026
|
+
}
|
|
18027
|
+
else if (type === CellValueType.text) {
|
|
18028
|
+
return "l"; // label
|
|
18029
|
+
}
|
|
18030
|
+
else {
|
|
18031
|
+
return "v"; // value
|
|
18032
|
+
}
|
|
18033
|
+
}
|
|
18034
|
+
}
|
|
18035
|
+
return "";
|
|
18036
|
+
},
|
|
18037
|
+
isExported: true,
|
|
18038
|
+
};
|
|
17880
18039
|
// -----------------------------------------------------------------------------
|
|
17881
18040
|
// ISERR
|
|
17882
18041
|
// -----------------------------------------------------------------------------
|
|
@@ -18032,6 +18191,7 @@ const NA = {
|
|
|
18032
18191
|
|
|
18033
18192
|
var info = /*#__PURE__*/Object.freeze({
|
|
18034
18193
|
__proto__: null,
|
|
18194
|
+
CELL: CELL,
|
|
18035
18195
|
ISBLANK: ISBLANK,
|
|
18036
18196
|
ISERR: ISERR,
|
|
18037
18197
|
ISERROR: ISERROR,
|
|
@@ -18323,7 +18483,7 @@ const ADDRESS = {
|
|
|
18323
18483
|
cellReference = rowPart + colPart;
|
|
18324
18484
|
}
|
|
18325
18485
|
if (sheet !== undefined) {
|
|
18326
|
-
return
|
|
18486
|
+
return getFullReference(toString(sheet), cellReference);
|
|
18327
18487
|
}
|
|
18328
18488
|
return cellReference;
|
|
18329
18489
|
},
|
|
@@ -18339,7 +18499,7 @@ const COLUMN = {
|
|
|
18339
18499
|
],
|
|
18340
18500
|
returns: ["NUMBER"],
|
|
18341
18501
|
compute: function (cellReference) {
|
|
18342
|
-
const _cellReference = cellReference || this.__originCellXC
|
|
18502
|
+
const _cellReference = cellReference || this.__originCellXC();
|
|
18343
18503
|
assert(() => !!_cellReference, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
|
|
18344
18504
|
const zone = toZone(_cellReference);
|
|
18345
18505
|
return zone.left + 1;
|
|
@@ -18506,7 +18666,7 @@ const ROW = {
|
|
|
18506
18666
|
],
|
|
18507
18667
|
returns: ["NUMBER"],
|
|
18508
18668
|
compute: function (cellReference) {
|
|
18509
|
-
cellReference = cellReference || this.__originCellXC
|
|
18669
|
+
cellReference = cellReference || this.__originCellXC();
|
|
18510
18670
|
assert(() => !!cellReference, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
|
|
18511
18671
|
const zone = toZone(cellReference);
|
|
18512
18672
|
return zone.top + 1;
|
|
@@ -23858,31 +24018,65 @@ css /* scss */ `
|
|
|
23858
24018
|
`;
|
|
23859
24019
|
class FindAndReplacePanel extends owl.Component {
|
|
23860
24020
|
static template = "o-spreadsheet-FindAndReplacePanel";
|
|
23861
|
-
|
|
24021
|
+
static components = { SelectionInput };
|
|
23862
24022
|
debounceTimeoutId;
|
|
23863
|
-
|
|
24023
|
+
initialShowFormulaState = false;
|
|
24024
|
+
dataRange = "";
|
|
23864
24025
|
searchInput = owl.useRef("searchInput");
|
|
24026
|
+
replaceInput = owl.useRef("replaceInput");
|
|
23865
24027
|
get hasSearchResult() {
|
|
23866
24028
|
return this.env.model.getters.getCurrentSelectedMatchIndex() !== null;
|
|
23867
24029
|
}
|
|
23868
24030
|
get pendingSearch() {
|
|
23869
24031
|
return this.debounceTimeoutId !== undefined;
|
|
23870
24032
|
}
|
|
24033
|
+
get searchOptions() {
|
|
24034
|
+
return this.env.model.getters.getSearchOptions();
|
|
24035
|
+
}
|
|
24036
|
+
get toSearch() {
|
|
24037
|
+
return this.searchInput.el?.value || "";
|
|
24038
|
+
}
|
|
24039
|
+
get toReplace() {
|
|
24040
|
+
return this.replaceInput.el?.value || "";
|
|
24041
|
+
}
|
|
24042
|
+
get allSheetsMatchesCount() {
|
|
24043
|
+
return _t("%s in all sheets", this.env.model.getters.getAllSheetMatchesCount());
|
|
24044
|
+
}
|
|
24045
|
+
get currentSheetMatchesCount() {
|
|
24046
|
+
return _t("%(matches)s in sheet %(sheetName)s", {
|
|
24047
|
+
matches: this.env.model.getters.getActiveSheetMatchesCount(),
|
|
24048
|
+
sheetName: this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId()),
|
|
24049
|
+
});
|
|
24050
|
+
}
|
|
24051
|
+
get specificRangeMatchesCount() {
|
|
24052
|
+
const range = this.searchOptions.specificRange;
|
|
24053
|
+
if (!range) {
|
|
24054
|
+
return "";
|
|
24055
|
+
}
|
|
24056
|
+
const { _sheetId, _zone } = range;
|
|
24057
|
+
return _t("%(matches)s in range %(range)s of sheet %(sheetName)s", {
|
|
24058
|
+
matches: this.env.model.getters.getSpecificRangeMatchesCount().toString(),
|
|
24059
|
+
range: zoneToXc(_zone),
|
|
24060
|
+
sheetName: this.env.model.getters.getSheetName(_sheetId),
|
|
24061
|
+
});
|
|
24062
|
+
}
|
|
23871
24063
|
setup() {
|
|
23872
|
-
this.
|
|
24064
|
+
this.initialShowFormulaState = this.env.model.getters.shouldShowFormulas();
|
|
23873
24065
|
owl.onMounted(() => this.searchInput.el?.focus());
|
|
23874
24066
|
owl.onWillUnmount(() => {
|
|
23875
24067
|
clearTimeout(this.debounceTimeoutId);
|
|
23876
24068
|
this.env.model.dispatch("CLEAR_SEARCH");
|
|
23877
|
-
this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.
|
|
24069
|
+
this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
|
|
23878
24070
|
});
|
|
23879
24071
|
owl.useEffect(() => {
|
|
23880
|
-
|
|
23881
|
-
this.searchFormulas
|
|
24072
|
+
const showFormula = this.env.model.getters.shouldShowFormulas();
|
|
24073
|
+
this.updateSearch({ searchFormulas: showFormula });
|
|
23882
24074
|
}, () => [this.env.model.getters.shouldShowFormulas()]);
|
|
23883
24075
|
}
|
|
23884
|
-
|
|
23885
|
-
this.
|
|
24076
|
+
onFocusSearch() {
|
|
24077
|
+
this.updateDataRange();
|
|
24078
|
+
}
|
|
24079
|
+
onInput() {
|
|
23886
24080
|
this.debouncedUpdateSearch();
|
|
23887
24081
|
}
|
|
23888
24082
|
onKeydownSearch(ev) {
|
|
@@ -23899,11 +24093,36 @@ class FindAndReplacePanel extends owl.Component {
|
|
|
23899
24093
|
this.replace();
|
|
23900
24094
|
}
|
|
23901
24095
|
}
|
|
23902
|
-
searchFormulas() {
|
|
24096
|
+
searchFormulas(ev) {
|
|
24097
|
+
const showFormula = ev.target.checked;
|
|
23903
24098
|
this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
|
|
23904
|
-
show:
|
|
24099
|
+
show: showFormula,
|
|
23905
24100
|
});
|
|
23906
|
-
this.updateSearch();
|
|
24101
|
+
this.updateSearch({ searchFormulas: showFormula });
|
|
24102
|
+
}
|
|
24103
|
+
searchExactMatch(ev) {
|
|
24104
|
+
const exactMatch = ev.target.checked;
|
|
24105
|
+
this.updateSearch({ exactMatch });
|
|
24106
|
+
}
|
|
24107
|
+
searchMatchCase(ev) {
|
|
24108
|
+
const matchCase = ev.target.checked;
|
|
24109
|
+
this.updateSearch({ matchCase });
|
|
24110
|
+
}
|
|
24111
|
+
changeSearchScope(ev) {
|
|
24112
|
+
const searchScope = ev.target.value;
|
|
24113
|
+
this.updateSearch({ searchScope });
|
|
24114
|
+
}
|
|
24115
|
+
onSearchRangeChanged(ranges) {
|
|
24116
|
+
this.dataRange = ranges[0];
|
|
24117
|
+
}
|
|
24118
|
+
updateDataRange() {
|
|
24119
|
+
if (!this.dataRange) {
|
|
24120
|
+
return;
|
|
24121
|
+
}
|
|
24122
|
+
if (this.searchOptions.searchScope === "specificRange") {
|
|
24123
|
+
const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.dataRange).rangeData;
|
|
24124
|
+
this.updateSearch({ specificRange });
|
|
24125
|
+
}
|
|
23907
24126
|
}
|
|
23908
24127
|
onSelectPreviousCell() {
|
|
23909
24128
|
this.env.model.dispatch("SELECT_SEARCH_PREVIOUS_MATCH");
|
|
@@ -23911,10 +24130,14 @@ class FindAndReplacePanel extends owl.Component {
|
|
|
23911
24130
|
onSelectNextCell() {
|
|
23912
24131
|
this.env.model.dispatch("SELECT_SEARCH_NEXT_MATCH");
|
|
23913
24132
|
}
|
|
23914
|
-
updateSearch() {
|
|
24133
|
+
updateSearch(updateSearchOptions) {
|
|
24134
|
+
const searchOptions = {
|
|
24135
|
+
...this.env.model.getters.getSearchOptions(),
|
|
24136
|
+
...updateSearchOptions,
|
|
24137
|
+
};
|
|
23915
24138
|
this.env.model.dispatch("UPDATE_SEARCH", {
|
|
23916
|
-
toSearch: this.
|
|
23917
|
-
searchOptions
|
|
24139
|
+
toSearch: this.toSearch,
|
|
24140
|
+
searchOptions,
|
|
23918
24141
|
});
|
|
23919
24142
|
}
|
|
23920
24143
|
debouncedUpdateSearch() {
|
|
@@ -23926,28 +24149,14 @@ class FindAndReplacePanel extends owl.Component {
|
|
|
23926
24149
|
}
|
|
23927
24150
|
replace() {
|
|
23928
24151
|
this.env.model.dispatch("REPLACE_SEARCH", {
|
|
23929
|
-
replaceWith: this.
|
|
24152
|
+
replaceWith: this.toReplace,
|
|
23930
24153
|
});
|
|
23931
24154
|
}
|
|
23932
24155
|
replaceAll() {
|
|
23933
24156
|
this.env.model.dispatch("REPLACE_ALL_SEARCH", {
|
|
23934
|
-
replaceWith: this.
|
|
24157
|
+
replaceWith: this.toReplace,
|
|
23935
24158
|
});
|
|
23936
24159
|
}
|
|
23937
|
-
// ---------------------------------------------------------------------------
|
|
23938
|
-
// Private
|
|
23939
|
-
// ---------------------------------------------------------------------------
|
|
23940
|
-
initialState() {
|
|
23941
|
-
return {
|
|
23942
|
-
toSearch: "",
|
|
23943
|
-
replaceWith: "",
|
|
23944
|
-
searchOptions: {
|
|
23945
|
-
matchCase: false,
|
|
23946
|
-
exactMatch: false,
|
|
23947
|
-
searchFormulas: false,
|
|
23948
|
-
},
|
|
23949
|
-
};
|
|
23950
|
-
}
|
|
23951
24160
|
}
|
|
23952
24161
|
FindAndReplacePanel.props = {
|
|
23953
24162
|
onCloseSidePanel: Function,
|
|
@@ -27093,7 +27302,7 @@ class GridComposer extends owl.Component {
|
|
|
27093
27302
|
get cellReference() {
|
|
27094
27303
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
27095
27304
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
27096
|
-
return
|
|
27305
|
+
return getFullReference(prefixSheet ? this.env.model.getters.getSheetName(sheetId) : undefined, toXC(col, row));
|
|
27097
27306
|
}
|
|
27098
27307
|
get cellReferenceStyle() {
|
|
27099
27308
|
const { x: left, y: top } = this.rect;
|
|
@@ -28536,22 +28745,15 @@ css /* scss */ `
|
|
|
28536
28745
|
height: 10000px;
|
|
28537
28746
|
background-color: ${SELECTION_BORDER_COLOR};
|
|
28538
28747
|
}
|
|
28539
|
-
.o-unhide {
|
|
28540
|
-
width:
|
|
28541
|
-
|
|
28542
|
-
|
|
28543
|
-
overflow: hidden;
|
|
28544
|
-
border-radius: 2px;
|
|
28545
|
-
top: calc(${HEADER_HEIGHT}px / 2 - ${UNHIDE_ICON_EDGE_LENGTH}px / 2);
|
|
28748
|
+
.o-unhide-buttons {
|
|
28749
|
+
width: fit-content;
|
|
28750
|
+
gap: 5px;
|
|
28751
|
+
transform: translate(-50%, 0);
|
|
28546
28752
|
}
|
|
28547
28753
|
.o-unhide:hover {
|
|
28548
28754
|
z-index: ${ComponentsImportance.Grid + 1};
|
|
28549
28755
|
background-color: lightgrey;
|
|
28550
28756
|
}
|
|
28551
|
-
.o-unhide > svg {
|
|
28552
|
-
position: relative;
|
|
28553
|
-
top: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28554
|
-
}
|
|
28555
28757
|
}
|
|
28556
28758
|
`;
|
|
28557
28759
|
AbstractResizer.props = {
|
|
@@ -28661,8 +28863,8 @@ class ColResizer extends AbstractResizer {
|
|
|
28661
28863
|
dimension: "COL",
|
|
28662
28864
|
});
|
|
28663
28865
|
}
|
|
28664
|
-
|
|
28665
|
-
return this._getDimensionsInViewport(hiddenIndex).start;
|
|
28866
|
+
getUnhideButtonStyle(hiddenIndex) {
|
|
28867
|
+
return cssPropertiesToCss({ left: this._getDimensionsInViewport(hiddenIndex).start + "px" });
|
|
28666
28868
|
}
|
|
28667
28869
|
}
|
|
28668
28870
|
css /* scss */ `
|
|
@@ -28708,18 +28910,9 @@ css /* scss */ `
|
|
|
28708
28910
|
height: 1px;
|
|
28709
28911
|
background-color: ${SELECTION_BORDER_COLOR};
|
|
28710
28912
|
}
|
|
28711
|
-
.o-unhide {
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
position: absolute;
|
|
28715
|
-
overflow: hidden;
|
|
28716
|
-
border-radius: 2px;
|
|
28717
|
-
left: calc(${HEADER_WIDTH}px - ${UNHIDE_ICON_EDGE_LENGTH}px - 2px);
|
|
28718
|
-
}
|
|
28719
|
-
.o-unhide > svg {
|
|
28720
|
-
position: relative;
|
|
28721
|
-
left: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28722
|
-
top: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28913
|
+
.o-unhide-buttons {
|
|
28914
|
+
height: fit-content;
|
|
28915
|
+
transform: translate(0, -50%);
|
|
28723
28916
|
}
|
|
28724
28917
|
.o-unhide:hover {
|
|
28725
28918
|
z-index: ${ComponentsImportance.Grid + 1};
|
|
@@ -28834,8 +29027,8 @@ class RowResizer extends AbstractResizer {
|
|
|
28834
29027
|
elements: hiddenElements,
|
|
28835
29028
|
});
|
|
28836
29029
|
}
|
|
28837
|
-
|
|
28838
|
-
return this._getDimensionsInViewport(hiddenIndex).start;
|
|
29030
|
+
getUnhideButtonStyle(hiddenIndex) {
|
|
29031
|
+
return cssPropertiesToCss({ top: this._getDimensionsInViewport(hiddenIndex).start + "px" });
|
|
28839
29032
|
}
|
|
28840
29033
|
}
|
|
28841
29034
|
css /* scss */ `
|
|
@@ -29342,7 +29535,6 @@ class Grid extends owl.Component {
|
|
|
29342
29535
|
owl.onMounted(() => this.focus());
|
|
29343
29536
|
this.props.exposeFocus(() => this.focus());
|
|
29344
29537
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
29345
|
-
owl.useEffect(() => this.focus(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
29346
29538
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
29347
29539
|
this.moveCanvas(deltaX, deltaY);
|
|
29348
29540
|
this.hoveredCell.col = undefined;
|
|
@@ -29779,6 +29971,7 @@ class Grid extends owl.Component {
|
|
|
29779
29971
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
29780
29972
|
const target = this.env.model.getters.getSelectedZones();
|
|
29781
29973
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
29974
|
+
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
29782
29975
|
if (clipboardString === content) {
|
|
29783
29976
|
// the paste actually comes from o-spreadsheet itself
|
|
29784
29977
|
interactivePaste(this.env, target);
|
|
@@ -29786,7 +29979,7 @@ class Grid extends owl.Component {
|
|
|
29786
29979
|
else {
|
|
29787
29980
|
interactivePasteFromOS(this.env, target, content);
|
|
29788
29981
|
}
|
|
29789
|
-
if (
|
|
29982
|
+
if (isCutOperation) {
|
|
29790
29983
|
await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
29791
29984
|
}
|
|
29792
29985
|
}
|
|
@@ -31399,12 +31592,6 @@ function convertChartData(chartData) {
|
|
|
31399
31592
|
}
|
|
31400
31593
|
function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
31401
31594
|
let { sheetName, xc } = splitReference(range);
|
|
31402
|
-
if (sheetName) {
|
|
31403
|
-
sheetName = getCanonicalSheetName(sheetName) + "!";
|
|
31404
|
-
}
|
|
31405
|
-
else {
|
|
31406
|
-
sheetName = "";
|
|
31407
|
-
}
|
|
31408
31595
|
let zone = toUnboundedZone(xc);
|
|
31409
31596
|
if (dataSetsHaveTitle && zone.bottom !== undefined && zone.right !== undefined) {
|
|
31410
31597
|
const height = zone.bottom - zone.top + 1;
|
|
@@ -31417,7 +31604,7 @@ function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
|
31417
31604
|
}
|
|
31418
31605
|
}
|
|
31419
31606
|
const dataXC = zoneToXc(zone);
|
|
31420
|
-
return sheetName
|
|
31607
|
+
return getFullReference(sheetName, dataXC);
|
|
31421
31608
|
}
|
|
31422
31609
|
|
|
31423
31610
|
/**
|
|
@@ -34080,6 +34267,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34080
34267
|
// ---------------------------------------------------------------------------
|
|
34081
34268
|
// Command Handling
|
|
34082
34269
|
// ---------------------------------------------------------------------------
|
|
34270
|
+
allowDispatch(cmd) {
|
|
34271
|
+
switch (cmd.type) {
|
|
34272
|
+
case "SET_BORDER":
|
|
34273
|
+
return this.checkBordersUnchanged(cmd);
|
|
34274
|
+
default:
|
|
34275
|
+
return "Success" /* CommandResult.Success */;
|
|
34276
|
+
}
|
|
34277
|
+
}
|
|
34083
34278
|
handle(cmd) {
|
|
34084
34279
|
switch (cmd.type) {
|
|
34085
34280
|
case "ADD_MERGE":
|
|
@@ -34499,6 +34694,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34499
34694
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
34500
34695
|
}
|
|
34501
34696
|
}
|
|
34697
|
+
checkBordersUnchanged(cmd) {
|
|
34698
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
34699
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
34700
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
34701
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
34702
|
+
}
|
|
34703
|
+
return "Success" /* CommandResult.Success */;
|
|
34704
|
+
}
|
|
34502
34705
|
// ---------------------------------------------------------------------------
|
|
34503
34706
|
// Import/Export
|
|
34504
34707
|
// ---------------------------------------------------------------------------
|
|
@@ -35325,7 +35528,6 @@ class CellPlugin extends CorePlugin {
|
|
|
35325
35528
|
static getters = [
|
|
35326
35529
|
"zoneToXC",
|
|
35327
35530
|
"getCells",
|
|
35328
|
-
"getFormulaCellContent",
|
|
35329
35531
|
"getTranslatedCellFormula",
|
|
35330
35532
|
"getCellStyle",
|
|
35331
35533
|
"getCellById",
|
|
@@ -35354,8 +35556,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35354
35556
|
allowDispatch(cmd) {
|
|
35355
35557
|
switch (cmd.type) {
|
|
35356
35558
|
case "UPDATE_CELL":
|
|
35559
|
+
return this.checkCellOutOfSheet(cmd);
|
|
35357
35560
|
case "CLEAR_CELL":
|
|
35358
|
-
return this.
|
|
35561
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
35359
35562
|
default:
|
|
35360
35563
|
return "Success" /* CommandResult.Success */;
|
|
35361
35564
|
}
|
|
@@ -35524,24 +35727,18 @@ class CellPlugin extends CorePlugin {
|
|
|
35524
35727
|
*/
|
|
35525
35728
|
getCellById(cellId) {
|
|
35526
35729
|
// this must be as fast as possible
|
|
35527
|
-
|
|
35528
|
-
|
|
35529
|
-
|
|
35530
|
-
if (cell) {
|
|
35531
|
-
return cell;
|
|
35532
|
-
}
|
|
35533
|
-
}
|
|
35534
|
-
return undefined;
|
|
35730
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35731
|
+
const sheet = this.cells[position.sheetId];
|
|
35732
|
+
return sheet[cellId];
|
|
35535
35733
|
}
|
|
35536
35734
|
/*
|
|
35537
35735
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
35538
35736
|
*/
|
|
35539
35737
|
getFormulaCellContent(sheetId, compiledFormula, dependencies) {
|
|
35540
|
-
const ranges = dependencies || compiledFormula.dependencies;
|
|
35541
35738
|
let rangeIndex = 0;
|
|
35542
35739
|
return concat(compiledFormula.tokens.map((token) => {
|
|
35543
35740
|
if (token.type === "REFERENCE") {
|
|
35544
|
-
const range =
|
|
35741
|
+
const range = dependencies[rangeIndex++];
|
|
35545
35742
|
return this.getters.getRangeString(range, sheetId);
|
|
35546
35743
|
}
|
|
35547
35744
|
return token.value;
|
|
@@ -35762,13 +35959,23 @@ class CellPlugin extends CorePlugin {
|
|
|
35762
35959
|
},
|
|
35763
35960
|
};
|
|
35764
35961
|
}
|
|
35765
|
-
checkCellOutOfSheet(
|
|
35962
|
+
checkCellOutOfSheet(cmd) {
|
|
35963
|
+
const { sheetId, col, row } = cmd;
|
|
35766
35964
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
35767
35965
|
if (!sheet)
|
|
35768
35966
|
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
35769
35967
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
35770
35968
|
return isInside(col, row, sheetZone) ? "Success" /* CommandResult.Success */ : "TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */;
|
|
35771
35969
|
}
|
|
35970
|
+
checkUselessClearCell(cmd) {
|
|
35971
|
+
const cell = this.getters.getCell(cmd);
|
|
35972
|
+
if (!cell)
|
|
35973
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35974
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
35975
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35976
|
+
}
|
|
35977
|
+
return "Success" /* CommandResult.Success */;
|
|
35978
|
+
}
|
|
35772
35979
|
}
|
|
35773
35980
|
class FormulaCellWithDependencies {
|
|
35774
35981
|
id;
|
|
@@ -36458,6 +36665,9 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
36458
36665
|
return this.rules[sheetId].find((rule) => rule.id === id);
|
|
36459
36666
|
}
|
|
36460
36667
|
getValidationRuleForCell({ sheetId, col, row }) {
|
|
36668
|
+
if (!this.rules[sheetId]) {
|
|
36669
|
+
return undefined;
|
|
36670
|
+
}
|
|
36461
36671
|
for (const rule of this.rules[sheetId]) {
|
|
36462
36672
|
for (const range of rule.ranges) {
|
|
36463
36673
|
if (isInside(col, row, range.zone)) {
|
|
@@ -37630,7 +37840,7 @@ class MergePlugin extends CorePlugin {
|
|
|
37630
37840
|
const rangeString = this.getters.getRangeString(expandedRange, forSheetId);
|
|
37631
37841
|
if (this.isSingleCellOrMerge(rangeImpl.sheetId, rangeImpl.zone)) {
|
|
37632
37842
|
const { sheetName, xc } = splitReference(rangeString);
|
|
37633
|
-
return
|
|
37843
|
+
return getFullReference(sheetName, xc.split(":")[0]);
|
|
37634
37844
|
}
|
|
37635
37845
|
return rangeString;
|
|
37636
37846
|
}
|
|
@@ -39055,10 +39265,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
39055
39265
|
// begin with the end.
|
|
39056
39266
|
rows.sort((a, b) => b - a);
|
|
39057
39267
|
for (let group of groupConsecutive(rows)) {
|
|
39268
|
+
// indexes are sorted in the descending order
|
|
39269
|
+
const from = group[group.length - 1];
|
|
39270
|
+
const to = group[0];
|
|
39058
39271
|
// Move the cells.
|
|
39059
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
39060
|
-
// Effectively delete the
|
|
39061
|
-
|
|
39272
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
39273
|
+
// Effectively delete the rows
|
|
39274
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
39062
39275
|
}
|
|
39063
39276
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
39064
39277
|
if (count) {
|
|
@@ -39080,8 +39293,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
39080
39293
|
this.addEmptyRows(sheet, quantity);
|
|
39081
39294
|
// Move the cells.
|
|
39082
39295
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
39083
|
-
// Recompute the left-right/top-bottom.
|
|
39084
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
39085
39296
|
if (index < sheet.panes.ySplit) {
|
|
39086
39297
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
39087
39298
|
}
|
|
@@ -39182,35 +39393,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
39182
39393
|
}
|
|
39183
39394
|
}
|
|
39184
39395
|
}
|
|
39185
|
-
updateRowsStructureOnDeletion(
|
|
39396
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
39186
39397
|
const rows = [];
|
|
39187
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39398
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
39188
39399
|
for (let i in sheet.rows) {
|
|
39189
|
-
|
|
39400
|
+
const row = Number(i);
|
|
39401
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
39190
39402
|
continue;
|
|
39191
39403
|
}
|
|
39192
39404
|
rows.push({
|
|
39193
|
-
cells: cellsQueue.
|
|
39405
|
+
cells: cellsQueue.pop(),
|
|
39194
39406
|
});
|
|
39195
39407
|
}
|
|
39196
39408
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39197
39409
|
}
|
|
39198
|
-
/**
|
|
39199
|
-
* Update the rows of the sheet after an addition:
|
|
39200
|
-
* - Rename the rows
|
|
39201
|
-
*
|
|
39202
|
-
* @param sheet Sheet on which the deletion occurs
|
|
39203
|
-
* @param addedRow Index of the added row
|
|
39204
|
-
* @param rowsToAdd Number of the rows to add
|
|
39205
|
-
*/
|
|
39206
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
39207
|
-
const rows = [];
|
|
39208
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39209
|
-
sheet.rows.forEach(() => rows.push({
|
|
39210
|
-
cells: cellsQueue.shift(),
|
|
39211
|
-
}));
|
|
39212
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39213
|
-
}
|
|
39214
39410
|
/**
|
|
39215
39411
|
* Add empty rows at the end of the rows
|
|
39216
39412
|
*
|
|
@@ -39737,6 +39933,7 @@ class CompilationParametersBuilder {
|
|
|
39737
39933
|
getters;
|
|
39738
39934
|
computeCell;
|
|
39739
39935
|
evalContext;
|
|
39936
|
+
rangeCache = {};
|
|
39740
39937
|
constructor(context, getters, computeCell) {
|
|
39741
39938
|
this.getters = getters;
|
|
39742
39939
|
this.computeCell = computeCell;
|
|
@@ -39759,7 +39956,8 @@ class CompilationParametersBuilder {
|
|
|
39759
39956
|
refFn(range, isMeta, functionName, paramNumber) {
|
|
39760
39957
|
if (isMeta) {
|
|
39761
39958
|
// Use zoneToXc of zone instead of getRangeString to avoid sending unbounded ranges
|
|
39762
|
-
|
|
39959
|
+
const sheetName = this.getters.getSheetName(range.sheetId);
|
|
39960
|
+
return { value: getFullReference(sheetName, zoneToXc(range.zone)) };
|
|
39763
39961
|
}
|
|
39764
39962
|
if (!isZoneValid(range.zone)) {
|
|
39765
39963
|
throw new InvalidReferenceError();
|
|
@@ -39822,17 +40020,24 @@ class CompilationParametersBuilder {
|
|
|
39822
40020
|
if (!_zone) {
|
|
39823
40021
|
return [[]];
|
|
39824
40022
|
}
|
|
40023
|
+
const { top, left, bottom, right } = zone;
|
|
40024
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
40025
|
+
if (cacheKey in this.rangeCache) {
|
|
40026
|
+
return this.rangeCache[cacheKey];
|
|
40027
|
+
}
|
|
39825
40028
|
const height = _zone.bottom - _zone.top + 1;
|
|
39826
40029
|
const width = _zone.right - _zone.left + 1;
|
|
39827
|
-
const matrix = Array
|
|
40030
|
+
const matrix = new Array(width);
|
|
39828
40031
|
// Performance issue: nested loop is faster than a map here
|
|
39829
40032
|
for (let col = _zone.left; col <= _zone.right; col++) {
|
|
40033
|
+
const colIndex = col - _zone.left;
|
|
40034
|
+
matrix[colIndex] = new Array(height);
|
|
39830
40035
|
for (let row = _zone.top; row <= _zone.bottom; row++) {
|
|
39831
|
-
const colIndex = col - _zone.left;
|
|
39832
40036
|
const rowIndex = row - _zone.top;
|
|
39833
40037
|
matrix[colIndex][rowIndex] = this.readCell({ sheetId, col, row });
|
|
39834
40038
|
}
|
|
39835
40039
|
}
|
|
40040
|
+
this.rangeCache[cacheKey] = matrix;
|
|
39836
40041
|
return matrix;
|
|
39837
40042
|
}
|
|
39838
40043
|
}
|
|
@@ -40038,6 +40243,7 @@ class Evaluator {
|
|
|
40038
40243
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
40039
40244
|
}
|
|
40040
40245
|
updateCompilationParameters() {
|
|
40246
|
+
// rebuild the compilation parameters (with a clean cache)
|
|
40041
40247
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40042
40248
|
}
|
|
40043
40249
|
evaluateCells(positions) {
|
|
@@ -40081,6 +40287,16 @@ class Evaluator {
|
|
|
40081
40287
|
this.evaluatedCells = new Map();
|
|
40082
40288
|
this.evaluate(this.getAllCells());
|
|
40083
40289
|
}
|
|
40290
|
+
evaluateFormula(sheetId, formulaString) {
|
|
40291
|
+
const compiledFormula = compile(formulaString);
|
|
40292
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40293
|
+
this.updateCompilationParameters();
|
|
40294
|
+
const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
|
|
40295
|
+
if (isMatrix(result)) {
|
|
40296
|
+
return matrixMap(result, (cell) => cell.value);
|
|
40297
|
+
}
|
|
40298
|
+
return result.value;
|
|
40299
|
+
}
|
|
40084
40300
|
getAllCells() {
|
|
40085
40301
|
const positionIds = new JetSet();
|
|
40086
40302
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
@@ -40107,6 +40323,7 @@ class Evaluator {
|
|
|
40107
40323
|
this.nextPositionsToUpdate = cells;
|
|
40108
40324
|
let currentIteration = 0;
|
|
40109
40325
|
while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
|
|
40326
|
+
this.updateCompilationParameters();
|
|
40110
40327
|
const positionIds = Array.from(this.nextPositionsToUpdate);
|
|
40111
40328
|
this.nextPositionsToUpdate.clear();
|
|
40112
40329
|
for (let i = 0; i < positionIds.length; ++i) {
|
|
@@ -40130,7 +40347,8 @@ class Evaluator {
|
|
|
40130
40347
|
if (!this.blockedArrayFormulas.has(positionId)) {
|
|
40131
40348
|
this.invalidateSpreading(positionId);
|
|
40132
40349
|
}
|
|
40133
|
-
const
|
|
40350
|
+
const cellPosition = this.decodePosition(positionId);
|
|
40351
|
+
const cell = this.getters.getCell(cellPosition);
|
|
40134
40352
|
if (cell === undefined) {
|
|
40135
40353
|
return createEvaluatedCell("", { locale: this.getters.getLocale() });
|
|
40136
40354
|
}
|
|
@@ -40141,7 +40359,7 @@ class Evaluator {
|
|
|
40141
40359
|
}
|
|
40142
40360
|
this.cellsBeingComputed.add(cellId);
|
|
40143
40361
|
return cell.isFormula
|
|
40144
|
-
? this.computeFormulaCell(cell)
|
|
40362
|
+
? this.computeFormulaCell(cellPosition.sheetId, cell)
|
|
40145
40363
|
: evaluateLiteral(cell.content, { format: cell.format, locale: this.getters.getLocale() });
|
|
40146
40364
|
}
|
|
40147
40365
|
catch (e) {
|
|
@@ -40167,14 +40385,9 @@ class Evaluator {
|
|
|
40167
40385
|
e.message = e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled);
|
|
40168
40386
|
return errorCell(e);
|
|
40169
40387
|
}
|
|
40170
|
-
computeFormulaCell(cellData) {
|
|
40388
|
+
computeFormulaCell(sheetId, cellData) {
|
|
40171
40389
|
const cellId = cellData.id;
|
|
40172
|
-
this.compilationParams
|
|
40173
|
-
// compute the value lazily for performance reasons
|
|
40174
|
-
const position = this.compilationParams[2].getters.getCellPosition(cellId);
|
|
40175
|
-
return toXC(position.col, position.row);
|
|
40176
|
-
};
|
|
40177
|
-
const formulaReturn = cellData.compiledFormula.execute(cellData.compiledFormula.dependencies, ...this.compilationParams);
|
|
40390
|
+
const formulaReturn = updateEvalContextAndExecute(cellData.compiledFormula, this.compilationParams, sheetId, cellId);
|
|
40178
40391
|
if (!isMatrix(formulaReturn)) {
|
|
40179
40392
|
return createEvaluatedCell(formulaReturn.value, {
|
|
40180
40393
|
format: cellData.format || formulaReturn.format,
|
|
@@ -40376,6 +40589,18 @@ class PositionBitsEncoder {
|
|
|
40376
40589
|
return sheetId;
|
|
40377
40590
|
}
|
|
40378
40591
|
}
|
|
40592
|
+
function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
|
|
40593
|
+
compilationParams[2].__originCellXC = lazy(() => {
|
|
40594
|
+
if (!cellId) {
|
|
40595
|
+
return undefined;
|
|
40596
|
+
}
|
|
40597
|
+
// compute the value lazily for performance reasons
|
|
40598
|
+
const position = compilationParams[2].getters.getCellPosition(cellId);
|
|
40599
|
+
return toXC(position.col, position.row);
|
|
40600
|
+
});
|
|
40601
|
+
compilationParams[2].__originSheetId = sheetId;
|
|
40602
|
+
return compiledFormula.execute(compiledFormula.dependencies, ...compilationParams);
|
|
40603
|
+
}
|
|
40379
40604
|
|
|
40380
40605
|
//#region
|
|
40381
40606
|
// ---------------------------------------------------------------------------
|
|
@@ -40470,7 +40695,6 @@ class PositionBitsEncoder {
|
|
|
40470
40695
|
// of other cells depending on it, at the next iteration.
|
|
40471
40696
|
//#endregion
|
|
40472
40697
|
class EvaluationPlugin extends UIPlugin {
|
|
40473
|
-
config;
|
|
40474
40698
|
static getters = [
|
|
40475
40699
|
"evaluateFormula",
|
|
40476
40700
|
"getCorrespondingFormulaCell",
|
|
@@ -40481,15 +40705,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40481
40705
|
"getEvaluatedCells",
|
|
40482
40706
|
"getEvaluatedCellsInZone",
|
|
40483
40707
|
"getSpreadPositionsOf",
|
|
40708
|
+
"getArrayFormulaSpreadingOn",
|
|
40484
40709
|
];
|
|
40485
40710
|
shouldRebuildDependenciesGraph = true;
|
|
40486
40711
|
evaluator;
|
|
40487
|
-
compilationParams;
|
|
40488
40712
|
positionsToUpdate = [];
|
|
40489
40713
|
constructor(config) {
|
|
40490
40714
|
super(config);
|
|
40491
|
-
this.config = config;
|
|
40492
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40493
40715
|
this.evaluator = new Evaluator(config.custom, this.getters);
|
|
40494
40716
|
}
|
|
40495
40717
|
// ---------------------------------------------------------------------------
|
|
@@ -40514,10 +40736,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40514
40736
|
case "EVALUATE_CELLS":
|
|
40515
40737
|
this.evaluator.evaluateAllCells();
|
|
40516
40738
|
break;
|
|
40517
|
-
case "UPDATE_LOCALE":
|
|
40518
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40519
|
-
this.evaluator.updateCompilationParameters();
|
|
40520
|
-
break;
|
|
40521
40739
|
}
|
|
40522
40740
|
}
|
|
40523
40741
|
finalize() {
|
|
@@ -40535,16 +40753,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40535
40753
|
// Getters
|
|
40536
40754
|
// ---------------------------------------------------------------------------
|
|
40537
40755
|
evaluateFormula(sheetId, formulaString) {
|
|
40538
|
-
|
|
40539
|
-
const ranges = [];
|
|
40540
|
-
for (let xc of compiledFormula.dependencies) {
|
|
40541
|
-
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40542
|
-
}
|
|
40543
|
-
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40544
|
-
if (isMatrix(array)) {
|
|
40545
|
-
return array.map((col) => col.map((row) => row.value));
|
|
40546
|
-
}
|
|
40547
|
-
return array.value;
|
|
40756
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
40548
40757
|
}
|
|
40549
40758
|
/**
|
|
40550
40759
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -40593,6 +40802,9 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40593
40802
|
getSpreadPositionsOf(position) {
|
|
40594
40803
|
return this.evaluator.getSpreadPositionsOf(position);
|
|
40595
40804
|
}
|
|
40805
|
+
getArrayFormulaSpreadingOn(position) {
|
|
40806
|
+
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
40807
|
+
}
|
|
40596
40808
|
// ---------------------------------------------------------------------------
|
|
40597
40809
|
// Export
|
|
40598
40810
|
// ---------------------------------------------------------------------------
|
|
@@ -40636,7 +40848,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40636
40848
|
else if (cell && cell.content) {
|
|
40637
40849
|
return undefined;
|
|
40638
40850
|
}
|
|
40639
|
-
const spreadingFormulaPosition = this.
|
|
40851
|
+
const spreadingFormulaPosition = this.getArrayFormulaSpreadingOn(position);
|
|
40640
40852
|
if (spreadingFormulaPosition === undefined) {
|
|
40641
40853
|
return undefined;
|
|
40642
40854
|
}
|
|
@@ -40646,9 +40858,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40646
40858
|
}
|
|
40647
40859
|
return undefined;
|
|
40648
40860
|
}
|
|
40649
|
-
getCompilationParameters() {
|
|
40650
|
-
return buildCompilationParameters(this.config.custom, this.getters, (position) => this.evaluator.getEvaluatedCell(position));
|
|
40651
|
-
}
|
|
40652
40861
|
}
|
|
40653
40862
|
function isBadExpression(tokens) {
|
|
40654
40863
|
try {
|
|
@@ -43347,11 +43556,26 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43347
43556
|
let cellsInRow = [];
|
|
43348
43557
|
for (let col of columnsIndex) {
|
|
43349
43558
|
const position = { col, row, sheetId };
|
|
43559
|
+
const spreader = getters.getArrayFormulaSpreadingOn(position);
|
|
43560
|
+
let cell = getters.getCell(position);
|
|
43561
|
+
const evaluatedCell = getters.getEvaluatedCell(position);
|
|
43562
|
+
if (spreader) {
|
|
43563
|
+
const isSpreaderCopied = rowsIndex.includes(spreader.row) && columnsIndex.includes(spreader.col);
|
|
43564
|
+
const content = isSpreaderCopied
|
|
43565
|
+
? ""
|
|
43566
|
+
: formatValue(evaluatedCell.value, { locale: getters.getLocale() });
|
|
43567
|
+
cell = {
|
|
43568
|
+
id: cell?.id || "",
|
|
43569
|
+
style: cell?.style,
|
|
43570
|
+
format: evaluatedCell.format,
|
|
43571
|
+
content,
|
|
43572
|
+
isFormula: false,
|
|
43573
|
+
};
|
|
43574
|
+
}
|
|
43350
43575
|
cellsInRow.push({
|
|
43351
|
-
cell
|
|
43352
|
-
style: getters.getCellComputedStyle(position),
|
|
43353
|
-
evaluatedCell: getters.getEvaluatedCell(position),
|
|
43576
|
+
cell,
|
|
43354
43577
|
border: getters.getCellBorder(position) || undefined,
|
|
43578
|
+
evaluatedCell,
|
|
43355
43579
|
position,
|
|
43356
43580
|
});
|
|
43357
43581
|
}
|
|
@@ -43473,13 +43697,6 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43473
43697
|
});
|
|
43474
43698
|
}
|
|
43475
43699
|
this.pasteCopiedTables(target);
|
|
43476
|
-
this.cells.forEach((row) => {
|
|
43477
|
-
row.forEach((c) => {
|
|
43478
|
-
if (c.cell) {
|
|
43479
|
-
c.cell = undefined;
|
|
43480
|
-
}
|
|
43481
|
-
});
|
|
43482
|
-
});
|
|
43483
43700
|
}
|
|
43484
43701
|
/**
|
|
43485
43702
|
* The clipped zone is copied as many times as it fits in the target.
|
|
@@ -43553,7 +43770,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43553
43770
|
clearClippedZones() {
|
|
43554
43771
|
for (const row of this.cells) {
|
|
43555
43772
|
for (const cell of row) {
|
|
43556
|
-
if (cell
|
|
43773
|
+
if (cell?.cell) {
|
|
43557
43774
|
this.dispatch("CLEAR_CELL", cell.position);
|
|
43558
43775
|
}
|
|
43559
43776
|
}
|
|
@@ -43579,6 +43796,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43579
43796
|
const rowCells = this.cells[r];
|
|
43580
43797
|
for (let c = 0; c < width; c++) {
|
|
43581
43798
|
const origin = rowCells[c];
|
|
43799
|
+
if (!origin) {
|
|
43800
|
+
continue;
|
|
43801
|
+
}
|
|
43582
43802
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
43583
43803
|
// TODO: refactor this part. the "Paste merge" action is also executed with
|
|
43584
43804
|
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
@@ -43602,53 +43822,42 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43602
43822
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43603
43823
|
const { sheetId, col, row } = target;
|
|
43604
43824
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43605
|
-
if (clipboardOption?.pasteOption
|
|
43606
|
-
const
|
|
43607
|
-
const
|
|
43608
|
-
|
|
43609
|
-
|
|
43610
|
-
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43611
|
-
left: targetBorders?.left || originBorders?.left,
|
|
43612
|
-
right: targetBorders?.right || originBorders?.right,
|
|
43613
|
-
};
|
|
43614
|
-
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43825
|
+
if (clipboardOption?.pasteOption === "onlyValue") {
|
|
43826
|
+
const locale = this.getters.getLocale();
|
|
43827
|
+
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43828
|
+
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
43829
|
+
return;
|
|
43615
43830
|
}
|
|
43616
|
-
|
|
43617
|
-
|
|
43618
|
-
|
|
43619
|
-
|
|
43620
|
-
|
|
43621
|
-
|
|
43622
|
-
|
|
43623
|
-
|
|
43624
|
-
|
|
43625
|
-
|
|
43626
|
-
|
|
43627
|
-
|
|
43628
|
-
|
|
43629
|
-
|
|
43630
|
-
}
|
|
43631
|
-
|
|
43632
|
-
|
|
43633
|
-
|
|
43634
|
-
|
|
43831
|
+
const targetBorders = this.getters.getCellBorder(target);
|
|
43832
|
+
const originBorders = origin.border;
|
|
43833
|
+
const border = {
|
|
43834
|
+
top: targetBorders?.top || originBorders?.top,
|
|
43835
|
+
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43836
|
+
left: targetBorders?.left || originBorders?.left,
|
|
43837
|
+
right: targetBorders?.right || originBorders?.right,
|
|
43838
|
+
};
|
|
43839
|
+
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43840
|
+
if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43841
|
+
this.dispatch("UPDATE_CELL", {
|
|
43842
|
+
...target,
|
|
43843
|
+
style: origin.cell?.style ?? null,
|
|
43844
|
+
format: origin.cell?.format ?? origin.evaluatedCell.format ?? targetCell.format,
|
|
43845
|
+
});
|
|
43846
|
+
return;
|
|
43847
|
+
}
|
|
43848
|
+
const content = origin.cell && origin.cell.isFormula && operation === "COPY"
|
|
43849
|
+
? this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula)
|
|
43850
|
+
: origin.cell?.content;
|
|
43851
|
+
if (content !== "" || origin.cell?.format || origin.cell?.style) {
|
|
43635
43852
|
this.dispatch("UPDATE_CELL", {
|
|
43636
43853
|
...target,
|
|
43637
43854
|
content,
|
|
43638
|
-
style: origin.cell
|
|
43639
|
-
format: origin.cell
|
|
43855
|
+
style: origin.cell?.style || null,
|
|
43856
|
+
format: origin.cell?.format,
|
|
43640
43857
|
});
|
|
43641
43858
|
}
|
|
43642
43859
|
else if (targetCell) {
|
|
43643
|
-
|
|
43644
|
-
this.dispatch("UPDATE_CELL", { ...target, content: "" });
|
|
43645
|
-
}
|
|
43646
|
-
else if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43647
|
-
this.dispatch("UPDATE_CELL", { ...target, style: null, format: "" });
|
|
43648
|
-
}
|
|
43649
|
-
else {
|
|
43650
|
-
this.dispatch("CLEAR_CELL", target);
|
|
43651
|
-
}
|
|
43860
|
+
this.dispatch("CLEAR_CELL", target);
|
|
43652
43861
|
}
|
|
43653
43862
|
}
|
|
43654
43863
|
/**
|
|
@@ -43710,22 +43919,28 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43710
43919
|
return (this.cells
|
|
43711
43920
|
.map((cells) => {
|
|
43712
43921
|
return cells
|
|
43713
|
-
.map((c) => this.getters.shouldShowFormulas() && c
|
|
43922
|
+
.map((c) => this.getters.shouldShowFormulas() && c?.cell?.isFormula
|
|
43714
43923
|
? c.cell?.content || ""
|
|
43715
|
-
: c
|
|
43924
|
+
: c?.evaluatedCell?.formattedValue || "")
|
|
43716
43925
|
.join("\t");
|
|
43717
43926
|
})
|
|
43718
43927
|
.join("\n") || "\t");
|
|
43719
43928
|
}
|
|
43720
43929
|
getHTMLContent() {
|
|
43721
43930
|
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
43931
|
+
if (!this.cells[0][0]) {
|
|
43932
|
+
return "";
|
|
43933
|
+
}
|
|
43722
43934
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
43723
43935
|
}
|
|
43724
43936
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
43725
43937
|
for (const row of this.cells) {
|
|
43726
43938
|
htmlTable += "<tr>";
|
|
43727
43939
|
for (const cell of row) {
|
|
43728
|
-
|
|
43940
|
+
if (!cell) {
|
|
43941
|
+
continue;
|
|
43942
|
+
}
|
|
43943
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
43729
43944
|
const cellText = this.getters.getCellText(cell.position);
|
|
43730
43945
|
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
43731
43946
|
}
|
|
@@ -44053,24 +44268,49 @@ var Direction;
|
|
|
44053
44268
|
*/
|
|
44054
44269
|
class FindAndReplacePlugin extends UIPlugin {
|
|
44055
44270
|
static layers = [3 /* LAYERS.Search */];
|
|
44056
|
-
static getters = [
|
|
44057
|
-
|
|
44271
|
+
static getters = [
|
|
44272
|
+
"getSearchMatches",
|
|
44273
|
+
"getCurrentSelectedMatchIndex",
|
|
44274
|
+
"getSearchOptions",
|
|
44275
|
+
"getAllSheetMatchesCount",
|
|
44276
|
+
"getActiveSheetMatchesCount",
|
|
44277
|
+
"getSpecificRangeMatchesCount",
|
|
44278
|
+
];
|
|
44279
|
+
allSheetsMatches = [];
|
|
44280
|
+
activeSheetMatches = [];
|
|
44281
|
+
specificRangeMatches = [];
|
|
44282
|
+
// fixme: why do we make selectedMatchIndex on top of a selected
|
|
44283
|
+
// property in the matches?
|
|
44058
44284
|
selectedMatchIndex = null;
|
|
44059
44285
|
currentSearchRegex = null;
|
|
44060
44286
|
searchOptions = {
|
|
44061
44287
|
matchCase: false,
|
|
44062
44288
|
exactMatch: false,
|
|
44063
44289
|
searchFormulas: false,
|
|
44290
|
+
searchScope: "allSheets",
|
|
44291
|
+
specificRange: undefined,
|
|
44064
44292
|
};
|
|
44065
44293
|
toSearch = "";
|
|
44066
44294
|
isSearchDirty = false;
|
|
44295
|
+
get searchMatches() {
|
|
44296
|
+
switch (this.searchOptions.searchScope) {
|
|
44297
|
+
case "allSheets":
|
|
44298
|
+
return this.allSheetsMatches;
|
|
44299
|
+
case "activeSheet":
|
|
44300
|
+
return this.activeSheetMatches;
|
|
44301
|
+
case "specificRange":
|
|
44302
|
+
return this.specificRangeMatches;
|
|
44303
|
+
}
|
|
44304
|
+
}
|
|
44067
44305
|
// ---------------------------------------------------------------------------
|
|
44068
44306
|
// Command Handling
|
|
44069
44307
|
// ---------------------------------------------------------------------------
|
|
44070
44308
|
handle(cmd) {
|
|
44071
44309
|
switch (cmd.type) {
|
|
44072
44310
|
case "UPDATE_SEARCH":
|
|
44073
|
-
|
|
44311
|
+
const rangeData = cmd.searchOptions.specificRange;
|
|
44312
|
+
const specificRange = rangeData && this.getters.getRangeFromRangeData(rangeData);
|
|
44313
|
+
this.updateSearch(cmd.toSearch, { ...cmd.searchOptions, specificRange });
|
|
44074
44314
|
break;
|
|
44075
44315
|
case "CLEAR_SEARCH":
|
|
44076
44316
|
this.clearSearch();
|
|
@@ -44100,7 +44340,9 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44100
44340
|
this.isSearchDirty = true;
|
|
44101
44341
|
break;
|
|
44102
44342
|
case "ACTIVATE_SHEET":
|
|
44103
|
-
this.
|
|
44343
|
+
if (this.searchOptions.searchScope === "activeSheet") {
|
|
44344
|
+
this.isSearchDirty = true;
|
|
44345
|
+
}
|
|
44104
44346
|
break;
|
|
44105
44347
|
}
|
|
44106
44348
|
}
|
|
@@ -44119,6 +44361,18 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44119
44361
|
getCurrentSelectedMatchIndex() {
|
|
44120
44362
|
return this.selectedMatchIndex;
|
|
44121
44363
|
}
|
|
44364
|
+
getSearchOptions() {
|
|
44365
|
+
return { ...this.searchOptions, specificRange: this.searchOptions.specificRange?.rangeData };
|
|
44366
|
+
}
|
|
44367
|
+
getAllSheetMatchesCount() {
|
|
44368
|
+
return this.allSheetsMatches.length;
|
|
44369
|
+
}
|
|
44370
|
+
getActiveSheetMatchesCount() {
|
|
44371
|
+
return this.activeSheetMatches.length;
|
|
44372
|
+
}
|
|
44373
|
+
getSpecificRangeMatchesCount() {
|
|
44374
|
+
return this.specificRangeMatches.length;
|
|
44375
|
+
}
|
|
44122
44376
|
// ---------------------------------------------------------------------------
|
|
44123
44377
|
// Search
|
|
44124
44378
|
// ---------------------------------------------------------------------------
|
|
@@ -44139,8 +44393,8 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44139
44393
|
* refresh the matches according to the current search options
|
|
44140
44394
|
*/
|
|
44141
44395
|
refreshSearch() {
|
|
44142
|
-
|
|
44143
|
-
this.
|
|
44396
|
+
this.selectedMatchIndex = null;
|
|
44397
|
+
this.findMatches();
|
|
44144
44398
|
this.selectNextCell(Direction.current);
|
|
44145
44399
|
}
|
|
44146
44400
|
/**
|
|
@@ -44155,45 +44409,65 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44155
44409
|
}
|
|
44156
44410
|
this.currentSearchRegex = RegExp(searchValue, flags);
|
|
44157
44411
|
}
|
|
44412
|
+
getSheetsInSearchOrder() {
|
|
44413
|
+
switch (this.searchOptions.searchScope) {
|
|
44414
|
+
case "allSheets":
|
|
44415
|
+
const sheetIds = this.getters.getSheetIds();
|
|
44416
|
+
const activeSheetIndex = sheetIds.findIndex((id) => id === this.getters.getActiveSheetId());
|
|
44417
|
+
return [
|
|
44418
|
+
sheetIds[activeSheetIndex],
|
|
44419
|
+
...sheetIds.slice(activeSheetIndex + 1),
|
|
44420
|
+
...sheetIds.slice(0, activeSheetIndex),
|
|
44421
|
+
];
|
|
44422
|
+
case "activeSheet":
|
|
44423
|
+
return [this.getters.getActiveSheetId()];
|
|
44424
|
+
case "specificRange":
|
|
44425
|
+
const specificRange = this.searchOptions.specificRange;
|
|
44426
|
+
if (!specificRange) {
|
|
44427
|
+
return [];
|
|
44428
|
+
}
|
|
44429
|
+
return specificRange ? [specificRange.sheetId] : [];
|
|
44430
|
+
}
|
|
44431
|
+
}
|
|
44158
44432
|
/**
|
|
44159
44433
|
* Find matches using the current regex
|
|
44160
44434
|
*/
|
|
44161
44435
|
findMatches() {
|
|
44162
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
44163
|
-
const cells = this.getters.getCells(sheetId);
|
|
44164
44436
|
const matches = [];
|
|
44165
|
-
if (this.toSearch
|
|
44166
|
-
for (const
|
|
44167
|
-
|
|
44168
|
-
|
|
44437
|
+
if (this.toSearch) {
|
|
44438
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
44439
|
+
matches.push(...this.findMatchesInSheet(sheetId));
|
|
44440
|
+
}
|
|
44441
|
+
}
|
|
44442
|
+
// set results
|
|
44443
|
+
this.allSheetsMatches = matches;
|
|
44444
|
+
this.activeSheetMatches = matches.filter((match) => match.sheetId === this.getters.getActiveSheetId());
|
|
44445
|
+
if (this.searchOptions.specificRange) {
|
|
44446
|
+
const { sheetId, zone } = this.searchOptions.specificRange;
|
|
44447
|
+
this.specificRangeMatches = matches.filter((match) => match.sheetId === sheetId && isInside(match.col, match.row, zone));
|
|
44448
|
+
}
|
|
44449
|
+
else {
|
|
44450
|
+
this.specificRangeMatches = [];
|
|
44451
|
+
}
|
|
44452
|
+
}
|
|
44453
|
+
findMatchesInSheet(sheetId) {
|
|
44454
|
+
const matches = [];
|
|
44455
|
+
const { left, right, top, bottom } = this.getters.getSheetZone(sheetId);
|
|
44456
|
+
for (let row = top; row <= bottom; row++) {
|
|
44457
|
+
for (let col = left; col <= right; col++) {
|
|
44169
44458
|
const isColHidden = this.getters.isColHidden(sheetId, col);
|
|
44170
44459
|
const isRowHidden = this.getters.isRowHidden(sheetId, row);
|
|
44171
44460
|
if (isColHidden || isRowHidden) {
|
|
44172
44461
|
continue;
|
|
44173
44462
|
}
|
|
44174
|
-
|
|
44175
|
-
|
|
44463
|
+
const cellPosition = { sheetId, col, row };
|
|
44464
|
+
if (this.currentSearchRegex?.test(this.getSearchableString(cellPosition))) {
|
|
44465
|
+
const match = { sheetId, col, row };
|
|
44176
44466
|
matches.push(match);
|
|
44177
44467
|
}
|
|
44178
|
-
for (const spreadPosition of this.getters.getSpreadPositionsOf(cellPosition)) {
|
|
44179
|
-
if (this.currentSearchRegex.test(this.getSearchableString(spreadPosition))) {
|
|
44180
|
-
const match = {
|
|
44181
|
-
col: spreadPosition.col,
|
|
44182
|
-
row: spreadPosition.row,
|
|
44183
|
-
selected: false,
|
|
44184
|
-
};
|
|
44185
|
-
matches.push(match);
|
|
44186
|
-
}
|
|
44187
|
-
}
|
|
44188
44468
|
}
|
|
44189
44469
|
}
|
|
44190
|
-
return matches
|
|
44191
|
-
}
|
|
44192
|
-
sortByRowThenColumn(a, b) {
|
|
44193
|
-
if (a.row === b.row) {
|
|
44194
|
-
return a.col - b.col;
|
|
44195
|
-
}
|
|
44196
|
-
return a.row > b.row ? 1 : -1;
|
|
44470
|
+
return matches;
|
|
44197
44471
|
}
|
|
44198
44472
|
/**
|
|
44199
44473
|
* Changes the selected search cell. Given a direction it will
|
|
@@ -44211,30 +44485,47 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44211
44485
|
}
|
|
44212
44486
|
let nextIndex;
|
|
44213
44487
|
if (this.selectedMatchIndex === null) {
|
|
44214
|
-
|
|
44488
|
+
let nextMatchIndex = -1;
|
|
44489
|
+
// if search is not available in current sheet will select in next sheet
|
|
44490
|
+
for (const sheetId of this.getSheetsInSearchOrder()) {
|
|
44491
|
+
nextMatchIndex = matches.findIndex((match) => match.sheetId === sheetId);
|
|
44492
|
+
if (nextMatchIndex !== -1) {
|
|
44493
|
+
break;
|
|
44494
|
+
}
|
|
44495
|
+
}
|
|
44496
|
+
nextIndex = nextMatchIndex;
|
|
44215
44497
|
}
|
|
44216
44498
|
else {
|
|
44217
44499
|
nextIndex = this.selectedMatchIndex + indexChange;
|
|
44218
44500
|
}
|
|
44219
|
-
//
|
|
44220
|
-
nextIndex = (
|
|
44501
|
+
// loop index value inside the array (index -1 => last index)
|
|
44502
|
+
nextIndex = (nextIndex + matches.length) % matches.length;
|
|
44221
44503
|
this.selectedMatchIndex = nextIndex;
|
|
44504
|
+
const selectedMatch = matches[nextIndex];
|
|
44505
|
+
// Switch to the sheet where the match is located
|
|
44506
|
+
if (this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
|
|
44507
|
+
this.dispatch("ACTIVATE_SHEET", {
|
|
44508
|
+
sheetIdFrom: this.getters.getActiveSheetId(),
|
|
44509
|
+
sheetIdTo: selectedMatch.sheetId,
|
|
44510
|
+
});
|
|
44511
|
+
}
|
|
44222
44512
|
// we want grid selection to capture the selection stream
|
|
44223
44513
|
this.selection.getBackToDefault();
|
|
44224
|
-
this.selection.selectCell(
|
|
44225
|
-
for (let index = 0; index < this.searchMatches.length; index++) {
|
|
44226
|
-
this.searchMatches[index].selected = index === this.selectedMatchIndex;
|
|
44227
|
-
}
|
|
44514
|
+
this.selection.selectCell(selectedMatch.col, selectedMatch.row);
|
|
44228
44515
|
}
|
|
44229
44516
|
clearSearch() {
|
|
44230
44517
|
this.toSearch = "";
|
|
44231
|
-
this.searchMatches = [];
|
|
44232
44518
|
this.selectedMatchIndex = null;
|
|
44233
44519
|
this.currentSearchRegex = null;
|
|
44520
|
+
this.allSheetsMatches = [];
|
|
44521
|
+
this.activeSheetMatches = [];
|
|
44522
|
+
this.specificRangeMatches = [];
|
|
44234
44523
|
this.searchOptions = {
|
|
44235
44524
|
matchCase: false,
|
|
44236
44525
|
exactMatch: false,
|
|
44237
44526
|
searchFormulas: false,
|
|
44527
|
+
searchScope: "allSheets",
|
|
44528
|
+
specificRange: undefined,
|
|
44238
44529
|
};
|
|
44239
44530
|
}
|
|
44240
44531
|
// ---------------------------------------------------------------------------
|
|
@@ -44244,9 +44535,7 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44244
44535
|
if (!this.currentSearchRegex) {
|
|
44245
44536
|
return;
|
|
44246
44537
|
}
|
|
44247
|
-
const
|
|
44248
|
-
const position = { sheetId, ...selectedMatch };
|
|
44249
|
-
const cell = this.getters.getCell(position);
|
|
44538
|
+
const cell = this.getters.getCell(selectedMatch);
|
|
44250
44539
|
if (!cell?.content) {
|
|
44251
44540
|
return;
|
|
44252
44541
|
}
|
|
@@ -44254,10 +44543,10 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44254
44543
|
return;
|
|
44255
44544
|
}
|
|
44256
44545
|
const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
|
|
44257
|
-
const toReplace = this.getSearchableString(
|
|
44546
|
+
const toReplace = this.getSearchableString(selectedMatch);
|
|
44258
44547
|
const content = toReplace.replace(replaceRegex, replaceWith);
|
|
44259
44548
|
const canonicalContent = canonicalizeNumberContent(content, this.getters.getLocale());
|
|
44260
|
-
this.dispatch("UPDATE_CELL", { ...
|
|
44549
|
+
this.dispatch("UPDATE_CELL", { ...selectedMatch, content: canonicalContent });
|
|
44261
44550
|
}
|
|
44262
44551
|
/**
|
|
44263
44552
|
* Replace the value of the currently selected match
|
|
@@ -44288,7 +44577,10 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44288
44577
|
drawGrid(renderingContext) {
|
|
44289
44578
|
const { ctx } = renderingContext;
|
|
44290
44579
|
const sheetId = this.getters.getActiveSheetId();
|
|
44291
|
-
for (const match of this.searchMatches) {
|
|
44580
|
+
for (const [index, match] of this.searchMatches.entries()) {
|
|
44581
|
+
if (match.sheetId !== sheetId) {
|
|
44582
|
+
continue; // Skip drawing matches from other sheets
|
|
44583
|
+
}
|
|
44292
44584
|
const merge = this.getters.getMerge({ sheetId, col: match.col, row: match.row });
|
|
44293
44585
|
const left = merge ? merge.left : match.col;
|
|
44294
44586
|
const right = merge ? merge.right : match.col;
|
|
@@ -44298,12 +44590,21 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44298
44590
|
if (width > 0 && height > 0) {
|
|
44299
44591
|
ctx.fillStyle = BACKGROUND_COLOR;
|
|
44300
44592
|
ctx.fillRect(x, y, width, height);
|
|
44301
|
-
if (
|
|
44593
|
+
if (index === this.selectedMatchIndex) {
|
|
44302
44594
|
ctx.strokeStyle = BORDER_COLOR;
|
|
44303
44595
|
ctx.strokeRect(x, y, width, height);
|
|
44304
44596
|
}
|
|
44305
44597
|
}
|
|
44306
44598
|
}
|
|
44599
|
+
if (this.searchOptions.searchScope === "specificRange") {
|
|
44600
|
+
const range = this.searchOptions.specificRange;
|
|
44601
|
+
if (!range || range.sheetId !== sheetId) {
|
|
44602
|
+
return;
|
|
44603
|
+
}
|
|
44604
|
+
const { x, y, width, height } = this.getters.getVisibleRect(range.zone);
|
|
44605
|
+
ctx.strokeStyle = BORDER_COLOR;
|
|
44606
|
+
ctx.strokeRect(x, y, width, height);
|
|
44607
|
+
}
|
|
44307
44608
|
}
|
|
44308
44609
|
}
|
|
44309
44610
|
|
|
@@ -46769,11 +47070,14 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
46769
47070
|
}
|
|
46770
47071
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
46771
47072
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
47073
|
+
if (this.state.operation === "CUT") {
|
|
47074
|
+
this.state = undefined;
|
|
47075
|
+
}
|
|
46772
47076
|
this.lastPasteState = this.state;
|
|
46773
47077
|
if (this.paintFormatStatus === "oneOff") {
|
|
46774
47078
|
this.paintFormatStatus = "inactive";
|
|
46775
|
-
this.status = "invisible";
|
|
46776
47079
|
}
|
|
47080
|
+
this.status = "invisible";
|
|
46777
47081
|
break;
|
|
46778
47082
|
case "COPY_PASTE_CELLS_ABOVE":
|
|
46779
47083
|
{
|
|
@@ -47000,92 +47304,6 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
47000
47304
|
}
|
|
47001
47305
|
}
|
|
47002
47306
|
|
|
47003
|
-
/**
|
|
47004
|
-
* Change the reference types inside the given token, if the token represent a range or a cell
|
|
47005
|
-
*
|
|
47006
|
-
* Eg. :
|
|
47007
|
-
* A1 => $A$1 => A$1 => $A1 => A1
|
|
47008
|
-
* A1:$B$1 => $A$1:B$1 => A$1:$B1 => $A1:B1 => A1:$B$1
|
|
47009
|
-
*/
|
|
47010
|
-
function loopThroughReferenceType(token) {
|
|
47011
|
-
if (token.type !== "REFERENCE")
|
|
47012
|
-
return token;
|
|
47013
|
-
const { xc, sheetName } = splitReference(token.value);
|
|
47014
|
-
const [left, right] = xc.split(":");
|
|
47015
|
-
const sheetRef = sheetName ? `${getCanonicalSheetName(sheetName)}!` : "";
|
|
47016
|
-
const updatedLeft = getTokenNextReferenceType(left);
|
|
47017
|
-
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
47018
|
-
return { ...token, value: sheetRef + updatedLeft + updatedRight };
|
|
47019
|
-
}
|
|
47020
|
-
/**
|
|
47021
|
-
* Get a new token with a changed type of reference from the given cell token symbol.
|
|
47022
|
-
* Undefined behavior if given a token other than a cell or if the Xc contains a sheet reference
|
|
47023
|
-
*
|
|
47024
|
-
* A1 => $A$1 => A$1 => $A1 => A1
|
|
47025
|
-
*/
|
|
47026
|
-
function getTokenNextReferenceType(xc) {
|
|
47027
|
-
switch (getReferenceType(xc)) {
|
|
47028
|
-
case "none":
|
|
47029
|
-
xc = setXcToReferenceType(xc, "colrow");
|
|
47030
|
-
break;
|
|
47031
|
-
case "colrow":
|
|
47032
|
-
xc = setXcToReferenceType(xc, "row");
|
|
47033
|
-
break;
|
|
47034
|
-
case "row":
|
|
47035
|
-
xc = setXcToReferenceType(xc, "col");
|
|
47036
|
-
break;
|
|
47037
|
-
case "col":
|
|
47038
|
-
xc = setXcToReferenceType(xc, "none");
|
|
47039
|
-
break;
|
|
47040
|
-
}
|
|
47041
|
-
return xc;
|
|
47042
|
-
}
|
|
47043
|
-
/**
|
|
47044
|
-
* Returns the given XC with the given reference type.
|
|
47045
|
-
*/
|
|
47046
|
-
function setXcToReferenceType(xc, referenceType) {
|
|
47047
|
-
xc = xc.replace(/\$/g, "");
|
|
47048
|
-
let indexOfNumber;
|
|
47049
|
-
switch (referenceType) {
|
|
47050
|
-
case "col":
|
|
47051
|
-
return "$" + xc;
|
|
47052
|
-
case "row":
|
|
47053
|
-
indexOfNumber = xc.search(/[0-9]/);
|
|
47054
|
-
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47055
|
-
case "colrow":
|
|
47056
|
-
indexOfNumber = xc.search(/[0-9]/);
|
|
47057
|
-
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47058
|
-
return "$" + xc;
|
|
47059
|
-
case "none":
|
|
47060
|
-
return xc;
|
|
47061
|
-
}
|
|
47062
|
-
}
|
|
47063
|
-
/**
|
|
47064
|
-
* Return the type of reference used in the given XC of a cell.
|
|
47065
|
-
* Undefined behavior if the XC have a sheet reference
|
|
47066
|
-
*/
|
|
47067
|
-
function getReferenceType(xcCell) {
|
|
47068
|
-
if (isColAndRowFixed(xcCell)) {
|
|
47069
|
-
return "colrow";
|
|
47070
|
-
}
|
|
47071
|
-
else if (isColFixed(xcCell)) {
|
|
47072
|
-
return "col";
|
|
47073
|
-
}
|
|
47074
|
-
else if (isRowFixed(xcCell)) {
|
|
47075
|
-
return "row";
|
|
47076
|
-
}
|
|
47077
|
-
return "none";
|
|
47078
|
-
}
|
|
47079
|
-
function isColFixed(xc) {
|
|
47080
|
-
return xc.startsWith("$");
|
|
47081
|
-
}
|
|
47082
|
-
function isRowFixed(xc) {
|
|
47083
|
-
return xc.includes("$", 1);
|
|
47084
|
-
}
|
|
47085
|
-
function isColAndRowFixed(xc) {
|
|
47086
|
-
return xc.startsWith("$") && xc.length > 1 && xc.slice(1).includes("$");
|
|
47087
|
-
}
|
|
47088
|
-
|
|
47089
47307
|
const CELL_DELETED_MESSAGE = _t("The cell you are trying to edit has been deleted.");
|
|
47090
47308
|
class EditionPlugin extends UIPlugin {
|
|
47091
47309
|
static getters = [
|
|
@@ -48003,32 +48221,32 @@ const selectionStatisticFunctions = [
|
|
|
48003
48221
|
{
|
|
48004
48222
|
name: _t("Sum"),
|
|
48005
48223
|
types: [CellValueType.number],
|
|
48006
|
-
compute: (values, locale) =>
|
|
48224
|
+
compute: (values, locale) => sum([[values]], locale),
|
|
48007
48225
|
},
|
|
48008
48226
|
{
|
|
48009
48227
|
name: _t("Avg"),
|
|
48010
48228
|
types: [CellValueType.number],
|
|
48011
|
-
compute: (values, locale) =>
|
|
48229
|
+
compute: (values, locale) => average([[values]], locale),
|
|
48012
48230
|
},
|
|
48013
48231
|
{
|
|
48014
48232
|
name: _t("Min"),
|
|
48015
48233
|
types: [CellValueType.number],
|
|
48016
|
-
compute: (values, locale) =>
|
|
48234
|
+
compute: (values, locale) => min([[values]], locale),
|
|
48017
48235
|
},
|
|
48018
48236
|
{
|
|
48019
48237
|
name: _t("Max"),
|
|
48020
48238
|
types: [CellValueType.number],
|
|
48021
|
-
compute: (values, locale) =>
|
|
48239
|
+
compute: (values, locale) => max([[values]], locale),
|
|
48022
48240
|
},
|
|
48023
48241
|
{
|
|
48024
48242
|
name: _t("Count"),
|
|
48025
48243
|
types: [CellValueType.number, CellValueType.text, CellValueType.boolean, CellValueType.error],
|
|
48026
|
-
compute: (values
|
|
48244
|
+
compute: (values) => countAny([[values]]),
|
|
48027
48245
|
},
|
|
48028
48246
|
{
|
|
48029
48247
|
name: _t("Count Numbers"),
|
|
48030
48248
|
types: [CellValueType.number, CellValueType.text, CellValueType.boolean, CellValueType.error],
|
|
48031
|
-
compute: (values, locale) =>
|
|
48249
|
+
compute: (values, locale) => countNumbers([[values]], locale),
|
|
48032
48250
|
},
|
|
48033
48251
|
];
|
|
48034
48252
|
/**
|
|
@@ -51943,6 +52161,7 @@ class Spreadsheet extends owl.Component {
|
|
|
51943
52161
|
};
|
|
51944
52162
|
sidePanel;
|
|
51945
52163
|
composer;
|
|
52164
|
+
spreadsheetRef = owl.useRef("spreadsheet");
|
|
51946
52165
|
_focusGrid;
|
|
51947
52166
|
keyDownMapping;
|
|
51948
52167
|
isViewportTooSmall = false;
|
|
@@ -51977,6 +52196,18 @@ class Spreadsheet extends owl.Component {
|
|
|
51977
52196
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
51978
52197
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
51979
52198
|
});
|
|
52199
|
+
owl.useEffect(() => {
|
|
52200
|
+
/**
|
|
52201
|
+
* Only refocus the grid if the active element is not a child of the spreadsheet
|
|
52202
|
+
* (i.e. activeElement is outside of the spreadsheetRef component)
|
|
52203
|
+
* and spreadsheet is a child of that element. Anything else means that the focus
|
|
52204
|
+
* is on an element that needs to keep it.
|
|
52205
|
+
*/
|
|
52206
|
+
if (!this.spreadsheetRef.el.contains(document.activeElement) &&
|
|
52207
|
+
document.activeElement?.contains(this.spreadsheetRef.el)) {
|
|
52208
|
+
this.focusGrid();
|
|
52209
|
+
}
|
|
52210
|
+
}, () => [this.env.model.getters.getActiveSheetId()]);
|
|
51980
52211
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
51981
52212
|
owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
51982
52213
|
this.bindModelEvents();
|
|
@@ -52058,7 +52289,7 @@ class Spreadsheet extends owl.Component {
|
|
|
52058
52289
|
}
|
|
52059
52290
|
focusGrid() {
|
|
52060
52291
|
if (!this._focusGrid) {
|
|
52061
|
-
|
|
52292
|
+
return;
|
|
52062
52293
|
}
|
|
52063
52294
|
this._focusGrid();
|
|
52064
52295
|
}
|
|
@@ -55451,19 +55682,22 @@ class Model extends EventBus {
|
|
|
55451
55682
|
* Check if the given command is allowed by all the plugins and the history.
|
|
55452
55683
|
*/
|
|
55453
55684
|
checkDispatchAllowed(command) {
|
|
55454
|
-
|
|
55455
|
-
|
|
55685
|
+
const results = isCoreCommand(command)
|
|
55686
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
55687
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
55688
|
+
if (results.some((r) => r !== "Success" /* CommandResult.Success */)) {
|
|
55689
|
+
return new DispatchResult(results.flat());
|
|
55456
55690
|
}
|
|
55457
|
-
return
|
|
55691
|
+
return DispatchResult.Success;
|
|
55458
55692
|
}
|
|
55459
55693
|
checkDispatchAllowedCoreCommand(command) {
|
|
55460
55694
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
55461
55695
|
results.push(this.range.allowDispatch(command));
|
|
55462
|
-
return
|
|
55696
|
+
return results;
|
|
55463
55697
|
}
|
|
55464
55698
|
checkDispatchAllowedLocalCommand(command) {
|
|
55465
55699
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
55466
|
-
return
|
|
55700
|
+
return results;
|
|
55467
55701
|
}
|
|
55468
55702
|
finalize() {
|
|
55469
55703
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -55758,6 +55992,7 @@ const components = {
|
|
|
55758
55992
|
FigureComponent,
|
|
55759
55993
|
Menu,
|
|
55760
55994
|
SelectionInput,
|
|
55995
|
+
ValidationMessages,
|
|
55761
55996
|
};
|
|
55762
55997
|
const hooks = {
|
|
55763
55998
|
useDragAndDropListItems,
|
|
@@ -55810,6 +56045,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
55810
56045
|
exports.tokenize = tokenize;
|
|
55811
56046
|
|
|
55812
56047
|
|
|
55813
|
-
__info__.version = "17.1.0-alpha.
|
|
55814
|
-
__info__.date = "2023-11-
|
|
55815
|
-
__info__.hash = "
|
|
56048
|
+
__info__.version = "17.1.0-alpha.4";
|
|
56049
|
+
__info__.date = "2023-11-24T13:12:24.882Z";
|
|
56050
|
+
__info__.hash = "255821b";
|