@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
|
@@ -309,15 +309,76 @@ for (let font of fontSizes) {
|
|
|
309
309
|
// -----------------------------------------------------------------------------
|
|
310
310
|
// Date Type
|
|
311
311
|
// -----------------------------------------------------------------------------
|
|
312
|
+
/**
|
|
313
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
314
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
315
|
+
* and it is timezone-agnostic.
|
|
316
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
317
|
+
*/
|
|
318
|
+
class DateTime {
|
|
319
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
320
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
321
|
+
}
|
|
322
|
+
static fromTimestamp(timestamp) {
|
|
323
|
+
const date = new Date(timestamp);
|
|
324
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
325
|
+
}
|
|
326
|
+
static now() {
|
|
327
|
+
const now = new Date();
|
|
328
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
329
|
+
}
|
|
330
|
+
toString() {
|
|
331
|
+
return this.jsDate.toString();
|
|
332
|
+
}
|
|
333
|
+
getTime() {
|
|
334
|
+
return this.jsDate.getTime();
|
|
335
|
+
}
|
|
336
|
+
getFullYear() {
|
|
337
|
+
return this.jsDate.getUTCFullYear();
|
|
338
|
+
}
|
|
339
|
+
getMonth() {
|
|
340
|
+
return this.jsDate.getUTCMonth();
|
|
341
|
+
}
|
|
342
|
+
getDate() {
|
|
343
|
+
return this.jsDate.getUTCDate();
|
|
344
|
+
}
|
|
345
|
+
getDay() {
|
|
346
|
+
return this.jsDate.getUTCDay();
|
|
347
|
+
}
|
|
348
|
+
getHours() {
|
|
349
|
+
return this.jsDate.getUTCHours();
|
|
350
|
+
}
|
|
351
|
+
getMinutes() {
|
|
352
|
+
return this.jsDate.getUTCMinutes();
|
|
353
|
+
}
|
|
354
|
+
getSeconds() {
|
|
355
|
+
return this.jsDate.getUTCSeconds();
|
|
356
|
+
}
|
|
357
|
+
setFullYear(year) {
|
|
358
|
+
this.jsDate.setFullYear(year);
|
|
359
|
+
}
|
|
360
|
+
setDate(date) {
|
|
361
|
+
this.jsDate.setUTCDate(date);
|
|
362
|
+
}
|
|
363
|
+
setHours(hours) {
|
|
364
|
+
this.jsDate.setUTCHours(hours);
|
|
365
|
+
}
|
|
366
|
+
setMinutes(minutes) {
|
|
367
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
368
|
+
}
|
|
369
|
+
setSeconds(seconds) {
|
|
370
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
312
373
|
// -----------------------------------------------------------------------------
|
|
313
374
|
// Parsing
|
|
314
375
|
// -----------------------------------------------------------------------------
|
|
315
|
-
const INITIAL_1900_DAY = new
|
|
376
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
316
377
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
317
378
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
318
|
-
const CURRENT_YEAR =
|
|
319
|
-
const INITIAL_JS_DAY =
|
|
320
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
379
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
380
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
381
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
321
382
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
322
383
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
323
384
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -366,7 +427,7 @@ function _parseDateTime(str) {
|
|
|
366
427
|
return {
|
|
367
428
|
value: date.value + time.value,
|
|
368
429
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
369
|
-
jsDate: new
|
|
430
|
+
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()),
|
|
370
431
|
};
|
|
371
432
|
}
|
|
372
433
|
return date || time;
|
|
@@ -383,13 +444,13 @@ function parseDate(str, dateFormat) {
|
|
|
383
444
|
const day = Number(parts[dayIndex]);
|
|
384
445
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
385
446
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
386
|
-
const jsDate = new
|
|
447
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
387
448
|
const sep = str.match(/\/|-|\s/)[0];
|
|
388
449
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
389
450
|
// invalid date
|
|
390
451
|
return null;
|
|
391
452
|
}
|
|
392
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
453
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
393
454
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
394
455
|
if (parts[yearIndex]) {
|
|
395
456
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -449,7 +510,7 @@ function parseTime(str) {
|
|
|
449
510
|
if (hours >= 24) {
|
|
450
511
|
format = "hhhh:mm:ss";
|
|
451
512
|
}
|
|
452
|
-
const jsDate = new
|
|
513
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
453
514
|
return {
|
|
454
515
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
455
516
|
format: format,
|
|
@@ -463,7 +524,7 @@ function parseTime(str) {
|
|
|
463
524
|
// -----------------------------------------------------------------------------
|
|
464
525
|
function numberToJsDate(value) {
|
|
465
526
|
const truncValue = Math.trunc(value);
|
|
466
|
-
let date =
|
|
527
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
467
528
|
let time = value - truncValue;
|
|
468
529
|
time = time < 0 ? 1 + time : time;
|
|
469
530
|
const hours = Math.round(time * 24);
|
|
@@ -480,7 +541,7 @@ function jsDateToRoundNumber(date) {
|
|
|
480
541
|
}
|
|
481
542
|
/** Return the number of days in the current month of the given date */
|
|
482
543
|
function getDaysInMonth(date) {
|
|
483
|
-
return new
|
|
544
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
484
545
|
}
|
|
485
546
|
function isLastDayOfMonth(date) {
|
|
486
547
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -498,7 +559,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
498
559
|
const yStart = date.getFullYear();
|
|
499
560
|
const mStart = date.getMonth();
|
|
500
561
|
const dStart = date.getDate();
|
|
501
|
-
const jsDate = new
|
|
562
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
502
563
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
503
564
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
504
565
|
}
|
|
@@ -626,13 +687,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
|
|
|
626
687
|
}
|
|
627
688
|
|
|
628
689
|
//------------------------------------------------------------------------------
|
|
629
|
-
/**
|
|
630
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
631
|
-
* is ordered.
|
|
632
|
-
*/
|
|
633
|
-
function stringify(obj) {
|
|
634
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
635
|
-
}
|
|
636
690
|
/**
|
|
637
691
|
* Remove quotes from a quoted string
|
|
638
692
|
* ```js
|
|
@@ -928,7 +982,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
928
982
|
*/
|
|
929
983
|
function getItemId(item, itemsDic) {
|
|
930
984
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
931
|
-
if (
|
|
985
|
+
if (deepEquals(value, item)) {
|
|
932
986
|
return parseInt(key, 10);
|
|
933
987
|
}
|
|
934
988
|
}
|
|
@@ -1064,6 +1118,22 @@ function transpose2dArray(matrix) {
|
|
|
1064
1118
|
if (!matrix.length)
|
|
1065
1119
|
return matrix;
|
|
1066
1120
|
return matrix[0].map((_, i) => matrix.map((row) => row[i]));
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Creates a version of the function that's memoized on the value of its first
|
|
1124
|
+
* argument, if any.
|
|
1125
|
+
*/
|
|
1126
|
+
function memoize(func) {
|
|
1127
|
+
const cache = new Map();
|
|
1128
|
+
const funcName = func.name ? func.name + " (memoized)" : "memoized";
|
|
1129
|
+
return {
|
|
1130
|
+
[funcName](...args) {
|
|
1131
|
+
if (!cache.has(args[0])) {
|
|
1132
|
+
cache.set(args[0], func(...args));
|
|
1133
|
+
}
|
|
1134
|
+
return cache.get(args[0]);
|
|
1135
|
+
},
|
|
1136
|
+
}[funcName];
|
|
1067
1137
|
}
|
|
1068
1138
|
|
|
1069
1139
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
@@ -1338,8 +1408,10 @@ function isSameColor(color1, color2) {
|
|
|
1338
1408
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
1339
1409
|
// Same as above, but matches the exact string (nothing before or after)
|
|
1340
1410
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
1341
|
-
/** Reference of a column header (eg. A, AB) */
|
|
1342
|
-
const colHeader = new RegExp(
|
|
1411
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
1412
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
1413
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
1414
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
1343
1415
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
1344
1416
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
1345
1417
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -1369,6 +1441,9 @@ function isRowReference(xc) {
|
|
|
1369
1441
|
function isColHeader(str) {
|
|
1370
1442
|
return colHeader.test(str);
|
|
1371
1443
|
}
|
|
1444
|
+
function isRowHeader(str) {
|
|
1445
|
+
return rowHeader.test(str);
|
|
1446
|
+
}
|
|
1372
1447
|
/**
|
|
1373
1448
|
* Return true if the given xc is the reference of a single cell,
|
|
1374
1449
|
* without any specified sheet (e.g. A1)
|
|
@@ -1867,7 +1942,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1867
1942
|
.map((p) => {
|
|
1868
1943
|
switch (p) {
|
|
1869
1944
|
case "hhhh":
|
|
1870
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
1945
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1871
1946
|
return helapsedHours.toString();
|
|
1872
1947
|
case "hh":
|
|
1873
1948
|
return hours.toString().padStart(2, "0");
|
|
@@ -2158,18 +2233,10 @@ class RangeImpl {
|
|
|
2158
2233
|
if (isFullCol) {
|
|
2159
2234
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2160
2235
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2161
|
-
if (zone.left === zone.right) {
|
|
2162
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2163
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2164
|
-
}
|
|
2165
2236
|
}
|
|
2166
2237
|
if (isFullRow) {
|
|
2167
2238
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2168
2239
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2169
|
-
if (zone.top === zone.bottom) {
|
|
2170
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2171
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2172
|
-
}
|
|
2173
2240
|
}
|
|
2174
2241
|
return parts;
|
|
2175
2242
|
}
|
|
@@ -3660,6 +3727,7 @@ exports.CommandResult = void 0;
|
|
|
3660
3727
|
CommandResult[CommandResult["ChartDoesNotExist"] = 85] = "ChartDoesNotExist";
|
|
3661
3728
|
CommandResult[CommandResult["InvalidHeaderIndex"] = 86] = "InvalidHeaderIndex";
|
|
3662
3729
|
CommandResult[CommandResult["InvalidQuantity"] = 87] = "InvalidQuantity";
|
|
3730
|
+
CommandResult[CommandResult["NoChanges"] = 88] = "NoChanges";
|
|
3663
3731
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
3664
3732
|
|
|
3665
3733
|
function isMatrix(x) {
|
|
@@ -5695,6 +5763,7 @@ function getMenuDescription(node) {
|
|
|
5695
5763
|
return node.description ? node.description : "";
|
|
5696
5764
|
}
|
|
5697
5765
|
|
|
5766
|
+
const macRegex = /Mac/i;
|
|
5698
5767
|
/**
|
|
5699
5768
|
* Return true if the event was triggered from
|
|
5700
5769
|
* a child element.
|
|
@@ -5712,6 +5781,17 @@ function gridOverlayPosition() {
|
|
|
5712
5781
|
}
|
|
5713
5782
|
function getOpenedMenus() {
|
|
5714
5783
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5784
|
+
}
|
|
5785
|
+
function isMacOS() {
|
|
5786
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
5787
|
+
}
|
|
5788
|
+
/**
|
|
5789
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
5790
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
5791
|
+
* On Mac, this is the "meta" or "command" key.
|
|
5792
|
+
*/
|
|
5793
|
+
function isCtrlKey(ev) {
|
|
5794
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
5715
5795
|
}
|
|
5716
5796
|
|
|
5717
5797
|
/**
|
|
@@ -8023,12 +8103,12 @@ function toString(value) {
|
|
|
8023
8103
|
}
|
|
8024
8104
|
}
|
|
8025
8105
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
8026
|
-
function normalizeString(str) {
|
|
8106
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
8027
8107
|
return str
|
|
8028
8108
|
.toLowerCase()
|
|
8029
8109
|
.normalize("NFD")
|
|
8030
8110
|
.replace(/[\u0300-\u036f]/g, "");
|
|
8031
|
-
}
|
|
8111
|
+
});
|
|
8032
8112
|
/**
|
|
8033
8113
|
* Normalize a value.
|
|
8034
8114
|
* If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
|
|
@@ -10872,7 +10952,7 @@ const DATE = {
|
|
|
10872
10952
|
if (_year < 1900) {
|
|
10873
10953
|
_year += 1900;
|
|
10874
10954
|
}
|
|
10875
|
-
const jsDate = new
|
|
10955
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
10876
10956
|
const result = jsDateToRoundNumber(jsDate);
|
|
10877
10957
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
10878
10958
|
return result;
|
|
@@ -10984,7 +11064,7 @@ const EOMONTH = {
|
|
|
10984
11064
|
const _months = Math.trunc(toNumber(months));
|
|
10985
11065
|
const yStart = _startDate.getFullYear();
|
|
10986
11066
|
const mStart = _startDate.getMonth();
|
|
10987
|
-
const jsDate = new
|
|
11067
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
10988
11068
|
return jsDateToRoundNumber(jsDate);
|
|
10989
11069
|
},
|
|
10990
11070
|
isExported: true,
|
|
@@ -11023,17 +11103,17 @@ const ISOWEEKNUM = {
|
|
|
11023
11103
|
// The first week of the year is the week that contains the first
|
|
11024
11104
|
// Thursday of the year.
|
|
11025
11105
|
let firstThursday = 1;
|
|
11026
|
-
while (new
|
|
11106
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
11027
11107
|
firstThursday += 1;
|
|
11028
11108
|
}
|
|
11029
|
-
const firstDayOfFirstWeek = new
|
|
11109
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
11030
11110
|
// The last week of the year is the week that contains the last Thursday of
|
|
11031
11111
|
// the year.
|
|
11032
11112
|
let lastThursday = 31;
|
|
11033
|
-
while (new
|
|
11113
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
11034
11114
|
lastThursday -= 1;
|
|
11035
11115
|
}
|
|
11036
|
-
const lastDayOfLastWeek = new
|
|
11116
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
11037
11117
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
11038
11118
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
11039
11119
|
let offsetYear;
|
|
@@ -11059,17 +11139,17 @@ const ISOWEEKNUM = {
|
|
|
11059
11139
|
case 1:
|
|
11060
11140
|
// firstDay is the 1st day of the 1st week of the year after
|
|
11061
11141
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
11062
|
-
firstDay = new
|
|
11142
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
11063
11143
|
break;
|
|
11064
11144
|
case -1:
|
|
11065
11145
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
11066
11146
|
// The first week of the previous year is the week that contains the
|
|
11067
11147
|
// first Thursday of the previous year.
|
|
11068
11148
|
let firstThursdayPreviousYear = 1;
|
|
11069
|
-
while (new
|
|
11149
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
11070
11150
|
firstThursdayPreviousYear += 1;
|
|
11071
11151
|
}
|
|
11072
|
-
firstDay = new
|
|
11152
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
11073
11153
|
break;
|
|
11074
11154
|
}
|
|
11075
11155
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -11208,8 +11288,8 @@ const NETWORKDAYS_INTL = {
|
|
|
11208
11288
|
});
|
|
11209
11289
|
}
|
|
11210
11290
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
11211
|
-
const stopDate =
|
|
11212
|
-
let stepDate =
|
|
11291
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
11292
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
11213
11293
|
const timeStopDate = stopDate.getTime();
|
|
11214
11294
|
let timeStepDate = stepDate.getTime();
|
|
11215
11295
|
let netWorkingDay = 0;
|
|
@@ -11233,8 +11313,7 @@ const NOW = {
|
|
|
11233
11313
|
returns: ["DATE"],
|
|
11234
11314
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
11235
11315
|
compute: function () {
|
|
11236
|
-
let today =
|
|
11237
|
-
today.setMilliseconds(0);
|
|
11316
|
+
let today = DateTime.now();
|
|
11238
11317
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
11239
11318
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
11240
11319
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -11308,8 +11387,8 @@ const TODAY = {
|
|
|
11308
11387
|
returns: ["DATE"],
|
|
11309
11388
|
computeFormat: () => "m/d/yyyy",
|
|
11310
11389
|
compute: function () {
|
|
11311
|
-
const today =
|
|
11312
|
-
const jsDate = new
|
|
11390
|
+
const today = DateTime.now();
|
|
11391
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
11313
11392
|
return jsDateToRoundNumber(jsDate);
|
|
11314
11393
|
},
|
|
11315
11394
|
isExported: true,
|
|
@@ -11364,10 +11443,10 @@ const WEEKNUM = {
|
|
|
11364
11443
|
}
|
|
11365
11444
|
const y = _date.getFullYear();
|
|
11366
11445
|
let dayStart = 1;
|
|
11367
|
-
let startDayOfFirstWeek = new
|
|
11446
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
11368
11447
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
11369
11448
|
dayStart += 1;
|
|
11370
|
-
startDayOfFirstWeek = new
|
|
11449
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
11371
11450
|
}
|
|
11372
11451
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
11373
11452
|
if (dif < 0) {
|
|
@@ -11421,7 +11500,7 @@ const WORKDAY_INTL = {
|
|
|
11421
11500
|
timesHoliday.add(holiday.getTime());
|
|
11422
11501
|
});
|
|
11423
11502
|
}
|
|
11424
|
-
let stepDate =
|
|
11503
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
11425
11504
|
let timeStepDate = stepDate.getTime();
|
|
11426
11505
|
const unitDay = Math.sign(_numDays);
|
|
11427
11506
|
let stepDay = Math.abs(_numDays);
|
|
@@ -11487,7 +11566,7 @@ const MONTH_START = {
|
|
|
11487
11566
|
const _startDate = toJsDate(date);
|
|
11488
11567
|
const yStart = _startDate.getFullYear();
|
|
11489
11568
|
const mStart = _startDate.getMonth();
|
|
11490
|
-
const jsDate = new
|
|
11569
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
11491
11570
|
return jsDateToRoundNumber(jsDate);
|
|
11492
11571
|
},
|
|
11493
11572
|
};
|
|
@@ -11531,7 +11610,7 @@ const QUARTER_START = {
|
|
|
11531
11610
|
compute: function (date) {
|
|
11532
11611
|
const quarter = QUARTER.compute(date);
|
|
11533
11612
|
const year = YEAR.compute(date);
|
|
11534
|
-
const jsDate = new
|
|
11613
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
11535
11614
|
return jsDateToRoundNumber(jsDate);
|
|
11536
11615
|
},
|
|
11537
11616
|
};
|
|
@@ -11548,7 +11627,7 @@ const QUARTER_END = {
|
|
|
11548
11627
|
compute: function (date) {
|
|
11549
11628
|
const quarter = QUARTER.compute(date);
|
|
11550
11629
|
const year = YEAR.compute(date);
|
|
11551
|
-
const jsDate = new
|
|
11630
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
11552
11631
|
return jsDateToRoundNumber(jsDate);
|
|
11553
11632
|
},
|
|
11554
11633
|
};
|
|
@@ -11564,7 +11643,7 @@ const YEAR_START = {
|
|
|
11564
11643
|
computeFormat: () => "m/d/yyyy",
|
|
11565
11644
|
compute: function (date) {
|
|
11566
11645
|
const year = YEAR.compute(date);
|
|
11567
|
-
const jsDate = new
|
|
11646
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
11568
11647
|
return jsDateToRoundNumber(jsDate);
|
|
11569
11648
|
},
|
|
11570
11649
|
};
|
|
@@ -11580,7 +11659,7 @@ const YEAR_END = {
|
|
|
11580
11659
|
computeFormat: () => "m/d/yyyy",
|
|
11581
11660
|
compute: function (date) {
|
|
11582
11661
|
const year = YEAR.compute(date);
|
|
11583
|
-
const jsDate = new
|
|
11662
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
11584
11663
|
return jsDateToRoundNumber(jsDate);
|
|
11585
11664
|
},
|
|
11586
11665
|
};
|
|
@@ -11714,7 +11793,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
11714
11793
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
11715
11794
|
const startDate = toJsDate(settlement);
|
|
11716
11795
|
const endDate = toJsDate(maturity);
|
|
11717
|
-
const startDatePlusOneYear =
|
|
11796
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
11718
11797
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
11719
11798
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
11720
11799
|
}
|
|
@@ -15640,7 +15719,7 @@ const machine = {
|
|
|
15640
15719
|
SPACE: goTo(State.RightRef),
|
|
15641
15720
|
NUMBER: goTo(State.Found),
|
|
15642
15721
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
15643
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
15722
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
15644
15723
|
},
|
|
15645
15724
|
[State.RightColumnRef]: {
|
|
15646
15725
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -15651,6 +15730,7 @@ const machine = {
|
|
|
15651
15730
|
SPACE: goTo(State.RightRowRef),
|
|
15652
15731
|
NUMBER: goTo(State.Found),
|
|
15653
15732
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
15733
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
15654
15734
|
},
|
|
15655
15735
|
[State.Found]: {},
|
|
15656
15736
|
};
|
|
@@ -16160,6 +16240,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
16160
16240
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
16161
16241
|
case "colrow":
|
|
16162
16242
|
indexOfNumber = xc.search(/[0-9]/);
|
|
16243
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
16244
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
16245
|
+
return "$" + xc;
|
|
16246
|
+
}
|
|
16163
16247
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
16164
16248
|
return "$" + xc;
|
|
16165
16249
|
case "none":
|
|
@@ -16933,10 +17017,10 @@ const arrowMap = {
|
|
|
16933
17017
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
16934
17018
|
const direction = arrowMap[ev.key];
|
|
16935
17019
|
if (ev.shiftKey) {
|
|
16936
|
-
selection.resizeAnchorZone(direction, ev
|
|
17020
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
16937
17021
|
}
|
|
16938
17022
|
else {
|
|
16939
|
-
selection.moveAnchorCell(direction, ev
|
|
17023
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
16940
17024
|
}
|
|
16941
17025
|
}
|
|
16942
17026
|
|
|
@@ -22593,7 +22677,10 @@ class GridOverlay extends owl.Component {
|
|
|
22593
22677
|
return;
|
|
22594
22678
|
}
|
|
22595
22679
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
22596
|
-
this.props.onCellClicked(col, row, {
|
|
22680
|
+
this.props.onCellClicked(col, row, {
|
|
22681
|
+
expandZone: ev.shiftKey,
|
|
22682
|
+
addZone: isCtrlKey(ev),
|
|
22683
|
+
});
|
|
22597
22684
|
}
|
|
22598
22685
|
onDoubleClick(ev) {
|
|
22599
22686
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -22681,6 +22768,7 @@ class AbstractResizer extends owl.Component {
|
|
|
22681
22768
|
draggerShadowThickness: 0,
|
|
22682
22769
|
delta: 0,
|
|
22683
22770
|
base: 0,
|
|
22771
|
+
position: "before",
|
|
22684
22772
|
});
|
|
22685
22773
|
}
|
|
22686
22774
|
_computeHandleDisplay(ev) {
|
|
@@ -22806,11 +22894,13 @@ class AbstractResizer extends owl.Component {
|
|
|
22806
22894
|
this.state.draggerLinePosition = dimensions.start;
|
|
22807
22895
|
this.state.draggerShadowPosition = dimensions.start;
|
|
22808
22896
|
this.state.base = elementIndex;
|
|
22897
|
+
this.state.position = "before";
|
|
22809
22898
|
}
|
|
22810
22899
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
22811
22900
|
this.state.draggerLinePosition = dimensions.end;
|
|
22812
22901
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
22813
|
-
this.state.base = elementIndex
|
|
22902
|
+
this.state.base = elementIndex;
|
|
22903
|
+
this.state.position = "after";
|
|
22814
22904
|
}
|
|
22815
22905
|
else {
|
|
22816
22906
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -22834,7 +22924,7 @@ class AbstractResizer extends owl.Component {
|
|
|
22834
22924
|
this._increaseSelection(index);
|
|
22835
22925
|
}
|
|
22836
22926
|
else {
|
|
22837
|
-
this._selectElement(index, ev
|
|
22927
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
22838
22928
|
}
|
|
22839
22929
|
this.lastSelectedElementIndex = index;
|
|
22840
22930
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -22847,7 +22937,7 @@ class AbstractResizer extends owl.Component {
|
|
|
22847
22937
|
const mouseUpSelect = () => {
|
|
22848
22938
|
this.state.isSelecting = false;
|
|
22849
22939
|
this.lastSelectedElementIndex = null;
|
|
22850
|
-
this.env.model.dispatch(ev
|
|
22940
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
22851
22941
|
this._computeGrabDisplay(ev);
|
|
22852
22942
|
};
|
|
22853
22943
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -22991,13 +23081,14 @@ class ColResizer extends AbstractResizer {
|
|
|
22991
23081
|
dimension: "COL",
|
|
22992
23082
|
base: this.state.base,
|
|
22993
23083
|
elements,
|
|
23084
|
+
position: this.state.position,
|
|
22994
23085
|
});
|
|
22995
23086
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22996
23087
|
this.env.raiseError(MergeErrorMessage);
|
|
22997
23088
|
}
|
|
22998
23089
|
}
|
|
22999
|
-
_selectElement(index,
|
|
23000
|
-
this.env.model.selection.selectColumn(index,
|
|
23090
|
+
_selectElement(index, addDistinctHeader) {
|
|
23091
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
23001
23092
|
}
|
|
23002
23093
|
_increaseSelection(index) {
|
|
23003
23094
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -23163,13 +23254,14 @@ class RowResizer extends AbstractResizer {
|
|
|
23163
23254
|
dimension: "ROW",
|
|
23164
23255
|
base: this.state.base,
|
|
23165
23256
|
elements,
|
|
23257
|
+
position: this.state.position,
|
|
23166
23258
|
});
|
|
23167
23259
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
23168
23260
|
this.env.raiseError(MergeErrorMessage);
|
|
23169
23261
|
}
|
|
23170
23262
|
}
|
|
23171
|
-
_selectElement(index,
|
|
23172
|
-
this.env.model.selection.selectRow(index,
|
|
23263
|
+
_selectElement(index, addDistinctHeader) {
|
|
23264
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
23173
23265
|
}
|
|
23174
23266
|
_increaseSelection(index) {
|
|
23175
23267
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -23271,8 +23363,8 @@ function useWheelHandler(handler) {
|
|
|
23271
23363
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
23272
23364
|
}
|
|
23273
23365
|
const onMouseWheel = (ev) => {
|
|
23274
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23275
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23366
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23367
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23276
23368
|
handler(deltaX, deltaY);
|
|
23277
23369
|
};
|
|
23278
23370
|
return onMouseWheel;
|
|
@@ -23916,8 +24008,8 @@ class Grid extends owl.Component {
|
|
|
23916
24008
|
// ---------------------------------------------------------------------------
|
|
23917
24009
|
// Zone selection with mouse
|
|
23918
24010
|
// ---------------------------------------------------------------------------
|
|
23919
|
-
onCellClicked(col, row, {
|
|
23920
|
-
if (
|
|
24011
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
24012
|
+
if (addZone) {
|
|
23921
24013
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
23922
24014
|
}
|
|
23923
24015
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
@@ -23926,10 +24018,10 @@ class Grid extends owl.Component {
|
|
|
23926
24018
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
23927
24019
|
this.env.model.dispatch("STOP_EDITION");
|
|
23928
24020
|
}
|
|
23929
|
-
if (
|
|
24021
|
+
if (expandZone) {
|
|
23930
24022
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
23931
24023
|
}
|
|
23932
|
-
else if (
|
|
24024
|
+
else if (addZone) {
|
|
23933
24025
|
this.env.model.selection.addCellToSelection(col, row);
|
|
23934
24026
|
}
|
|
23935
24027
|
else {
|
|
@@ -23991,9 +24083,7 @@ class Grid extends owl.Component {
|
|
|
23991
24083
|
return;
|
|
23992
24084
|
}
|
|
23993
24085
|
let keyDownString = "";
|
|
23994
|
-
if (ev
|
|
23995
|
-
keyDownString += "CTRL+";
|
|
23996
|
-
if (ev.metaKey)
|
|
24086
|
+
if (isCtrlKey(ev))
|
|
23997
24087
|
keyDownString += "CTRL+";
|
|
23998
24088
|
if (ev.altKey)
|
|
23999
24089
|
keyDownString += "ALT+";
|
|
@@ -27945,6 +28035,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
27945
28035
|
// ---------------------------------------------------------------------------
|
|
27946
28036
|
// Command Handling
|
|
27947
28037
|
// ---------------------------------------------------------------------------
|
|
28038
|
+
allowDispatch(cmd) {
|
|
28039
|
+
switch (cmd.type) {
|
|
28040
|
+
case "SET_BORDER":
|
|
28041
|
+
return this.checkBordersUnchanged(cmd);
|
|
28042
|
+
default:
|
|
28043
|
+
return 0 /* CommandResult.Success */;
|
|
28044
|
+
}
|
|
28045
|
+
}
|
|
27948
28046
|
handle(cmd) {
|
|
27949
28047
|
switch (cmd.type) {
|
|
27950
28048
|
case "ADD_MERGE":
|
|
@@ -28340,6 +28438,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
28340
28438
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right");
|
|
28341
28439
|
}
|
|
28342
28440
|
}
|
|
28441
|
+
checkBordersUnchanged(cmd) {
|
|
28442
|
+
var _a, _b, _c, _d;
|
|
28443
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
28444
|
+
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);
|
|
28445
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
28446
|
+
return 88 /* CommandResult.NoChanges */;
|
|
28447
|
+
}
|
|
28448
|
+
return 0 /* CommandResult.Success */;
|
|
28449
|
+
}
|
|
28343
28450
|
// ---------------------------------------------------------------------------
|
|
28344
28451
|
// Import/Export
|
|
28345
28452
|
// ---------------------------------------------------------------------------
|
|
@@ -28375,7 +28482,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
28375
28482
|
*/
|
|
28376
28483
|
function getBorderId(border) {
|
|
28377
28484
|
for (let [key, value] of Object.entries(borders)) {
|
|
28378
|
-
if (
|
|
28485
|
+
if (deepEquals(value, border)) {
|
|
28379
28486
|
return parseInt(key, 10);
|
|
28380
28487
|
}
|
|
28381
28488
|
}
|
|
@@ -28443,8 +28550,9 @@ class CellPlugin extends CorePlugin {
|
|
|
28443
28550
|
allowDispatch(cmd) {
|
|
28444
28551
|
switch (cmd.type) {
|
|
28445
28552
|
case "UPDATE_CELL":
|
|
28553
|
+
return this.checkCellOutOfSheet(cmd);
|
|
28446
28554
|
case "CLEAR_CELL":
|
|
28447
|
-
return this.
|
|
28555
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
28448
28556
|
default:
|
|
28449
28557
|
return 0 /* CommandResult.Success */;
|
|
28450
28558
|
}
|
|
@@ -28603,14 +28711,9 @@ class CellPlugin extends CorePlugin {
|
|
|
28603
28711
|
*/
|
|
28604
28712
|
getCellById(cellId) {
|
|
28605
28713
|
// this must be as fast as possible
|
|
28606
|
-
|
|
28607
|
-
|
|
28608
|
-
|
|
28609
|
-
if (cell) {
|
|
28610
|
-
return cell;
|
|
28611
|
-
}
|
|
28612
|
-
}
|
|
28613
|
-
return undefined;
|
|
28714
|
+
const position = this.getters.getCellPosition(cellId);
|
|
28715
|
+
const sheet = this.cells[position.sheetId];
|
|
28716
|
+
return sheet[cellId];
|
|
28614
28717
|
}
|
|
28615
28718
|
/*
|
|
28616
28719
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -28851,13 +28954,23 @@ class CellPlugin extends CorePlugin {
|
|
|
28851
28954
|
dependencies: [],
|
|
28852
28955
|
};
|
|
28853
28956
|
}
|
|
28854
|
-
checkCellOutOfSheet(
|
|
28957
|
+
checkCellOutOfSheet(cmd) {
|
|
28958
|
+
const { sheetId, col, row } = cmd;
|
|
28855
28959
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
28856
28960
|
if (!sheet)
|
|
28857
28961
|
return 27 /* CommandResult.InvalidSheetId */;
|
|
28858
28962
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
28859
28963
|
return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
|
|
28860
28964
|
}
|
|
28965
|
+
checkUselessClearCell(cmd) {
|
|
28966
|
+
const cell = this.getters.getCell(cmd);
|
|
28967
|
+
if (!cell)
|
|
28968
|
+
return 88 /* CommandResult.NoChanges */;
|
|
28969
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
28970
|
+
return 88 /* CommandResult.NoChanges */;
|
|
28971
|
+
}
|
|
28972
|
+
return 0 /* CommandResult.Success */;
|
|
28973
|
+
}
|
|
28861
28974
|
}
|
|
28862
28975
|
CellPlugin.getters = [
|
|
28863
28976
|
"zoneToXC",
|
|
@@ -31318,7 +31431,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
31318
31431
|
const elements = cmd.dimension === "COL"
|
|
31319
31432
|
? this.getNumberCols(cmd.sheetId)
|
|
31320
31433
|
: this.getNumberRows(cmd.sheetId);
|
|
31321
|
-
if (cmd.base < 0 || cmd.base
|
|
31434
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
31322
31435
|
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
31323
31436
|
}
|
|
31324
31437
|
else if (cmd.quantity <= 0) {
|
|
@@ -31918,10 +32031,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
31918
32031
|
// begin with the end.
|
|
31919
32032
|
rows.sort((a, b) => b - a);
|
|
31920
32033
|
for (let group of groupConsecutive(rows)) {
|
|
32034
|
+
// indexes are sorted in the descending order
|
|
32035
|
+
const from = group[group.length - 1];
|
|
32036
|
+
const to = group[0];
|
|
31921
32037
|
// Move the cells.
|
|
31922
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
31923
|
-
// Effectively delete the
|
|
31924
|
-
|
|
32038
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
32039
|
+
// Effectively delete the rows
|
|
32040
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
31925
32041
|
}
|
|
31926
32042
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
31927
32043
|
if (count) {
|
|
@@ -31943,8 +32059,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
31943
32059
|
this.addEmptyRows(sheet, quantity);
|
|
31944
32060
|
// Move the cells.
|
|
31945
32061
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
31946
|
-
// Recompute the left-right/top-bottom.
|
|
31947
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
31948
32062
|
if (index < sheet.panes.ySplit) {
|
|
31949
32063
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
31950
32064
|
}
|
|
@@ -32045,35 +32159,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
32045
32159
|
}
|
|
32046
32160
|
}
|
|
32047
32161
|
}
|
|
32048
|
-
updateRowsStructureOnDeletion(
|
|
32162
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
32049
32163
|
const rows = [];
|
|
32050
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
32164
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
32051
32165
|
for (let i in sheet.rows) {
|
|
32052
|
-
|
|
32166
|
+
const row = Number(i);
|
|
32167
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
32053
32168
|
continue;
|
|
32054
32169
|
}
|
|
32055
32170
|
rows.push({
|
|
32056
|
-
cells: cellsQueue.
|
|
32171
|
+
cells: cellsQueue.pop(),
|
|
32057
32172
|
});
|
|
32058
32173
|
}
|
|
32059
32174
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
32060
32175
|
}
|
|
32061
|
-
/**
|
|
32062
|
-
* Update the rows of the sheet after an addition:
|
|
32063
|
-
* - Rename the rows
|
|
32064
|
-
*
|
|
32065
|
-
* @param sheet Sheet on which the deletion occurs
|
|
32066
|
-
* @param addedRow Index of the added row
|
|
32067
|
-
* @param rowsToAdd Number of the rows to add
|
|
32068
|
-
*/
|
|
32069
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
32070
|
-
const rows = [];
|
|
32071
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
32072
|
-
sheet.rows.forEach(() => rows.push({
|
|
32073
|
-
cells: cellsQueue.shift(),
|
|
32074
|
-
}));
|
|
32075
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
32076
|
-
}
|
|
32077
32176
|
/**
|
|
32078
32177
|
* Add empty rows at the end of the rows
|
|
32079
32178
|
*
|
|
@@ -32355,13 +32454,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32355
32454
|
// Getters
|
|
32356
32455
|
// ---------------------------------------------------------------------------
|
|
32357
32456
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
32358
|
-
|
|
32359
|
-
|
|
32360
|
-
|
|
32361
|
-
|
|
32362
|
-
|
|
32457
|
+
try {
|
|
32458
|
+
const compiledFormula = compile(formulaString);
|
|
32459
|
+
const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
|
|
32460
|
+
const ranges = [];
|
|
32461
|
+
for (let xc of compiledFormula.dependencies) {
|
|
32462
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
32463
|
+
}
|
|
32464
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
32465
|
+
}
|
|
32466
|
+
catch (error) {
|
|
32467
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
32363
32468
|
}
|
|
32364
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
32365
32469
|
}
|
|
32366
32470
|
/**
|
|
32367
32471
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -32530,6 +32634,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32530
32634
|
}
|
|
32531
32635
|
return evaluatedCell;
|
|
32532
32636
|
};
|
|
32637
|
+
const rangeCache = {};
|
|
32533
32638
|
/**
|
|
32534
32639
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
32535
32640
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -32546,21 +32651,26 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32546
32651
|
// Performance issue: Avoid fetching data on positions that are out of the spreadsheet
|
|
32547
32652
|
// e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
|
|
32548
32653
|
const sheetZone = getters.getSheetZone(sheetId);
|
|
32549
|
-
const result = [];
|
|
32550
32654
|
const zone = intersection(range.zone, sheetZone);
|
|
32551
32655
|
if (!zone) {
|
|
32552
|
-
|
|
32553
|
-
return result;
|
|
32656
|
+
return [[]];
|
|
32554
32657
|
}
|
|
32658
|
+
const { top, left, bottom, right } = zone;
|
|
32659
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
32660
|
+
if (cacheKey in rangeCache) {
|
|
32661
|
+
return rangeCache[cacheKey];
|
|
32662
|
+
}
|
|
32663
|
+
const result = new Array(right - left + 1);
|
|
32555
32664
|
// Performance issue: nested loop is faster than a map here
|
|
32556
|
-
for (let col =
|
|
32557
|
-
const rowValues =
|
|
32558
|
-
for (let row =
|
|
32665
|
+
for (let col = left; col <= right; col++) {
|
|
32666
|
+
const rowValues = new Array(bottom - top + 1);
|
|
32667
|
+
for (let row = top; row <= bottom; row++) {
|
|
32559
32668
|
const cell = evalContext.getters.getCell({ sheetId: range.sheetId, col, row });
|
|
32560
|
-
rowValues
|
|
32669
|
+
rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
|
|
32561
32670
|
}
|
|
32562
|
-
result
|
|
32671
|
+
result[col - left] = rowValues;
|
|
32563
32672
|
}
|
|
32673
|
+
rangeCache[cacheKey] = result;
|
|
32564
32674
|
return result;
|
|
32565
32675
|
}
|
|
32566
32676
|
/**
|
|
@@ -32847,39 +32957,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32847
32957
|
this.computedIcons[sheetId] = {};
|
|
32848
32958
|
const computedStyle = this.computedStyles[sheetId];
|
|
32849
32959
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
32850
|
-
|
|
32851
|
-
|
|
32852
|
-
|
|
32853
|
-
|
|
32854
|
-
|
|
32855
|
-
|
|
32856
|
-
|
|
32857
|
-
|
|
32858
|
-
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
|
|
32863
|
-
|
|
32864
|
-
|
|
32865
|
-
for (let
|
|
32866
|
-
|
|
32867
|
-
|
|
32868
|
-
|
|
32869
|
-
if (
|
|
32870
|
-
|
|
32871
|
-
|
|
32872
|
-
|
|
32873
|
-
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32874
|
-
}
|
|
32960
|
+
switch (cf.rule.type) {
|
|
32961
|
+
case "ColorScaleRule":
|
|
32962
|
+
for (let range of cf.ranges) {
|
|
32963
|
+
this.applyColorScale(range, cf.rule);
|
|
32964
|
+
}
|
|
32965
|
+
break;
|
|
32966
|
+
case "IconSetRule":
|
|
32967
|
+
for (let range of cf.ranges) {
|
|
32968
|
+
this.applyIcon(range, cf.rule);
|
|
32969
|
+
}
|
|
32970
|
+
break;
|
|
32971
|
+
default:
|
|
32972
|
+
for (let ref of cf.ranges) {
|
|
32973
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
32974
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
32975
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
32976
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
32977
|
+
let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
32978
|
+
if (pr && pr(cell, cf.rule)) {
|
|
32979
|
+
if (!computedStyle[col])
|
|
32980
|
+
computedStyle[col] = [];
|
|
32981
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
32982
|
+
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32875
32983
|
}
|
|
32876
32984
|
}
|
|
32877
32985
|
}
|
|
32878
|
-
|
|
32879
|
-
|
|
32880
|
-
}
|
|
32881
|
-
catch (_) {
|
|
32882
|
-
// we don't care about the errors within the evaluation of a rule
|
|
32986
|
+
}
|
|
32987
|
+
break;
|
|
32883
32988
|
}
|
|
32884
32989
|
}
|
|
32885
32990
|
}
|
|
@@ -32904,7 +33009,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32904
33009
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
32905
33010
|
case "formula":
|
|
32906
33011
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
32907
|
-
return
|
|
33012
|
+
return typeof value === "number" ? value : null;
|
|
32908
33013
|
default:
|
|
32909
33014
|
return null;
|
|
32910
33015
|
}
|
|
@@ -34466,24 +34571,27 @@ class AutofillPlugin extends UIPlugin {
|
|
|
34466
34571
|
* autofiller
|
|
34467
34572
|
*/
|
|
34468
34573
|
autofillAuto() {
|
|
34574
|
+
var _a, _b;
|
|
34469
34575
|
const zone = this.getters.getSelectedZone();
|
|
34470
34576
|
const sheetId = this.getters.getActiveSheetId();
|
|
34471
34577
|
let col = zone.left;
|
|
34472
34578
|
let row = zone.bottom;
|
|
34473
34579
|
if (col > 0) {
|
|
34474
|
-
let
|
|
34475
|
-
while (
|
|
34580
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
34581
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
34582
|
+
((_a = this.getters.getCell(leftPosition)) === null || _a === void 0 ? void 0 : _a.content)) {
|
|
34476
34583
|
row += 1;
|
|
34477
|
-
|
|
34584
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
34478
34585
|
}
|
|
34479
34586
|
}
|
|
34480
34587
|
if (row === zone.bottom) {
|
|
34481
34588
|
col = zone.right;
|
|
34482
34589
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
34483
|
-
let
|
|
34484
|
-
while (
|
|
34590
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
34591
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
34592
|
+
((_b = this.getters.getCell(rightPosition)) === null || _b === void 0 ? void 0 : _b.content)) {
|
|
34485
34593
|
row += 1;
|
|
34486
|
-
|
|
34594
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
34487
34595
|
}
|
|
34488
34596
|
}
|
|
34489
34597
|
}
|
|
@@ -39215,7 +39323,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
39215
39323
|
sheetId: cmd.sheetId,
|
|
39216
39324
|
base: cmd.base,
|
|
39217
39325
|
quantity: thickness,
|
|
39218
|
-
position:
|
|
39326
|
+
position: cmd.position,
|
|
39219
39327
|
});
|
|
39220
39328
|
const isCol = cmd.dimension === "COL";
|
|
39221
39329
|
const start = cmd.elements[0];
|
|
@@ -39232,12 +39340,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
39232
39340
|
},
|
|
39233
39341
|
];
|
|
39234
39342
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
39343
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
39235
39344
|
const pasteTarget = [
|
|
39236
39345
|
{
|
|
39237
|
-
left: isCol ?
|
|
39238
|
-
right: isCol ?
|
|
39239
|
-
top: !isCol ?
|
|
39240
|
-
bottom: !isCol ?
|
|
39346
|
+
left: isCol ? base : 0,
|
|
39347
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
39348
|
+
top: !isCol ? base : 0,
|
|
39349
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
39241
39350
|
},
|
|
39242
39351
|
];
|
|
39243
39352
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -39274,6 +39383,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
39274
39383
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
39275
39384
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
39276
39385
|
}
|
|
39386
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
39387
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
39388
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
39389
|
+
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
39390
|
+
}
|
|
39277
39391
|
return 0 /* CommandResult.Success */;
|
|
39278
39392
|
}
|
|
39279
39393
|
//-------------------------------------------
|
|
@@ -40827,7 +40941,7 @@ class Spreadsheet extends owl.Component {
|
|
|
40827
40941
|
}
|
|
40828
40942
|
onKeydown(ev) {
|
|
40829
40943
|
let keyDownString = "";
|
|
40830
|
-
if (ev
|
|
40944
|
+
if (isCtrlKey(ev)) {
|
|
40831
40945
|
keyDownString += "CTRL+";
|
|
40832
40946
|
}
|
|
40833
40947
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -41674,9 +41788,9 @@ function revertChanges(revisions) {
|
|
|
41674
41788
|
* Apply the changes of the given HistoryChange to the state
|
|
41675
41789
|
*/
|
|
41676
41790
|
function applyChange(change, target) {
|
|
41677
|
-
let val = change.
|
|
41678
|
-
|
|
41679
|
-
for (let pathIndex =
|
|
41791
|
+
let val = change.path[0];
|
|
41792
|
+
const key = change.path[change.path.length - 1];
|
|
41793
|
+
for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
|
|
41680
41794
|
const p = change.path[pathIndex];
|
|
41681
41795
|
if (val[p] === undefined) {
|
|
41682
41796
|
const nextPath = change.path[pathIndex + 1];
|
|
@@ -42431,13 +42545,14 @@ class StateObserver {
|
|
|
42431
42545
|
}
|
|
42432
42546
|
addChange(...args) {
|
|
42433
42547
|
const val = args.pop();
|
|
42434
|
-
const
|
|
42548
|
+
const root = args[0];
|
|
42435
42549
|
let value = root;
|
|
42436
|
-
let key =
|
|
42437
|
-
|
|
42438
|
-
|
|
42550
|
+
let key = args[args.length - 1];
|
|
42551
|
+
const pathLength = args.length - 2;
|
|
42552
|
+
for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
|
|
42553
|
+
const p = args[pathIndex];
|
|
42439
42554
|
if (value[p] === undefined) {
|
|
42440
|
-
const nextPath =
|
|
42555
|
+
const nextPath = args[pathIndex + 1];
|
|
42441
42556
|
value[p] = createEmptyStructure(nextPath);
|
|
42442
42557
|
}
|
|
42443
42558
|
value = value[p];
|
|
@@ -42446,8 +42561,7 @@ class StateObserver {
|
|
|
42446
42561
|
return;
|
|
42447
42562
|
}
|
|
42448
42563
|
this.changes.push({
|
|
42449
|
-
|
|
42450
|
-
path,
|
|
42564
|
+
path: args,
|
|
42451
42565
|
before: value[key],
|
|
42452
42566
|
after: val,
|
|
42453
42567
|
});
|
|
@@ -44221,7 +44335,10 @@ class Model extends EventBus {
|
|
|
44221
44335
|
*/
|
|
44222
44336
|
checkDispatchAllowed(command) {
|
|
44223
44337
|
const results = this.handlers.map((handler) => handler.allowDispatch(command));
|
|
44224
|
-
|
|
44338
|
+
if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
|
|
44339
|
+
return new DispatchResult(results.flat());
|
|
44340
|
+
}
|
|
44341
|
+
return DispatchResult.Success;
|
|
44225
44342
|
}
|
|
44226
44343
|
finalize() {
|
|
44227
44344
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -44449,6 +44566,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
44449
44566
|
exports.tokenize = tokenize;
|
|
44450
44567
|
|
|
44451
44568
|
|
|
44452
|
-
__info__.version = '16.1.
|
|
44453
|
-
__info__.date = '
|
|
44454
|
-
__info__.hash = '
|
|
44569
|
+
__info__.version = '16.1.31';
|
|
44570
|
+
__info__.date = '2024-01-12T13:42:11.001Z';
|
|
44571
|
+
__info__.hash = 'f51befa';
|