@odoo/o-spreadsheet 18.0.10 → 18.0.11
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 +694 -314
- package/dist/o-spreadsheet.d.ts +30 -16
- package/dist/o-spreadsheet.esm.js +694 -314
- package/dist/o-spreadsheet.iife.js +694 -314
- package/dist/o-spreadsheet.iife.min.js +372 -345
- package/dist/o_spreadsheet.xml +11 -5
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.0.
|
|
6
|
-
* @date 2025-01-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.0.11
|
|
6
|
+
* @date 2025-01-27T10:08:13.567Z
|
|
7
|
+
* @hash e8c6bd1
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -4210,15 +4210,18 @@
|
|
|
4210
4210
|
let currentIndex;
|
|
4211
4211
|
let currentVal;
|
|
4212
4212
|
let currentType;
|
|
4213
|
+
const getValue = sortOrder === "desc"
|
|
4214
|
+
? (i) => normalizeValue(getValueInData(data, rangeLength - i - 1))
|
|
4215
|
+
: (i) => normalizeValue(getValueInData(data, i));
|
|
4213
4216
|
while (indexRight - indexLeft >= 0) {
|
|
4214
4217
|
indexMedian = Math.floor((indexLeft + indexRight) / 2);
|
|
4215
4218
|
currentIndex = indexMedian;
|
|
4216
|
-
currentVal =
|
|
4219
|
+
currentVal = getValue(currentIndex);
|
|
4217
4220
|
currentType = typeof currentVal;
|
|
4218
4221
|
// 1 - linear search to find value with the same type
|
|
4219
4222
|
while (indexLeft < currentIndex && targetType !== currentType) {
|
|
4220
4223
|
currentIndex--;
|
|
4221
|
-
currentVal =
|
|
4224
|
+
currentVal = getValue(currentIndex);
|
|
4222
4225
|
currentType = typeof currentVal;
|
|
4223
4226
|
}
|
|
4224
4227
|
if (currentType !== targetType || currentVal === undefined || currentVal === null) {
|
|
@@ -4234,8 +4237,7 @@
|
|
|
4234
4237
|
if (matchVal === undefined ||
|
|
4235
4238
|
matchVal === null ||
|
|
4236
4239
|
matchVal < currentVal ||
|
|
4237
|
-
(matchVal === currentVal &&
|
|
4238
|
-
(matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
|
|
4240
|
+
(matchVal === currentVal && matchValIndex < currentIndex)) {
|
|
4239
4241
|
matchVal = currentVal;
|
|
4240
4242
|
matchValIndex = currentIndex;
|
|
4241
4243
|
}
|
|
@@ -4243,15 +4245,13 @@
|
|
|
4243
4245
|
else if (mode === "nextGreater" && currentVal >= _target) {
|
|
4244
4246
|
if (matchVal === undefined ||
|
|
4245
4247
|
matchVal > currentVal ||
|
|
4246
|
-
(matchVal === currentVal &&
|
|
4247
|
-
(matchVal === currentVal && sortOrder === "desc" && matchValIndex > currentIndex)) {
|
|
4248
|
+
(matchVal === currentVal && matchValIndex < currentIndex)) {
|
|
4248
4249
|
matchVal = currentVal;
|
|
4249
4250
|
matchValIndex = currentIndex;
|
|
4250
4251
|
}
|
|
4251
4252
|
}
|
|
4252
4253
|
// 3 - give new indexes for the Binary search
|
|
4253
|
-
if ((
|
|
4254
|
-
(sortOrder === "desc" && currentVal <= _target)) {
|
|
4254
|
+
if (currentVal > _target || (mode === "strict" && currentVal === _target)) {
|
|
4255
4255
|
indexRight = currentIndex - 1;
|
|
4256
4256
|
}
|
|
4257
4257
|
else {
|
|
@@ -4259,7 +4259,10 @@
|
|
|
4259
4259
|
}
|
|
4260
4260
|
}
|
|
4261
4261
|
// note that valMinIndex could be 0
|
|
4262
|
-
|
|
4262
|
+
if (matchValIndex === undefined) {
|
|
4263
|
+
return -1;
|
|
4264
|
+
}
|
|
4265
|
+
return sortOrder === "desc" ? rangeLength - matchValIndex - 1 : matchValIndex;
|
|
4263
4266
|
}
|
|
4264
4267
|
/**
|
|
4265
4268
|
* Perform a linear search and return the index of the match.
|
|
@@ -4391,47 +4394,83 @@
|
|
|
4391
4394
|
return true;
|
|
4392
4395
|
}
|
|
4393
4396
|
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
case "yesterday":
|
|
4400
|
-
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
|
|
4401
|
-
case "tomorrow":
|
|
4402
|
-
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
|
|
4403
|
-
case "lastWeek":
|
|
4404
|
-
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
|
|
4405
|
-
case "lastMonth":
|
|
4406
|
-
return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
|
|
4407
|
-
case "lastYear":
|
|
4408
|
-
return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
|
|
4409
|
-
}
|
|
4397
|
+
/**
|
|
4398
|
+
* Add the `https` prefix to the url if it's missing
|
|
4399
|
+
*/
|
|
4400
|
+
function withHttps(url) {
|
|
4401
|
+
return !/^https?:\/\//i.test(url) ? `https://${url}` : url;
|
|
4410
4402
|
}
|
|
4411
|
-
|
|
4412
|
-
function
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4403
|
+
const urlRegistry = new Registry();
|
|
4404
|
+
function createWebLink(url, label) {
|
|
4405
|
+
url = withHttps(url);
|
|
4406
|
+
return {
|
|
4407
|
+
url,
|
|
4408
|
+
label: label || url,
|
|
4409
|
+
isExternal: true,
|
|
4410
|
+
isUrlEditable: true,
|
|
4411
|
+
};
|
|
4417
4412
|
}
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4413
|
+
urlRegistry.add("sheet_URL", {
|
|
4414
|
+
match: (url) => isSheetUrl(url),
|
|
4415
|
+
createLink: (url, label) => {
|
|
4416
|
+
return {
|
|
4417
|
+
label,
|
|
4418
|
+
url,
|
|
4419
|
+
isExternal: false,
|
|
4420
|
+
isUrlEditable: false,
|
|
4421
|
+
};
|
|
4422
|
+
},
|
|
4423
|
+
urlRepresentation(url, getters) {
|
|
4424
|
+
const sheetId = parseSheetUrl(url);
|
|
4425
|
+
return getters.tryGetSheetName(sheetId) || _t("Invalid sheet");
|
|
4426
|
+
},
|
|
4427
|
+
open(url, env) {
|
|
4428
|
+
const sheetId = parseSheetUrl(url);
|
|
4429
|
+
const result = env.model.dispatch("ACTIVATE_SHEET", {
|
|
4430
|
+
sheetIdFrom: env.model.getters.getActiveSheetId(),
|
|
4431
|
+
sheetIdTo: sheetId,
|
|
4432
|
+
});
|
|
4433
|
+
if (result.isCancelledBecause("SheetIsHidden" /* CommandResult.SheetIsHidden */)) {
|
|
4434
|
+
env.notifyUser({
|
|
4435
|
+
type: "warning",
|
|
4436
|
+
sticky: false,
|
|
4437
|
+
text: _t("Cannot open the link because the linked sheet is hidden."),
|
|
4438
|
+
});
|
|
4439
|
+
}
|
|
4440
|
+
},
|
|
4441
|
+
sequence: 0,
|
|
4442
|
+
});
|
|
4443
|
+
const WebUrlSpec = {
|
|
4444
|
+
createLink: createWebLink,
|
|
4445
|
+
match: (url) => isWebLink(url),
|
|
4446
|
+
open: (url) => window.open(url, "_blank"),
|
|
4447
|
+
urlRepresentation: (url) => url,
|
|
4448
|
+
sequence: 0,
|
|
4449
|
+
};
|
|
4450
|
+
function findMatchingSpec(url) {
|
|
4451
|
+
return (urlRegistry
|
|
4452
|
+
.getAll()
|
|
4453
|
+
.sort((a, b) => a.sequence - b.sequence)
|
|
4454
|
+
.find((urlType) => urlType.match(url)) || WebUrlSpec);
|
|
4421
4455
|
}
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4456
|
+
function urlRepresentation(link, getters) {
|
|
4457
|
+
return findMatchingSpec(link.url).urlRepresentation(link.url, getters);
|
|
4458
|
+
}
|
|
4459
|
+
function openLink(link, env) {
|
|
4460
|
+
findMatchingSpec(link.url).open(link.url, env);
|
|
4461
|
+
}
|
|
4462
|
+
function detectLink(value) {
|
|
4463
|
+
if (typeof value !== "string") {
|
|
4464
|
+
return undefined;
|
|
4465
|
+
}
|
|
4466
|
+
if (isMarkdownLink(value)) {
|
|
4467
|
+
const { label, url } = parseMarkdownLink(value);
|
|
4468
|
+
return findMatchingSpec(url).createLink(url, label);
|
|
4469
|
+
}
|
|
4470
|
+
else if (isWebLink(value)) {
|
|
4471
|
+
return createWebLink(value);
|
|
4472
|
+
}
|
|
4473
|
+
return undefined;
|
|
4435
4474
|
}
|
|
4436
4475
|
|
|
4437
4476
|
function tokenizeFormat(str) {
|
|
@@ -5493,6 +5532,193 @@
|
|
|
5493
5532
|
}
|
|
5494
5533
|
}
|
|
5495
5534
|
|
|
5535
|
+
function evaluateLiteral(literalCell, localeFormat) {
|
|
5536
|
+
const value = isTextFormat(localeFormat.format) ? literalCell.content : literalCell.parsedValue;
|
|
5537
|
+
const functionResult = { value, format: localeFormat.format };
|
|
5538
|
+
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
5539
|
+
}
|
|
5540
|
+
function parseLiteral(content, locale) {
|
|
5541
|
+
if (content.startsWith("=")) {
|
|
5542
|
+
throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
|
|
5543
|
+
}
|
|
5544
|
+
if (content === "") {
|
|
5545
|
+
return null;
|
|
5546
|
+
}
|
|
5547
|
+
if (isNumber(content, DEFAULT_LOCALE)) {
|
|
5548
|
+
return parseNumber(content, DEFAULT_LOCALE);
|
|
5549
|
+
}
|
|
5550
|
+
const internalDate = parseDateTime(content, locale);
|
|
5551
|
+
if (internalDate) {
|
|
5552
|
+
return internalDate.value;
|
|
5553
|
+
}
|
|
5554
|
+
if (isBoolean(content)) {
|
|
5555
|
+
return content.toUpperCase() === "TRUE" ? true : false;
|
|
5556
|
+
}
|
|
5557
|
+
return content;
|
|
5558
|
+
}
|
|
5559
|
+
function createEvaluatedCell(functionResult, locale = DEFAULT_LOCALE, cell) {
|
|
5560
|
+
const link = detectLink(functionResult.value);
|
|
5561
|
+
if (!link) {
|
|
5562
|
+
return _createEvaluatedCell(functionResult, locale, cell);
|
|
5563
|
+
}
|
|
5564
|
+
const value = parseLiteral(link.label, locale);
|
|
5565
|
+
const format = functionResult.format ||
|
|
5566
|
+
(typeof value === "number"
|
|
5567
|
+
? detectDateFormat(link.label, locale) || detectNumberFormat(link.label)
|
|
5568
|
+
: undefined);
|
|
5569
|
+
const linkPayload = {
|
|
5570
|
+
value,
|
|
5571
|
+
format,
|
|
5572
|
+
};
|
|
5573
|
+
return {
|
|
5574
|
+
..._createEvaluatedCell(linkPayload, locale, cell),
|
|
5575
|
+
link,
|
|
5576
|
+
};
|
|
5577
|
+
}
|
|
5578
|
+
function _createEvaluatedCell(functionResult, locale, cell) {
|
|
5579
|
+
let { value, format, message } = functionResult;
|
|
5580
|
+
format = cell?.format || format;
|
|
5581
|
+
const formattedValue = formatValue(value, { format, locale });
|
|
5582
|
+
if (isEvaluationError(value)) {
|
|
5583
|
+
return errorCell(value, message);
|
|
5584
|
+
}
|
|
5585
|
+
if (isTextFormat(format)) {
|
|
5586
|
+
// TO DO:
|
|
5587
|
+
// with the next line, the value of the cell is transformed depending on the format.
|
|
5588
|
+
// This shouldn't happen, by doing this, the formulas handling numbers are not able
|
|
5589
|
+
// to interpret the value as a number.
|
|
5590
|
+
return textCell(toString(value), format, formattedValue);
|
|
5591
|
+
}
|
|
5592
|
+
if (value === null) {
|
|
5593
|
+
return emptyCell(format);
|
|
5594
|
+
}
|
|
5595
|
+
if (typeof value === "number") {
|
|
5596
|
+
if (isDateTimeFormat(format || "")) {
|
|
5597
|
+
return dateTimeCell(value, format, formattedValue);
|
|
5598
|
+
}
|
|
5599
|
+
return numberCell(value, format, formattedValue);
|
|
5600
|
+
}
|
|
5601
|
+
if (typeof value === "boolean") {
|
|
5602
|
+
return booleanCell(value, format, formattedValue);
|
|
5603
|
+
}
|
|
5604
|
+
return textCell(value, format, formattedValue);
|
|
5605
|
+
}
|
|
5606
|
+
function textCell(value, format, formattedValue) {
|
|
5607
|
+
return {
|
|
5608
|
+
value,
|
|
5609
|
+
format,
|
|
5610
|
+
formattedValue,
|
|
5611
|
+
type: CellValueType.text,
|
|
5612
|
+
isAutoSummable: true,
|
|
5613
|
+
defaultAlign: "left",
|
|
5614
|
+
};
|
|
5615
|
+
}
|
|
5616
|
+
function numberCell(value, format, formattedValue) {
|
|
5617
|
+
return {
|
|
5618
|
+
value: value || 0, // necessary to avoid "-0" and NaN values,
|
|
5619
|
+
format,
|
|
5620
|
+
formattedValue,
|
|
5621
|
+
type: CellValueType.number,
|
|
5622
|
+
isAutoSummable: true,
|
|
5623
|
+
defaultAlign: "right",
|
|
5624
|
+
};
|
|
5625
|
+
}
|
|
5626
|
+
const emptyCell = memoize(function emptyCell(format) {
|
|
5627
|
+
return {
|
|
5628
|
+
value: null,
|
|
5629
|
+
format,
|
|
5630
|
+
formattedValue: "",
|
|
5631
|
+
type: CellValueType.empty,
|
|
5632
|
+
isAutoSummable: true,
|
|
5633
|
+
defaultAlign: "left",
|
|
5634
|
+
};
|
|
5635
|
+
});
|
|
5636
|
+
function dateTimeCell(value, format, formattedValue) {
|
|
5637
|
+
return {
|
|
5638
|
+
value,
|
|
5639
|
+
format,
|
|
5640
|
+
formattedValue,
|
|
5641
|
+
type: CellValueType.number,
|
|
5642
|
+
isAutoSummable: false,
|
|
5643
|
+
defaultAlign: "right",
|
|
5644
|
+
};
|
|
5645
|
+
}
|
|
5646
|
+
function booleanCell(value, format, formattedValue) {
|
|
5647
|
+
return {
|
|
5648
|
+
value,
|
|
5649
|
+
format,
|
|
5650
|
+
formattedValue,
|
|
5651
|
+
type: CellValueType.boolean,
|
|
5652
|
+
isAutoSummable: false,
|
|
5653
|
+
defaultAlign: "center",
|
|
5654
|
+
};
|
|
5655
|
+
}
|
|
5656
|
+
function errorCell(value, message) {
|
|
5657
|
+
return {
|
|
5658
|
+
value,
|
|
5659
|
+
formattedValue: value,
|
|
5660
|
+
message,
|
|
5661
|
+
type: CellValueType.error,
|
|
5662
|
+
isAutoSummable: false,
|
|
5663
|
+
defaultAlign: "center",
|
|
5664
|
+
};
|
|
5665
|
+
}
|
|
5666
|
+
|
|
5667
|
+
function toCriterionDateNumber(dateValue) {
|
|
5668
|
+
const today = DateTime.now();
|
|
5669
|
+
switch (dateValue) {
|
|
5670
|
+
case "today":
|
|
5671
|
+
return jsDateToNumber(today);
|
|
5672
|
+
case "yesterday":
|
|
5673
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 1)));
|
|
5674
|
+
case "tomorrow":
|
|
5675
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() + 1)));
|
|
5676
|
+
case "lastWeek":
|
|
5677
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setDate(today.getDate() - 7)));
|
|
5678
|
+
case "lastMonth":
|
|
5679
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setMonth(today.getMonth() - 1)));
|
|
5680
|
+
case "lastYear":
|
|
5681
|
+
return jsDateToNumber(DateTime.fromTimestamp(today.setFullYear(today.getFullYear() - 1)));
|
|
5682
|
+
}
|
|
5683
|
+
}
|
|
5684
|
+
/** Get all the dates values of a criterion converted to numbers, converting date values such as "today" to actual dates */
|
|
5685
|
+
function getDateNumberCriterionValues(criterion, locale) {
|
|
5686
|
+
if ("dateValue" in criterion && criterion.dateValue !== "exactDate") {
|
|
5687
|
+
return [toCriterionDateNumber(criterion.dateValue)];
|
|
5688
|
+
}
|
|
5689
|
+
return criterion.values.map((value) => valueToDateNumber(value, locale));
|
|
5690
|
+
}
|
|
5691
|
+
/** Convert the criterion values to numbers. Return undefined values if they cannot be converted to numbers. */
|
|
5692
|
+
function getCriterionValuesAsNumber(criterion, locale) {
|
|
5693
|
+
return criterion.values.map((value) => tryToNumber(value, locale));
|
|
5694
|
+
}
|
|
5695
|
+
function getDateCriterionFormattedValues(values, locale) {
|
|
5696
|
+
return values.map((valueStr) => {
|
|
5697
|
+
if (valueStr.startsWith("=")) {
|
|
5698
|
+
return valueStr;
|
|
5699
|
+
}
|
|
5700
|
+
const value = parseLiteral(valueStr, locale);
|
|
5701
|
+
if (typeof value === "number") {
|
|
5702
|
+
return formatValue(value, { format: locale.dateFormat, locale });
|
|
5703
|
+
}
|
|
5704
|
+
return "";
|
|
5705
|
+
});
|
|
5706
|
+
}
|
|
5707
|
+
|
|
5708
|
+
const MAX_DELAY = 140;
|
|
5709
|
+
const MIN_DELAY = 20;
|
|
5710
|
+
const ACCELERATION = 0.035;
|
|
5711
|
+
/**
|
|
5712
|
+
* Decreasing exponential function used to determine the "speed" of edge-scrolling
|
|
5713
|
+
* as the timeout delay.
|
|
5714
|
+
*
|
|
5715
|
+
* Returns a timeout delay in milliseconds.
|
|
5716
|
+
*/
|
|
5717
|
+
function scrollDelay(value) {
|
|
5718
|
+
// decreasing exponential from MAX_DELAY to MIN_DELAY
|
|
5719
|
+
return MIN_DELAY + (MAX_DELAY - MIN_DELAY) * Math.exp(-ACCELERATION * (value - 1));
|
|
5720
|
+
}
|
|
5721
|
+
|
|
5496
5722
|
class RangeImpl {
|
|
5497
5723
|
getSheetSize;
|
|
5498
5724
|
_zone;
|
|
@@ -22094,217 +22320,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22094
22320
|
},
|
|
22095
22321
|
});
|
|
22096
22322
|
|
|
22097
|
-
/**
|
|
22098
|
-
* Add the `https` prefix to the url if it's missing
|
|
22099
|
-
*/
|
|
22100
|
-
function withHttps(url) {
|
|
22101
|
-
return !/^https?:\/\//i.test(url) ? `https://${url}` : url;
|
|
22102
|
-
}
|
|
22103
|
-
const urlRegistry = new Registry();
|
|
22104
|
-
function createWebLink(url, label) {
|
|
22105
|
-
url = withHttps(url);
|
|
22106
|
-
return {
|
|
22107
|
-
url,
|
|
22108
|
-
label: label || url,
|
|
22109
|
-
isExternal: true,
|
|
22110
|
-
isUrlEditable: true,
|
|
22111
|
-
};
|
|
22112
|
-
}
|
|
22113
|
-
urlRegistry.add("sheet_URL", {
|
|
22114
|
-
match: (url) => isSheetUrl(url),
|
|
22115
|
-
createLink: (url, label) => {
|
|
22116
|
-
return {
|
|
22117
|
-
label,
|
|
22118
|
-
url,
|
|
22119
|
-
isExternal: false,
|
|
22120
|
-
isUrlEditable: false,
|
|
22121
|
-
};
|
|
22122
|
-
},
|
|
22123
|
-
urlRepresentation(url, getters) {
|
|
22124
|
-
const sheetId = parseSheetUrl(url);
|
|
22125
|
-
return getters.tryGetSheetName(sheetId) || _t("Invalid sheet");
|
|
22126
|
-
},
|
|
22127
|
-
open(url, env) {
|
|
22128
|
-
const sheetId = parseSheetUrl(url);
|
|
22129
|
-
const result = env.model.dispatch("ACTIVATE_SHEET", {
|
|
22130
|
-
sheetIdFrom: env.model.getters.getActiveSheetId(),
|
|
22131
|
-
sheetIdTo: sheetId,
|
|
22132
|
-
});
|
|
22133
|
-
if (result.isCancelledBecause("SheetIsHidden" /* CommandResult.SheetIsHidden */)) {
|
|
22134
|
-
env.notifyUser({
|
|
22135
|
-
type: "warning",
|
|
22136
|
-
sticky: false,
|
|
22137
|
-
text: _t("Cannot open the link because the linked sheet is hidden."),
|
|
22138
|
-
});
|
|
22139
|
-
}
|
|
22140
|
-
},
|
|
22141
|
-
sequence: 0,
|
|
22142
|
-
});
|
|
22143
|
-
const WebUrlSpec = {
|
|
22144
|
-
createLink: createWebLink,
|
|
22145
|
-
match: (url) => isWebLink(url),
|
|
22146
|
-
open: (url) => window.open(url, "_blank"),
|
|
22147
|
-
urlRepresentation: (url) => url,
|
|
22148
|
-
sequence: 0,
|
|
22149
|
-
};
|
|
22150
|
-
function findMatchingSpec(url) {
|
|
22151
|
-
return (urlRegistry
|
|
22152
|
-
.getAll()
|
|
22153
|
-
.sort((a, b) => a.sequence - b.sequence)
|
|
22154
|
-
.find((urlType) => urlType.match(url)) || WebUrlSpec);
|
|
22155
|
-
}
|
|
22156
|
-
function urlRepresentation(link, getters) {
|
|
22157
|
-
return findMatchingSpec(link.url).urlRepresentation(link.url, getters);
|
|
22158
|
-
}
|
|
22159
|
-
function openLink(link, env) {
|
|
22160
|
-
findMatchingSpec(link.url).open(link.url, env);
|
|
22161
|
-
}
|
|
22162
|
-
function detectLink(value) {
|
|
22163
|
-
if (typeof value !== "string") {
|
|
22164
|
-
return undefined;
|
|
22165
|
-
}
|
|
22166
|
-
if (isMarkdownLink(value)) {
|
|
22167
|
-
const { label, url } = parseMarkdownLink(value);
|
|
22168
|
-
return findMatchingSpec(url).createLink(url, label);
|
|
22169
|
-
}
|
|
22170
|
-
else if (isWebLink(value)) {
|
|
22171
|
-
return createWebLink(value);
|
|
22172
|
-
}
|
|
22173
|
-
return undefined;
|
|
22174
|
-
}
|
|
22175
|
-
|
|
22176
|
-
function evaluateLiteral(literalCell, localeFormat) {
|
|
22177
|
-
const value = isTextFormat(localeFormat.format) ? literalCell.content : literalCell.parsedValue;
|
|
22178
|
-
const functionResult = { value, format: localeFormat.format };
|
|
22179
|
-
return createEvaluatedCell(functionResult, localeFormat.locale);
|
|
22180
|
-
}
|
|
22181
|
-
function parseLiteral(content, locale) {
|
|
22182
|
-
if (content.startsWith("=")) {
|
|
22183
|
-
throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
|
|
22184
|
-
}
|
|
22185
|
-
if (content === "") {
|
|
22186
|
-
return null;
|
|
22187
|
-
}
|
|
22188
|
-
if (isNumber(content, DEFAULT_LOCALE)) {
|
|
22189
|
-
return parseNumber(content, DEFAULT_LOCALE);
|
|
22190
|
-
}
|
|
22191
|
-
const internalDate = parseDateTime(content, locale);
|
|
22192
|
-
if (internalDate) {
|
|
22193
|
-
return internalDate.value;
|
|
22194
|
-
}
|
|
22195
|
-
if (isBoolean(content)) {
|
|
22196
|
-
return content.toUpperCase() === "TRUE" ? true : false;
|
|
22197
|
-
}
|
|
22198
|
-
return content;
|
|
22199
|
-
}
|
|
22200
|
-
function createEvaluatedCell(functionResult, locale = DEFAULT_LOCALE, cell) {
|
|
22201
|
-
const link = detectLink(functionResult.value);
|
|
22202
|
-
if (!link) {
|
|
22203
|
-
return _createEvaluatedCell(functionResult, locale, cell);
|
|
22204
|
-
}
|
|
22205
|
-
const value = parseLiteral(link.label, locale);
|
|
22206
|
-
const format = functionResult.format ||
|
|
22207
|
-
(typeof value === "number"
|
|
22208
|
-
? detectDateFormat(link.label, locale) || detectNumberFormat(link.label)
|
|
22209
|
-
: undefined);
|
|
22210
|
-
const linkPayload = {
|
|
22211
|
-
value,
|
|
22212
|
-
format,
|
|
22213
|
-
};
|
|
22214
|
-
return {
|
|
22215
|
-
..._createEvaluatedCell(linkPayload, locale, cell),
|
|
22216
|
-
link,
|
|
22217
|
-
};
|
|
22218
|
-
}
|
|
22219
|
-
function _createEvaluatedCell(functionResult, locale, cell) {
|
|
22220
|
-
let { value, format, message } = functionResult;
|
|
22221
|
-
format = cell?.format || format;
|
|
22222
|
-
const formattedValue = formatValue(value, { format, locale });
|
|
22223
|
-
if (isEvaluationError(value)) {
|
|
22224
|
-
return errorCell(value, message);
|
|
22225
|
-
}
|
|
22226
|
-
if (isTextFormat(format)) {
|
|
22227
|
-
// TO DO:
|
|
22228
|
-
// with the next line, the value of the cell is transformed depending on the format.
|
|
22229
|
-
// This shouldn't happen, by doing this, the formulas handling numbers are not able
|
|
22230
|
-
// to interpret the value as a number.
|
|
22231
|
-
return textCell(toString(value), format, formattedValue);
|
|
22232
|
-
}
|
|
22233
|
-
if (value === null) {
|
|
22234
|
-
return emptyCell(format);
|
|
22235
|
-
}
|
|
22236
|
-
if (typeof value === "number") {
|
|
22237
|
-
if (isDateTimeFormat(format || "")) {
|
|
22238
|
-
return dateTimeCell(value, format, formattedValue);
|
|
22239
|
-
}
|
|
22240
|
-
return numberCell(value, format, formattedValue);
|
|
22241
|
-
}
|
|
22242
|
-
if (typeof value === "boolean") {
|
|
22243
|
-
return booleanCell(value, format, formattedValue);
|
|
22244
|
-
}
|
|
22245
|
-
return textCell(value, format, formattedValue);
|
|
22246
|
-
}
|
|
22247
|
-
function textCell(value, format, formattedValue) {
|
|
22248
|
-
return {
|
|
22249
|
-
value,
|
|
22250
|
-
format,
|
|
22251
|
-
formattedValue,
|
|
22252
|
-
type: CellValueType.text,
|
|
22253
|
-
isAutoSummable: true,
|
|
22254
|
-
defaultAlign: "left",
|
|
22255
|
-
};
|
|
22256
|
-
}
|
|
22257
|
-
function numberCell(value, format, formattedValue) {
|
|
22258
|
-
return {
|
|
22259
|
-
value: value || 0, // necessary to avoid "-0" and NaN values,
|
|
22260
|
-
format,
|
|
22261
|
-
formattedValue,
|
|
22262
|
-
type: CellValueType.number,
|
|
22263
|
-
isAutoSummable: true,
|
|
22264
|
-
defaultAlign: "right",
|
|
22265
|
-
};
|
|
22266
|
-
}
|
|
22267
|
-
const emptyCell = memoize(function emptyCell(format) {
|
|
22268
|
-
return {
|
|
22269
|
-
value: null,
|
|
22270
|
-
format,
|
|
22271
|
-
formattedValue: "",
|
|
22272
|
-
type: CellValueType.empty,
|
|
22273
|
-
isAutoSummable: true,
|
|
22274
|
-
defaultAlign: "left",
|
|
22275
|
-
};
|
|
22276
|
-
});
|
|
22277
|
-
function dateTimeCell(value, format, formattedValue) {
|
|
22278
|
-
return {
|
|
22279
|
-
value,
|
|
22280
|
-
format,
|
|
22281
|
-
formattedValue,
|
|
22282
|
-
type: CellValueType.number,
|
|
22283
|
-
isAutoSummable: false,
|
|
22284
|
-
defaultAlign: "right",
|
|
22285
|
-
};
|
|
22286
|
-
}
|
|
22287
|
-
function booleanCell(value, format, formattedValue) {
|
|
22288
|
-
return {
|
|
22289
|
-
value,
|
|
22290
|
-
format,
|
|
22291
|
-
formattedValue,
|
|
22292
|
-
type: CellValueType.boolean,
|
|
22293
|
-
isAutoSummable: false,
|
|
22294
|
-
defaultAlign: "center",
|
|
22295
|
-
};
|
|
22296
|
-
}
|
|
22297
|
-
function errorCell(value, message) {
|
|
22298
|
-
return {
|
|
22299
|
-
value,
|
|
22300
|
-
formattedValue: value,
|
|
22301
|
-
message,
|
|
22302
|
-
type: CellValueType.error,
|
|
22303
|
-
isAutoSummable: false,
|
|
22304
|
-
defaultAlign: "center",
|
|
22305
|
-
};
|
|
22306
|
-
}
|
|
22307
|
-
|
|
22308
22323
|
/**
|
|
22309
22324
|
* An AutofillModifierImplementation is used to describe how to handle a
|
|
22310
22325
|
* AutofillModifier.
|
|
@@ -23450,6 +23465,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23450
23465
|
WarningTypes["CfIconSetEmptyIconNotSupported"] = "IconSets with empty icons";
|
|
23451
23466
|
WarningTypes["BadlyFormattedHyperlink"] = "Badly formatted hyperlink";
|
|
23452
23467
|
WarningTypes["NumFmtIdNotSupported"] = "Number format";
|
|
23468
|
+
WarningTypes["TimeDataValidationNotSupported"] = "Time data validation rules";
|
|
23469
|
+
WarningTypes["TextLengthDataValidationNotSupported"] = "Text length data validation rules";
|
|
23470
|
+
WarningTypes["WholeNumberDataValidationNotSupported"] = "Whole number data validation rules";
|
|
23471
|
+
WarningTypes["NotEqualDateDataValidationNotSupported"] = "Not equal date data validation rules";
|
|
23453
23472
|
})(WarningTypes || (WarningTypes = {}));
|
|
23454
23473
|
class XLSXImportWarningManager {
|
|
23455
23474
|
_parsingWarnings = new Set();
|
|
@@ -23828,6 +23847,25 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23828
23847
|
webp: "image/webp",
|
|
23829
23848
|
jpg: "image/jpeg",
|
|
23830
23849
|
};
|
|
23850
|
+
const XLSX_DV_DECIMAL_OPERATOR_MAPPING = {
|
|
23851
|
+
between: "isBetween",
|
|
23852
|
+
notBetween: "isNotBetween",
|
|
23853
|
+
equal: "isEqual",
|
|
23854
|
+
notEqual: "isNotEqual",
|
|
23855
|
+
greaterThan: "isGreaterThan",
|
|
23856
|
+
greaterThanOrEqual: "isGreaterOrEqualTo",
|
|
23857
|
+
lessThan: "isLessThan",
|
|
23858
|
+
lessThanOrEqual: "isLessOrEqualTo",
|
|
23859
|
+
};
|
|
23860
|
+
const XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING = {
|
|
23861
|
+
between: "dateIsBetween",
|
|
23862
|
+
notBetween: "dateIsNotBetween",
|
|
23863
|
+
equal: "dateIs",
|
|
23864
|
+
greaterThan: "dateIsAfter",
|
|
23865
|
+
greaterThanOrEqual: "dateIsOnOrAfter",
|
|
23866
|
+
lessThan: "dateIsBefore",
|
|
23867
|
+
lessThanOrEqual: "dateIsOnOrBefore",
|
|
23868
|
+
};
|
|
23831
23869
|
|
|
23832
23870
|
/**
|
|
23833
23871
|
* Most of the functions could stay private, but are exported for testing purposes
|
|
@@ -24597,6 +24635,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24597
24635
|
}
|
|
24598
24636
|
return position / HEIGHT_FACTOR;
|
|
24599
24637
|
}
|
|
24638
|
+
/**
|
|
24639
|
+
* Convert the o-spreadsheet data validation decimal
|
|
24640
|
+
* criterion type to the corresponding excel operator.
|
|
24641
|
+
*/
|
|
24642
|
+
function convertDecimalCriterionTypeToExcelOperator(operator) {
|
|
24643
|
+
return Object.keys(XLSX_DV_DECIMAL_OPERATOR_MAPPING).find((key) => XLSX_DV_DECIMAL_OPERATOR_MAPPING[key] === operator);
|
|
24644
|
+
}
|
|
24645
|
+
/**
|
|
24646
|
+
* Convert the o-spreadsheet data validation date
|
|
24647
|
+
* criterion type to the corresponding excel operator.
|
|
24648
|
+
*/
|
|
24649
|
+
function convertDateCriterionTypeToExcelOperator(operator) {
|
|
24650
|
+
return Object.keys(XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING).find((key) => XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[key] === operator);
|
|
24651
|
+
}
|
|
24600
24652
|
|
|
24601
24653
|
function convertFigures(sheetData) {
|
|
24602
24654
|
let id = 1;
|
|
@@ -24706,6 +24758,112 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24706
24758
|
};
|
|
24707
24759
|
}
|
|
24708
24760
|
|
|
24761
|
+
function convertDataValidationRules(xlsxDataValidations, warningManager) {
|
|
24762
|
+
const dvRules = [];
|
|
24763
|
+
let dvId = 1;
|
|
24764
|
+
for (const dv of xlsxDataValidations) {
|
|
24765
|
+
if (!dv) {
|
|
24766
|
+
continue;
|
|
24767
|
+
}
|
|
24768
|
+
switch (dv.type) {
|
|
24769
|
+
case "time":
|
|
24770
|
+
warningManager.generateNotSupportedWarning(WarningTypes.TimeDataValidationNotSupported);
|
|
24771
|
+
break;
|
|
24772
|
+
case "textLength":
|
|
24773
|
+
warningManager.generateNotSupportedWarning(WarningTypes.TextLengthDataValidationNotSupported);
|
|
24774
|
+
break;
|
|
24775
|
+
case "whole":
|
|
24776
|
+
warningManager.generateNotSupportedWarning(WarningTypes.WholeNumberDataValidationNotSupported);
|
|
24777
|
+
break;
|
|
24778
|
+
case "decimal":
|
|
24779
|
+
const decimalRule = convertDecimalRule(dvId++, dv);
|
|
24780
|
+
dvRules.push(decimalRule);
|
|
24781
|
+
break;
|
|
24782
|
+
case "list":
|
|
24783
|
+
const listRule = convertListrule(dvId++, dv);
|
|
24784
|
+
dvRules.push(listRule);
|
|
24785
|
+
break;
|
|
24786
|
+
case "date":
|
|
24787
|
+
if (dv.operator === "notEqual") {
|
|
24788
|
+
warningManager.generateNotSupportedWarning(WarningTypes.NotEqualDateDataValidationNotSupported);
|
|
24789
|
+
break;
|
|
24790
|
+
}
|
|
24791
|
+
const dateRule = convertDateRule(dvId++, dv);
|
|
24792
|
+
dvRules.push(dateRule);
|
|
24793
|
+
break;
|
|
24794
|
+
case "custom":
|
|
24795
|
+
const customRule = convertCustomRule(dvId++, dv);
|
|
24796
|
+
dvRules.push(customRule);
|
|
24797
|
+
break;
|
|
24798
|
+
}
|
|
24799
|
+
}
|
|
24800
|
+
return dvRules;
|
|
24801
|
+
}
|
|
24802
|
+
function convertDecimalRule(id, dv) {
|
|
24803
|
+
const values = [dv.formula1.toString()];
|
|
24804
|
+
if (dv.formula2) {
|
|
24805
|
+
values.push(dv.formula2.toString());
|
|
24806
|
+
}
|
|
24807
|
+
return {
|
|
24808
|
+
id: id.toString(),
|
|
24809
|
+
ranges: dv.sqref,
|
|
24810
|
+
isBlocking: dv.errorStyle !== "warning",
|
|
24811
|
+
criterion: {
|
|
24812
|
+
type: XLSX_DV_DECIMAL_OPERATOR_MAPPING[dv.operator],
|
|
24813
|
+
values,
|
|
24814
|
+
},
|
|
24815
|
+
};
|
|
24816
|
+
}
|
|
24817
|
+
function convertListrule(id, dv) {
|
|
24818
|
+
const formula1 = dv.formula1.toString();
|
|
24819
|
+
const isRangeRule = rangeReference.test(formula1);
|
|
24820
|
+
return {
|
|
24821
|
+
id: id.toString(),
|
|
24822
|
+
ranges: dv.sqref,
|
|
24823
|
+
isBlocking: dv.errorStyle !== "warning",
|
|
24824
|
+
criterion: {
|
|
24825
|
+
type: isRangeRule ? "isValueInRange" : "isValueInList",
|
|
24826
|
+
values: isRangeRule ? [formula1] : formula1.replaceAll('"', "").split(","),
|
|
24827
|
+
displayStyle: "arrow",
|
|
24828
|
+
},
|
|
24829
|
+
};
|
|
24830
|
+
}
|
|
24831
|
+
function convertDateRule(id, dv) {
|
|
24832
|
+
let criterion;
|
|
24833
|
+
const values = [dv.formula1.toString()];
|
|
24834
|
+
if (dv.formula2) {
|
|
24835
|
+
values.push(dv.formula2.toString());
|
|
24836
|
+
criterion = {
|
|
24837
|
+
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
24838
|
+
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
24839
|
+
};
|
|
24840
|
+
}
|
|
24841
|
+
else {
|
|
24842
|
+
criterion = {
|
|
24843
|
+
type: XLSX_DV_DATE_OPERATOR_TO_DV_TYPE_MAPPING[dv.operator],
|
|
24844
|
+
values: getDateCriterionFormattedValues(values, DEFAULT_LOCALE),
|
|
24845
|
+
dateValue: "exactDate",
|
|
24846
|
+
};
|
|
24847
|
+
}
|
|
24848
|
+
return {
|
|
24849
|
+
id: id.toString(),
|
|
24850
|
+
ranges: dv.sqref,
|
|
24851
|
+
isBlocking: dv.errorStyle !== "warning",
|
|
24852
|
+
criterion: criterion,
|
|
24853
|
+
};
|
|
24854
|
+
}
|
|
24855
|
+
function convertCustomRule(id, dv) {
|
|
24856
|
+
return {
|
|
24857
|
+
id: id.toString(),
|
|
24858
|
+
ranges: dv.sqref,
|
|
24859
|
+
isBlocking: dv.errorStyle !== "warning",
|
|
24860
|
+
criterion: {
|
|
24861
|
+
type: "customFormula",
|
|
24862
|
+
values: [`=${dv.formula1.toString()}`],
|
|
24863
|
+
},
|
|
24864
|
+
};
|
|
24865
|
+
}
|
|
24866
|
+
|
|
24709
24867
|
/**
|
|
24710
24868
|
* Match external reference (ex. '[1]Sheet 3'!$B$4)
|
|
24711
24869
|
*
|
|
@@ -24826,6 +24984,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24826
24984
|
cols: convertCols(sheet, sheetDims[0], colHeaderGroups),
|
|
24827
24985
|
rows: convertRows(sheet, sheetDims[1], rowHeaderGroups),
|
|
24828
24986
|
conditionalFormats: convertConditionalFormats(sheet.cfs, data.dxfs, warningManager),
|
|
24987
|
+
dataValidationRules: convertDataValidationRules(sheet.dataValidations, warningManager),
|
|
24829
24988
|
figures: convertFigures(sheet),
|
|
24830
24989
|
isVisible: sheet.isVisible,
|
|
24831
24990
|
panes: sheetOptions
|
|
@@ -26106,6 +26265,41 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26106
26265
|
}
|
|
26107
26266
|
}
|
|
26108
26267
|
|
|
26268
|
+
class XlsxDataValidationExtractor extends XlsxBaseExtractor {
|
|
26269
|
+
theme;
|
|
26270
|
+
constructor(sheetFile, xlsxStructure, warningManager, theme) {
|
|
26271
|
+
super(sheetFile, xlsxStructure, warningManager);
|
|
26272
|
+
this.theme = theme;
|
|
26273
|
+
}
|
|
26274
|
+
extractDataValidations() {
|
|
26275
|
+
const dataValidations = this.mapOnElements({ parent: this.rootFile.file.xml, query: "worksheet > dataValidations > dataValidation" }, (dvElement) => {
|
|
26276
|
+
return {
|
|
26277
|
+
type: this.extractAttr(dvElement, "type", { required: true }).asString(),
|
|
26278
|
+
operator: this.extractAttr(dvElement, "operator", {
|
|
26279
|
+
default: "between",
|
|
26280
|
+
})?.asString(),
|
|
26281
|
+
sqref: this.extractAttr(dvElement, "sqref", { required: true }).asString().split(" "),
|
|
26282
|
+
errorStyle: this.extractAttr(dvElement, "errorStyle")?.asString(),
|
|
26283
|
+
formula1: this.extractDataValidationFormula(dvElement, 1)[0],
|
|
26284
|
+
formula2: this.extractDataValidationFormula(dvElement, 2)[0],
|
|
26285
|
+
showErrorMessage: this.extractAttr(dvElement, "showErrorMessage")?.asBool(),
|
|
26286
|
+
errorTitle: this.extractAttr(dvElement, "errorTitle")?.asString(),
|
|
26287
|
+
error: this.extractAttr(dvElement, "error")?.asString(),
|
|
26288
|
+
showInputMessage: this.extractAttr(dvElement, "showInputMessage")?.asBool(),
|
|
26289
|
+
promptTitle: this.extractAttr(dvElement, "promptTitle")?.asString(),
|
|
26290
|
+
prompt: this.extractAttr(dvElement, "prompt")?.asString(),
|
|
26291
|
+
allowBlank: this.extractAttr(dvElement, "allowBlank")?.asBool(),
|
|
26292
|
+
};
|
|
26293
|
+
});
|
|
26294
|
+
return dataValidations;
|
|
26295
|
+
}
|
|
26296
|
+
extractDataValidationFormula(dvElement, index) {
|
|
26297
|
+
return this.mapOnElements({ parent: dvElement, query: `formula${index}` }, (cfFormulaElements) => {
|
|
26298
|
+
return this.extractTextContent(cfFormulaElements, { required: true });
|
|
26299
|
+
});
|
|
26300
|
+
}
|
|
26301
|
+
}
|
|
26302
|
+
|
|
26109
26303
|
class XlsxChartExtractor extends XlsxBaseExtractor {
|
|
26110
26304
|
extractChart() {
|
|
26111
26305
|
return this.mapOnElements({ parent: this.rootFile.file.xml, query: "c:chartSpace" }, (rootChartElement) => {
|
|
@@ -26473,6 +26667,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26473
26667
|
sharedFormulas: this.extractSharedFormulas(sheetElement),
|
|
26474
26668
|
merges: this.extractMerges(sheetElement),
|
|
26475
26669
|
cfs: this.extractConditionalFormats(),
|
|
26670
|
+
dataValidations: this.extractDataValidations(),
|
|
26476
26671
|
figures: this.extractFigures(sheetElement),
|
|
26477
26672
|
hyperlinks: this.extractHyperLinks(sheetElement),
|
|
26478
26673
|
tables: this.extractTables(sheetElement),
|
|
@@ -26544,6 +26739,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26544
26739
|
extractConditionalFormats() {
|
|
26545
26740
|
return new XlsxCfExtractor(this.rootFile, this.xlsxFileStructure, this.warningManager, this.theme).extractConditionalFormattings();
|
|
26546
26741
|
}
|
|
26742
|
+
extractDataValidations() {
|
|
26743
|
+
return new XlsxDataValidationExtractor(this.rootFile, this.xlsxFileStructure, this.warningManager, this.theme).extractDataValidations();
|
|
26744
|
+
}
|
|
26547
26745
|
extractFigures(worksheet) {
|
|
26548
26746
|
const figures = this.mapOnElements({ parent: worksheet, query: "drawing" }, (drawingElement) => {
|
|
26549
26747
|
const drawingId = this.extractAttr(drawingElement, "r:id", { required: true })?.asString();
|
|
@@ -27824,6 +28022,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27824
28022
|
rows: {},
|
|
27825
28023
|
merges: [],
|
|
27826
28024
|
conditionalFormats: [],
|
|
28025
|
+
dataValidationRules: [],
|
|
27827
28026
|
figures: [],
|
|
27828
28027
|
tables: [],
|
|
27829
28028
|
isVisible: true,
|
|
@@ -31387,6 +31586,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31387
31586
|
this.currentDisplayValue = newDisplay;
|
|
31388
31587
|
if (!anchor)
|
|
31389
31588
|
return;
|
|
31589
|
+
el.style.top = "";
|
|
31590
|
+
el.style.left = "";
|
|
31591
|
+
el.style["max-height"] = "";
|
|
31592
|
+
el.style["max-width"] = "";
|
|
31390
31593
|
const propsMaxSize = { width: this.props.maxWidth, height: this.props.maxHeight };
|
|
31391
31594
|
let elDims = {
|
|
31392
31595
|
width: el.getBoundingClientRect().width,
|
|
@@ -40247,7 +40450,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40247
40450
|
name: _t("Date is"),
|
|
40248
40451
|
getPreview: (criterion, getters) => {
|
|
40249
40452
|
return criterion.dateValue === "exactDate"
|
|
40250
|
-
? _t("Date is %s", getDateCriterionFormattedValues(criterion, getters)[0])
|
|
40453
|
+
? _t("Date is %s", getDateCriterionFormattedValues(criterion.values, getters.getLocale())[0])
|
|
40251
40454
|
: _t("Date is %s", DVTerms.DateIs[criterion.dateValue]);
|
|
40252
40455
|
},
|
|
40253
40456
|
});
|
|
@@ -40272,7 +40475,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40272
40475
|
name: _t("Date is before"),
|
|
40273
40476
|
getPreview: (criterion, getters) => {
|
|
40274
40477
|
return criterion.dateValue === "exactDate"
|
|
40275
|
-
? _t("Date is before %s", getDateCriterionFormattedValues(criterion, getters)[0])
|
|
40478
|
+
? _t("Date is before %s", getDateCriterionFormattedValues(criterion.values, getters.getLocale())[0])
|
|
40276
40479
|
: _t("Date is before %s", DVTerms.DateIsBefore[criterion.dateValue]);
|
|
40277
40480
|
},
|
|
40278
40481
|
});
|
|
@@ -40297,7 +40500,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40297
40500
|
name: _t("Date is on or before"),
|
|
40298
40501
|
getPreview: (criterion, getters) => {
|
|
40299
40502
|
return criterion.dateValue === "exactDate"
|
|
40300
|
-
? _t("Date is on or before %s", getDateCriterionFormattedValues(criterion, getters)[0])
|
|
40503
|
+
? _t("Date is on or before %s", getDateCriterionFormattedValues(criterion.values, getters.getLocale())[0])
|
|
40301
40504
|
: _t("Date is on or before %s", DVTerms.DateIsBefore[criterion.dateValue]);
|
|
40302
40505
|
},
|
|
40303
40506
|
});
|
|
@@ -40322,7 +40525,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40322
40525
|
name: _t("Date is after"),
|
|
40323
40526
|
getPreview: (criterion, getters) => {
|
|
40324
40527
|
return criterion.dateValue === "exactDate"
|
|
40325
|
-
? _t("Date is after %s", getDateCriterionFormattedValues(criterion, getters)[0])
|
|
40528
|
+
? _t("Date is after %s", getDateCriterionFormattedValues(criterion.values, getters.getLocale())[0])
|
|
40326
40529
|
: _t("Date is after %s", DVTerms.DateIsBefore[criterion.dateValue]);
|
|
40327
40530
|
},
|
|
40328
40531
|
});
|
|
@@ -40347,7 +40550,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40347
40550
|
name: _t("Date is on or after"),
|
|
40348
40551
|
getPreview: (criterion, getters) => {
|
|
40349
40552
|
return criterion.dateValue === "exactDate"
|
|
40350
|
-
? _t("Date is on or after %s", getDateCriterionFormattedValues(criterion, getters)[0])
|
|
40553
|
+
? _t("Date is on or after %s", getDateCriterionFormattedValues(criterion.values, getters.getLocale())[0])
|
|
40351
40554
|
: _t("Date is on or after %s", DVTerms.DateIsBefore[criterion.dateValue]);
|
|
40352
40555
|
},
|
|
40353
40556
|
});
|
|
@@ -40373,7 +40576,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40373
40576
|
numberOfValues: () => 2,
|
|
40374
40577
|
name: _t("Date is between"),
|
|
40375
40578
|
getPreview: (criterion, getters) => {
|
|
40376
|
-
const values = getDateCriterionFormattedValues(criterion, getters);
|
|
40579
|
+
const values = getDateCriterionFormattedValues(criterion.values, getters.getLocale());
|
|
40377
40580
|
return _t("Date is between %s and %s", values[0], values[1]);
|
|
40378
40581
|
},
|
|
40379
40582
|
});
|
|
@@ -40399,7 +40602,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40399
40602
|
numberOfValues: () => 2,
|
|
40400
40603
|
name: _t("Date is not between"),
|
|
40401
40604
|
getPreview: (criterion, getters) => {
|
|
40402
|
-
const values = getDateCriterionFormattedValues(criterion, getters);
|
|
40605
|
+
const values = getDateCriterionFormattedValues(criterion.values, getters.getLocale());
|
|
40403
40606
|
return _t("Date is not between %s and %s", values[0], values[1]);
|
|
40404
40607
|
},
|
|
40405
40608
|
});
|
|
@@ -40682,19 +40885,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40682
40885
|
const valueAsNumber = tryToNumber(value, DEFAULT_LOCALE);
|
|
40683
40886
|
return valueAsNumber !== undefined;
|
|
40684
40887
|
}
|
|
40685
|
-
function getDateCriterionFormattedValues(criterion, getters) {
|
|
40686
|
-
const locale = getters.getLocale();
|
|
40687
|
-
return criterion.values.map((valueStr) => {
|
|
40688
|
-
if (valueStr.startsWith("=")) {
|
|
40689
|
-
return valueStr;
|
|
40690
|
-
}
|
|
40691
|
-
const value = parseLiteral(valueStr, locale);
|
|
40692
|
-
if (typeof value === "number") {
|
|
40693
|
-
return formatValue(value, { format: locale.dateFormat, locale });
|
|
40694
|
-
}
|
|
40695
|
-
return "";
|
|
40696
|
-
});
|
|
40697
|
-
}
|
|
40698
40888
|
|
|
40699
40889
|
/** This component looks like a select input, but on click it opens a Menu with the items given as props instead of a dropdown */
|
|
40700
40890
|
class SelectMenu extends owl.Component {
|
|
@@ -46397,7 +46587,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
46397
46587
|
return;
|
|
46398
46588
|
}
|
|
46399
46589
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
46400
|
-
const zone = this.env.model.getters.
|
|
46590
|
+
const zone = positionToZone(this.env.model.getters.getSelection().anchor.cell);
|
|
46401
46591
|
const rect = this.env.model.getters.getVisibleRect(zone);
|
|
46402
46592
|
if (!deepEquals(rect, this.rect) || sheetId !== this.composerStore.currentEditedCell.sheetId) {
|
|
46403
46593
|
this.isCellReferenceVisible = true;
|
|
@@ -48231,13 +48421,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48231
48421
|
drawLayer(renderingContext, layer) {
|
|
48232
48422
|
switch (layer) {
|
|
48233
48423
|
case "Background":
|
|
48234
|
-
|
|
48235
|
-
this.
|
|
48236
|
-
|
|
48237
|
-
|
|
48238
|
-
|
|
48239
|
-
|
|
48240
|
-
|
|
48424
|
+
this.drawGlobalBackground(renderingContext);
|
|
48425
|
+
for (const zone of this.getters.getAllActiveViewportsZones()) {
|
|
48426
|
+
const { ctx } = renderingContext;
|
|
48427
|
+
ctx.save();
|
|
48428
|
+
ctx.beginPath();
|
|
48429
|
+
const rect = this.getters.getVisibleRect(zone);
|
|
48430
|
+
ctx.rect(rect.x, rect.y, rect.width, rect.height);
|
|
48431
|
+
ctx.clip();
|
|
48432
|
+
const boxes = this.getGridBoxes(zone);
|
|
48433
|
+
this.drawBackground(renderingContext, boxes);
|
|
48434
|
+
this.drawOverflowingCellBackground(renderingContext, boxes);
|
|
48435
|
+
this.drawCellBackground(renderingContext, boxes);
|
|
48436
|
+
this.drawBorders(renderingContext, boxes);
|
|
48437
|
+
this.drawTexts(renderingContext, boxes);
|
|
48438
|
+
this.drawIcon(renderingContext, boxes);
|
|
48439
|
+
ctx.restore();
|
|
48440
|
+
}
|
|
48241
48441
|
this.drawFrozenPanes(renderingContext);
|
|
48242
48442
|
break;
|
|
48243
48443
|
case "Headers":
|
|
@@ -48248,12 +48448,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48248
48448
|
break;
|
|
48249
48449
|
}
|
|
48250
48450
|
}
|
|
48251
|
-
|
|
48252
|
-
const { ctx
|
|
48451
|
+
drawGlobalBackground(renderingContext) {
|
|
48452
|
+
const { ctx } = renderingContext;
|
|
48253
48453
|
const { width, height } = this.getters.getSheetViewDimensionWithHeaders();
|
|
48254
48454
|
// white background
|
|
48255
48455
|
ctx.fillStyle = "#ffffff";
|
|
48256
48456
|
ctx.fillRect(0, 0, width + CANVAS_SHIFT, height + CANVAS_SHIFT);
|
|
48457
|
+
}
|
|
48458
|
+
drawBackground(renderingContext, boxes) {
|
|
48459
|
+
const { ctx, thinLineWidth } = renderingContext;
|
|
48257
48460
|
const areGridLinesVisible = !this.getters.isDashboard() &&
|
|
48258
48461
|
this.getters.getGridLinesVisibility(this.getters.getActiveSheetId());
|
|
48259
48462
|
const inset = areGridLinesVisible ? 0.1 * thinLineWidth : 0;
|
|
@@ -48684,7 +48887,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48684
48887
|
const position = { sheetId, col, row };
|
|
48685
48888
|
const cell = this.getters.getEvaluatedCell(position);
|
|
48686
48889
|
const showFormula = this.getters.shouldShowFormulas();
|
|
48687
|
-
const { x, y, width, height } = this.getters.
|
|
48890
|
+
const { x, y, width, height } = this.getters.getRect(zone);
|
|
48688
48891
|
const { verticalAlign } = this.getters.getCellStyle(position);
|
|
48689
48892
|
const box = {
|
|
48690
48893
|
x,
|
|
@@ -48802,12 +49005,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48802
49005
|
}
|
|
48803
49006
|
return box;
|
|
48804
49007
|
}
|
|
48805
|
-
getGridBoxes() {
|
|
49008
|
+
getGridBoxes(zone) {
|
|
48806
49009
|
const boxes = [];
|
|
48807
|
-
const visibleCols = this.getters
|
|
49010
|
+
const visibleCols = this.getters
|
|
49011
|
+
.getSheetViewVisibleCols()
|
|
49012
|
+
.filter((col) => col >= zone.left && col <= zone.right);
|
|
48808
49013
|
const left = visibleCols[0];
|
|
48809
49014
|
const right = visibleCols[visibleCols.length - 1];
|
|
48810
|
-
const visibleRows = this.getters
|
|
49015
|
+
const visibleRows = this.getters
|
|
49016
|
+
.getSheetViewVisibleRows()
|
|
49017
|
+
.filter((row) => row >= zone.top && row <= zone.bottom);
|
|
48811
49018
|
const top = visibleRows[0];
|
|
48812
49019
|
const bottom = visibleRows[visibleRows.length - 1];
|
|
48813
49020
|
const viewport = { left, right, top, bottom };
|
|
@@ -52291,6 +52498,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52291
52498
|
}
|
|
52292
52499
|
}
|
|
52293
52500
|
}
|
|
52501
|
+
exportForExcel(data) {
|
|
52502
|
+
if (!data.sheets) {
|
|
52503
|
+
return;
|
|
52504
|
+
}
|
|
52505
|
+
for (const sheet of data.sheets) {
|
|
52506
|
+
sheet.dataValidationRules = [];
|
|
52507
|
+
for (const rule of this.rules[sheet.id]) {
|
|
52508
|
+
sheet.dataValidationRules.push({
|
|
52509
|
+
...rule,
|
|
52510
|
+
ranges: rule.ranges.map((range) => this.getters.getRangeString(range, sheet.id, { useFixedReference: true })),
|
|
52511
|
+
});
|
|
52512
|
+
}
|
|
52513
|
+
}
|
|
52514
|
+
}
|
|
52294
52515
|
checkCriterionTypeIsValid(cmd) {
|
|
52295
52516
|
return dataValidationEvaluatorRegistry.contains(cmd.rule.criterion.type)
|
|
52296
52517
|
? "Success" /* CommandResult.Success */
|
|
@@ -54058,6 +54279,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
54058
54279
|
formats: {},
|
|
54059
54280
|
borders: {},
|
|
54060
54281
|
conditionalFormats: [],
|
|
54282
|
+
dataValidationRules: [],
|
|
54061
54283
|
figures: [],
|
|
54062
54284
|
tables: [],
|
|
54063
54285
|
areGridLinesVisible: sheet.areGridLinesVisible === undefined ? true : sheet.areGridLinesVisible,
|
|
@@ -64541,8 +64763,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64541
64763
|
},
|
|
64542
64764
|
];
|
|
64543
64765
|
handler.paste({ zones: pasteTarget, sheetId }, data, { isCutOperation: true });
|
|
64766
|
+
const selection = pasteTarget[0];
|
|
64767
|
+
const col = selection.left;
|
|
64768
|
+
const row = selection.top;
|
|
64769
|
+
this.setSelectionMixin({ zone: selection, cell: { col, row } }, [selection]);
|
|
64544
64770
|
const toRemove = isBasedBefore ? cmd.elements.map((el) => el + thickness) : cmd.elements;
|
|
64545
|
-
let currentIndex = cmd.base;
|
|
64771
|
+
let currentIndex = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
64546
64772
|
for (const element of toRemove) {
|
|
64547
64773
|
const size = this.getters.getHeaderSize(cmd.sheetId, cmd.dimension, element);
|
|
64548
64774
|
this.dispatch("RESIZE_COLUMNS_ROWS", {
|
|
@@ -64825,22 +65051,33 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64825
65051
|
}
|
|
64826
65052
|
/**
|
|
64827
65053
|
*
|
|
64828
|
-
*
|
|
64829
|
-
*
|
|
65054
|
+
* Computes the visible coordinates & dimensions of a given zone inside the viewport
|
|
65055
|
+
*
|
|
64830
65056
|
*/
|
|
64831
|
-
|
|
65057
|
+
getVisibleRect(zone) {
|
|
64832
65058
|
const targetZone = intersection(zone, this);
|
|
64833
65059
|
if (targetZone) {
|
|
64834
65060
|
const x = this.getters.getColRowOffset("COL", this.left, targetZone.left) + this.offsetCorrectionX;
|
|
64835
65061
|
const y = this.getters.getColRowOffset("ROW", this.top, targetZone.top) + this.offsetCorrectionY;
|
|
64836
65062
|
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
|
|
64837
65063
|
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
|
|
64838
|
-
return {
|
|
64839
|
-
|
|
64840
|
-
|
|
64841
|
-
|
|
64842
|
-
|
|
64843
|
-
|
|
65064
|
+
return { x, y, width, height };
|
|
65065
|
+
}
|
|
65066
|
+
return undefined;
|
|
65067
|
+
}
|
|
65068
|
+
/**
|
|
65069
|
+
*
|
|
65070
|
+
* @returns Computes the absolute coordinates & dimensions of a given zone inside the viewport
|
|
65071
|
+
*
|
|
65072
|
+
*/
|
|
65073
|
+
getFullRect(zone) {
|
|
65074
|
+
const targetZone = intersection(zone, this);
|
|
65075
|
+
if (targetZone) {
|
|
65076
|
+
const x = this.getters.getColRowOffset("COL", this.left, zone.left) + this.offsetCorrectionX;
|
|
65077
|
+
const y = this.getters.getColRowOffset("ROW", this.top, zone.top) + this.offsetCorrectionY;
|
|
65078
|
+
const width = this.getters.getColRowOffset("COL", zone.left, zone.right + 1);
|
|
65079
|
+
const height = this.getters.getColRowOffset("ROW", zone.top, zone.bottom + 1);
|
|
65080
|
+
return { x, y, width, height };
|
|
64844
65081
|
}
|
|
64845
65082
|
return undefined;
|
|
64846
65083
|
}
|
|
@@ -65010,6 +65247,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65010
65247
|
"isPositionVisible",
|
|
65011
65248
|
"getColDimensionsInViewport",
|
|
65012
65249
|
"getRowDimensionsInViewport",
|
|
65250
|
+
"getAllActiveViewportsZones",
|
|
65251
|
+
"getRect",
|
|
65013
65252
|
];
|
|
65014
65253
|
viewports = {};
|
|
65015
65254
|
/**
|
|
@@ -65396,16 +65635,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65396
65635
|
getVisibleRectWithoutHeaders(zone) {
|
|
65397
65636
|
const sheetId = this.getters.getActiveSheetId();
|
|
65398
65637
|
const viewportRects = this.getSubViewports(sheetId)
|
|
65399
|
-
.map((viewport) => viewport.
|
|
65638
|
+
.map((viewport) => viewport.getVisibleRect(zone))
|
|
65400
65639
|
.filter(isDefined);
|
|
65401
65640
|
if (viewportRects.length === 0) {
|
|
65402
65641
|
return { x: 0, y: 0, width: 0, height: 0 };
|
|
65403
65642
|
}
|
|
65404
|
-
|
|
65405
|
-
|
|
65406
|
-
|
|
65407
|
-
|
|
65408
|
-
|
|
65643
|
+
return this.recomposeRect(viewportRects);
|
|
65644
|
+
}
|
|
65645
|
+
/**
|
|
65646
|
+
* Computes the actual size and position (:Rect) of the zone on the canvas
|
|
65647
|
+
* regardless of the viewport dimensions.
|
|
65648
|
+
*/
|
|
65649
|
+
getRect(zone) {
|
|
65650
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
65651
|
+
const viewportRects = this.getSubViewports(sheetId)
|
|
65652
|
+
.map((viewport) => viewport.getFullRect(zone))
|
|
65653
|
+
.filter(isDefined);
|
|
65654
|
+
if (viewportRects.length === 0) {
|
|
65655
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
65656
|
+
}
|
|
65657
|
+
const rect = this.recomposeRect(viewportRects);
|
|
65658
|
+
return { ...rect, x: rect.x + this.gridOffsetX, y: rect.y + this.gridOffsetY };
|
|
65409
65659
|
}
|
|
65410
65660
|
/**
|
|
65411
65661
|
* Returns the position of the MainViewport relatively to the start of the grid (without headers)
|
|
@@ -65449,6 +65699,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65449
65699
|
end: start + (isRowHidden ? 0 : size),
|
|
65450
65700
|
};
|
|
65451
65701
|
}
|
|
65702
|
+
getAllActiveViewportsZones() {
|
|
65703
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
65704
|
+
return this.getSubViewports(sheetId);
|
|
65705
|
+
}
|
|
65452
65706
|
// ---------------------------------------------------------------------------
|
|
65453
65707
|
// Private
|
|
65454
65708
|
// ---------------------------------------------------------------------------
|
|
@@ -65639,6 +65893,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65639
65893
|
const height = this.sheetViewHeight + this.gridOffsetY;
|
|
65640
65894
|
return { xRatio: offsetCorrectionX / width, yRatio: offsetCorrectionY / height };
|
|
65641
65895
|
}
|
|
65896
|
+
recomposeRect(viewportRects) {
|
|
65897
|
+
const x = Math.min(...viewportRects.map((rect) => rect.x));
|
|
65898
|
+
const y = Math.min(...viewportRects.map((rect) => rect.y));
|
|
65899
|
+
const width = Math.max(...viewportRects.map((rect) => rect.x + rect.width)) - x;
|
|
65900
|
+
const height = Math.max(...viewportRects.map((rect) => rect.y + rect.height)) - y;
|
|
65901
|
+
return { x, y, width, height };
|
|
65902
|
+
}
|
|
65642
65903
|
}
|
|
65643
65904
|
|
|
65644
65905
|
class HeaderPositionsUIPlugin extends UIPlugin {
|
|
@@ -70944,6 +71205,124 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70944
71205
|
}
|
|
70945
71206
|
}
|
|
70946
71207
|
|
|
71208
|
+
function addDataValidationRules(dataValidationRules) {
|
|
71209
|
+
const dvRulesCount = dataValidationRules.length;
|
|
71210
|
+
if (dvRulesCount === 0) {
|
|
71211
|
+
return [];
|
|
71212
|
+
}
|
|
71213
|
+
const dvNodes = [new XMLString(`<dataValidations count="${dvRulesCount}">`)];
|
|
71214
|
+
for (const dvRule of dataValidationRules) {
|
|
71215
|
+
switch (dvRule.criterion.type) {
|
|
71216
|
+
case "dateIs":
|
|
71217
|
+
case "dateIsBefore":
|
|
71218
|
+
case "dateIsOnOrBefore":
|
|
71219
|
+
case "dateIsAfter":
|
|
71220
|
+
case "dateIsOnOrAfter":
|
|
71221
|
+
case "dateIsBetween":
|
|
71222
|
+
case "dateIsNotBetween":
|
|
71223
|
+
dvNodes.push(addDateRule(dvRule));
|
|
71224
|
+
break;
|
|
71225
|
+
case "isEqual":
|
|
71226
|
+
case "isNotEqual":
|
|
71227
|
+
case "isGreaterThan":
|
|
71228
|
+
case "isGreaterOrEqualTo":
|
|
71229
|
+
case "isLessThan":
|
|
71230
|
+
case "isLessOrEqualTo":
|
|
71231
|
+
case "isBetween":
|
|
71232
|
+
case "isNotBetween":
|
|
71233
|
+
dvNodes.push(addDecimalRule(dvRule));
|
|
71234
|
+
break;
|
|
71235
|
+
case "isValueInRange":
|
|
71236
|
+
case "isValueInList":
|
|
71237
|
+
dvNodes.push(addListRule(dvRule));
|
|
71238
|
+
break;
|
|
71239
|
+
case "customFormula":
|
|
71240
|
+
dvNodes.push(addCustomFormulaRule(dvRule));
|
|
71241
|
+
break;
|
|
71242
|
+
default:
|
|
71243
|
+
console.warn(`Data validation ${dvRule.criterion.type} is not supported in xlsx.`);
|
|
71244
|
+
break;
|
|
71245
|
+
}
|
|
71246
|
+
}
|
|
71247
|
+
dvNodes.push(new XMLString("</dataValidations>"));
|
|
71248
|
+
return dvNodes;
|
|
71249
|
+
}
|
|
71250
|
+
function addDateRule(dvRule) {
|
|
71251
|
+
const rule = dvRule.criterion;
|
|
71252
|
+
const formula1 = adaptFormulaToExcel(rule.values[0]);
|
|
71253
|
+
const formula2 = rule.values[1] ? adaptFormulaToExcel(rule.values[1]) : undefined;
|
|
71254
|
+
const operator = convertDateCriterionTypeToExcelOperator(dvRule.criterion.type);
|
|
71255
|
+
const attributes = commonDataValidationAttributes(dvRule);
|
|
71256
|
+
attributes.push(["type", "date"], ["operator", operator]);
|
|
71257
|
+
if (formula2) {
|
|
71258
|
+
return escapeXml /*xml*/ `
|
|
71259
|
+
<dataValidation ${formatAttributes(attributes)}>
|
|
71260
|
+
<formula1>${toNumber(formula1, DEFAULT_LOCALE)}</formula1>
|
|
71261
|
+
<formula2>${toNumber(formula2, DEFAULT_LOCALE)}</formula2>
|
|
71262
|
+
</dataValidation>
|
|
71263
|
+
`;
|
|
71264
|
+
}
|
|
71265
|
+
return escapeXml /*xml*/ `
|
|
71266
|
+
<dataValidation ${formatAttributes(attributes)}>
|
|
71267
|
+
<formula1>${toNumber(formula1, DEFAULT_LOCALE)}</formula1>
|
|
71268
|
+
</dataValidation>
|
|
71269
|
+
`;
|
|
71270
|
+
}
|
|
71271
|
+
function addDecimalRule(dvRule) {
|
|
71272
|
+
const rule = dvRule.criterion;
|
|
71273
|
+
const formula1 = adaptFormulaToExcel(rule.values[0]);
|
|
71274
|
+
const formula2 = rule.values[1] ? adaptFormulaToExcel(rule.values[1]) : undefined;
|
|
71275
|
+
const operator = convertDecimalCriterionTypeToExcelOperator(dvRule.criterion.type);
|
|
71276
|
+
const attributes = commonDataValidationAttributes(dvRule);
|
|
71277
|
+
attributes.push(["type", "decimal"], ["operator", operator]);
|
|
71278
|
+
if (formula2) {
|
|
71279
|
+
return escapeXml /*xml*/ `
|
|
71280
|
+
<dataValidation ${formatAttributes(attributes)}>
|
|
71281
|
+
<formula1>${formula1}</formula1>
|
|
71282
|
+
<formula2>${formula2}</formula2>
|
|
71283
|
+
</dataValidation>
|
|
71284
|
+
`;
|
|
71285
|
+
}
|
|
71286
|
+
return escapeXml /*xml*/ `
|
|
71287
|
+
<dataValidation ${formatAttributes(attributes)}>
|
|
71288
|
+
<formula1>${formula1}</formula1>
|
|
71289
|
+
</dataValidation>
|
|
71290
|
+
`;
|
|
71291
|
+
}
|
|
71292
|
+
function addListRule(dvRule) {
|
|
71293
|
+
const rule = dvRule.criterion;
|
|
71294
|
+
const formula1 = dvRule.criterion.type === "isValueInRange"
|
|
71295
|
+
? adaptFormulaToExcel(rule.values[0])
|
|
71296
|
+
: `"${rule.values.join(",")}"`;
|
|
71297
|
+
const attributes = commonDataValidationAttributes(dvRule);
|
|
71298
|
+
attributes.push(["type", "list"]);
|
|
71299
|
+
return escapeXml /*xml*/ `
|
|
71300
|
+
<dataValidation ${formatAttributes(attributes)}>
|
|
71301
|
+
<formula1>${formula1}</formula1>
|
|
71302
|
+
</dataValidation>
|
|
71303
|
+
`;
|
|
71304
|
+
}
|
|
71305
|
+
function addCustomFormulaRule(dvRule) {
|
|
71306
|
+
const rule = dvRule.criterion;
|
|
71307
|
+
const formula1 = adaptFormulaToExcel(rule.values[0]);
|
|
71308
|
+
const attributes = commonDataValidationAttributes(dvRule);
|
|
71309
|
+
attributes.push(["type", "custom"]);
|
|
71310
|
+
return escapeXml /*xml*/ `
|
|
71311
|
+
<dataValidation ${formatAttributes(attributes)}>
|
|
71312
|
+
<formula1>${formula1}</formula1>
|
|
71313
|
+
</dataValidation>
|
|
71314
|
+
`;
|
|
71315
|
+
}
|
|
71316
|
+
function commonDataValidationAttributes(dvRule) {
|
|
71317
|
+
return [
|
|
71318
|
+
["allowBlank", "1"],
|
|
71319
|
+
["showInputMessage", "1"],
|
|
71320
|
+
["showErrorMessage", "1"],
|
|
71321
|
+
["errorStyle", !dvRule.isBlocking ? "warning" : ""],
|
|
71322
|
+
["sqref", dvRule.ranges.join(" ")],
|
|
71323
|
+
];
|
|
71324
|
+
}
|
|
71325
|
+
|
|
70947
71326
|
function createDrawing(drawingRelIds, sheet, figures) {
|
|
70948
71327
|
const namespaces = [
|
|
70949
71328
|
["xmlns:xdr", NAMESPACE.drawing],
|
|
@@ -71722,6 +72101,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
71722
72101
|
${addRows(construct, data, sheet)}
|
|
71723
72102
|
${addMerges(sheet.merges)}
|
|
71724
72103
|
${joinXmlNodes(addConditionalFormatting(construct.dxfs, sheet.conditionalFormats))}
|
|
72104
|
+
${joinXmlNodes(addDataValidationRules(sheet.dataValidationRules))}
|
|
71725
72105
|
${addHyperlinks(construct, data, sheetIndex)}
|
|
71726
72106
|
${drawingNode}
|
|
71727
72107
|
${tablesNode}
|
|
@@ -72673,9 +73053,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72673
73053
|
exports.tokenize = tokenize;
|
|
72674
73054
|
|
|
72675
73055
|
|
|
72676
|
-
__info__.version = "18.0.
|
|
72677
|
-
__info__.date = "2025-01-
|
|
72678
|
-
__info__.hash = "
|
|
73056
|
+
__info__.version = "18.0.11";
|
|
73057
|
+
__info__.date = "2025-01-27T10:08:13.567Z";
|
|
73058
|
+
__info__.hash = "e8c6bd1";
|
|
72679
73059
|
|
|
72680
73060
|
|
|
72681
73061
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|