@odoo/o-spreadsheet 18.0.4 → 18.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o-spreadsheet.cjs.js +257 -167
- package/dist/o-spreadsheet.d.ts +4099 -4085
- package/dist/o-spreadsheet.esm.js +257 -167
- package/dist/o-spreadsheet.iife.js +257 -167
- package/dist/o-spreadsheet.iife.min.js +505 -505
- package/dist/o_spreadsheet.xml +5 -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 2024-11-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.0.5
|
|
6
|
+
* @date 2024-11-22T14:19:19.721Z
|
|
7
|
+
* @hash 9eb34d9
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -130,7 +130,6 @@ const SELECTION_BORDER_COLOR = "#3266ca";
|
|
|
130
130
|
const HEADER_BORDER_COLOR = "#C0C0C0";
|
|
131
131
|
const CELL_BORDER_COLOR = "#E2E3E3";
|
|
132
132
|
const BACKGROUND_CHART_COLOR = "#FFFFFF";
|
|
133
|
-
const BORDER_CHART_COLOR = "#FFFFFF";
|
|
134
133
|
const DISABLED_TEXT_COLOR = "#CACACA";
|
|
135
134
|
const DEFAULT_COLOR_SCALE_MIDPOINT_COLOR = 0xb6d7a8;
|
|
136
135
|
const LINK_COLOR = "#017E84";
|
|
@@ -3224,7 +3223,6 @@ var ClipboardMIMEType;
|
|
|
3224
3223
|
(function (ClipboardMIMEType) {
|
|
3225
3224
|
ClipboardMIMEType["PlainText"] = "text/plain";
|
|
3226
3225
|
ClipboardMIMEType["Html"] = "text/html";
|
|
3227
|
-
ClipboardMIMEType["OSpreadsheet"] = "web application/o-spreadsheet";
|
|
3228
3226
|
})(ClipboardMIMEType || (ClipboardMIMEType = {}));
|
|
3229
3227
|
|
|
3230
3228
|
function isSheetDependent(cmd) {
|
|
@@ -4334,7 +4332,9 @@ function linearSearch(data, target, mode, numberOfValues, getValueInData, revers
|
|
|
4334
4332
|
return reverseSearch ? numberOfValues - i - 1 : i;
|
|
4335
4333
|
}
|
|
4336
4334
|
}
|
|
4337
|
-
return reverseSearch
|
|
4335
|
+
return reverseSearch && closestMatchIndex !== -1
|
|
4336
|
+
? numberOfValues - closestMatchIndex - 1
|
|
4337
|
+
: closestMatchIndex;
|
|
4338
4338
|
}
|
|
4339
4339
|
/**
|
|
4340
4340
|
* Normalize a value.
|
|
@@ -6147,6 +6147,22 @@ function getPasteZones(target, content) {
|
|
|
6147
6147
|
const width = content[0].length, height = content.length;
|
|
6148
6148
|
return target.map((t) => splitZoneForPaste(t, width, height)).flat();
|
|
6149
6149
|
}
|
|
6150
|
+
function parseOSClipboardContent(content) {
|
|
6151
|
+
if (!content[ClipboardMIMEType.Html]) {
|
|
6152
|
+
return {
|
|
6153
|
+
text: content[ClipboardMIMEType.PlainText],
|
|
6154
|
+
};
|
|
6155
|
+
}
|
|
6156
|
+
const htmlDocument = new DOMParser().parseFromString(content[ClipboardMIMEType.Html], "text/html");
|
|
6157
|
+
const oSheetClipboardData = htmlDocument
|
|
6158
|
+
.querySelector("div")
|
|
6159
|
+
?.getAttribute("data-osheet-clipboard");
|
|
6160
|
+
const spreadsheetContent = oSheetClipboardData && JSON.parse(oSheetClipboardData);
|
|
6161
|
+
return {
|
|
6162
|
+
text: content[ClipboardMIMEType.PlainText],
|
|
6163
|
+
data: spreadsheetContent,
|
|
6164
|
+
};
|
|
6165
|
+
}
|
|
6150
6166
|
|
|
6151
6167
|
class ClipboardHandler {
|
|
6152
6168
|
getters;
|
|
@@ -6168,7 +6184,7 @@ class ClipboardHandler {
|
|
|
6168
6184
|
getPasteTarget(sheetId, target, content, options) {
|
|
6169
6185
|
return { zones: [], sheetId };
|
|
6170
6186
|
}
|
|
6171
|
-
|
|
6187
|
+
convertTextToClipboardData(data) {
|
|
6172
6188
|
return;
|
|
6173
6189
|
}
|
|
6174
6190
|
}
|
|
@@ -7998,7 +8014,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
7998
8014
|
this.dispatch("CLEAR_CELL", target);
|
|
7999
8015
|
}
|
|
8000
8016
|
}
|
|
8001
|
-
|
|
8017
|
+
convertTextToClipboardData(text) {
|
|
8002
8018
|
const locale = this.getters.getLocale();
|
|
8003
8019
|
const copiedData = {
|
|
8004
8020
|
cells: [],
|
|
@@ -8106,6 +8122,7 @@ class ChartClipboardHandler extends AbstractFigureClipboardHandler {
|
|
|
8106
8122
|
|
|
8107
8123
|
class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
|
|
8108
8124
|
uuidGenerator = new UuidGenerator();
|
|
8125
|
+
queuedChanges = {};
|
|
8109
8126
|
copy(data) {
|
|
8110
8127
|
if (!data.zones.length) {
|
|
8111
8128
|
return;
|
|
@@ -8127,6 +8144,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8127
8144
|
return { cfRules };
|
|
8128
8145
|
}
|
|
8129
8146
|
paste(target, clippedContent, options) {
|
|
8147
|
+
this.queuedChanges = {};
|
|
8130
8148
|
if (options.pasteOption === "asValue") {
|
|
8131
8149
|
return;
|
|
8132
8150
|
}
|
|
@@ -8138,6 +8156,7 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8138
8156
|
else {
|
|
8139
8157
|
this.pasteFromCut(sheetId, zones, clippedContent);
|
|
8140
8158
|
}
|
|
8159
|
+
this.executeQueuedChanges();
|
|
8141
8160
|
}
|
|
8142
8161
|
pasteFromCut(sheetId, target, content) {
|
|
8143
8162
|
const selection = target[0];
|
|
@@ -8177,34 +8196,56 @@ class ConditionalFormatClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8177
8196
|
* Add or remove cells to a given conditional formatting rule.
|
|
8178
8197
|
*/
|
|
8179
8198
|
adaptCFRules(sheetId, cf, toAdd, toRemove) {
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
return;
|
|
8199
|
+
if (!this.queuedChanges[sheetId]) {
|
|
8200
|
+
this.queuedChanges[sheetId] = [];
|
|
8183
8201
|
}
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8202
|
+
const queuedChange = this.queuedChanges[sheetId].find((queued) => queued.cf.id === cf.id);
|
|
8203
|
+
if (!queuedChange) {
|
|
8204
|
+
this.queuedChanges[sheetId].push({ toAdd, toRemove, cf });
|
|
8205
|
+
}
|
|
8206
|
+
else {
|
|
8207
|
+
queuedChange.toAdd.push(...toAdd);
|
|
8208
|
+
queuedChange.toRemove.push(...toRemove);
|
|
8209
|
+
}
|
|
8210
|
+
}
|
|
8211
|
+
executeQueuedChanges() {
|
|
8212
|
+
for (const sheetId in this.queuedChanges) {
|
|
8213
|
+
for (const { toAdd, toRemove, cf } of this.queuedChanges[sheetId]) {
|
|
8214
|
+
const newRangesXc = this.getters.getAdaptedCfRanges(sheetId, cf, toAdd, toRemove);
|
|
8215
|
+
if (!newRangesXc) {
|
|
8216
|
+
continue;
|
|
8217
|
+
}
|
|
8218
|
+
if (newRangesXc.length === 0) {
|
|
8219
|
+
this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
|
|
8220
|
+
continue;
|
|
8221
|
+
}
|
|
8222
|
+
this.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
8223
|
+
cf: {
|
|
8224
|
+
id: cf.id,
|
|
8225
|
+
rule: cf.rule,
|
|
8226
|
+
stopIfTrue: cf.stopIfTrue,
|
|
8227
|
+
},
|
|
8228
|
+
ranges: newRangesXc,
|
|
8229
|
+
sheetId,
|
|
8230
|
+
});
|
|
8231
|
+
}
|
|
8187
8232
|
}
|
|
8188
|
-
this.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
8189
|
-
cf: {
|
|
8190
|
-
id: cf.id,
|
|
8191
|
-
rule: cf.rule,
|
|
8192
|
-
stopIfTrue: cf.stopIfTrue,
|
|
8193
|
-
},
|
|
8194
|
-
ranges: newRangesXc,
|
|
8195
|
-
sheetId,
|
|
8196
|
-
});
|
|
8197
8233
|
}
|
|
8198
8234
|
getCFToCopyTo(targetSheetId, originCF) {
|
|
8199
|
-
|
|
8235
|
+
let targetCF = this.getters
|
|
8200
8236
|
.getConditionalFormats(targetSheetId)
|
|
8201
8237
|
.find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
|
|
8202
|
-
|
|
8238
|
+
const queuedCfs = this.queuedChanges[targetSheetId];
|
|
8239
|
+
if (!targetCF && queuedCfs) {
|
|
8240
|
+
targetCF = queuedCfs.find((queued) => queued.cf.stopIfTrue === originCF.stopIfTrue && deepEquals(queued.cf.rule, originCF.rule))?.cf;
|
|
8241
|
+
}
|
|
8242
|
+
return targetCF || { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
|
|
8203
8243
|
}
|
|
8204
8244
|
}
|
|
8205
8245
|
|
|
8206
8246
|
class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
|
|
8207
8247
|
uuidGenerator = new UuidGenerator();
|
|
8248
|
+
queuedChanges = {};
|
|
8208
8249
|
copy(data) {
|
|
8209
8250
|
const { rowsIndexes, columnsIndexes } = data;
|
|
8210
8251
|
const sheetId = data.sheetId;
|
|
@@ -8221,6 +8262,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8221
8262
|
return { dvRules };
|
|
8222
8263
|
}
|
|
8223
8264
|
paste(target, clippedContent, options) {
|
|
8265
|
+
this.queuedChanges = {};
|
|
8224
8266
|
if (options.pasteOption) {
|
|
8225
8267
|
return;
|
|
8226
8268
|
}
|
|
@@ -8232,6 +8274,7 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8232
8274
|
else {
|
|
8233
8275
|
this.pasteFromCut(sheetId, zones, clippedContent);
|
|
8234
8276
|
}
|
|
8277
|
+
this.executeQueuedChanges();
|
|
8235
8278
|
}
|
|
8236
8279
|
pasteFromCut(sheetId, target, content) {
|
|
8237
8280
|
const selection = target[0];
|
|
@@ -8278,29 +8321,55 @@ class DataValidationClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
8278
8321
|
}
|
|
8279
8322
|
}
|
|
8280
8323
|
getDataValidationRuleToCopyTo(targetSheetId, originRule, newId = true) {
|
|
8281
|
-
|
|
8324
|
+
let targetRule = this.getters
|
|
8282
8325
|
.getDataValidationRules(targetSheetId)
|
|
8283
8326
|
.find((rule) => deepEquals(originRule.criterion, rule.criterion) &&
|
|
8284
8327
|
originRule.isBlocking === rule.isBlocking);
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8328
|
+
const queuedRules = this.queuedChanges[targetSheetId];
|
|
8329
|
+
if (!targetRule && queuedRules) {
|
|
8330
|
+
targetRule = queuedRules.find((queued) => deepEquals(originRule.criterion, queued.rule.criterion) &&
|
|
8331
|
+
originRule.isBlocking === queued.rule.isBlocking)?.rule;
|
|
8332
|
+
}
|
|
8333
|
+
return (targetRule || {
|
|
8334
|
+
...originRule,
|
|
8335
|
+
id: newId ? this.uuidGenerator.uuidv4() : originRule.id,
|
|
8336
|
+
ranges: [],
|
|
8337
|
+
});
|
|
8288
8338
|
}
|
|
8289
8339
|
/**
|
|
8290
8340
|
* Add or remove XCs to a given data validation rule.
|
|
8291
8341
|
*/
|
|
8292
8342
|
adaptDataValidationRule(sheetId, rule, toAdd, toRemove) {
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8343
|
+
if (!this.queuedChanges[sheetId]) {
|
|
8344
|
+
this.queuedChanges[sheetId] = [];
|
|
8345
|
+
}
|
|
8346
|
+
const queuedChange = this.queuedChanges[sheetId].find((queued) => queued.rule.id === rule.id);
|
|
8347
|
+
if (!queuedChange) {
|
|
8348
|
+
this.queuedChanges[sheetId].push({ toAdd, toRemove, rule });
|
|
8349
|
+
}
|
|
8350
|
+
else {
|
|
8351
|
+
queuedChange.toAdd.push(...toAdd);
|
|
8352
|
+
queuedChange.toRemove.push(...toRemove);
|
|
8353
|
+
}
|
|
8354
|
+
}
|
|
8355
|
+
executeQueuedChanges() {
|
|
8356
|
+
for (const sheetId in this.queuedChanges) {
|
|
8357
|
+
for (const { toAdd, toRemove, rule: dv } of this.queuedChanges[sheetId]) {
|
|
8358
|
+
// Remove the zones first in case the same position is in toAdd and toRemove
|
|
8359
|
+
const dvZones = dv.ranges.map((range) => range.zone);
|
|
8360
|
+
const withRemovedZones = recomputeZones(dvZones, toRemove);
|
|
8361
|
+
const newDvZones = recomputeZones([...withRemovedZones, ...toAdd], []);
|
|
8362
|
+
if (newDvZones.length === 0) {
|
|
8363
|
+
this.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: dv.id });
|
|
8364
|
+
continue;
|
|
8365
|
+
}
|
|
8366
|
+
this.dispatch("ADD_DATA_VALIDATION_RULE", {
|
|
8367
|
+
rule: dv,
|
|
8368
|
+
ranges: newDvZones.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
|
|
8369
|
+
sheetId,
|
|
8370
|
+
});
|
|
8371
|
+
}
|
|
8298
8372
|
}
|
|
8299
|
-
this.dispatch("ADD_DATA_VALIDATION_RULE", {
|
|
8300
|
-
rule,
|
|
8301
|
-
ranges: newDvZones.map((zone) => this.getters.getRangeDataFromZone(sheetId, zone)),
|
|
8302
|
-
sheetId,
|
|
8303
|
-
});
|
|
8304
8373
|
}
|
|
8305
8374
|
}
|
|
8306
8375
|
|
|
@@ -10360,6 +10429,10 @@ function makeArg(str, description) {
|
|
|
10360
10429
|
description,
|
|
10361
10430
|
type: types,
|
|
10362
10431
|
};
|
|
10432
|
+
const acceptErrors = types.includes("ANY") || types.includes("RANGE");
|
|
10433
|
+
if (acceptErrors) {
|
|
10434
|
+
result.acceptErrors = true;
|
|
10435
|
+
}
|
|
10363
10436
|
if (isOptional) {
|
|
10364
10437
|
result.optional = true;
|
|
10365
10438
|
}
|
|
@@ -12423,8 +12496,8 @@ const AVERAGEIFS = {
|
|
|
12423
12496
|
const COUNT = {
|
|
12424
12497
|
description: _t("The number of numeric values in dataset."),
|
|
12425
12498
|
args: [
|
|
12426
|
-
arg("value1 (number, range<number>)", _t("The first value or range to consider when counting.")),
|
|
12427
|
-
arg("value2 (number, range<number>, repeating)", _t("Additional values or ranges to consider when counting.")),
|
|
12499
|
+
arg("value1 (number, any, range<number>)", _t("The first value or range to consider when counting.")),
|
|
12500
|
+
arg("value2 (number, any, range<number>, repeating)", _t("Additional values or ranges to consider when counting.")),
|
|
12428
12501
|
],
|
|
12429
12502
|
compute: function (...values) {
|
|
12430
12503
|
return countNumbers(values, this.locale);
|
|
@@ -12813,6 +12886,7 @@ const PEARSON = {
|
|
|
12813
12886
|
},
|
|
12814
12887
|
isExported: true,
|
|
12815
12888
|
};
|
|
12889
|
+
// CORREL
|
|
12816
12890
|
// In GSheet, CORREL is just an alias to PEARSON
|
|
12817
12891
|
const CORREL = PEARSON;
|
|
12818
12892
|
// -----------------------------------------------------------------------------
|
|
@@ -13424,7 +13498,7 @@ function getMatchingCells(database, field, criteria, locale) {
|
|
|
13424
13498
|
}
|
|
13425
13499
|
const databaseArgs = [
|
|
13426
13500
|
arg("database (range)", _t("The array or range containing the data to consider, structured in such a way that the first row contains the labels for each column's values.")),
|
|
13427
|
-
arg("field (
|
|
13501
|
+
arg("field (number, string)", _t("Indicates which column in database contains the values to be extracted and operated on.")),
|
|
13428
13502
|
arg("criteria (range)", _t("An array or range containing zero or more criteria to filter the database values by before operating.")),
|
|
13429
13503
|
];
|
|
13430
13504
|
// -----------------------------------------------------------------------------
|
|
@@ -17783,7 +17857,7 @@ const IFS = {
|
|
|
17783
17857
|
args: [
|
|
17784
17858
|
arg("condition1 (boolean)", _t("The first condition to be evaluated. This can be a boolean, a number, an array, or a reference to any of those.")),
|
|
17785
17859
|
arg("value1 (any)", _t("The returned value if condition1 is TRUE.")),
|
|
17786
|
-
arg("condition2 (boolean, repeating)", _t("Additional conditions to be evaluated if the previous ones are FALSE.")),
|
|
17860
|
+
arg("condition2 (boolean, any, repeating)", _t("Additional conditions to be evaluated if the previous ones are FALSE.")),
|
|
17787
17861
|
arg("value2 (any, repeating)", _t("Additional values to be returned if their corresponding conditions are TRUE.")),
|
|
17788
17862
|
],
|
|
17789
17863
|
compute: function (...values) {
|
|
@@ -18022,7 +18096,7 @@ const COLUMNS = {
|
|
|
18022
18096
|
const HLOOKUP = {
|
|
18023
18097
|
description: _t("Horizontal lookup"),
|
|
18024
18098
|
args: [
|
|
18025
|
-
arg("search_key (
|
|
18099
|
+
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18026
18100
|
arg("range (range)", _t("The range to consider for the search. The first row in the range is searched for the key specified in search_key.")),
|
|
18027
18101
|
arg("index (number)", _t("The row index of the value to be returned, where the first row in range is numbered 1.")),
|
|
18028
18102
|
arg(`is_sorted (boolean, default=${DEFAULT_IS_SORTED})`, _t("Indicates whether the row to be searched (the first row of the specified range) is sorted, in which case the closest match for search_key will be returned.")),
|
|
@@ -18030,9 +18104,6 @@ const HLOOKUP = {
|
|
|
18030
18104
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18031
18105
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18032
18106
|
assert(() => 1 <= _index && _index <= range[0].length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18033
|
-
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
18034
|
-
return searchKey;
|
|
18035
|
-
}
|
|
18036
18107
|
const getValueFromRange = (range, index) => range[index][0].value;
|
|
18037
18108
|
const _isSorted = toBoolean(isSorted.value);
|
|
18038
18109
|
const colIndex = _isSorted
|
|
@@ -18129,7 +18200,7 @@ const INDIRECT = {
|
|
|
18129
18200
|
const LOOKUP = {
|
|
18130
18201
|
description: _t("Look up a value."),
|
|
18131
18202
|
args: [
|
|
18132
|
-
arg("search_key (
|
|
18203
|
+
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18133
18204
|
arg("search_array (range)", _t("One method of using this function is to provide a single sorted row or column search_array to look through for the search_key with a second argument result_range. The other way is to combine these two arguments into one search_array where the first row or column is searched and a value is returned from the last row or column in the array. If search_key is not found, a non-exact match may be returned.")),
|
|
18134
18205
|
arg("result_range (range, optional)", _t("The range from which to return a result. The value returned corresponds to the location where search_key is found in search_range. This range must be only a single row or column and should not be used if using the search_result_array method.")),
|
|
18135
18206
|
],
|
|
@@ -18169,7 +18240,7 @@ const DEFAULT_SEARCH_TYPE = 1;
|
|
|
18169
18240
|
const MATCH = {
|
|
18170
18241
|
description: _t("Position of item in range that matches value."),
|
|
18171
18242
|
args: [
|
|
18172
|
-
arg("search_key (
|
|
18243
|
+
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18173
18244
|
arg("range (any, range)", _t("The one-dimensional array to be searched.")),
|
|
18174
18245
|
arg(`search_type (number, default=${DEFAULT_SEARCH_TYPE})`, _t("The search method. 1 (default) finds the largest value less than or equal to search_key when range is sorted in ascending order. 0 finds the exact value when range is unsorted. -1 finds the smallest value greater than or equal to search_key when range is sorted in descending order.")),
|
|
18175
18246
|
],
|
|
@@ -18244,7 +18315,7 @@ const ROWS = {
|
|
|
18244
18315
|
const VLOOKUP = {
|
|
18245
18316
|
description: _t("Vertical lookup."),
|
|
18246
18317
|
args: [
|
|
18247
|
-
arg("search_key (
|
|
18318
|
+
arg("search_key (string, number, boolean)", _t("The value to search for. For example, 42, 'Cats', or I24.")),
|
|
18248
18319
|
arg("range (any, range)", _t("The range to consider for the search. The first column in the range is searched for the key specified in search_key.")),
|
|
18249
18320
|
arg("index (number)", _t("The column index of the value to be returned, where the first column in range is numbered 1.")),
|
|
18250
18321
|
arg(`is_sorted (boolean, default=${DEFAULT_IS_SORTED})`, _t("Indicates whether the column to be searched (the first column of the specified range) is sorted, in which case the closest match for search_key will be returned.")),
|
|
@@ -18252,9 +18323,6 @@ const VLOOKUP = {
|
|
|
18252
18323
|
compute: function (searchKey, range, index, isSorted = { value: DEFAULT_IS_SORTED }) {
|
|
18253
18324
|
const _index = Math.trunc(toNumber(index?.value, this.locale));
|
|
18254
18325
|
assert(() => 1 <= _index && _index <= range.length, _t("[[FUNCTION_NAME]] evaluates to an out of bounds range."));
|
|
18255
|
-
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
18256
|
-
return searchKey;
|
|
18257
|
-
}
|
|
18258
18326
|
const getValueFromRange = (range, index) => range[0][index].value;
|
|
18259
18327
|
const _isSorted = toBoolean(isSorted.value);
|
|
18260
18328
|
const rowIndex = _isSorted
|
|
@@ -18280,7 +18348,7 @@ const MATCH_MODE = {
|
|
|
18280
18348
|
const XLOOKUP = {
|
|
18281
18349
|
description: _t("Search a range for a match and return the corresponding item from a second range."),
|
|
18282
18350
|
args: [
|
|
18283
|
-
arg("search_key (
|
|
18351
|
+
arg("search_key (string,number,boolean)", _t("The value to search for.")),
|
|
18284
18352
|
arg("lookup_range (any, range)", _t("The range to consider for the search. Should be a single column or a single row.")),
|
|
18285
18353
|
arg("return_range (any, range)", _t("The range containing the return value. Should have the same dimensions as lookup_range.")),
|
|
18286
18354
|
arg("if_not_found (any, optional)", _t("If a valid match is not found, return this value.")),
|
|
@@ -18305,9 +18373,6 @@ const XLOOKUP = {
|
|
|
18305
18373
|
assert(() => lookupDirection === "col"
|
|
18306
18374
|
? returnRange[0].length === lookupRange[0].length
|
|
18307
18375
|
: returnRange.length === lookupRange.length, _t("return_range should have the same dimensions as lookup_range."));
|
|
18308
|
-
if (searchKey && isEvaluationError(searchKey.value)) {
|
|
18309
|
-
return [[searchKey]];
|
|
18310
|
-
}
|
|
18311
18376
|
const getElement = lookupDirection === "col"
|
|
18312
18377
|
? (range, index) => range[0][index].value
|
|
18313
18378
|
: (range, index) => range[index][0].value;
|
|
@@ -18332,13 +18397,14 @@ const XLOOKUP = {
|
|
|
18332
18397
|
//--------------------------------------------------------------------------
|
|
18333
18398
|
// Pivot functions
|
|
18334
18399
|
//--------------------------------------------------------------------------
|
|
18400
|
+
// PIVOT.VALUE
|
|
18335
18401
|
const PIVOT_VALUE = {
|
|
18336
18402
|
description: _t("Get the value from a pivot."),
|
|
18337
18403
|
args: [
|
|
18338
|
-
arg("pivot_id (string)", _t("ID of the pivot.")),
|
|
18404
|
+
arg("pivot_id (number,string)", _t("ID of the pivot.")),
|
|
18339
18405
|
arg("measure_name (string)", _t("Name of the measure.")),
|
|
18340
18406
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18341
|
-
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18407
|
+
arg("domain_value (number,string,boolean,optional,repeating)", _t("Value.")),
|
|
18342
18408
|
],
|
|
18343
18409
|
compute: function (formulaId, measureName, ...domainArgs) {
|
|
18344
18410
|
const _pivotFormulaId = toString(formulaId);
|
|
@@ -18365,12 +18431,13 @@ const PIVOT_VALUE = {
|
|
|
18365
18431
|
return pivot.getPivotCellValueAndFormat(_measure, domain);
|
|
18366
18432
|
},
|
|
18367
18433
|
};
|
|
18434
|
+
// PIVOT.HEADER
|
|
18368
18435
|
const PIVOT_HEADER = {
|
|
18369
18436
|
description: _t("Get the header of a pivot."),
|
|
18370
18437
|
args: [
|
|
18371
|
-
arg("pivot_id (string)", _t("ID of the pivot.")),
|
|
18438
|
+
arg("pivot_id (number,string)", _t("ID of the pivot.")),
|
|
18372
18439
|
arg("domain_field_name (string,optional,repeating)", _t("Field name.")),
|
|
18373
|
-
arg("domain_value (string,optional,repeating)", _t("Value.")),
|
|
18440
|
+
arg("domain_value (number,string,value,optional,repeating)", _t("Value.")),
|
|
18374
18441
|
],
|
|
18375
18442
|
compute: function (pivotId, ...domainArgs) {
|
|
18376
18443
|
const _pivotFormulaId = toString(pivotId);
|
|
@@ -18617,8 +18684,8 @@ const getNeutral = { number: 0, string: "", boolean: false };
|
|
|
18617
18684
|
const EQ = {
|
|
18618
18685
|
description: _t("Equal."),
|
|
18619
18686
|
args: [
|
|
18620
|
-
arg("value1 (
|
|
18621
|
-
arg("value2 (
|
|
18687
|
+
arg("value1 (string, number, boolean)", _t("The first value.")),
|
|
18688
|
+
arg("value2 (string, number, boolean)", _t("The value to test against value1 for equality.")),
|
|
18622
18689
|
],
|
|
18623
18690
|
compute: function (value1, value2) {
|
|
18624
18691
|
let _value1 = isEmpty(value1) ? getNeutral[typeof value2?.value] : value1?.value;
|
|
@@ -18629,12 +18696,6 @@ const EQ = {
|
|
|
18629
18696
|
if (typeof _value2 === "string") {
|
|
18630
18697
|
_value2 = _value2.toUpperCase();
|
|
18631
18698
|
}
|
|
18632
|
-
if (isEvaluationError(_value1)) {
|
|
18633
|
-
throw value1;
|
|
18634
|
-
}
|
|
18635
|
-
if (isEvaluationError(_value2)) {
|
|
18636
|
-
throw value2;
|
|
18637
|
-
}
|
|
18638
18699
|
return _value1 === _value2;
|
|
18639
18700
|
},
|
|
18640
18701
|
};
|
|
@@ -18669,8 +18730,8 @@ function applyRelationalOperator(value1, value2, cb) {
|
|
|
18669
18730
|
const GT = {
|
|
18670
18731
|
description: _t("Strictly greater than."),
|
|
18671
18732
|
args: [
|
|
18672
|
-
arg("value1 (
|
|
18673
|
-
arg("value2 (
|
|
18733
|
+
arg("value1 (number, string, boolean)", _t("The value to test as being greater than value2.")),
|
|
18734
|
+
arg("value2 (number, string, boolean)", _t("The second value.")),
|
|
18674
18735
|
],
|
|
18675
18736
|
compute: function (value1, value2) {
|
|
18676
18737
|
return applyRelationalOperator(value1, value2, (v1, v2) => {
|
|
@@ -18684,8 +18745,8 @@ const GT = {
|
|
|
18684
18745
|
const GTE = {
|
|
18685
18746
|
description: _t("Greater than or equal to."),
|
|
18686
18747
|
args: [
|
|
18687
|
-
arg("value1 (
|
|
18688
|
-
arg("value2 (
|
|
18748
|
+
arg("value1 (number, string, boolean)", _t("The value to test as being greater than or equal to value2.")),
|
|
18749
|
+
arg("value2 (number, string, boolean)", _t("The second value.")),
|
|
18689
18750
|
],
|
|
18690
18751
|
compute: function (value1, value2) {
|
|
18691
18752
|
return applyRelationalOperator(value1, value2, (v1, v2) => {
|
|
@@ -18699,8 +18760,8 @@ const GTE = {
|
|
|
18699
18760
|
const LT = {
|
|
18700
18761
|
description: _t("Less than."),
|
|
18701
18762
|
args: [
|
|
18702
|
-
arg("value1 (
|
|
18703
|
-
arg("value2 (
|
|
18763
|
+
arg("value1 (number, string, boolean)", _t("The value to test as being less than value2.")),
|
|
18764
|
+
arg("value2 (number, string, boolean)", _t("The second value.")),
|
|
18704
18765
|
],
|
|
18705
18766
|
compute: function (value1, value2) {
|
|
18706
18767
|
return !GTE.compute.bind(this)(value1, value2);
|
|
@@ -18712,8 +18773,8 @@ const LT = {
|
|
|
18712
18773
|
const LTE = {
|
|
18713
18774
|
description: _t("Less than or equal to."),
|
|
18714
18775
|
args: [
|
|
18715
|
-
arg("value1 (
|
|
18716
|
-
arg("value2 (
|
|
18776
|
+
arg("value1 (number, string, boolean)", _t("The value to test as being less than or equal to value2.")),
|
|
18777
|
+
arg("value2 (number, string, boolean)", _t("The second value.")),
|
|
18717
18778
|
],
|
|
18718
18779
|
compute: function (value1, value2) {
|
|
18719
18780
|
return !GT.compute.bind(this)(value1, value2);
|
|
@@ -18757,8 +18818,8 @@ const MULTIPLY = {
|
|
|
18757
18818
|
const NE = {
|
|
18758
18819
|
description: _t("Not equal."),
|
|
18759
18820
|
args: [
|
|
18760
|
-
arg("value1 (
|
|
18761
|
-
arg("value2 (
|
|
18821
|
+
arg("value1 (string, number, boolean)", _t("The first value.")),
|
|
18822
|
+
arg("value2 (string, number, boolean)", _t("The value to test against value1 for inequality.")),
|
|
18762
18823
|
],
|
|
18763
18824
|
compute: function (value1, value2) {
|
|
18764
18825
|
return !EQ.compute.bind(this)(value1, value2);
|
|
@@ -19672,6 +19733,16 @@ function createComputeFunction(descr, functionName) {
|
|
|
19672
19733
|
});
|
|
19673
19734
|
}
|
|
19674
19735
|
function errorHandlingCompute(...args) {
|
|
19736
|
+
for (let i = 0; i < args.length; i++) {
|
|
19737
|
+
const arg = args[i];
|
|
19738
|
+
const argDefinition = descr.args[descr.getArgToFocus(i + 1) - 1];
|
|
19739
|
+
// Early exit if the argument is an error and the function does not accept errors
|
|
19740
|
+
// We only check scalar arguments, not matrix arguments for performance reasons.
|
|
19741
|
+
// Casting helpers are responsible for handling errors in matrix arguments.
|
|
19742
|
+
if (!argDefinition.acceptErrors && !isMatrix(arg) && isEvaluationError(arg?.value)) {
|
|
19743
|
+
return arg;
|
|
19744
|
+
}
|
|
19745
|
+
}
|
|
19675
19746
|
try {
|
|
19676
19747
|
return computeFunctionToObject.apply(this, args);
|
|
19677
19748
|
}
|
|
@@ -20611,10 +20682,10 @@ css /* scss */ `
|
|
|
20611
20682
|
}
|
|
20612
20683
|
|
|
20613
20684
|
.fa-stack {
|
|
20614
|
-
|
|
20615
|
-
width:
|
|
20616
|
-
height:
|
|
20617
|
-
line-height:
|
|
20685
|
+
/* reset stack size which is doubled by default */
|
|
20686
|
+
width: ${CLOSE_ICON_RADIUS * 2}px;
|
|
20687
|
+
height: ${CLOSE_ICON_RADIUS * 2}px;
|
|
20688
|
+
line-height: ${CLOSE_ICON_RADIUS * 2}px;
|
|
20618
20689
|
}
|
|
20619
20690
|
|
|
20620
20691
|
.force-open-assistant {
|
|
@@ -27814,17 +27885,15 @@ function interactivePasteFromOS(env, target, clipboardContent, pasteOption) {
|
|
|
27814
27885
|
});
|
|
27815
27886
|
}
|
|
27816
27887
|
catch (error) {
|
|
27817
|
-
const parsedSpreadsheetContent = clipboardContent
|
|
27818
|
-
|
|
27819
|
-
: {};
|
|
27820
|
-
if (parsedSpreadsheetContent.version && parsedSpreadsheetContent.version !== CURRENT_VERSION) {
|
|
27888
|
+
const parsedSpreadsheetContent = clipboardContent.data;
|
|
27889
|
+
if (parsedSpreadsheetContent?.version !== CURRENT_VERSION) {
|
|
27821
27890
|
env.raiseError(_t("An unexpected error occurred while pasting content.\
|
|
27822
27891
|
This is probably due to a spreadsheet version mismatch."));
|
|
27823
27892
|
}
|
|
27824
27893
|
result = env.model.dispatch("PASTE_FROM_OS_CLIPBOARD", {
|
|
27825
27894
|
target,
|
|
27826
27895
|
clipboardContent: {
|
|
27827
|
-
|
|
27896
|
+
text: clipboardContent.text,
|
|
27828
27897
|
},
|
|
27829
27898
|
pasteOption,
|
|
27830
27899
|
});
|
|
@@ -28552,8 +28621,8 @@ function createBarChartRuntime(chart, getters) {
|
|
|
28552
28621
|
const dataset = {
|
|
28553
28622
|
label,
|
|
28554
28623
|
data,
|
|
28555
|
-
borderColor:
|
|
28556
|
-
borderWidth: 1,
|
|
28624
|
+
borderColor: definition.background || BACKGROUND_CHART_COLOR,
|
|
28625
|
+
borderWidth: definition.stacked ? 1 : 0,
|
|
28557
28626
|
backgroundColor: color,
|
|
28558
28627
|
};
|
|
28559
28628
|
config.data.datasets.push(dataset);
|
|
@@ -32652,13 +32721,11 @@ async function paste$1(env, pasteOption) {
|
|
|
32652
32721
|
const osClipboard = await env.clipboard.read();
|
|
32653
32722
|
switch (osClipboard.status) {
|
|
32654
32723
|
case "ok":
|
|
32655
|
-
const
|
|
32656
|
-
const
|
|
32657
|
-
const clipboardId = JSON.parse(osClipboardSpreadsheetContent).clipboardId ??
|
|
32658
|
-
htmlDocument.querySelector("div")?.getAttribute("data-clipboard-id");
|
|
32724
|
+
const clipboardContent = parseOSClipboardContent(osClipboard.content);
|
|
32725
|
+
const clipboardId = clipboardContent.data?.clipboardId;
|
|
32659
32726
|
const target = env.model.getters.getSelectedZones();
|
|
32660
32727
|
if (env.model.getters.getClipboardId() !== clipboardId) {
|
|
32661
|
-
interactivePasteFromOS(env, target,
|
|
32728
|
+
interactivePasteFromOS(env, target, clipboardContent, pasteOption);
|
|
32662
32729
|
}
|
|
32663
32730
|
else {
|
|
32664
32731
|
interactivePaste(env, target, pasteOption);
|
|
@@ -49794,25 +49861,20 @@ class Grid extends owl.Component {
|
|
|
49794
49861
|
if (!clipboardData) {
|
|
49795
49862
|
return;
|
|
49796
49863
|
}
|
|
49797
|
-
const
|
|
49798
|
-
|
|
49799
|
-
|
|
49800
|
-
|
|
49864
|
+
const osClipboard = {
|
|
49865
|
+
content: {
|
|
49866
|
+
[ClipboardMIMEType.PlainText]: clipboardData?.getData(ClipboardMIMEType.PlainText),
|
|
49867
|
+
[ClipboardMIMEType.Html]: clipboardData?.getData(ClipboardMIMEType.Html),
|
|
49868
|
+
},
|
|
49869
|
+
};
|
|
49801
49870
|
const target = this.env.model.getters.getSelectedZones();
|
|
49802
49871
|
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
49803
|
-
const
|
|
49804
|
-
|
|
49872
|
+
const clipboardContent = parseOSClipboardContent(osClipboard.content);
|
|
49873
|
+
const clipboardId = clipboardContent.data?.clipboardId;
|
|
49805
49874
|
if (this.env.model.getters.getClipboardId() === clipboardId) {
|
|
49806
49875
|
interactivePaste(this.env, target);
|
|
49807
49876
|
}
|
|
49808
49877
|
else {
|
|
49809
|
-
const clipboardContent = {
|
|
49810
|
-
[ClipboardMIMEType.PlainText]: clipboardDataTextContent,
|
|
49811
|
-
[ClipboardMIMEType.Html]: clipboardDataHtmlContent,
|
|
49812
|
-
};
|
|
49813
|
-
if (osClipboardSpreadsheetContent !== "{}") {
|
|
49814
|
-
clipboardContent[ClipboardMIMEType.OSpreadsheet] = osClipboardSpreadsheetContent;
|
|
49815
|
-
}
|
|
49816
49878
|
interactivePasteFromOS(this.env, target, clipboardContent);
|
|
49817
49879
|
}
|
|
49818
49880
|
if (isCutOperation) {
|
|
@@ -51695,8 +51757,9 @@ class ConditionalFormatPlugin extends CorePlugin {
|
|
|
51695
51757
|
if (replaceIndex > -1) {
|
|
51696
51758
|
currentRanges = rules[replaceIndex].ranges.map(toUnboundedZone);
|
|
51697
51759
|
}
|
|
51698
|
-
|
|
51699
|
-
|
|
51760
|
+
// Remove the zones first in case the same position is in toAdd and toRemove
|
|
51761
|
+
const withRemovedZones = recomputeZones(currentRanges, toRemove);
|
|
51762
|
+
return recomputeZones([...toAdd, ...withRemovedZones], []).map((zone) => this.getters.getRangeDataFromZone(sheetId, zone));
|
|
51700
51763
|
}
|
|
51701
51764
|
// ---------------------------------------------------------------------------
|
|
51702
51765
|
// Private
|
|
@@ -57290,6 +57353,9 @@ class Evaluator {
|
|
|
57290
57353
|
}
|
|
57291
57354
|
for (let i = 0; i < positions.length; ++i) {
|
|
57292
57355
|
const position = positions[i];
|
|
57356
|
+
if (this.nextPositionsToUpdate.has(position)) {
|
|
57357
|
+
continue;
|
|
57358
|
+
}
|
|
57293
57359
|
const evaluatedCell = this.computeCell(position);
|
|
57294
57360
|
if (evaluatedCell !== EMPTY_CELL) {
|
|
57295
57361
|
this.evaluatedCells.set(position, evaluatedCell);
|
|
@@ -57297,6 +57363,9 @@ class Evaluator {
|
|
|
57297
57363
|
}
|
|
57298
57364
|
onIterationEndEvaluationRegistry.getAll().forEach((callback) => callback(this.getters));
|
|
57299
57365
|
}
|
|
57366
|
+
if (currentIteration >= MAX_ITERATION) {
|
|
57367
|
+
console.warn("Maximum iteration reached while evaluating cells");
|
|
57368
|
+
}
|
|
57300
57369
|
}
|
|
57301
57370
|
computeCell(position) {
|
|
57302
57371
|
const evaluation = this.evaluatedCells.get(position);
|
|
@@ -57331,7 +57400,6 @@ class Evaluator {
|
|
|
57331
57400
|
}
|
|
57332
57401
|
finally {
|
|
57333
57402
|
this.cellsBeingComputed.delete(cellId);
|
|
57334
|
-
this.nextPositionsToUpdate.delete(position);
|
|
57335
57403
|
}
|
|
57336
57404
|
}
|
|
57337
57405
|
computeAndSave(position) {
|
|
@@ -57367,6 +57435,7 @@ class Evaluator {
|
|
|
57367
57435
|
invalidatePositionsDependingOnSpread(sheetId, resultZone) {
|
|
57368
57436
|
// the result matrix is split in 2 zones to exclude the array formula position
|
|
57369
57437
|
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn(excludeTopLeft(resultZone).map((zone) => ({ sheetId, zone })));
|
|
57438
|
+
invalidatedPositions.delete({ sheetId, col: resultZone.left, row: resultZone.top });
|
|
57370
57439
|
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
57371
57440
|
}
|
|
57372
57441
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
@@ -58489,25 +58558,11 @@ class EvaluationDataValidationPlugin extends UIPlugin {
|
|
|
58489
58558
|
}
|
|
58490
58559
|
switch (cmd.type) {
|
|
58491
58560
|
case "ADD_DATA_VALIDATION_RULE":
|
|
58492
|
-
const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
|
|
58493
|
-
if (cmd.rule.criterion.type === "isBoolean") {
|
|
58494
|
-
this.setContentToBooleanCells({ ...cmd.rule, ranges });
|
|
58495
|
-
}
|
|
58496
|
-
delete this.validationResults[cmd.sheetId];
|
|
58497
|
-
break;
|
|
58498
58561
|
case "REMOVE_DATA_VALIDATION_RULE":
|
|
58499
58562
|
delete this.validationResults[cmd.sheetId];
|
|
58500
58563
|
break;
|
|
58501
58564
|
}
|
|
58502
58565
|
}
|
|
58503
|
-
setContentToBooleanCells(rule) {
|
|
58504
|
-
for (const position of getCellPositionsInRanges(rule.ranges)) {
|
|
58505
|
-
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
58506
|
-
if (evaluatedCell.type !== CellValueType.boolean) {
|
|
58507
|
-
this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
|
|
58508
|
-
}
|
|
58509
|
-
}
|
|
58510
|
-
}
|
|
58511
58566
|
isDataValidationInvalid(cellPosition) {
|
|
58512
58567
|
return !this.getValidationResultForCell(cellPosition).isValid;
|
|
58513
58568
|
}
|
|
@@ -60987,7 +61042,7 @@ class Session extends EventBus {
|
|
|
60987
61042
|
* Notify the server that the user client left the collaborative session
|
|
60988
61043
|
*/
|
|
60989
61044
|
async leave(data) {
|
|
60990
|
-
if (Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
|
|
61045
|
+
if (data && Object.keys(this.clients).length === 1 && this.processedRevisions.size) {
|
|
60991
61046
|
await this.snapshot(data());
|
|
60992
61047
|
}
|
|
60993
61048
|
delete this.clients[this.clientId];
|
|
@@ -62542,6 +62597,42 @@ class CellComputedStylePlugin extends UIPlugin {
|
|
|
62542
62597
|
}
|
|
62543
62598
|
}
|
|
62544
62599
|
|
|
62600
|
+
class DataValidationInsertionPlugin extends UIPlugin {
|
|
62601
|
+
handle(cmd) {
|
|
62602
|
+
switch (cmd.type) {
|
|
62603
|
+
case "ADD_DATA_VALIDATION_RULE":
|
|
62604
|
+
if (cmd.rule.criterion.type === "isBoolean") {
|
|
62605
|
+
const ranges = cmd.ranges.map((range) => this.getters.getRangeFromRangeData(range));
|
|
62606
|
+
for (const position of getCellPositionsInRanges(ranges)) {
|
|
62607
|
+
const cell = this.getters.getCell(position);
|
|
62608
|
+
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
62609
|
+
if (!cell?.content) {
|
|
62610
|
+
this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
|
|
62611
|
+
// In this case, a cell has been updated in the core plugin but
|
|
62612
|
+
// not yet evaluated. This can occur after a paste operation.
|
|
62613
|
+
}
|
|
62614
|
+
else if (cell?.content && evaluatedCell.type === CellValueType.empty) {
|
|
62615
|
+
let value;
|
|
62616
|
+
if (cell.content.startsWith("=")) {
|
|
62617
|
+
const result = this.getters.evaluateFormula(position.sheetId, cell.content);
|
|
62618
|
+
value = (isMatrix(result) ? result[0][0] : result)?.toString();
|
|
62619
|
+
}
|
|
62620
|
+
else {
|
|
62621
|
+
value = cell.content;
|
|
62622
|
+
}
|
|
62623
|
+
if (!value || !isBoolean(value)) {
|
|
62624
|
+
this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
|
|
62625
|
+
}
|
|
62626
|
+
}
|
|
62627
|
+
else if (evaluatedCell.type !== CellValueType.boolean) {
|
|
62628
|
+
this.dispatch("UPDATE_CELL", { ...position, content: "FALSE" });
|
|
62629
|
+
}
|
|
62630
|
+
}
|
|
62631
|
+
}
|
|
62632
|
+
}
|
|
62633
|
+
}
|
|
62634
|
+
}
|
|
62635
|
+
|
|
62545
62636
|
const genericRepeatsTransforms = [
|
|
62546
62637
|
repeatSheetDependantCommand,
|
|
62547
62638
|
repeatTargetDependantCommand,
|
|
@@ -63195,7 +63286,7 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
63195
63286
|
const zones = this.getters.getSelectedZones();
|
|
63196
63287
|
return this.isCutAllowedOn(zones);
|
|
63197
63288
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
63198
|
-
const copiedData = this.
|
|
63289
|
+
const copiedData = this.convertTextToClipboardData(cmd.clipboardContent.text ?? "");
|
|
63199
63290
|
const pasteOption = cmd.pasteOption;
|
|
63200
63291
|
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption, isCutOperation: false });
|
|
63201
63292
|
}
|
|
@@ -63248,12 +63339,9 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
63248
63339
|
break;
|
|
63249
63340
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
63250
63341
|
this._isCutOperation = false;
|
|
63251
|
-
|
|
63252
|
-
|
|
63253
|
-
|
|
63254
|
-
else {
|
|
63255
|
-
this.copiedData = this.convertOSClipboardData(cmd.clipboardContent[ClipboardMIMEType.PlainText] ?? "");
|
|
63256
|
-
}
|
|
63342
|
+
this.copiedData =
|
|
63343
|
+
cmd.clipboardContent.data ||
|
|
63344
|
+
this.convertTextToClipboardData(cmd.clipboardContent.text ?? "");
|
|
63257
63345
|
const pasteOption = cmd.pasteOption;
|
|
63258
63346
|
this.paste(cmd.target, this.copiedData, {
|
|
63259
63347
|
pasteOption,
|
|
@@ -63384,11 +63472,11 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
63384
63472
|
}
|
|
63385
63473
|
}
|
|
63386
63474
|
}
|
|
63387
|
-
|
|
63475
|
+
convertTextToClipboardData(clipboardData) {
|
|
63388
63476
|
const handlers = this.selectClipboardHandlers({ figureId: true }).concat(this.selectClipboardHandlers({}));
|
|
63389
63477
|
let copiedData = {};
|
|
63390
63478
|
for (const { handlerName, handler } of handlers) {
|
|
63391
|
-
const data = handler.
|
|
63479
|
+
const data = handler.convertTextToClipboardData(clipboardData);
|
|
63392
63480
|
copiedData[handlerName] = data;
|
|
63393
63481
|
const minimalKeys = ["sheetId", "cells", "zones", "figureId"];
|
|
63394
63482
|
for (const key of minimalKeys) {
|
|
@@ -63557,21 +63645,20 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
63557
63645
|
return {
|
|
63558
63646
|
[ClipboardMIMEType.PlainText]: this.getPlainTextContent(),
|
|
63559
63647
|
[ClipboardMIMEType.Html]: this.getHTMLContent(),
|
|
63560
|
-
[ClipboardMIMEType.OSpreadsheet]: this.getSerializedGridData(),
|
|
63561
63648
|
};
|
|
63562
63649
|
}
|
|
63563
|
-
|
|
63650
|
+
getSheetData() {
|
|
63564
63651
|
const data = {
|
|
63565
63652
|
version: CURRENT_VERSION,
|
|
63566
63653
|
clipboardId: this.clipboardId,
|
|
63567
63654
|
};
|
|
63568
63655
|
if (this.copiedData && "figureId" in this.copiedData) {
|
|
63569
|
-
return
|
|
63656
|
+
return data;
|
|
63570
63657
|
}
|
|
63571
|
-
return
|
|
63658
|
+
return {
|
|
63572
63659
|
...data,
|
|
63573
63660
|
...this.copiedData,
|
|
63574
|
-
}
|
|
63661
|
+
};
|
|
63575
63662
|
}
|
|
63576
63663
|
getPlainTextContent() {
|
|
63577
63664
|
if (!this.copiedData?.cells) {
|
|
@@ -63588,31 +63675,36 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
63588
63675
|
.join("\n") || "\t");
|
|
63589
63676
|
}
|
|
63590
63677
|
getHTMLContent() {
|
|
63591
|
-
|
|
63592
|
-
|
|
63678
|
+
let innerHTML = "";
|
|
63679
|
+
const cells = this.copiedData?.cells;
|
|
63680
|
+
if (!cells) {
|
|
63681
|
+
innerHTML = "\t";
|
|
63593
63682
|
}
|
|
63594
|
-
|
|
63595
|
-
|
|
63596
|
-
return `<div data-clipboard-id="${this.clipboardId}">${this.getters.getCellText(cells[0][0].position)}</div>`;
|
|
63683
|
+
else if (cells.length === 1 && cells[0].length === 1) {
|
|
63684
|
+
innerHTML = `${this.getters.getCellText(cells[0][0].position)}`;
|
|
63597
63685
|
}
|
|
63598
|
-
if (!cells[0][0]) {
|
|
63686
|
+
else if (!cells[0][0]) {
|
|
63599
63687
|
return "";
|
|
63600
63688
|
}
|
|
63601
|
-
|
|
63602
|
-
|
|
63603
|
-
|
|
63604
|
-
|
|
63605
|
-
|
|
63606
|
-
|
|
63689
|
+
else {
|
|
63690
|
+
let htmlTable = `<table border="1" style="border-collapse:collapse">`;
|
|
63691
|
+
for (const row of cells) {
|
|
63692
|
+
htmlTable += "<tr>";
|
|
63693
|
+
for (const cell of row) {
|
|
63694
|
+
if (!cell) {
|
|
63695
|
+
continue;
|
|
63696
|
+
}
|
|
63697
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
63698
|
+
const cellText = this.getters.getCellText(cell.position);
|
|
63699
|
+
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
63607
63700
|
}
|
|
63608
|
-
|
|
63609
|
-
const cellText = this.getters.getCellText(cell.position);
|
|
63610
|
-
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
63701
|
+
htmlTable += "</tr>";
|
|
63611
63702
|
}
|
|
63612
|
-
htmlTable += "</
|
|
63703
|
+
htmlTable += "</table>";
|
|
63704
|
+
innerHTML = htmlTable;
|
|
63613
63705
|
}
|
|
63614
|
-
|
|
63615
|
-
return
|
|
63706
|
+
const serializedData = JSON.stringify(this.getSheetData());
|
|
63707
|
+
return `<div data-osheet-clipboard='${xmlEscape(serializedData)}'>${innerHTML}</div>`;
|
|
63616
63708
|
}
|
|
63617
63709
|
isCutOperation() {
|
|
63618
63710
|
return this._isCutOperation ?? false;
|
|
@@ -65599,7 +65691,8 @@ const featurePluginRegistry = new Registry()
|
|
|
65599
65691
|
.add("history", HistoryPlugin)
|
|
65600
65692
|
.add("data_cleanup", DataCleanupPlugin)
|
|
65601
65693
|
.add("table_autofill", TableAutofillPlugin)
|
|
65602
|
-
.add("table_ui_resize", TableResizeUI)
|
|
65694
|
+
.add("table_ui_resize", TableResizeUI)
|
|
65695
|
+
.add("datavalidation_insert", DataValidationInsertionPlugin);
|
|
65603
65696
|
// Plugins which have a state, but which should not be shared in collaborative
|
|
65604
65697
|
const statefulUIPluginRegistry = new Registry()
|
|
65605
65698
|
.add("selection", GridSelectionPlugin)
|
|
@@ -67859,10 +67952,6 @@ class WebClipboardWrapper {
|
|
|
67859
67952
|
[ClipboardMIMEType.PlainText]: this.getBlob(content, ClipboardMIMEType.PlainText),
|
|
67860
67953
|
[ClipboardMIMEType.Html]: this.getBlob(content, ClipboardMIMEType.Html),
|
|
67861
67954
|
};
|
|
67862
|
-
const spreadsheetData = content[ClipboardMIMEType.OSpreadsheet];
|
|
67863
|
-
if (spreadsheetData) {
|
|
67864
|
-
clipboardItemData[ClipboardMIMEType.OSpreadsheet] = this.getBlob(content, ClipboardMIMEType.OSpreadsheet);
|
|
67865
|
-
}
|
|
67866
67955
|
return [new ClipboardItem(clipboardItemData)];
|
|
67867
67956
|
}
|
|
67868
67957
|
getBlob(clipboardContent, type) {
|
|
@@ -71866,7 +71955,8 @@ class Model extends EventBus {
|
|
|
71866
71955
|
this.session.join(this.config.client);
|
|
71867
71956
|
}
|
|
71868
71957
|
async leaveSession() {
|
|
71869
|
-
|
|
71958
|
+
const snapshot = this.getters.isReadonly() ? undefined : lazy(() => this.exportData());
|
|
71959
|
+
await this.session.leave(snapshot);
|
|
71870
71960
|
}
|
|
71871
71961
|
setupUiPlugin(Plugin) {
|
|
71872
71962
|
const plugin = new Plugin(this.uiPluginConfig);
|
|
@@ -72480,6 +72570,6 @@ exports.tokenColors = tokenColors;
|
|
|
72480
72570
|
exports.tokenize = tokenize;
|
|
72481
72571
|
|
|
72482
72572
|
|
|
72483
|
-
__info__.version = "18.0.
|
|
72484
|
-
__info__.date = "2024-11-
|
|
72485
|
-
__info__.hash = "
|
|
72573
|
+
__info__.version = "18.0.5";
|
|
72574
|
+
__info__.date = "2024-11-22T14:19:19.721Z";
|
|
72575
|
+
__info__.hash = "9eb34d9";
|