@odoo/o-spreadsheet 17.4.7 → 17.4.9
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 +225 -160
- package/dist/o-spreadsheet.d.ts +6 -0
- package/dist/o-spreadsheet.esm.js +225 -160
- package/dist/o-spreadsheet.iife.js +225 -160
- package/dist/o-spreadsheet.iife.min.js +265 -265
- package/dist/o_spreadsheet.xml +3 -3
- package/package.json +2 -2
|
@@ -2,14 +2,119 @@
|
|
|
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 17.4.
|
|
6
|
-
* @date 2024-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.4.9
|
|
6
|
+
* @date 2024-10-14T07:53:51.633Z
|
|
7
|
+
* @hash b7015b7
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
+
function createActions(menuItems) {
|
|
14
|
+
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
15
|
+
}
|
|
16
|
+
let nextItemId = 1;
|
|
17
|
+
function createAction(item) {
|
|
18
|
+
const name = item.name;
|
|
19
|
+
const children = item.children;
|
|
20
|
+
const description = item.description;
|
|
21
|
+
const icon = item.icon;
|
|
22
|
+
const secondaryIcon = item.secondaryIcon;
|
|
23
|
+
const itemId = item.id || nextItemId++;
|
|
24
|
+
return {
|
|
25
|
+
id: itemId.toString(),
|
|
26
|
+
name: typeof name === "function" ? name : () => name,
|
|
27
|
+
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
28
|
+
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
29
|
+
isActive: item.isActive,
|
|
30
|
+
execute: item.execute,
|
|
31
|
+
children: children
|
|
32
|
+
? (env) => {
|
|
33
|
+
return children
|
|
34
|
+
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
35
|
+
.flat()
|
|
36
|
+
.map(createAction);
|
|
37
|
+
}
|
|
38
|
+
: () => [],
|
|
39
|
+
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
40
|
+
separator: item.separator || false,
|
|
41
|
+
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
42
|
+
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
43
|
+
description: typeof description === "function" ? description : () => description || "",
|
|
44
|
+
textColor: item.textColor,
|
|
45
|
+
sequence: item.sequence || 0,
|
|
46
|
+
onStartHover: item.onStartHover,
|
|
47
|
+
onStopHover: item.onStopHover,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Registry
|
|
53
|
+
*
|
|
54
|
+
* The Registry class is basically just a mapping from a string key to an object.
|
|
55
|
+
* It is really not much more than an object. It is however useful for the
|
|
56
|
+
* following reasons:
|
|
57
|
+
*
|
|
58
|
+
* 1. it let us react and execute code when someone add something to the registry
|
|
59
|
+
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
60
|
+
* 2. it throws an error when the get operation fails
|
|
61
|
+
* 3. it provides a chained API to add items to the registry.
|
|
62
|
+
*/
|
|
63
|
+
class Registry {
|
|
64
|
+
content = {};
|
|
65
|
+
/**
|
|
66
|
+
* Add an item to the registry
|
|
67
|
+
*
|
|
68
|
+
* Note that this also returns the registry, so another add method call can
|
|
69
|
+
* be chained
|
|
70
|
+
*/
|
|
71
|
+
add(key, value) {
|
|
72
|
+
this.content[key] = value;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get an item from the registry
|
|
77
|
+
*/
|
|
78
|
+
get(key) {
|
|
79
|
+
/**
|
|
80
|
+
* Note: key in {} is ~12 times slower than {}[key].
|
|
81
|
+
* So, we check the absence of key only when the direct access returns
|
|
82
|
+
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
83
|
+
*/
|
|
84
|
+
const content = this.content[key];
|
|
85
|
+
if (!content) {
|
|
86
|
+
if (!(key in this.content)) {
|
|
87
|
+
throw new Error(`Cannot find ${key} in this registry!`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return content;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if the key is already in the registry
|
|
94
|
+
*/
|
|
95
|
+
contains(key) {
|
|
96
|
+
return key in this.content;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get a list of all elements in the registry
|
|
100
|
+
*/
|
|
101
|
+
getAll() {
|
|
102
|
+
return Object.values(this.content);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get a list of all keys in the registry
|
|
106
|
+
*/
|
|
107
|
+
getKeys() {
|
|
108
|
+
return Object.keys(this.content);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Remove an item from the registry
|
|
112
|
+
*/
|
|
113
|
+
remove(key) {
|
|
114
|
+
delete this.content[key];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
13
118
|
const CANVAS_SHIFT = 0.5;
|
|
14
119
|
// Colors
|
|
15
120
|
const HIGHLIGHT_COLOR = "#37A850";
|
|
@@ -166,7 +271,7 @@
|
|
|
166
271
|
underline: false,
|
|
167
272
|
fontSize: 10,
|
|
168
273
|
fillColor: "",
|
|
169
|
-
textColor: "
|
|
274
|
+
textColor: "",
|
|
170
275
|
};
|
|
171
276
|
const DEFAULT_VERTICAL_ALIGN = DEFAULT_STYLE.verticalAlign;
|
|
172
277
|
const DEFAULT_WRAPPING_MODE = DEFAULT_STYLE.wrapping;
|
|
@@ -5398,110 +5503,6 @@
|
|
|
5398
5503
|
}
|
|
5399
5504
|
}
|
|
5400
5505
|
|
|
5401
|
-
function createActions(menuItems) {
|
|
5402
|
-
return menuItems.map(createAction).sort((a, b) => a.sequence - b.sequence);
|
|
5403
|
-
}
|
|
5404
|
-
const uuidGenerator$1 = new UuidGenerator();
|
|
5405
|
-
function createAction(item) {
|
|
5406
|
-
const name = item.name;
|
|
5407
|
-
const children = item.children;
|
|
5408
|
-
const description = item.description;
|
|
5409
|
-
const icon = item.icon;
|
|
5410
|
-
const secondaryIcon = item.secondaryIcon;
|
|
5411
|
-
return {
|
|
5412
|
-
id: item.id || uuidGenerator$1.uuidv4(),
|
|
5413
|
-
name: typeof name === "function" ? name : () => name,
|
|
5414
|
-
isVisible: item.isVisible ? item.isVisible : () => true,
|
|
5415
|
-
isEnabled: item.isEnabled ? item.isEnabled : () => true,
|
|
5416
|
-
isActive: item.isActive,
|
|
5417
|
-
execute: item.execute,
|
|
5418
|
-
children: children
|
|
5419
|
-
? (env) => {
|
|
5420
|
-
return children
|
|
5421
|
-
.map((child) => (typeof child === "function" ? child(env) : child))
|
|
5422
|
-
.flat()
|
|
5423
|
-
.map(createAction);
|
|
5424
|
-
}
|
|
5425
|
-
: () => [],
|
|
5426
|
-
isReadonlyAllowed: item.isReadonlyAllowed || false,
|
|
5427
|
-
separator: item.separator || false,
|
|
5428
|
-
icon: typeof icon === "function" ? icon : () => icon || "",
|
|
5429
|
-
secondaryIcon: typeof secondaryIcon === "function" ? secondaryIcon : () => secondaryIcon || "",
|
|
5430
|
-
description: typeof description === "function" ? description : () => description || "",
|
|
5431
|
-
textColor: item.textColor,
|
|
5432
|
-
sequence: item.sequence || 0,
|
|
5433
|
-
onStartHover: item.onStartHover,
|
|
5434
|
-
onStopHover: item.onStopHover,
|
|
5435
|
-
};
|
|
5436
|
-
}
|
|
5437
|
-
|
|
5438
|
-
/**
|
|
5439
|
-
* Registry
|
|
5440
|
-
*
|
|
5441
|
-
* The Registry class is basically just a mapping from a string key to an object.
|
|
5442
|
-
* It is really not much more than an object. It is however useful for the
|
|
5443
|
-
* following reasons:
|
|
5444
|
-
*
|
|
5445
|
-
* 1. it let us react and execute code when someone add something to the registry
|
|
5446
|
-
* (for example, the FunctionRegistry subclass this for this purpose)
|
|
5447
|
-
* 2. it throws an error when the get operation fails
|
|
5448
|
-
* 3. it provides a chained API to add items to the registry.
|
|
5449
|
-
*/
|
|
5450
|
-
class Registry {
|
|
5451
|
-
content = {};
|
|
5452
|
-
/**
|
|
5453
|
-
* Add an item to the registry
|
|
5454
|
-
*
|
|
5455
|
-
* Note that this also returns the registry, so another add method call can
|
|
5456
|
-
* be chained
|
|
5457
|
-
*/
|
|
5458
|
-
add(key, value) {
|
|
5459
|
-
this.content[key] = value;
|
|
5460
|
-
return this;
|
|
5461
|
-
}
|
|
5462
|
-
/**
|
|
5463
|
-
* Get an item from the registry
|
|
5464
|
-
*/
|
|
5465
|
-
get(key) {
|
|
5466
|
-
/**
|
|
5467
|
-
* Note: key in {} is ~12 times slower than {}[key].
|
|
5468
|
-
* So, we check the absence of key only when the direct access returns
|
|
5469
|
-
* a falsy value. It's done to ensure that the registry can contains falsy values
|
|
5470
|
-
*/
|
|
5471
|
-
const content = this.content[key];
|
|
5472
|
-
if (!content) {
|
|
5473
|
-
if (!(key in this.content)) {
|
|
5474
|
-
throw new Error(`Cannot find ${key} in this registry!`);
|
|
5475
|
-
}
|
|
5476
|
-
}
|
|
5477
|
-
return content;
|
|
5478
|
-
}
|
|
5479
|
-
/**
|
|
5480
|
-
* Check if the key is already in the registry
|
|
5481
|
-
*/
|
|
5482
|
-
contains(key) {
|
|
5483
|
-
return key in this.content;
|
|
5484
|
-
}
|
|
5485
|
-
/**
|
|
5486
|
-
* Get a list of all elements in the registry
|
|
5487
|
-
*/
|
|
5488
|
-
getAll() {
|
|
5489
|
-
return Object.values(this.content);
|
|
5490
|
-
}
|
|
5491
|
-
/**
|
|
5492
|
-
* Get a list of all keys in the registry
|
|
5493
|
-
*/
|
|
5494
|
-
getKeys() {
|
|
5495
|
-
return Object.keys(this.content);
|
|
5496
|
-
}
|
|
5497
|
-
/**
|
|
5498
|
-
* Remove an item from the registry
|
|
5499
|
-
*/
|
|
5500
|
-
remove(key) {
|
|
5501
|
-
delete this.content[key];
|
|
5502
|
-
}
|
|
5503
|
-
}
|
|
5504
|
-
|
|
5505
5506
|
function getClipboardDataPositions(sheetId, zones) {
|
|
5506
5507
|
const lefts = new Set(zones.map((z) => z.left));
|
|
5507
5508
|
const rights = new Set(zones.map((z) => z.right));
|
|
@@ -7280,31 +7281,34 @@
|
|
|
7280
7281
|
for (let col of columnsIndexes) {
|
|
7281
7282
|
const position = { col, row, sheetId };
|
|
7282
7283
|
const table = this.getters.getTable(position);
|
|
7283
|
-
if (!table
|
|
7284
|
+
if (!table) {
|
|
7284
7285
|
tableCellsInRow.push({});
|
|
7285
7286
|
continue;
|
|
7286
7287
|
}
|
|
7287
7288
|
const coreTable = this.getters.getCoreTable(position);
|
|
7288
7289
|
const tableZone = coreTable?.range.zone;
|
|
7290
|
+
let copiedTable = undefined;
|
|
7289
7291
|
// Copy whole table
|
|
7290
|
-
if (
|
|
7291
|
-
|
|
7292
|
+
if (!copiedTablesIds.has(table.id) &&
|
|
7293
|
+
coreTable &&
|
|
7294
|
+
tableZone &&
|
|
7295
|
+
zones.some((z) => isZoneInside(tableZone, z))) {
|
|
7296
|
+
copiedTablesIds.add(table.id);
|
|
7292
7297
|
const values = [];
|
|
7293
7298
|
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
7294
7299
|
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
7295
7300
|
}
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
},
|
|
7302
|
-
});
|
|
7303
|
-
}
|
|
7304
|
-
// Copy only style of cell
|
|
7305
|
-
else if (table) {
|
|
7306
|
-
tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
|
|
7301
|
+
copiedTable = {
|
|
7302
|
+
range: coreTable.range,
|
|
7303
|
+
config: coreTable.config,
|
|
7304
|
+
type: coreTable.type,
|
|
7305
|
+
};
|
|
7307
7306
|
}
|
|
7307
|
+
tableCellsInRow.push({
|
|
7308
|
+
table: copiedTable,
|
|
7309
|
+
style: this.getTableStyleToCopy(position),
|
|
7310
|
+
isWholeTableCopied: copiedTablesIds.has(table.id),
|
|
7311
|
+
});
|
|
7308
7312
|
}
|
|
7309
7313
|
}
|
|
7310
7314
|
return {
|
|
@@ -7385,11 +7389,14 @@
|
|
|
7385
7389
|
tableType: tableCell.table.type,
|
|
7386
7390
|
});
|
|
7387
7391
|
}
|
|
7388
|
-
// Do not paste table style if we're inside another table
|
|
7389
7392
|
// We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
|
|
7390
7393
|
// dynamic tables are not yet computed
|
|
7391
|
-
if (
|
|
7392
|
-
|
|
7394
|
+
if (this.getters.getCoreTable(position) || options?.pasteOption === "asValue") {
|
|
7395
|
+
return;
|
|
7396
|
+
}
|
|
7397
|
+
if ((!options?.pasteOption && !tableCell.isWholeTableCopied) ||
|
|
7398
|
+
options?.pasteOption === "onlyFormat") {
|
|
7399
|
+
if (tableCell.style?.style) {
|
|
7393
7400
|
this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
|
|
7394
7401
|
}
|
|
7395
7402
|
if (tableCell.style?.border) {
|
|
@@ -19155,9 +19162,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19155
19162
|
return error;
|
|
19156
19163
|
}
|
|
19157
19164
|
if (!pivot.areDomainArgsFieldsValid(domainArgs)) {
|
|
19165
|
+
const suggestion = _t("Consider using a dynamic pivot formula: %s. Or re-insert the static pivot from the Data menu.", `=PIVOT(${_pivotFormulaId})`);
|
|
19158
19166
|
return {
|
|
19159
19167
|
value: CellErrorType.GenericError,
|
|
19160
|
-
message: _t("Dimensions don't match the pivot definition"),
|
|
19168
|
+
message: _t("Dimensions don't match the pivot definition") + ". " + suggestion,
|
|
19161
19169
|
};
|
|
19162
19170
|
}
|
|
19163
19171
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
@@ -19184,9 +19192,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19184
19192
|
return error;
|
|
19185
19193
|
}
|
|
19186
19194
|
if (!pivot.areDomainArgsFieldsValid(domainArgs)) {
|
|
19195
|
+
const suggestion = _t("Consider using a dynamic pivot formula: %s. Or re-insert the static pivot from the Data menu.", `=PIVOT(${_pivotFormulaId})`);
|
|
19187
19196
|
return {
|
|
19188
19197
|
value: CellErrorType.GenericError,
|
|
19189
|
-
message: _t("Dimensions don't match the pivot definition"),
|
|
19198
|
+
message: _t("Dimensions don't match the pivot definition") + ". " + suggestion,
|
|
19190
19199
|
};
|
|
19191
19200
|
}
|
|
19192
19201
|
const domain = pivot.parseArgsToPivotDomain(domainArgs);
|
|
@@ -22362,6 +22371,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22362
22371
|
// replace the whole token
|
|
22363
22372
|
start = tokenAtCursor.start;
|
|
22364
22373
|
}
|
|
22374
|
+
this.composer.stopComposerRangeSelection();
|
|
22365
22375
|
this.composer.changeComposerCursorSelection(start, end);
|
|
22366
22376
|
this.composer.replaceComposerCursorSelection(value);
|
|
22367
22377
|
}
|
|
@@ -22379,6 +22389,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22379
22389
|
// replace the whole token
|
|
22380
22390
|
start = tokenAtCursor.start;
|
|
22381
22391
|
}
|
|
22392
|
+
this.composer.stopComposerRangeSelection();
|
|
22382
22393
|
this.composer.changeComposerCursorSelection(start, end);
|
|
22383
22394
|
this.composer.replaceComposerCursorSelection(value);
|
|
22384
22395
|
}
|
|
@@ -28409,6 +28420,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28409
28420
|
});
|
|
28410
28421
|
env.model.dispatch("REFRESH_PIVOT", { id: pivotId });
|
|
28411
28422
|
},
|
|
28423
|
+
isVisible: (env) => env.model.getters.getPivot(pivotId).isValid(),
|
|
28412
28424
|
}));
|
|
28413
28425
|
const REINSERT_STATIC_PIVOT_CHILDREN = (env) => env.model.getters.getPivotIds().map((pivotId, index) => ({
|
|
28414
28426
|
id: `reinsert_static_pivot_${env.model.getters.getPivotFormulaId(pivotId)}`,
|
|
@@ -28427,6 +28439,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28427
28439
|
});
|
|
28428
28440
|
env.model.dispatch("REFRESH_PIVOT", { id: pivotId });
|
|
28429
28441
|
},
|
|
28442
|
+
isVisible: (env) => env.model.getters.getPivot(pivotId).isValid(),
|
|
28430
28443
|
}));
|
|
28431
28444
|
//------------------------------------------------------------------------------
|
|
28432
28445
|
// Image
|
|
@@ -29298,7 +29311,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29298
29311
|
sequence: 1020,
|
|
29299
29312
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
29300
29313
|
children: [REINSERT_DYNAMIC_PIVOT_CHILDREN],
|
|
29301
|
-
isVisible: (env) => env.model.getters.getPivotIds().
|
|
29314
|
+
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
29302
29315
|
};
|
|
29303
29316
|
const reinsertStaticPivotMenu = {
|
|
29304
29317
|
id: "reinsert_static_pivot",
|
|
@@ -29306,7 +29319,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29306
29319
|
sequence: 1020,
|
|
29307
29320
|
icon: "o-spreadsheet-Icon.INSERT_PIVOT",
|
|
29308
29321
|
children: [REINSERT_STATIC_PIVOT_CHILDREN],
|
|
29309
|
-
isVisible: (env) => env.model.getters.getPivotIds().
|
|
29322
|
+
isVisible: (env) => env.model.getters.getPivotIds().some((id) => env.model.getters.getPivot(id).isValid()),
|
|
29310
29323
|
};
|
|
29311
29324
|
|
|
29312
29325
|
var ACTION_DATA = /*#__PURE__*/Object.freeze({
|
|
@@ -37192,6 +37205,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37192
37205
|
mutators = ["reset", "deferUpdates", "applyUpdate", "discardPendingUpdate", "update"];
|
|
37193
37206
|
updatesAreDeferred = false;
|
|
37194
37207
|
draft = null;
|
|
37208
|
+
notification = this.get(NotificationStore);
|
|
37209
|
+
alreadyNotified = false;
|
|
37195
37210
|
constructor(get, pivotId) {
|
|
37196
37211
|
super(get);
|
|
37197
37212
|
this.pivotId = pivotId;
|
|
@@ -37298,6 +37313,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37298
37313
|
pivot: this.draft,
|
|
37299
37314
|
});
|
|
37300
37315
|
this.draft = null;
|
|
37316
|
+
if (!this.alreadyNotified && !this.isDynamicPivotInViewport()) {
|
|
37317
|
+
const formulaId = this.getters.getPivotFormulaId(this.pivotId);
|
|
37318
|
+
const pivotExample = `=PIVOT(${formulaId})`;
|
|
37319
|
+
this.alreadyNotified = true;
|
|
37320
|
+
this.notification.notifyUser({
|
|
37321
|
+
type: "info",
|
|
37322
|
+
text: _t("Pivot updates only work with dynamic pivot tables. Use %s or re-insert the static pivot from the Data menu.", pivotExample),
|
|
37323
|
+
sticky: false,
|
|
37324
|
+
});
|
|
37325
|
+
}
|
|
37301
37326
|
}
|
|
37302
37327
|
}
|
|
37303
37328
|
discardPendingUpdate() {
|
|
@@ -37328,15 +37353,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
37328
37353
|
return;
|
|
37329
37354
|
}
|
|
37330
37355
|
const cleanedWithGranularity = this.addDefaultDateTimeGranularity(this.fields, cleanedDefinition);
|
|
37331
|
-
|
|
37332
|
-
|
|
37356
|
+
this.draft = cleanedWithGranularity;
|
|
37357
|
+
if (!this.updatesAreDeferred) {
|
|
37358
|
+
this.applyUpdate();
|
|
37333
37359
|
}
|
|
37334
|
-
|
|
37335
|
-
|
|
37336
|
-
|
|
37337
|
-
|
|
37338
|
-
|
|
37360
|
+
}
|
|
37361
|
+
isDynamicPivotInViewport() {
|
|
37362
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
37363
|
+
for (const col of this.getters.getSheetViewVisibleCols()) {
|
|
37364
|
+
for (const row of this.getters.getSheetViewVisibleRows()) {
|
|
37365
|
+
const isDynamicPivot = this.getters.isSpillPivotFormula({ sheetId, col, row });
|
|
37366
|
+
if (isDynamicPivot) {
|
|
37367
|
+
return true;
|
|
37368
|
+
}
|
|
37369
|
+
}
|
|
37339
37370
|
}
|
|
37371
|
+
return false;
|
|
37340
37372
|
}
|
|
37341
37373
|
addDefaultDateTimeGranularity(fields, definition) {
|
|
37342
37374
|
const { columns, rows } = definition;
|
|
@@ -52427,7 +52459,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52427
52459
|
case "DUPLICATE_PIVOT": {
|
|
52428
52460
|
const { pivotId, newPivotId } = cmd;
|
|
52429
52461
|
const pivot = deepCopy(this.getPivotCore(pivotId).definition);
|
|
52430
|
-
pivot.name =
|
|
52462
|
+
pivot.name = cmd.duplicatedPivotName ?? pivot.name + " (copy)";
|
|
52431
52463
|
this.addPivot(newPivotId, pivot);
|
|
52432
52464
|
break;
|
|
52433
52465
|
}
|
|
@@ -57516,6 +57548,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57516
57548
|
case "REMOTE_REVISION":
|
|
57517
57549
|
case "REVISION_REDONE":
|
|
57518
57550
|
case "REVISION_UNDONE":
|
|
57551
|
+
case "SNAPSHOT_CREATED":
|
|
57519
57552
|
return this.processedRevisions.has(message.nextRevisionId);
|
|
57520
57553
|
default:
|
|
57521
57554
|
return false;
|
|
@@ -58031,12 +58064,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58031
58064
|
this.dispatch("DUPLICATE_PIVOT", {
|
|
58032
58065
|
pivotId,
|
|
58033
58066
|
newPivotId,
|
|
58067
|
+
duplicatedPivotName: _t("%s (copy)", this.getters.getPivotCoreDefinition(pivotId).name),
|
|
58034
58068
|
});
|
|
58035
58069
|
const activeSheetId = this.getters.getActiveSheetId();
|
|
58036
58070
|
const position = this.getters.getSheetIds().indexOf(activeSheetId) + 1;
|
|
58037
58071
|
const formulaId = this.getters.getPivotFormulaId(newPivotId);
|
|
58038
58072
|
const newPivotName = this.getters.getPivotName(newPivotId);
|
|
58039
|
-
this.dispatch("CREATE_SHEET", {
|
|
58073
|
+
const result = this.dispatch("CREATE_SHEET", {
|
|
58040
58074
|
sheetId: newSheetId,
|
|
58041
58075
|
name: this.getPivotDuplicateSheetName(_t("%(newPivotName)s (Pivot #%(formulaId)s)", {
|
|
58042
58076
|
newPivotName,
|
|
@@ -58044,20 +58078,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58044
58078
|
})),
|
|
58045
58079
|
position,
|
|
58046
58080
|
});
|
|
58047
|
-
|
|
58048
|
-
|
|
58049
|
-
|
|
58050
|
-
|
|
58051
|
-
|
|
58052
|
-
|
|
58053
|
-
|
|
58081
|
+
if (result.isSuccessful) {
|
|
58082
|
+
this.dispatch("ACTIVATE_SHEET", { sheetIdFrom: activeSheetId, sheetIdTo: newSheetId });
|
|
58083
|
+
this.dispatch("UPDATE_CELL", {
|
|
58084
|
+
sheetId: newSheetId,
|
|
58085
|
+
col: 0,
|
|
58086
|
+
row: 0,
|
|
58087
|
+
content: `=PIVOT(${formulaId})`,
|
|
58088
|
+
});
|
|
58089
|
+
}
|
|
58054
58090
|
}
|
|
58055
58091
|
getPivotDuplicateSheetName(pivotName) {
|
|
58056
58092
|
let i = 1;
|
|
58057
58093
|
const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
|
|
58058
|
-
|
|
58094
|
+
const sanitizedName = pivotName.replace(new RegExp(FORBIDDEN_IN_EXCEL_REGEX, "g"), " ");
|
|
58095
|
+
let name = sanitizedName;
|
|
58059
58096
|
while (names.includes(name)) {
|
|
58060
|
-
name = `${
|
|
58097
|
+
name = `${sanitizedName} (${i})`;
|
|
58061
58098
|
i++;
|
|
58062
58099
|
}
|
|
58063
58100
|
return name;
|
|
@@ -58638,9 +58675,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58638
58675
|
"HIDE_COLUMNS_ROWS",
|
|
58639
58676
|
"UNHIDE_COLUMNS_ROWS",
|
|
58640
58677
|
"UNFOLD_HEADER_GROUP",
|
|
58678
|
+
"UNGROUP_HEADERS",
|
|
58641
58679
|
"FOLD_HEADER_GROUP",
|
|
58642
58680
|
"FOLD_ALL_HEADER_GROUPS",
|
|
58643
58681
|
"UNFOLD_ALL_HEADER_GROUPS",
|
|
58682
|
+
"FOLD_HEADER_GROUPS_IN_ZONE",
|
|
58683
|
+
"UNFOLD_HEADER_GROUPS_IN_ZONE",
|
|
58644
58684
|
"CREATE_TABLE",
|
|
58645
58685
|
"UPDATE_TABLE",
|
|
58646
58686
|
"UPDATE_FILTER",
|
|
@@ -58661,6 +58701,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58661
58701
|
handle(cmd) {
|
|
58662
58702
|
if (invalidateEvaluationCommands.has(cmd.type) ||
|
|
58663
58703
|
cmd.type === "UPDATE_CELL" ||
|
|
58704
|
+
cmd.type === "SET_FORMATTING" ||
|
|
58664
58705
|
cmd.type === "EVALUATE_CELLS") {
|
|
58665
58706
|
this.styles = {};
|
|
58666
58707
|
this.borders = {};
|
|
@@ -59955,6 +59996,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59955
59996
|
case "UNFOLD_HEADER_GROUP":
|
|
59956
59997
|
case "FOLD_ALL_HEADER_GROUPS":
|
|
59957
59998
|
case "UNFOLD_ALL_HEADER_GROUPS":
|
|
59999
|
+
case "FOLD_HEADER_GROUPS_IN_ZONE":
|
|
60000
|
+
case "UNFOLD_HEADER_GROUPS_IN_ZONE":
|
|
59958
60001
|
this.updateHiddenRows(cmd.sheetId);
|
|
59959
60002
|
break;
|
|
59960
60003
|
case "UPDATE_FILTER":
|
|
@@ -65901,7 +65944,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65901
65944
|
* The value does not matter, it can be hardcoded.
|
|
65902
65945
|
*/
|
|
65903
65946
|
const catAxId = 17781237;
|
|
65947
|
+
const secondaryCatAxId = 17781238;
|
|
65904
65948
|
const valAxId = 88853993;
|
|
65949
|
+
const secondaryValAxId = 88853994;
|
|
65905
65950
|
function createChart(chart, chartSheetIndex, data) {
|
|
65906
65951
|
const namespaces = [
|
|
65907
65952
|
["xmlns:r", RELATIONSHIP_NSR],
|
|
@@ -66217,8 +66262,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66217
66262
|
<!-- each data marker in the series does not have a different color -->
|
|
66218
66263
|
<c:varyColors val="0"/>
|
|
66219
66264
|
${barDataSetNode}
|
|
66220
|
-
<c:axId val="${
|
|
66221
|
-
<c:axId val="${
|
|
66265
|
+
<c:axId val="${useRightAxisForBarSerie ? secondaryCatAxId : catAxId}" />
|
|
66266
|
+
<c:axId val="${useRightAxisForBarSerie ? secondaryValAxId : valAxId}" />
|
|
66222
66267
|
</c:barChart>
|
|
66223
66268
|
${leftDataSetsNodes.length
|
|
66224
66269
|
? escapeXml /*xml*/ `
|
|
@@ -66239,21 +66284,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
66239
66284
|
<!-- each data marker in the series does not have a different color -->
|
|
66240
66285
|
<c:varyColors val="0"/>
|
|
66241
66286
|
${joinXmlNodes(rightDataSetsNodes)}
|
|
66242
|
-
<c:axId val="${
|
|
66243
|
-
<c:axId val="${
|
|
66287
|
+
<c:axId val="${secondaryCatAxId}" />
|
|
66288
|
+
<c:axId val="${secondaryValAxId}" />
|
|
66244
66289
|
</c:lineChart>
|
|
66245
66290
|
`
|
|
66246
66291
|
: ""}
|
|
66247
66292
|
${!useRightAxisForBarSerie || leftDataSetsNodes.length
|
|
66248
66293
|
? escapeXml /*xml*/ `
|
|
66249
|
-
${addAx("b", "c:catAx", catAxId
|
|
66250
|
-
${addAx("
|
|
66294
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
66295
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
66251
66296
|
`
|
|
66252
66297
|
: ""}
|
|
66253
66298
|
${useRightAxisForBarSerie || rightDataSetsNodes.length
|
|
66254
66299
|
? escapeXml /*xml*/ `
|
|
66255
|
-
${addAx("b", "c:catAx",
|
|
66256
|
-
${addAx("
|
|
66300
|
+
${addAx("b", "c:catAx", secondaryCatAxId, secondaryValAxId, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length || !useRightAxisForBarSerie ? 1 : 0)}
|
|
66301
|
+
${addAx("r", "c:valAx", secondaryValAxId, secondaryCatAxId, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
66257
66302
|
`
|
|
66258
66303
|
: ""}
|
|
66259
66304
|
`;
|
|
@@ -67274,6 +67319,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67274
67319
|
["id", i + 1], // id cannot be 0
|
|
67275
67320
|
["name", colName],
|
|
67276
67321
|
];
|
|
67322
|
+
if (table.config.totalRow) {
|
|
67323
|
+
// Note: To be 100% complete, we could also add a `totalsRowLabel` attribute for total strings, and a tag
|
|
67324
|
+
// `<totalsRowFormula>` for the formula of the total. But those doesn't seem to be mandatory for Excel.
|
|
67325
|
+
const colTotalXc = toXC(tableZone.left + i, tableZone.bottom);
|
|
67326
|
+
const colTotalContent = sheetData.cells[colTotalXc]?.content;
|
|
67327
|
+
if (colTotalContent?.startsWith("=")) {
|
|
67328
|
+
colAttributes.push(["totalsRowFunction", "custom"]);
|
|
67329
|
+
}
|
|
67330
|
+
}
|
|
67277
67331
|
columns.push(escapeXml /*xml*/ `<tableColumn ${formatAttributes(colAttributes)}/>`);
|
|
67278
67332
|
}
|
|
67279
67333
|
return escapeXml /*xml*/ `
|
|
@@ -67368,8 +67422,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67368
67422
|
}
|
|
67369
67423
|
else if (cell.content && cell.content !== "") {
|
|
67370
67424
|
const isTableHeader = isCellTableHeader(c, r, sheet);
|
|
67425
|
+
const isTableTotal = isCellTableTotal(c, r, sheet);
|
|
67371
67426
|
const isPlainText = !!(cell.format && data.formats[cell.format] === PLAIN_TEXT_FORMAT);
|
|
67372
|
-
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isPlainText));
|
|
67427
|
+
({ attrs: additionalAttrs, node: cellNode } = addContent(cell.content, construct.sharedStrings, isTableHeader || isTableTotal || isPlainText));
|
|
67373
67428
|
}
|
|
67374
67429
|
attributes.push(...additionalAttrs);
|
|
67375
67430
|
// prettier-ignore
|
|
@@ -67403,6 +67458,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67403
67458
|
return isInside(col, row, headerZone);
|
|
67404
67459
|
});
|
|
67405
67460
|
}
|
|
67461
|
+
function isCellTableTotal(col, row, sheet) {
|
|
67462
|
+
return sheet.tables.some((table) => {
|
|
67463
|
+
if (!table.config.totalRow) {
|
|
67464
|
+
return false;
|
|
67465
|
+
}
|
|
67466
|
+
const zone = toZone(table.range);
|
|
67467
|
+
const totalZone = { ...zone, top: zone.bottom };
|
|
67468
|
+
return isInside(col, row, totalZone);
|
|
67469
|
+
});
|
|
67470
|
+
}
|
|
67406
67471
|
function addHyperlinks(construct, data, sheetIndex) {
|
|
67407
67472
|
const sheet = data.sheets[sheetIndex];
|
|
67408
67473
|
const cells = sheet.cells;
|
|
@@ -67881,7 +67946,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67881
67946
|
isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
|
|
67882
67947
|
isDashboard: () => this.config.mode === "dashboard",
|
|
67883
67948
|
};
|
|
67884
|
-
this.uuidGenerator.setIsFastStrategy(true);
|
|
67885
67949
|
// Initiate stream processor
|
|
67886
67950
|
this.selection = new SelectionStreamProcessorImpl(this.getters);
|
|
67887
67951
|
this.coreHandlers.push(this.range);
|
|
@@ -68414,6 +68478,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68414
68478
|
UNDO_REDO_PIVOT_COMMANDS,
|
|
68415
68479
|
createPivotFormula,
|
|
68416
68480
|
areDomainArgsFieldsValid,
|
|
68481
|
+
formatTickValue,
|
|
68417
68482
|
};
|
|
68418
68483
|
const links = {
|
|
68419
68484
|
isMarkdownLink,
|
|
@@ -68544,9 +68609,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
68544
68609
|
exports.tokenize = tokenize;
|
|
68545
68610
|
|
|
68546
68611
|
|
|
68547
|
-
__info__.version = "17.4.
|
|
68548
|
-
__info__.date = "2024-
|
|
68549
|
-
__info__.hash = "
|
|
68612
|
+
__info__.version = "17.4.9";
|
|
68613
|
+
__info__.date = "2024-10-14T07:53:51.633Z";
|
|
68614
|
+
__info__.hash = "b7015b7";
|
|
68550
68615
|
|
|
68551
68616
|
|
|
68552
68617
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|