@odoo/o-spreadsheet 16.3.18 → 16.3.22
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 +224 -136
- package/dist/o-spreadsheet.d.ts +40 -10
- package/dist/o-spreadsheet.esm.js +224 -136
- package/dist/o-spreadsheet.iife.js +224 -136
- package/dist/o-spreadsheet.iife.min.js +256 -256
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +1 -1
|
@@ -298,15 +298,80 @@ const FONT_SIZES = [6, 7, 8, 9, 10, 11, 12, 14, 18, 24, 36];
|
|
|
298
298
|
// -----------------------------------------------------------------------------
|
|
299
299
|
// Date Type
|
|
300
300
|
// -----------------------------------------------------------------------------
|
|
301
|
+
/**
|
|
302
|
+
* A DateTime object that can be used to manipulate spreadsheet dates.
|
|
303
|
+
* Conceptually, a spreadsheet date is simply a number with a date format,
|
|
304
|
+
* and it is timezone-agnostic.
|
|
305
|
+
* This DateTime object consistently uses UTC time to represent a naive date and time.
|
|
306
|
+
*/
|
|
307
|
+
class DateTime {
|
|
308
|
+
jsDate;
|
|
309
|
+
constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
|
|
310
|
+
this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
|
|
311
|
+
}
|
|
312
|
+
static fromTimestamp(timestamp) {
|
|
313
|
+
const date = new Date(timestamp);
|
|
314
|
+
return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
|
|
315
|
+
}
|
|
316
|
+
static now() {
|
|
317
|
+
const now = new Date();
|
|
318
|
+
return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
|
|
319
|
+
}
|
|
320
|
+
toString() {
|
|
321
|
+
return this.jsDate.toString();
|
|
322
|
+
}
|
|
323
|
+
toLocaleDateString() {
|
|
324
|
+
return this.jsDate.toLocaleDateString();
|
|
325
|
+
}
|
|
326
|
+
getTime() {
|
|
327
|
+
return this.jsDate.getTime();
|
|
328
|
+
}
|
|
329
|
+
getFullYear() {
|
|
330
|
+
return this.jsDate.getUTCFullYear();
|
|
331
|
+
}
|
|
332
|
+
getMonth() {
|
|
333
|
+
return this.jsDate.getUTCMonth();
|
|
334
|
+
}
|
|
335
|
+
getDate() {
|
|
336
|
+
return this.jsDate.getUTCDate();
|
|
337
|
+
}
|
|
338
|
+
getDay() {
|
|
339
|
+
return this.jsDate.getUTCDay();
|
|
340
|
+
}
|
|
341
|
+
getHours() {
|
|
342
|
+
return this.jsDate.getUTCHours();
|
|
343
|
+
}
|
|
344
|
+
getMinutes() {
|
|
345
|
+
return this.jsDate.getUTCMinutes();
|
|
346
|
+
}
|
|
347
|
+
getSeconds() {
|
|
348
|
+
return this.jsDate.getUTCSeconds();
|
|
349
|
+
}
|
|
350
|
+
setFullYear(year) {
|
|
351
|
+
this.jsDate.setFullYear(year);
|
|
352
|
+
}
|
|
353
|
+
setDate(date) {
|
|
354
|
+
this.jsDate.setUTCDate(date);
|
|
355
|
+
}
|
|
356
|
+
setHours(hours) {
|
|
357
|
+
this.jsDate.setUTCHours(hours);
|
|
358
|
+
}
|
|
359
|
+
setMinutes(minutes) {
|
|
360
|
+
this.jsDate.setUTCMinutes(minutes);
|
|
361
|
+
}
|
|
362
|
+
setSeconds(seconds) {
|
|
363
|
+
this.jsDate.setUTCSeconds(seconds);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
301
366
|
// -----------------------------------------------------------------------------
|
|
302
367
|
// Parsing
|
|
303
368
|
// -----------------------------------------------------------------------------
|
|
304
|
-
const INITIAL_1900_DAY = new
|
|
369
|
+
const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
|
|
305
370
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
306
371
|
const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
|
|
307
|
-
const CURRENT_YEAR =
|
|
308
|
-
const INITIAL_JS_DAY =
|
|
309
|
-
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY;
|
|
372
|
+
const CURRENT_YEAR = DateTime.now().getFullYear();
|
|
373
|
+
const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
|
|
374
|
+
const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY.getTime();
|
|
310
375
|
const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
|
|
311
376
|
const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
|
|
312
377
|
const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
|
|
@@ -355,7 +420,7 @@ function _parseDateTime(str) {
|
|
|
355
420
|
return {
|
|
356
421
|
value: date.value + time.value,
|
|
357
422
|
format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
|
|
358
|
-
jsDate: new
|
|
423
|
+
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()),
|
|
359
424
|
};
|
|
360
425
|
}
|
|
361
426
|
return date || time;
|
|
@@ -372,13 +437,13 @@ function parseDate(str, dateFormat) {
|
|
|
372
437
|
const day = Number(parts[dayIndex]);
|
|
373
438
|
const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
|
|
374
439
|
const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
|
|
375
|
-
const jsDate = new
|
|
440
|
+
const jsDate = new DateTime(year, month - 1, day);
|
|
376
441
|
const sep = str.match(/\/|-|\s/)[0];
|
|
377
442
|
if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
|
|
378
443
|
// invalid date
|
|
379
444
|
return null;
|
|
380
445
|
}
|
|
381
|
-
const delta = jsDate - INITIAL_1900_DAY;
|
|
446
|
+
const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
|
|
382
447
|
let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
|
|
383
448
|
if (parts[yearIndex]) {
|
|
384
449
|
format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
|
|
@@ -438,7 +503,7 @@ function parseTime(str) {
|
|
|
438
503
|
if (hours >= 24) {
|
|
439
504
|
format = "hhhh:mm:ss";
|
|
440
505
|
}
|
|
441
|
-
const jsDate = new
|
|
506
|
+
const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
|
|
442
507
|
return {
|
|
443
508
|
value: hours / 24 + minutes / 1440 + seconds / 86400,
|
|
444
509
|
format: format,
|
|
@@ -452,7 +517,7 @@ function parseTime(str) {
|
|
|
452
517
|
// -----------------------------------------------------------------------------
|
|
453
518
|
function numberToJsDate(value) {
|
|
454
519
|
const truncValue = Math.trunc(value);
|
|
455
|
-
let date =
|
|
520
|
+
let date = DateTime.fromTimestamp(truncValue * MS_PER_DAY - DATE_JS_1900_OFFSET);
|
|
456
521
|
let time = value - truncValue;
|
|
457
522
|
time = time < 0 ? 1 + time : time;
|
|
458
523
|
const hours = Math.round(time * 24);
|
|
@@ -469,7 +534,7 @@ function jsDateToRoundNumber(date) {
|
|
|
469
534
|
}
|
|
470
535
|
/** Return the number of days in the current month of the given date */
|
|
471
536
|
function getDaysInMonth(date) {
|
|
472
|
-
return new
|
|
537
|
+
return new DateTime(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
473
538
|
}
|
|
474
539
|
function isLastDayOfMonth(date) {
|
|
475
540
|
return getDaysInMonth(date) === date.getDate();
|
|
@@ -487,7 +552,7 @@ function addMonthsToDate(date, months, keepEndOfMonth) {
|
|
|
487
552
|
const yStart = date.getFullYear();
|
|
488
553
|
const mStart = date.getMonth();
|
|
489
554
|
const dStart = date.getDate();
|
|
490
|
-
const jsDate = new
|
|
555
|
+
const jsDate = new DateTime(yStart, mStart + months, 1);
|
|
491
556
|
if (keepEndOfMonth && dStart === getDaysInMonth(date)) {
|
|
492
557
|
jsDate.setDate(getDaysInMonth(jsDate));
|
|
493
558
|
}
|
|
@@ -647,13 +712,6 @@ function areTwoDatesWithinOneYear(startDate, endDate) {
|
|
|
647
712
|
}
|
|
648
713
|
|
|
649
714
|
//------------------------------------------------------------------------------
|
|
650
|
-
/**
|
|
651
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
652
|
-
* is ordered.
|
|
653
|
-
*/
|
|
654
|
-
function stringify(obj) {
|
|
655
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
656
|
-
}
|
|
657
715
|
/**
|
|
658
716
|
* Remove quotes from a quoted string
|
|
659
717
|
* ```js
|
|
@@ -883,7 +941,7 @@ function isBoolean(str) {
|
|
|
883
941
|
function isDateTime(str) {
|
|
884
942
|
return parseDateTime(str) !== null;
|
|
885
943
|
}
|
|
886
|
-
const MARKDOWN_LINK_REGEX = /^\[(
|
|
944
|
+
const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
|
|
887
945
|
//link must start with http or https
|
|
888
946
|
//https://stackoverflow.com/a/3809435/4760614
|
|
889
947
|
const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
|
|
@@ -952,7 +1010,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
952
1010
|
*/
|
|
953
1011
|
function getItemId(item, itemsDic) {
|
|
954
1012
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
955
|
-
if (
|
|
1013
|
+
if (deepEquals(value, item)) {
|
|
956
1014
|
return parseInt(key, 10);
|
|
957
1015
|
}
|
|
958
1016
|
}
|
|
@@ -1952,7 +2010,7 @@ function formatJSTime(jsDate, format) {
|
|
|
1952
2010
|
.map((p) => {
|
|
1953
2011
|
switch (p) {
|
|
1954
2012
|
case "hhhh":
|
|
1955
|
-
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY) / (60 * 60 * 1000));
|
|
2013
|
+
const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY.getTime()) / (60 * 60 * 1000));
|
|
1956
2014
|
return helapsedHours.toString();
|
|
1957
2015
|
case "hh":
|
|
1958
2016
|
return hours.toString().padStart(2, "0");
|
|
@@ -2199,8 +2257,10 @@ function convertInternalFormatToFormat(internalFormat) {
|
|
|
2199
2257
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
2200
2258
|
// Same as above, but matches the exact string (nothing before or after)
|
|
2201
2259
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
2202
|
-
/** Reference of a column header (eg. A, AB) */
|
|
2203
|
-
const colHeader = new RegExp(
|
|
2260
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
2261
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
2262
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
2263
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
2204
2264
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
2205
2265
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
2206
2266
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -2230,6 +2290,9 @@ function isRowReference(xc) {
|
|
|
2230
2290
|
function isColHeader(str) {
|
|
2231
2291
|
return colHeader.test(str);
|
|
2232
2292
|
}
|
|
2293
|
+
function isRowHeader(str) {
|
|
2294
|
+
return rowHeader.test(str);
|
|
2295
|
+
}
|
|
2233
2296
|
/**
|
|
2234
2297
|
* Return true if the given xc is the reference of a single cell,
|
|
2235
2298
|
* without any specified sheet (e.g. A1)
|
|
@@ -2296,18 +2359,10 @@ class RangeImpl {
|
|
|
2296
2359
|
if (isFullCol) {
|
|
2297
2360
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2298
2361
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2299
|
-
if (zone.left === zone.right) {
|
|
2300
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2301
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2302
|
-
}
|
|
2303
2362
|
}
|
|
2304
2363
|
if (isFullRow) {
|
|
2305
2364
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2306
2365
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2307
|
-
if (zone.top === zone.bottom) {
|
|
2308
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2309
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2310
|
-
}
|
|
2311
2366
|
}
|
|
2312
2367
|
return parts;
|
|
2313
2368
|
}
|
|
@@ -5167,6 +5222,7 @@ const FilterMenuPopoverBuilder = {
|
|
|
5167
5222
|
},
|
|
5168
5223
|
};
|
|
5169
5224
|
|
|
5225
|
+
const macRegex = /Mac/i;
|
|
5170
5226
|
/**
|
|
5171
5227
|
* Return true if the event was triggered from
|
|
5172
5228
|
* a child element.
|
|
@@ -5212,6 +5268,17 @@ function setElementScrollTop(el, scroll) {
|
|
|
5212
5268
|
}
|
|
5213
5269
|
function getOpenedMenus() {
|
|
5214
5270
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5271
|
+
}
|
|
5272
|
+
function isMacOS() {
|
|
5273
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
5274
|
+
}
|
|
5275
|
+
/**
|
|
5276
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
5277
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
5278
|
+
* On Mac, this is the "meta" or "command" key.
|
|
5279
|
+
*/
|
|
5280
|
+
function isCtrlKey(ev) {
|
|
5281
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
5215
5282
|
}
|
|
5216
5283
|
|
|
5217
5284
|
/**
|
|
@@ -9598,6 +9665,9 @@ function arg(definition, description = "") {
|
|
|
9598
9665
|
function makeArg(str, description) {
|
|
9599
9666
|
let parts = str.match(ARG_REGEXP);
|
|
9600
9667
|
let name = parts[1].trim();
|
|
9668
|
+
if (!name) {
|
|
9669
|
+
throw new Error(`Function argument definition is missing a name: '${str}'.`);
|
|
9670
|
+
}
|
|
9601
9671
|
let types = [];
|
|
9602
9672
|
let isOptional = false;
|
|
9603
9673
|
let isRepeating = false;
|
|
@@ -12051,7 +12121,7 @@ const DATE = {
|
|
|
12051
12121
|
if (_year < 1900) {
|
|
12052
12122
|
_year += 1900;
|
|
12053
12123
|
}
|
|
12054
|
-
const jsDate = new
|
|
12124
|
+
const jsDate = new DateTime(_year, _month - 1, _day);
|
|
12055
12125
|
const result = jsDateToRoundNumber(jsDate);
|
|
12056
12126
|
assert(() => result >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
|
|
12057
12127
|
return result;
|
|
@@ -12094,7 +12164,7 @@ const DATEDIF = {
|
|
|
12094
12164
|
// See: https://support.microsoft.com/en-us/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c
|
|
12095
12165
|
let days = jsEndDate.getDate() - jsStartDate.getDate();
|
|
12096
12166
|
if (days < 0) {
|
|
12097
|
-
const monthBeforeEndMonth = new
|
|
12167
|
+
const monthBeforeEndMonth = new DateTime(jsEndDate.getFullYear(), jsEndDate.getMonth() - 1, 1);
|
|
12098
12168
|
const daysInMonthBeforeEndMonth = getDaysInMonth(monthBeforeEndMonth);
|
|
12099
12169
|
days = daysInMonthBeforeEndMonth - Math.abs(days);
|
|
12100
12170
|
}
|
|
@@ -12103,7 +12173,7 @@ const DATEDIF = {
|
|
|
12103
12173
|
if (areTwoDatesWithinOneYear(_startDate, _endDate)) {
|
|
12104
12174
|
return getTimeDifferenceInWholeDays(jsStartDate, jsEndDate);
|
|
12105
12175
|
}
|
|
12106
|
-
const endDateWithinOneYear = new
|
|
12176
|
+
const endDateWithinOneYear = new DateTime(jsStartDate.getFullYear(), jsEndDate.getMonth(), jsEndDate.getDate());
|
|
12107
12177
|
let days = getTimeDifferenceInWholeDays(jsStartDate, endDateWithinOneYear);
|
|
12108
12178
|
if (days < 0) {
|
|
12109
12179
|
endDateWithinOneYear.setFullYear(jsStartDate.getFullYear() + 1);
|
|
@@ -12216,7 +12286,7 @@ const EOMONTH = {
|
|
|
12216
12286
|
const _months = Math.trunc(toNumber(months));
|
|
12217
12287
|
const yStart = _startDate.getFullYear();
|
|
12218
12288
|
const mStart = _startDate.getMonth();
|
|
12219
|
-
const jsDate = new
|
|
12289
|
+
const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
|
|
12220
12290
|
return jsDateToRoundNumber(jsDate);
|
|
12221
12291
|
},
|
|
12222
12292
|
isExported: true,
|
|
@@ -12253,17 +12323,17 @@ const ISOWEEKNUM = {
|
|
|
12253
12323
|
// The first week of the year is the week that contains the first
|
|
12254
12324
|
// Thursday of the year.
|
|
12255
12325
|
let firstThursday = 1;
|
|
12256
|
-
while (new
|
|
12326
|
+
while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
|
|
12257
12327
|
firstThursday += 1;
|
|
12258
12328
|
}
|
|
12259
|
-
const firstDayOfFirstWeek = new
|
|
12329
|
+
const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
|
|
12260
12330
|
// The last week of the year is the week that contains the last Thursday of
|
|
12261
12331
|
// the year.
|
|
12262
12332
|
let lastThursday = 31;
|
|
12263
|
-
while (new
|
|
12333
|
+
while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
|
|
12264
12334
|
lastThursday -= 1;
|
|
12265
12335
|
}
|
|
12266
|
-
const lastDayOfLastWeek = new
|
|
12336
|
+
const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
|
|
12267
12337
|
// B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
|
|
12268
12338
|
// If our date < firstDayOfFirstWeek then it's in the weeks of the year before
|
|
12269
12339
|
let offsetYear;
|
|
@@ -12289,17 +12359,17 @@ const ISOWEEKNUM = {
|
|
|
12289
12359
|
case 1:
|
|
12290
12360
|
// firstDay is the 1st day of the 1st week of the year after
|
|
12291
12361
|
// firstDay = lastDayOfLastWeek + 1 Day
|
|
12292
|
-
firstDay = new
|
|
12362
|
+
firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
|
|
12293
12363
|
break;
|
|
12294
12364
|
case -1:
|
|
12295
12365
|
// firstDay is the 1st day of the 1st week of the previous year.
|
|
12296
12366
|
// The first week of the previous year is the week that contains the
|
|
12297
12367
|
// first Thursday of the previous year.
|
|
12298
12368
|
let firstThursdayPreviousYear = 1;
|
|
12299
|
-
while (new
|
|
12369
|
+
while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
|
|
12300
12370
|
firstThursdayPreviousYear += 1;
|
|
12301
12371
|
}
|
|
12302
|
-
firstDay = new
|
|
12372
|
+
firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
|
|
12303
12373
|
break;
|
|
12304
12374
|
}
|
|
12305
12375
|
const diff = (_date.getTime() - firstDay.getTime()) / MS_PER_DAY;
|
|
@@ -12434,8 +12504,8 @@ const NETWORKDAYS_INTL = {
|
|
|
12434
12504
|
});
|
|
12435
12505
|
}
|
|
12436
12506
|
const invertDate = _startDate.getTime() > _endDate.getTime();
|
|
12437
|
-
const stopDate =
|
|
12438
|
-
let stepDate =
|
|
12507
|
+
const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
|
|
12508
|
+
let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
|
|
12439
12509
|
const timeStopDate = stopDate.getTime();
|
|
12440
12510
|
let timeStepDate = stepDate.getTime();
|
|
12441
12511
|
let netWorkingDay = 0;
|
|
@@ -12459,8 +12529,7 @@ const NOW = {
|
|
|
12459
12529
|
returns: ["DATE"],
|
|
12460
12530
|
computeFormat: () => "m/d/yyyy hh:mm:ss",
|
|
12461
12531
|
compute: function () {
|
|
12462
|
-
let today =
|
|
12463
|
-
today.setMilliseconds(0);
|
|
12532
|
+
let today = DateTime.now();
|
|
12464
12533
|
const delta = today.getTime() - INITIAL_1900_DAY.getTime();
|
|
12465
12534
|
const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
|
|
12466
12535
|
return Math.floor(delta / MS_PER_DAY) + time;
|
|
@@ -12530,8 +12599,8 @@ const TODAY = {
|
|
|
12530
12599
|
returns: ["DATE"],
|
|
12531
12600
|
computeFormat: () => "m/d/yyyy",
|
|
12532
12601
|
compute: function () {
|
|
12533
|
-
const today =
|
|
12534
|
-
const jsDate = new
|
|
12602
|
+
const today = DateTime.now();
|
|
12603
|
+
const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
|
|
12535
12604
|
return jsDateToRoundNumber(jsDate);
|
|
12536
12605
|
},
|
|
12537
12606
|
isExported: true,
|
|
@@ -12586,10 +12655,10 @@ const WEEKNUM = {
|
|
|
12586
12655
|
}
|
|
12587
12656
|
const y = _date.getFullYear();
|
|
12588
12657
|
let dayStart = 1;
|
|
12589
|
-
let startDayOfFirstWeek = new
|
|
12658
|
+
let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12590
12659
|
while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
|
|
12591
12660
|
dayStart += 1;
|
|
12592
|
-
startDayOfFirstWeek = new
|
|
12661
|
+
startDayOfFirstWeek = new DateTime(y, 0, dayStart);
|
|
12593
12662
|
}
|
|
12594
12663
|
const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / MS_PER_DAY;
|
|
12595
12664
|
if (dif < 0) {
|
|
@@ -12643,7 +12712,7 @@ const WORKDAY_INTL = {
|
|
|
12643
12712
|
timesHoliday.add(holiday.getTime());
|
|
12644
12713
|
});
|
|
12645
12714
|
}
|
|
12646
|
-
let stepDate =
|
|
12715
|
+
let stepDate = DateTime.fromTimestamp(_startDate.getTime());
|
|
12647
12716
|
let timeStepDate = stepDate.getTime();
|
|
12648
12717
|
const unitDay = Math.sign(_numDays);
|
|
12649
12718
|
let stepDay = Math.abs(_numDays);
|
|
@@ -12705,7 +12774,7 @@ const MONTH_START = {
|
|
|
12705
12774
|
const _startDate = toJsDate(date);
|
|
12706
12775
|
const yStart = _startDate.getFullYear();
|
|
12707
12776
|
const mStart = _startDate.getMonth();
|
|
12708
|
-
const jsDate = new
|
|
12777
|
+
const jsDate = new DateTime(yStart, mStart, 1);
|
|
12709
12778
|
return jsDateToRoundNumber(jsDate);
|
|
12710
12779
|
},
|
|
12711
12780
|
};
|
|
@@ -12743,7 +12812,7 @@ const QUARTER_START = {
|
|
|
12743
12812
|
compute: function (date) {
|
|
12744
12813
|
const quarter = QUARTER.compute(date);
|
|
12745
12814
|
const year = YEAR.compute(date);
|
|
12746
|
-
const jsDate = new
|
|
12815
|
+
const jsDate = new DateTime(year, (quarter - 1) * 3, 1);
|
|
12747
12816
|
return jsDateToRoundNumber(jsDate);
|
|
12748
12817
|
},
|
|
12749
12818
|
};
|
|
@@ -12758,7 +12827,7 @@ const QUARTER_END = {
|
|
|
12758
12827
|
compute: function (date) {
|
|
12759
12828
|
const quarter = QUARTER.compute(date);
|
|
12760
12829
|
const year = YEAR.compute(date);
|
|
12761
|
-
const jsDate = new
|
|
12830
|
+
const jsDate = new DateTime(year, quarter * 3, 0);
|
|
12762
12831
|
return jsDateToRoundNumber(jsDate);
|
|
12763
12832
|
},
|
|
12764
12833
|
};
|
|
@@ -12772,7 +12841,7 @@ const YEAR_START = {
|
|
|
12772
12841
|
computeFormat: () => "m/d/yyyy",
|
|
12773
12842
|
compute: function (date) {
|
|
12774
12843
|
const year = YEAR.compute(date);
|
|
12775
|
-
const jsDate = new
|
|
12844
|
+
const jsDate = new DateTime(year, 0, 1);
|
|
12776
12845
|
return jsDateToRoundNumber(jsDate);
|
|
12777
12846
|
},
|
|
12778
12847
|
};
|
|
@@ -12786,7 +12855,7 @@ const YEAR_END = {
|
|
|
12786
12855
|
computeFormat: () => "m/d/yyyy",
|
|
12787
12856
|
compute: function (date) {
|
|
12788
12857
|
const year = YEAR.compute(date);
|
|
12789
|
-
const jsDate = new
|
|
12858
|
+
const jsDate = new DateTime(year + 1, 0, 0);
|
|
12790
12859
|
return jsDateToRoundNumber(jsDate);
|
|
12791
12860
|
},
|
|
12792
12861
|
};
|
|
@@ -12834,8 +12903,8 @@ const DEFAULT_DELTA_ARG = 0;
|
|
|
12834
12903
|
const DELTA = {
|
|
12835
12904
|
description: _lt("Compare two numeric values, returning 1 if they're equal."),
|
|
12836
12905
|
args: [
|
|
12837
|
-
arg(" (number)", _lt("The first number to compare.")),
|
|
12838
|
-
arg(` (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12906
|
+
arg("number1 (number)", _lt("The first number to compare.")),
|
|
12907
|
+
arg(`number2 (number, default=${DEFAULT_DELTA_ARG})`, _lt("The second number to compare.")),
|
|
12839
12908
|
],
|
|
12840
12909
|
returns: ["NUMBER"],
|
|
12841
12910
|
compute: function (number1, number2 = DEFAULT_DELTA_ARG) {
|
|
@@ -12921,7 +12990,7 @@ function assertDeprecationFactorStrictlyPositive(factor) {
|
|
|
12921
12990
|
function assertSettlementLessThanOneYearBeforeMaturity(settlement, maturity) {
|
|
12922
12991
|
const startDate = toJsDate(settlement);
|
|
12923
12992
|
const endDate = toJsDate(maturity);
|
|
12924
|
-
const startDatePlusOneYear =
|
|
12993
|
+
const startDatePlusOneYear = toJsDate(settlement);
|
|
12925
12994
|
startDatePlusOneYear.setFullYear(startDate.getFullYear() + 1);
|
|
12926
12995
|
assert(() => endDate.getTime() <= startDatePlusOneYear.getTime(), _lt("The settlement date (%s) must at most one year after the maturity date (%s).", settlement.toString(), maturity.toString()));
|
|
12927
12996
|
}
|
|
@@ -13056,7 +13125,7 @@ const AMORLINC = {
|
|
|
13056
13125
|
arg("salvage (number)", _lt("The value of the asset at the end of depreciation.")),
|
|
13057
13126
|
arg("period (number)", _lt("The single period within life for which to calculate depreciation.")),
|
|
13058
13127
|
arg("rate (number)", _lt("The deprecation rate.")),
|
|
13059
|
-
arg(" (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
13128
|
+
arg("day_count_convention (number, optional)", _lt("An indicator of what day count method to use.")),
|
|
13060
13129
|
],
|
|
13061
13130
|
returns: ["NUMBER"],
|
|
13062
13131
|
compute: function (cost, purchaseDate, firstPeriodEnd, salvage, period, rate, dayCountConvention = DEFAULT_DAY_COUNT_CONVENTION) {
|
|
@@ -16039,8 +16108,8 @@ const MID = {
|
|
|
16039
16108
|
description: _lt("A segment of a string."),
|
|
16040
16109
|
args: [
|
|
16041
16110
|
arg("text (string)", _lt("The string to extract a segment from.")),
|
|
16042
|
-
arg(" (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
16043
|
-
arg(" (number)", _lt("The length of the segment to extract.")),
|
|
16111
|
+
arg("starting_at (number)", _lt("The index from the left of string from which to begin extracting. The first character in string has the index 1.")),
|
|
16112
|
+
arg("extract_length (number)", _lt("The length of the segment to extract.")),
|
|
16044
16113
|
],
|
|
16045
16114
|
returns: ["STRING"],
|
|
16046
16115
|
compute: function (text, starting_at, extract_length) {
|
|
@@ -17709,10 +17778,10 @@ const arrowMap = {
|
|
|
17709
17778
|
function updateSelectionWithArrowKeys(ev, selection) {
|
|
17710
17779
|
const direction = arrowMap[ev.key];
|
|
17711
17780
|
if (ev.shiftKey) {
|
|
17712
|
-
selection.resizeAnchorZone(direction, ev
|
|
17781
|
+
selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
17713
17782
|
}
|
|
17714
17783
|
else {
|
|
17715
|
-
selection.moveAnchorCell(direction, ev
|
|
17784
|
+
selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
17716
17785
|
}
|
|
17717
17786
|
}
|
|
17718
17787
|
|
|
@@ -22409,7 +22478,10 @@ class GridOverlay extends Component {
|
|
|
22409
22478
|
return;
|
|
22410
22479
|
}
|
|
22411
22480
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
22412
|
-
this.props.onCellClicked(col, row, {
|
|
22481
|
+
this.props.onCellClicked(col, row, {
|
|
22482
|
+
expandZone: ev.shiftKey,
|
|
22483
|
+
addZone: isCtrlKey(ev),
|
|
22484
|
+
});
|
|
22413
22485
|
}
|
|
22414
22486
|
onDoubleClick(ev) {
|
|
22415
22487
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -22482,6 +22554,7 @@ class AbstractResizer extends Component {
|
|
|
22482
22554
|
draggerShadowThickness: 0,
|
|
22483
22555
|
delta: 0,
|
|
22484
22556
|
base: 0,
|
|
22557
|
+
position: "before",
|
|
22485
22558
|
});
|
|
22486
22559
|
_computeHandleDisplay(ev) {
|
|
22487
22560
|
const position = this._getEvOffset(ev);
|
|
@@ -22606,11 +22679,13 @@ class AbstractResizer extends Component {
|
|
|
22606
22679
|
this.state.draggerLinePosition = dimensions.start;
|
|
22607
22680
|
this.state.draggerShadowPosition = dimensions.start;
|
|
22608
22681
|
this.state.base = elementIndex;
|
|
22682
|
+
this.state.position = "before";
|
|
22609
22683
|
}
|
|
22610
22684
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
22611
22685
|
this.state.draggerLinePosition = dimensions.end;
|
|
22612
22686
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
22613
|
-
this.state.base = elementIndex
|
|
22687
|
+
this.state.base = elementIndex;
|
|
22688
|
+
this.state.position = "after";
|
|
22614
22689
|
}
|
|
22615
22690
|
else {
|
|
22616
22691
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -22634,7 +22709,7 @@ class AbstractResizer extends Component {
|
|
|
22634
22709
|
this._increaseSelection(index);
|
|
22635
22710
|
}
|
|
22636
22711
|
else {
|
|
22637
|
-
this._selectElement(index, ev
|
|
22712
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
22638
22713
|
}
|
|
22639
22714
|
this.lastSelectedElementIndex = index;
|
|
22640
22715
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -22647,7 +22722,7 @@ class AbstractResizer extends Component {
|
|
|
22647
22722
|
const mouseUpSelect = () => {
|
|
22648
22723
|
this.state.isSelecting = false;
|
|
22649
22724
|
this.lastSelectedElementIndex = null;
|
|
22650
|
-
this.env.model.dispatch(ev
|
|
22725
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
22651
22726
|
this._computeGrabDisplay(ev);
|
|
22652
22727
|
};
|
|
22653
22728
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -22793,13 +22868,14 @@ class ColResizer extends AbstractResizer {
|
|
|
22793
22868
|
dimension: "COL",
|
|
22794
22869
|
base: this.state.base,
|
|
22795
22870
|
elements,
|
|
22871
|
+
position: this.state.position,
|
|
22796
22872
|
});
|
|
22797
22873
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22798
22874
|
this.env.raiseError(MergeErrorMessage);
|
|
22799
22875
|
}
|
|
22800
22876
|
}
|
|
22801
|
-
_selectElement(index,
|
|
22802
|
-
this.env.model.selection.selectColumn(index,
|
|
22877
|
+
_selectElement(index, addDistinctHeader) {
|
|
22878
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22803
22879
|
}
|
|
22804
22880
|
_increaseSelection(index) {
|
|
22805
22881
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -22966,13 +23042,14 @@ class RowResizer extends AbstractResizer {
|
|
|
22966
23042
|
dimension: "ROW",
|
|
22967
23043
|
base: this.state.base,
|
|
22968
23044
|
elements,
|
|
23045
|
+
position: this.state.position,
|
|
22969
23046
|
});
|
|
22970
23047
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22971
23048
|
this.env.raiseError(MergeErrorMessage);
|
|
22972
23049
|
}
|
|
22973
23050
|
}
|
|
22974
|
-
_selectElement(index,
|
|
22975
|
-
this.env.model.selection.selectRow(index,
|
|
23051
|
+
_selectElement(index, addDistinctHeader) {
|
|
23052
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22976
23053
|
}
|
|
22977
23054
|
_increaseSelection(index) {
|
|
22978
23055
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -23073,8 +23150,8 @@ function useWheelHandler(handler) {
|
|
|
23073
23150
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
23074
23151
|
}
|
|
23075
23152
|
const onMouseWheel = (ev) => {
|
|
23076
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23077
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23153
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
23154
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
23078
23155
|
handler(deltaX, deltaY);
|
|
23079
23156
|
};
|
|
23080
23157
|
return onMouseWheel;
|
|
@@ -23776,8 +23853,8 @@ class Grid extends Component {
|
|
|
23776
23853
|
// ---------------------------------------------------------------------------
|
|
23777
23854
|
// Zone selection with mouse
|
|
23778
23855
|
// ---------------------------------------------------------------------------
|
|
23779
|
-
onCellClicked(col, row, {
|
|
23780
|
-
if (
|
|
23856
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
23857
|
+
if (addZone) {
|
|
23781
23858
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
23782
23859
|
}
|
|
23783
23860
|
if (this.env.model.getters.hasOpenedPopover()) {
|
|
@@ -23786,10 +23863,10 @@ class Grid extends Component {
|
|
|
23786
23863
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
23787
23864
|
this.env.model.dispatch("STOP_EDITION");
|
|
23788
23865
|
}
|
|
23789
|
-
if (
|
|
23866
|
+
if (expandZone) {
|
|
23790
23867
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
23791
23868
|
}
|
|
23792
|
-
else if (
|
|
23869
|
+
else if (addZone) {
|
|
23793
23870
|
this.env.model.selection.addCellToSelection(col, row);
|
|
23794
23871
|
}
|
|
23795
23872
|
else {
|
|
@@ -23851,9 +23928,7 @@ class Grid extends Component {
|
|
|
23851
23928
|
return;
|
|
23852
23929
|
}
|
|
23853
23930
|
let keyDownString = "";
|
|
23854
|
-
if (ev
|
|
23855
|
-
keyDownString += "CTRL+";
|
|
23856
|
-
if (ev.metaKey)
|
|
23931
|
+
if (isCtrlKey(ev))
|
|
23857
23932
|
keyDownString += "CTRL+";
|
|
23858
23933
|
if (ev.altKey)
|
|
23859
23934
|
keyDownString += "ALT+";
|
|
@@ -25761,7 +25836,7 @@ const machine = {
|
|
|
25761
25836
|
SPACE: goTo(State.RightRef),
|
|
25762
25837
|
NUMBER: goTo(State.Found),
|
|
25763
25838
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
25764
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
25839
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
25765
25840
|
},
|
|
25766
25841
|
[State.RightColumnRef]: {
|
|
25767
25842
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -25772,6 +25847,7 @@ const machine = {
|
|
|
25772
25847
|
SPACE: goTo(State.RightRowRef),
|
|
25773
25848
|
NUMBER: goTo(State.Found),
|
|
25774
25849
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
25850
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
25775
25851
|
},
|
|
25776
25852
|
[State.Found]: {},
|
|
25777
25853
|
};
|
|
@@ -29479,7 +29555,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
29479
29555
|
*/
|
|
29480
29556
|
function getBorderId(border) {
|
|
29481
29557
|
for (let [key, value] of Object.entries(borders)) {
|
|
29482
|
-
if (
|
|
29558
|
+
if (deepEquals(value, border)) {
|
|
29483
29559
|
return parseInt(key, 10);
|
|
29484
29560
|
}
|
|
29485
29561
|
}
|
|
@@ -32447,7 +32523,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
32447
32523
|
const elements = cmd.dimension === "COL"
|
|
32448
32524
|
? this.getNumberCols(cmd.sheetId)
|
|
32449
32525
|
: this.getNumberRows(cmd.sheetId);
|
|
32450
|
-
if (cmd.base < 0 || cmd.base
|
|
32526
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
32451
32527
|
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
32452
32528
|
}
|
|
32453
32529
|
else if (cmd.quantity <= 0) {
|
|
@@ -33480,13 +33556,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
33480
33556
|
// Getters
|
|
33481
33557
|
// ---------------------------------------------------------------------------
|
|
33482
33558
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
33483
|
-
|
|
33484
|
-
|
|
33485
|
-
|
|
33486
|
-
|
|
33487
|
-
|
|
33559
|
+
try {
|
|
33560
|
+
const compiledFormula = compile(formulaString);
|
|
33561
|
+
const params = this.getCompilationParameters((cell) => this.getEvaluatedCell(this.getters.getCellPosition(cell.id)));
|
|
33562
|
+
const ranges = [];
|
|
33563
|
+
for (let xc of compiledFormula.dependencies) {
|
|
33564
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
33565
|
+
}
|
|
33566
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
33567
|
+
}
|
|
33568
|
+
catch (error) {
|
|
33569
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
33488
33570
|
}
|
|
33489
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
33490
33571
|
}
|
|
33491
33572
|
/**
|
|
33492
33573
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -33911,39 +33992,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33911
33992
|
this.computedIcons[sheetId] = {};
|
|
33912
33993
|
const computedStyle = this.computedStyles[sheetId];
|
|
33913
33994
|
for (let cf of this.getters.getConditionalFormats(sheetId).reverse()) {
|
|
33914
|
-
|
|
33915
|
-
|
|
33916
|
-
|
|
33917
|
-
|
|
33918
|
-
|
|
33919
|
-
|
|
33920
|
-
|
|
33921
|
-
|
|
33922
|
-
|
|
33923
|
-
|
|
33924
|
-
|
|
33925
|
-
|
|
33926
|
-
|
|
33927
|
-
|
|
33928
|
-
|
|
33929
|
-
for (let
|
|
33930
|
-
|
|
33931
|
-
|
|
33932
|
-
|
|
33933
|
-
if (
|
|
33934
|
-
|
|
33935
|
-
|
|
33936
|
-
|
|
33937
|
-
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
33938
|
-
}
|
|
33995
|
+
switch (cf.rule.type) {
|
|
33996
|
+
case "ColorScaleRule":
|
|
33997
|
+
for (let range of cf.ranges) {
|
|
33998
|
+
this.applyColorScale(range, cf.rule);
|
|
33999
|
+
}
|
|
34000
|
+
break;
|
|
34001
|
+
case "IconSetRule":
|
|
34002
|
+
for (let range of cf.ranges) {
|
|
34003
|
+
this.applyIcon(range, cf.rule);
|
|
34004
|
+
}
|
|
34005
|
+
break;
|
|
34006
|
+
default:
|
|
34007
|
+
for (let ref of cf.ranges) {
|
|
34008
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
34009
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
34010
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
34011
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
34012
|
+
let cell = this.getters.getEvaluatedCell({ sheetId, col, row });
|
|
34013
|
+
if (pr && pr(cell, cf.rule)) {
|
|
34014
|
+
if (!computedStyle[col])
|
|
34015
|
+
computedStyle[col] = [];
|
|
34016
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
34017
|
+
computedStyle[col][row] = Object.assign(computedStyle[col]?.[row] || {}, cf.rule.style);
|
|
33939
34018
|
}
|
|
33940
34019
|
}
|
|
33941
34020
|
}
|
|
33942
|
-
|
|
33943
|
-
|
|
33944
|
-
}
|
|
33945
|
-
catch (_) {
|
|
33946
|
-
// we don't care about the errors within the evaluation of a rule
|
|
34021
|
+
}
|
|
34022
|
+
break;
|
|
33947
34023
|
}
|
|
33948
34024
|
}
|
|
33949
34025
|
}
|
|
@@ -33968,7 +34044,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
33968
34044
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
33969
34045
|
case "formula":
|
|
33970
34046
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
33971
|
-
return
|
|
34047
|
+
return typeof value === "number" ? value : null;
|
|
33972
34048
|
default:
|
|
33973
34049
|
return null;
|
|
33974
34050
|
}
|
|
@@ -35617,19 +35693,21 @@ class AutofillPlugin extends UIPlugin {
|
|
|
35617
35693
|
let col = zone.left;
|
|
35618
35694
|
let row = zone.bottom;
|
|
35619
35695
|
if (col > 0) {
|
|
35620
|
-
let
|
|
35621
|
-
while (
|
|
35696
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
35697
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
35698
|
+
this.getters.getCell(leftPosition)?.content) {
|
|
35622
35699
|
row += 1;
|
|
35623
|
-
|
|
35700
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
35624
35701
|
}
|
|
35625
35702
|
}
|
|
35626
35703
|
if (row === zone.bottom) {
|
|
35627
35704
|
col = zone.right;
|
|
35628
35705
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
35629
|
-
let
|
|
35630
|
-
while (
|
|
35706
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
35707
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
35708
|
+
this.getters.getCell(rightPosition)?.content) {
|
|
35631
35709
|
row += 1;
|
|
35632
|
-
|
|
35710
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
35633
35711
|
}
|
|
35634
35712
|
}
|
|
35635
35713
|
}
|
|
@@ -40577,6 +40655,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
40577
40655
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
40578
40656
|
case "colrow":
|
|
40579
40657
|
indexOfNumber = xc.search(/[0-9]/);
|
|
40658
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
40659
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
40660
|
+
return "$" + xc;
|
|
40661
|
+
}
|
|
40580
40662
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
40581
40663
|
return "$" + xc;
|
|
40582
40664
|
case "none":
|
|
@@ -41758,7 +41840,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41758
41840
|
sheetId: cmd.sheetId,
|
|
41759
41841
|
base: cmd.base,
|
|
41760
41842
|
quantity: thickness,
|
|
41761
|
-
position:
|
|
41843
|
+
position: cmd.position,
|
|
41762
41844
|
});
|
|
41763
41845
|
const isCol = cmd.dimension === "COL";
|
|
41764
41846
|
const start = cmd.elements[0];
|
|
@@ -41775,12 +41857,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41775
41857
|
},
|
|
41776
41858
|
];
|
|
41777
41859
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
41860
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
41778
41861
|
const pasteTarget = [
|
|
41779
41862
|
{
|
|
41780
|
-
left: isCol ?
|
|
41781
|
-
right: isCol ?
|
|
41782
|
-
top: !isCol ?
|
|
41783
|
-
bottom: !isCol ?
|
|
41863
|
+
left: isCol ? base : 0,
|
|
41864
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
41865
|
+
top: !isCol ? base : 0,
|
|
41866
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
41784
41867
|
},
|
|
41785
41868
|
];
|
|
41786
41869
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -41817,6 +41900,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
41817
41900
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
41818
41901
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
41819
41902
|
}
|
|
41903
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
41904
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
41905
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
41906
|
+
return 86 /* CommandResult.InvalidHeaderIndex */;
|
|
41907
|
+
}
|
|
41820
41908
|
return 0 /* CommandResult.Success */;
|
|
41821
41909
|
}
|
|
41822
41910
|
//-------------------------------------------
|
|
@@ -44098,7 +44186,7 @@ class Spreadsheet extends Component {
|
|
|
44098
44186
|
}
|
|
44099
44187
|
onKeydown(ev) {
|
|
44100
44188
|
let keyDownString = "";
|
|
44101
|
-
if (ev
|
|
44189
|
+
if (isCtrlKey(ev)) {
|
|
44102
44190
|
keyDownString += "CTRL+";
|
|
44103
44191
|
}
|
|
44104
44192
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -47807,6 +47895,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
47807
47895
|
export { AbstractChart, CommandResult, CorePlugin, 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, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
47808
47896
|
|
|
47809
47897
|
|
|
47810
|
-
__info__.version = '16.3.
|
|
47811
|
-
__info__.date = '
|
|
47812
|
-
__info__.hash = '
|
|
47898
|
+
__info__.version = '16.3.22';
|
|
47899
|
+
__info__.date = '2024-01-17T10:24:07.652Z';
|
|
47900
|
+
__info__.hash = '2c1b136';
|