@odoo/o-spreadsheet 17.1.0-alpha.2 → 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 +818 -668
- package/dist/o-spreadsheet.d.ts +169 -191
- package/dist/o-spreadsheet.esm.js +817 -669
- package/dist/o-spreadsheet.iife.js +818 -668
- package/dist/o-spreadsheet.iife.min.js +322 -348
- 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
|
(function (exports, owl) {
|
|
@@ -228,7 +228,6 @@
|
|
|
228
228
|
const SCROLLBAR_WIDTH = 15;
|
|
229
229
|
const AUTOFILL_EDGE_LENGTH = 8;
|
|
230
230
|
const ICON_EDGE_LENGTH = 18;
|
|
231
|
-
const UNHIDE_ICON_EDGE_LENGTH = 14;
|
|
232
231
|
const MIN_CF_ICON_MARGIN = 4;
|
|
233
232
|
const MIN_CELL_TEXT_MARGIN = 4;
|
|
234
233
|
const CF_ICON_EDGE_LENGTH = 15;
|
|
@@ -692,8 +691,7 @@
|
|
|
692
691
|
*
|
|
693
692
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
694
693
|
*/
|
|
695
|
-
const
|
|
696
|
-
" ",
|
|
694
|
+
const whiteSpaceSpecialCharacters = [
|
|
697
695
|
"\t",
|
|
698
696
|
"\f",
|
|
699
697
|
"\v",
|
|
@@ -708,8 +706,7 @@
|
|
|
708
706
|
String.fromCharCode(parseInt("3000", 16)),
|
|
709
707
|
String.fromCharCode(parseInt("feff", 16)),
|
|
710
708
|
];
|
|
711
|
-
const whiteSpaceRegexp = new RegExp(
|
|
712
|
-
const newLineRegex = /\r\n|\r|\n/g;
|
|
709
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
|
|
713
710
|
/**
|
|
714
711
|
* Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
|
|
715
712
|
* different newlines types by \n.
|
|
@@ -717,9 +714,9 @@
|
|
|
717
714
|
function replaceSpecialSpaces(text) {
|
|
718
715
|
if (!text)
|
|
719
716
|
return "";
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
return text;
|
|
717
|
+
if (!whiteSpaceRegexp.test(text))
|
|
718
|
+
return text;
|
|
719
|
+
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
723
720
|
}
|
|
724
721
|
/**
|
|
725
722
|
* Determine if the numbers are consecutive.
|
|
@@ -2061,6 +2058,7 @@
|
|
|
2061
2058
|
CommandResult["InvalidNumberOfCriterionValues"] = "InvalidNumberOfCriterionValues";
|
|
2062
2059
|
CommandResult["BlockingValidationRule"] = "BlockingValidationRule";
|
|
2063
2060
|
CommandResult["InvalidCopyPasteSelection"] = "InvalidCopyPasteSelection";
|
|
2061
|
+
CommandResult["NoChanges"] = "NoChanges";
|
|
2064
2062
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
2065
2063
|
|
|
2066
2064
|
const DEFAULT_LOCALES = [
|
|
@@ -2190,12 +2188,12 @@
|
|
|
2190
2188
|
}
|
|
2191
2189
|
}
|
|
2192
2190
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
2193
|
-
function normalizeString(str) {
|
|
2191
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
2194
2192
|
return str
|
|
2195
2193
|
.toLowerCase()
|
|
2196
2194
|
.normalize("NFD")
|
|
2197
2195
|
.replace(/[\u0300-\u036f]/g, "");
|
|
2198
|
-
}
|
|
2196
|
+
});
|
|
2199
2197
|
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);
|
|
2200
2198
|
function toBoolean(value) {
|
|
2201
2199
|
switch (typeof value) {
|
|
@@ -3428,11 +3426,18 @@
|
|
|
3428
3426
|
return singleCellReference.test(xc);
|
|
3429
3427
|
}
|
|
3430
3428
|
function splitReference(ref) {
|
|
3429
|
+
if (!ref.includes("!")) {
|
|
3430
|
+
return { xc: ref };
|
|
3431
|
+
}
|
|
3431
3432
|
const parts = ref.split("!");
|
|
3432
3433
|
const xc = parts.pop();
|
|
3433
3434
|
const sheetName = getUnquotedSheetName(parts.join("!")) || undefined;
|
|
3434
3435
|
return { sheetName, xc };
|
|
3435
3436
|
}
|
|
3437
|
+
/** Return a reference SheetName!xc from the given arguments */
|
|
3438
|
+
function getFullReference(sheetName, xc) {
|
|
3439
|
+
return sheetName !== undefined ? `${getCanonicalSheetName(sheetName)}!${xc}` : xc;
|
|
3440
|
+
}
|
|
3436
3441
|
|
|
3437
3442
|
/**
|
|
3438
3443
|
* Convert from a cartesian reference to a Zone
|
|
@@ -4541,14 +4546,14 @@
|
|
|
4541
4546
|
switch (context.textBaseline) {
|
|
4542
4547
|
case "top":
|
|
4543
4548
|
underlineY += boxHeight - 2 * strokeWidth;
|
|
4544
|
-
strikeY += boxHeight -
|
|
4549
|
+
strikeY += boxHeight / 2 - strokeWidth;
|
|
4545
4550
|
break;
|
|
4546
4551
|
case "middle":
|
|
4547
4552
|
underlineY += boxHeight / 2 - strokeWidth;
|
|
4548
4553
|
break;
|
|
4549
4554
|
case "alphabetic":
|
|
4550
4555
|
underlineY += 2 * strokeWidth;
|
|
4551
|
-
strikeY -=
|
|
4556
|
+
strikeY -= 3 * strokeWidth;
|
|
4552
4557
|
break;
|
|
4553
4558
|
case "bottom":
|
|
4554
4559
|
underlineY = y;
|
|
@@ -4611,6 +4616,7 @@
|
|
|
4611
4616
|
const children = item.children;
|
|
4612
4617
|
const description = item.description;
|
|
4613
4618
|
const icon = item.icon;
|
|
4619
|
+
const secondaryIcon = item.secondaryIcon;
|
|
4614
4620
|
return {
|
|
4615
4621
|
id: item.id || uuidGenerator$2.uuidv4(),
|
|
4616
4622
|
name: typeof name === "function" ? name : () => name,
|
|
@@ -4629,6 +4635,7 @@
|
|
|
4629
4635
|
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
4630
4636
|
separator: item.separator || false,
|
|
4631
4637
|
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
4638
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
4632
4639
|
description: typeof description === "function" ? description : () => description || "",
|
|
4633
4640
|
textColor: item.textColor,
|
|
4634
4641
|
sequence: item.sequence || 0,
|
|
@@ -5967,7 +5974,7 @@
|
|
|
5967
5974
|
return { cellData: {} };
|
|
5968
5975
|
}
|
|
5969
5976
|
const sheetId = data.sheetId;
|
|
5970
|
-
const content = getters.getTranslatedCellFormula(sheetId, x, y, cell.compiledFormula
|
|
5977
|
+
const content = getters.getTranslatedCellFormula(sheetId, x, y, cell.compiledFormula);
|
|
5971
5978
|
return {
|
|
5972
5979
|
cellData: {
|
|
5973
5980
|
border: data.border,
|
|
@@ -6984,11 +6991,9 @@
|
|
|
6984
6991
|
padding: ${MENU_VERTICAL_PADDING}px 0px;
|
|
6985
6992
|
width: ${MENU_WIDTH}px;
|
|
6986
6993
|
box-sizing: border-box !important;
|
|
6994
|
+
user-select: none;
|
|
6987
6995
|
|
|
6988
6996
|
.o-menu-item {
|
|
6989
|
-
display: flex;
|
|
6990
|
-
justify-content: space-between;
|
|
6991
|
-
align-items: center;
|
|
6992
6997
|
box-sizing: border-box;
|
|
6993
6998
|
height: ${MENU_ITEM_HEIGHT}px;
|
|
6994
6999
|
padding: ${MENU_ITEM_PADDING_VERTICAL}px ${MENU_ITEM_PADDING_HORIZONTAL}px;
|
|
@@ -6999,20 +7004,12 @@
|
|
|
6999
7004
|
min-width: 40%;
|
|
7000
7005
|
}
|
|
7001
7006
|
|
|
7002
|
-
&.o-menu-root {
|
|
7003
|
-
display: flex;
|
|
7004
|
-
justify-content: space-between;
|
|
7005
|
-
}
|
|
7006
|
-
|
|
7007
7007
|
.o-menu-item-icon {
|
|
7008
7008
|
display: inline-block;
|
|
7009
7009
|
margin: 0px 8px 0px 0px;
|
|
7010
7010
|
width: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
7011
7011
|
line-height: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
7012
7012
|
}
|
|
7013
|
-
.o-menu-item-root {
|
|
7014
|
-
width: 10px;
|
|
7015
|
-
}
|
|
7016
7013
|
|
|
7017
7014
|
&:not(.disabled) {
|
|
7018
7015
|
&:hover,
|
|
@@ -7355,7 +7352,7 @@
|
|
|
7355
7352
|
return result;
|
|
7356
7353
|
}
|
|
7357
7354
|
function tokenizeDebugger(chars) {
|
|
7358
|
-
if (chars.current
|
|
7355
|
+
if (chars.current === "?") {
|
|
7359
7356
|
chars.shift();
|
|
7360
7357
|
return { type: "DEBUGGER", value: "?" };
|
|
7361
7358
|
}
|
|
@@ -7366,7 +7363,7 @@
|
|
|
7366
7363
|
")": "RIGHT_PAREN",
|
|
7367
7364
|
};
|
|
7368
7365
|
function tokenizeMisc(chars) {
|
|
7369
|
-
if (chars.current
|
|
7366
|
+
if (chars.current in misc$1) {
|
|
7370
7367
|
const value = chars.shift();
|
|
7371
7368
|
const type = misc$1[value];
|
|
7372
7369
|
return { type, value };
|
|
@@ -7374,7 +7371,7 @@
|
|
|
7374
7371
|
return null;
|
|
7375
7372
|
}
|
|
7376
7373
|
function tokenizeArgsSeparator(chars, locale) {
|
|
7377
|
-
if (chars.current
|
|
7374
|
+
if (chars.current === locale.formulaArgSeparator) {
|
|
7378
7375
|
const value = chars.shift();
|
|
7379
7376
|
const type = "ARG_SEPARATOR";
|
|
7380
7377
|
return { type, value };
|
|
@@ -7399,14 +7396,13 @@
|
|
|
7399
7396
|
return null;
|
|
7400
7397
|
}
|
|
7401
7398
|
function tokenizeString(chars) {
|
|
7402
|
-
if (chars.current
|
|
7399
|
+
if (chars.current === '"') {
|
|
7403
7400
|
const startChar = chars.shift();
|
|
7404
7401
|
let letters = startChar;
|
|
7405
|
-
while (chars.current()
|
|
7406
|
-
(chars.current() !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7402
|
+
while (chars.current && (chars.current !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7407
7403
|
letters += chars.shift();
|
|
7408
7404
|
}
|
|
7409
|
-
if (chars.current
|
|
7405
|
+
if (chars.current === '"') {
|
|
7410
7406
|
letters += chars.shift();
|
|
7411
7407
|
}
|
|
7412
7408
|
return {
|
|
@@ -7433,14 +7429,14 @@
|
|
|
7433
7429
|
let result = "";
|
|
7434
7430
|
// there are two main cases to manage: either something which starts with
|
|
7435
7431
|
// a ', like 'Sheet 2'A2, or a word-like element.
|
|
7436
|
-
if (chars.current
|
|
7432
|
+
if (chars.current === "'") {
|
|
7437
7433
|
let lastChar = chars.shift();
|
|
7438
7434
|
result += lastChar;
|
|
7439
|
-
while (chars.current
|
|
7435
|
+
while (chars.current) {
|
|
7440
7436
|
lastChar = chars.shift();
|
|
7441
7437
|
result += lastChar;
|
|
7442
7438
|
if (lastChar === "'") {
|
|
7443
|
-
if (chars.current
|
|
7439
|
+
if (chars.current && chars.current === "'") {
|
|
7444
7440
|
lastChar = chars.shift();
|
|
7445
7441
|
result += lastChar;
|
|
7446
7442
|
}
|
|
@@ -7456,7 +7452,7 @@
|
|
|
7456
7452
|
};
|
|
7457
7453
|
}
|
|
7458
7454
|
}
|
|
7459
|
-
while (chars.current
|
|
7455
|
+
while (chars.current && separatorRegexp.test(chars.current)) {
|
|
7460
7456
|
result += chars.shift();
|
|
7461
7457
|
}
|
|
7462
7458
|
if (result.length) {
|
|
@@ -7471,14 +7467,14 @@
|
|
|
7471
7467
|
}
|
|
7472
7468
|
function tokenizeSpace(chars) {
|
|
7473
7469
|
let length = 0;
|
|
7474
|
-
while (chars.current
|
|
7470
|
+
while (chars.current === NEWLINE) {
|
|
7475
7471
|
length++;
|
|
7476
7472
|
chars.shift();
|
|
7477
7473
|
}
|
|
7478
7474
|
if (length) {
|
|
7479
7475
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
7480
7476
|
}
|
|
7481
|
-
while (chars.current
|
|
7477
|
+
while (chars.current === " ") {
|
|
7482
7478
|
length++;
|
|
7483
7479
|
chars.shift();
|
|
7484
7480
|
}
|
|
@@ -7497,17 +7493,20 @@
|
|
|
7497
7493
|
class TokenizingChars {
|
|
7498
7494
|
text;
|
|
7499
7495
|
currentIndex = 0;
|
|
7496
|
+
current;
|
|
7500
7497
|
constructor(text) {
|
|
7501
7498
|
this.text = text;
|
|
7502
|
-
|
|
7503
|
-
current() {
|
|
7504
|
-
return this.text[this.currentIndex];
|
|
7499
|
+
this.current = text[0];
|
|
7505
7500
|
}
|
|
7506
7501
|
shift() {
|
|
7507
|
-
|
|
7502
|
+
const current = this.current;
|
|
7503
|
+
const next = this.text[++this.currentIndex];
|
|
7504
|
+
this.current = next;
|
|
7505
|
+
return current;
|
|
7508
7506
|
}
|
|
7509
7507
|
advanceBy(length) {
|
|
7510
7508
|
this.currentIndex += length;
|
|
7509
|
+
this.current = this.text[this.currentIndex];
|
|
7511
7510
|
}
|
|
7512
7511
|
isOver() {
|
|
7513
7512
|
return this.currentIndex >= this.text.length;
|
|
@@ -10719,6 +10718,17 @@
|
|
|
10719
10718
|
const IS_ONLY_ONE_RANGE = (env) => {
|
|
10720
10719
|
return env.model.getters.getSelectedZones().length === 1;
|
|
10721
10720
|
};
|
|
10721
|
+
const CAN_INSERT_HEADER = (env, dimension) => {
|
|
10722
|
+
if (!IS_ONLY_ONE_RANGE(env)) {
|
|
10723
|
+
return false;
|
|
10724
|
+
}
|
|
10725
|
+
const activeHeaders = dimension === "COL" ? env.model.getters.getActiveCols() : env.model.getters.getActiveRows();
|
|
10726
|
+
const ortogonalActiveHeaders = dimension === "COL" ? env.model.getters.getActiveRows() : env.model.getters.getActiveCols();
|
|
10727
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
10728
|
+
const zone = env.model.getters.getSelectedZone();
|
|
10729
|
+
const allSheetSelected = isEqual(zone, env.model.getters.getSheetZone(sheetId));
|
|
10730
|
+
return isConsecutive(activeHeaders) && (ortogonalActiveHeaders.size === 0 || allSheetSelected);
|
|
10731
|
+
};
|
|
10722
10732
|
|
|
10723
10733
|
const undo = {
|
|
10724
10734
|
name: _t("Undo"),
|
|
@@ -11300,7 +11310,7 @@
|
|
|
11300
11310
|
) {
|
|
11301
11311
|
const _array = toMatrix(arg);
|
|
11302
11312
|
const _nbRows = toInteger(rows?.value, this.locale);
|
|
11303
|
-
const _nbColumns = columns !== undefined ? toInteger(columns.value, this.
|
|
11313
|
+
const _nbColumns = columns !== undefined ? toInteger(columns.value, this.locale) : _array.length;
|
|
11304
11314
|
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()));
|
|
11305
11315
|
assert(() => _nbColumns >= _array.length, _t("The columns arguments (%s) must be greater or equal than the number of columns of the array.", _nbColumns.toString()));
|
|
11306
11316
|
return generateMatrix(_nbColumns, _nbRows, (col, row) => col >= _array.length || row >= _array[col].length ? padWith : _array[col][row]);
|
|
@@ -11789,6 +11799,10 @@
|
|
|
11789
11799
|
FORMAT_LARGE_NUMBER: FORMAT_LARGE_NUMBER
|
|
11790
11800
|
});
|
|
11791
11801
|
|
|
11802
|
+
function sum(values, locale) {
|
|
11803
|
+
return reduceNumbers(values, (acc, a) => acc + a, 0, locale);
|
|
11804
|
+
}
|
|
11805
|
+
|
|
11792
11806
|
const DEFAULT_FACTOR = 1;
|
|
11793
11807
|
const DEFAULT_MODE = 0;
|
|
11794
11808
|
const DEFAULT_PLACES = 0;
|
|
@@ -12740,7 +12754,7 @@
|
|
|
12740
12754
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
12741
12755
|
},
|
|
12742
12756
|
compute: function (...values) {
|
|
12743
|
-
return
|
|
12757
|
+
return sum(values, this.locale);
|
|
12744
12758
|
},
|
|
12745
12759
|
isExported: true,
|
|
12746
12760
|
};
|
|
@@ -12909,6 +12923,44 @@
|
|
|
12909
12923
|
const dims = args[0].length;
|
|
12910
12924
|
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())));
|
|
12911
12925
|
}
|
|
12926
|
+
function average(values, locale) {
|
|
12927
|
+
let count = 0;
|
|
12928
|
+
const sum = reduceNumbers(values, (acc, a) => {
|
|
12929
|
+
count += 1;
|
|
12930
|
+
return acc + a;
|
|
12931
|
+
}, 0, locale);
|
|
12932
|
+
assert(() => count !== 0, _t("Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error."));
|
|
12933
|
+
return sum / count;
|
|
12934
|
+
}
|
|
12935
|
+
function countNumbers(values, locale) {
|
|
12936
|
+
let count = 0;
|
|
12937
|
+
for (let n of values) {
|
|
12938
|
+
if (isMatrix(n)) {
|
|
12939
|
+
for (let i of n) {
|
|
12940
|
+
for (let j of i) {
|
|
12941
|
+
if (typeof j === "number") {
|
|
12942
|
+
count += 1;
|
|
12943
|
+
}
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12946
|
+
}
|
|
12947
|
+
else if (typeof n !== "string" || isNumber(n, locale) || parseDateTime(n, locale)) {
|
|
12948
|
+
count += 1;
|
|
12949
|
+
}
|
|
12950
|
+
}
|
|
12951
|
+
return count;
|
|
12952
|
+
}
|
|
12953
|
+
function countAny(values) {
|
|
12954
|
+
return reduceAny(values, (acc, a) => (a !== undefined && a !== null ? acc + 1 : acc), 0);
|
|
12955
|
+
}
|
|
12956
|
+
function max(values, locale) {
|
|
12957
|
+
const result = reduceNumbers(values, (acc, a) => (acc < a ? a : acc), -Infinity, locale);
|
|
12958
|
+
return result === -Infinity ? 0 : result;
|
|
12959
|
+
}
|
|
12960
|
+
function min(values, locale) {
|
|
12961
|
+
const result = reduceNumbers(values, (acc, a) => (a < acc ? a : acc), Infinity, locale);
|
|
12962
|
+
return result === Infinity ? 0 : result;
|
|
12963
|
+
}
|
|
12912
12964
|
|
|
12913
12965
|
function filterAndFlatData(dataY, dataX) {
|
|
12914
12966
|
const _flatDataY = [];
|
|
@@ -13179,13 +13231,7 @@
|
|
|
13179
13231
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13180
13232
|
},
|
|
13181
13233
|
compute: function (...values) {
|
|
13182
|
-
|
|
13183
|
-
const sum = reduceNumbers(values, (acc, a) => {
|
|
13184
|
-
count += 1;
|
|
13185
|
-
return acc + a;
|
|
13186
|
-
}, 0, this.locale);
|
|
13187
|
-
assert(() => count !== 0, _t("Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error."));
|
|
13188
|
-
return sum / count;
|
|
13234
|
+
return average(values, this.locale);
|
|
13189
13235
|
},
|
|
13190
13236
|
isExported: true,
|
|
13191
13237
|
};
|
|
@@ -13343,24 +13389,7 @@
|
|
|
13343
13389
|
],
|
|
13344
13390
|
returns: ["NUMBER"],
|
|
13345
13391
|
compute: function (...values) {
|
|
13346
|
-
|
|
13347
|
-
for (let n of values) {
|
|
13348
|
-
if (isMatrix(n)) {
|
|
13349
|
-
for (let i of n) {
|
|
13350
|
-
for (let j of i) {
|
|
13351
|
-
if (typeof j === "number") {
|
|
13352
|
-
count += 1;
|
|
13353
|
-
}
|
|
13354
|
-
}
|
|
13355
|
-
}
|
|
13356
|
-
}
|
|
13357
|
-
else if (typeof n !== "string" ||
|
|
13358
|
-
isNumber(n, this.locale) ||
|
|
13359
|
-
parseDateTime(n, this.locale)) {
|
|
13360
|
-
count += 1;
|
|
13361
|
-
}
|
|
13362
|
-
}
|
|
13363
|
-
return count;
|
|
13392
|
+
return countNumbers(values, this.locale);
|
|
13364
13393
|
},
|
|
13365
13394
|
isExported: true,
|
|
13366
13395
|
};
|
|
@@ -13375,7 +13404,7 @@
|
|
|
13375
13404
|
],
|
|
13376
13405
|
returns: ["NUMBER"],
|
|
13377
13406
|
compute: function (...values) {
|
|
13378
|
-
return
|
|
13407
|
+
return countAny(values);
|
|
13379
13408
|
},
|
|
13380
13409
|
isExported: true,
|
|
13381
13410
|
};
|
|
@@ -13605,8 +13634,7 @@
|
|
|
13605
13634
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13606
13635
|
},
|
|
13607
13636
|
compute: function (...values) {
|
|
13608
|
-
|
|
13609
|
-
return result === -Infinity ? 0 : result;
|
|
13637
|
+
return max(values, this.locale);
|
|
13610
13638
|
},
|
|
13611
13639
|
isExported: true,
|
|
13612
13640
|
};
|
|
@@ -13693,8 +13721,7 @@
|
|
|
13693
13721
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13694
13722
|
},
|
|
13695
13723
|
compute: function (...values) {
|
|
13696
|
-
|
|
13697
|
-
return result === Infinity ? 0 : result;
|
|
13724
|
+
return min(values, this.locale);
|
|
13698
13725
|
},
|
|
13699
13726
|
isExported: true,
|
|
13700
13727
|
};
|
|
@@ -17865,6 +17892,149 @@
|
|
|
17865
17892
|
YIELDMAT: YIELDMAT
|
|
17866
17893
|
});
|
|
17867
17894
|
|
|
17895
|
+
/**
|
|
17896
|
+
* Change the reference types inside the given token, if the token represent a range or a cell
|
|
17897
|
+
*
|
|
17898
|
+
* Eg. :
|
|
17899
|
+
* A1 => $A$1 => A$1 => $A1 => A1
|
|
17900
|
+
* A1:$B$1 => $A$1:B$1 => A$1:$B1 => $A1:B1 => A1:$B$1
|
|
17901
|
+
*/
|
|
17902
|
+
function loopThroughReferenceType(token) {
|
|
17903
|
+
if (token.type !== "REFERENCE")
|
|
17904
|
+
return token;
|
|
17905
|
+
const { xc, sheetName } = splitReference(token.value);
|
|
17906
|
+
const [left, right] = xc.split(":");
|
|
17907
|
+
const updatedLeft = getTokenNextReferenceType(left);
|
|
17908
|
+
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
17909
|
+
return { ...token, value: getFullReference(sheetName, updatedLeft + updatedRight) };
|
|
17910
|
+
}
|
|
17911
|
+
/**
|
|
17912
|
+
* Get a new token with a changed type of reference from the given cell token symbol.
|
|
17913
|
+
* Undefined behavior if given a token other than a cell or if the Xc contains a sheet reference
|
|
17914
|
+
*
|
|
17915
|
+
* A1 => $A$1 => A$1 => $A1 => A1
|
|
17916
|
+
*/
|
|
17917
|
+
function getTokenNextReferenceType(xc) {
|
|
17918
|
+
switch (getReferenceType(xc)) {
|
|
17919
|
+
case "none":
|
|
17920
|
+
xc = setXcToFixedReferenceType(xc, "colrow");
|
|
17921
|
+
break;
|
|
17922
|
+
case "colrow":
|
|
17923
|
+
xc = setXcToFixedReferenceType(xc, "row");
|
|
17924
|
+
break;
|
|
17925
|
+
case "row":
|
|
17926
|
+
xc = setXcToFixedReferenceType(xc, "col");
|
|
17927
|
+
break;
|
|
17928
|
+
case "col":
|
|
17929
|
+
xc = setXcToFixedReferenceType(xc, "none");
|
|
17930
|
+
break;
|
|
17931
|
+
}
|
|
17932
|
+
return xc;
|
|
17933
|
+
}
|
|
17934
|
+
/**
|
|
17935
|
+
* Returns the given XC with the given reference type. The XC string should not contain a sheet name.
|
|
17936
|
+
*/
|
|
17937
|
+
function setXcToFixedReferenceType(xc, referenceType) {
|
|
17938
|
+
if (xc.includes("!")) {
|
|
17939
|
+
throw new Error("The given XC should not contain a sheet name");
|
|
17940
|
+
}
|
|
17941
|
+
xc = xc.replace(/\$/g, "");
|
|
17942
|
+
let indexOfNumber;
|
|
17943
|
+
switch (referenceType) {
|
|
17944
|
+
case "col":
|
|
17945
|
+
return "$" + xc;
|
|
17946
|
+
case "row":
|
|
17947
|
+
indexOfNumber = xc.search(/[0-9]/);
|
|
17948
|
+
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
17949
|
+
case "colrow":
|
|
17950
|
+
indexOfNumber = xc.search(/[0-9]/);
|
|
17951
|
+
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
17952
|
+
return "$" + xc;
|
|
17953
|
+
case "none":
|
|
17954
|
+
return xc;
|
|
17955
|
+
}
|
|
17956
|
+
}
|
|
17957
|
+
/**
|
|
17958
|
+
* Return the type of reference used in the given XC of a cell.
|
|
17959
|
+
* Undefined behavior if the XC have a sheet reference
|
|
17960
|
+
*/
|
|
17961
|
+
function getReferenceType(xcCell) {
|
|
17962
|
+
if (isColAndRowFixed(xcCell)) {
|
|
17963
|
+
return "colrow";
|
|
17964
|
+
}
|
|
17965
|
+
else if (isColFixed(xcCell)) {
|
|
17966
|
+
return "col";
|
|
17967
|
+
}
|
|
17968
|
+
else if (isRowFixed(xcCell)) {
|
|
17969
|
+
return "row";
|
|
17970
|
+
}
|
|
17971
|
+
return "none";
|
|
17972
|
+
}
|
|
17973
|
+
function isColFixed(xc) {
|
|
17974
|
+
return xc.startsWith("$");
|
|
17975
|
+
}
|
|
17976
|
+
function isRowFixed(xc) {
|
|
17977
|
+
return xc.includes("$", 1);
|
|
17978
|
+
}
|
|
17979
|
+
function isColAndRowFixed(xc) {
|
|
17980
|
+
return xc.startsWith("$") && xc.length > 1 && xc.slice(1).includes("$");
|
|
17981
|
+
}
|
|
17982
|
+
|
|
17983
|
+
// -----------------------------------------------------------------------------
|
|
17984
|
+
// CELL
|
|
17985
|
+
// -----------------------------------------------------------------------------
|
|
17986
|
+
// NOTE: missing from Excel: "color", "filename", "parentheses", "prefix", "protect" and "width"
|
|
17987
|
+
const CELL_INFO_TYPES = ["address", "col", "contents", "format", "row", "type"];
|
|
17988
|
+
const CELL = {
|
|
17989
|
+
description: _t("Gets information about a cell."),
|
|
17990
|
+
args: [
|
|
17991
|
+
arg("info_type (string)", _t("The type of information requested. Can be one of %s", CELL_INFO_TYPES.join(", "))),
|
|
17992
|
+
arg("reference (meta)", _t("The reference to the cell.")),
|
|
17993
|
+
],
|
|
17994
|
+
returns: ["ANY"],
|
|
17995
|
+
compute: function (info, reference) {
|
|
17996
|
+
const _info = toString(info).toLowerCase();
|
|
17997
|
+
assert(() => CELL_INFO_TYPES.includes(_info), _t("The info_type should be one of %s.", CELL_INFO_TYPES.join(", ")));
|
|
17998
|
+
const sheetId = this.__originSheetId;
|
|
17999
|
+
const topLeftReference = reference.includes(":") ? reference.split(":")[0] : reference;
|
|
18000
|
+
let { sheetName, xc } = splitReference(topLeftReference);
|
|
18001
|
+
// only put the sheet name if the referenced range is in another sheet than the cell the formula is on
|
|
18002
|
+
sheetName = sheetName === this.getters.getSheetName(sheetId) ? undefined : sheetName;
|
|
18003
|
+
const fixedRef = getFullReference(sheetName, setXcToFixedReferenceType(xc, "colrow"));
|
|
18004
|
+
const range = this.getters.getRangeFromSheetXC(sheetId, fixedRef);
|
|
18005
|
+
switch (_info) {
|
|
18006
|
+
case "address":
|
|
18007
|
+
return this.getters.getRangeString(range, sheetId);
|
|
18008
|
+
case "col":
|
|
18009
|
+
return range.zone.left + 1;
|
|
18010
|
+
case "contents": {
|
|
18011
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18012
|
+
return this.getters.getEvaluatedCell(position).value;
|
|
18013
|
+
}
|
|
18014
|
+
case "format": {
|
|
18015
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18016
|
+
return this.getters.getEvaluatedCell(position).format || "";
|
|
18017
|
+
}
|
|
18018
|
+
case "row":
|
|
18019
|
+
return range.zone.top + 1;
|
|
18020
|
+
case "type": {
|
|
18021
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18022
|
+
const type = this.getters.getEvaluatedCell(position).type;
|
|
18023
|
+
if (type === CellValueType.empty) {
|
|
18024
|
+
return "b"; // blank
|
|
18025
|
+
}
|
|
18026
|
+
else if (type === CellValueType.text) {
|
|
18027
|
+
return "l"; // label
|
|
18028
|
+
}
|
|
18029
|
+
else {
|
|
18030
|
+
return "v"; // value
|
|
18031
|
+
}
|
|
18032
|
+
}
|
|
18033
|
+
}
|
|
18034
|
+
return "";
|
|
18035
|
+
},
|
|
18036
|
+
isExported: true,
|
|
18037
|
+
};
|
|
17868
18038
|
// -----------------------------------------------------------------------------
|
|
17869
18039
|
// ISERR
|
|
17870
18040
|
// -----------------------------------------------------------------------------
|
|
@@ -18020,6 +18190,7 @@
|
|
|
18020
18190
|
|
|
18021
18191
|
var info = /*#__PURE__*/Object.freeze({
|
|
18022
18192
|
__proto__: null,
|
|
18193
|
+
CELL: CELL,
|
|
18023
18194
|
ISBLANK: ISBLANK,
|
|
18024
18195
|
ISERR: ISERR,
|
|
18025
18196
|
ISERROR: ISERROR,
|
|
@@ -18311,7 +18482,7 @@
|
|
|
18311
18482
|
cellReference = rowPart + colPart;
|
|
18312
18483
|
}
|
|
18313
18484
|
if (sheet !== undefined) {
|
|
18314
|
-
return
|
|
18485
|
+
return getFullReference(toString(sheet), cellReference);
|
|
18315
18486
|
}
|
|
18316
18487
|
return cellReference;
|
|
18317
18488
|
},
|
|
@@ -18327,7 +18498,7 @@
|
|
|
18327
18498
|
],
|
|
18328
18499
|
returns: ["NUMBER"],
|
|
18329
18500
|
compute: function (cellReference) {
|
|
18330
|
-
const _cellReference = cellReference || this.__originCellXC
|
|
18501
|
+
const _cellReference = cellReference || this.__originCellXC();
|
|
18331
18502
|
assert(() => !!_cellReference, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
|
|
18332
18503
|
const zone = toZone(_cellReference);
|
|
18333
18504
|
return zone.left + 1;
|
|
@@ -18494,7 +18665,7 @@
|
|
|
18494
18665
|
],
|
|
18495
18666
|
returns: ["NUMBER"],
|
|
18496
18667
|
compute: function (cellReference) {
|
|
18497
|
-
cellReference = cellReference || this.__originCellXC
|
|
18668
|
+
cellReference = cellReference || this.__originCellXC();
|
|
18498
18669
|
assert(() => !!cellReference, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
|
|
18499
18670
|
const zone = toZone(cellReference);
|
|
18500
18671
|
return zone.top + 1;
|
|
@@ -19396,9 +19567,7 @@
|
|
|
19396
19567
|
const number = getRowsNumber(env);
|
|
19397
19568
|
return number === 1 ? _t("Insert row") : _t("Insert %s rows", number.toString());
|
|
19398
19569
|
},
|
|
19399
|
-
isVisible: (env) =>
|
|
19400
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19401
|
-
env.model.getters.getActiveCols().size === 0,
|
|
19570
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "ROW"),
|
|
19402
19571
|
icon: "o-spreadsheet-Icon.INSERT_ROW",
|
|
19403
19572
|
};
|
|
19404
19573
|
const rowInsertRowBefore = {
|
|
@@ -19407,9 +19576,7 @@
|
|
|
19407
19576
|
return number === 1 ? _t("Insert row above") : _t("Insert %s rows above", number.toString());
|
|
19408
19577
|
},
|
|
19409
19578
|
execute: INSERT_ROWS_BEFORE_ACTION,
|
|
19410
|
-
isVisible: (env) =>
|
|
19411
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19412
|
-
env.model.getters.getActiveCols().size === 0,
|
|
19579
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "ROW"),
|
|
19413
19580
|
icon: "o-spreadsheet-Icon.INSERT_ROW_BEFORE",
|
|
19414
19581
|
};
|
|
19415
19582
|
const topBarInsertRowsBefore = {
|
|
@@ -19440,9 +19607,7 @@
|
|
|
19440
19607
|
const number = getRowsNumber(env);
|
|
19441
19608
|
return number === 1 ? _t("Insert row below") : _t("Insert %s rows below", number.toString());
|
|
19442
19609
|
},
|
|
19443
|
-
isVisible: (env) =>
|
|
19444
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19445
|
-
env.model.getters.getActiveCols().size === 0,
|
|
19610
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "ROW"),
|
|
19446
19611
|
icon: "o-spreadsheet-Icon.INSERT_ROW_AFTER",
|
|
19447
19612
|
};
|
|
19448
19613
|
const topBarInsertRowsAfter = {
|
|
@@ -19460,9 +19625,7 @@
|
|
|
19460
19625
|
const number = getColumnsNumber(env);
|
|
19461
19626
|
return number === 1 ? _t("Insert column") : _t("Insert %s columns", number.toString());
|
|
19462
19627
|
},
|
|
19463
|
-
isVisible: (env) =>
|
|
19464
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19465
|
-
env.model.getters.getActiveRows().size === 0,
|
|
19628
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "COL"),
|
|
19466
19629
|
icon: "o-spreadsheet-Icon.INSERT_COL",
|
|
19467
19630
|
};
|
|
19468
19631
|
const colInsertColsBefore = {
|
|
@@ -19473,9 +19636,7 @@
|
|
|
19473
19636
|
: _t("Insert %s columns left", number.toString());
|
|
19474
19637
|
},
|
|
19475
19638
|
execute: INSERT_COLUMNS_BEFORE_ACTION,
|
|
19476
|
-
isVisible: (env) =>
|
|
19477
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19478
|
-
env.model.getters.getActiveRows().size === 0,
|
|
19639
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "COL"),
|
|
19479
19640
|
icon: "o-spreadsheet-Icon.INSERT_COL_BEFORE",
|
|
19480
19641
|
};
|
|
19481
19642
|
const topBarInsertColsBefore = {
|
|
@@ -19508,9 +19669,7 @@
|
|
|
19508
19669
|
: _t("Insert %s columns right", number.toString());
|
|
19509
19670
|
},
|
|
19510
19671
|
execute: INSERT_COLUMNS_AFTER_ACTION,
|
|
19511
|
-
isVisible: (env) =>
|
|
19512
|
-
IS_ONLY_ONE_RANGE(env) &&
|
|
19513
|
-
env.model.getters.getActiveRows().size === 0,
|
|
19672
|
+
isVisible: (env) => CAN_INSERT_HEADER(env, "COL"),
|
|
19514
19673
|
icon: "o-spreadsheet-Icon.INSERT_COL_AFTER",
|
|
19515
19674
|
};
|
|
19516
19675
|
const topBarInsertColsAfter = {
|
|
@@ -23851,38 +24010,72 @@
|
|
|
23851
24010
|
}
|
|
23852
24011
|
.o-input-count {
|
|
23853
24012
|
width: fit-content;
|
|
23854
|
-
padding:
|
|
24013
|
+
padding: 4px 0 4px 4px;
|
|
23855
24014
|
}
|
|
23856
24015
|
}
|
|
23857
24016
|
}
|
|
23858
24017
|
`;
|
|
23859
24018
|
class FindAndReplacePanel extends owl.Component {
|
|
23860
24019
|
static template = "o-spreadsheet-FindAndReplacePanel";
|
|
23861
|
-
|
|
24020
|
+
static components = { SelectionInput };
|
|
23862
24021
|
debounceTimeoutId;
|
|
23863
|
-
|
|
24022
|
+
initialShowFormulaState = false;
|
|
24023
|
+
dataRange = "";
|
|
23864
24024
|
searchInput = owl.useRef("searchInput");
|
|
24025
|
+
replaceInput = owl.useRef("replaceInput");
|
|
23865
24026
|
get hasSearchResult() {
|
|
23866
24027
|
return this.env.model.getters.getCurrentSelectedMatchIndex() !== null;
|
|
23867
24028
|
}
|
|
23868
24029
|
get pendingSearch() {
|
|
23869
24030
|
return this.debounceTimeoutId !== undefined;
|
|
23870
24031
|
}
|
|
24032
|
+
get searchOptions() {
|
|
24033
|
+
return this.env.model.getters.getSearchOptions();
|
|
24034
|
+
}
|
|
24035
|
+
get toSearch() {
|
|
24036
|
+
return this.searchInput.el?.value || "";
|
|
24037
|
+
}
|
|
24038
|
+
get toReplace() {
|
|
24039
|
+
return this.replaceInput.el?.value || "";
|
|
24040
|
+
}
|
|
24041
|
+
get allSheetsMatchesCount() {
|
|
24042
|
+
return _t("%s in all sheets", this.env.model.getters.getAllSheetMatchesCount());
|
|
24043
|
+
}
|
|
24044
|
+
get currentSheetMatchesCount() {
|
|
24045
|
+
return _t("%(matches)s in sheet %(sheetName)s", {
|
|
24046
|
+
matches: this.env.model.getters.getActiveSheetMatchesCount(),
|
|
24047
|
+
sheetName: this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId()),
|
|
24048
|
+
});
|
|
24049
|
+
}
|
|
24050
|
+
get specificRangeMatchesCount() {
|
|
24051
|
+
const range = this.searchOptions.specificRange;
|
|
24052
|
+
if (!range) {
|
|
24053
|
+
return "";
|
|
24054
|
+
}
|
|
24055
|
+
const { _sheetId, _zone } = range;
|
|
24056
|
+
return _t("%(matches)s in range %(range)s of sheet %(sheetName)s", {
|
|
24057
|
+
matches: this.env.model.getters.getSpecificRangeMatchesCount().toString(),
|
|
24058
|
+
range: zoneToXc(_zone),
|
|
24059
|
+
sheetName: this.env.model.getters.getSheetName(_sheetId),
|
|
24060
|
+
});
|
|
24061
|
+
}
|
|
23871
24062
|
setup() {
|
|
23872
|
-
this.
|
|
24063
|
+
this.initialShowFormulaState = this.env.model.getters.shouldShowFormulas();
|
|
23873
24064
|
owl.onMounted(() => this.searchInput.el?.focus());
|
|
23874
24065
|
owl.onWillUnmount(() => {
|
|
23875
24066
|
clearTimeout(this.debounceTimeoutId);
|
|
23876
24067
|
this.env.model.dispatch("CLEAR_SEARCH");
|
|
23877
|
-
this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.
|
|
24068
|
+
this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
|
|
23878
24069
|
});
|
|
23879
24070
|
owl.useEffect(() => {
|
|
23880
|
-
|
|
23881
|
-
this.searchFormulas
|
|
24071
|
+
const showFormula = this.env.model.getters.shouldShowFormulas();
|
|
24072
|
+
this.updateSearch({ searchFormulas: showFormula });
|
|
23882
24073
|
}, () => [this.env.model.getters.shouldShowFormulas()]);
|
|
23883
24074
|
}
|
|
23884
|
-
|
|
23885
|
-
this.
|
|
24075
|
+
onFocusSearch() {
|
|
24076
|
+
this.updateDataRange();
|
|
24077
|
+
}
|
|
24078
|
+
onInput() {
|
|
23886
24079
|
this.debouncedUpdateSearch();
|
|
23887
24080
|
}
|
|
23888
24081
|
onKeydownSearch(ev) {
|
|
@@ -23899,11 +24092,36 @@
|
|
|
23899
24092
|
this.replace();
|
|
23900
24093
|
}
|
|
23901
24094
|
}
|
|
23902
|
-
searchFormulas() {
|
|
24095
|
+
searchFormulas(ev) {
|
|
24096
|
+
const showFormula = ev.target.checked;
|
|
23903
24097
|
this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
|
|
23904
|
-
show:
|
|
24098
|
+
show: showFormula,
|
|
23905
24099
|
});
|
|
23906
|
-
this.updateSearch();
|
|
24100
|
+
this.updateSearch({ searchFormulas: showFormula });
|
|
24101
|
+
}
|
|
24102
|
+
searchExactMatch(ev) {
|
|
24103
|
+
const exactMatch = ev.target.checked;
|
|
24104
|
+
this.updateSearch({ exactMatch });
|
|
24105
|
+
}
|
|
24106
|
+
searchMatchCase(ev) {
|
|
24107
|
+
const matchCase = ev.target.checked;
|
|
24108
|
+
this.updateSearch({ matchCase });
|
|
24109
|
+
}
|
|
24110
|
+
changeSearchScope(ev) {
|
|
24111
|
+
const searchScope = ev.target.value;
|
|
24112
|
+
this.updateSearch({ searchScope });
|
|
24113
|
+
}
|
|
24114
|
+
onSearchRangeChanged(ranges) {
|
|
24115
|
+
this.dataRange = ranges[0];
|
|
24116
|
+
}
|
|
24117
|
+
updateDataRange() {
|
|
24118
|
+
if (!this.dataRange) {
|
|
24119
|
+
return;
|
|
24120
|
+
}
|
|
24121
|
+
if (this.searchOptions.searchScope === "specificRange") {
|
|
24122
|
+
const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.dataRange).rangeData;
|
|
24123
|
+
this.updateSearch({ specificRange });
|
|
24124
|
+
}
|
|
23907
24125
|
}
|
|
23908
24126
|
onSelectPreviousCell() {
|
|
23909
24127
|
this.env.model.dispatch("SELECT_SEARCH_PREVIOUS_MATCH");
|
|
@@ -23911,10 +24129,14 @@
|
|
|
23911
24129
|
onSelectNextCell() {
|
|
23912
24130
|
this.env.model.dispatch("SELECT_SEARCH_NEXT_MATCH");
|
|
23913
24131
|
}
|
|
23914
|
-
updateSearch() {
|
|
24132
|
+
updateSearch(updateSearchOptions) {
|
|
24133
|
+
const searchOptions = {
|
|
24134
|
+
...this.env.model.getters.getSearchOptions(),
|
|
24135
|
+
...updateSearchOptions,
|
|
24136
|
+
};
|
|
23915
24137
|
this.env.model.dispatch("UPDATE_SEARCH", {
|
|
23916
|
-
toSearch: this.
|
|
23917
|
-
searchOptions
|
|
24138
|
+
toSearch: this.toSearch,
|
|
24139
|
+
searchOptions,
|
|
23918
24140
|
});
|
|
23919
24141
|
}
|
|
23920
24142
|
debouncedUpdateSearch() {
|
|
@@ -23926,28 +24148,14 @@
|
|
|
23926
24148
|
}
|
|
23927
24149
|
replace() {
|
|
23928
24150
|
this.env.model.dispatch("REPLACE_SEARCH", {
|
|
23929
|
-
replaceWith: this.
|
|
24151
|
+
replaceWith: this.toReplace,
|
|
23930
24152
|
});
|
|
23931
24153
|
}
|
|
23932
24154
|
replaceAll() {
|
|
23933
24155
|
this.env.model.dispatch("REPLACE_ALL_SEARCH", {
|
|
23934
|
-
replaceWith: this.
|
|
24156
|
+
replaceWith: this.toReplace,
|
|
23935
24157
|
});
|
|
23936
24158
|
}
|
|
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
24159
|
}
|
|
23952
24160
|
FindAndReplacePanel.props = {
|
|
23953
24161
|
onCloseSidePanel: Function,
|
|
@@ -27093,7 +27301,7 @@
|
|
|
27093
27301
|
get cellReference() {
|
|
27094
27302
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
27095
27303
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
27096
|
-
return
|
|
27304
|
+
return getFullReference(prefixSheet ? this.env.model.getters.getSheetName(sheetId) : undefined, toXC(col, row));
|
|
27097
27305
|
}
|
|
27098
27306
|
get cellReferenceStyle() {
|
|
27099
27307
|
const { x: left, y: top } = this.rect;
|
|
@@ -28536,22 +28744,15 @@
|
|
|
28536
28744
|
height: 10000px;
|
|
28537
28745
|
background-color: ${SELECTION_BORDER_COLOR};
|
|
28538
28746
|
}
|
|
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);
|
|
28747
|
+
.o-unhide-buttons {
|
|
28748
|
+
width: fit-content;
|
|
28749
|
+
gap: 5px;
|
|
28750
|
+
transform: translate(-50%, 0);
|
|
28546
28751
|
}
|
|
28547
28752
|
.o-unhide:hover {
|
|
28548
28753
|
z-index: ${ComponentsImportance.Grid + 1};
|
|
28549
28754
|
background-color: lightgrey;
|
|
28550
28755
|
}
|
|
28551
|
-
.o-unhide > svg {
|
|
28552
|
-
position: relative;
|
|
28553
|
-
top: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28554
|
-
}
|
|
28555
28756
|
}
|
|
28556
28757
|
`;
|
|
28557
28758
|
AbstractResizer.props = {
|
|
@@ -28661,8 +28862,8 @@
|
|
|
28661
28862
|
dimension: "COL",
|
|
28662
28863
|
});
|
|
28663
28864
|
}
|
|
28664
|
-
|
|
28665
|
-
return this._getDimensionsInViewport(hiddenIndex).start;
|
|
28865
|
+
getUnhideButtonStyle(hiddenIndex) {
|
|
28866
|
+
return cssPropertiesToCss({ left: this._getDimensionsInViewport(hiddenIndex).start + "px" });
|
|
28666
28867
|
}
|
|
28667
28868
|
}
|
|
28668
28869
|
css /* scss */ `
|
|
@@ -28708,18 +28909,9 @@
|
|
|
28708
28909
|
height: 1px;
|
|
28709
28910
|
background-color: ${SELECTION_BORDER_COLOR};
|
|
28710
28911
|
}
|
|
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);
|
|
28912
|
+
.o-unhide-buttons {
|
|
28913
|
+
height: fit-content;
|
|
28914
|
+
transform: translate(0, -50%);
|
|
28723
28915
|
}
|
|
28724
28916
|
.o-unhide:hover {
|
|
28725
28917
|
z-index: ${ComponentsImportance.Grid + 1};
|
|
@@ -28834,8 +29026,8 @@
|
|
|
28834
29026
|
elements: hiddenElements,
|
|
28835
29027
|
});
|
|
28836
29028
|
}
|
|
28837
|
-
|
|
28838
|
-
return this._getDimensionsInViewport(hiddenIndex).start;
|
|
29029
|
+
getUnhideButtonStyle(hiddenIndex) {
|
|
29030
|
+
return cssPropertiesToCss({ top: this._getDimensionsInViewport(hiddenIndex).start + "px" });
|
|
28839
29031
|
}
|
|
28840
29032
|
}
|
|
28841
29033
|
css /* scss */ `
|
|
@@ -29342,7 +29534,6 @@
|
|
|
29342
29534
|
owl.onMounted(() => this.focus());
|
|
29343
29535
|
this.props.exposeFocus(() => this.focus());
|
|
29344
29536
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
29345
|
-
owl.useEffect(() => this.focus(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
29346
29537
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
29347
29538
|
this.moveCanvas(deltaX, deltaY);
|
|
29348
29539
|
this.hoveredCell.col = undefined;
|
|
@@ -29779,6 +29970,7 @@
|
|
|
29779
29970
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
29780
29971
|
const target = this.env.model.getters.getSelectedZones();
|
|
29781
29972
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
29973
|
+
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
29782
29974
|
if (clipboardString === content) {
|
|
29783
29975
|
// the paste actually comes from o-spreadsheet itself
|
|
29784
29976
|
interactivePaste(this.env, target);
|
|
@@ -29786,7 +29978,7 @@
|
|
|
29786
29978
|
else {
|
|
29787
29979
|
interactivePasteFromOS(this.env, target, content);
|
|
29788
29980
|
}
|
|
29789
|
-
if (
|
|
29981
|
+
if (isCutOperation) {
|
|
29790
29982
|
await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
29791
29983
|
}
|
|
29792
29984
|
}
|
|
@@ -31399,12 +31591,6 @@
|
|
|
31399
31591
|
}
|
|
31400
31592
|
function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
31401
31593
|
let { sheetName, xc } = splitReference(range);
|
|
31402
|
-
if (sheetName) {
|
|
31403
|
-
sheetName = getCanonicalSheetName(sheetName) + "!";
|
|
31404
|
-
}
|
|
31405
|
-
else {
|
|
31406
|
-
sheetName = "";
|
|
31407
|
-
}
|
|
31408
31594
|
let zone = toUnboundedZone(xc);
|
|
31409
31595
|
if (dataSetsHaveTitle && zone.bottom !== undefined && zone.right !== undefined) {
|
|
31410
31596
|
const height = zone.bottom - zone.top + 1;
|
|
@@ -31417,7 +31603,7 @@
|
|
|
31417
31603
|
}
|
|
31418
31604
|
}
|
|
31419
31605
|
const dataXC = zoneToXc(zone);
|
|
31420
|
-
return sheetName
|
|
31606
|
+
return getFullReference(sheetName, dataXC);
|
|
31421
31607
|
}
|
|
31422
31608
|
|
|
31423
31609
|
/**
|
|
@@ -34080,6 +34266,14 @@
|
|
|
34080
34266
|
// ---------------------------------------------------------------------------
|
|
34081
34267
|
// Command Handling
|
|
34082
34268
|
// ---------------------------------------------------------------------------
|
|
34269
|
+
allowDispatch(cmd) {
|
|
34270
|
+
switch (cmd.type) {
|
|
34271
|
+
case "SET_BORDER":
|
|
34272
|
+
return this.checkBordersUnchanged(cmd);
|
|
34273
|
+
default:
|
|
34274
|
+
return "Success" /* CommandResult.Success */;
|
|
34275
|
+
}
|
|
34276
|
+
}
|
|
34083
34277
|
handle(cmd) {
|
|
34084
34278
|
switch (cmd.type) {
|
|
34085
34279
|
case "ADD_MERGE":
|
|
@@ -34499,6 +34693,14 @@
|
|
|
34499
34693
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
34500
34694
|
}
|
|
34501
34695
|
}
|
|
34696
|
+
checkBordersUnchanged(cmd) {
|
|
34697
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
34698
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
34699
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
34700
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
34701
|
+
}
|
|
34702
|
+
return "Success" /* CommandResult.Success */;
|
|
34703
|
+
}
|
|
34502
34704
|
// ---------------------------------------------------------------------------
|
|
34503
34705
|
// Import/Export
|
|
34504
34706
|
// ---------------------------------------------------------------------------
|
|
@@ -34967,6 +35169,9 @@
|
|
|
34967
35169
|
// -----------------------------------------------------------------------------
|
|
34968
35170
|
function compile(formula) {
|
|
34969
35171
|
const tokens = rangeTokenize(formula);
|
|
35172
|
+
return compileTokens(tokens);
|
|
35173
|
+
}
|
|
35174
|
+
function compileTokens(tokens) {
|
|
34970
35175
|
const { dependencies, constantValues } = formulaArguments(tokens);
|
|
34971
35176
|
const cacheKey = compilationCacheKey(tokens, dependencies, constantValues);
|
|
34972
35177
|
if (!functionCache[cacheKey]) {
|
|
@@ -35322,7 +35527,6 @@
|
|
|
35322
35527
|
static getters = [
|
|
35323
35528
|
"zoneToXC",
|
|
35324
35529
|
"getCells",
|
|
35325
|
-
"getFormulaCellContent",
|
|
35326
35530
|
"getTranslatedCellFormula",
|
|
35327
35531
|
"getCellStyle",
|
|
35328
35532
|
"getCellById",
|
|
@@ -35333,11 +35537,11 @@
|
|
|
35333
35537
|
for (const sheet of Object.keys(this.cells)) {
|
|
35334
35538
|
for (const cell of Object.values(this.cells[sheet] || {})) {
|
|
35335
35539
|
if (cell.isFormula) {
|
|
35336
|
-
for (const range of cell.dependencies) {
|
|
35540
|
+
for (const range of cell.compiledFormula.dependencies) {
|
|
35337
35541
|
if (!sheetId || range.sheetId === sheetId) {
|
|
35338
35542
|
const change = applyChange(range);
|
|
35339
35543
|
if (change.changeType !== "NONE") {
|
|
35340
|
-
this.history.update("cells", sheet, cell.id, "dependencies", cell.dependencies.indexOf(range), change.range);
|
|
35544
|
+
this.history.update("cells", sheet, cell.id, "compiledFormula", "dependencies", cell.compiledFormula.dependencies.indexOf(range), change.range);
|
|
35341
35545
|
}
|
|
35342
35546
|
}
|
|
35343
35547
|
}
|
|
@@ -35351,8 +35555,9 @@
|
|
|
35351
35555
|
allowDispatch(cmd) {
|
|
35352
35556
|
switch (cmd.type) {
|
|
35353
35557
|
case "UPDATE_CELL":
|
|
35558
|
+
return this.checkCellOutOfSheet(cmd);
|
|
35354
35559
|
case "CLEAR_CELL":
|
|
35355
|
-
return this.
|
|
35560
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
35356
35561
|
default:
|
|
35357
35562
|
return "Success" /* CommandResult.Success */;
|
|
35358
35563
|
}
|
|
@@ -35521,24 +35726,18 @@
|
|
|
35521
35726
|
*/
|
|
35522
35727
|
getCellById(cellId) {
|
|
35523
35728
|
// this must be as fast as possible
|
|
35524
|
-
|
|
35525
|
-
|
|
35526
|
-
|
|
35527
|
-
if (cell) {
|
|
35528
|
-
return cell;
|
|
35529
|
-
}
|
|
35530
|
-
}
|
|
35531
|
-
return undefined;
|
|
35729
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35730
|
+
const sheet = this.cells[position.sheetId];
|
|
35731
|
+
return sheet[cellId];
|
|
35532
35732
|
}
|
|
35533
35733
|
/*
|
|
35534
35734
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
35535
35735
|
*/
|
|
35536
|
-
getFormulaCellContent(sheetId,
|
|
35537
|
-
const ranges = dependencies || cell.dependencies;
|
|
35736
|
+
getFormulaCellContent(sheetId, compiledFormula, dependencies) {
|
|
35538
35737
|
let rangeIndex = 0;
|
|
35539
|
-
return concat(
|
|
35738
|
+
return concat(compiledFormula.tokens.map((token) => {
|
|
35540
35739
|
if (token.type === "REFERENCE") {
|
|
35541
|
-
const range =
|
|
35740
|
+
const range = dependencies[rangeIndex++];
|
|
35542
35741
|
return this.getters.getRangeString(range, sheetId);
|
|
35543
35742
|
}
|
|
35544
35743
|
return token.value;
|
|
@@ -35547,12 +35746,9 @@
|
|
|
35547
35746
|
/*
|
|
35548
35747
|
* Constructs a formula string based on an initial formula and a translation vector
|
|
35549
35748
|
*/
|
|
35550
|
-
getTranslatedCellFormula(sheetId, offsetX, offsetY, compiledFormula
|
|
35551
|
-
const adaptedDependencies = this.getters.createAdaptedRanges(dependencies, offsetX, offsetY, sheetId);
|
|
35552
|
-
return this.getFormulaCellContent(sheetId,
|
|
35553
|
-
compiledFormula,
|
|
35554
|
-
dependencies: adaptedDependencies,
|
|
35555
|
-
});
|
|
35749
|
+
getTranslatedCellFormula(sheetId, offsetX, offsetY, compiledFormula) {
|
|
35750
|
+
const adaptedDependencies = this.getters.createAdaptedRanges(compiledFormula.dependencies, offsetX, offsetY, sheetId);
|
|
35751
|
+
return this.getFormulaCellContent(sheetId, compiledFormula, adaptedDependencies);
|
|
35556
35752
|
}
|
|
35557
35753
|
getCellStyle(position) {
|
|
35558
35754
|
return this.getters.getCell(position)?.style || {};
|
|
@@ -35732,8 +35928,10 @@
|
|
|
35732
35928
|
style,
|
|
35733
35929
|
format,
|
|
35734
35930
|
isFormula: true,
|
|
35735
|
-
compiledFormula
|
|
35736
|
-
|
|
35931
|
+
compiledFormula: {
|
|
35932
|
+
...compiledFormula,
|
|
35933
|
+
dependencies: [],
|
|
35934
|
+
},
|
|
35737
35935
|
};
|
|
35738
35936
|
}
|
|
35739
35937
|
/**
|
|
@@ -35742,7 +35940,7 @@
|
|
|
35742
35940
|
*/
|
|
35743
35941
|
createFormulaCellWithDependencies(id, compiledFormula, format, style, sheetId) {
|
|
35744
35942
|
const dependencies = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
35745
|
-
return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.
|
|
35943
|
+
return new FormulaCellWithDependencies(id, compiledFormula, format, style, dependencies, sheetId, this.getters.getRangeString.bind(this));
|
|
35746
35944
|
}
|
|
35747
35945
|
createErrorFormula(id, content, format, style, error) {
|
|
35748
35946
|
return {
|
|
@@ -35752,46 +35950,72 @@
|
|
|
35752
35950
|
format,
|
|
35753
35951
|
isFormula: true,
|
|
35754
35952
|
compiledFormula: {
|
|
35755
|
-
dependencies: [],
|
|
35756
35953
|
tokens: tokenize(content),
|
|
35954
|
+
dependencies: [],
|
|
35757
35955
|
execute: function () {
|
|
35758
35956
|
throw error;
|
|
35759
35957
|
},
|
|
35760
35958
|
},
|
|
35761
|
-
dependencies: [],
|
|
35762
35959
|
};
|
|
35763
35960
|
}
|
|
35764
|
-
checkCellOutOfSheet(
|
|
35961
|
+
checkCellOutOfSheet(cmd) {
|
|
35962
|
+
const { sheetId, col, row } = cmd;
|
|
35765
35963
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
35766
35964
|
if (!sheet)
|
|
35767
35965
|
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
35768
35966
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
35769
35967
|
return isInside(col, row, sheetZone) ? "Success" /* CommandResult.Success */ : "TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */;
|
|
35770
35968
|
}
|
|
35969
|
+
checkUselessClearCell(cmd) {
|
|
35970
|
+
const cell = this.getters.getCell(cmd);
|
|
35971
|
+
if (!cell)
|
|
35972
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35973
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
35974
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35975
|
+
}
|
|
35976
|
+
return "Success" /* CommandResult.Success */;
|
|
35977
|
+
}
|
|
35771
35978
|
}
|
|
35772
35979
|
class FormulaCellWithDependencies {
|
|
35773
35980
|
id;
|
|
35774
|
-
compiledFormula;
|
|
35775
35981
|
format;
|
|
35776
35982
|
style;
|
|
35777
|
-
dependencies;
|
|
35778
35983
|
sheetId;
|
|
35779
|
-
|
|
35984
|
+
getRangeString;
|
|
35780
35985
|
isFormula = true;
|
|
35781
|
-
|
|
35986
|
+
compiledFormula;
|
|
35987
|
+
constructor(id, compiledFormula, format, style, dependencies, sheetId, getRangeString) {
|
|
35782
35988
|
this.id = id;
|
|
35783
|
-
this.compiledFormula = compiledFormula;
|
|
35784
35989
|
this.format = format;
|
|
35785
35990
|
this.style = style;
|
|
35786
|
-
this.dependencies = dependencies;
|
|
35787
35991
|
this.sheetId = sheetId;
|
|
35788
|
-
this.
|
|
35992
|
+
this.getRangeString = getRangeString;
|
|
35993
|
+
let rangeIndex = 0;
|
|
35994
|
+
const tokens = compiledFormula.tokens.map((token) => {
|
|
35995
|
+
if (token.type === "REFERENCE") {
|
|
35996
|
+
const index = rangeIndex++;
|
|
35997
|
+
return new RangeReferenceToken(() => this.getRangeString(dependencies[index], this.sheetId));
|
|
35998
|
+
}
|
|
35999
|
+
return token;
|
|
36000
|
+
});
|
|
36001
|
+
this.compiledFormula = {
|
|
36002
|
+
...compiledFormula,
|
|
36003
|
+
dependencies,
|
|
36004
|
+
tokens,
|
|
36005
|
+
};
|
|
35789
36006
|
}
|
|
35790
36007
|
get content() {
|
|
35791
|
-
return this.
|
|
35792
|
-
|
|
35793
|
-
|
|
35794
|
-
|
|
36008
|
+
return concat(this.compiledFormula.tokens.map((token) => token.value));
|
|
36009
|
+
}
|
|
36010
|
+
}
|
|
36011
|
+
class RangeReferenceToken {
|
|
36012
|
+
getValue;
|
|
36013
|
+
type = "REFERENCE";
|
|
36014
|
+
constructor(getValue) {
|
|
36015
|
+
this.getValue = getValue;
|
|
36016
|
+
}
|
|
36017
|
+
get value() {
|
|
36018
|
+
return this.getValue();
|
|
35795
36019
|
}
|
|
35796
36020
|
}
|
|
35797
36021
|
|
|
@@ -36440,6 +36664,9 @@
|
|
|
36440
36664
|
return this.rules[sheetId].find((rule) => rule.id === id);
|
|
36441
36665
|
}
|
|
36442
36666
|
getValidationRuleForCell({ sheetId, col, row }) {
|
|
36667
|
+
if (!this.rules[sheetId]) {
|
|
36668
|
+
return undefined;
|
|
36669
|
+
}
|
|
36443
36670
|
for (const rule of this.rules[sheetId]) {
|
|
36444
36671
|
for (const range of rule.ranges) {
|
|
36445
36672
|
if (isInside(col, row, range.zone)) {
|
|
@@ -36936,6 +37163,13 @@
|
|
|
36936
37163
|
}
|
|
36937
37164
|
onDeleteColumnsRows(cmd) {
|
|
36938
37165
|
for (const table of this.getFilterTables(cmd.sheetId)) {
|
|
37166
|
+
// Remove the filter tables whose data filter headers are in the removed rows.
|
|
37167
|
+
if (cmd.dimension === "ROW" && cmd.elements.includes(table.zone.top)) {
|
|
37168
|
+
const tables = { ...this.tables[cmd.sheetId] };
|
|
37169
|
+
delete tables[table.id];
|
|
37170
|
+
this.history.update("tables", cmd.sheetId, tables);
|
|
37171
|
+
continue;
|
|
37172
|
+
}
|
|
36939
37173
|
const zone = reduceZoneOnDeletion(table.zone, cmd.dimension === "COL" ? "left" : "top", cmd.elements);
|
|
36940
37174
|
if (!zone) {
|
|
36941
37175
|
const tables = { ...this.tables[cmd.sheetId] };
|
|
@@ -37605,7 +37839,7 @@
|
|
|
37605
37839
|
const rangeString = this.getters.getRangeString(expandedRange, forSheetId);
|
|
37606
37840
|
if (this.isSingleCellOrMerge(rangeImpl.sheetId, rangeImpl.zone)) {
|
|
37607
37841
|
const { sheetName, xc } = splitReference(rangeString);
|
|
37608
|
-
return
|
|
37842
|
+
return getFullReference(sheetName, xc.split(":")[0]);
|
|
37609
37843
|
}
|
|
37610
37844
|
return rangeString;
|
|
37611
37845
|
}
|
|
@@ -39030,10 +39264,13 @@
|
|
|
39030
39264
|
// begin with the end.
|
|
39031
39265
|
rows.sort((a, b) => b - a);
|
|
39032
39266
|
for (let group of groupConsecutive(rows)) {
|
|
39267
|
+
// indexes are sorted in the descending order
|
|
39268
|
+
const from = group[group.length - 1];
|
|
39269
|
+
const to = group[0];
|
|
39033
39270
|
// Move the cells.
|
|
39034
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
39035
|
-
// Effectively delete the
|
|
39036
|
-
|
|
39271
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
39272
|
+
// Effectively delete the rows
|
|
39273
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
39037
39274
|
}
|
|
39038
39275
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
39039
39276
|
if (count) {
|
|
@@ -39055,8 +39292,6 @@
|
|
|
39055
39292
|
this.addEmptyRows(sheet, quantity);
|
|
39056
39293
|
// Move the cells.
|
|
39057
39294
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
39058
|
-
// Recompute the left-right/top-bottom.
|
|
39059
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
39060
39295
|
if (index < sheet.panes.ySplit) {
|
|
39061
39296
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
39062
39297
|
}
|
|
@@ -39157,35 +39392,20 @@
|
|
|
39157
39392
|
}
|
|
39158
39393
|
}
|
|
39159
39394
|
}
|
|
39160
|
-
updateRowsStructureOnDeletion(
|
|
39395
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
39161
39396
|
const rows = [];
|
|
39162
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39397
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
39163
39398
|
for (let i in sheet.rows) {
|
|
39164
|
-
|
|
39399
|
+
const row = Number(i);
|
|
39400
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
39165
39401
|
continue;
|
|
39166
39402
|
}
|
|
39167
39403
|
rows.push({
|
|
39168
|
-
cells: cellsQueue.
|
|
39404
|
+
cells: cellsQueue.pop(),
|
|
39169
39405
|
});
|
|
39170
39406
|
}
|
|
39171
39407
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39172
39408
|
}
|
|
39173
|
-
/**
|
|
39174
|
-
* Update the rows of the sheet after an addition:
|
|
39175
|
-
* - Rename the rows
|
|
39176
|
-
*
|
|
39177
|
-
* @param sheet Sheet on which the deletion occurs
|
|
39178
|
-
* @param addedRow Index of the added row
|
|
39179
|
-
* @param rowsToAdd Number of the rows to add
|
|
39180
|
-
*/
|
|
39181
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
39182
|
-
const rows = [];
|
|
39183
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39184
|
-
sheet.rows.forEach(() => rows.push({
|
|
39185
|
-
cells: cellsQueue.shift(),
|
|
39186
|
-
}));
|
|
39187
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39188
|
-
}
|
|
39189
39409
|
/**
|
|
39190
39410
|
* Add empty rows at the end of the rows
|
|
39191
39411
|
*
|
|
@@ -39712,6 +39932,7 @@
|
|
|
39712
39932
|
getters;
|
|
39713
39933
|
computeCell;
|
|
39714
39934
|
evalContext;
|
|
39935
|
+
rangeCache = {};
|
|
39715
39936
|
constructor(context, getters, computeCell) {
|
|
39716
39937
|
this.getters = getters;
|
|
39717
39938
|
this.computeCell = computeCell;
|
|
@@ -39734,7 +39955,8 @@
|
|
|
39734
39955
|
refFn(range, isMeta, functionName, paramNumber) {
|
|
39735
39956
|
if (isMeta) {
|
|
39736
39957
|
// Use zoneToXc of zone instead of getRangeString to avoid sending unbounded ranges
|
|
39737
|
-
|
|
39958
|
+
const sheetName = this.getters.getSheetName(range.sheetId);
|
|
39959
|
+
return { value: getFullReference(sheetName, zoneToXc(range.zone)) };
|
|
39738
39960
|
}
|
|
39739
39961
|
if (!isZoneValid(range.zone)) {
|
|
39740
39962
|
throw new InvalidReferenceError();
|
|
@@ -39797,17 +40019,24 @@
|
|
|
39797
40019
|
if (!_zone) {
|
|
39798
40020
|
return [[]];
|
|
39799
40021
|
}
|
|
40022
|
+
const { top, left, bottom, right } = zone;
|
|
40023
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
40024
|
+
if (cacheKey in this.rangeCache) {
|
|
40025
|
+
return this.rangeCache[cacheKey];
|
|
40026
|
+
}
|
|
39800
40027
|
const height = _zone.bottom - _zone.top + 1;
|
|
39801
40028
|
const width = _zone.right - _zone.left + 1;
|
|
39802
|
-
const matrix = Array
|
|
40029
|
+
const matrix = new Array(width);
|
|
39803
40030
|
// Performance issue: nested loop is faster than a map here
|
|
39804
40031
|
for (let col = _zone.left; col <= _zone.right; col++) {
|
|
40032
|
+
const colIndex = col - _zone.left;
|
|
40033
|
+
matrix[colIndex] = new Array(height);
|
|
39805
40034
|
for (let row = _zone.top; row <= _zone.bottom; row++) {
|
|
39806
|
-
const colIndex = col - _zone.left;
|
|
39807
40035
|
const rowIndex = row - _zone.top;
|
|
39808
40036
|
matrix[colIndex][rowIndex] = this.readCell({ sheetId, col, row });
|
|
39809
40037
|
}
|
|
39810
40038
|
}
|
|
40039
|
+
this.rangeCache[cacheKey] = matrix;
|
|
39811
40040
|
return matrix;
|
|
39812
40041
|
}
|
|
39813
40042
|
}
|
|
@@ -39984,6 +40213,13 @@
|
|
|
39984
40213
|
return (this.evaluatedCells.get(this.encodePosition(position)) ||
|
|
39985
40214
|
createEvaluatedCell("", { locale: this.getters.getLocale() }));
|
|
39986
40215
|
}
|
|
40216
|
+
getSpreadPositionsOf(position) {
|
|
40217
|
+
const positionId = this.encodePosition(position);
|
|
40218
|
+
if (!this.spreadingRelations.isArrayFormula(positionId)) {
|
|
40219
|
+
return [];
|
|
40220
|
+
}
|
|
40221
|
+
return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map(this.decodePosition.bind(this));
|
|
40222
|
+
}
|
|
39987
40223
|
getArrayFormulaSpreadingOn(position) {
|
|
39988
40224
|
const positionId = this.encodePosition(position);
|
|
39989
40225
|
const formulaPosition = this.getArrayFormulaSpreadingOnId(positionId);
|
|
@@ -40006,6 +40242,7 @@
|
|
|
40006
40242
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
40007
40243
|
}
|
|
40008
40244
|
updateCompilationParameters() {
|
|
40245
|
+
// rebuild the compilation parameters (with a clean cache)
|
|
40009
40246
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40010
40247
|
}
|
|
40011
40248
|
evaluateCells(positions) {
|
|
@@ -40049,6 +40286,16 @@
|
|
|
40049
40286
|
this.evaluatedCells = new Map();
|
|
40050
40287
|
this.evaluate(this.getAllCells());
|
|
40051
40288
|
}
|
|
40289
|
+
evaluateFormula(sheetId, formulaString) {
|
|
40290
|
+
const compiledFormula = compile(formulaString);
|
|
40291
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40292
|
+
this.updateCompilationParameters();
|
|
40293
|
+
const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
|
|
40294
|
+
if (isMatrix(result)) {
|
|
40295
|
+
return matrixMap(result, (cell) => cell.value);
|
|
40296
|
+
}
|
|
40297
|
+
return result.value;
|
|
40298
|
+
}
|
|
40052
40299
|
getAllCells() {
|
|
40053
40300
|
const positionIds = new JetSet();
|
|
40054
40301
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
@@ -40075,6 +40322,7 @@
|
|
|
40075
40322
|
this.nextPositionsToUpdate = cells;
|
|
40076
40323
|
let currentIteration = 0;
|
|
40077
40324
|
while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
|
|
40325
|
+
this.updateCompilationParameters();
|
|
40078
40326
|
const positionIds = Array.from(this.nextPositionsToUpdate);
|
|
40079
40327
|
this.nextPositionsToUpdate.clear();
|
|
40080
40328
|
for (let i = 0; i < positionIds.length; ++i) {
|
|
@@ -40098,7 +40346,8 @@
|
|
|
40098
40346
|
if (!this.blockedArrayFormulas.has(positionId)) {
|
|
40099
40347
|
this.invalidateSpreading(positionId);
|
|
40100
40348
|
}
|
|
40101
|
-
const
|
|
40349
|
+
const cellPosition = this.decodePosition(positionId);
|
|
40350
|
+
const cell = this.getters.getCell(cellPosition);
|
|
40102
40351
|
if (cell === undefined) {
|
|
40103
40352
|
return createEvaluatedCell("", { locale: this.getters.getLocale() });
|
|
40104
40353
|
}
|
|
@@ -40109,7 +40358,7 @@
|
|
|
40109
40358
|
}
|
|
40110
40359
|
this.cellsBeingComputed.add(cellId);
|
|
40111
40360
|
return cell.isFormula
|
|
40112
|
-
? this.computeFormulaCell(cell)
|
|
40361
|
+
? this.computeFormulaCell(cellPosition.sheetId, cell)
|
|
40113
40362
|
: evaluateLiteral(cell.content, { format: cell.format, locale: this.getters.getLocale() });
|
|
40114
40363
|
}
|
|
40115
40364
|
catch (e) {
|
|
@@ -40135,14 +40384,9 @@
|
|
|
40135
40384
|
e.message = e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled);
|
|
40136
40385
|
return errorCell(e);
|
|
40137
40386
|
}
|
|
40138
|
-
computeFormulaCell(cellData) {
|
|
40387
|
+
computeFormulaCell(sheetId, cellData) {
|
|
40139
40388
|
const cellId = cellData.id;
|
|
40140
|
-
this.compilationParams
|
|
40141
|
-
// compute the value lazily for performance reasons
|
|
40142
|
-
const position = this.compilationParams[2].getters.getCellPosition(cellId);
|
|
40143
|
-
return toXC(position.col, position.row);
|
|
40144
|
-
};
|
|
40145
|
-
const formulaReturn = cellData.compiledFormula.execute(cellData.dependencies, ...this.compilationParams);
|
|
40389
|
+
const formulaReturn = updateEvalContextAndExecute(cellData.compiledFormula, this.compilationParams, sheetId, cellId);
|
|
40146
40390
|
if (!isMatrix(formulaReturn)) {
|
|
40147
40391
|
return createEvaluatedCell(formulaReturn.value, {
|
|
40148
40392
|
format: cellData.format || formulaReturn.format,
|
|
@@ -40242,7 +40486,7 @@
|
|
|
40242
40486
|
return [];
|
|
40243
40487
|
}
|
|
40244
40488
|
const dependencies = [];
|
|
40245
|
-
for (const range of cell.dependencies) {
|
|
40489
|
+
for (const range of cell.compiledFormula.dependencies) {
|
|
40246
40490
|
if (range.invalidSheetName || range.invalidXc) {
|
|
40247
40491
|
continue;
|
|
40248
40492
|
}
|
|
@@ -40344,6 +40588,18 @@
|
|
|
40344
40588
|
return sheetId;
|
|
40345
40589
|
}
|
|
40346
40590
|
}
|
|
40591
|
+
function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
|
|
40592
|
+
compilationParams[2].__originCellXC = lazy(() => {
|
|
40593
|
+
if (!cellId) {
|
|
40594
|
+
return undefined;
|
|
40595
|
+
}
|
|
40596
|
+
// compute the value lazily for performance reasons
|
|
40597
|
+
const position = compilationParams[2].getters.getCellPosition(cellId);
|
|
40598
|
+
return toXC(position.col, position.row);
|
|
40599
|
+
});
|
|
40600
|
+
compilationParams[2].__originSheetId = sheetId;
|
|
40601
|
+
return compiledFormula.execute(compiledFormula.dependencies, ...compilationParams);
|
|
40602
|
+
}
|
|
40347
40603
|
|
|
40348
40604
|
//#region
|
|
40349
40605
|
// ---------------------------------------------------------------------------
|
|
@@ -40438,7 +40694,6 @@
|
|
|
40438
40694
|
// of other cells depending on it, at the next iteration.
|
|
40439
40695
|
//#endregion
|
|
40440
40696
|
class EvaluationPlugin extends UIPlugin {
|
|
40441
|
-
config;
|
|
40442
40697
|
static getters = [
|
|
40443
40698
|
"evaluateFormula",
|
|
40444
40699
|
"getCorrespondingFormulaCell",
|
|
@@ -40448,15 +40703,14 @@
|
|
|
40448
40703
|
"getEvaluatedCell",
|
|
40449
40704
|
"getEvaluatedCells",
|
|
40450
40705
|
"getEvaluatedCellsInZone",
|
|
40706
|
+
"getSpreadPositionsOf",
|
|
40707
|
+
"getArrayFormulaSpreadingOn",
|
|
40451
40708
|
];
|
|
40452
40709
|
shouldRebuildDependenciesGraph = true;
|
|
40453
40710
|
evaluator;
|
|
40454
|
-
compilationParams;
|
|
40455
40711
|
positionsToUpdate = [];
|
|
40456
40712
|
constructor(config) {
|
|
40457
40713
|
super(config);
|
|
40458
|
-
this.config = config;
|
|
40459
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40460
40714
|
this.evaluator = new Evaluator(config.custom, this.getters);
|
|
40461
40715
|
}
|
|
40462
40716
|
// ---------------------------------------------------------------------------
|
|
@@ -40481,10 +40735,6 @@
|
|
|
40481
40735
|
case "EVALUATE_CELLS":
|
|
40482
40736
|
this.evaluator.evaluateAllCells();
|
|
40483
40737
|
break;
|
|
40484
|
-
case "UPDATE_LOCALE":
|
|
40485
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40486
|
-
this.evaluator.updateCompilationParameters();
|
|
40487
|
-
break;
|
|
40488
40738
|
}
|
|
40489
40739
|
}
|
|
40490
40740
|
finalize() {
|
|
@@ -40502,16 +40752,7 @@
|
|
|
40502
40752
|
// Getters
|
|
40503
40753
|
// ---------------------------------------------------------------------------
|
|
40504
40754
|
evaluateFormula(sheetId, formulaString) {
|
|
40505
|
-
|
|
40506
|
-
const ranges = [];
|
|
40507
|
-
for (let xc of compiledFormula.dependencies) {
|
|
40508
|
-
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40509
|
-
}
|
|
40510
|
-
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40511
|
-
if (isMatrix(array)) {
|
|
40512
|
-
return array.map((col) => col.map((row) => row.value));
|
|
40513
|
-
}
|
|
40514
|
-
return array.value;
|
|
40755
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
40515
40756
|
}
|
|
40516
40757
|
/**
|
|
40517
40758
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -40557,6 +40798,12 @@
|
|
|
40557
40798
|
getEvaluatedCellsInZone(sheetId, zone) {
|
|
40558
40799
|
return positions(zone).map(({ col, row }) => this.getters.getEvaluatedCell({ sheetId, col, row }));
|
|
40559
40800
|
}
|
|
40801
|
+
getSpreadPositionsOf(position) {
|
|
40802
|
+
return this.evaluator.getSpreadPositionsOf(position);
|
|
40803
|
+
}
|
|
40804
|
+
getArrayFormulaSpreadingOn(position) {
|
|
40805
|
+
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
40806
|
+
}
|
|
40560
40807
|
// ---------------------------------------------------------------------------
|
|
40561
40808
|
// Export
|
|
40562
40809
|
// ---------------------------------------------------------------------------
|
|
@@ -40594,13 +40841,13 @@
|
|
|
40594
40841
|
*/
|
|
40595
40842
|
getCorrespondingFormulaCell(position) {
|
|
40596
40843
|
const cell = this.getters.getCell(position);
|
|
40597
|
-
if (cell && cell.
|
|
40598
|
-
|
|
40599
|
-
|
|
40600
|
-
|
|
40844
|
+
if (cell && cell.isFormula) {
|
|
40845
|
+
return isBadExpression(cell.compiledFormula.tokens) ? undefined : cell;
|
|
40846
|
+
}
|
|
40847
|
+
else if (cell && cell.content) {
|
|
40601
40848
|
return undefined;
|
|
40602
40849
|
}
|
|
40603
|
-
const spreadingFormulaPosition = this.
|
|
40850
|
+
const spreadingFormulaPosition = this.getArrayFormulaSpreadingOn(position);
|
|
40604
40851
|
if (spreadingFormulaPosition === undefined) {
|
|
40605
40852
|
return undefined;
|
|
40606
40853
|
}
|
|
@@ -40610,13 +40857,10 @@
|
|
|
40610
40857
|
}
|
|
40611
40858
|
return undefined;
|
|
40612
40859
|
}
|
|
40613
|
-
getCompilationParameters() {
|
|
40614
|
-
return buildCompilationParameters(this.config.custom, this.getters, (position) => this.evaluator.getEvaluatedCell(position));
|
|
40615
|
-
}
|
|
40616
40860
|
}
|
|
40617
|
-
function isBadExpression(
|
|
40861
|
+
function isBadExpression(tokens) {
|
|
40618
40862
|
try {
|
|
40619
|
-
|
|
40863
|
+
compileTokens(tokens);
|
|
40620
40864
|
return false;
|
|
40621
40865
|
}
|
|
40622
40866
|
catch (error) {
|
|
@@ -40785,22 +41029,20 @@
|
|
|
40785
41029
|
invalidateCFEvaluationCommands.has(cmd.type) ||
|
|
40786
41030
|
cmd.type === "EVALUATE_CELLS" ||
|
|
40787
41031
|
cmd.type === "UPDATE_CELL") {
|
|
40788
|
-
|
|
40789
|
-
|
|
40790
|
-
this.history.update("charts", chartId, undefined);
|
|
40791
|
-
}
|
|
41032
|
+
for (const chartId in this.charts) {
|
|
41033
|
+
this.charts[chartId] = undefined;
|
|
40792
41034
|
}
|
|
40793
41035
|
}
|
|
40794
41036
|
switch (cmd.type) {
|
|
40795
41037
|
case "UPDATE_CHART":
|
|
40796
41038
|
case "CREATE_CHART":
|
|
40797
41039
|
case "DELETE_FIGURE":
|
|
40798
|
-
this.
|
|
41040
|
+
this.charts[cmd.id] = undefined;
|
|
40799
41041
|
break;
|
|
40800
41042
|
case "DELETE_SHEET":
|
|
40801
41043
|
for (let chartId in this.charts) {
|
|
40802
41044
|
if (!this.getters.isChartDefined(chartId)) {
|
|
40803
|
-
this.
|
|
41045
|
+
this.charts[chartId] = undefined;
|
|
40804
41046
|
}
|
|
40805
41047
|
}
|
|
40806
41048
|
break;
|
|
@@ -40812,8 +41054,7 @@
|
|
|
40812
41054
|
if (!chart) {
|
|
40813
41055
|
throw new Error(`No chart for the given id: ${figureId}`);
|
|
40814
41056
|
}
|
|
40815
|
-
|
|
40816
|
-
this.history.update("charts", figureId, runtime);
|
|
41057
|
+
this.charts[figureId] = this.createRuntimeChart(chart);
|
|
40817
41058
|
}
|
|
40818
41059
|
return this.charts[figureId];
|
|
40819
41060
|
}
|
|
@@ -40965,7 +41206,10 @@
|
|
|
40965
41206
|
const values = cf.rule.values.map((value, i) => {
|
|
40966
41207
|
const compiledFormula = formulas[i];
|
|
40967
41208
|
if (compiledFormula) {
|
|
40968
|
-
return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top,
|
|
41209
|
+
return this.getters.getTranslatedCellFormula(sheetId, col - zone.left, row - zone.top, {
|
|
41210
|
+
...compiledFormula,
|
|
41211
|
+
dependencies: compiledFormula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)),
|
|
41212
|
+
});
|
|
40969
41213
|
}
|
|
40970
41214
|
return value;
|
|
40971
41215
|
});
|
|
@@ -41337,7 +41581,10 @@
|
|
|
41337
41581
|
}
|
|
41338
41582
|
try {
|
|
41339
41583
|
const formula = compile(value);
|
|
41340
|
-
const translatedFormula = this.getters.getTranslatedCellFormula(sheetId, offset.col, offset.row,
|
|
41584
|
+
const translatedFormula = this.getters.getTranslatedCellFormula(sheetId, offset.col, offset.row, {
|
|
41585
|
+
...formula,
|
|
41586
|
+
dependencies: formula.dependencies.map((d) => this.getters.getRangeFromSheetXC(sheetId, d)),
|
|
41587
|
+
});
|
|
41341
41588
|
const evaluated = this.getters.evaluateFormula(sheetId, translatedFormula);
|
|
41342
41589
|
return evaluated && !isMatrix(evaluated) ? evaluated.toString() : "";
|
|
41343
41590
|
}
|
|
@@ -43308,11 +43555,26 @@
|
|
|
43308
43555
|
let cellsInRow = [];
|
|
43309
43556
|
for (let col of columnsIndex) {
|
|
43310
43557
|
const position = { col, row, sheetId };
|
|
43558
|
+
const spreader = getters.getArrayFormulaSpreadingOn(position);
|
|
43559
|
+
let cell = getters.getCell(position);
|
|
43560
|
+
const evaluatedCell = getters.getEvaluatedCell(position);
|
|
43561
|
+
if (spreader) {
|
|
43562
|
+
const isSpreaderCopied = rowsIndex.includes(spreader.row) && columnsIndex.includes(spreader.col);
|
|
43563
|
+
const content = isSpreaderCopied
|
|
43564
|
+
? ""
|
|
43565
|
+
: formatValue(evaluatedCell.value, { locale: getters.getLocale() });
|
|
43566
|
+
cell = {
|
|
43567
|
+
id: cell?.id || "",
|
|
43568
|
+
style: cell?.style,
|
|
43569
|
+
format: evaluatedCell.format,
|
|
43570
|
+
content,
|
|
43571
|
+
isFormula: false,
|
|
43572
|
+
};
|
|
43573
|
+
}
|
|
43311
43574
|
cellsInRow.push({
|
|
43312
|
-
cell
|
|
43313
|
-
style: getters.getCellComputedStyle(position),
|
|
43314
|
-
evaluatedCell: getters.getEvaluatedCell(position),
|
|
43575
|
+
cell,
|
|
43315
43576
|
border: getters.getCellBorder(position) || undefined,
|
|
43577
|
+
evaluatedCell,
|
|
43316
43578
|
position,
|
|
43317
43579
|
});
|
|
43318
43580
|
}
|
|
@@ -43434,13 +43696,6 @@
|
|
|
43434
43696
|
});
|
|
43435
43697
|
}
|
|
43436
43698
|
this.pasteCopiedTables(target);
|
|
43437
|
-
this.cells.forEach((row) => {
|
|
43438
|
-
row.forEach((c) => {
|
|
43439
|
-
if (c.cell) {
|
|
43440
|
-
c.cell = undefined;
|
|
43441
|
-
}
|
|
43442
|
-
});
|
|
43443
|
-
});
|
|
43444
43699
|
}
|
|
43445
43700
|
/**
|
|
43446
43701
|
* The clipped zone is copied as many times as it fits in the target.
|
|
@@ -43514,7 +43769,7 @@
|
|
|
43514
43769
|
clearClippedZones() {
|
|
43515
43770
|
for (const row of this.cells) {
|
|
43516
43771
|
for (const cell of row) {
|
|
43517
|
-
if (cell
|
|
43772
|
+
if (cell?.cell) {
|
|
43518
43773
|
this.dispatch("CLEAR_CELL", cell.position);
|
|
43519
43774
|
}
|
|
43520
43775
|
}
|
|
@@ -43540,6 +43795,9 @@
|
|
|
43540
43795
|
const rowCells = this.cells[r];
|
|
43541
43796
|
for (let c = 0; c < width; c++) {
|
|
43542
43797
|
const origin = rowCells[c];
|
|
43798
|
+
if (!origin) {
|
|
43799
|
+
continue;
|
|
43800
|
+
}
|
|
43543
43801
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
43544
43802
|
// TODO: refactor this part. the "Paste merge" action is also executed with
|
|
43545
43803
|
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
@@ -43563,53 +43821,42 @@
|
|
|
43563
43821
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43564
43822
|
const { sheetId, col, row } = target;
|
|
43565
43823
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43566
|
-
if (clipboardOption?.pasteOption
|
|
43567
|
-
const
|
|
43568
|
-
const
|
|
43569
|
-
|
|
43570
|
-
|
|
43571
|
-
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43572
|
-
left: targetBorders?.left || originBorders?.left,
|
|
43573
|
-
right: targetBorders?.right || originBorders?.right,
|
|
43574
|
-
};
|
|
43575
|
-
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43824
|
+
if (clipboardOption?.pasteOption === "onlyValue") {
|
|
43825
|
+
const locale = this.getters.getLocale();
|
|
43826
|
+
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43827
|
+
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
43828
|
+
return;
|
|
43576
43829
|
}
|
|
43577
|
-
|
|
43578
|
-
|
|
43579
|
-
|
|
43580
|
-
|
|
43581
|
-
|
|
43582
|
-
|
|
43583
|
-
|
|
43584
|
-
|
|
43585
|
-
|
|
43586
|
-
|
|
43587
|
-
|
|
43588
|
-
|
|
43589
|
-
|
|
43590
|
-
|
|
43591
|
-
}
|
|
43592
|
-
|
|
43593
|
-
|
|
43594
|
-
|
|
43595
|
-
|
|
43830
|
+
const targetBorders = this.getters.getCellBorder(target);
|
|
43831
|
+
const originBorders = origin.border;
|
|
43832
|
+
const border = {
|
|
43833
|
+
top: targetBorders?.top || originBorders?.top,
|
|
43834
|
+
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43835
|
+
left: targetBorders?.left || originBorders?.left,
|
|
43836
|
+
right: targetBorders?.right || originBorders?.right,
|
|
43837
|
+
};
|
|
43838
|
+
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43839
|
+
if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43840
|
+
this.dispatch("UPDATE_CELL", {
|
|
43841
|
+
...target,
|
|
43842
|
+
style: origin.cell?.style ?? null,
|
|
43843
|
+
format: origin.cell?.format ?? origin.evaluatedCell.format ?? targetCell.format,
|
|
43844
|
+
});
|
|
43845
|
+
return;
|
|
43846
|
+
}
|
|
43847
|
+
const content = origin.cell && origin.cell.isFormula && operation === "COPY"
|
|
43848
|
+
? this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula)
|
|
43849
|
+
: origin.cell?.content;
|
|
43850
|
+
if (content !== "" || origin.cell?.format || origin.cell?.style) {
|
|
43596
43851
|
this.dispatch("UPDATE_CELL", {
|
|
43597
43852
|
...target,
|
|
43598
43853
|
content,
|
|
43599
|
-
style: origin.cell
|
|
43600
|
-
format: origin.cell
|
|
43854
|
+
style: origin.cell?.style || null,
|
|
43855
|
+
format: origin.cell?.format,
|
|
43601
43856
|
});
|
|
43602
43857
|
}
|
|
43603
43858
|
else if (targetCell) {
|
|
43604
|
-
|
|
43605
|
-
this.dispatch("UPDATE_CELL", { ...target, content: "" });
|
|
43606
|
-
}
|
|
43607
|
-
else if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43608
|
-
this.dispatch("UPDATE_CELL", { ...target, style: null, format: "" });
|
|
43609
|
-
}
|
|
43610
|
-
else {
|
|
43611
|
-
this.dispatch("CLEAR_CELL", target);
|
|
43612
|
-
}
|
|
43859
|
+
this.dispatch("CLEAR_CELL", target);
|
|
43613
43860
|
}
|
|
43614
43861
|
}
|
|
43615
43862
|
/**
|
|
@@ -43671,22 +43918,28 @@
|
|
|
43671
43918
|
return (this.cells
|
|
43672
43919
|
.map((cells) => {
|
|
43673
43920
|
return cells
|
|
43674
|
-
.map((c) => this.getters.shouldShowFormulas() && c
|
|
43921
|
+
.map((c) => this.getters.shouldShowFormulas() && c?.cell?.isFormula
|
|
43675
43922
|
? c.cell?.content || ""
|
|
43676
|
-
: c
|
|
43923
|
+
: c?.evaluatedCell?.formattedValue || "")
|
|
43677
43924
|
.join("\t");
|
|
43678
43925
|
})
|
|
43679
43926
|
.join("\n") || "\t");
|
|
43680
43927
|
}
|
|
43681
43928
|
getHTMLContent() {
|
|
43682
43929
|
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
43930
|
+
if (!this.cells[0][0]) {
|
|
43931
|
+
return "";
|
|
43932
|
+
}
|
|
43683
43933
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
43684
43934
|
}
|
|
43685
43935
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
43686
43936
|
for (const row of this.cells) {
|
|
43687
43937
|
htmlTable += "<tr>";
|
|
43688
43938
|
for (const cell of row) {
|
|
43689
|
-
|
|
43939
|
+
if (!cell) {
|
|
43940
|
+
continue;
|
|
43941
|
+
}
|
|
43942
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
43690
43943
|
const cellText = this.getters.getCellText(cell.position);
|
|
43691
43944
|
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
43692
43945
|
}
|
|
@@ -44014,24 +44267,49 @@
|
|
|
44014
44267
|
*/
|
|
44015
44268
|
class FindAndReplacePlugin extends UIPlugin {
|
|
44016
44269
|
static layers = [3 /* LAYERS.Search */];
|
|
44017
|
-
static getters = [
|
|
44018
|
-
|
|
44270
|
+
static getters = [
|
|
44271
|
+
"getSearchMatches",
|
|
44272
|
+
"getCurrentSelectedMatchIndex",
|
|
44273
|
+
"getSearchOptions",
|
|
44274
|
+
"getAllSheetMatchesCount",
|
|
44275
|
+
"getActiveSheetMatchesCount",
|
|
44276
|
+
"getSpecificRangeMatchesCount",
|
|
44277
|
+
];
|
|
44278
|
+
allSheetsMatches = [];
|
|
44279
|
+
activeSheetMatches = [];
|
|
44280
|
+
specificRangeMatches = [];
|
|
44281
|
+
// fixme: why do we make selectedMatchIndex on top of a selected
|
|
44282
|
+
// property in the matches?
|
|
44019
44283
|
selectedMatchIndex = null;
|
|
44020
44284
|
currentSearchRegex = null;
|
|
44021
44285
|
searchOptions = {
|
|
44022
44286
|
matchCase: false,
|
|
44023
44287
|
exactMatch: false,
|
|
44024
44288
|
searchFormulas: false,
|
|
44289
|
+
searchScope: "allSheets",
|
|
44290
|
+
specificRange: undefined,
|
|
44025
44291
|
};
|
|
44026
44292
|
toSearch = "";
|
|
44027
44293
|
isSearchDirty = false;
|
|
44294
|
+
get searchMatches() {
|
|
44295
|
+
switch (this.searchOptions.searchScope) {
|
|
44296
|
+
case "allSheets":
|
|
44297
|
+
return this.allSheetsMatches;
|
|
44298
|
+
case "activeSheet":
|
|
44299
|
+
return this.activeSheetMatches;
|
|
44300
|
+
case "specificRange":
|
|
44301
|
+
return this.specificRangeMatches;
|
|
44302
|
+
}
|
|
44303
|
+
}
|
|
44028
44304
|
// ---------------------------------------------------------------------------
|
|
44029
44305
|
// Command Handling
|
|
44030
44306
|
// ---------------------------------------------------------------------------
|
|
44031
44307
|
handle(cmd) {
|
|
44032
44308
|
switch (cmd.type) {
|
|
44033
44309
|
case "UPDATE_SEARCH":
|
|
44034
|
-
|
|
44310
|
+
const rangeData = cmd.searchOptions.specificRange;
|
|
44311
|
+
const specificRange = rangeData && this.getters.getRangeFromRangeData(rangeData);
|
|
44312
|
+
this.updateSearch(cmd.toSearch, { ...cmd.searchOptions, specificRange });
|
|
44035
44313
|
break;
|
|
44036
44314
|
case "CLEAR_SEARCH":
|
|
44037
44315
|
this.clearSearch();
|
|
@@ -44061,7 +44339,9 @@
|
|
|
44061
44339
|
this.isSearchDirty = true;
|
|
44062
44340
|
break;
|
|
44063
44341
|
case "ACTIVATE_SHEET":
|
|
44064
|
-
this.
|
|
44342
|
+
if (this.searchOptions.searchScope === "activeSheet") {
|
|
44343
|
+
this.isSearchDirty = true;
|
|
44344
|
+
}
|
|
44065
44345
|
break;
|
|
44066
44346
|
}
|
|
44067
44347
|
}
|
|
@@ -44080,6 +44360,18 @@
|
|
|
44080
44360
|
getCurrentSelectedMatchIndex() {
|
|
44081
44361
|
return this.selectedMatchIndex;
|
|
44082
44362
|
}
|
|
44363
|
+
getSearchOptions() {
|
|
44364
|
+
return { ...this.searchOptions, specificRange: this.searchOptions.specificRange?.rangeData };
|
|
44365
|
+
}
|
|
44366
|
+
getAllSheetMatchesCount() {
|
|
44367
|
+
return this.allSheetsMatches.length;
|
|
44368
|
+
}
|
|
44369
|
+
getActiveSheetMatchesCount() {
|
|
44370
|
+
return this.activeSheetMatches.length;
|
|
44371
|
+
}
|
|
44372
|
+
getSpecificRangeMatchesCount() {
|
|
44373
|
+
return this.specificRangeMatches.length;
|
|
44374
|
+
}
|
|
44083
44375
|
// ---------------------------------------------------------------------------
|
|
44084
44376
|
// Search
|
|
44085
44377
|
// ---------------------------------------------------------------------------
|
|
@@ -44100,8 +44392,8 @@
|
|
|
44100
44392
|
* refresh the matches according to the current search options
|
|
44101
44393
|
*/
|
|
44102
44394
|
refreshSearch() {
|
|
44103
|
-
|
|
44104
|
-
this.
|
|
44395
|
+
this.selectedMatchIndex = null;
|
|
44396
|
+
this.findMatches();
|
|
44105
44397
|
this.selectNextCell(Direction.current);
|
|
44106
44398
|
}
|
|
44107
44399
|
/**
|
|
@@ -44116,36 +44408,65 @@
|
|
|
44116
44408
|
}
|
|
44117
44409
|
this.currentSearchRegex = RegExp(searchValue, flags);
|
|
44118
44410
|
}
|
|
44411
|
+
getSheetsInSearchOrder() {
|
|
44412
|
+
switch (this.searchOptions.searchScope) {
|
|
44413
|
+
case "allSheets":
|
|
44414
|
+
const sheetIds = this.getters.getSheetIds();
|
|
44415
|
+
const activeSheetIndex = sheetIds.findIndex((id) => id === this.getters.getActiveSheetId());
|
|
44416
|
+
return [
|
|
44417
|
+
sheetIds[activeSheetIndex],
|
|
44418
|
+
...sheetIds.slice(activeSheetIndex + 1),
|
|
44419
|
+
...sheetIds.slice(0, activeSheetIndex),
|
|
44420
|
+
];
|
|
44421
|
+
case "activeSheet":
|
|
44422
|
+
return [this.getters.getActiveSheetId()];
|
|
44423
|
+
case "specificRange":
|
|
44424
|
+
const specificRange = this.searchOptions.specificRange;
|
|
44425
|
+
if (!specificRange) {
|
|
44426
|
+
return [];
|
|
44427
|
+
}
|
|
44428
|
+
return specificRange ? [specificRange.sheetId] : [];
|
|
44429
|
+
}
|
|
44430
|
+
}
|
|
44119
44431
|
/**
|
|
44120
44432
|
* Find matches using the current regex
|
|
44121
44433
|
*/
|
|
44122
44434
|
findMatches() {
|
|
44123
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
44124
|
-
const cells = this.getters.getCells(sheetId);
|
|
44125
44435
|
const matches = [];
|
|
44126
44436
|
if (this.toSearch) {
|
|
44127
|
-
for (const
|
|
44128
|
-
|
|
44437
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
44438
|
+
matches.push(...this.findMatchesInSheet(sheetId));
|
|
44439
|
+
}
|
|
44440
|
+
}
|
|
44441
|
+
// set results
|
|
44442
|
+
this.allSheetsMatches = matches;
|
|
44443
|
+
this.activeSheetMatches = matches.filter((match) => match.sheetId === this.getters.getActiveSheetId());
|
|
44444
|
+
if (this.searchOptions.specificRange) {
|
|
44445
|
+
const { sheetId, zone } = this.searchOptions.specificRange;
|
|
44446
|
+
this.specificRangeMatches = matches.filter((match) => match.sheetId === sheetId && isInside(match.col, match.row, zone));
|
|
44447
|
+
}
|
|
44448
|
+
else {
|
|
44449
|
+
this.specificRangeMatches = [];
|
|
44450
|
+
}
|
|
44451
|
+
}
|
|
44452
|
+
findMatchesInSheet(sheetId) {
|
|
44453
|
+
const matches = [];
|
|
44454
|
+
const { left, right, top, bottom } = this.getters.getSheetZone(sheetId);
|
|
44455
|
+
for (let row = top; row <= bottom; row++) {
|
|
44456
|
+
for (let col = left; col <= right; col++) {
|
|
44129
44457
|
const isColHidden = this.getters.isColHidden(sheetId, col);
|
|
44130
44458
|
const isRowHidden = this.getters.isRowHidden(sheetId, row);
|
|
44131
44459
|
if (isColHidden || isRowHidden) {
|
|
44132
44460
|
continue;
|
|
44133
44461
|
}
|
|
44134
|
-
|
|
44135
|
-
|
|
44136
|
-
|
|
44137
|
-
const match = { col, row, selected: false };
|
|
44462
|
+
const cellPosition = { sheetId, col, row };
|
|
44463
|
+
if (this.currentSearchRegex?.test(this.getSearchableString(cellPosition))) {
|
|
44464
|
+
const match = { sheetId, col, row };
|
|
44138
44465
|
matches.push(match);
|
|
44139
44466
|
}
|
|
44140
44467
|
}
|
|
44141
44468
|
}
|
|
44142
|
-
return matches
|
|
44143
|
-
}
|
|
44144
|
-
sortByRowThenColumn(a, b) {
|
|
44145
|
-
if (a.row === b.row) {
|
|
44146
|
-
return a.col - b.col;
|
|
44147
|
-
}
|
|
44148
|
-
return a.row > b.row ? 1 : -1;
|
|
44469
|
+
return matches;
|
|
44149
44470
|
}
|
|
44150
44471
|
/**
|
|
44151
44472
|
* Changes the selected search cell. Given a direction it will
|
|
@@ -44163,30 +44484,47 @@
|
|
|
44163
44484
|
}
|
|
44164
44485
|
let nextIndex;
|
|
44165
44486
|
if (this.selectedMatchIndex === null) {
|
|
44166
|
-
|
|
44487
|
+
let nextMatchIndex = -1;
|
|
44488
|
+
// if search is not available in current sheet will select in next sheet
|
|
44489
|
+
for (const sheetId of this.getSheetsInSearchOrder()) {
|
|
44490
|
+
nextMatchIndex = matches.findIndex((match) => match.sheetId === sheetId);
|
|
44491
|
+
if (nextMatchIndex !== -1) {
|
|
44492
|
+
break;
|
|
44493
|
+
}
|
|
44494
|
+
}
|
|
44495
|
+
nextIndex = nextMatchIndex;
|
|
44167
44496
|
}
|
|
44168
44497
|
else {
|
|
44169
44498
|
nextIndex = this.selectedMatchIndex + indexChange;
|
|
44170
44499
|
}
|
|
44171
|
-
//
|
|
44172
|
-
nextIndex = (
|
|
44500
|
+
// loop index value inside the array (index -1 => last index)
|
|
44501
|
+
nextIndex = (nextIndex + matches.length) % matches.length;
|
|
44173
44502
|
this.selectedMatchIndex = nextIndex;
|
|
44503
|
+
const selectedMatch = matches[nextIndex];
|
|
44504
|
+
// Switch to the sheet where the match is located
|
|
44505
|
+
if (this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
|
|
44506
|
+
this.dispatch("ACTIVATE_SHEET", {
|
|
44507
|
+
sheetIdFrom: this.getters.getActiveSheetId(),
|
|
44508
|
+
sheetIdTo: selectedMatch.sheetId,
|
|
44509
|
+
});
|
|
44510
|
+
}
|
|
44174
44511
|
// we want grid selection to capture the selection stream
|
|
44175
44512
|
this.selection.getBackToDefault();
|
|
44176
|
-
this.selection.selectCell(
|
|
44177
|
-
for (let index = 0; index < this.searchMatches.length; index++) {
|
|
44178
|
-
this.searchMatches[index].selected = index === this.selectedMatchIndex;
|
|
44179
|
-
}
|
|
44513
|
+
this.selection.selectCell(selectedMatch.col, selectedMatch.row);
|
|
44180
44514
|
}
|
|
44181
44515
|
clearSearch() {
|
|
44182
44516
|
this.toSearch = "";
|
|
44183
|
-
this.searchMatches = [];
|
|
44184
44517
|
this.selectedMatchIndex = null;
|
|
44185
44518
|
this.currentSearchRegex = null;
|
|
44519
|
+
this.allSheetsMatches = [];
|
|
44520
|
+
this.activeSheetMatches = [];
|
|
44521
|
+
this.specificRangeMatches = [];
|
|
44186
44522
|
this.searchOptions = {
|
|
44187
44523
|
matchCase: false,
|
|
44188
44524
|
exactMatch: false,
|
|
44189
44525
|
searchFormulas: false,
|
|
44526
|
+
searchScope: "allSheets",
|
|
44527
|
+
specificRange: undefined,
|
|
44190
44528
|
};
|
|
44191
44529
|
}
|
|
44192
44530
|
// ---------------------------------------------------------------------------
|
|
@@ -44196,17 +44534,18 @@
|
|
|
44196
44534
|
if (!this.currentSearchRegex) {
|
|
44197
44535
|
return;
|
|
44198
44536
|
}
|
|
44199
|
-
const
|
|
44200
|
-
|
|
44201
|
-
|
|
44537
|
+
const cell = this.getters.getCell(selectedMatch);
|
|
44538
|
+
if (!cell?.content) {
|
|
44539
|
+
return;
|
|
44540
|
+
}
|
|
44202
44541
|
if (cell?.isFormula && !this.searchOptions.searchFormulas) {
|
|
44203
44542
|
return;
|
|
44204
44543
|
}
|
|
44205
44544
|
const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
|
|
44206
|
-
const toReplace = this.getSearchableString(
|
|
44545
|
+
const toReplace = this.getSearchableString(selectedMatch);
|
|
44207
44546
|
const content = toReplace.replace(replaceRegex, replaceWith);
|
|
44208
44547
|
const canonicalContent = canonicalizeNumberContent(content, this.getters.getLocale());
|
|
44209
|
-
this.dispatch("UPDATE_CELL", {
|
|
44548
|
+
this.dispatch("UPDATE_CELL", { ...selectedMatch, content: canonicalContent });
|
|
44210
44549
|
}
|
|
44211
44550
|
/**
|
|
44212
44551
|
* Replace the value of the currently selected match
|
|
@@ -44237,7 +44576,10 @@
|
|
|
44237
44576
|
drawGrid(renderingContext) {
|
|
44238
44577
|
const { ctx } = renderingContext;
|
|
44239
44578
|
const sheetId = this.getters.getActiveSheetId();
|
|
44240
|
-
for (const match of this.searchMatches) {
|
|
44579
|
+
for (const [index, match] of this.searchMatches.entries()) {
|
|
44580
|
+
if (match.sheetId !== sheetId) {
|
|
44581
|
+
continue; // Skip drawing matches from other sheets
|
|
44582
|
+
}
|
|
44241
44583
|
const merge = this.getters.getMerge({ sheetId, col: match.col, row: match.row });
|
|
44242
44584
|
const left = merge ? merge.left : match.col;
|
|
44243
44585
|
const right = merge ? merge.right : match.col;
|
|
@@ -44247,12 +44589,21 @@
|
|
|
44247
44589
|
if (width > 0 && height > 0) {
|
|
44248
44590
|
ctx.fillStyle = BACKGROUND_COLOR;
|
|
44249
44591
|
ctx.fillRect(x, y, width, height);
|
|
44250
|
-
if (
|
|
44592
|
+
if (index === this.selectedMatchIndex) {
|
|
44251
44593
|
ctx.strokeStyle = BORDER_COLOR;
|
|
44252
44594
|
ctx.strokeRect(x, y, width, height);
|
|
44253
44595
|
}
|
|
44254
44596
|
}
|
|
44255
44597
|
}
|
|
44598
|
+
if (this.searchOptions.searchScope === "specificRange") {
|
|
44599
|
+
const range = this.searchOptions.specificRange;
|
|
44600
|
+
if (!range || range.sheetId !== sheetId) {
|
|
44601
|
+
return;
|
|
44602
|
+
}
|
|
44603
|
+
const { x, y, width, height } = this.getters.getVisibleRect(range.zone);
|
|
44604
|
+
ctx.strokeStyle = BORDER_COLOR;
|
|
44605
|
+
ctx.strokeRect(x, y, width, height);
|
|
44606
|
+
}
|
|
44256
44607
|
}
|
|
44257
44608
|
}
|
|
44258
44609
|
|
|
@@ -45535,7 +45886,6 @@
|
|
|
45535
45886
|
}
|
|
45536
45887
|
|
|
45537
45888
|
class SortPlugin extends UIPlugin {
|
|
45538
|
-
static getters = ["getContiguousZone"];
|
|
45539
45889
|
allowDispatch(cmd) {
|
|
45540
45890
|
switch (cmd.type) {
|
|
45541
45891
|
case "SORT_CELLS":
|
|
@@ -45583,143 +45933,6 @@
|
|
|
45583
45933
|
}
|
|
45584
45934
|
return "Success" /* CommandResult.Success */;
|
|
45585
45935
|
}
|
|
45586
|
-
// getContiguousZone helpers
|
|
45587
|
-
/**
|
|
45588
|
-
* safe-version of expandZone to make sure we don't get out of the grid
|
|
45589
|
-
*/
|
|
45590
|
-
expand(sheetId, z) {
|
|
45591
|
-
const { left, right, top, bottom } = this.getters.expandZone(sheetId, z);
|
|
45592
|
-
return {
|
|
45593
|
-
left: Math.max(0, left),
|
|
45594
|
-
right: Math.min(this.getters.getNumberCols(sheetId) - 1, right),
|
|
45595
|
-
top: Math.max(0, top),
|
|
45596
|
-
bottom: Math.min(this.getters.getNumberRows(sheetId) - 1, bottom),
|
|
45597
|
-
};
|
|
45598
|
-
}
|
|
45599
|
-
/**
|
|
45600
|
-
* verifies the presence of at least one non-empty cell in the given zone
|
|
45601
|
-
*/
|
|
45602
|
-
checkExpandedValues(sheetId, z) {
|
|
45603
|
-
const expandedZone = this.expand(sheetId, z);
|
|
45604
|
-
let cell;
|
|
45605
|
-
if (this.getters.doesIntersectMerge(sheetId, expandedZone)) {
|
|
45606
|
-
const { left, right, top, bottom } = expandedZone;
|
|
45607
|
-
for (let c = left; c <= right; c++) {
|
|
45608
|
-
for (let r = top; r <= bottom; r++) {
|
|
45609
|
-
const { col, row } = this.getters.getMainCellPosition({ sheetId, col: c, row: r });
|
|
45610
|
-
cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
45611
|
-
if (cell.formattedValue) {
|
|
45612
|
-
return true;
|
|
45613
|
-
}
|
|
45614
|
-
}
|
|
45615
|
-
}
|
|
45616
|
-
}
|
|
45617
|
-
else {
|
|
45618
|
-
for (let cell of this.getters.getEvaluatedCellsInZone(sheetId, expandedZone)) {
|
|
45619
|
-
if (cell.formattedValue) {
|
|
45620
|
-
return true;
|
|
45621
|
-
}
|
|
45622
|
-
}
|
|
45623
|
-
}
|
|
45624
|
-
return false;
|
|
45625
|
-
}
|
|
45626
|
-
/**
|
|
45627
|
-
* This function will expand the provided zone in directions (top, bottom, left, right) for which there
|
|
45628
|
-
* are non-null cells on the external boundary of the zone in the given direction.
|
|
45629
|
-
*
|
|
45630
|
-
* Example:
|
|
45631
|
-
* A B C D E
|
|
45632
|
-
* ___ ___ ___ ___ ___
|
|
45633
|
-
* 1 | | D | | | |
|
|
45634
|
-
* ___ ___ ___ ___ ___
|
|
45635
|
-
* 2 | 5 | | 1 | D | |
|
|
45636
|
-
* ___ ___ ___ ___ ___
|
|
45637
|
-
* 3 | | | A | X | |
|
|
45638
|
-
* ___ ___ ___ ___ ___
|
|
45639
|
-
* 4 | | | | | |
|
|
45640
|
-
* ___ ___ ___ ___ ___
|
|
45641
|
-
*
|
|
45642
|
-
* Let's consider a provided zone corresponding to (C2:D3) - (left:2, right: 3, top:1, bottom:2)
|
|
45643
|
-
* - the top external boundary is (B1:E1)
|
|
45644
|
-
* Since we have B1='D' != "", we expand to the top: => (C1:D3)
|
|
45645
|
-
* The top boundary having reached the top of the grid, we cannot expand in that direction anymore
|
|
45646
|
-
*
|
|
45647
|
-
* - the left boundary is (B1:B4)
|
|
45648
|
-
* since we have B1 again, we expand to the left => (B1:D3)
|
|
45649
|
-
*
|
|
45650
|
-
* - the right and bottom boundaries are a dead end for now as (E1:E4) and (A4:E4) are empty.
|
|
45651
|
-
*
|
|
45652
|
-
* - the left boundary is now (A1:A4)
|
|
45653
|
-
* Since we have A2=5 != "", we can therefore expand to the left => (A1:D3)
|
|
45654
|
-
*
|
|
45655
|
-
* This will be the final zone as left and top have reached the boundaries of the grid and
|
|
45656
|
-
* the other boundaries (E1:E4) and (A4:E4) are empty.
|
|
45657
|
-
*
|
|
45658
|
-
* @param sheetId UID of concerned sheet
|
|
45659
|
-
* @param zone Zone
|
|
45660
|
-
*
|
|
45661
|
-
*/
|
|
45662
|
-
getContiguousZone(sheetId, zone) {
|
|
45663
|
-
let { top, bottom, left, right } = zone;
|
|
45664
|
-
let canExpand;
|
|
45665
|
-
let stop = false;
|
|
45666
|
-
while (!stop) {
|
|
45667
|
-
stop = true;
|
|
45668
|
-
/** top row external boundary */
|
|
45669
|
-
if (top > 0) {
|
|
45670
|
-
canExpand = this.checkExpandedValues(sheetId, {
|
|
45671
|
-
left: left - 1,
|
|
45672
|
-
right: right + 1,
|
|
45673
|
-
top: top - 1,
|
|
45674
|
-
bottom: top - 1,
|
|
45675
|
-
});
|
|
45676
|
-
if (canExpand) {
|
|
45677
|
-
stop = false;
|
|
45678
|
-
top--;
|
|
45679
|
-
}
|
|
45680
|
-
}
|
|
45681
|
-
/** left column external boundary */
|
|
45682
|
-
if (left > 0) {
|
|
45683
|
-
canExpand = this.checkExpandedValues(sheetId, {
|
|
45684
|
-
left: left - 1,
|
|
45685
|
-
right: left - 1,
|
|
45686
|
-
top: top - 1,
|
|
45687
|
-
bottom: bottom + 1,
|
|
45688
|
-
});
|
|
45689
|
-
if (canExpand) {
|
|
45690
|
-
stop = false;
|
|
45691
|
-
left--;
|
|
45692
|
-
}
|
|
45693
|
-
}
|
|
45694
|
-
/** right column external boundary */
|
|
45695
|
-
if (right < this.getters.getNumberCols(sheetId) - 1) {
|
|
45696
|
-
canExpand = this.checkExpandedValues(sheetId, {
|
|
45697
|
-
left: right + 1,
|
|
45698
|
-
right: right + 1,
|
|
45699
|
-
top: top - 1,
|
|
45700
|
-
bottom: bottom + 1,
|
|
45701
|
-
});
|
|
45702
|
-
if (canExpand) {
|
|
45703
|
-
stop = false;
|
|
45704
|
-
right++;
|
|
45705
|
-
}
|
|
45706
|
-
}
|
|
45707
|
-
/** bottom row external boundary */
|
|
45708
|
-
if (bottom < this.getters.getNumberRows(sheetId) - 1) {
|
|
45709
|
-
canExpand = this.checkExpandedValues(sheetId, {
|
|
45710
|
-
left: left - 1,
|
|
45711
|
-
right: right + 1,
|
|
45712
|
-
top: bottom + 1,
|
|
45713
|
-
bottom: bottom + 1,
|
|
45714
|
-
});
|
|
45715
|
-
if (canExpand) {
|
|
45716
|
-
stop = false;
|
|
45717
|
-
bottom++;
|
|
45718
|
-
}
|
|
45719
|
-
}
|
|
45720
|
-
}
|
|
45721
|
-
return { left, right, top, bottom };
|
|
45722
|
-
}
|
|
45723
45936
|
/**
|
|
45724
45937
|
* This function evaluates if the top row of a provided zone can be considered as a `header`
|
|
45725
45938
|
* by checking the following criteria:
|
|
@@ -45784,7 +45997,7 @@
|
|
|
45784
45997
|
if (cell.isFormula) {
|
|
45785
45998
|
const position = this.getters.getCellPosition(cell.id);
|
|
45786
45999
|
// we only have a vertical offset
|
|
45787
|
-
content = this.getters.getTranslatedCellFormula(sheetId, 0, newRow - position.row, cell.compiledFormula
|
|
46000
|
+
content = this.getters.getTranslatedCellFormula(sheetId, 0, newRow - position.row, cell.compiledFormula);
|
|
45788
46001
|
}
|
|
45789
46002
|
newCellValues.style = cell.style;
|
|
45790
46003
|
newCellValues.content = content;
|
|
@@ -45853,6 +46066,8 @@
|
|
|
45853
46066
|
"getTextWidth",
|
|
45854
46067
|
"getCellText",
|
|
45855
46068
|
"getCellMultiLineText",
|
|
46069
|
+
"getContiguousZone",
|
|
46070
|
+
"isCellEmpty",
|
|
45856
46071
|
];
|
|
45857
46072
|
ctx = document.createElement("canvas").getContext("2d");
|
|
45858
46073
|
// ---------------------------------------------------------------------------
|
|
@@ -45942,9 +46157,52 @@
|
|
|
45942
46157
|
const hasListIcon = !this.getters.isReadonly() && this.getters.cellHasListDataValidationIcon(position);
|
|
45943
46158
|
return isFilterHeader || hasListIcon;
|
|
45944
46159
|
}
|
|
45945
|
-
|
|
45946
|
-
|
|
45947
|
-
|
|
46160
|
+
/**
|
|
46161
|
+
* Expands the given zone until bordered by empty cells or reached the sheet boundaries.
|
|
46162
|
+
*/
|
|
46163
|
+
getContiguousZone(sheetId, zoneToExpand) {
|
|
46164
|
+
/** Try to expand the zone by one col/row in any direction to include a new non-empty cell */
|
|
46165
|
+
const expandZone = (zone) => {
|
|
46166
|
+
for (const col of range(zone.left, zone.right + 1)) {
|
|
46167
|
+
if (!this.isCellEmpty({ sheetId, col, row: zone.top - 1 })) {
|
|
46168
|
+
return { ...zone, top: zone.top - 1 };
|
|
46169
|
+
}
|
|
46170
|
+
if (!this.isCellEmpty({ sheetId, col, row: zone.bottom + 1 })) {
|
|
46171
|
+
return { ...zone, bottom: zone.bottom + 1 };
|
|
46172
|
+
}
|
|
46173
|
+
}
|
|
46174
|
+
for (const row of range(zone.top, zone.bottom + 1)) {
|
|
46175
|
+
if (!this.isCellEmpty({ sheetId, col: zone.left - 1, row })) {
|
|
46176
|
+
return { ...zone, left: zone.left - 1 };
|
|
46177
|
+
}
|
|
46178
|
+
if (!this.isCellEmpty({ sheetId, col: zone.right + 1, row })) {
|
|
46179
|
+
return { ...zone, right: zone.right + 1 };
|
|
46180
|
+
}
|
|
46181
|
+
}
|
|
46182
|
+
return zone;
|
|
46183
|
+
};
|
|
46184
|
+
let hasExpanded = false;
|
|
46185
|
+
let zone = zoneToExpand;
|
|
46186
|
+
do {
|
|
46187
|
+
hasExpanded = false;
|
|
46188
|
+
const newZone = expandZone(zone);
|
|
46189
|
+
if (!isEqual(zone, newZone)) {
|
|
46190
|
+
hasExpanded = true;
|
|
46191
|
+
zone = newZone;
|
|
46192
|
+
continue;
|
|
46193
|
+
}
|
|
46194
|
+
} while (hasExpanded);
|
|
46195
|
+
return zone;
|
|
46196
|
+
}
|
|
46197
|
+
/**
|
|
46198
|
+
* Check if a cell is empty. If the cell is part of a merge,
|
|
46199
|
+
* check if the merge containing the cell is empty.
|
|
46200
|
+
*/
|
|
46201
|
+
isCellEmpty(position) {
|
|
46202
|
+
const mainPosition = this.getters.getMainCellPosition(position);
|
|
46203
|
+
const cell = this.getters.getEvaluatedCell(mainPosition);
|
|
46204
|
+
return cell.type === CellValueType.empty;
|
|
46205
|
+
}
|
|
45948
46206
|
getColMaxWidth(sheetId, index) {
|
|
45949
46207
|
const cellsPositions = positions(this.getters.getColsZone(sheetId, index, index));
|
|
45950
46208
|
const sizes = cellsPositions.map((position) => this.getCellWidth({ sheetId, ...position }));
|
|
@@ -46811,11 +47069,14 @@
|
|
|
46811
47069
|
}
|
|
46812
47070
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
46813
47071
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
47072
|
+
if (this.state.operation === "CUT") {
|
|
47073
|
+
this.state = undefined;
|
|
47074
|
+
}
|
|
46814
47075
|
this.lastPasteState = this.state;
|
|
46815
47076
|
if (this.paintFormatStatus === "oneOff") {
|
|
46816
47077
|
this.paintFormatStatus = "inactive";
|
|
46817
|
-
this.status = "invisible";
|
|
46818
47078
|
}
|
|
47079
|
+
this.status = "invisible";
|
|
46819
47080
|
break;
|
|
46820
47081
|
case "COPY_PASTE_CELLS_ABOVE":
|
|
46821
47082
|
{
|
|
@@ -47042,92 +47303,6 @@
|
|
|
47042
47303
|
}
|
|
47043
47304
|
}
|
|
47044
47305
|
|
|
47045
|
-
/**
|
|
47046
|
-
* Change the reference types inside the given token, if the token represent a range or a cell
|
|
47047
|
-
*
|
|
47048
|
-
* Eg. :
|
|
47049
|
-
* A1 => $A$1 => A$1 => $A1 => A1
|
|
47050
|
-
* A1:$B$1 => $A$1:B$1 => A$1:$B1 => $A1:B1 => A1:$B$1
|
|
47051
|
-
*/
|
|
47052
|
-
function loopThroughReferenceType(token) {
|
|
47053
|
-
if (token.type !== "REFERENCE")
|
|
47054
|
-
return token;
|
|
47055
|
-
const { xc, sheetName } = splitReference(token.value);
|
|
47056
|
-
const [left, right] = xc.split(":");
|
|
47057
|
-
const sheetRef = sheetName ? `${getCanonicalSheetName(sheetName)}!` : "";
|
|
47058
|
-
const updatedLeft = getTokenNextReferenceType(left);
|
|
47059
|
-
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
47060
|
-
return { ...token, value: sheetRef + updatedLeft + updatedRight };
|
|
47061
|
-
}
|
|
47062
|
-
/**
|
|
47063
|
-
* Get a new token with a changed type of reference from the given cell token symbol.
|
|
47064
|
-
* Undefined behavior if given a token other than a cell or if the Xc contains a sheet reference
|
|
47065
|
-
*
|
|
47066
|
-
* A1 => $A$1 => A$1 => $A1 => A1
|
|
47067
|
-
*/
|
|
47068
|
-
function getTokenNextReferenceType(xc) {
|
|
47069
|
-
switch (getReferenceType(xc)) {
|
|
47070
|
-
case "none":
|
|
47071
|
-
xc = setXcToReferenceType(xc, "colrow");
|
|
47072
|
-
break;
|
|
47073
|
-
case "colrow":
|
|
47074
|
-
xc = setXcToReferenceType(xc, "row");
|
|
47075
|
-
break;
|
|
47076
|
-
case "row":
|
|
47077
|
-
xc = setXcToReferenceType(xc, "col");
|
|
47078
|
-
break;
|
|
47079
|
-
case "col":
|
|
47080
|
-
xc = setXcToReferenceType(xc, "none");
|
|
47081
|
-
break;
|
|
47082
|
-
}
|
|
47083
|
-
return xc;
|
|
47084
|
-
}
|
|
47085
|
-
/**
|
|
47086
|
-
* Returns the given XC with the given reference type.
|
|
47087
|
-
*/
|
|
47088
|
-
function setXcToReferenceType(xc, referenceType) {
|
|
47089
|
-
xc = xc.replace(/\$/g, "");
|
|
47090
|
-
let indexOfNumber;
|
|
47091
|
-
switch (referenceType) {
|
|
47092
|
-
case "col":
|
|
47093
|
-
return "$" + xc;
|
|
47094
|
-
case "row":
|
|
47095
|
-
indexOfNumber = xc.search(/[0-9]/);
|
|
47096
|
-
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47097
|
-
case "colrow":
|
|
47098
|
-
indexOfNumber = xc.search(/[0-9]/);
|
|
47099
|
-
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47100
|
-
return "$" + xc;
|
|
47101
|
-
case "none":
|
|
47102
|
-
return xc;
|
|
47103
|
-
}
|
|
47104
|
-
}
|
|
47105
|
-
/**
|
|
47106
|
-
* Return the type of reference used in the given XC of a cell.
|
|
47107
|
-
* Undefined behavior if the XC have a sheet reference
|
|
47108
|
-
*/
|
|
47109
|
-
function getReferenceType(xcCell) {
|
|
47110
|
-
if (isColAndRowFixed(xcCell)) {
|
|
47111
|
-
return "colrow";
|
|
47112
|
-
}
|
|
47113
|
-
else if (isColFixed(xcCell)) {
|
|
47114
|
-
return "col";
|
|
47115
|
-
}
|
|
47116
|
-
else if (isRowFixed(xcCell)) {
|
|
47117
|
-
return "row";
|
|
47118
|
-
}
|
|
47119
|
-
return "none";
|
|
47120
|
-
}
|
|
47121
|
-
function isColFixed(xc) {
|
|
47122
|
-
return xc.startsWith("$");
|
|
47123
|
-
}
|
|
47124
|
-
function isRowFixed(xc) {
|
|
47125
|
-
return xc.includes("$", 1);
|
|
47126
|
-
}
|
|
47127
|
-
function isColAndRowFixed(xc) {
|
|
47128
|
-
return xc.startsWith("$") && xc.length > 1 && xc.slice(1).includes("$");
|
|
47129
|
-
}
|
|
47130
|
-
|
|
47131
47306
|
const CELL_DELETED_MESSAGE = _t("The cell you are trying to edit has been deleted.");
|
|
47132
47307
|
class EditionPlugin extends UIPlugin {
|
|
47133
47308
|
static getters = [
|
|
@@ -47849,6 +48024,8 @@
|
|
|
47849
48024
|
case "EVALUATE_CELLS":
|
|
47850
48025
|
case "ACTIVATE_SHEET":
|
|
47851
48026
|
case "REMOVE_FILTER_TABLE":
|
|
48027
|
+
case "ADD_COLUMNS_ROWS":
|
|
48028
|
+
case "REMOVE_COLUMNS_ROWS":
|
|
47852
48029
|
this.isEvaluationDirty = true;
|
|
47853
48030
|
break;
|
|
47854
48031
|
case "START":
|
|
@@ -48043,32 +48220,32 @@
|
|
|
48043
48220
|
{
|
|
48044
48221
|
name: _t("Sum"),
|
|
48045
48222
|
types: [CellValueType.number],
|
|
48046
|
-
compute: (values, locale) =>
|
|
48223
|
+
compute: (values, locale) => sum([[values]], locale),
|
|
48047
48224
|
},
|
|
48048
48225
|
{
|
|
48049
48226
|
name: _t("Avg"),
|
|
48050
48227
|
types: [CellValueType.number],
|
|
48051
|
-
compute: (values, locale) =>
|
|
48228
|
+
compute: (values, locale) => average([[values]], locale),
|
|
48052
48229
|
},
|
|
48053
48230
|
{
|
|
48054
48231
|
name: _t("Min"),
|
|
48055
48232
|
types: [CellValueType.number],
|
|
48056
|
-
compute: (values, locale) =>
|
|
48233
|
+
compute: (values, locale) => min([[values]], locale),
|
|
48057
48234
|
},
|
|
48058
48235
|
{
|
|
48059
48236
|
name: _t("Max"),
|
|
48060
48237
|
types: [CellValueType.number],
|
|
48061
|
-
compute: (values, locale) =>
|
|
48238
|
+
compute: (values, locale) => max([[values]], locale),
|
|
48062
48239
|
},
|
|
48063
48240
|
{
|
|
48064
48241
|
name: _t("Count"),
|
|
48065
48242
|
types: [CellValueType.number, CellValueType.text, CellValueType.boolean, CellValueType.error],
|
|
48066
|
-
compute: (values
|
|
48243
|
+
compute: (values) => countAny([[values]]),
|
|
48067
48244
|
},
|
|
48068
48245
|
{
|
|
48069
48246
|
name: _t("Count Numbers"),
|
|
48070
48247
|
types: [CellValueType.number, CellValueType.text, CellValueType.boolean, CellValueType.error],
|
|
48071
|
-
compute: (values, locale) =>
|
|
48248
|
+
compute: (values, locale) => countNumbers([[values]], locale),
|
|
48072
48249
|
},
|
|
48073
48250
|
];
|
|
48074
48251
|
/**
|
|
@@ -51983,6 +52160,7 @@
|
|
|
51983
52160
|
};
|
|
51984
52161
|
sidePanel;
|
|
51985
52162
|
composer;
|
|
52163
|
+
spreadsheetRef = owl.useRef("spreadsheet");
|
|
51986
52164
|
_focusGrid;
|
|
51987
52165
|
keyDownMapping;
|
|
51988
52166
|
isViewportTooSmall = false;
|
|
@@ -52017,6 +52195,18 @@
|
|
|
52017
52195
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
52018
52196
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
52019
52197
|
});
|
|
52198
|
+
owl.useEffect(() => {
|
|
52199
|
+
/**
|
|
52200
|
+
* Only refocus the grid if the active element is not a child of the spreadsheet
|
|
52201
|
+
* (i.e. activeElement is outside of the spreadsheetRef component)
|
|
52202
|
+
* and spreadsheet is a child of that element. Anything else means that the focus
|
|
52203
|
+
* is on an element that needs to keep it.
|
|
52204
|
+
*/
|
|
52205
|
+
if (!this.spreadsheetRef.el.contains(document.activeElement) &&
|
|
52206
|
+
document.activeElement?.contains(this.spreadsheetRef.el)) {
|
|
52207
|
+
this.focusGrid();
|
|
52208
|
+
}
|
|
52209
|
+
}, () => [this.env.model.getters.getActiveSheetId()]);
|
|
52020
52210
|
owl.useExternalListener(window, "resize", () => this.render(true));
|
|
52021
52211
|
owl.useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
52022
52212
|
this.bindModelEvents();
|
|
@@ -52098,7 +52288,7 @@
|
|
|
52098
52288
|
}
|
|
52099
52289
|
focusGrid() {
|
|
52100
52290
|
if (!this._focusGrid) {
|
|
52101
|
-
|
|
52291
|
+
return;
|
|
52102
52292
|
}
|
|
52103
52293
|
this._focusGrid();
|
|
52104
52294
|
}
|
|
@@ -53367,7 +53557,7 @@
|
|
|
53367
53557
|
scrollIntoView: false,
|
|
53368
53558
|
});
|
|
53369
53559
|
}
|
|
53370
|
-
const tableZone = this.
|
|
53560
|
+
const tableZone = this.getters.getContiguousZone(sheetId, anchor.zone);
|
|
53371
53561
|
return !deepEquals(tableZone, anchor.zone)
|
|
53372
53562
|
? this.modifyAnchor({ ...anchor, zone: tableZone }, "updateAnchor", {
|
|
53373
53563
|
scrollIntoView: false,
|
|
@@ -53380,7 +53570,8 @@
|
|
|
53380
53570
|
* cells bordering it
|
|
53381
53571
|
*/
|
|
53382
53572
|
selectTableAroundSelection() {
|
|
53383
|
-
const
|
|
53573
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
53574
|
+
const tableZone = this.getters.getContiguousZone(sheetId, this.anchor.zone);
|
|
53384
53575
|
return this.modifyAnchor({ ...this.anchor, zone: tableZone }, "updateAnchor", {
|
|
53385
53576
|
scrollIntoView: false,
|
|
53386
53577
|
});
|
|
@@ -53557,11 +53748,12 @@
|
|
|
53557
53748
|
* next cluster if the given cell is outside a cluster or at the border of a cluster in the given direction.
|
|
53558
53749
|
*/
|
|
53559
53750
|
getEndOfCluster(startPosition, dim, dir) {
|
|
53560
|
-
const
|
|
53751
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
53561
53752
|
let currentPosition = startPosition;
|
|
53562
53753
|
// If both the current cell and the next cell are not empty, we want to go to the end of the cluster
|
|
53563
53754
|
const nextCellPosition = this.getNextCellPosition(startPosition, dim, dir);
|
|
53564
|
-
let mode = !this.isCellEmpty(currentPosition,
|
|
53755
|
+
let mode = !this.getters.isCellEmpty({ ...currentPosition, sheetId }) &&
|
|
53756
|
+
!this.getters.isCellEmpty({ ...nextCellPosition, sheetId })
|
|
53565
53757
|
? "endOfCluster"
|
|
53566
53758
|
: "nextCluster";
|
|
53567
53759
|
while (true) {
|
|
@@ -53571,7 +53763,7 @@
|
|
|
53571
53763
|
currentPosition.row === nextCellPosition.row) {
|
|
53572
53764
|
break;
|
|
53573
53765
|
}
|
|
53574
|
-
const isNextCellEmpty = this.isCellEmpty(nextCellPosition,
|
|
53766
|
+
const isNextCellEmpty = this.getters.isCellEmpty({ ...nextCellPosition, sheetId });
|
|
53575
53767
|
if (mode === "endOfCluster" && isNextCellEmpty) {
|
|
53576
53768
|
break;
|
|
53577
53769
|
}
|
|
@@ -53584,15 +53776,6 @@
|
|
|
53584
53776
|
}
|
|
53585
53777
|
return dim === "cols" ? currentPosition.col : currentPosition.row;
|
|
53586
53778
|
}
|
|
53587
|
-
/**
|
|
53588
|
-
* Check if a cell is empty or undefined in the model. If the cell is part of a merge,
|
|
53589
|
-
* check if the merge containing the cell is empty.
|
|
53590
|
-
*/
|
|
53591
|
-
isCellEmpty({ col, row }, sheetId = this.getters.getActiveSheetId()) {
|
|
53592
|
-
const position = this.getters.getMainCellPosition({ sheetId, col, row });
|
|
53593
|
-
const cell = this.getters.getEvaluatedCell(position);
|
|
53594
|
-
return cell.type === CellValueType.empty;
|
|
53595
|
-
}
|
|
53596
53779
|
/** Computes the next cell position in the given direction by crossing through merges and skipping hidden cells.
|
|
53597
53780
|
*
|
|
53598
53781
|
* This has the same behaviour as getNextAvailablePosition() for certain arguments, but use this method instead
|
|
@@ -53611,45 +53794,6 @@
|
|
|
53611
53794
|
getPosition() {
|
|
53612
53795
|
return { ...this.anchor.cell };
|
|
53613
53796
|
}
|
|
53614
|
-
/**
|
|
53615
|
-
* Expand the given zone to a table.
|
|
53616
|
-
* We define a table by the smallest zone that contain the anchor and that have only empty
|
|
53617
|
-
* cells bordering it
|
|
53618
|
-
*/
|
|
53619
|
-
expandZoneToTable(zoneToExpand) {
|
|
53620
|
-
/** Try to expand the zone by one col/row in any direction to include a new non-empty cell */
|
|
53621
|
-
const expandZone = (zone) => {
|
|
53622
|
-
for (const col of range(zone.left, zone.right + 1)) {
|
|
53623
|
-
if (!this.isCellEmpty({ col, row: zone.top - 1 })) {
|
|
53624
|
-
return { ...zone, top: zone.top - 1 };
|
|
53625
|
-
}
|
|
53626
|
-
if (!this.isCellEmpty({ col, row: zone.bottom + 1 })) {
|
|
53627
|
-
return { ...zone, bottom: zone.bottom + 1 };
|
|
53628
|
-
}
|
|
53629
|
-
}
|
|
53630
|
-
for (const row of range(zone.top, zone.bottom + 1)) {
|
|
53631
|
-
if (!this.isCellEmpty({ col: zone.left - 1, row })) {
|
|
53632
|
-
return { ...zone, left: zone.left - 1 };
|
|
53633
|
-
}
|
|
53634
|
-
if (!this.isCellEmpty({ col: zone.right + 1, row })) {
|
|
53635
|
-
return { ...zone, right: zone.right + 1 };
|
|
53636
|
-
}
|
|
53637
|
-
}
|
|
53638
|
-
return zone;
|
|
53639
|
-
};
|
|
53640
|
-
let hasExpanded = false;
|
|
53641
|
-
let zone = zoneToExpand;
|
|
53642
|
-
do {
|
|
53643
|
-
hasExpanded = false;
|
|
53644
|
-
const newZone = expandZone(zone);
|
|
53645
|
-
if (!isEqual(zone, newZone)) {
|
|
53646
|
-
hasExpanded = true;
|
|
53647
|
-
zone = newZone;
|
|
53648
|
-
continue;
|
|
53649
|
-
}
|
|
53650
|
-
} while (hasExpanded);
|
|
53651
|
-
return zone;
|
|
53652
|
-
}
|
|
53653
53797
|
}
|
|
53654
53798
|
|
|
53655
53799
|
class StateObserver {
|
|
@@ -55537,19 +55681,22 @@
|
|
|
55537
55681
|
* Check if the given command is allowed by all the plugins and the history.
|
|
55538
55682
|
*/
|
|
55539
55683
|
checkDispatchAllowed(command) {
|
|
55540
|
-
|
|
55541
|
-
|
|
55684
|
+
const results = isCoreCommand(command)
|
|
55685
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
55686
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
55687
|
+
if (results.some((r) => r !== "Success" /* CommandResult.Success */)) {
|
|
55688
|
+
return new DispatchResult(results.flat());
|
|
55542
55689
|
}
|
|
55543
|
-
return
|
|
55690
|
+
return DispatchResult.Success;
|
|
55544
55691
|
}
|
|
55545
55692
|
checkDispatchAllowedCoreCommand(command) {
|
|
55546
55693
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
55547
55694
|
results.push(this.range.allowDispatch(command));
|
|
55548
|
-
return
|
|
55695
|
+
return results;
|
|
55549
55696
|
}
|
|
55550
55697
|
checkDispatchAllowedLocalCommand(command) {
|
|
55551
55698
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
55552
|
-
return
|
|
55699
|
+
return results;
|
|
55553
55700
|
}
|
|
55554
55701
|
finalize() {
|
|
55555
55702
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -55844,6 +55991,7 @@
|
|
|
55844
55991
|
FigureComponent,
|
|
55845
55992
|
Menu,
|
|
55846
55993
|
SelectionInput,
|
|
55994
|
+
ValidationMessages,
|
|
55847
55995
|
};
|
|
55848
55996
|
const hooks = {
|
|
55849
55997
|
useDragAndDropListItems,
|
|
@@ -55872,6 +56020,7 @@
|
|
|
55872
56020
|
exports.addFunction = addFunction;
|
|
55873
56021
|
exports.astToFormula = astToFormula;
|
|
55874
56022
|
exports.compile = compile;
|
|
56023
|
+
exports.compileTokens = compileTokens;
|
|
55875
56024
|
exports.components = components;
|
|
55876
56025
|
exports.constants = constants;
|
|
55877
56026
|
exports.convertAstNodes = convertAstNodes;
|
|
@@ -55887,6 +56036,7 @@
|
|
|
55887
56036
|
exports.links = links;
|
|
55888
56037
|
exports.load = load;
|
|
55889
56038
|
exports.parse = parse;
|
|
56039
|
+
exports.parseTokens = parseTokens;
|
|
55890
56040
|
exports.readonlyAllowedCommands = readonlyAllowedCommands;
|
|
55891
56041
|
exports.registries = registries;
|
|
55892
56042
|
exports.setDefaultSheetViewSize = setDefaultSheetViewSize;
|
|
@@ -55894,9 +56044,9 @@
|
|
|
55894
56044
|
exports.tokenize = tokenize;
|
|
55895
56045
|
|
|
55896
56046
|
|
|
55897
|
-
__info__.version = "17.1.0-alpha.
|
|
55898
|
-
__info__.date = "2023-11-
|
|
55899
|
-
__info__.hash = "
|
|
56047
|
+
__info__.version = "17.1.0-alpha.4";
|
|
56048
|
+
__info__.date = "2023-11-24T13:12:24.882Z";
|
|
56049
|
+
__info__.hash = "255821b";
|
|
55900
56050
|
|
|
55901
56051
|
|
|
55902
56052
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|