@odoo/o-spreadsheet 17.1.0-alpha.3 → 17.1.0-alpha.5
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 +769 -520
- package/dist/o-spreadsheet.d.ts +164 -164
- package/dist/o-spreadsheet.esm.js +769 -520
- package/dist/o-spreadsheet.iife.js +769 -520
- package/dist/o-spreadsheet.iife.min.js +299 -327
- package/dist/o_spreadsheet.xml +100 -62
- 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-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.1.0-alpha.5
|
|
6
|
+
* @date 2023-12-05T09:51:40.034Z
|
|
7
|
+
* @hash c2823eb
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -227,7 +227,6 @@ const DEFAULT_CELL_HEIGHT = 23;
|
|
|
227
227
|
const SCROLLBAR_WIDTH = 15;
|
|
228
228
|
const AUTOFILL_EDGE_LENGTH = 8;
|
|
229
229
|
const ICON_EDGE_LENGTH = 18;
|
|
230
|
-
const UNHIDE_ICON_EDGE_LENGTH = 14;
|
|
231
230
|
const MIN_CF_ICON_MARGIN = 4;
|
|
232
231
|
const MIN_CELL_TEXT_MARGIN = 4;
|
|
233
232
|
const CF_ICON_EDGE_LENGTH = 15;
|
|
@@ -691,8 +690,7 @@ function removeFalsyAttributes(obj) {
|
|
|
691
690
|
*
|
|
692
691
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
693
692
|
*/
|
|
694
|
-
const
|
|
695
|
-
" ",
|
|
693
|
+
const whiteSpaceSpecialCharacters = [
|
|
696
694
|
"\t",
|
|
697
695
|
"\f",
|
|
698
696
|
"\v",
|
|
@@ -707,8 +705,7 @@ const whiteSpaceCharacters = [
|
|
|
707
705
|
String.fromCharCode(parseInt("3000", 16)),
|
|
708
706
|
String.fromCharCode(parseInt("feff", 16)),
|
|
709
707
|
];
|
|
710
|
-
const whiteSpaceRegexp = new RegExp(
|
|
711
|
-
const newLineRegex = /\r\n|\r|\n/g;
|
|
708
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
|
|
712
709
|
/**
|
|
713
710
|
* Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
|
|
714
711
|
* different newlines types by \n.
|
|
@@ -716,9 +713,9 @@ const newLineRegex = /\r\n|\r|\n/g;
|
|
|
716
713
|
function replaceSpecialSpaces(text) {
|
|
717
714
|
if (!text)
|
|
718
715
|
return "";
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
return text;
|
|
716
|
+
if (!whiteSpaceRegexp.test(text))
|
|
717
|
+
return text;
|
|
718
|
+
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
722
719
|
}
|
|
723
720
|
/**
|
|
724
721
|
* Determine if the numbers are consecutive.
|
|
@@ -2060,6 +2057,7 @@ var CommandResult;
|
|
|
2060
2057
|
CommandResult["InvalidNumberOfCriterionValues"] = "InvalidNumberOfCriterionValues";
|
|
2061
2058
|
CommandResult["BlockingValidationRule"] = "BlockingValidationRule";
|
|
2062
2059
|
CommandResult["InvalidCopyPasteSelection"] = "InvalidCopyPasteSelection";
|
|
2060
|
+
CommandResult["NoChanges"] = "NoChanges";
|
|
2063
2061
|
})(CommandResult || (CommandResult = {}));
|
|
2064
2062
|
|
|
2065
2063
|
const DEFAULT_LOCALES = [
|
|
@@ -2189,12 +2187,12 @@ function toString(value) {
|
|
|
2189
2187
|
}
|
|
2190
2188
|
}
|
|
2191
2189
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
2192
|
-
function normalizeString(str) {
|
|
2190
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
2193
2191
|
return str
|
|
2194
2192
|
.toLowerCase()
|
|
2195
2193
|
.normalize("NFD")
|
|
2196
2194
|
.replace(/[\u0300-\u036f]/g, "");
|
|
2197
|
-
}
|
|
2195
|
+
});
|
|
2198
2196
|
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);
|
|
2199
2197
|
function toBoolean(value) {
|
|
2200
2198
|
switch (typeof value) {
|
|
@@ -3388,8 +3386,10 @@ function convertInternalFormatToFormat(internalFormat) {
|
|
|
3388
3386
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
3389
3387
|
// Same as above, but matches the exact string (nothing before or after)
|
|
3390
3388
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
3391
|
-
/** Reference of a column header (eg. A, AB) */
|
|
3392
|
-
const colHeader = new RegExp(
|
|
3389
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
3390
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
3391
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
3392
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
3393
3393
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
3394
3394
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
3395
3395
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -3419,6 +3419,9 @@ function isRowReference(xc) {
|
|
|
3419
3419
|
function isColHeader(str) {
|
|
3420
3420
|
return colHeader.test(str);
|
|
3421
3421
|
}
|
|
3422
|
+
function isRowHeader(str) {
|
|
3423
|
+
return rowHeader.test(str);
|
|
3424
|
+
}
|
|
3422
3425
|
/**
|
|
3423
3426
|
* Return true if the given xc is the reference of a single cell,
|
|
3424
3427
|
* without any specified sheet (e.g. A1)
|
|
@@ -3427,11 +3430,18 @@ function isSingleCellReference(xc) {
|
|
|
3427
3430
|
return singleCellReference.test(xc);
|
|
3428
3431
|
}
|
|
3429
3432
|
function splitReference(ref) {
|
|
3433
|
+
if (!ref.includes("!")) {
|
|
3434
|
+
return { xc: ref };
|
|
3435
|
+
}
|
|
3430
3436
|
const parts = ref.split("!");
|
|
3431
3437
|
const xc = parts.pop();
|
|
3432
3438
|
const sheetName = getUnquotedSheetName(parts.join("!")) || undefined;
|
|
3433
3439
|
return { sheetName, xc };
|
|
3434
3440
|
}
|
|
3441
|
+
/** Return a reference SheetName!xc from the given arguments */
|
|
3442
|
+
function getFullReference(sheetName, xc) {
|
|
3443
|
+
return sheetName !== undefined ? `${getCanonicalSheetName(sheetName)}!${xc}` : xc;
|
|
3444
|
+
}
|
|
3435
3445
|
|
|
3436
3446
|
/**
|
|
3437
3447
|
* Convert from a cartesian reference to a Zone
|
|
@@ -4102,18 +4112,10 @@ class RangeImpl {
|
|
|
4102
4112
|
if (isFullCol) {
|
|
4103
4113
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4104
4114
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4105
|
-
if (zone.left === zone.right) {
|
|
4106
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4107
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4108
|
-
}
|
|
4109
4115
|
}
|
|
4110
4116
|
if (isFullRow) {
|
|
4111
4117
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4112
4118
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4113
|
-
if (zone.top === zone.bottom) {
|
|
4114
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4115
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4116
|
-
}
|
|
4117
4119
|
}
|
|
4118
4120
|
return parts;
|
|
4119
4121
|
}
|
|
@@ -4355,7 +4357,7 @@ function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
|
4355
4357
|
function getDefaultCellHeight(ctx, cell, colSize) {
|
|
4356
4358
|
if (!cell || !cell.content)
|
|
4357
4359
|
return DEFAULT_CELL_HEIGHT;
|
|
4358
|
-
const maxWidth = cell.style?.wrapping ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
|
|
4360
|
+
const maxWidth = cell.style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
|
|
4359
4361
|
const numberOfLines = cell.isFormula
|
|
4360
4362
|
? 1
|
|
4361
4363
|
: splitTextToWidth(ctx, cell.content, cell.style, maxWidth).length;
|
|
@@ -4540,14 +4542,14 @@ function drawDecoratedText(context, text, position, underline = false, strikethr
|
|
|
4540
4542
|
switch (context.textBaseline) {
|
|
4541
4543
|
case "top":
|
|
4542
4544
|
underlineY += boxHeight - 2 * strokeWidth;
|
|
4543
|
-
strikeY += boxHeight -
|
|
4545
|
+
strikeY += boxHeight / 2 - strokeWidth;
|
|
4544
4546
|
break;
|
|
4545
4547
|
case "middle":
|
|
4546
4548
|
underlineY += boxHeight / 2 - strokeWidth;
|
|
4547
4549
|
break;
|
|
4548
4550
|
case "alphabetic":
|
|
4549
4551
|
underlineY += 2 * strokeWidth;
|
|
4550
|
-
strikeY -=
|
|
4552
|
+
strikeY -= 3 * strokeWidth;
|
|
4551
4553
|
break;
|
|
4552
4554
|
case "bottom":
|
|
4553
4555
|
underlineY = y;
|
|
@@ -4610,6 +4612,7 @@ function createAction(item) {
|
|
|
4610
4612
|
const children = item.children;
|
|
4611
4613
|
const description = item.description;
|
|
4612
4614
|
const icon = item.icon;
|
|
4615
|
+
const secondaryIcon = item.secondaryIcon;
|
|
4613
4616
|
return {
|
|
4614
4617
|
id: item.id || uuidGenerator$2.uuidv4(),
|
|
4615
4618
|
name: typeof name === "function" ? name : () => name,
|
|
@@ -4628,6 +4631,7 @@ function createAction(item) {
|
|
|
4628
4631
|
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
4629
4632
|
separator: item.separator || false,
|
|
4630
4633
|
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
4634
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
4631
4635
|
description: typeof description === "function" ? description : () => description || "",
|
|
4632
4636
|
textColor: item.textColor,
|
|
4633
4637
|
sequence: item.sequence || 0,
|
|
@@ -6250,10 +6254,6 @@ css /* scss */ `
|
|
|
6250
6254
|
|
|
6251
6255
|
.o-error-tooltip-message {
|
|
6252
6256
|
overflow: hidden;
|
|
6253
|
-
display: -webkit-box; /* Limit to 3 lines */
|
|
6254
|
-
-webkit-line-clamp: 3;
|
|
6255
|
-
line-clamp: 3;
|
|
6256
|
-
-webkit-box-orient: vertical;
|
|
6257
6257
|
}
|
|
6258
6258
|
}
|
|
6259
6259
|
`;
|
|
@@ -6661,6 +6661,9 @@ function keyboardEventToShortcutString(ev, mode = "key") {
|
|
|
6661
6661
|
keyDownString += letterRegex.test(key) ? key.toUpperCase() : key;
|
|
6662
6662
|
return keyDownString;
|
|
6663
6663
|
}
|
|
6664
|
+
function isMacOS() {
|
|
6665
|
+
return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
|
|
6666
|
+
}
|
|
6664
6667
|
|
|
6665
6668
|
/**
|
|
6666
6669
|
* Return the o-spreadsheet element position relative
|
|
@@ -6983,11 +6986,9 @@ css /* scss */ `
|
|
|
6983
6986
|
padding: ${MENU_VERTICAL_PADDING}px 0px;
|
|
6984
6987
|
width: ${MENU_WIDTH}px;
|
|
6985
6988
|
box-sizing: border-box !important;
|
|
6989
|
+
user-select: none;
|
|
6986
6990
|
|
|
6987
6991
|
.o-menu-item {
|
|
6988
|
-
display: flex;
|
|
6989
|
-
justify-content: space-between;
|
|
6990
|
-
align-items: center;
|
|
6991
6992
|
box-sizing: border-box;
|
|
6992
6993
|
height: ${MENU_ITEM_HEIGHT}px;
|
|
6993
6994
|
padding: ${MENU_ITEM_PADDING_VERTICAL}px ${MENU_ITEM_PADDING_HORIZONTAL}px;
|
|
@@ -6998,20 +6999,12 @@ css /* scss */ `
|
|
|
6998
6999
|
min-width: 40%;
|
|
6999
7000
|
}
|
|
7000
7001
|
|
|
7001
|
-
&.o-menu-root {
|
|
7002
|
-
display: flex;
|
|
7003
|
-
justify-content: space-between;
|
|
7004
|
-
}
|
|
7005
|
-
|
|
7006
7002
|
.o-menu-item-icon {
|
|
7007
7003
|
display: inline-block;
|
|
7008
7004
|
margin: 0px 8px 0px 0px;
|
|
7009
7005
|
width: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
7010
7006
|
line-height: ${MENU_ITEM_HEIGHT - 2 * MENU_ITEM_PADDING_VERTICAL}px;
|
|
7011
7007
|
}
|
|
7012
|
-
.o-menu-item-root {
|
|
7013
|
-
width: 10px;
|
|
7014
|
-
}
|
|
7015
7008
|
|
|
7016
7009
|
&:not(.disabled) {
|
|
7017
7010
|
&:hover,
|
|
@@ -7354,7 +7347,7 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
|
7354
7347
|
return result;
|
|
7355
7348
|
}
|
|
7356
7349
|
function tokenizeDebugger(chars) {
|
|
7357
|
-
if (chars.current
|
|
7350
|
+
if (chars.current === "?") {
|
|
7358
7351
|
chars.shift();
|
|
7359
7352
|
return { type: "DEBUGGER", value: "?" };
|
|
7360
7353
|
}
|
|
@@ -7365,7 +7358,7 @@ const misc$1 = {
|
|
|
7365
7358
|
")": "RIGHT_PAREN",
|
|
7366
7359
|
};
|
|
7367
7360
|
function tokenizeMisc(chars) {
|
|
7368
|
-
if (chars.current
|
|
7361
|
+
if (chars.current in misc$1) {
|
|
7369
7362
|
const value = chars.shift();
|
|
7370
7363
|
const type = misc$1[value];
|
|
7371
7364
|
return { type, value };
|
|
@@ -7373,7 +7366,7 @@ function tokenizeMisc(chars) {
|
|
|
7373
7366
|
return null;
|
|
7374
7367
|
}
|
|
7375
7368
|
function tokenizeArgsSeparator(chars, locale) {
|
|
7376
|
-
if (chars.current
|
|
7369
|
+
if (chars.current === locale.formulaArgSeparator) {
|
|
7377
7370
|
const value = chars.shift();
|
|
7378
7371
|
const type = "ARG_SEPARATOR";
|
|
7379
7372
|
return { type, value };
|
|
@@ -7398,14 +7391,13 @@ function tokenizeNumber(chars, locale) {
|
|
|
7398
7391
|
return null;
|
|
7399
7392
|
}
|
|
7400
7393
|
function tokenizeString(chars) {
|
|
7401
|
-
if (chars.current
|
|
7394
|
+
if (chars.current === '"') {
|
|
7402
7395
|
const startChar = chars.shift();
|
|
7403
7396
|
let letters = startChar;
|
|
7404
|
-
while (chars.current()
|
|
7405
|
-
(chars.current() !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7397
|
+
while (chars.current && (chars.current !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7406
7398
|
letters += chars.shift();
|
|
7407
7399
|
}
|
|
7408
|
-
if (chars.current
|
|
7400
|
+
if (chars.current === '"') {
|
|
7409
7401
|
letters += chars.shift();
|
|
7410
7402
|
}
|
|
7411
7403
|
return {
|
|
@@ -7432,14 +7424,14 @@ function tokenizeSymbol(chars) {
|
|
|
7432
7424
|
let result = "";
|
|
7433
7425
|
// there are two main cases to manage: either something which starts with
|
|
7434
7426
|
// a ', like 'Sheet 2'A2, or a word-like element.
|
|
7435
|
-
if (chars.current
|
|
7427
|
+
if (chars.current === "'") {
|
|
7436
7428
|
let lastChar = chars.shift();
|
|
7437
7429
|
result += lastChar;
|
|
7438
|
-
while (chars.current
|
|
7430
|
+
while (chars.current) {
|
|
7439
7431
|
lastChar = chars.shift();
|
|
7440
7432
|
result += lastChar;
|
|
7441
7433
|
if (lastChar === "'") {
|
|
7442
|
-
if (chars.current
|
|
7434
|
+
if (chars.current && chars.current === "'") {
|
|
7443
7435
|
lastChar = chars.shift();
|
|
7444
7436
|
result += lastChar;
|
|
7445
7437
|
}
|
|
@@ -7455,7 +7447,7 @@ function tokenizeSymbol(chars) {
|
|
|
7455
7447
|
};
|
|
7456
7448
|
}
|
|
7457
7449
|
}
|
|
7458
|
-
while (chars.current
|
|
7450
|
+
while (chars.current && separatorRegexp.test(chars.current)) {
|
|
7459
7451
|
result += chars.shift();
|
|
7460
7452
|
}
|
|
7461
7453
|
if (result.length) {
|
|
@@ -7470,14 +7462,14 @@ function tokenizeSymbol(chars) {
|
|
|
7470
7462
|
}
|
|
7471
7463
|
function tokenizeSpace(chars) {
|
|
7472
7464
|
let length = 0;
|
|
7473
|
-
while (chars.current
|
|
7465
|
+
while (chars.current === NEWLINE) {
|
|
7474
7466
|
length++;
|
|
7475
7467
|
chars.shift();
|
|
7476
7468
|
}
|
|
7477
7469
|
if (length) {
|
|
7478
7470
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
7479
7471
|
}
|
|
7480
|
-
while (chars.current
|
|
7472
|
+
while (chars.current === " ") {
|
|
7481
7473
|
length++;
|
|
7482
7474
|
chars.shift();
|
|
7483
7475
|
}
|
|
@@ -7496,17 +7488,20 @@ function tokenizeInvalidRange(chars) {
|
|
|
7496
7488
|
class TokenizingChars {
|
|
7497
7489
|
text;
|
|
7498
7490
|
currentIndex = 0;
|
|
7491
|
+
current;
|
|
7499
7492
|
constructor(text) {
|
|
7500
7493
|
this.text = text;
|
|
7501
|
-
|
|
7502
|
-
current() {
|
|
7503
|
-
return this.text[this.currentIndex];
|
|
7494
|
+
this.current = text[0];
|
|
7504
7495
|
}
|
|
7505
7496
|
shift() {
|
|
7506
|
-
|
|
7497
|
+
const current = this.current;
|
|
7498
|
+
const next = this.text[++this.currentIndex];
|
|
7499
|
+
this.current = next;
|
|
7500
|
+
return current;
|
|
7507
7501
|
}
|
|
7508
7502
|
advanceBy(length) {
|
|
7509
7503
|
this.currentIndex += length;
|
|
7504
|
+
this.current = this.text[this.currentIndex];
|
|
7510
7505
|
}
|
|
7511
7506
|
isOver() {
|
|
7512
7507
|
return this.currentIndex >= this.text.length;
|
|
@@ -11310,7 +11305,7 @@ const EXPAND = {
|
|
|
11310
11305
|
) {
|
|
11311
11306
|
const _array = toMatrix(arg);
|
|
11312
11307
|
const _nbRows = toInteger(rows?.value, this.locale);
|
|
11313
|
-
const _nbColumns = columns !== undefined ? toInteger(columns.value, this.
|
|
11308
|
+
const _nbColumns = columns !== undefined ? toInteger(columns.value, this.locale) : _array.length;
|
|
11314
11309
|
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()));
|
|
11315
11310
|
assert(() => _nbColumns >= _array.length, _t("The columns arguments (%s) must be greater or equal than the number of columns of the array.", _nbColumns.toString()));
|
|
11316
11311
|
return generateMatrix(_nbColumns, _nbRows, (col, row) => col >= _array.length || row >= _array[col].length ? padWith : _array[col][row]);
|
|
@@ -11799,6 +11794,10 @@ var misc = /*#__PURE__*/Object.freeze({
|
|
|
11799
11794
|
FORMAT_LARGE_NUMBER: FORMAT_LARGE_NUMBER
|
|
11800
11795
|
});
|
|
11801
11796
|
|
|
11797
|
+
function sum(values, locale) {
|
|
11798
|
+
return reduceNumbers(values, (acc, a) => acc + a, 0, locale);
|
|
11799
|
+
}
|
|
11800
|
+
|
|
11802
11801
|
const DEFAULT_FACTOR = 1;
|
|
11803
11802
|
const DEFAULT_MODE = 0;
|
|
11804
11803
|
const DEFAULT_PLACES = 0;
|
|
@@ -12750,7 +12749,7 @@ const SUM = {
|
|
|
12750
12749
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
12751
12750
|
},
|
|
12752
12751
|
compute: function (...values) {
|
|
12753
|
-
return
|
|
12752
|
+
return sum(values, this.locale);
|
|
12754
12753
|
},
|
|
12755
12754
|
isExported: true,
|
|
12756
12755
|
};
|
|
@@ -12919,6 +12918,44 @@ function assertSameNumberOfElements(...args) {
|
|
|
12919
12918
|
const dims = args[0].length;
|
|
12920
12919
|
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())));
|
|
12921
12920
|
}
|
|
12921
|
+
function average(values, locale) {
|
|
12922
|
+
let count = 0;
|
|
12923
|
+
const sum = reduceNumbers(values, (acc, a) => {
|
|
12924
|
+
count += 1;
|
|
12925
|
+
return acc + a;
|
|
12926
|
+
}, 0, locale);
|
|
12927
|
+
assert(() => count !== 0, _t("Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error."));
|
|
12928
|
+
return sum / count;
|
|
12929
|
+
}
|
|
12930
|
+
function countNumbers(values, locale) {
|
|
12931
|
+
let count = 0;
|
|
12932
|
+
for (let n of values) {
|
|
12933
|
+
if (isMatrix(n)) {
|
|
12934
|
+
for (let i of n) {
|
|
12935
|
+
for (let j of i) {
|
|
12936
|
+
if (typeof j === "number") {
|
|
12937
|
+
count += 1;
|
|
12938
|
+
}
|
|
12939
|
+
}
|
|
12940
|
+
}
|
|
12941
|
+
}
|
|
12942
|
+
else if (typeof n !== "string" || isNumber(n, locale) || parseDateTime(n, locale)) {
|
|
12943
|
+
count += 1;
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12946
|
+
return count;
|
|
12947
|
+
}
|
|
12948
|
+
function countAny(values) {
|
|
12949
|
+
return reduceAny(values, (acc, a) => (a !== undefined && a !== null ? acc + 1 : acc), 0);
|
|
12950
|
+
}
|
|
12951
|
+
function max(values, locale) {
|
|
12952
|
+
const result = reduceNumbers(values, (acc, a) => (acc < a ? a : acc), -Infinity, locale);
|
|
12953
|
+
return result === -Infinity ? 0 : result;
|
|
12954
|
+
}
|
|
12955
|
+
function min(values, locale) {
|
|
12956
|
+
const result = reduceNumbers(values, (acc, a) => (a < acc ? a : acc), Infinity, locale);
|
|
12957
|
+
return result === Infinity ? 0 : result;
|
|
12958
|
+
}
|
|
12922
12959
|
|
|
12923
12960
|
function filterAndFlatData(dataY, dataX) {
|
|
12924
12961
|
const _flatDataY = [];
|
|
@@ -13189,13 +13226,7 @@ const AVERAGE = {
|
|
|
13189
13226
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13190
13227
|
},
|
|
13191
13228
|
compute: function (...values) {
|
|
13192
|
-
|
|
13193
|
-
const sum = reduceNumbers(values, (acc, a) => {
|
|
13194
|
-
count += 1;
|
|
13195
|
-
return acc + a;
|
|
13196
|
-
}, 0, this.locale);
|
|
13197
|
-
assert(() => count !== 0, _t("Evaluation of function [[FUNCTION_NAME]] caused a divide by zero error."));
|
|
13198
|
-
return sum / count;
|
|
13229
|
+
return average(values, this.locale);
|
|
13199
13230
|
},
|
|
13200
13231
|
isExported: true,
|
|
13201
13232
|
};
|
|
@@ -13353,24 +13384,7 @@ const COUNT = {
|
|
|
13353
13384
|
],
|
|
13354
13385
|
returns: ["NUMBER"],
|
|
13355
13386
|
compute: function (...values) {
|
|
13356
|
-
|
|
13357
|
-
for (let n of values) {
|
|
13358
|
-
if (isMatrix(n)) {
|
|
13359
|
-
for (let i of n) {
|
|
13360
|
-
for (let j of i) {
|
|
13361
|
-
if (typeof j === "number") {
|
|
13362
|
-
count += 1;
|
|
13363
|
-
}
|
|
13364
|
-
}
|
|
13365
|
-
}
|
|
13366
|
-
}
|
|
13367
|
-
else if (typeof n !== "string" ||
|
|
13368
|
-
isNumber(n, this.locale) ||
|
|
13369
|
-
parseDateTime(n, this.locale)) {
|
|
13370
|
-
count += 1;
|
|
13371
|
-
}
|
|
13372
|
-
}
|
|
13373
|
-
return count;
|
|
13387
|
+
return countNumbers(values, this.locale);
|
|
13374
13388
|
},
|
|
13375
13389
|
isExported: true,
|
|
13376
13390
|
};
|
|
@@ -13385,7 +13399,7 @@ const COUNTA = {
|
|
|
13385
13399
|
],
|
|
13386
13400
|
returns: ["NUMBER"],
|
|
13387
13401
|
compute: function (...values) {
|
|
13388
|
-
return
|
|
13402
|
+
return countAny(values);
|
|
13389
13403
|
},
|
|
13390
13404
|
isExported: true,
|
|
13391
13405
|
};
|
|
@@ -13615,8 +13629,7 @@ const MAX = {
|
|
|
13615
13629
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13616
13630
|
},
|
|
13617
13631
|
compute: function (...values) {
|
|
13618
|
-
|
|
13619
|
-
return result === -Infinity ? 0 : result;
|
|
13632
|
+
return max(values, this.locale);
|
|
13620
13633
|
},
|
|
13621
13634
|
isExported: true,
|
|
13622
13635
|
};
|
|
@@ -13703,8 +13716,7 @@ const MIN = {
|
|
|
13703
13716
|
return isMatrix(value1) ? value1[0][0]?.format : value1?.format;
|
|
13704
13717
|
},
|
|
13705
13718
|
compute: function (...values) {
|
|
13706
|
-
|
|
13707
|
-
return result === Infinity ? 0 : result;
|
|
13719
|
+
return min(values, this.locale);
|
|
13708
13720
|
},
|
|
13709
13721
|
isExported: true,
|
|
13710
13722
|
};
|
|
@@ -17875,6 +17887,153 @@ var financial = /*#__PURE__*/Object.freeze({
|
|
|
17875
17887
|
YIELDMAT: YIELDMAT
|
|
17876
17888
|
});
|
|
17877
17889
|
|
|
17890
|
+
/**
|
|
17891
|
+
* Change the reference types inside the given token, if the token represent a range or a cell
|
|
17892
|
+
*
|
|
17893
|
+
* Eg. :
|
|
17894
|
+
* A1 => $A$1 => A$1 => $A1 => A1
|
|
17895
|
+
* A1:$B$1 => $A$1:B$1 => A$1:$B1 => $A1:B1 => A1:$B$1
|
|
17896
|
+
*/
|
|
17897
|
+
function loopThroughReferenceType(token) {
|
|
17898
|
+
if (token.type !== "REFERENCE")
|
|
17899
|
+
return token;
|
|
17900
|
+
const { xc, sheetName } = splitReference(token.value);
|
|
17901
|
+
const [left, right] = xc.split(":");
|
|
17902
|
+
const updatedLeft = getTokenNextReferenceType(left);
|
|
17903
|
+
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
17904
|
+
return { ...token, value: getFullReference(sheetName, updatedLeft + updatedRight) };
|
|
17905
|
+
}
|
|
17906
|
+
/**
|
|
17907
|
+
* Get a new token with a changed type of reference from the given cell token symbol.
|
|
17908
|
+
* Undefined behavior if given a token other than a cell or if the Xc contains a sheet reference
|
|
17909
|
+
*
|
|
17910
|
+
* A1 => $A$1 => A$1 => $A1 => A1
|
|
17911
|
+
*/
|
|
17912
|
+
function getTokenNextReferenceType(xc) {
|
|
17913
|
+
switch (getReferenceType(xc)) {
|
|
17914
|
+
case "none":
|
|
17915
|
+
xc = setXcToFixedReferenceType(xc, "colrow");
|
|
17916
|
+
break;
|
|
17917
|
+
case "colrow":
|
|
17918
|
+
xc = setXcToFixedReferenceType(xc, "row");
|
|
17919
|
+
break;
|
|
17920
|
+
case "row":
|
|
17921
|
+
xc = setXcToFixedReferenceType(xc, "col");
|
|
17922
|
+
break;
|
|
17923
|
+
case "col":
|
|
17924
|
+
xc = setXcToFixedReferenceType(xc, "none");
|
|
17925
|
+
break;
|
|
17926
|
+
}
|
|
17927
|
+
return xc;
|
|
17928
|
+
}
|
|
17929
|
+
/**
|
|
17930
|
+
* Returns the given XC with the given reference type. The XC string should not contain a sheet name.
|
|
17931
|
+
*/
|
|
17932
|
+
function setXcToFixedReferenceType(xc, referenceType) {
|
|
17933
|
+
if (xc.includes("!")) {
|
|
17934
|
+
throw new Error("The given XC should not contain a sheet name");
|
|
17935
|
+
}
|
|
17936
|
+
xc = xc.replace(/\$/g, "");
|
|
17937
|
+
let indexOfNumber;
|
|
17938
|
+
switch (referenceType) {
|
|
17939
|
+
case "col":
|
|
17940
|
+
return "$" + xc;
|
|
17941
|
+
case "row":
|
|
17942
|
+
indexOfNumber = xc.search(/[0-9]/);
|
|
17943
|
+
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
17944
|
+
case "colrow":
|
|
17945
|
+
indexOfNumber = xc.search(/[0-9]/);
|
|
17946
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
17947
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
17948
|
+
return "$" + xc;
|
|
17949
|
+
}
|
|
17950
|
+
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
17951
|
+
return "$" + xc;
|
|
17952
|
+
case "none":
|
|
17953
|
+
return xc;
|
|
17954
|
+
}
|
|
17955
|
+
}
|
|
17956
|
+
/**
|
|
17957
|
+
* Return the type of reference used in the given XC of a cell.
|
|
17958
|
+
* Undefined behavior if the XC have a sheet reference
|
|
17959
|
+
*/
|
|
17960
|
+
function getReferenceType(xcCell) {
|
|
17961
|
+
if (isColAndRowFixed(xcCell)) {
|
|
17962
|
+
return "colrow";
|
|
17963
|
+
}
|
|
17964
|
+
else if (isColFixed(xcCell)) {
|
|
17965
|
+
return "col";
|
|
17966
|
+
}
|
|
17967
|
+
else if (isRowFixed(xcCell)) {
|
|
17968
|
+
return "row";
|
|
17969
|
+
}
|
|
17970
|
+
return "none";
|
|
17971
|
+
}
|
|
17972
|
+
function isColFixed(xc) {
|
|
17973
|
+
return xc.startsWith("$");
|
|
17974
|
+
}
|
|
17975
|
+
function isRowFixed(xc) {
|
|
17976
|
+
return xc.includes("$", 1);
|
|
17977
|
+
}
|
|
17978
|
+
function isColAndRowFixed(xc) {
|
|
17979
|
+
return xc.startsWith("$") && xc.length > 1 && xc.slice(1).includes("$");
|
|
17980
|
+
}
|
|
17981
|
+
|
|
17982
|
+
// -----------------------------------------------------------------------------
|
|
17983
|
+
// CELL
|
|
17984
|
+
// -----------------------------------------------------------------------------
|
|
17985
|
+
// NOTE: missing from Excel: "color", "filename", "parentheses", "prefix", "protect" and "width"
|
|
17986
|
+
const CELL_INFO_TYPES = ["address", "col", "contents", "format", "row", "type"];
|
|
17987
|
+
const CELL = {
|
|
17988
|
+
description: _t("Gets information about a cell."),
|
|
17989
|
+
args: [
|
|
17990
|
+
arg("info_type (string)", _t("The type of information requested. Can be one of %s", CELL_INFO_TYPES.join(", "))),
|
|
17991
|
+
arg("reference (meta)", _t("The reference to the cell.")),
|
|
17992
|
+
],
|
|
17993
|
+
returns: ["ANY"],
|
|
17994
|
+
compute: function (info, reference) {
|
|
17995
|
+
const _info = toString(info).toLowerCase();
|
|
17996
|
+
assert(() => CELL_INFO_TYPES.includes(_info), _t("The info_type should be one of %s.", CELL_INFO_TYPES.join(", ")));
|
|
17997
|
+
const sheetId = this.__originSheetId;
|
|
17998
|
+
const topLeftReference = reference.includes(":") ? reference.split(":")[0] : reference;
|
|
17999
|
+
let { sheetName, xc } = splitReference(topLeftReference);
|
|
18000
|
+
// only put the sheet name if the referenced range is in another sheet than the cell the formula is on
|
|
18001
|
+
sheetName = sheetName === this.getters.getSheetName(sheetId) ? undefined : sheetName;
|
|
18002
|
+
const fixedRef = getFullReference(sheetName, setXcToFixedReferenceType(xc, "colrow"));
|
|
18003
|
+
const range = this.getters.getRangeFromSheetXC(sheetId, fixedRef);
|
|
18004
|
+
switch (_info) {
|
|
18005
|
+
case "address":
|
|
18006
|
+
return this.getters.getRangeString(range, sheetId);
|
|
18007
|
+
case "col":
|
|
18008
|
+
return range.zone.left + 1;
|
|
18009
|
+
case "contents": {
|
|
18010
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18011
|
+
return this.getters.getEvaluatedCell(position).value;
|
|
18012
|
+
}
|
|
18013
|
+
case "format": {
|
|
18014
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18015
|
+
return this.getters.getEvaluatedCell(position).format || "";
|
|
18016
|
+
}
|
|
18017
|
+
case "row":
|
|
18018
|
+
return range.zone.top + 1;
|
|
18019
|
+
case "type": {
|
|
18020
|
+
const position = { sheetId: range.sheetId, col: range.zone.left, row: range.zone.top };
|
|
18021
|
+
const type = this.getters.getEvaluatedCell(position).type;
|
|
18022
|
+
if (type === CellValueType.empty) {
|
|
18023
|
+
return "b"; // blank
|
|
18024
|
+
}
|
|
18025
|
+
else if (type === CellValueType.text) {
|
|
18026
|
+
return "l"; // label
|
|
18027
|
+
}
|
|
18028
|
+
else {
|
|
18029
|
+
return "v"; // value
|
|
18030
|
+
}
|
|
18031
|
+
}
|
|
18032
|
+
}
|
|
18033
|
+
return "";
|
|
18034
|
+
},
|
|
18035
|
+
isExported: true,
|
|
18036
|
+
};
|
|
17878
18037
|
// -----------------------------------------------------------------------------
|
|
17879
18038
|
// ISERR
|
|
17880
18039
|
// -----------------------------------------------------------------------------
|
|
@@ -18030,6 +18189,7 @@ const NA = {
|
|
|
18030
18189
|
|
|
18031
18190
|
var info = /*#__PURE__*/Object.freeze({
|
|
18032
18191
|
__proto__: null,
|
|
18192
|
+
CELL: CELL,
|
|
18033
18193
|
ISBLANK: ISBLANK,
|
|
18034
18194
|
ISERR: ISERR,
|
|
18035
18195
|
ISERROR: ISERROR,
|
|
@@ -18321,7 +18481,7 @@ const ADDRESS = {
|
|
|
18321
18481
|
cellReference = rowPart + colPart;
|
|
18322
18482
|
}
|
|
18323
18483
|
if (sheet !== undefined) {
|
|
18324
|
-
return
|
|
18484
|
+
return getFullReference(toString(sheet), cellReference);
|
|
18325
18485
|
}
|
|
18326
18486
|
return cellReference;
|
|
18327
18487
|
},
|
|
@@ -18337,7 +18497,7 @@ const COLUMN = {
|
|
|
18337
18497
|
],
|
|
18338
18498
|
returns: ["NUMBER"],
|
|
18339
18499
|
compute: function (cellReference) {
|
|
18340
|
-
const _cellReference = cellReference || this.__originCellXC
|
|
18500
|
+
const _cellReference = cellReference || this.__originCellXC();
|
|
18341
18501
|
assert(() => !!_cellReference, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
|
|
18342
18502
|
const zone = toZone(_cellReference);
|
|
18343
18503
|
return zone.left + 1;
|
|
@@ -18504,7 +18664,7 @@ const ROW = {
|
|
|
18504
18664
|
],
|
|
18505
18665
|
returns: ["NUMBER"],
|
|
18506
18666
|
compute: function (cellReference) {
|
|
18507
|
-
cellReference = cellReference || this.__originCellXC
|
|
18667
|
+
cellReference = cellReference || this.__originCellXC();
|
|
18508
18668
|
assert(() => !!cellReference, "In this context, the function [[FUNCTION_NAME]] needs to have a cell or range in parameter.");
|
|
18509
18669
|
const zone = toZone(cellReference);
|
|
18510
18670
|
return zone.top + 1;
|
|
@@ -23856,31 +24016,65 @@ css /* scss */ `
|
|
|
23856
24016
|
`;
|
|
23857
24017
|
class FindAndReplacePanel extends Component {
|
|
23858
24018
|
static template = "o-spreadsheet-FindAndReplacePanel";
|
|
23859
|
-
|
|
24019
|
+
static components = { SelectionInput };
|
|
23860
24020
|
debounceTimeoutId;
|
|
23861
|
-
|
|
24021
|
+
initialShowFormulaState = false;
|
|
24022
|
+
dataRange = "";
|
|
23862
24023
|
searchInput = useRef("searchInput");
|
|
24024
|
+
replaceInput = useRef("replaceInput");
|
|
23863
24025
|
get hasSearchResult() {
|
|
23864
24026
|
return this.env.model.getters.getCurrentSelectedMatchIndex() !== null;
|
|
23865
24027
|
}
|
|
23866
24028
|
get pendingSearch() {
|
|
23867
24029
|
return this.debounceTimeoutId !== undefined;
|
|
23868
24030
|
}
|
|
24031
|
+
get searchOptions() {
|
|
24032
|
+
return this.env.model.getters.getSearchOptions();
|
|
24033
|
+
}
|
|
24034
|
+
get toSearch() {
|
|
24035
|
+
return this.searchInput.el?.value || "";
|
|
24036
|
+
}
|
|
24037
|
+
get toReplace() {
|
|
24038
|
+
return this.replaceInput.el?.value || "";
|
|
24039
|
+
}
|
|
24040
|
+
get allSheetsMatchesCount() {
|
|
24041
|
+
return _t("%s in all sheets", this.env.model.getters.getAllSheetMatchesCount());
|
|
24042
|
+
}
|
|
24043
|
+
get currentSheetMatchesCount() {
|
|
24044
|
+
return _t("%(matches)s in sheet %(sheetName)s", {
|
|
24045
|
+
matches: this.env.model.getters.getActiveSheetMatchesCount(),
|
|
24046
|
+
sheetName: this.env.model.getters.getSheetName(this.env.model.getters.getActiveSheetId()),
|
|
24047
|
+
});
|
|
24048
|
+
}
|
|
24049
|
+
get specificRangeMatchesCount() {
|
|
24050
|
+
const range = this.searchOptions.specificRange;
|
|
24051
|
+
if (!range) {
|
|
24052
|
+
return "";
|
|
24053
|
+
}
|
|
24054
|
+
const { _sheetId, _zone } = range;
|
|
24055
|
+
return _t("%(matches)s in range %(range)s of sheet %(sheetName)s", {
|
|
24056
|
+
matches: this.env.model.getters.getSpecificRangeMatchesCount().toString(),
|
|
24057
|
+
range: zoneToXc(_zone),
|
|
24058
|
+
sheetName: this.env.model.getters.getSheetName(_sheetId),
|
|
24059
|
+
});
|
|
24060
|
+
}
|
|
23869
24061
|
setup() {
|
|
23870
|
-
this.
|
|
24062
|
+
this.initialShowFormulaState = this.env.model.getters.shouldShowFormulas();
|
|
23871
24063
|
onMounted(() => this.searchInput.el?.focus());
|
|
23872
24064
|
onWillUnmount(() => {
|
|
23873
24065
|
clearTimeout(this.debounceTimeoutId);
|
|
23874
24066
|
this.env.model.dispatch("CLEAR_SEARCH");
|
|
23875
|
-
this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.
|
|
24067
|
+
this.env.model.dispatch("SET_FORMULA_VISIBILITY", { show: this.initialShowFormulaState });
|
|
23876
24068
|
});
|
|
23877
24069
|
useEffect(() => {
|
|
23878
|
-
|
|
23879
|
-
this.searchFormulas
|
|
24070
|
+
const showFormula = this.env.model.getters.shouldShowFormulas();
|
|
24071
|
+
this.updateSearch({ searchFormulas: showFormula });
|
|
23880
24072
|
}, () => [this.env.model.getters.shouldShowFormulas()]);
|
|
23881
24073
|
}
|
|
23882
|
-
|
|
23883
|
-
this.
|
|
24074
|
+
onFocusSearch() {
|
|
24075
|
+
this.updateDataRange();
|
|
24076
|
+
}
|
|
24077
|
+
onInput() {
|
|
23884
24078
|
this.debouncedUpdateSearch();
|
|
23885
24079
|
}
|
|
23886
24080
|
onKeydownSearch(ev) {
|
|
@@ -23897,11 +24091,36 @@ class FindAndReplacePanel extends Component {
|
|
|
23897
24091
|
this.replace();
|
|
23898
24092
|
}
|
|
23899
24093
|
}
|
|
23900
|
-
searchFormulas() {
|
|
24094
|
+
searchFormulas(ev) {
|
|
24095
|
+
const showFormula = ev.target.checked;
|
|
23901
24096
|
this.env.model.dispatch("SET_FORMULA_VISIBILITY", {
|
|
23902
|
-
show:
|
|
24097
|
+
show: showFormula,
|
|
23903
24098
|
});
|
|
23904
|
-
this.updateSearch();
|
|
24099
|
+
this.updateSearch({ searchFormulas: showFormula });
|
|
24100
|
+
}
|
|
24101
|
+
searchExactMatch(ev) {
|
|
24102
|
+
const exactMatch = ev.target.checked;
|
|
24103
|
+
this.updateSearch({ exactMatch });
|
|
24104
|
+
}
|
|
24105
|
+
searchMatchCase(ev) {
|
|
24106
|
+
const matchCase = ev.target.checked;
|
|
24107
|
+
this.updateSearch({ matchCase });
|
|
24108
|
+
}
|
|
24109
|
+
changeSearchScope(ev) {
|
|
24110
|
+
const searchScope = ev.target.value;
|
|
24111
|
+
this.updateSearch({ searchScope });
|
|
24112
|
+
}
|
|
24113
|
+
onSearchRangeChanged(ranges) {
|
|
24114
|
+
this.dataRange = ranges[0];
|
|
24115
|
+
}
|
|
24116
|
+
updateDataRange() {
|
|
24117
|
+
if (!this.dataRange) {
|
|
24118
|
+
return;
|
|
24119
|
+
}
|
|
24120
|
+
if (this.searchOptions.searchScope === "specificRange") {
|
|
24121
|
+
const specificRange = this.env.model.getters.getRangeFromSheetXC(this.env.model.getters.getActiveSheetId(), this.dataRange).rangeData;
|
|
24122
|
+
this.updateSearch({ specificRange });
|
|
24123
|
+
}
|
|
23905
24124
|
}
|
|
23906
24125
|
onSelectPreviousCell() {
|
|
23907
24126
|
this.env.model.dispatch("SELECT_SEARCH_PREVIOUS_MATCH");
|
|
@@ -23909,10 +24128,14 @@ class FindAndReplacePanel extends Component {
|
|
|
23909
24128
|
onSelectNextCell() {
|
|
23910
24129
|
this.env.model.dispatch("SELECT_SEARCH_NEXT_MATCH");
|
|
23911
24130
|
}
|
|
23912
|
-
updateSearch() {
|
|
24131
|
+
updateSearch(updateSearchOptions) {
|
|
24132
|
+
const searchOptions = {
|
|
24133
|
+
...this.env.model.getters.getSearchOptions(),
|
|
24134
|
+
...updateSearchOptions,
|
|
24135
|
+
};
|
|
23913
24136
|
this.env.model.dispatch("UPDATE_SEARCH", {
|
|
23914
|
-
toSearch: this.
|
|
23915
|
-
searchOptions
|
|
24137
|
+
toSearch: this.toSearch,
|
|
24138
|
+
searchOptions,
|
|
23916
24139
|
});
|
|
23917
24140
|
}
|
|
23918
24141
|
debouncedUpdateSearch() {
|
|
@@ -23924,28 +24147,14 @@ class FindAndReplacePanel extends Component {
|
|
|
23924
24147
|
}
|
|
23925
24148
|
replace() {
|
|
23926
24149
|
this.env.model.dispatch("REPLACE_SEARCH", {
|
|
23927
|
-
replaceWith: this.
|
|
24150
|
+
replaceWith: this.toReplace,
|
|
23928
24151
|
});
|
|
23929
24152
|
}
|
|
23930
24153
|
replaceAll() {
|
|
23931
24154
|
this.env.model.dispatch("REPLACE_ALL_SEARCH", {
|
|
23932
|
-
replaceWith: this.
|
|
24155
|
+
replaceWith: this.toReplace,
|
|
23933
24156
|
});
|
|
23934
24157
|
}
|
|
23935
|
-
// ---------------------------------------------------------------------------
|
|
23936
|
-
// Private
|
|
23937
|
-
// ---------------------------------------------------------------------------
|
|
23938
|
-
initialState() {
|
|
23939
|
-
return {
|
|
23940
|
-
toSearch: "",
|
|
23941
|
-
replaceWith: "",
|
|
23942
|
-
searchOptions: {
|
|
23943
|
-
matchCase: false,
|
|
23944
|
-
exactMatch: false,
|
|
23945
|
-
searchFormulas: false,
|
|
23946
|
-
},
|
|
23947
|
-
};
|
|
23948
|
-
}
|
|
23949
24158
|
}
|
|
23950
24159
|
FindAndReplacePanel.props = {
|
|
23951
24160
|
onCloseSidePanel: Function,
|
|
@@ -27091,7 +27300,7 @@ class GridComposer extends Component {
|
|
|
27091
27300
|
get cellReference() {
|
|
27092
27301
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
27093
27302
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
27094
|
-
return
|
|
27303
|
+
return getFullReference(prefixSheet ? this.env.model.getters.getSheetName(sheetId) : undefined, toXC(col, row));
|
|
27095
27304
|
}
|
|
27096
27305
|
get cellReferenceStyle() {
|
|
27097
27306
|
const { x: left, y: top } = this.rect;
|
|
@@ -28308,6 +28517,7 @@ class AbstractResizer extends Component {
|
|
|
28308
28517
|
draggerShadowThickness: 0,
|
|
28309
28518
|
delta: 0,
|
|
28310
28519
|
base: 0,
|
|
28520
|
+
position: "before",
|
|
28311
28521
|
});
|
|
28312
28522
|
_computeHandleDisplay(ev) {
|
|
28313
28523
|
const position = this._getEvOffset(ev);
|
|
@@ -28432,11 +28642,13 @@ class AbstractResizer extends Component {
|
|
|
28432
28642
|
this.state.draggerLinePosition = dimensions.start;
|
|
28433
28643
|
this.state.draggerShadowPosition = dimensions.start;
|
|
28434
28644
|
this.state.base = elementIndex;
|
|
28645
|
+
this.state.position = "before";
|
|
28435
28646
|
}
|
|
28436
28647
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
28437
28648
|
this.state.draggerLinePosition = dimensions.end;
|
|
28438
28649
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
28439
|
-
this.state.base = elementIndex
|
|
28650
|
+
this.state.base = elementIndex;
|
|
28651
|
+
this.state.position = "after";
|
|
28440
28652
|
}
|
|
28441
28653
|
else {
|
|
28442
28654
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -28534,22 +28746,15 @@ css /* scss */ `
|
|
|
28534
28746
|
height: 10000px;
|
|
28535
28747
|
background-color: ${SELECTION_BORDER_COLOR};
|
|
28536
28748
|
}
|
|
28537
|
-
.o-unhide {
|
|
28538
|
-
width:
|
|
28539
|
-
|
|
28540
|
-
|
|
28541
|
-
overflow: hidden;
|
|
28542
|
-
border-radius: 2px;
|
|
28543
|
-
top: calc(${HEADER_HEIGHT}px / 2 - ${UNHIDE_ICON_EDGE_LENGTH}px / 2);
|
|
28749
|
+
.o-unhide-buttons {
|
|
28750
|
+
width: fit-content;
|
|
28751
|
+
gap: 5px;
|
|
28752
|
+
transform: translate(-50%, 0);
|
|
28544
28753
|
}
|
|
28545
28754
|
.o-unhide:hover {
|
|
28546
28755
|
z-index: ${ComponentsImportance.Grid + 1};
|
|
28547
28756
|
background-color: lightgrey;
|
|
28548
28757
|
}
|
|
28549
|
-
.o-unhide > svg {
|
|
28550
|
-
position: relative;
|
|
28551
|
-
top: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28552
|
-
}
|
|
28553
28758
|
}
|
|
28554
28759
|
`;
|
|
28555
28760
|
AbstractResizer.props = {
|
|
@@ -28618,6 +28823,7 @@ class ColResizer extends AbstractResizer {
|
|
|
28618
28823
|
dimension: "COL",
|
|
28619
28824
|
base: this.state.base,
|
|
28620
28825
|
elements,
|
|
28826
|
+
position: this.state.position,
|
|
28621
28827
|
});
|
|
28622
28828
|
if (!result.isSuccessful && result.reasons.includes("WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */)) {
|
|
28623
28829
|
this.env.raiseError(MergeErrorMessage);
|
|
@@ -28659,8 +28865,8 @@ class ColResizer extends AbstractResizer {
|
|
|
28659
28865
|
dimension: "COL",
|
|
28660
28866
|
});
|
|
28661
28867
|
}
|
|
28662
|
-
|
|
28663
|
-
return this._getDimensionsInViewport(hiddenIndex).start;
|
|
28868
|
+
getUnhideButtonStyle(hiddenIndex) {
|
|
28869
|
+
return cssPropertiesToCss({ left: this._getDimensionsInViewport(hiddenIndex).start + "px" });
|
|
28664
28870
|
}
|
|
28665
28871
|
}
|
|
28666
28872
|
css /* scss */ `
|
|
@@ -28706,18 +28912,9 @@ css /* scss */ `
|
|
|
28706
28912
|
height: 1px;
|
|
28707
28913
|
background-color: ${SELECTION_BORDER_COLOR};
|
|
28708
28914
|
}
|
|
28709
|
-
.o-unhide {
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
position: absolute;
|
|
28713
|
-
overflow: hidden;
|
|
28714
|
-
border-radius: 2px;
|
|
28715
|
-
left: calc(${HEADER_WIDTH}px - ${UNHIDE_ICON_EDGE_LENGTH}px - 2px);
|
|
28716
|
-
}
|
|
28717
|
-
.o-unhide > svg {
|
|
28718
|
-
position: relative;
|
|
28719
|
-
left: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28720
|
-
top: calc(${UNHIDE_ICON_EDGE_LENGTH}px / 2 - ${ICON_EDGE_LENGTH}px / 2);
|
|
28915
|
+
.o-unhide-buttons {
|
|
28916
|
+
height: fit-content;
|
|
28917
|
+
transform: translate(0, -50%);
|
|
28721
28918
|
}
|
|
28722
28919
|
.o-unhide:hover {
|
|
28723
28920
|
z-index: ${ComponentsImportance.Grid + 1};
|
|
@@ -28791,6 +28988,7 @@ class RowResizer extends AbstractResizer {
|
|
|
28791
28988
|
dimension: "ROW",
|
|
28792
28989
|
base: this.state.base,
|
|
28793
28990
|
elements,
|
|
28991
|
+
position: this.state.position,
|
|
28794
28992
|
});
|
|
28795
28993
|
if (!result.isSuccessful && result.reasons.includes("WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */)) {
|
|
28796
28994
|
this.env.raiseError(MergeErrorMessage);
|
|
@@ -28832,8 +29030,8 @@ class RowResizer extends AbstractResizer {
|
|
|
28832
29030
|
elements: hiddenElements,
|
|
28833
29031
|
});
|
|
28834
29032
|
}
|
|
28835
|
-
|
|
28836
|
-
return this._getDimensionsInViewport(hiddenIndex).start;
|
|
29033
|
+
getUnhideButtonStyle(hiddenIndex) {
|
|
29034
|
+
return cssPropertiesToCss({ top: this._getDimensionsInViewport(hiddenIndex).start + "px" });
|
|
28837
29035
|
}
|
|
28838
29036
|
}
|
|
28839
29037
|
css /* scss */ `
|
|
@@ -28898,8 +29096,8 @@ function useWheelHandler(handler) {
|
|
|
28898
29096
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
28899
29097
|
}
|
|
28900
29098
|
const onMouseWheel = (ev) => {
|
|
28901
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
28902
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
29099
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
29100
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
28903
29101
|
handler(deltaX, deltaY);
|
|
28904
29102
|
};
|
|
28905
29103
|
return onMouseWheel;
|
|
@@ -29340,7 +29538,6 @@ class Grid extends Component {
|
|
|
29340
29538
|
onMounted(() => this.focus());
|
|
29341
29539
|
this.props.exposeFocus(() => this.focus());
|
|
29342
29540
|
useGridDrawing("canvas", this.env.model, () => this.env.model.getters.getSheetViewDimensionWithHeaders());
|
|
29343
|
-
useEffect(() => this.focus(), () => [this.env.model.getters.getActiveSheetId()]);
|
|
29344
29541
|
this.onMouseWheel = useWheelHandler((deltaX, deltaY) => {
|
|
29345
29542
|
this.moveCanvas(deltaX, deltaY);
|
|
29346
29543
|
this.hoveredCell.col = undefined;
|
|
@@ -29777,6 +29974,7 @@ class Grid extends Component {
|
|
|
29777
29974
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
29778
29975
|
const target = this.env.model.getters.getSelectedZones();
|
|
29779
29976
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
29977
|
+
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
29780
29978
|
if (clipboardString === content) {
|
|
29781
29979
|
// the paste actually comes from o-spreadsheet itself
|
|
29782
29980
|
interactivePaste(this.env, target);
|
|
@@ -29784,7 +29982,7 @@ class Grid extends Component {
|
|
|
29784
29982
|
else {
|
|
29785
29983
|
interactivePasteFromOS(this.env, target, content);
|
|
29786
29984
|
}
|
|
29787
|
-
if (
|
|
29985
|
+
if (isCutOperation) {
|
|
29788
29986
|
await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
29789
29987
|
}
|
|
29790
29988
|
}
|
|
@@ -31397,12 +31595,6 @@ function convertChartData(chartData) {
|
|
|
31397
31595
|
}
|
|
31398
31596
|
function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
31399
31597
|
let { sheetName, xc } = splitReference(range);
|
|
31400
|
-
if (sheetName) {
|
|
31401
|
-
sheetName = getCanonicalSheetName(sheetName) + "!";
|
|
31402
|
-
}
|
|
31403
|
-
else {
|
|
31404
|
-
sheetName = "";
|
|
31405
|
-
}
|
|
31406
31598
|
let zone = toUnboundedZone(xc);
|
|
31407
31599
|
if (dataSetsHaveTitle && zone.bottom !== undefined && zone.right !== undefined) {
|
|
31408
31600
|
const height = zone.bottom - zone.top + 1;
|
|
@@ -31415,7 +31607,7 @@ function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
|
31415
31607
|
}
|
|
31416
31608
|
}
|
|
31417
31609
|
const dataXC = zoneToXc(zone);
|
|
31418
|
-
return sheetName
|
|
31610
|
+
return getFullReference(sheetName, dataXC);
|
|
31419
31611
|
}
|
|
31420
31612
|
|
|
31421
31613
|
/**
|
|
@@ -33342,7 +33534,7 @@ const machine = {
|
|
|
33342
33534
|
SPACE: goTo(State.RightRef),
|
|
33343
33535
|
NUMBER: goTo(State.Found),
|
|
33344
33536
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
33345
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
33537
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
33346
33538
|
},
|
|
33347
33539
|
[State.RightColumnRef]: {
|
|
33348
33540
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -33353,6 +33545,7 @@ const machine = {
|
|
|
33353
33545
|
SPACE: goTo(State.RightRowRef),
|
|
33354
33546
|
NUMBER: goTo(State.Found),
|
|
33355
33547
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
33548
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
33356
33549
|
},
|
|
33357
33550
|
[State.Found]: {},
|
|
33358
33551
|
};
|
|
@@ -34078,6 +34271,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34078
34271
|
// ---------------------------------------------------------------------------
|
|
34079
34272
|
// Command Handling
|
|
34080
34273
|
// ---------------------------------------------------------------------------
|
|
34274
|
+
allowDispatch(cmd) {
|
|
34275
|
+
switch (cmd.type) {
|
|
34276
|
+
case "SET_BORDER":
|
|
34277
|
+
return this.checkBordersUnchanged(cmd);
|
|
34278
|
+
default:
|
|
34279
|
+
return "Success" /* CommandResult.Success */;
|
|
34280
|
+
}
|
|
34281
|
+
}
|
|
34081
34282
|
handle(cmd) {
|
|
34082
34283
|
switch (cmd.type) {
|
|
34083
34284
|
case "ADD_MERGE":
|
|
@@ -34497,6 +34698,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34497
34698
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
34498
34699
|
}
|
|
34499
34700
|
}
|
|
34701
|
+
checkBordersUnchanged(cmd) {
|
|
34702
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
34703
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
34704
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
34705
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
34706
|
+
}
|
|
34707
|
+
return "Success" /* CommandResult.Success */;
|
|
34708
|
+
}
|
|
34500
34709
|
// ---------------------------------------------------------------------------
|
|
34501
34710
|
// Import/Export
|
|
34502
34711
|
// ---------------------------------------------------------------------------
|
|
@@ -35323,7 +35532,6 @@ class CellPlugin extends CorePlugin {
|
|
|
35323
35532
|
static getters = [
|
|
35324
35533
|
"zoneToXC",
|
|
35325
35534
|
"getCells",
|
|
35326
|
-
"getFormulaCellContent",
|
|
35327
35535
|
"getTranslatedCellFormula",
|
|
35328
35536
|
"getCellStyle",
|
|
35329
35537
|
"getCellById",
|
|
@@ -35352,8 +35560,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35352
35560
|
allowDispatch(cmd) {
|
|
35353
35561
|
switch (cmd.type) {
|
|
35354
35562
|
case "UPDATE_CELL":
|
|
35563
|
+
return this.checkCellOutOfSheet(cmd);
|
|
35355
35564
|
case "CLEAR_CELL":
|
|
35356
|
-
return this.
|
|
35565
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
35357
35566
|
default:
|
|
35358
35567
|
return "Success" /* CommandResult.Success */;
|
|
35359
35568
|
}
|
|
@@ -35522,24 +35731,18 @@ class CellPlugin extends CorePlugin {
|
|
|
35522
35731
|
*/
|
|
35523
35732
|
getCellById(cellId) {
|
|
35524
35733
|
// this must be as fast as possible
|
|
35525
|
-
|
|
35526
|
-
|
|
35527
|
-
|
|
35528
|
-
if (cell) {
|
|
35529
|
-
return cell;
|
|
35530
|
-
}
|
|
35531
|
-
}
|
|
35532
|
-
return undefined;
|
|
35734
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35735
|
+
const sheet = this.cells[position.sheetId];
|
|
35736
|
+
return sheet[cellId];
|
|
35533
35737
|
}
|
|
35534
35738
|
/*
|
|
35535
35739
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
35536
35740
|
*/
|
|
35537
35741
|
getFormulaCellContent(sheetId, compiledFormula, dependencies) {
|
|
35538
|
-
const ranges = dependencies || compiledFormula.dependencies;
|
|
35539
35742
|
let rangeIndex = 0;
|
|
35540
35743
|
return concat(compiledFormula.tokens.map((token) => {
|
|
35541
35744
|
if (token.type === "REFERENCE") {
|
|
35542
|
-
const range =
|
|
35745
|
+
const range = dependencies[rangeIndex++];
|
|
35543
35746
|
return this.getters.getRangeString(range, sheetId);
|
|
35544
35747
|
}
|
|
35545
35748
|
return token.value;
|
|
@@ -35760,13 +35963,23 @@ class CellPlugin extends CorePlugin {
|
|
|
35760
35963
|
},
|
|
35761
35964
|
};
|
|
35762
35965
|
}
|
|
35763
|
-
checkCellOutOfSheet(
|
|
35966
|
+
checkCellOutOfSheet(cmd) {
|
|
35967
|
+
const { sheetId, col, row } = cmd;
|
|
35764
35968
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
35765
35969
|
if (!sheet)
|
|
35766
35970
|
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
35767
35971
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
35768
35972
|
return isInside(col, row, sheetZone) ? "Success" /* CommandResult.Success */ : "TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */;
|
|
35769
35973
|
}
|
|
35974
|
+
checkUselessClearCell(cmd) {
|
|
35975
|
+
const cell = this.getters.getCell(cmd);
|
|
35976
|
+
if (!cell)
|
|
35977
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35978
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
35979
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35980
|
+
}
|
|
35981
|
+
return "Success" /* CommandResult.Success */;
|
|
35982
|
+
}
|
|
35770
35983
|
}
|
|
35771
35984
|
class FormulaCellWithDependencies {
|
|
35772
35985
|
id;
|
|
@@ -36456,6 +36669,9 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
36456
36669
|
return this.rules[sheetId].find((rule) => rule.id === id);
|
|
36457
36670
|
}
|
|
36458
36671
|
getValidationRuleForCell({ sheetId, col, row }) {
|
|
36672
|
+
if (!this.rules[sheetId]) {
|
|
36673
|
+
return undefined;
|
|
36674
|
+
}
|
|
36459
36675
|
for (const rule of this.rules[sheetId]) {
|
|
36460
36676
|
for (const range of rule.ranges) {
|
|
36461
36677
|
if (isInside(col, row, range.zone)) {
|
|
@@ -37309,7 +37525,16 @@ class HeaderVisibilityPlugin extends CorePlugin {
|
|
|
37309
37525
|
return consecutiveIndexes;
|
|
37310
37526
|
}
|
|
37311
37527
|
getAllVisibleHeaders(sheetId, dimension) {
|
|
37312
|
-
|
|
37528
|
+
const headers = range(0, this.getters.getNumberHeaders(sheetId, dimension));
|
|
37529
|
+
const foldedHeaders = [];
|
|
37530
|
+
this.getters.getHeaderGroups(sheetId, dimension).forEach((group) => {
|
|
37531
|
+
if (group.isFolded) {
|
|
37532
|
+
foldedHeaders.push(...range(group.start, group.end + 1));
|
|
37533
|
+
}
|
|
37534
|
+
});
|
|
37535
|
+
return headers.filter((i) => {
|
|
37536
|
+
return !this.hiddenHeaders[sheetId][dimension][i] && !foldedHeaders.includes(i);
|
|
37537
|
+
});
|
|
37313
37538
|
}
|
|
37314
37539
|
import(data) {
|
|
37315
37540
|
for (let sheet of data.sheets) {
|
|
@@ -37628,7 +37853,7 @@ class MergePlugin extends CorePlugin {
|
|
|
37628
37853
|
const rangeString = this.getters.getRangeString(expandedRange, forSheetId);
|
|
37629
37854
|
if (this.isSingleCellOrMerge(rangeImpl.sheetId, rangeImpl.zone)) {
|
|
37630
37855
|
const { sheetName, xc } = splitReference(rangeString);
|
|
37631
|
-
return
|
|
37856
|
+
return getFullReference(sheetName, xc.split(":")[0]);
|
|
37632
37857
|
}
|
|
37633
37858
|
return rangeString;
|
|
37634
37859
|
}
|
|
@@ -39053,10 +39278,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
39053
39278
|
// begin with the end.
|
|
39054
39279
|
rows.sort((a, b) => b - a);
|
|
39055
39280
|
for (let group of groupConsecutive(rows)) {
|
|
39281
|
+
// indexes are sorted in the descending order
|
|
39282
|
+
const from = group[group.length - 1];
|
|
39283
|
+
const to = group[0];
|
|
39056
39284
|
// Move the cells.
|
|
39057
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
39058
|
-
// Effectively delete the
|
|
39059
|
-
|
|
39285
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
39286
|
+
// Effectively delete the rows
|
|
39287
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
39060
39288
|
}
|
|
39061
39289
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
39062
39290
|
if (count) {
|
|
@@ -39078,8 +39306,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
39078
39306
|
this.addEmptyRows(sheet, quantity);
|
|
39079
39307
|
// Move the cells.
|
|
39080
39308
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
39081
|
-
// Recompute the left-right/top-bottom.
|
|
39082
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
39083
39309
|
if (index < sheet.panes.ySplit) {
|
|
39084
39310
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
39085
39311
|
}
|
|
@@ -39180,35 +39406,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
39180
39406
|
}
|
|
39181
39407
|
}
|
|
39182
39408
|
}
|
|
39183
|
-
updateRowsStructureOnDeletion(
|
|
39409
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
39184
39410
|
const rows = [];
|
|
39185
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39411
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
39186
39412
|
for (let i in sheet.rows) {
|
|
39187
|
-
|
|
39413
|
+
const row = Number(i);
|
|
39414
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
39188
39415
|
continue;
|
|
39189
39416
|
}
|
|
39190
39417
|
rows.push({
|
|
39191
|
-
cells: cellsQueue.
|
|
39418
|
+
cells: cellsQueue.pop(),
|
|
39192
39419
|
});
|
|
39193
39420
|
}
|
|
39194
39421
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39195
39422
|
}
|
|
39196
|
-
/**
|
|
39197
|
-
* Update the rows of the sheet after an addition:
|
|
39198
|
-
* - Rename the rows
|
|
39199
|
-
*
|
|
39200
|
-
* @param sheet Sheet on which the deletion occurs
|
|
39201
|
-
* @param addedRow Index of the added row
|
|
39202
|
-
* @param rowsToAdd Number of the rows to add
|
|
39203
|
-
*/
|
|
39204
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
39205
|
-
const rows = [];
|
|
39206
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39207
|
-
sheet.rows.forEach(() => rows.push({
|
|
39208
|
-
cells: cellsQueue.shift(),
|
|
39209
|
-
}));
|
|
39210
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39211
|
-
}
|
|
39212
39423
|
/**
|
|
39213
39424
|
* Add empty rows at the end of the rows
|
|
39214
39425
|
*
|
|
@@ -39735,6 +39946,7 @@ class CompilationParametersBuilder {
|
|
|
39735
39946
|
getters;
|
|
39736
39947
|
computeCell;
|
|
39737
39948
|
evalContext;
|
|
39949
|
+
rangeCache = {};
|
|
39738
39950
|
constructor(context, getters, computeCell) {
|
|
39739
39951
|
this.getters = getters;
|
|
39740
39952
|
this.computeCell = computeCell;
|
|
@@ -39757,7 +39969,8 @@ class CompilationParametersBuilder {
|
|
|
39757
39969
|
refFn(range, isMeta, functionName, paramNumber) {
|
|
39758
39970
|
if (isMeta) {
|
|
39759
39971
|
// Use zoneToXc of zone instead of getRangeString to avoid sending unbounded ranges
|
|
39760
|
-
|
|
39972
|
+
const sheetName = this.getters.getSheetName(range.sheetId);
|
|
39973
|
+
return { value: getFullReference(sheetName, zoneToXc(range.zone)) };
|
|
39761
39974
|
}
|
|
39762
39975
|
if (!isZoneValid(range.zone)) {
|
|
39763
39976
|
throw new InvalidReferenceError();
|
|
@@ -39782,10 +39995,13 @@ class CompilationParametersBuilder {
|
|
|
39782
39995
|
if (evaluatedCell === undefined) {
|
|
39783
39996
|
return { value: null, format: this.getters.getCell(position)?.format };
|
|
39784
39997
|
}
|
|
39998
|
+
if (evaluatedCell.type === CellValueType.error) {
|
|
39999
|
+
throw evaluatedCell.error;
|
|
40000
|
+
}
|
|
39785
40001
|
return evaluatedCell;
|
|
39786
40002
|
}
|
|
39787
40003
|
getEvaluatedCellIfNotEmpty(position) {
|
|
39788
|
-
const evaluatedCell = this.
|
|
40004
|
+
const evaluatedCell = this.computeCell(position);
|
|
39789
40005
|
if (evaluatedCell.type === CellValueType.empty) {
|
|
39790
40006
|
const cell = this.getters.getCell(position);
|
|
39791
40007
|
if (!cell || (!cell.isFormula && cell.content === "")) {
|
|
@@ -39794,13 +40010,6 @@ class CompilationParametersBuilder {
|
|
|
39794
40010
|
}
|
|
39795
40011
|
return evaluatedCell;
|
|
39796
40012
|
}
|
|
39797
|
-
getEvaluatedCell(position) {
|
|
39798
|
-
const evaluatedCell = this.computeCell(position);
|
|
39799
|
-
if (evaluatedCell.type === CellValueType.error) {
|
|
39800
|
-
throw evaluatedCell.error;
|
|
39801
|
-
}
|
|
39802
|
-
return evaluatedCell;
|
|
39803
|
-
}
|
|
39804
40013
|
/**
|
|
39805
40014
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
39806
40015
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -39820,17 +40029,33 @@ class CompilationParametersBuilder {
|
|
|
39820
40029
|
if (!_zone) {
|
|
39821
40030
|
return [[]];
|
|
39822
40031
|
}
|
|
40032
|
+
const { top, left, bottom, right } = zone;
|
|
40033
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
40034
|
+
if (cacheKey in this.rangeCache) {
|
|
40035
|
+
const result = this.rangeCache[cacheKey];
|
|
40036
|
+
if (result instanceof EvaluationError) {
|
|
40037
|
+
throw result;
|
|
40038
|
+
}
|
|
40039
|
+
return result;
|
|
40040
|
+
}
|
|
39823
40041
|
const height = _zone.bottom - _zone.top + 1;
|
|
39824
40042
|
const width = _zone.right - _zone.left + 1;
|
|
39825
|
-
const matrix = Array
|
|
40043
|
+
const matrix = new Array(width);
|
|
39826
40044
|
// Performance issue: nested loop is faster than a map here
|
|
39827
40045
|
for (let col = _zone.left; col <= _zone.right; col++) {
|
|
40046
|
+
const colIndex = col - _zone.left;
|
|
40047
|
+
matrix[colIndex] = new Array(height);
|
|
39828
40048
|
for (let row = _zone.top; row <= _zone.bottom; row++) {
|
|
39829
|
-
const
|
|
40049
|
+
const evaluatedCell = this.getEvaluatedCellIfNotEmpty({ sheetId, col, row });
|
|
40050
|
+
if (evaluatedCell?.type === CellValueType.error) {
|
|
40051
|
+
this.rangeCache[cacheKey] = evaluatedCell.error;
|
|
40052
|
+
throw evaluatedCell.error;
|
|
40053
|
+
}
|
|
39830
40054
|
const rowIndex = row - _zone.top;
|
|
39831
40055
|
matrix[colIndex][rowIndex] = this.readCell({ sheetId, col, row });
|
|
39832
40056
|
}
|
|
39833
40057
|
}
|
|
40058
|
+
this.rangeCache[cacheKey] = matrix;
|
|
39834
40059
|
return matrix;
|
|
39835
40060
|
}
|
|
39836
40061
|
}
|
|
@@ -40036,6 +40261,7 @@ class Evaluator {
|
|
|
40036
40261
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
40037
40262
|
}
|
|
40038
40263
|
updateCompilationParameters() {
|
|
40264
|
+
// rebuild the compilation parameters (with a clean cache)
|
|
40039
40265
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40040
40266
|
}
|
|
40041
40267
|
evaluateCells(positions) {
|
|
@@ -40079,6 +40305,16 @@ class Evaluator {
|
|
|
40079
40305
|
this.evaluatedCells = new Map();
|
|
40080
40306
|
this.evaluate(this.getAllCells());
|
|
40081
40307
|
}
|
|
40308
|
+
evaluateFormula(sheetId, formulaString) {
|
|
40309
|
+
const compiledFormula = compile(formulaString);
|
|
40310
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40311
|
+
this.updateCompilationParameters();
|
|
40312
|
+
const result = updateEvalContextAndExecute({ ...compiledFormula, dependencies: ranges }, this.compilationParams, sheetId);
|
|
40313
|
+
if (isMatrix(result)) {
|
|
40314
|
+
return matrixMap(result, (cell) => cell.value);
|
|
40315
|
+
}
|
|
40316
|
+
return result.value;
|
|
40317
|
+
}
|
|
40082
40318
|
getAllCells() {
|
|
40083
40319
|
const positionIds = new JetSet();
|
|
40084
40320
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
@@ -40105,6 +40341,7 @@ class Evaluator {
|
|
|
40105
40341
|
this.nextPositionsToUpdate = cells;
|
|
40106
40342
|
let currentIteration = 0;
|
|
40107
40343
|
while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
|
|
40344
|
+
this.updateCompilationParameters();
|
|
40108
40345
|
const positionIds = Array.from(this.nextPositionsToUpdate);
|
|
40109
40346
|
this.nextPositionsToUpdate.clear();
|
|
40110
40347
|
for (let i = 0; i < positionIds.length; ++i) {
|
|
@@ -40128,7 +40365,8 @@ class Evaluator {
|
|
|
40128
40365
|
if (!this.blockedArrayFormulas.has(positionId)) {
|
|
40129
40366
|
this.invalidateSpreading(positionId);
|
|
40130
40367
|
}
|
|
40131
|
-
const
|
|
40368
|
+
const cellPosition = this.decodePosition(positionId);
|
|
40369
|
+
const cell = this.getters.getCell(cellPosition);
|
|
40132
40370
|
if (cell === undefined) {
|
|
40133
40371
|
return createEvaluatedCell("", { locale: this.getters.getLocale() });
|
|
40134
40372
|
}
|
|
@@ -40139,7 +40377,7 @@ class Evaluator {
|
|
|
40139
40377
|
}
|
|
40140
40378
|
this.cellsBeingComputed.add(cellId);
|
|
40141
40379
|
return cell.isFormula
|
|
40142
|
-
? this.computeFormulaCell(cell)
|
|
40380
|
+
? this.computeFormulaCell(cellPosition.sheetId, cell)
|
|
40143
40381
|
: evaluateLiteral(cell.content, { format: cell.format, locale: this.getters.getLocale() });
|
|
40144
40382
|
}
|
|
40145
40383
|
catch (e) {
|
|
@@ -40165,14 +40403,9 @@ class Evaluator {
|
|
|
40165
40403
|
e.message = e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled);
|
|
40166
40404
|
return errorCell(e);
|
|
40167
40405
|
}
|
|
40168
|
-
computeFormulaCell(cellData) {
|
|
40406
|
+
computeFormulaCell(sheetId, cellData) {
|
|
40169
40407
|
const cellId = cellData.id;
|
|
40170
|
-
this.compilationParams
|
|
40171
|
-
// compute the value lazily for performance reasons
|
|
40172
|
-
const position = this.compilationParams[2].getters.getCellPosition(cellId);
|
|
40173
|
-
return toXC(position.col, position.row);
|
|
40174
|
-
};
|
|
40175
|
-
const formulaReturn = cellData.compiledFormula.execute(cellData.compiledFormula.dependencies, ...this.compilationParams);
|
|
40408
|
+
const formulaReturn = updateEvalContextAndExecute(cellData.compiledFormula, this.compilationParams, sheetId, cellId);
|
|
40176
40409
|
if (!isMatrix(formulaReturn)) {
|
|
40177
40410
|
return createEvaluatedCell(formulaReturn.value, {
|
|
40178
40411
|
format: cellData.format || formulaReturn.format,
|
|
@@ -40374,6 +40607,18 @@ class PositionBitsEncoder {
|
|
|
40374
40607
|
return sheetId;
|
|
40375
40608
|
}
|
|
40376
40609
|
}
|
|
40610
|
+
function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
|
|
40611
|
+
compilationParams[2].__originCellXC = lazy(() => {
|
|
40612
|
+
if (!cellId) {
|
|
40613
|
+
return undefined;
|
|
40614
|
+
}
|
|
40615
|
+
// compute the value lazily for performance reasons
|
|
40616
|
+
const position = compilationParams[2].getters.getCellPosition(cellId);
|
|
40617
|
+
return toXC(position.col, position.row);
|
|
40618
|
+
});
|
|
40619
|
+
compilationParams[2].__originSheetId = sheetId;
|
|
40620
|
+
return compiledFormula.execute(compiledFormula.dependencies, ...compilationParams);
|
|
40621
|
+
}
|
|
40377
40622
|
|
|
40378
40623
|
//#region
|
|
40379
40624
|
// ---------------------------------------------------------------------------
|
|
@@ -40468,7 +40713,6 @@ class PositionBitsEncoder {
|
|
|
40468
40713
|
// of other cells depending on it, at the next iteration.
|
|
40469
40714
|
//#endregion
|
|
40470
40715
|
class EvaluationPlugin extends UIPlugin {
|
|
40471
|
-
config;
|
|
40472
40716
|
static getters = [
|
|
40473
40717
|
"evaluateFormula",
|
|
40474
40718
|
"getCorrespondingFormulaCell",
|
|
@@ -40479,15 +40723,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40479
40723
|
"getEvaluatedCells",
|
|
40480
40724
|
"getEvaluatedCellsInZone",
|
|
40481
40725
|
"getSpreadPositionsOf",
|
|
40726
|
+
"getArrayFormulaSpreadingOn",
|
|
40482
40727
|
];
|
|
40483
40728
|
shouldRebuildDependenciesGraph = true;
|
|
40484
40729
|
evaluator;
|
|
40485
|
-
compilationParams;
|
|
40486
40730
|
positionsToUpdate = [];
|
|
40487
40731
|
constructor(config) {
|
|
40488
40732
|
super(config);
|
|
40489
|
-
this.config = config;
|
|
40490
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40491
40733
|
this.evaluator = new Evaluator(config.custom, this.getters);
|
|
40492
40734
|
}
|
|
40493
40735
|
// ---------------------------------------------------------------------------
|
|
@@ -40512,10 +40754,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40512
40754
|
case "EVALUATE_CELLS":
|
|
40513
40755
|
this.evaluator.evaluateAllCells();
|
|
40514
40756
|
break;
|
|
40515
|
-
case "UPDATE_LOCALE":
|
|
40516
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40517
|
-
this.evaluator.updateCompilationParameters();
|
|
40518
|
-
break;
|
|
40519
40757
|
}
|
|
40520
40758
|
}
|
|
40521
40759
|
finalize() {
|
|
@@ -40533,16 +40771,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40533
40771
|
// Getters
|
|
40534
40772
|
// ---------------------------------------------------------------------------
|
|
40535
40773
|
evaluateFormula(sheetId, formulaString) {
|
|
40536
|
-
|
|
40537
|
-
const ranges = [];
|
|
40538
|
-
for (let xc of compiledFormula.dependencies) {
|
|
40539
|
-
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40540
|
-
}
|
|
40541
|
-
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40542
|
-
if (isMatrix(array)) {
|
|
40543
|
-
return array.map((col) => col.map((row) => row.value));
|
|
40544
|
-
}
|
|
40545
|
-
return array.value;
|
|
40774
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
40546
40775
|
}
|
|
40547
40776
|
/**
|
|
40548
40777
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -40591,6 +40820,9 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40591
40820
|
getSpreadPositionsOf(position) {
|
|
40592
40821
|
return this.evaluator.getSpreadPositionsOf(position);
|
|
40593
40822
|
}
|
|
40823
|
+
getArrayFormulaSpreadingOn(position) {
|
|
40824
|
+
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
40825
|
+
}
|
|
40594
40826
|
// ---------------------------------------------------------------------------
|
|
40595
40827
|
// Export
|
|
40596
40828
|
// ---------------------------------------------------------------------------
|
|
@@ -40634,7 +40866,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40634
40866
|
else if (cell && cell.content) {
|
|
40635
40867
|
return undefined;
|
|
40636
40868
|
}
|
|
40637
|
-
const spreadingFormulaPosition = this.
|
|
40869
|
+
const spreadingFormulaPosition = this.getArrayFormulaSpreadingOn(position);
|
|
40638
40870
|
if (spreadingFormulaPosition === undefined) {
|
|
40639
40871
|
return undefined;
|
|
40640
40872
|
}
|
|
@@ -40644,9 +40876,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40644
40876
|
}
|
|
40645
40877
|
return undefined;
|
|
40646
40878
|
}
|
|
40647
|
-
getCompilationParameters() {
|
|
40648
|
-
return buildCompilationParameters(this.config.custom, this.getters, (position) => this.evaluator.getEvaluatedCell(position));
|
|
40649
|
-
}
|
|
40650
40879
|
}
|
|
40651
40880
|
function isBadExpression(tokens) {
|
|
40652
40881
|
try {
|
|
@@ -40923,7 +41152,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
40923
41152
|
// ---------------------------------------------------------------------------
|
|
40924
41153
|
handle(cmd) {
|
|
40925
41154
|
if (invalidateCFEvaluationCommands.has(cmd.type) ||
|
|
40926
|
-
(cmd.type === "UPDATE_CELL" && "content" in cmd)) {
|
|
41155
|
+
(cmd.type === "UPDATE_CELL" && ("content" in cmd || "format" in cmd))) {
|
|
40927
41156
|
this.isStale = true;
|
|
40928
41157
|
}
|
|
40929
41158
|
}
|
|
@@ -41249,7 +41478,7 @@ class EvaluationDataValidationPlugin extends UIPlugin {
|
|
|
41249
41478
|
handle(cmd) {
|
|
41250
41479
|
if (invalidateEvaluationCommands.has(cmd.type) ||
|
|
41251
41480
|
cmd.type === "EVALUATE_CELLS" ||
|
|
41252
|
-
(cmd.type === "UPDATE_CELL" && "content" in cmd)) {
|
|
41481
|
+
(cmd.type === "UPDATE_CELL" && ("content" in cmd || "format" in cmd))) {
|
|
41253
41482
|
this.validationResults = {};
|
|
41254
41483
|
return;
|
|
41255
41484
|
}
|
|
@@ -41787,19 +42016,21 @@ class AutofillPlugin extends UIPlugin {
|
|
|
41787
42016
|
let col = zone.left;
|
|
41788
42017
|
let row = zone.bottom;
|
|
41789
42018
|
if (col > 0) {
|
|
41790
|
-
let
|
|
41791
|
-
while (
|
|
42019
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
42020
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
42021
|
+
this.getters.getCell(leftPosition)?.content) {
|
|
41792
42022
|
row += 1;
|
|
41793
|
-
|
|
42023
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
41794
42024
|
}
|
|
41795
42025
|
}
|
|
41796
42026
|
if (row === zone.bottom) {
|
|
41797
42027
|
col = zone.right;
|
|
41798
42028
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
41799
|
-
let
|
|
41800
|
-
while (
|
|
42029
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
42030
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
42031
|
+
this.getters.getCell(rightPosition)?.content) {
|
|
41801
42032
|
row += 1;
|
|
41802
|
-
|
|
42033
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
41803
42034
|
}
|
|
41804
42035
|
}
|
|
41805
42036
|
}
|
|
@@ -42791,6 +43022,7 @@ class Session extends EventBus {
|
|
|
42791
43022
|
isReplayingInitialRevisions = false;
|
|
42792
43023
|
processedRevisions = new Set();
|
|
42793
43024
|
uuidGenerator = new UuidGenerator();
|
|
43025
|
+
lastLocalOperation;
|
|
42794
43026
|
/**
|
|
42795
43027
|
* Manages the collaboration between multiple users on the same spreadsheet.
|
|
42796
43028
|
* It can forward local state changes to other users to ensure they all eventually
|
|
@@ -42823,6 +43055,11 @@ class Session extends EventBus {
|
|
|
42823
43055
|
return;
|
|
42824
43056
|
const revision = new Revision(this.uuidGenerator.uuidv4(), this.clientId, commands, rootCommand, changes, Date.now());
|
|
42825
43057
|
this.revisions.append(revision.id, revision);
|
|
43058
|
+
// REQUEST_REDO just repeats the last operation, the
|
|
43059
|
+
// last operation is still the same and should not change.
|
|
43060
|
+
if (rootCommand.type !== "REQUEST_REDO") {
|
|
43061
|
+
this.lastLocalOperation = revision;
|
|
43062
|
+
}
|
|
42826
43063
|
this.trigger("new-local-state-update", { id: revision.id });
|
|
42827
43064
|
this.sendUpdateMessage({
|
|
42828
43065
|
type: "REMOTE_REVISION",
|
|
@@ -42919,19 +43156,10 @@ class Session extends EventBus {
|
|
|
42919
43156
|
return this.pendingMessages.length === 0;
|
|
42920
43157
|
}
|
|
42921
43158
|
/**
|
|
42922
|
-
* Get the last local revision
|
|
43159
|
+
* Get the last local revision
|
|
42923
43160
|
* */
|
|
42924
|
-
getLastLocalNonEmptyRevision(
|
|
42925
|
-
|
|
42926
|
-
for (const rev of revisions) {
|
|
42927
|
-
if (rev.rootCommand === "SNAPSHOT")
|
|
42928
|
-
return undefined;
|
|
42929
|
-
if (!rev.rootCommand || rev.rootCommand === "REMOTE")
|
|
42930
|
-
continue;
|
|
42931
|
-
if (!ignoredRootCommands.includes(rev.rootCommand?.type) && rev.commands.length)
|
|
42932
|
-
return rev;
|
|
42933
|
-
}
|
|
42934
|
-
return undefined;
|
|
43161
|
+
getLastLocalNonEmptyRevision() {
|
|
43162
|
+
return this.lastLocalOperation;
|
|
42935
43163
|
}
|
|
42936
43164
|
_move(position) {
|
|
42937
43165
|
// this method is debounced and might be called after the client
|
|
@@ -42991,7 +43219,7 @@ class Session extends EventBus {
|
|
|
42991
43219
|
break;
|
|
42992
43220
|
case "REMOTE_REVISION":
|
|
42993
43221
|
const { clientId, commands, timestamp } = message;
|
|
42994
|
-
const revision = new Revision(message.nextRevisionId, clientId, commands,
|
|
43222
|
+
const revision = new Revision(message.nextRevisionId, clientId, commands, undefined, undefined, timestamp);
|
|
42995
43223
|
if (revision.clientId !== this.clientId) {
|
|
42996
43224
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
42997
43225
|
const pendingCommands = this.pendingMessages
|
|
@@ -43004,10 +43232,11 @@ class Session extends EventBus {
|
|
|
43004
43232
|
}
|
|
43005
43233
|
break;
|
|
43006
43234
|
case "SNAPSHOT_CREATED": {
|
|
43007
|
-
const revision = new Revision(message.nextRevisionId, "server", [],
|
|
43235
|
+
const revision = new Revision(message.nextRevisionId, "server", [], undefined, undefined, Date.now());
|
|
43008
43236
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
43009
43237
|
this.dropPendingHistoryMessages();
|
|
43010
43238
|
this.trigger("snapshot");
|
|
43239
|
+
this.lastLocalOperation = undefined;
|
|
43011
43240
|
break;
|
|
43012
43241
|
}
|
|
43013
43242
|
}
|
|
@@ -43345,11 +43574,26 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43345
43574
|
let cellsInRow = [];
|
|
43346
43575
|
for (let col of columnsIndex) {
|
|
43347
43576
|
const position = { col, row, sheetId };
|
|
43577
|
+
const spreader = getters.getArrayFormulaSpreadingOn(position);
|
|
43578
|
+
let cell = getters.getCell(position);
|
|
43579
|
+
const evaluatedCell = getters.getEvaluatedCell(position);
|
|
43580
|
+
if (spreader) {
|
|
43581
|
+
const isSpreaderCopied = rowsIndex.includes(spreader.row) && columnsIndex.includes(spreader.col);
|
|
43582
|
+
const content = isSpreaderCopied
|
|
43583
|
+
? ""
|
|
43584
|
+
: formatValue(evaluatedCell.value, { locale: getters.getLocale() });
|
|
43585
|
+
cell = {
|
|
43586
|
+
id: cell?.id || "",
|
|
43587
|
+
style: cell?.style,
|
|
43588
|
+
format: evaluatedCell.format,
|
|
43589
|
+
content,
|
|
43590
|
+
isFormula: false,
|
|
43591
|
+
};
|
|
43592
|
+
}
|
|
43348
43593
|
cellsInRow.push({
|
|
43349
|
-
cell
|
|
43350
|
-
style: getters.getCellComputedStyle(position),
|
|
43351
|
-
evaluatedCell: getters.getEvaluatedCell(position),
|
|
43594
|
+
cell,
|
|
43352
43595
|
border: getters.getCellBorder(position) || undefined,
|
|
43596
|
+
evaluatedCell,
|
|
43353
43597
|
position,
|
|
43354
43598
|
});
|
|
43355
43599
|
}
|
|
@@ -43471,13 +43715,6 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43471
43715
|
});
|
|
43472
43716
|
}
|
|
43473
43717
|
this.pasteCopiedTables(target);
|
|
43474
|
-
this.cells.forEach((row) => {
|
|
43475
|
-
row.forEach((c) => {
|
|
43476
|
-
if (c.cell) {
|
|
43477
|
-
c.cell = undefined;
|
|
43478
|
-
}
|
|
43479
|
-
});
|
|
43480
|
-
});
|
|
43481
43718
|
}
|
|
43482
43719
|
/**
|
|
43483
43720
|
* The clipped zone is copied as many times as it fits in the target.
|
|
@@ -43551,7 +43788,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43551
43788
|
clearClippedZones() {
|
|
43552
43789
|
for (const row of this.cells) {
|
|
43553
43790
|
for (const cell of row) {
|
|
43554
|
-
if (cell
|
|
43791
|
+
if (cell?.cell) {
|
|
43555
43792
|
this.dispatch("CLEAR_CELL", cell.position);
|
|
43556
43793
|
}
|
|
43557
43794
|
}
|
|
@@ -43577,6 +43814,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43577
43814
|
const rowCells = this.cells[r];
|
|
43578
43815
|
for (let c = 0; c < width; c++) {
|
|
43579
43816
|
const origin = rowCells[c];
|
|
43817
|
+
if (!origin) {
|
|
43818
|
+
continue;
|
|
43819
|
+
}
|
|
43580
43820
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
43581
43821
|
// TODO: refactor this part. the "Paste merge" action is also executed with
|
|
43582
43822
|
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
@@ -43600,53 +43840,42 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43600
43840
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43601
43841
|
const { sheetId, col, row } = target;
|
|
43602
43842
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43603
|
-
if (clipboardOption?.pasteOption
|
|
43604
|
-
const
|
|
43605
|
-
const
|
|
43606
|
-
|
|
43607
|
-
|
|
43608
|
-
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43609
|
-
left: targetBorders?.left || originBorders?.left,
|
|
43610
|
-
right: targetBorders?.right || originBorders?.right,
|
|
43611
|
-
};
|
|
43612
|
-
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43843
|
+
if (clipboardOption?.pasteOption === "onlyValue") {
|
|
43844
|
+
const locale = this.getters.getLocale();
|
|
43845
|
+
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43846
|
+
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
43847
|
+
return;
|
|
43613
43848
|
}
|
|
43614
|
-
|
|
43615
|
-
|
|
43616
|
-
|
|
43617
|
-
|
|
43618
|
-
|
|
43619
|
-
|
|
43620
|
-
|
|
43621
|
-
|
|
43622
|
-
|
|
43623
|
-
|
|
43624
|
-
|
|
43625
|
-
|
|
43626
|
-
|
|
43627
|
-
|
|
43628
|
-
}
|
|
43629
|
-
|
|
43630
|
-
|
|
43631
|
-
|
|
43632
|
-
|
|
43849
|
+
const targetBorders = this.getters.getCellBorder(target);
|
|
43850
|
+
const originBorders = origin.border;
|
|
43851
|
+
const border = {
|
|
43852
|
+
top: targetBorders?.top || originBorders?.top,
|
|
43853
|
+
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43854
|
+
left: targetBorders?.left || originBorders?.left,
|
|
43855
|
+
right: targetBorders?.right || originBorders?.right,
|
|
43856
|
+
};
|
|
43857
|
+
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43858
|
+
if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43859
|
+
this.dispatch("UPDATE_CELL", {
|
|
43860
|
+
...target,
|
|
43861
|
+
style: origin.cell?.style ?? null,
|
|
43862
|
+
format: origin.cell?.format ?? origin.evaluatedCell.format ?? targetCell.format,
|
|
43863
|
+
});
|
|
43864
|
+
return;
|
|
43865
|
+
}
|
|
43866
|
+
const content = origin.cell && origin.cell.isFormula && operation === "COPY"
|
|
43867
|
+
? this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula)
|
|
43868
|
+
: origin.cell?.content;
|
|
43869
|
+
if (content !== "" || origin.cell?.format || origin.cell?.style) {
|
|
43633
43870
|
this.dispatch("UPDATE_CELL", {
|
|
43634
43871
|
...target,
|
|
43635
43872
|
content,
|
|
43636
|
-
style: origin.cell
|
|
43637
|
-
format: origin.cell
|
|
43873
|
+
style: origin.cell?.style || null,
|
|
43874
|
+
format: origin.cell?.format,
|
|
43638
43875
|
});
|
|
43639
43876
|
}
|
|
43640
43877
|
else if (targetCell) {
|
|
43641
|
-
|
|
43642
|
-
this.dispatch("UPDATE_CELL", { ...target, content: "" });
|
|
43643
|
-
}
|
|
43644
|
-
else if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43645
|
-
this.dispatch("UPDATE_CELL", { ...target, style: null, format: "" });
|
|
43646
|
-
}
|
|
43647
|
-
else {
|
|
43648
|
-
this.dispatch("CLEAR_CELL", target);
|
|
43649
|
-
}
|
|
43878
|
+
this.dispatch("CLEAR_CELL", target);
|
|
43650
43879
|
}
|
|
43651
43880
|
}
|
|
43652
43881
|
/**
|
|
@@ -43708,22 +43937,28 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43708
43937
|
return (this.cells
|
|
43709
43938
|
.map((cells) => {
|
|
43710
43939
|
return cells
|
|
43711
|
-
.map((c) => this.getters.shouldShowFormulas() && c
|
|
43940
|
+
.map((c) => this.getters.shouldShowFormulas() && c?.cell?.isFormula
|
|
43712
43941
|
? c.cell?.content || ""
|
|
43713
|
-
: c
|
|
43942
|
+
: c?.evaluatedCell?.formattedValue || "")
|
|
43714
43943
|
.join("\t");
|
|
43715
43944
|
})
|
|
43716
43945
|
.join("\n") || "\t");
|
|
43717
43946
|
}
|
|
43718
43947
|
getHTMLContent() {
|
|
43719
43948
|
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
43949
|
+
if (!this.cells[0][0]) {
|
|
43950
|
+
return "";
|
|
43951
|
+
}
|
|
43720
43952
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
43721
43953
|
}
|
|
43722
43954
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
43723
43955
|
for (const row of this.cells) {
|
|
43724
43956
|
htmlTable += "<tr>";
|
|
43725
43957
|
for (const cell of row) {
|
|
43726
|
-
|
|
43958
|
+
if (!cell) {
|
|
43959
|
+
continue;
|
|
43960
|
+
}
|
|
43961
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
43727
43962
|
const cellText = this.getters.getCellText(cell.position);
|
|
43728
43963
|
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
43729
43964
|
}
|
|
@@ -44051,24 +44286,49 @@ var Direction;
|
|
|
44051
44286
|
*/
|
|
44052
44287
|
class FindAndReplacePlugin extends UIPlugin {
|
|
44053
44288
|
static layers = [3 /* LAYERS.Search */];
|
|
44054
|
-
static getters = [
|
|
44055
|
-
|
|
44289
|
+
static getters = [
|
|
44290
|
+
"getSearchMatches",
|
|
44291
|
+
"getCurrentSelectedMatchIndex",
|
|
44292
|
+
"getSearchOptions",
|
|
44293
|
+
"getAllSheetMatchesCount",
|
|
44294
|
+
"getActiveSheetMatchesCount",
|
|
44295
|
+
"getSpecificRangeMatchesCount",
|
|
44296
|
+
];
|
|
44297
|
+
allSheetsMatches = [];
|
|
44298
|
+
activeSheetMatches = [];
|
|
44299
|
+
specificRangeMatches = [];
|
|
44300
|
+
// fixme: why do we make selectedMatchIndex on top of a selected
|
|
44301
|
+
// property in the matches?
|
|
44056
44302
|
selectedMatchIndex = null;
|
|
44057
44303
|
currentSearchRegex = null;
|
|
44058
44304
|
searchOptions = {
|
|
44059
44305
|
matchCase: false,
|
|
44060
44306
|
exactMatch: false,
|
|
44061
44307
|
searchFormulas: false,
|
|
44308
|
+
searchScope: "allSheets",
|
|
44309
|
+
specificRange: undefined,
|
|
44062
44310
|
};
|
|
44063
44311
|
toSearch = "";
|
|
44064
44312
|
isSearchDirty = false;
|
|
44313
|
+
get searchMatches() {
|
|
44314
|
+
switch (this.searchOptions.searchScope) {
|
|
44315
|
+
case "allSheets":
|
|
44316
|
+
return this.allSheetsMatches;
|
|
44317
|
+
case "activeSheet":
|
|
44318
|
+
return this.activeSheetMatches;
|
|
44319
|
+
case "specificRange":
|
|
44320
|
+
return this.specificRangeMatches;
|
|
44321
|
+
}
|
|
44322
|
+
}
|
|
44065
44323
|
// ---------------------------------------------------------------------------
|
|
44066
44324
|
// Command Handling
|
|
44067
44325
|
// ---------------------------------------------------------------------------
|
|
44068
44326
|
handle(cmd) {
|
|
44069
44327
|
switch (cmd.type) {
|
|
44070
44328
|
case "UPDATE_SEARCH":
|
|
44071
|
-
|
|
44329
|
+
const rangeData = cmd.searchOptions.specificRange;
|
|
44330
|
+
const specificRange = rangeData && this.getters.getRangeFromRangeData(rangeData);
|
|
44331
|
+
this.updateSearch(cmd.toSearch, { ...cmd.searchOptions, specificRange });
|
|
44072
44332
|
break;
|
|
44073
44333
|
case "CLEAR_SEARCH":
|
|
44074
44334
|
this.clearSearch();
|
|
@@ -44098,7 +44358,9 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44098
44358
|
this.isSearchDirty = true;
|
|
44099
44359
|
break;
|
|
44100
44360
|
case "ACTIVATE_SHEET":
|
|
44101
|
-
this.
|
|
44361
|
+
if (this.searchOptions.searchScope === "activeSheet") {
|
|
44362
|
+
this.isSearchDirty = true;
|
|
44363
|
+
}
|
|
44102
44364
|
break;
|
|
44103
44365
|
}
|
|
44104
44366
|
}
|
|
@@ -44117,6 +44379,18 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44117
44379
|
getCurrentSelectedMatchIndex() {
|
|
44118
44380
|
return this.selectedMatchIndex;
|
|
44119
44381
|
}
|
|
44382
|
+
getSearchOptions() {
|
|
44383
|
+
return { ...this.searchOptions, specificRange: this.searchOptions.specificRange?.rangeData };
|
|
44384
|
+
}
|
|
44385
|
+
getAllSheetMatchesCount() {
|
|
44386
|
+
return this.allSheetsMatches.length;
|
|
44387
|
+
}
|
|
44388
|
+
getActiveSheetMatchesCount() {
|
|
44389
|
+
return this.activeSheetMatches.length;
|
|
44390
|
+
}
|
|
44391
|
+
getSpecificRangeMatchesCount() {
|
|
44392
|
+
return this.specificRangeMatches.length;
|
|
44393
|
+
}
|
|
44120
44394
|
// ---------------------------------------------------------------------------
|
|
44121
44395
|
// Search
|
|
44122
44396
|
// ---------------------------------------------------------------------------
|
|
@@ -44137,8 +44411,8 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44137
44411
|
* refresh the matches according to the current search options
|
|
44138
44412
|
*/
|
|
44139
44413
|
refreshSearch() {
|
|
44140
|
-
|
|
44141
|
-
this.
|
|
44414
|
+
this.selectedMatchIndex = null;
|
|
44415
|
+
this.findMatches();
|
|
44142
44416
|
this.selectNextCell(Direction.current);
|
|
44143
44417
|
}
|
|
44144
44418
|
/**
|
|
@@ -44153,45 +44427,65 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44153
44427
|
}
|
|
44154
44428
|
this.currentSearchRegex = RegExp(searchValue, flags);
|
|
44155
44429
|
}
|
|
44430
|
+
getSheetsInSearchOrder() {
|
|
44431
|
+
switch (this.searchOptions.searchScope) {
|
|
44432
|
+
case "allSheets":
|
|
44433
|
+
const sheetIds = this.getters.getSheetIds();
|
|
44434
|
+
const activeSheetIndex = sheetIds.findIndex((id) => id === this.getters.getActiveSheetId());
|
|
44435
|
+
return [
|
|
44436
|
+
sheetIds[activeSheetIndex],
|
|
44437
|
+
...sheetIds.slice(activeSheetIndex + 1),
|
|
44438
|
+
...sheetIds.slice(0, activeSheetIndex),
|
|
44439
|
+
];
|
|
44440
|
+
case "activeSheet":
|
|
44441
|
+
return [this.getters.getActiveSheetId()];
|
|
44442
|
+
case "specificRange":
|
|
44443
|
+
const specificRange = this.searchOptions.specificRange;
|
|
44444
|
+
if (!specificRange) {
|
|
44445
|
+
return [];
|
|
44446
|
+
}
|
|
44447
|
+
return specificRange ? [specificRange.sheetId] : [];
|
|
44448
|
+
}
|
|
44449
|
+
}
|
|
44156
44450
|
/**
|
|
44157
44451
|
* Find matches using the current regex
|
|
44158
44452
|
*/
|
|
44159
44453
|
findMatches() {
|
|
44160
|
-
const sheetId = this.getters.getActiveSheetId();
|
|
44161
|
-
const cells = this.getters.getCells(sheetId);
|
|
44162
44454
|
const matches = [];
|
|
44163
|
-
if (this.toSearch
|
|
44164
|
-
for (const
|
|
44165
|
-
|
|
44166
|
-
|
|
44455
|
+
if (this.toSearch) {
|
|
44456
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
44457
|
+
matches.push(...this.findMatchesInSheet(sheetId));
|
|
44458
|
+
}
|
|
44459
|
+
}
|
|
44460
|
+
// set results
|
|
44461
|
+
this.allSheetsMatches = matches;
|
|
44462
|
+
this.activeSheetMatches = matches.filter((match) => match.sheetId === this.getters.getActiveSheetId());
|
|
44463
|
+
if (this.searchOptions.specificRange) {
|
|
44464
|
+
const { sheetId, zone } = this.searchOptions.specificRange;
|
|
44465
|
+
this.specificRangeMatches = matches.filter((match) => match.sheetId === sheetId && isInside(match.col, match.row, zone));
|
|
44466
|
+
}
|
|
44467
|
+
else {
|
|
44468
|
+
this.specificRangeMatches = [];
|
|
44469
|
+
}
|
|
44470
|
+
}
|
|
44471
|
+
findMatchesInSheet(sheetId) {
|
|
44472
|
+
const matches = [];
|
|
44473
|
+
const { left, right, top, bottom } = this.getters.getSheetZone(sheetId);
|
|
44474
|
+
for (let row = top; row <= bottom; row++) {
|
|
44475
|
+
for (let col = left; col <= right; col++) {
|
|
44167
44476
|
const isColHidden = this.getters.isColHidden(sheetId, col);
|
|
44168
44477
|
const isRowHidden = this.getters.isRowHidden(sheetId, row);
|
|
44169
44478
|
if (isColHidden || isRowHidden) {
|
|
44170
44479
|
continue;
|
|
44171
44480
|
}
|
|
44172
|
-
|
|
44173
|
-
|
|
44481
|
+
const cellPosition = { sheetId, col, row };
|
|
44482
|
+
if (this.currentSearchRegex?.test(this.getSearchableString(cellPosition))) {
|
|
44483
|
+
const match = { sheetId, col, row };
|
|
44174
44484
|
matches.push(match);
|
|
44175
44485
|
}
|
|
44176
|
-
for (const spreadPosition of this.getters.getSpreadPositionsOf(cellPosition)) {
|
|
44177
|
-
if (this.currentSearchRegex.test(this.getSearchableString(spreadPosition))) {
|
|
44178
|
-
const match = {
|
|
44179
|
-
col: spreadPosition.col,
|
|
44180
|
-
row: spreadPosition.row,
|
|
44181
|
-
selected: false,
|
|
44182
|
-
};
|
|
44183
|
-
matches.push(match);
|
|
44184
|
-
}
|
|
44185
|
-
}
|
|
44186
44486
|
}
|
|
44187
44487
|
}
|
|
44188
|
-
return matches
|
|
44189
|
-
}
|
|
44190
|
-
sortByRowThenColumn(a, b) {
|
|
44191
|
-
if (a.row === b.row) {
|
|
44192
|
-
return a.col - b.col;
|
|
44193
|
-
}
|
|
44194
|
-
return a.row > b.row ? 1 : -1;
|
|
44488
|
+
return matches;
|
|
44195
44489
|
}
|
|
44196
44490
|
/**
|
|
44197
44491
|
* Changes the selected search cell. Given a direction it will
|
|
@@ -44209,30 +44503,47 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44209
44503
|
}
|
|
44210
44504
|
let nextIndex;
|
|
44211
44505
|
if (this.selectedMatchIndex === null) {
|
|
44212
|
-
|
|
44506
|
+
let nextMatchIndex = -1;
|
|
44507
|
+
// if search is not available in current sheet will select in next sheet
|
|
44508
|
+
for (const sheetId of this.getSheetsInSearchOrder()) {
|
|
44509
|
+
nextMatchIndex = matches.findIndex((match) => match.sheetId === sheetId);
|
|
44510
|
+
if (nextMatchIndex !== -1) {
|
|
44511
|
+
break;
|
|
44512
|
+
}
|
|
44513
|
+
}
|
|
44514
|
+
nextIndex = nextMatchIndex;
|
|
44213
44515
|
}
|
|
44214
44516
|
else {
|
|
44215
44517
|
nextIndex = this.selectedMatchIndex + indexChange;
|
|
44216
44518
|
}
|
|
44217
|
-
//
|
|
44218
|
-
nextIndex = (
|
|
44519
|
+
// loop index value inside the array (index -1 => last index)
|
|
44520
|
+
nextIndex = (nextIndex + matches.length) % matches.length;
|
|
44219
44521
|
this.selectedMatchIndex = nextIndex;
|
|
44522
|
+
const selectedMatch = matches[nextIndex];
|
|
44523
|
+
// Switch to the sheet where the match is located
|
|
44524
|
+
if (this.getters.getActiveSheetId() !== selectedMatch.sheetId) {
|
|
44525
|
+
this.dispatch("ACTIVATE_SHEET", {
|
|
44526
|
+
sheetIdFrom: this.getters.getActiveSheetId(),
|
|
44527
|
+
sheetIdTo: selectedMatch.sheetId,
|
|
44528
|
+
});
|
|
44529
|
+
}
|
|
44220
44530
|
// we want grid selection to capture the selection stream
|
|
44221
44531
|
this.selection.getBackToDefault();
|
|
44222
|
-
this.selection.selectCell(
|
|
44223
|
-
for (let index = 0; index < this.searchMatches.length; index++) {
|
|
44224
|
-
this.searchMatches[index].selected = index === this.selectedMatchIndex;
|
|
44225
|
-
}
|
|
44532
|
+
this.selection.selectCell(selectedMatch.col, selectedMatch.row);
|
|
44226
44533
|
}
|
|
44227
44534
|
clearSearch() {
|
|
44228
44535
|
this.toSearch = "";
|
|
44229
|
-
this.searchMatches = [];
|
|
44230
44536
|
this.selectedMatchIndex = null;
|
|
44231
44537
|
this.currentSearchRegex = null;
|
|
44538
|
+
this.allSheetsMatches = [];
|
|
44539
|
+
this.activeSheetMatches = [];
|
|
44540
|
+
this.specificRangeMatches = [];
|
|
44232
44541
|
this.searchOptions = {
|
|
44233
44542
|
matchCase: false,
|
|
44234
44543
|
exactMatch: false,
|
|
44235
44544
|
searchFormulas: false,
|
|
44545
|
+
searchScope: "allSheets",
|
|
44546
|
+
specificRange: undefined,
|
|
44236
44547
|
};
|
|
44237
44548
|
}
|
|
44238
44549
|
// ---------------------------------------------------------------------------
|
|
@@ -44242,9 +44553,7 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44242
44553
|
if (!this.currentSearchRegex) {
|
|
44243
44554
|
return;
|
|
44244
44555
|
}
|
|
44245
|
-
const
|
|
44246
|
-
const position = { sheetId, ...selectedMatch };
|
|
44247
|
-
const cell = this.getters.getCell(position);
|
|
44556
|
+
const cell = this.getters.getCell(selectedMatch);
|
|
44248
44557
|
if (!cell?.content) {
|
|
44249
44558
|
return;
|
|
44250
44559
|
}
|
|
@@ -44252,10 +44561,10 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44252
44561
|
return;
|
|
44253
44562
|
}
|
|
44254
44563
|
const replaceRegex = new RegExp(this.currentSearchRegex.source, this.currentSearchRegex.flags + "g");
|
|
44255
|
-
const toReplace = this.getSearchableString(
|
|
44564
|
+
const toReplace = this.getSearchableString(selectedMatch);
|
|
44256
44565
|
const content = toReplace.replace(replaceRegex, replaceWith);
|
|
44257
44566
|
const canonicalContent = canonicalizeNumberContent(content, this.getters.getLocale());
|
|
44258
|
-
this.dispatch("UPDATE_CELL", { ...
|
|
44567
|
+
this.dispatch("UPDATE_CELL", { ...selectedMatch, content: canonicalContent });
|
|
44259
44568
|
}
|
|
44260
44569
|
/**
|
|
44261
44570
|
* Replace the value of the currently selected match
|
|
@@ -44286,7 +44595,10 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44286
44595
|
drawGrid(renderingContext) {
|
|
44287
44596
|
const { ctx } = renderingContext;
|
|
44288
44597
|
const sheetId = this.getters.getActiveSheetId();
|
|
44289
|
-
for (const match of this.searchMatches) {
|
|
44598
|
+
for (const [index, match] of this.searchMatches.entries()) {
|
|
44599
|
+
if (match.sheetId !== sheetId) {
|
|
44600
|
+
continue; // Skip drawing matches from other sheets
|
|
44601
|
+
}
|
|
44290
44602
|
const merge = this.getters.getMerge({ sheetId, col: match.col, row: match.row });
|
|
44291
44603
|
const left = merge ? merge.left : match.col;
|
|
44292
44604
|
const right = merge ? merge.right : match.col;
|
|
@@ -44296,12 +44608,21 @@ class FindAndReplacePlugin extends UIPlugin {
|
|
|
44296
44608
|
if (width > 0 && height > 0) {
|
|
44297
44609
|
ctx.fillStyle = BACKGROUND_COLOR;
|
|
44298
44610
|
ctx.fillRect(x, y, width, height);
|
|
44299
|
-
if (
|
|
44611
|
+
if (index === this.selectedMatchIndex) {
|
|
44300
44612
|
ctx.strokeStyle = BORDER_COLOR;
|
|
44301
44613
|
ctx.strokeRect(x, y, width, height);
|
|
44302
44614
|
}
|
|
44303
44615
|
}
|
|
44304
44616
|
}
|
|
44617
|
+
if (this.searchOptions.searchScope === "specificRange") {
|
|
44618
|
+
const range = this.searchOptions.specificRange;
|
|
44619
|
+
if (!range || range.sheetId !== sheetId) {
|
|
44620
|
+
return;
|
|
44621
|
+
}
|
|
44622
|
+
const { x, y, width, height } = this.getters.getVisibleRect(range.zone);
|
|
44623
|
+
ctx.strokeStyle = BORDER_COLOR;
|
|
44624
|
+
ctx.strokeRect(x, y, width, height);
|
|
44625
|
+
}
|
|
44305
44626
|
}
|
|
44306
44627
|
}
|
|
44307
44628
|
|
|
@@ -45560,6 +45881,9 @@ class SelectionInputsManagerPlugin extends UIPlugin {
|
|
|
45560
45881
|
// Other
|
|
45561
45882
|
// ---------------------------------------------------------------------------
|
|
45562
45883
|
initInput(id, initialRanges, inputHasSingleRange = false) {
|
|
45884
|
+
if (this.inputs[id]) {
|
|
45885
|
+
this.unfocus();
|
|
45886
|
+
}
|
|
45563
45887
|
this.inputs[id] = new SelectionInputPlugin(this.config, initialRanges, inputHasSingleRange);
|
|
45564
45888
|
if (initialRanges.length === 0) {
|
|
45565
45889
|
const input = this.inputs[id];
|
|
@@ -46268,7 +46592,7 @@ class HistoryPlugin extends UIPlugin {
|
|
|
46268
46592
|
* Ignore standard undo/redo revisions (that are empty)
|
|
46269
46593
|
*/
|
|
46270
46594
|
getPossibleRevisionToRepeat() {
|
|
46271
|
-
return this.session.getLastLocalNonEmptyRevision(
|
|
46595
|
+
return this.session.getLastLocalNonEmptyRevision();
|
|
46272
46596
|
}
|
|
46273
46597
|
}
|
|
46274
46598
|
|
|
@@ -46767,11 +47091,14 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
46767
47091
|
}
|
|
46768
47092
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
46769
47093
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
47094
|
+
if (this.state.operation === "CUT") {
|
|
47095
|
+
this.state = undefined;
|
|
47096
|
+
}
|
|
46770
47097
|
this.lastPasteState = this.state;
|
|
46771
47098
|
if (this.paintFormatStatus === "oneOff") {
|
|
46772
47099
|
this.paintFormatStatus = "inactive";
|
|
46773
|
-
this.status = "invisible";
|
|
46774
47100
|
}
|
|
47101
|
+
this.status = "invisible";
|
|
46775
47102
|
break;
|
|
46776
47103
|
case "COPY_PASTE_CELLS_ABOVE":
|
|
46777
47104
|
{
|
|
@@ -46998,92 +47325,6 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
46998
47325
|
}
|
|
46999
47326
|
}
|
|
47000
47327
|
|
|
47001
|
-
/**
|
|
47002
|
-
* Change the reference types inside the given token, if the token represent a range or a cell
|
|
47003
|
-
*
|
|
47004
|
-
* Eg. :
|
|
47005
|
-
* A1 => $A$1 => A$1 => $A1 => A1
|
|
47006
|
-
* A1:$B$1 => $A$1:B$1 => A$1:$B1 => $A1:B1 => A1:$B$1
|
|
47007
|
-
*/
|
|
47008
|
-
function loopThroughReferenceType(token) {
|
|
47009
|
-
if (token.type !== "REFERENCE")
|
|
47010
|
-
return token;
|
|
47011
|
-
const { xc, sheetName } = splitReference(token.value);
|
|
47012
|
-
const [left, right] = xc.split(":");
|
|
47013
|
-
const sheetRef = sheetName ? `${getCanonicalSheetName(sheetName)}!` : "";
|
|
47014
|
-
const updatedLeft = getTokenNextReferenceType(left);
|
|
47015
|
-
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
47016
|
-
return { ...token, value: sheetRef + updatedLeft + updatedRight };
|
|
47017
|
-
}
|
|
47018
|
-
/**
|
|
47019
|
-
* Get a new token with a changed type of reference from the given cell token symbol.
|
|
47020
|
-
* Undefined behavior if given a token other than a cell or if the Xc contains a sheet reference
|
|
47021
|
-
*
|
|
47022
|
-
* A1 => $A$1 => A$1 => $A1 => A1
|
|
47023
|
-
*/
|
|
47024
|
-
function getTokenNextReferenceType(xc) {
|
|
47025
|
-
switch (getReferenceType(xc)) {
|
|
47026
|
-
case "none":
|
|
47027
|
-
xc = setXcToReferenceType(xc, "colrow");
|
|
47028
|
-
break;
|
|
47029
|
-
case "colrow":
|
|
47030
|
-
xc = setXcToReferenceType(xc, "row");
|
|
47031
|
-
break;
|
|
47032
|
-
case "row":
|
|
47033
|
-
xc = setXcToReferenceType(xc, "col");
|
|
47034
|
-
break;
|
|
47035
|
-
case "col":
|
|
47036
|
-
xc = setXcToReferenceType(xc, "none");
|
|
47037
|
-
break;
|
|
47038
|
-
}
|
|
47039
|
-
return xc;
|
|
47040
|
-
}
|
|
47041
|
-
/**
|
|
47042
|
-
* Returns the given XC with the given reference type.
|
|
47043
|
-
*/
|
|
47044
|
-
function setXcToReferenceType(xc, referenceType) {
|
|
47045
|
-
xc = xc.replace(/\$/g, "");
|
|
47046
|
-
let indexOfNumber;
|
|
47047
|
-
switch (referenceType) {
|
|
47048
|
-
case "col":
|
|
47049
|
-
return "$" + xc;
|
|
47050
|
-
case "row":
|
|
47051
|
-
indexOfNumber = xc.search(/[0-9]/);
|
|
47052
|
-
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47053
|
-
case "colrow":
|
|
47054
|
-
indexOfNumber = xc.search(/[0-9]/);
|
|
47055
|
-
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47056
|
-
return "$" + xc;
|
|
47057
|
-
case "none":
|
|
47058
|
-
return xc;
|
|
47059
|
-
}
|
|
47060
|
-
}
|
|
47061
|
-
/**
|
|
47062
|
-
* Return the type of reference used in the given XC of a cell.
|
|
47063
|
-
* Undefined behavior if the XC have a sheet reference
|
|
47064
|
-
*/
|
|
47065
|
-
function getReferenceType(xcCell) {
|
|
47066
|
-
if (isColAndRowFixed(xcCell)) {
|
|
47067
|
-
return "colrow";
|
|
47068
|
-
}
|
|
47069
|
-
else if (isColFixed(xcCell)) {
|
|
47070
|
-
return "col";
|
|
47071
|
-
}
|
|
47072
|
-
else if (isRowFixed(xcCell)) {
|
|
47073
|
-
return "row";
|
|
47074
|
-
}
|
|
47075
|
-
return "none";
|
|
47076
|
-
}
|
|
47077
|
-
function isColFixed(xc) {
|
|
47078
|
-
return xc.startsWith("$");
|
|
47079
|
-
}
|
|
47080
|
-
function isRowFixed(xc) {
|
|
47081
|
-
return xc.includes("$", 1);
|
|
47082
|
-
}
|
|
47083
|
-
function isColAndRowFixed(xc) {
|
|
47084
|
-
return xc.startsWith("$") && xc.length > 1 && xc.slice(1).includes("$");
|
|
47085
|
-
}
|
|
47086
|
-
|
|
47087
47328
|
const CELL_DELETED_MESSAGE = _t("The cell you are trying to edit has been deleted.");
|
|
47088
47329
|
class EditionPlugin extends UIPlugin {
|
|
47089
47330
|
static getters = [
|
|
@@ -47822,6 +48063,12 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
47822
48063
|
break;
|
|
47823
48064
|
case "HIDE_COLUMNS_ROWS":
|
|
47824
48065
|
case "UNHIDE_COLUMNS_ROWS":
|
|
48066
|
+
case "GROUP_HEADERS":
|
|
48067
|
+
case "UNGROUP_HEADERS":
|
|
48068
|
+
case "FOLD_HEADER_GROUP":
|
|
48069
|
+
case "UNFOLD_HEADER_GROUP":
|
|
48070
|
+
case "FOLD_ALL_HEADER_GROUPS":
|
|
48071
|
+
case "UNFOLD_ALL_HEADER_GROUPS":
|
|
47825
48072
|
this.updateHiddenRows();
|
|
47826
48073
|
break;
|
|
47827
48074
|
case "UPDATE_FILTER":
|
|
@@ -48001,32 +48248,32 @@ const selectionStatisticFunctions = [
|
|
|
48001
48248
|
{
|
|
48002
48249
|
name: _t("Sum"),
|
|
48003
48250
|
types: [CellValueType.number],
|
|
48004
|
-
compute: (values, locale) =>
|
|
48251
|
+
compute: (values, locale) => sum([[values]], locale),
|
|
48005
48252
|
},
|
|
48006
48253
|
{
|
|
48007
48254
|
name: _t("Avg"),
|
|
48008
48255
|
types: [CellValueType.number],
|
|
48009
|
-
compute: (values, locale) =>
|
|
48256
|
+
compute: (values, locale) => average([[values]], locale),
|
|
48010
48257
|
},
|
|
48011
48258
|
{
|
|
48012
48259
|
name: _t("Min"),
|
|
48013
48260
|
types: [CellValueType.number],
|
|
48014
|
-
compute: (values, locale) =>
|
|
48261
|
+
compute: (values, locale) => min([[values]], locale),
|
|
48015
48262
|
},
|
|
48016
48263
|
{
|
|
48017
48264
|
name: _t("Max"),
|
|
48018
48265
|
types: [CellValueType.number],
|
|
48019
|
-
compute: (values, locale) =>
|
|
48266
|
+
compute: (values, locale) => max([[values]], locale),
|
|
48020
48267
|
},
|
|
48021
48268
|
{
|
|
48022
48269
|
name: _t("Count"),
|
|
48023
48270
|
types: [CellValueType.number, CellValueType.text, CellValueType.boolean, CellValueType.error],
|
|
48024
|
-
compute: (values
|
|
48271
|
+
compute: (values) => countAny([[values]]),
|
|
48025
48272
|
},
|
|
48026
48273
|
{
|
|
48027
48274
|
name: _t("Count Numbers"),
|
|
48028
48275
|
types: [CellValueType.number, CellValueType.text, CellValueType.boolean, CellValueType.error],
|
|
48029
|
-
compute: (values, locale) =>
|
|
48276
|
+
compute: (values, locale) => countNumbers([[values]], locale),
|
|
48030
48277
|
},
|
|
48031
48278
|
];
|
|
48032
48279
|
/**
|
|
@@ -48523,7 +48770,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
48523
48770
|
sheetId: cmd.sheetId,
|
|
48524
48771
|
base: cmd.base,
|
|
48525
48772
|
quantity: thickness,
|
|
48526
|
-
position:
|
|
48773
|
+
position: cmd.position,
|
|
48527
48774
|
});
|
|
48528
48775
|
const isCol = cmd.dimension === "COL";
|
|
48529
48776
|
const start = cmd.elements[0];
|
|
@@ -48540,12 +48787,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
48540
48787
|
},
|
|
48541
48788
|
];
|
|
48542
48789
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
48790
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
48543
48791
|
const pasteTarget = [
|
|
48544
48792
|
{
|
|
48545
|
-
left: isCol ?
|
|
48546
|
-
right: isCol ?
|
|
48547
|
-
top: !isCol ?
|
|
48548
|
-
bottom: !isCol ?
|
|
48793
|
+
left: isCol ? base : 0,
|
|
48794
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
48795
|
+
top: !isCol ? base : 0,
|
|
48796
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
48549
48797
|
},
|
|
48550
48798
|
];
|
|
48551
48799
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -48580,6 +48828,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
48580
48828
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
48581
48829
|
return "WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */;
|
|
48582
48830
|
}
|
|
48831
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
48832
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
48833
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
48834
|
+
return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
|
|
48835
|
+
}
|
|
48583
48836
|
return "Success" /* CommandResult.Success */;
|
|
48584
48837
|
}
|
|
48585
48838
|
//-------------------------------------------
|
|
@@ -48757,9 +49010,6 @@ class InternalViewport {
|
|
|
48757
49010
|
*/
|
|
48758
49011
|
adjustPosition(position) {
|
|
48759
49012
|
const sheetId = this.sheetId;
|
|
48760
|
-
if (!position) {
|
|
48761
|
-
position = this.getters.getSheetPosition(sheetId);
|
|
48762
|
-
}
|
|
48763
49013
|
const mainCellPosition = this.getters.getMainCellPosition({ sheetId, ...position });
|
|
48764
49014
|
const { col, row } = this.getters.getNextVisibleCellPosition(mainCellPosition);
|
|
48765
49015
|
if (isInside(col, this.boundaries.top, this.boundaries)) {
|
|
@@ -48772,56 +49022,50 @@ class InternalViewport {
|
|
|
48772
49022
|
adjustPositionX(targetCol) {
|
|
48773
49023
|
const sheetId = this.sheetId;
|
|
48774
49024
|
const { end } = this.getters.getColDimensions(sheetId, targetCol);
|
|
48775
|
-
const maxCol = this.getters.getNumberCols(sheetId);
|
|
48776
49025
|
if (this.offsetX + this.offsetCorrectionX + this.viewportWidth < end) {
|
|
49026
|
+
const maxCol = this.getters.getNumberCols(sheetId);
|
|
48777
49027
|
let finalTarget = targetCol;
|
|
48778
|
-
while (this.getters.isColHidden(sheetId, finalTarget) &&
|
|
49028
|
+
while (this.getters.isColHidden(sheetId, finalTarget) && finalTarget < maxCol) {
|
|
48779
49029
|
finalTarget++;
|
|
48780
49030
|
}
|
|
48781
49031
|
const finalTargetEnd = this.getters.getColDimensions(sheetId, finalTarget).end;
|
|
48782
49032
|
const startIndex = this.searchHeaderIndex("COL", finalTargetEnd - this.viewportWidth - this.offsetCorrectionX, this.boundaries.left);
|
|
48783
|
-
this.
|
|
49033
|
+
this.offsetScrollbarX =
|
|
48784
49034
|
this.getters.getColDimensions(sheetId, startIndex).end - this.offsetCorrectionX;
|
|
48785
|
-
this.offsetScrollbarX = this.offsetX;
|
|
48786
|
-
this.adjustViewportZoneX();
|
|
48787
49035
|
}
|
|
48788
49036
|
else if (this.left > targetCol) {
|
|
48789
49037
|
let finalTarget = targetCol;
|
|
48790
|
-
while (this.getters.isColHidden(sheetId, finalTarget) &&
|
|
49038
|
+
while (this.getters.isColHidden(sheetId, finalTarget) && finalTarget > 0) {
|
|
48791
49039
|
finalTarget--;
|
|
48792
49040
|
}
|
|
48793
|
-
this.
|
|
49041
|
+
this.offsetScrollbarX =
|
|
48794
49042
|
this.getters.getColDimensions(sheetId, finalTarget).start - this.offsetCorrectionX;
|
|
48795
|
-
this.offsetScrollbarX = this.offsetX;
|
|
48796
|
-
this.adjustViewportZoneX();
|
|
48797
49043
|
}
|
|
49044
|
+
this.adjustViewportZoneX();
|
|
48798
49045
|
}
|
|
48799
49046
|
adjustPositionY(targetRow) {
|
|
48800
49047
|
const sheetId = this.sheetId;
|
|
48801
49048
|
const { end } = this.getters.getRowDimensions(sheetId, targetRow);
|
|
48802
|
-
const maxRow = this.getters.getNumberRows(sheetId);
|
|
48803
49049
|
if (this.offsetY + this.viewportHeight + this.offsetCorrectionY < end) {
|
|
49050
|
+
const maxRow = this.getters.getNumberRows(sheetId);
|
|
48804
49051
|
let finalTarget = targetRow;
|
|
48805
|
-
while (this.getters.isRowHidden(sheetId, finalTarget) &&
|
|
49052
|
+
while (this.getters.isRowHidden(sheetId, finalTarget) && finalTarget < maxRow) {
|
|
48806
49053
|
finalTarget++;
|
|
48807
49054
|
}
|
|
48808
49055
|
const finalTargetEnd = this.getters.getRowDimensions(sheetId, finalTarget).end;
|
|
48809
49056
|
const startIndex = this.searchHeaderIndex("ROW", finalTargetEnd - this.viewportHeight - this.offsetCorrectionY, this.boundaries.top);
|
|
48810
|
-
this.
|
|
49057
|
+
this.offsetScrollbarY =
|
|
48811
49058
|
this.getters.getRowDimensions(sheetId, startIndex).end - this.offsetCorrectionY;
|
|
48812
|
-
this.offsetScrollbarY = this.offsetY;
|
|
48813
|
-
this.adjustViewportZoneY();
|
|
48814
49059
|
}
|
|
48815
49060
|
else if (this.top > targetRow) {
|
|
48816
49061
|
let finalTarget = targetRow;
|
|
48817
|
-
while (this.getters.isRowHidden(sheetId, finalTarget) &&
|
|
49062
|
+
while (this.getters.isRowHidden(sheetId, finalTarget) && finalTarget > 0) {
|
|
48818
49063
|
finalTarget--;
|
|
48819
49064
|
}
|
|
48820
|
-
this.
|
|
49065
|
+
this.offsetScrollbarY =
|
|
48821
49066
|
this.getters.getRowDimensions(sheetId, finalTarget).start - this.offsetCorrectionY;
|
|
48822
|
-
this.offsetScrollbarY = this.offsetY;
|
|
48823
|
-
this.adjustViewportZoneY();
|
|
48824
49067
|
}
|
|
49068
|
+
this.adjustViewportZoneY();
|
|
48825
49069
|
}
|
|
48826
49070
|
setViewportOffset(offsetX, offsetY) {
|
|
48827
49071
|
this.setViewportOffsetX(offsetX);
|
|
@@ -48837,11 +49081,10 @@ class InternalViewport {
|
|
|
48837
49081
|
* @returns Computes the absolute coordinate of a given zone inside the viewport
|
|
48838
49082
|
*/
|
|
48839
49083
|
getRect(zone) {
|
|
48840
|
-
const targetZone = intersection(zone, this
|
|
49084
|
+
const targetZone = intersection(zone, this);
|
|
48841
49085
|
if (targetZone) {
|
|
48842
|
-
const x = this.getters.getColRowOffset("COL", this.
|
|
48843
|
-
|
|
48844
|
-
const y = this.getters.getColRowOffset("ROW", this.zone.top, targetZone.top) + this.offsetCorrectionY;
|
|
49086
|
+
const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) + this.offsetCorrectionX;
|
|
49087
|
+
const y = this.getters.getColRowOffset("ROW", this.top, targetZone.top) + this.offsetCorrectionY;
|
|
48845
49088
|
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
|
|
48846
49089
|
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
|
|
48847
49090
|
return {
|
|
@@ -48851,9 +49094,7 @@ class InternalViewport {
|
|
|
48851
49094
|
height,
|
|
48852
49095
|
};
|
|
48853
49096
|
}
|
|
48854
|
-
|
|
48855
|
-
return undefined;
|
|
48856
|
-
}
|
|
49097
|
+
return undefined;
|
|
48857
49098
|
}
|
|
48858
49099
|
isVisible(col, row) {
|
|
48859
49100
|
const isInside = row <= this.bottom && row >= this.top && col >= this.left && col <= this.right;
|
|
@@ -48861,7 +49102,6 @@ class InternalViewport {
|
|
|
48861
49102
|
!this.getters.isColHidden(this.sheetId, col) &&
|
|
48862
49103
|
!this.getters.isRowHidden(this.sheetId, row));
|
|
48863
49104
|
}
|
|
48864
|
-
// PRIVATE
|
|
48865
49105
|
searchHeaderIndex(dimension, position, startIndex = 0) {
|
|
48866
49106
|
const sheetId = this.sheetId;
|
|
48867
49107
|
const headers = this.getters.getNumberHeaders(sheetId, dimension);
|
|
@@ -48884,9 +49124,6 @@ class InternalViewport {
|
|
|
48884
49124
|
}
|
|
48885
49125
|
return -1;
|
|
48886
49126
|
}
|
|
48887
|
-
get zone() {
|
|
48888
|
-
return { left: this.left, right: this.right, top: this.top, bottom: this.bottom };
|
|
48889
|
-
}
|
|
48890
49127
|
setViewportOffsetX(offsetX) {
|
|
48891
49128
|
if (!this.canScrollHorizontally) {
|
|
48892
49129
|
return;
|
|
@@ -48911,11 +49148,6 @@ class InternalViewport {
|
|
|
48911
49148
|
this.offsetScrollbarX = Math.max(0, viewportWidth - this.viewportWidth);
|
|
48912
49149
|
}
|
|
48913
49150
|
}
|
|
48914
|
-
this.left = this.getColIndex(this.offsetScrollbarX);
|
|
48915
|
-
this.right = this.getColIndex(this.offsetScrollbarX + this.viewportWidth);
|
|
48916
|
-
if (this.right === -1) {
|
|
48917
|
-
this.right = this.boundaries.right;
|
|
48918
|
-
}
|
|
48919
49151
|
this.adjustViewportZoneX();
|
|
48920
49152
|
}
|
|
48921
49153
|
/** Corrects the viewport's vertical offset based on the current structure
|
|
@@ -48928,11 +49160,6 @@ class InternalViewport {
|
|
|
48928
49160
|
this.offsetScrollbarY = Math.max(0, paneHeight - this.viewportHeight);
|
|
48929
49161
|
}
|
|
48930
49162
|
}
|
|
48931
|
-
this.top = this.getRowIndex(this.offsetScrollbarY);
|
|
48932
|
-
this.bottom = this.getRowIndex(this.offsetScrollbarY + this.viewportHeight);
|
|
48933
|
-
if (this.bottom === -1) {
|
|
48934
|
-
this.bottom = this.boundaries.bottom;
|
|
48935
|
-
}
|
|
48936
49163
|
this.adjustViewportZoneY();
|
|
48937
49164
|
}
|
|
48938
49165
|
/** Updates the pane zone and snapped offset based on its horizontal
|
|
@@ -49310,7 +49537,7 @@ class SheetViewPlugin extends UIPlugin {
|
|
|
49310
49537
|
isVisibleInViewport({ sheetId, col, row }) {
|
|
49311
49538
|
return this.getSubViewports(sheetId).some((pane) => pane.isVisible(col, row));
|
|
49312
49539
|
}
|
|
49313
|
-
// =>
|
|
49540
|
+
// => returns the new offset
|
|
49314
49541
|
getEdgeScrollCol(x, previousX, startingX) {
|
|
49315
49542
|
let canEdgeScroll = false;
|
|
49316
49543
|
let direction = 0;
|
|
@@ -49625,10 +49852,13 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
49625
49852
|
}
|
|
49626
49853
|
break;
|
|
49627
49854
|
case "UPDATE_CELL":
|
|
49628
|
-
if ("content" in cmd || "format" in cmd
|
|
49855
|
+
if ("content" in cmd || "format" in cmd) {
|
|
49629
49856
|
this.headerPositions = {};
|
|
49630
49857
|
this.isDirty = true;
|
|
49631
49858
|
}
|
|
49859
|
+
else {
|
|
49860
|
+
this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
|
|
49861
|
+
}
|
|
49632
49862
|
break;
|
|
49633
49863
|
case "UPDATE_FILTER":
|
|
49634
49864
|
case "REMOVE_FILTER_TABLE":
|
|
@@ -51785,6 +52015,8 @@ css /* scss */ `
|
|
|
51785
52015
|
*:before,
|
|
51786
52016
|
*:after {
|
|
51787
52017
|
box-sizing: content-box;
|
|
52018
|
+
/** rtl not supported ATM */
|
|
52019
|
+
direction: ltr;
|
|
51788
52020
|
}
|
|
51789
52021
|
.o-separator {
|
|
51790
52022
|
border-bottom: ${MENU_SEPARATOR_BORDER_WIDTH}px solid ${SEPARATOR_COLOR};
|
|
@@ -51941,6 +52173,7 @@ class Spreadsheet extends Component {
|
|
|
51941
52173
|
};
|
|
51942
52174
|
sidePanel;
|
|
51943
52175
|
composer;
|
|
52176
|
+
spreadsheetRef = useRef("spreadsheet");
|
|
51944
52177
|
_focusGrid;
|
|
51945
52178
|
keyDownMapping;
|
|
51946
52179
|
isViewportTooSmall = false;
|
|
@@ -51975,6 +52208,18 @@ class Spreadsheet extends Component {
|
|
|
51975
52208
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
51976
52209
|
startCellEdition: (content) => this.onGridComposerCellFocused(content),
|
|
51977
52210
|
});
|
|
52211
|
+
useEffect(() => {
|
|
52212
|
+
/**
|
|
52213
|
+
* Only refocus the grid if the active element is not a child of the spreadsheet
|
|
52214
|
+
* (i.e. activeElement is outside of the spreadsheetRef component)
|
|
52215
|
+
* and spreadsheet is a child of that element. Anything else means that the focus
|
|
52216
|
+
* is on an element that needs to keep it.
|
|
52217
|
+
*/
|
|
52218
|
+
if (!this.spreadsheetRef.el.contains(document.activeElement) &&
|
|
52219
|
+
document.activeElement?.contains(this.spreadsheetRef.el)) {
|
|
52220
|
+
this.focusGrid();
|
|
52221
|
+
}
|
|
52222
|
+
}, () => [this.env.model.getters.getActiveSheetId()]);
|
|
51978
52223
|
useExternalListener(window, "resize", () => this.render(true));
|
|
51979
52224
|
useExternalListener(window, "beforeunload", this.unbindModelEvents.bind(this));
|
|
51980
52225
|
this.bindModelEvents();
|
|
@@ -52056,7 +52301,7 @@ class Spreadsheet extends Component {
|
|
|
52056
52301
|
}
|
|
52057
52302
|
focusGrid() {
|
|
52058
52303
|
if (!this._focusGrid) {
|
|
52059
|
-
|
|
52304
|
+
return;
|
|
52060
52305
|
}
|
|
52061
52306
|
this._focusGrid();
|
|
52062
52307
|
}
|
|
@@ -55449,19 +55694,22 @@ class Model extends EventBus {
|
|
|
55449
55694
|
* Check if the given command is allowed by all the plugins and the history.
|
|
55450
55695
|
*/
|
|
55451
55696
|
checkDispatchAllowed(command) {
|
|
55452
|
-
|
|
55453
|
-
|
|
55697
|
+
const results = isCoreCommand(command)
|
|
55698
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
55699
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
55700
|
+
if (results.some((r) => r !== "Success" /* CommandResult.Success */)) {
|
|
55701
|
+
return new DispatchResult(results.flat());
|
|
55454
55702
|
}
|
|
55455
|
-
return
|
|
55703
|
+
return DispatchResult.Success;
|
|
55456
55704
|
}
|
|
55457
55705
|
checkDispatchAllowedCoreCommand(command) {
|
|
55458
55706
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
55459
55707
|
results.push(this.range.allowDispatch(command));
|
|
55460
|
-
return
|
|
55708
|
+
return results;
|
|
55461
55709
|
}
|
|
55462
55710
|
checkDispatchAllowedLocalCommand(command) {
|
|
55463
55711
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
55464
|
-
return
|
|
55712
|
+
return results;
|
|
55465
55713
|
}
|
|
55466
55714
|
finalize() {
|
|
55467
55715
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -55756,6 +56004,7 @@ const components = {
|
|
|
55756
56004
|
FigureComponent,
|
|
55757
56005
|
Menu,
|
|
55758
56006
|
SelectionInput,
|
|
56007
|
+
ValidationMessages,
|
|
55759
56008
|
};
|
|
55760
56009
|
const hooks = {
|
|
55761
56010
|
useDragAndDropListItems,
|
|
@@ -55773,6 +56022,6 @@ const constants = {
|
|
|
55773
56022
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
55774
56023
|
|
|
55775
56024
|
|
|
55776
|
-
__info__.version = "17.1.0-alpha.
|
|
55777
|
-
__info__.date = "2023-
|
|
55778
|
-
__info__.hash = "
|
|
56025
|
+
__info__.version = "17.1.0-alpha.5";
|
|
56026
|
+
__info__.date = "2023-12-05T09:51:40.034Z";
|
|
56027
|
+
__info__.hash = "c2823eb";
|