@odoo/o-spreadsheet 16.1.27 → 16.1.31
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 +301 -184
- package/dist/o-spreadsheet.d.ts +48 -25
- package/dist/o-spreadsheet.esm.js +301 -184
- package/dist/o-spreadsheet.iife.js +301 -184
- package/dist/o-spreadsheet.iife.min.js +230 -230
- package/dist/o_spreadsheet.xml +6 -7
- package/package.json +1 -1
|
@@ -305,15 +305,76 @@ for (let font of fontSizes) {
|
|
|
305
305
|
// -----------------------------------------------------------------------------
|
|
306
306
|
// Date Type
|
|
307
307
|
// -----------------------------------------------------------------------------
|
|
308
|
+
/**
|
|
309
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
310
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
311
|
+
* and it is timezone-agnostic.
|
|
312
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
313
|
+
*/
|
|
314
|
+
class DateTime {
|
|
315
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
316
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
317
|
+
}
|
|
318
|
+
static fromTimestamp(timestamp) {
|
|
319
|
+
const date = new Date(timestamp);
|
|
320
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
321
|
+
}
|
|
322
|
+
static now() {
|
|
323
|
+
const now = new Date();
|
|
324
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
325
|
+
}
|
|
326
|
+
toString() {
|
|
327
|
+
return this.jsDate.toString();
|
|
328
|
+
}
|
|
329
|
+
getTime() {
|
|
330
|
+
return this.jsDate.getTime();
|
|
331
|
+
}
|
|
332
|
+
getFullYear() {
|
|
333
|
+
return this.jsDate.getUTCFullYear();
|
|
334
|
+
}
|
|
335
|
+
getMonth() {
|
|
336
|
+
return this.jsDate.getUTCMonth();
|
|
337
|
+
}
|
|
338
|
+
getDate() {
|
|
339
|
+
return this.jsDate.getUTCDate();
|
|
340
|
+
}
|
|
341
|
+
getDay() {
|
|
342
|
+
return this.jsDate.getUTCDay();
|
|
343
|
+
}
|
|
344
|
+
getHours() {
|
|
345
|
+
return this.jsDate.getUTCHours();
|
|
346
|
+
}
|
|
347
|
+
getMinutes() {
|
|
348
|
+
return this.jsDate.getUTCMinutes();
|
|
349
|
+
}
|
|
350
|
+
getSeconds() {
|
|
351
|
+
return this.jsDate.getUTCSeconds();
|
|
352
|
+
}
|
|
353
|
+
setFullYear(year) {
|
|
354
|
+
this.jsDate.setFullYear(year);
|
|
355
|
+
}
|
|
356
|
+
setDate(date) {
|
|
357
|
+
this.jsDate.setUTCDate(date);
|
|
358
|
+
}
|
|
359
|
+
setHours(hours) {
|
|
360
|
+
this.jsDate.setUTCHours(hours);
|
|
361
|
+
}
|
|
362
|
+
setMinutes(minutes) {
|
|
363
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
364
|
+
}
|
|
365
|
+
setSeconds(seconds) {
|
|
366
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
308
369
|
// -----------------------------------------------------------------------------
|
|
309
370
|
// Parsing
|
|
310
371
|
// -----------------------------------------------------------------------------
|
|
311
|
-
const INITIAL_1900_DAY = new
|
|
372
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
312
373
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
313
374
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
314
|
-
const CURRENT_YEAR =
|
|
315
|
-
const INITIAL_JS_DAY =
|
|
316
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
375
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
376
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
377
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
317
378
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
318
379
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
319
380
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -362,7 +423,7 @@ function _parseDateTime(str) {
|
|
|
362
423
|
return {
|
|
363
424
|
value: date.value + time.value,
|
|
364
425
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
365
|
-
jsDate: new
|
|
426
|
+
jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
|
|
366
427
|
};
|
|
367
428
|
}
|
|
368
429
|
return date || time;
|
|
@@ -379,13 +440,13 @@ function parseDate(str, dateFormat) {
|
|
|
379
440
|
const day = Number(parts[dayIndex]);
|
|
380
441
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
381
442
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
382
|
-
const jsDate = new
|
|
443
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
383
444
|
const sep = str.match(/\/|-|\s/)[0];
|
|
384
445
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
385
446
|
// invalid date
|
|
386
447
|
return null;
|
|
387
448
|
}
|
|
388
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
449
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
389
450
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
390
451
|
if (parts[yearIndex]) {
|
|
391
452
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -445,7 +506,7 @@ function parseTime(str) {
|
|
|
445
506
|
if (hours >= 24) {
|
|
446
507
|
format = "hhhh:mm:ss";
|
|
447
508
|
}
|
|
448
|
-
const jsDate = new
|
|
509
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
449
510
|
return {
|
|
450
511
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
451
512
|
format: format,
|
|
@@ -459,7 +520,7 @@ function parseTime(str) {
|
|
|
459
520
|
// -----------------------------------------------------------------------------
|
|
460
521
|
function numberToJsDate(value) {
|
|
461
522
|
const truncValue = Math.trunc(value);
|
|
462
|
-
let date =
|
|
523
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
463
524
|
let time = value - truncValue;
|
|
464
525
|
time = time < 0 ? 1 + time : time;
|
|
465
526
|
const hours = Math.round(time * 24);
|
|
@@ -476,7 +537,7 @@ function jsDateToRoundNumber(date) {
|
|
|
476
537
|
}
|
|
477
538
|
/** Return the number of days in the current month of the given date */
|
|
478
539
|
function getDaysInMonth(date) {
|
|
479
|
-
return new
|
|
540
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
480
541
|
}
|
|
481
542
|
function isLastDayOfMonth(date) {
|
|
482
543
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -494,7 +555,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
494
555
|
const yStart = date.getFullYear();
|
|
495
556
|
const mStart = date.getMonth();
|
|
496
557
|
const dStart = date.getDate();
|
|
497
|
-
const jsDate = new
|
|
558
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
498
559
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
499
560
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
500
561
|
}
|
|
@@ -622,13 +683,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
|
|
|
622
683
|
}
|
|
623
684
|
|
|
624
685
|
//------------------------------------------------------------------------------
|
|
625
|
-
/**
|
|
626
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
627
|
-
* is ordered.
|
|
628
|
-
*/
|
|
629
|
-
function stringify(obj) {
|
|
630
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
631
|
-
}
|
|
632
686
|
/**
|
|
633
687
|
* Remove quotes from a quoted string
|
|
634
688
|
* ```js
|
|
@@ -924,7 +978,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
924
978
|
*/
|
|
925
979
|
function getItemId(item, itemsDic) {
|
|
926
980
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
927
|
-
if (
|
|
981
|
+
if (deepEquals(value, item)) {
|
|
928
982
|
return parseInt(key, 10);
|
|
929
983
|
}
|
|
930
984
|
}
|
|
@@ -1060,6 +1114,22 @@ function transpose2dArray(matrix) {
|
|
|
1060
1114
|
if (!matrix.length)
|
|
1061
1115
|
return matrix;
|
|
1062
1116
|
return matrix[0].map((_, i) => matrix.map((row) => row[i]));
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Creates a version of the function that's memoized on the value of its first
|
|
1120
|
+
* argument, if any.
|
|
1121
|
+
*/
|
|
1122
|
+
function memoize(func) {
|
|
1123
|
+
const cache = new Map();
|
|
1124
|
+
const funcName = func.name ? func.name + " (memoized)" : "memoized";
|
|
1125
|
+
return {
|
|
1126
|
+
[funcName](...args) {
|
|
1127
|
+
if (!cache.has(args[0])) {
|
|
1128
|
+
cache.set(args[0], func(...args));
|
|
1129
|
+
}
|
|
1130
|
+
return cache.get(args[0]);
|
|
1131
|
+
},
|
|
1132
|
+
}[funcName];
|
|
1063
1133
|
}
|
|
1064
1134
|
|
|
1065
1135
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
@@ -1334,8 +1404,10 @@ function isSameColor(color1, color2) {
|
|
|
1334
1404
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
1335
1405
|
// Same as above, but matches the exact string (nothing before or after)
|
|
1336
1406
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
1337
|
-
/** Reference of a column header (eg. A, AB) */
|
|
1338
|
-
const colHeader = new RegExp(
|
|
1407
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
1408
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
1409
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
1410
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
1339
1411
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
1340
1412
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
1341
1413
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -1365,6 +1437,9 @@ function isRowReference(xc) {
|
|
|
1365
1437
|
function isColHeader(str) {
|
|
1366
1438
|
return colHeader.test(str);
|
|
1367
1439
|
}
|
|
1440
|
+
function isRowHeader(str) {
|
|
1441
|
+
return rowHeader.test(str);
|
|
1442
|
+
}
|
|
1368
1443
|
/**
|
|
1369
1444
|
* Return true if the given xc is the reference of a single cell,
|
|
1370
1445
|
* without any specified sheet (e.g. A1)
|
|
@@ -1863,7 +1938,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1863
1938
|
.map((p) => {
|
|
1864
1939
|
switch (p) {
|
|
1865
1940
|
case "hhhh":
|
|
1866
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
1941
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1867
1942
|
return helapsedHours.toString();
|
|
1868
1943
|
case "hh":
|
|
1869
1944
|
return hours.toString().padStart(2, "0");
|
|
@@ -2154,18 +2229,10 @@ class RangeImpl {
|
|
|
2154
2229
|
if (isFullCol) {
|
|
2155
2230
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2156
2231
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2157
|
-
if (zone.left === zone.right) {
|
|
2158
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2159
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2160
|
-
}
|
|
2161
2232
|
}
|
|
2162
2233
|
if (isFullRow) {
|
|
2163
2234
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2164
2235
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2165
|
-
if (zone.top === zone.bottom) {
|
|
2166
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2167
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2168
|
-
}
|
|
2169
2236
|
}
|
|
2170
2237
|
return parts;
|
|
2171
2238
|
}
|
|
@@ -3656,6 +3723,7 @@ var CommandResult;
|
|
|
3656
3723
|
CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
|
|
3657
3724
|
CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
|
|
3658
3725
|
CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
|
|
3726
|
+
CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
|
|
3659
3727
|
})(CommandResult || (CommandResult = {}));
|
|
3660
3728
|
|
|
3661
3729
|
function isMatrix(x) {
|
|
@@ -5691,6 +5759,7 @@ function getMenuDescription(node) {
|
|
|
5691
5759
|
return node.description ? node.description : "";
|
|
5692
5760
|
}
|
|
5693
5761
|
|
|
5762
|
+
const macRegex = /Mac/i;
|
|
5694
5763
|
/**
|
|
5695
5764
|
* Return true if the event was triggered from
|
|
5696
5765
|
* a child element.
|
|
@@ -5708,6 +5777,17 @@ function gridOverlayPosition() {
|
|
|
5708
5777
|
}
|
|
5709
5778
|
function getOpenedMenus() {
|
|
5710
5779
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5780
|
+
}
|
|
5781
|
+
function isMacOS() {
|
|
5782
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
5783
|
+
}
|
|
5784
|
+
/**
|
|
5785
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
5786
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
5787
|
+
* On Mac, this is the "meta" or "command" key.
|
|
5788
|
+
*/
|
|
5789
|
+
function isCtrlKey(ev) {
|
|
5790
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
5711
5791
|
}
|
|
5712
5792
|
|
|
5713
5793
|
/**
|
|
@@ -8019,12 +8099,12 @@ function toString(value) {
|
|
|
8019
8099
|
}
|
|
8020
8100
|
}
|
|
8021
8101
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
8022
|
-
function normalizeString(str) {
|
|
8102
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
8023
8103
|
return str
|
|
8024
8104
|
.toLowerCase()
|
|
8025
8105
|
.normalize("NFD")
|
|
8026
8106
|
.replace(/[\u0300-\u036f]/g, "");
|
|
8027
|
-
}
|
|
8107
|
+
});
|
|
8028
8108
|
/**
|
|
8029
8109
|
* Normalize a value.
|
|
8030
8110
|
* If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
|
|
@@ -10868,7 +10948,7 @@ const DATE = {
|
|
|
10868
10948
|
if (_year < 1900) {
|
|
10869
10949
|
_year += 1900;
|
|
10870
10950
|
}
|
|
10871
|
-
const jsDate = new
|
|
10951
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
10872
10952
|
const result = jsDateToRoundNumber(jsDate);
|
|
10873
10953
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
10874
10954
|
return result;
|
|
@@ -10980,7 +11060,7 @@ const EOMONTH = {
|
|
|
10980
11060
|
const _months = Math.trunc(toNumber(months));
|
|
10981
11061
|
const yStart = _startDate.getFullYear();
|
|
10982
11062
|
const mStart = _startDate.getMonth();
|
|
10983
|
-
const jsDate = new
|
|
11063
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
10984
11064
|
return jsDateToRoundNumber(jsDate);
|
|
10985
11065
|
},
|
|
10986
11066
|
isExported: true,
|
|
@@ -11019,17 +11099,17 @@ const ISOWEEKNUM = {
|
|
|
11019
11099
|
// The first week of the year is the week that contains the first
|
|
11020
11100
|
// Thursday of the year.
|
|
11021
11101
|
let firstThursday = 1;
|
|
11022
|
-
while (new
|
|
11102
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
11023
11103
|
firstThursday += 1;
|
|
11024
11104
|
}
|
|
11025
|
-
const firstDayOfFirstWeek = new
|
|
11105
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
11026
11106
|
// The last week of the year is the week that contains the last Thursday of
|
|
11027
11107
|
// the year.
|
|
11028
11108
|
let lastThursday = 31;
|
|
11029
|
-
while (new
|
|
11109
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
11030
11110
|
lastThursday -= 1;
|
|
11031
11111
|
}
|
|
11032
|
-
const lastDayOfLastWeek = new
|
|
11112
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
11033
11113
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
11034
11114
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
11035
11115
|
let offsetYear;
|
|
@@ -11055,17 +11135,17 @@ const ISOWEEKNUM = {
|
|
|
11055
11135
|
case 1:
|
|
11056
11136
|
// firstDay is the 1st day of the 1st week of the year after
|
|
11057
11137
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
11058
|
-
firstDay = new
|
|
11138
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
11059
11139
|
break;
|
|
11060
11140
|
case -1:
|
|
11061
11141
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
11062
11142
|
// The first week of the previous year is the week that contains the
|
|
11063
11143
|
// first Thursday of the previous year.
|
|
11064
11144
|
let firstThursdayPreviousYear = 1;
|
|
11065
|
-
while (new
|
|
11145
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
11066
11146
|
firstThursdayPreviousYear += 1;
|
|
11067
11147
|
}
|
|
11068
|
-
firstDay = new
|
|
11148
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
11069
11149
|
break;
|
|
11070
11150
|
}
|
|
11071
11151
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -11204,8 +11284,8 @@ const NETWORKDAYS_INTL = {
|
|
|
11204
11284
|
});
|
|
11205
11285
|
}
|
|
11206
11286
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
11207
|
-
const stopDate =
|
|
11208
|
-
let stepDate =
|
|
11287
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
11288
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
11209
11289
|
const timeStopDate = stopDate.getTime();
|
|
11210
11290
|
let timeStepDate = stepDate.getTime();
|
|
11211
11291
|
let netWorkingDay = 0;
|
|
@@ -11229,8 +11309,7 @@ const NOW = {
|
|
|
11229
11309
|
returns: ["DATE"],
|
|
11230
11310
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
11231
11311
|
compute: function () {
|
|
11232
|
-
let today =
|
|
11233
|
-
today.setMilliseconds(0);
|
|
11312
|
+
let today = DateTime.now();
|
|
11234
11313
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
11235
11314
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
11236
11315
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -11304,8 +11383,8 @@ const TODAY = {
|
|
|
11304
11383
|
returns: ["DATE"],
|
|
11305
11384
|
computeFormat: () => "m/d/yyyy",
|
|
11306
11385
|
compute: function () {
|
|
11307
|
-
const today =
|
|
11308
|
-
const jsDate = new
|
|
11386
|
+
const today = DateTime.now();
|
|
11387
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
11309
11388
|
return jsDateToRoundNumber(jsDate);
|
|
11310
11389
|
},
|
|
11311
11390
|
isExported: true,
|
|
@@ -11360,10 +11439,10 @@ const WEEKNUM = {
|
|
|
11360
11439
|
}
|
|
11361
11440
|
const y = _date.getFullYear();
|
|
11362
11441
|
let dayStart = 1;
|
|
11363
|
-
let startDayOfFirstWeek = new
|
|
11442
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
11364
11443
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
11365
11444
|
dayStart += 1;
|
|
11366
|
-
startDayOfFirstWeek = new
|
|
11445
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
11367
11446
|
}
|
|
11368
11447
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
11369
11448
|
if (dif < 0) {
|
|
@@ -11417,7 +11496,7 @@ const WORKDAY_INTL = {
|
|
|
11417
11496
|
timesHoliday.add(holiday.getTime());
|
|
11418
11497
|
});
|
|
11419
11498
|
}
|
|
11420
|
-
let stepDate =
|
|
11499
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
11421
11500
|
let timeStepDate = stepDate.getTime();
|
|
11422
11501
|
const unitDay = Math.sign(_numDays);
|
|
11423
11502
|
let stepDay = Math.abs(_numDays);
|
|
@@ -11483,7 +11562,7 @@ const MONTH_START = {
|
|
|
11483
11562
|
const _startDate = toJsDate(date);
|
|
11484
11563
|
const yStart = _startDate.getFullYear();
|
|
11485
11564
|
const mStart = _startDate.getMonth();
|
|
11486
|
-
const jsDate = new
|
|
11565
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
11487
11566
|
return jsDateToRoundNumber(jsDate);
|
|
11488
11567
|
},
|
|
11489
11568
|
};
|
|
@@ -11527,7 +11606,7 @@ const QUARTER_START = {
|
|
|
11527
11606
|
compute: function (date) {
|
|
11528
11607
|
const quarter = QUARTER.compute(date);
|
|
11529
11608
|
const year = YEAR.compute(date);
|
|
11530
|
-
const jsDate = new
|
|
11609
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
11531
11610
|
return jsDateToRoundNumber(jsDate);
|
|
11532
11611
|
},
|
|
11533
11612
|
};
|
|
@@ -11544,7 +11623,7 @@ const QUARTER_END = {
|
|
|
11544
11623
|
compute: function (date) {
|
|
11545
11624
|
const quarter = QUARTER.compute(date);
|
|
11546
11625
|
const year = YEAR.compute(date);
|
|
11547
|
-
const jsDate = new
|
|
11626
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
11548
11627
|
return jsDateToRoundNumber(jsDate);
|
|
11549
11628
|
},
|
|
11550
11629
|
};
|
|
@@ -11560,7 +11639,7 @@ const YEAR_START = {
|
|
|
11560
11639
|
computeFormat: () => "m/d/yyyy",
|
|
11561
11640
|
compute: function (date) {
|
|
11562
11641
|
const year = YEAR.compute(date);
|
|
11563
|
-
const jsDate = new
|
|
11642
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
11564
11643
|
return jsDateToRoundNumber(jsDate);
|
|
11565
11644
|
},
|
|
11566
11645
|
};
|
|
@@ -11576,7 +11655,7 @@ const YEAR_END = {
|
|
|
11576
11655
|
computeFormat: () => "m/d/yyyy",
|
|
11577
11656
|
compute: function (date) {
|
|
11578
11657
|
const year = YEAR.compute(date);
|
|
11579
|
-
const jsDate = new
|
|
11658
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
11580
11659
|
return jsDateToRoundNumber(jsDate);
|
|
11581
11660
|
},
|
|
11582
11661
|
};
|
|
@@ -11710,7 +11789,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
11710
11789
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
11711
11790
|
const startDate = toJsDate(settlement);
|
|
11712
11791
|
const endDate = toJsDate(maturity);
|
|
11713
|
-
const startDatePlusOneYear =
|
|
11792
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
11714
11793
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
11715
11794
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
11716
11795
|
}
|
|
@@ -15636,7 +15715,7 @@ const machine = {
|
|
|
15636
15715
|
SPACE: goTo(State.RightRef),
|
|
15637
15716
|
NUMBER: goTo(State.Found),
|
|
15638
15717
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
15639
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
15718
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
15640
15719
|
},
|
|
15641
15720
|
[State.RightColumnRef]: {
|
|
15642
15721
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -15647,6 +15726,7 @@ const machine = {
|
|
|
15647
15726
|
SPACE: goTo(State.RightRowRef),
|
|
15648
15727
|
NUMBER: goTo(State.Found),
|
|
15649
15728
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
15729
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
15650
15730
|
},
|
|
15651
15731
|
[State.Found]: {},
|
|
15652
15732
|
};
|
|
@@ -16156,6 +16236,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
16156
16236
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
16157
16237
|
case "colrow":
|
|
16158
16238
|
indexOfNumber = xc.search(/[0-9]/);
|
|
16239
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
16240
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
16241
|
+
return "$" + xc;
|
|
16242
|
+
}
|
|
16159
16243
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
16160
16244
|
return "$" + xc;
|
|
16161
16245
|
case "none":
|
|
@@ -16929,10 +17013,10 @@ const arrowMap = {
|
|
|
16929
17013
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
16930
17014
|
const direction = arrowMap[ev.key];
|
|
16931
17015
|
if (ev.shiftKey) {
|
|
16932
|
-
selection.resizeAnchorZone(direction, ev
|
|
17016
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
16933
17017
|
}
|
|
16934
17018
|
else {
|
|
16935
|
-
selection.moveAnchorCell(direction, ev
|
|
17019
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
16936
17020
|
}
|
|
16937
17021
|
}
|
|
16938
17022
|
|
|
@@ -22589,7 +22673,10 @@ class GridOverlay extends Component {
|
|
|
22589
22673
|
return;
|
|
22590
22674
|
}
|
|
22591
22675
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
22592
|
-
this.props.onCellClicked(col, row, {
|
|
22676
|
+
this.props.onCellClicked(col, row, {
|
|
22677
|
+
expandZone: ev.shiftKey,
|
|
22678
|
+
addZone: isCtrlKey(ev),
|
|
22679
|
+
});
|
|
22593
22680
|
}
|
|
22594
22681
|
onDoubleClick(ev) {
|
|
22595
22682
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -22677,6 +22764,7 @@ class AbstractResizer extends Component {
|
|
|
22677
22764
|
draggerShadowThickness: 0,
|
|
22678
22765
|
delta: 0,
|
|
22679
22766
|
base: 0,
|
|
22767
|
+
position: "before",
|
|
22680
22768
|
});
|
|
22681
22769
|
}
|
|
22682
22770
|
_computeHandleDisplay(ev) {
|
|
@@ -22802,11 +22890,13 @@ class AbstractResizer extends Component {
|
|
|
22802
22890
|
this.state.draggerLinePosition = dimensions.start;
|
|
22803
22891
|
this.state.draggerShadowPosition = dimensions.start;
|
|
22804
22892
|
this.state.base = elementIndex;
|
|
22893
|
+
this.state.position = "before";
|
|
22805
22894
|
}
|
|
22806
22895
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
22807
22896
|
this.state.draggerLinePosition = dimensions.end;
|
|
22808
22897
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
22809
|
-
this.state.base = elementIndex
|
|
22898
|
+
this.state.base = elementIndex;
|
|
22899
|
+
this.state.position = "after";
|
|
22810
22900
|
}
|
|
22811
22901
|
else {
|
|
22812
22902
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -22830,7 +22920,7 @@ class AbstractResizer extends Component {
|
|
|
22830
22920
|
this._increaseSelection(index);
|
|
22831
22921
|
}
|
|
22832
22922
|
else {
|
|
22833
|
-
this._selectElement(index, ev
|
|
22923
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
22834
22924
|
}
|
|
22835
22925
|
this.lastSelectedElementIndex = index;
|
|
22836
22926
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -22843,7 +22933,7 @@ class AbstractResizer extends Component {
|
|
|
22843
22933
|
const mouseUpSelect = () => {
|
|
22844
22934
|
this.state.isSelecting = false;
|
|
22845
22935
|
this.lastSelectedElementIndex = null;
|
|
22846
|
-
this.env.model.dispatch(ev
|
|
22936
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
22847
22937
|
this._computeGrabDisplay(ev);
|
|
22848
22938
|
};
|
|
22849
22939
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -22987,13 +23077,14 @@ class ColResizer extends AbstractResizer {
|
|
|
22987
23077
|
dimension: "COL",
|
|
22988
23078
|
base: this.state.base,
|
|
22989
23079
|
elements,
|
|
23080
|
+
position: this.state.position,
|
|
22990
23081
|
});
|
|
22991
23082
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22992
23083
|
this.env.raiseError(MergeErrorMessage);
|
|
22993
23084
|
}
|
|
22994
23085
|
}
|
|
22995
|
-
_selectElement(index,
|
|
22996
|
-
this.env.model.selection.selectColumn(index,
|
|
23086
|
+
_selectElement(index, addDistinctHeader) {
|
|
23087
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22997
23088
|
}
|
|
22998
23089
|
_increaseSelection(index) {
|
|
22999
23090
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -23159,13 +23250,14 @@ class RowResizer extends AbstractResizer {
|
|
|
23159
23250
|
dimension: "ROW",
|
|
23160
23251
|
base: this.state.base,
|
|
23161
23252
|
elements,
|
|
23253
|
+
position: this.state.position,
|
|
23162
23254
|
});
|
|
23163
23255
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
23164
23256
|
this.env.raiseError(MergeErrorMessage);
|
|
23165
23257
|
}
|
|
23166
23258
|
}
|
|
23167
|
-
_selectElement(index,
|
|
23168
|
-
this.env.model.selection.selectRow(index,
|
|
23259
|
+
_selectElement(index, addDistinctHeader) {
|
|
23260
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
23169
23261
|
}
|
|
23170
23262
|
_increaseSelection(index) {
|
|
23171
23263
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -23267,8 +23359,8 @@ function useWheelHandler(handler) {
|
|
|
23267
23359
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
23268
23360
|
}
|
|
23269
23361
|
const onMouseWheel = (ev) => {
|
|
23270
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23271
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23362
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23363
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23272
23364
|
handler(deltaX, deltaY);
|
|
23273
23365
|
};
|
|
23274
23366
|
return onMouseWheel;
|
|
@@ -23912,8 +24004,8 @@ class Grid extends Component {
|
|
|
23912
24004
|
// ---------------------------------------------------------------------------
|
|
23913
24005
|
// Zone selection with mouse
|
|
23914
24006
|
// ---------------------------------------------------------------------------
|
|
23915
|
-
onCellClicked(col, row, {
|
|
23916
|
-
if (
|
|
24007
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
24008
|
+
if (addZone) {
|
|
23917
24009
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
23918
24010
|
}
|
|
23919
24011
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
@@ -23922,10 +24014,10 @@ class Grid extends Component {
|
|
|
23922
24014
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
23923
24015
|
this.env.model.dispatch("STOP_EDITION");
|
|
23924
24016
|
}
|
|
23925
|
-
if (
|
|
24017
|
+
if (expandZone) {
|
|
23926
24018
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
23927
24019
|
}
|
|
23928
|
-
else if (
|
|
24020
|
+
else if (addZone) {
|
|
23929
24021
|
this.env.model.selection.addCellToSelection(col, row);
|
|
23930
24022
|
}
|
|
23931
24023
|
else {
|
|
@@ -23987,9 +24079,7 @@ class Grid extends Component {
|
|
|
23987
24079
|
return;
|
|
23988
24080
|
}
|
|
23989
24081
|
let keyDownString = "";
|
|
23990
|
-
if (ev
|
|
23991
|
-
keyDownString += "CTRL+";
|
|
23992
|
-
if (ev.metaKey)
|
|
24082
|
+
if (isCtrlKey(ev))
|
|
23993
24083
|
keyDownString += "CTRL+";
|
|
23994
24084
|
if (ev.altKey)
|
|
23995
24085
|
keyDownString += "ALT+";
|
|
@@ -27941,6 +28031,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
27941
28031
|
// ---------------------------------------------------------------------------
|
|
27942
28032
|
// Command Handling
|
|
27943
28033
|
// ---------------------------------------------------------------------------
|
|
28034
|
+
allowDispatch(cmd) {
|
|
28035
|
+
switch (cmd.type) {
|
|
28036
|
+
case "SET_BORDER":
|
|
28037
|
+
return this.checkBordersUnchanged(cmd);
|
|
28038
|
+
default:
|
|
28039
|
+
return 0 /* CommandResult.Success */;
|
|
28040
|
+
}
|
|
28041
|
+
}
|
|
27944
28042
|
handle(cmd) {
|
|
27945
28043
|
switch (cmd.type) {
|
|
27946
28044
|
case "ADD_MERGE":
|
|
@@ -28336,6 +28434,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
28336
28434
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right");
|
|
28337
28435
|
}
|
|
28338
28436
|
}
|
|
28437
|
+
checkBordersUnchanged(cmd) {
|
|
28438
|
+
var _a, _b, _c, _d;
|
|
28439
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
28440
|
+
const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
|
|
28441
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
28442
|
+
return 88 /* CommandResult.NoChanges */;
|
|
28443
|
+
}
|
|
28444
|
+
return 0 /* CommandResult.Success */;
|
|
28445
|
+
}
|
|
28339
28446
|
// ---------------------------------------------------------------------------
|
|
28340
28447
|
// Import/Export
|
|
28341
28448
|
// ---------------------------------------------------------------------------
|
|
@@ -28371,7 +28478,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
28371
28478
|
*/
|
|
28372
28479
|
function getBorderId(border) {
|
|
28373
28480
|
for (let [key, value] of Object.entries(borders)) {
|
|
28374
|
-
if (
|
|
28481
|
+
if (deepEquals(value, border)) {
|
|
28375
28482
|
return parseInt(key, 10);
|
|
28376
28483
|
}
|
|
28377
28484
|
}
|
|
@@ -28439,8 +28546,9 @@ class CellPlugin extends CorePlugin {
|
|
|
28439
28546
|
allowDispatch(cmd) {
|
|
28440
28547
|
switch (cmd.type) {
|
|
28441
28548
|
case "UPDATE_CELL":
|
|
28549
|
+
return this.checkCellOutOfSheet(cmd);
|
|
28442
28550
|
case "CLEAR_CELL":
|
|
28443
|
-
return this.
|
|
28551
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
28444
28552
|
default:
|
|
28445
28553
|
return 0 /* CommandResult.Success */;
|
|
28446
28554
|
}
|
|
@@ -28599,14 +28707,9 @@ class CellPlugin extends CorePlugin {
|
|
|
28599
28707
|
*/
|
|
28600
28708
|
getCellById(cellId) {
|
|
28601
28709
|
// this must be as fast as possible
|
|
28602
|
-
|
|
28603
|
-
|
|
28604
|
-
|
|
28605
|
-
if (cell) {
|
|
28606
|
-
return cell;
|
|
28607
|
-
}
|
|
28608
|
-
}
|
|
28609
|
-
return undefined;
|
|
28710
|
+
const position = this.getters.getCellPosition(cellId);
|
|
28711
|
+
const sheet = this.cells[position.sheetId];
|
|
28712
|
+
return sheet[cellId];
|
|
28610
28713
|
}
|
|
28611
28714
|
/*
|
|
28612
28715
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -28847,13 +28950,23 @@ class CellPlugin extends CorePlugin {
|
|
|
28847
28950
|
dependencies: [],
|
|
28848
28951
|
};
|
|
28849
28952
|
}
|
|
28850
|
-
checkCellOutOfSheet(
|
|
28953
|
+
checkCellOutOfSheet(cmd) {
|
|
28954
|
+
const { sheetId, col, row } = cmd;
|
|
28851
28955
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
28852
28956
|
if (!sheet)
|
|
28853
28957
|
return 27 /* CommandResult.InvalidSheetId */;
|
|
28854
28958
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
28855
28959
|
return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
|
|
28856
28960
|
}
|
|
28961
|
+
checkUselessClearCell(cmd) {
|
|
28962
|
+
const cell = this.getters.getCell(cmd);
|
|
28963
|
+
if (!cell)
|
|
28964
|
+
return 88 /* CommandResult.NoChanges */;
|
|
28965
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
28966
|
+
return 88 /* CommandResult.NoChanges */;
|
|
28967
|
+
}
|
|
28968
|
+
return 0 /* CommandResult.Success */;
|
|
28969
|
+
}
|
|
28857
28970
|
}
|
|
28858
28971
|
CellPlugin.getters = [
|
|
28859
28972
|
"zoneToXC",
|
|
@@ -31314,7 +31427,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
31314
31427
|
const elements = cmd.dimension === "COL"
|
|
31315
31428
|
? this.getNumberCols(cmd.sheetId)
|
|
31316
31429
|
: this.getNumberRows(cmd.sheetId);
|
|
31317
|
-
if (cmd.base < 0 || cmd.base
|
|
31430
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
31318
31431
|
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
31319
31432
|
}
|
|
31320
31433
|
else if (cmd.quantity <= 0) {
|
|
@@ -31914,10 +32027,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
31914
32027
|
// begin with the end.
|
|
31915
32028
|
rows.sort((a, b) => b - a);
|
|
31916
32029
|
for (let group of groupConsecutive(rows)) {
|
|
32030
|
+
// indexes are sorted in the descending order
|
|
32031
|
+
const from = group[group.length - 1];
|
|
32032
|
+
const to = group[0];
|
|
31917
32033
|
// Move the cells.
|
|
31918
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
31919
|
-
// Effectively delete the
|
|
31920
|
-
|
|
32034
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
32035
|
+
// Effectively delete the rows
|
|
32036
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
31921
32037
|
}
|
|
31922
32038
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
31923
32039
|
if (count) {
|
|
@@ -31939,8 +32055,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
31939
32055
|
this.addEmptyRows(sheet, quantity);
|
|
31940
32056
|
// Move the cells.
|
|
31941
32057
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
31942
|
-
// Recompute the left-right/top-bottom.
|
|
31943
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
31944
32058
|
if (index < sheet.panes.ySplit) {
|
|
31945
32059
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
31946
32060
|
}
|
|
@@ -32041,35 +32155,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
32041
32155
|
}
|
|
32042
32156
|
}
|
|
32043
32157
|
}
|
|
32044
|
-
updateRowsStructureOnDeletion(
|
|
32158
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
32045
32159
|
const rows = [];
|
|
32046
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
32160
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
32047
32161
|
for (let i in sheet.rows) {
|
|
32048
|
-
|
|
32162
|
+
const row = Number(i);
|
|
32163
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
32049
32164
|
continue;
|
|
32050
32165
|
}
|
|
32051
32166
|
rows.push({
|
|
32052
|
-
cells: cellsQueue.
|
|
32167
|
+
cells: cellsQueue.pop(),
|
|
32053
32168
|
});
|
|
32054
32169
|
}
|
|
32055
32170
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
32056
32171
|
}
|
|
32057
|
-
/**
|
|
32058
|
-
* Update the rows of the sheet after an addition:
|
|
32059
|
-
* - Rename the rows
|
|
32060
|
-
*
|
|
32061
|
-
* @param sheet Sheet on which the deletion occurs
|
|
32062
|
-
* @param addedRow Index of the added row
|
|
32063
|
-
* @param rowsToAdd Number of the rows to add
|
|
32064
|
-
*/
|
|
32065
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
32066
|
-
const rows = [];
|
|
32067
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
32068
|
-
sheet.rows.forEach(() => rows.push({
|
|
32069
|
-
cells: cellsQueue.shift(),
|
|
32070
|
-
}));
|
|
32071
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
32072
|
-
}
|
|
32073
32172
|
/**
|
|
32074
32173
|
* Add empty rows at the end of the rows
|
|
32075
32174
|
*
|
|
@@ -32351,13 +32450,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32351
32450
|
// Getters
|
|
32352
32451
|
// ---------------------------------------------------------------------------
|
|
32353
32452
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
32354
|
-
|
|
32355
|
-
|
|
32356
|
-
|
|
32357
|
-
|
|
32358
|
-
|
|
32453
|
+
try {
|
|
32454
|
+
const compiledFormula = compile(formulaString);
|
|
32455
|
+
const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
|
|
32456
|
+
const ranges = [];
|
|
32457
|
+
for (let xc of compiledFormula.dependencies) {
|
|
32458
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
32459
|
+
}
|
|
32460
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
32461
|
+
}
|
|
32462
|
+
catch (error) {
|
|
32463
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
32359
32464
|
}
|
|
32360
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
32361
32465
|
}
|
|
32362
32466
|
/**
|
|
32363
32467
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -32526,6 +32630,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32526
32630
|
}
|
|
32527
32631
|
return evaluatedCell;
|
|
32528
32632
|
};
|
|
32633
|
+
const rangeCache = {};
|
|
32529
32634
|
/**
|
|
32530
32635
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
32531
32636
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -32542,21 +32647,26 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32542
32647
|
// Performance issue: Avoid fetching data on positions that are out of the spreadsheet
|
|
32543
32648
|
// e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
|
|
32544
32649
|
const sheetZone = getters.getSheetZone(sheetId);
|
|
32545
|
-
const result = [];
|
|
32546
32650
|
const zone = intersection(range.zone, sheetZone);
|
|
32547
32651
|
if (!zone) {
|
|
32548
|
-
|
|
32549
|
-
return result;
|
|
32652
|
+
return [[]];
|
|
32550
32653
|
}
|
|
32654
|
+
const { top, left, bottom, right } = zone;
|
|
32655
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
32656
|
+
if (cacheKey in rangeCache) {
|
|
32657
|
+
return rangeCache[cacheKey];
|
|
32658
|
+
}
|
|
32659
|
+
const result = new Array(right - left + 1);
|
|
32551
32660
|
// Performance issue: nested loop is faster than a map here
|
|
32552
|
-
for (let col =
|
|
32553
|
-
const rowValues =
|
|
32554
|
-
for (let row =
|
|
32661
|
+
for (let col = left; col <= right; col++) {
|
|
32662
|
+
const rowValues = new Array(bottom - top + 1);
|
|
32663
|
+
for (let row = top; row <= bottom; row++) {
|
|
32555
32664
|
const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
|
|
32556
|
-
rowValues
|
|
32665
|
+
rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
|
|
32557
32666
|
}
|
|
32558
|
-
result
|
|
32667
|
+
result[col - left] = rowValues;
|
|
32559
32668
|
}
|
|
32669
|
+
rangeCache[cacheKey] = result;
|
|
32560
32670
|
return result;
|
|
32561
32671
|
}
|
|
32562
32672
|
/**
|
|
@@ -32843,39 +32953,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32843
32953
|
this.computedIcons[sheetId] = {};
|
|
32844
32954
|
const computedStyle = this.computedStyles[sheetId];
|
|
32845
32955
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
32846
|
-
|
|
32847
|
-
|
|
32848
|
-
|
|
32849
|
-
|
|
32850
|
-
|
|
32851
|
-
|
|
32852
|
-
|
|
32853
|
-
|
|
32854
|
-
|
|
32855
|
-
|
|
32856
|
-
|
|
32857
|
-
|
|
32858
|
-
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
for (let
|
|
32862
|
-
|
|
32863
|
-
|
|
32864
|
-
|
|
32865
|
-
if (
|
|
32866
|
-
|
|
32867
|
-
|
|
32868
|
-
|
|
32869
|
-
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32870
|
-
}
|
|
32956
|
+
switch (cf.rule.type) {
|
|
32957
|
+
case "ColorScaleRule":
|
|
32958
|
+
for (let range of cf.ranges) {
|
|
32959
|
+
this.applyColorScale(range, cf.rule);
|
|
32960
|
+
}
|
|
32961
|
+
break;
|
|
32962
|
+
case "IconSetRule":
|
|
32963
|
+
for (let range of cf.ranges) {
|
|
32964
|
+
this.applyIcon(range, cf.rule);
|
|
32965
|
+
}
|
|
32966
|
+
break;
|
|
32967
|
+
default:
|
|
32968
|
+
for (let ref of cf.ranges) {
|
|
32969
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
32970
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
32971
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
32972
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
32973
|
+
let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
32974
|
+
if (pr && pr(cell, cf.rule)) {
|
|
32975
|
+
if (!computedStyle[col])
|
|
32976
|
+
computedStyle[col] = [];
|
|
32977
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
32978
|
+
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32871
32979
|
}
|
|
32872
32980
|
}
|
|
32873
32981
|
}
|
|
32874
|
-
|
|
32875
|
-
|
|
32876
|
-
}
|
|
32877
|
-
catch (_) {
|
|
32878
|
-
// we don't care about the errors within the evaluation of a rule
|
|
32982
|
+
}
|
|
32983
|
+
break;
|
|
32879
32984
|
}
|
|
32880
32985
|
}
|
|
32881
32986
|
}
|
|
@@ -32900,7 +33005,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32900
33005
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
32901
33006
|
case "formula":
|
|
32902
33007
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
32903
|
-
return
|
|
33008
|
+
return typeof value === "number" ? value : null;
|
|
32904
33009
|
default:
|
|
32905
33010
|
return null;
|
|
32906
33011
|
}
|
|
@@ -34462,24 +34567,27 @@ class AutofillPlugin extends UIPlugin {
|
|
|
34462
34567
|
* autofiller
|
|
34463
34568
|
*/
|
|
34464
34569
|
autofillAuto() {
|
|
34570
|
+
var _a, _b;
|
|
34465
34571
|
const zone = this.getters.getSelectedZone();
|
|
34466
34572
|
const sheetId = this.getters.getActiveSheetId();
|
|
34467
34573
|
let col = zone.left;
|
|
34468
34574
|
let row = zone.bottom;
|
|
34469
34575
|
if (col > 0) {
|
|
34470
|
-
let
|
|
34471
|
-
while (
|
|
34576
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
34577
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
34578
|
+
((_a = this.getters.getCell(leftPosition)) === null || _a === void 0 ? void 0 : _a.content)) {
|
|
34472
34579
|
row += 1;
|
|
34473
|
-
|
|
34580
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
34474
34581
|
}
|
|
34475
34582
|
}
|
|
34476
34583
|
if (row === zone.bottom) {
|
|
34477
34584
|
col = zone.right;
|
|
34478
34585
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
34479
|
-
let
|
|
34480
|
-
while (
|
|
34586
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
34587
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
34588
|
+
((_b = this.getters.getCell(rightPosition)) === null || _b === void 0 ? void 0 : _b.content)) {
|
|
34481
34589
|
row += 1;
|
|
34482
|
-
|
|
34590
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
34483
34591
|
}
|
|
34484
34592
|
}
|
|
34485
34593
|
}
|
|
@@ -39211,7 +39319,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
39211
39319
|
sheetId: cmd.sheetId,
|
|
39212
39320
|
base: cmd.base,
|
|
39213
39321
|
quantity: thickness,
|
|
39214
|
-
position:
|
|
39322
|
+
position: cmd.position,
|
|
39215
39323
|
});
|
|
39216
39324
|
const isCol = cmd.dimension === "COL";
|
|
39217
39325
|
const start = cmd.elements[0];
|
|
@@ -39228,12 +39336,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
39228
39336
|
},
|
|
39229
39337
|
];
|
|
39230
39338
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
39339
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
39231
39340
|
const pasteTarget = [
|
|
39232
39341
|
{
|
|
39233
|
-
left: isCol ?
|
|
39234
|
-
right: isCol ?
|
|
39235
|
-
top: !isCol ?
|
|
39236
|
-
bottom: !isCol ?
|
|
39342
|
+
left: isCol ? base : 0,
|
|
39343
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
39344
|
+
top: !isCol ? base : 0,
|
|
39345
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
39237
39346
|
},
|
|
39238
39347
|
];
|
|
39239
39348
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -39270,6 +39379,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
39270
39379
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
39271
39380
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
39272
39381
|
}
|
|
39382
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
39383
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
39384
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
39385
|
+
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
39386
|
+
}
|
|
39273
39387
|
return 0 /* CommandResult.Success */;
|
|
39274
39388
|
}
|
|
39275
39389
|
//-------------------------------------------
|
|
@@ -40823,7 +40937,7 @@ class Spreadsheet extends Component {
|
|
|
40823
40937
|
}
|
|
40824
40938
|
onKeydown(ev) {
|
|
40825
40939
|
let keyDownString = "";
|
|
40826
|
-
if (ev
|
|
40940
|
+
if (isCtrlKey(ev)) {
|
|
40827
40941
|
keyDownString += "CTRL+";
|
|
40828
40942
|
}
|
|
40829
40943
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -41670,9 +41784,9 @@ function revertChanges(revisions) {
|
|
|
41670
41784
|
* Apply the changes of the given HistoryChange to the state
|
|
41671
41785
|
*/
|
|
41672
41786
|
function applyChange(change, target) {
|
|
41673
|
-
let val = change.
|
|
41674
|
-
|
|
41675
|
-
for (let pathIndex =
|
|
41787
|
+
let val = change.path[0];
|
|
41788
|
+
const key = change.path[change.path.length - 1];
|
|
41789
|
+
for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
|
|
41676
41790
|
const p = change.path[pathIndex];
|
|
41677
41791
|
if (val[p] === undefined) {
|
|
41678
41792
|
const nextPath = change.path[pathIndex + 1];
|
|
@@ -42427,13 +42541,14 @@ class StateObserver {
|
|
|
42427
42541
|
}
|
|
42428
42542
|
addChange(...args) {
|
|
42429
42543
|
const val = args.pop();
|
|
42430
|
-
const
|
|
42544
|
+
const root = args[0];
|
|
42431
42545
|
let value = root;
|
|
42432
|
-
let key =
|
|
42433
|
-
|
|
42434
|
-
|
|
42546
|
+
let key = args[args.length - 1];
|
|
42547
|
+
const pathLength = args.length - 2;
|
|
42548
|
+
for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
|
|
42549
|
+
const p = args[pathIndex];
|
|
42435
42550
|
if (value[p] === undefined) {
|
|
42436
|
-
const nextPath =
|
|
42551
|
+
const nextPath = args[pathIndex + 1];
|
|
42437
42552
|
value[p] = createEmptyStructure(nextPath);
|
|
42438
42553
|
}
|
|
42439
42554
|
value = value[p];
|
|
@@ -42442,8 +42557,7 @@ class StateObserver {
|
|
|
42442
42557
|
return;
|
|
42443
42558
|
}
|
|
42444
42559
|
this.changes.push({
|
|
42445
|
-
|
|
42446
|
-
path,
|
|
42560
|
+
path: args,
|
|
42447
42561
|
before: value[key],
|
|
42448
42562
|
after: val,
|
|
42449
42563
|
});
|
|
@@ -44217,7 +44331,10 @@ class Model extends EventBus {
|
|
|
44217
44331
|
*/
|
|
44218
44332
|
checkDispatchAllowed(command) {
|
|
44219
44333
|
const results = this.handlers.map((handler) => handler.allowDispatch(command));
|
|
44220
|
-
|
|
44334
|
+
if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
|
|
44335
|
+
return new DispatchResult(results.flat());
|
|
44336
|
+
}
|
|
44337
|
+
return DispatchResult.Success;
|
|
44221
44338
|
}
|
|
44222
44339
|
finalize() {
|
|
44223
44340
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -44417,6 +44534,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
44417
44534
|
export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, links, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
|
|
44418
44535
|
|
|
44419
44536
|
|
|
44420
|
-
__info__.version = '16.1.
|
|
44421
|
-
__info__.date = '
|
|
44422
|
-
__info__.hash = '
|
|
44537
|
+
__info__.version = '16.1.31';
|
|
44538
|
+
__info__.date = '2024-01-12T13:42:11.001Z';
|
|
44539
|
+
__info__.hash = 'f51befa';
|