@odoo/o-spreadsheet 17.2.1 → 17.3.0-alpha.1
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 +461 -174
- package/dist/o-spreadsheet.d.ts +58 -20
- package/dist/o-spreadsheet.esm.js +461 -174
- package/dist/o-spreadsheet.iife.js +461 -174
- package/dist/o-spreadsheet.iife.min.js +269 -264
- package/dist/o_spreadsheet.xml +28 -6
- package/package.json +2 -2
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.
|
|
7
|
-
* @date 2024-03-25T09:
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.3.0-alpha.1
|
|
7
|
+
* @date 2024-03-25T09:43:36.072Z
|
|
8
|
+
* @hash 4095c41
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { reactive, useEnv, useSubEnv, useState, onWillUnmount, markRaw, toRaw, Component, useRef, onMounted, useEffect, onPatched, useComponent, onWillPatch, onWillUpdateProps, useExternalListener, onWillStart, xml, useChildSubEnv } from '@odoo/owl';
|
|
@@ -4201,6 +4201,10 @@ function organizeZone(zone) {
|
|
|
4201
4201
|
function positionToZone(position) {
|
|
4202
4202
|
return { left: position.col, right: position.col, top: position.row, bottom: position.row };
|
|
4203
4203
|
}
|
|
4204
|
+
/** Transform a zone into a zone with only its top-left position */
|
|
4205
|
+
function zoneToTopLeft(zone) {
|
|
4206
|
+
return { ...zone, right: zone.left, bottom: zone.top };
|
|
4207
|
+
}
|
|
4204
4208
|
function isFullRow(zone) {
|
|
4205
4209
|
return zone.right === undefined;
|
|
4206
4210
|
}
|
|
@@ -4240,6 +4244,16 @@ function getZonesRows(zones) {
|
|
|
4240
4244
|
}
|
|
4241
4245
|
return set;
|
|
4242
4246
|
}
|
|
4247
|
+
function unionPositionsToZone(positions) {
|
|
4248
|
+
const zone = { top: Infinity, left: Infinity, bottom: -Infinity, right: -Infinity };
|
|
4249
|
+
for (const { col, row } of positions) {
|
|
4250
|
+
zone.top = Math.min(zone.top, row);
|
|
4251
|
+
zone.left = Math.min(zone.left, col);
|
|
4252
|
+
zone.bottom = Math.max(zone.bottom, row);
|
|
4253
|
+
zone.right = Math.max(zone.right, col);
|
|
4254
|
+
}
|
|
4255
|
+
return zone;
|
|
4256
|
+
}
|
|
4243
4257
|
|
|
4244
4258
|
class RangeImpl {
|
|
4245
4259
|
getSheetSize;
|
|
@@ -5569,7 +5583,7 @@ class CellClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
5569
5583
|
const spreader = this.getters.getArrayFormulaSpreadingOn(position);
|
|
5570
5584
|
let cell = this.getters.getCell(position);
|
|
5571
5585
|
const evaluatedCell = this.getters.getEvaluatedCell(position);
|
|
5572
|
-
if (spreader) {
|
|
5586
|
+
if (spreader && !deepEquals(spreader, position)) {
|
|
5573
5587
|
const isSpreaderCopied = rowsIndexes.includes(spreader.row) && columnsIndexes.includes(spreader.col);
|
|
5574
5588
|
const content = isSpreaderCopied
|
|
5575
5589
|
? ""
|
|
@@ -6216,19 +6230,25 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
6216
6230
|
tableCellsInRow.push({});
|
|
6217
6231
|
continue;
|
|
6218
6232
|
}
|
|
6233
|
+
const coreTable = this.getters.getCoreTable(position);
|
|
6234
|
+
const tableZone = coreTable?.range.zone;
|
|
6219
6235
|
// Copy whole table
|
|
6220
|
-
if (zones.some((z) => isZoneInside(
|
|
6221
|
-
copiedTablesIds.add(
|
|
6236
|
+
if (coreTable && tableZone && zones.some((z) => isZoneInside(tableZone, z))) {
|
|
6237
|
+
copiedTablesIds.add(coreTable.id);
|
|
6222
6238
|
const values = [];
|
|
6223
|
-
for (const col of range(
|
|
6224
|
-
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row:
|
|
6239
|
+
for (const col of range(tableZone.left, tableZone.right + 1)) {
|
|
6240
|
+
values.push(this.getters.getFilterHiddenValues({ sheetId, col, row: tableZone.top }));
|
|
6225
6241
|
}
|
|
6226
6242
|
tableCellsInRow.push({
|
|
6227
|
-
table: {
|
|
6243
|
+
table: {
|
|
6244
|
+
range: coreTable.range,
|
|
6245
|
+
config: coreTable.config,
|
|
6246
|
+
type: coreTable.type,
|
|
6247
|
+
},
|
|
6228
6248
|
});
|
|
6229
6249
|
}
|
|
6230
6250
|
// Copy only style of cell
|
|
6231
|
-
else {
|
|
6251
|
+
else if (table) {
|
|
6232
6252
|
tableCellsInRow.push({ style: this.getTableStyleToCopy(position) });
|
|
6233
6253
|
}
|
|
6234
6254
|
}
|
|
@@ -6299,7 +6319,7 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
6299
6319
|
}
|
|
6300
6320
|
pasteTableCell(sheetId, tableCell, position, options) {
|
|
6301
6321
|
if (tableCell.table && !options?.pasteOption) {
|
|
6302
|
-
const { range: tableRange
|
|
6322
|
+
const { range: tableRange } = tableCell.table;
|
|
6303
6323
|
const zoneDims = zoneToDimension(tableRange.zone);
|
|
6304
6324
|
const newTableZone = {
|
|
6305
6325
|
left: position.col,
|
|
@@ -6311,18 +6331,13 @@ class TableClipboardHandler extends AbstractCellClipboardHandler {
|
|
|
6311
6331
|
sheetId: position.sheetId,
|
|
6312
6332
|
ranges: [this.getters.getRangeDataFromZone(sheetId, newTableZone)],
|
|
6313
6333
|
config: tableCell.table.config,
|
|
6334
|
+
tableType: tableCell.table.type,
|
|
6314
6335
|
});
|
|
6315
|
-
for (const i of range(0, filtersValues.length)) {
|
|
6316
|
-
this.dispatch("UPDATE_FILTER", {
|
|
6317
|
-
sheetId: position.sheetId,
|
|
6318
|
-
col: newTableZone.left + i,
|
|
6319
|
-
row: newTableZone.top,
|
|
6320
|
-
hiddenValues: filtersValues[i],
|
|
6321
|
-
});
|
|
6322
|
-
}
|
|
6323
6336
|
}
|
|
6324
6337
|
// Do not paste table style if we're inside another table
|
|
6325
|
-
|
|
6338
|
+
// We cannot check for dynamic tables, because at this point the paste can have changed the evaluation, and the
|
|
6339
|
+
// dynamic tables are not yet computed
|
|
6340
|
+
if (!this.getters.getCoreTable(position)) {
|
|
6326
6341
|
if (tableCell.style?.style && options?.pasteOption !== "asValue") {
|
|
6327
6342
|
this.dispatch("UPDATE_CELL", { ...position, style: tableCell.style.style });
|
|
6328
6343
|
}
|
|
@@ -7424,9 +7439,11 @@ const TableTerms = {
|
|
|
7424
7439
|
bandedColumns: _t("Banded columns"),
|
|
7425
7440
|
automaticAutofill: _t("Automatically autofill formulas"),
|
|
7426
7441
|
totalRow: _t("Total row"),
|
|
7442
|
+
isDynamic: _t("Auto-adjust to formula result"),
|
|
7427
7443
|
},
|
|
7428
7444
|
Tooltips: {
|
|
7429
7445
|
filterWithoutHeader: _t("Cannot have filters without a header row"),
|
|
7446
|
+
isDynamic: _t("For tables based on array formulas only"),
|
|
7430
7447
|
},
|
|
7431
7448
|
};
|
|
7432
7449
|
|
|
@@ -22227,6 +22244,7 @@ class LinkDisplay extends Component {
|
|
|
22227
22244
|
}
|
|
22228
22245
|
edit() {
|
|
22229
22246
|
const { col, row } = this.props.cellPosition;
|
|
22247
|
+
this.env.model.selection.selectCell(col, row);
|
|
22230
22248
|
this.cellPopovers.open({ col, row }, "LinkEditor");
|
|
22231
22249
|
}
|
|
22232
22250
|
unlink() {
|
|
@@ -23343,13 +23361,20 @@ const TABLE_PRESETS = {
|
|
|
23343
23361
|
* If a single cell is selected, expand the selection to non-empty adjacent cells to create a table.
|
|
23344
23362
|
*/
|
|
23345
23363
|
function interactiveCreateTable(env, sheetId, tableConfig) {
|
|
23346
|
-
|
|
23347
|
-
|
|
23364
|
+
let target = env.model.getters.getSelectedZones();
|
|
23365
|
+
let isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
|
|
23366
|
+
if (target.length === 1 && !isDynamic && getZoneArea(target[0]) === 1) {
|
|
23348
23367
|
env.model.selection.selectTableAroundSelection();
|
|
23368
|
+
target = env.model.getters.getSelectedZones();
|
|
23369
|
+
isDynamic = env.model.getters.canCreateDynamicTableOnZones(sheetId, target);
|
|
23349
23370
|
}
|
|
23350
|
-
const target = env.model.getters.getSelectedZones();
|
|
23351
23371
|
const ranges = target.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
|
|
23352
|
-
const result = env.model.dispatch("CREATE_TABLE", {
|
|
23372
|
+
const result = env.model.dispatch("CREATE_TABLE", {
|
|
23373
|
+
ranges,
|
|
23374
|
+
sheetId,
|
|
23375
|
+
config: tableConfig,
|
|
23376
|
+
tableType: isDynamic ? "dynamic" : "static",
|
|
23377
|
+
});
|
|
23353
23378
|
if (result.isCancelledBecause("TableOverlap" /* CommandResult.TableOverlap */)) {
|
|
23354
23379
|
env.raiseError(TableTerms.Errors.TableOverlap);
|
|
23355
23380
|
}
|
|
@@ -23797,9 +23822,13 @@ const INSERT_TABLE = (env) => {
|
|
|
23797
23822
|
};
|
|
23798
23823
|
const DELETE_SELECTED_TABLE = (env) => {
|
|
23799
23824
|
const position = env.model.getters.getActivePosition();
|
|
23825
|
+
const table = env.model.getters.getTable(position);
|
|
23826
|
+
if (!table) {
|
|
23827
|
+
return;
|
|
23828
|
+
}
|
|
23800
23829
|
env.model.dispatch("REMOVE_TABLE", {
|
|
23801
23830
|
sheetId: position.sheetId,
|
|
23802
|
-
target: [
|
|
23831
|
+
target: [table.range.zone],
|
|
23803
23832
|
});
|
|
23804
23833
|
};
|
|
23805
23834
|
//------------------------------------------------------------------------------
|
|
@@ -30307,6 +30336,24 @@ function getTableContentZone(tableZone, tableConfig) {
|
|
|
30307
30336
|
const contentZone = { ...tableZone, top: tableZone.top + numberOfHeaders };
|
|
30308
30337
|
return contentZone.top <= contentZone.bottom ? contentZone : undefined;
|
|
30309
30338
|
}
|
|
30339
|
+
function getTableTopLeft(table) {
|
|
30340
|
+
const range = table.range;
|
|
30341
|
+
return { row: range.zone.top, col: range.zone.left, sheetId: range.sheetId };
|
|
30342
|
+
}
|
|
30343
|
+
function createFilter(id, range, config, createRange) {
|
|
30344
|
+
const zone = range.zone;
|
|
30345
|
+
if (zone.left !== zone.right) {
|
|
30346
|
+
throw new Error("Can only define a filter on a single column");
|
|
30347
|
+
}
|
|
30348
|
+
const filteredZone = { ...zone, top: zone.top + config.numberOfHeaders };
|
|
30349
|
+
const filteredRange = createRange(range.sheetId, filteredZone);
|
|
30350
|
+
return {
|
|
30351
|
+
id,
|
|
30352
|
+
rangeWithHeaders: range,
|
|
30353
|
+
col: zone.left,
|
|
30354
|
+
filteredRange: filteredZone.top > filteredZone.bottom ? undefined : filteredRange,
|
|
30355
|
+
};
|
|
30356
|
+
}
|
|
30310
30357
|
function getComputedTableStyle(tableConfig, numberOfCols, numberOfRows) {
|
|
30311
30358
|
return {
|
|
30312
30359
|
borders: getAllTableBorders(tableConfig, numberOfCols, numberOfRows),
|
|
@@ -30744,6 +30791,11 @@ css /* scss */ `
|
|
|
30744
30791
|
color: #ffffff;
|
|
30745
30792
|
background: #d94b4b;
|
|
30746
30793
|
}
|
|
30794
|
+
|
|
30795
|
+
.o-info-icon {
|
|
30796
|
+
width: 14px;
|
|
30797
|
+
height: 14px;
|
|
30798
|
+
}
|
|
30747
30799
|
}
|
|
30748
30800
|
`;
|
|
30749
30801
|
class TablePanel extends Component {
|
|
@@ -30775,6 +30827,29 @@ class TablePanel extends Component {
|
|
|
30775
30827
|
const numberOfHeaders = hasHeaders ? 1 : 0;
|
|
30776
30828
|
this.updateNumberOfHeaders(numberOfHeaders);
|
|
30777
30829
|
}
|
|
30830
|
+
updateTableIsDynamic(isDynamic) {
|
|
30831
|
+
const newTableType = isDynamic ? "dynamic" : "forceStatic";
|
|
30832
|
+
if (newTableType === this.props.table.type) {
|
|
30833
|
+
return;
|
|
30834
|
+
}
|
|
30835
|
+
const uiTable = this.env.model.getters.getTable(getTableTopLeft(this.props.table));
|
|
30836
|
+
if (!uiTable) {
|
|
30837
|
+
return;
|
|
30838
|
+
}
|
|
30839
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30840
|
+
const result = this.env.model.dispatch("UPDATE_TABLE", {
|
|
30841
|
+
sheetId,
|
|
30842
|
+
zone: this.props.table.range.zone,
|
|
30843
|
+
newTableRange: uiTable.range.rangeData,
|
|
30844
|
+
tableType: newTableType,
|
|
30845
|
+
});
|
|
30846
|
+
const updatedTable = this.env.model.getters.getCoreTable(getTableTopLeft(this.props.table));
|
|
30847
|
+
if (result.isSuccessful && updatedTable) {
|
|
30848
|
+
const newTableRange = updatedTable.range;
|
|
30849
|
+
this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
|
|
30850
|
+
this.state.tableZoneErrors = [];
|
|
30851
|
+
}
|
|
30852
|
+
}
|
|
30778
30853
|
onChangeNumberOfHeaders(ev) {
|
|
30779
30854
|
const input = ev.target;
|
|
30780
30855
|
const numberOfHeaders = parseInt(input.value);
|
|
@@ -30798,35 +30873,59 @@ class TablePanel extends Component {
|
|
|
30798
30873
|
}
|
|
30799
30874
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30800
30875
|
this.state.tableXc = ranges[0];
|
|
30876
|
+
const newTableRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
|
|
30801
30877
|
this.state.tableZoneErrors = this.env.model.canDispatch("UPDATE_TABLE", {
|
|
30802
30878
|
sheetId,
|
|
30803
30879
|
zone: this.props.table.range.zone,
|
|
30804
30880
|
newTableRange: this.env.model.getters.getRangeDataFromXc(sheetId, this.state.tableXc),
|
|
30881
|
+
tableType: this.getNewTableType(newTableRange.zone),
|
|
30805
30882
|
}).reasons;
|
|
30806
30883
|
}
|
|
30807
30884
|
onRangeConfirmed() {
|
|
30808
30885
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30809
|
-
|
|
30886
|
+
let newRange = this.env.model.getters.getRangeFromSheetXC(sheetId, this.state.tableXc);
|
|
30887
|
+
if (getZoneArea(newRange.zone) === 1) {
|
|
30888
|
+
const extendedZone = this.env.model.getters.getContiguousZone(sheetId, newRange.zone);
|
|
30889
|
+
newRange = this.env.model.getters.getRangeFromZone(sheetId, extendedZone);
|
|
30890
|
+
}
|
|
30810
30891
|
const result = this.env.model.dispatch("UPDATE_TABLE", {
|
|
30811
30892
|
sheetId,
|
|
30812
30893
|
zone: this.props.table.range.zone,
|
|
30813
30894
|
newTableRange: newRange.rangeData,
|
|
30895
|
+
tableType: this.getNewTableType(newRange.zone),
|
|
30814
30896
|
});
|
|
30815
|
-
|
|
30816
|
-
|
|
30897
|
+
const position = { sheetId, col: newRange.zone.left, row: newRange.zone.top };
|
|
30898
|
+
const updatedTable = this.env.model.getters.getCoreTable(position);
|
|
30899
|
+
if (result.isSuccessful && updatedTable) {
|
|
30900
|
+
const newTopLeft = getTableTopLeft(updatedTable);
|
|
30817
30901
|
this.env.model.selection.selectZone({
|
|
30818
|
-
zone: positionToZone(
|
|
30819
|
-
cell:
|
|
30902
|
+
zone: positionToZone(newTopLeft),
|
|
30903
|
+
cell: newTopLeft,
|
|
30820
30904
|
});
|
|
30905
|
+
const newTableRange = updatedTable.range;
|
|
30906
|
+
this.state.tableXc = this.env.model.getters.getRangeString(newTableRange, sheetId);
|
|
30907
|
+
}
|
|
30908
|
+
else {
|
|
30909
|
+
const oldTableRange = this.props.table.range;
|
|
30910
|
+
this.state.tableXc = this.env.model.getters.getRangeString(oldTableRange, sheetId);
|
|
30821
30911
|
}
|
|
30822
30912
|
this.state.tableZoneErrors = [];
|
|
30823
|
-
this.state.tableXc = result.isSuccessful
|
|
30824
|
-
? this.state.tableXc
|
|
30825
|
-
: this.env.model.getters.getRangeString(this.props.table.range, sheetId);
|
|
30826
30913
|
}
|
|
30827
30914
|
deleteTable() {
|
|
30828
30915
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30829
|
-
this.env.model.dispatch("REMOVE_TABLE", {
|
|
30916
|
+
this.env.model.dispatch("REMOVE_TABLE", {
|
|
30917
|
+
sheetId,
|
|
30918
|
+
target: [this.props.table.range.zone],
|
|
30919
|
+
});
|
|
30920
|
+
}
|
|
30921
|
+
getNewTableType(newTableZone) {
|
|
30922
|
+
if (this.props.table.type === "forceStatic") {
|
|
30923
|
+
return "forceStatic";
|
|
30924
|
+
}
|
|
30925
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30926
|
+
return this.env.model.getters.canCreateDynamicTableOnZones(sheetId, [newTableZone])
|
|
30927
|
+
? "dynamic"
|
|
30928
|
+
: "static";
|
|
30830
30929
|
}
|
|
30831
30930
|
get tableConfig() {
|
|
30832
30931
|
return this.props.table.config;
|
|
@@ -30844,6 +30943,14 @@ class TablePanel extends Component {
|
|
|
30844
30943
|
get hasFilterCheckboxTooltip() {
|
|
30845
30944
|
return this.canHaveFilters ? undefined : TableTerms.Tooltips.filterWithoutHeader;
|
|
30846
30945
|
}
|
|
30946
|
+
get canBeDynamic() {
|
|
30947
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
30948
|
+
return (this.props.table.type === "dynamic" ||
|
|
30949
|
+
this.env.model.getters.canCreateDynamicTableOnZones(sheetId, [this.props.table.range.zone]));
|
|
30950
|
+
}
|
|
30951
|
+
get dynamicTableTooltip() {
|
|
30952
|
+
return TableTerms.Tooltips.isDynamic;
|
|
30953
|
+
}
|
|
30847
30954
|
}
|
|
30848
30955
|
|
|
30849
30956
|
const sidePanelRegistry = new Registry();
|
|
@@ -30906,11 +31013,8 @@ sidePanelRegistry.add("TableSidePanel", {
|
|
|
30906
31013
|
if (!table) {
|
|
30907
31014
|
return { isOpen: false };
|
|
30908
31015
|
}
|
|
30909
|
-
|
|
30910
|
-
|
|
30911
|
-
props: { table },
|
|
30912
|
-
key: table.id,
|
|
30913
|
-
};
|
|
31016
|
+
const coreTable = getters.getCoreTable(getTableTopLeft(table));
|
|
31017
|
+
return { isOpen: true, props: { table: coreTable }, key: table.id };
|
|
30914
31018
|
},
|
|
30915
31019
|
});
|
|
30916
31020
|
|
|
@@ -31855,9 +31959,6 @@ class FunctionDescriptionProvider extends Component {
|
|
|
31855
31959
|
this.assistantState.allowCellSelectionBehind = false;
|
|
31856
31960
|
}, 2000);
|
|
31857
31961
|
}
|
|
31858
|
-
get formulaArgSeparator() {
|
|
31859
|
-
return this.env.model.getters.getLocale().formulaArgSeparator + " ";
|
|
31860
|
-
}
|
|
31861
31962
|
}
|
|
31862
31963
|
|
|
31863
31964
|
const functions$2 = functionRegistry.content;
|
|
@@ -32755,8 +32856,7 @@ class FilterIconsOverlay extends Component {
|
|
|
32755
32856
|
};
|
|
32756
32857
|
getFilterHeadersPositions() {
|
|
32757
32858
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
32758
|
-
|
|
32759
|
-
return headerPositions.map((position) => ({ sheetId, ...position }));
|
|
32859
|
+
return this.env.model.getters.getFilterHeaders(sheetId);
|
|
32760
32860
|
}
|
|
32761
32861
|
}
|
|
32762
32862
|
|
|
@@ -44825,22 +44925,12 @@ class SheetPlugin extends CorePlugin {
|
|
|
44825
44925
|
}
|
|
44826
44926
|
|
|
44827
44927
|
class TablePlugin extends CorePlugin {
|
|
44828
|
-
static getters = [
|
|
44829
|
-
"getFilter",
|
|
44830
|
-
"getFilters",
|
|
44831
|
-
"getTable",
|
|
44832
|
-
"getTables",
|
|
44833
|
-
"getTablesInZone",
|
|
44834
|
-
"getTablesOverlappingZones",
|
|
44835
|
-
"getFilterId",
|
|
44836
|
-
"getFilterHeaders",
|
|
44837
|
-
"isFilterHeader",
|
|
44838
|
-
];
|
|
44928
|
+
static getters = ["getCoreTable", "getCoreTables"];
|
|
44839
44929
|
tables = {};
|
|
44840
44930
|
adaptRanges(applyChange, sheetId) {
|
|
44841
44931
|
const sheetIds = sheetId ? [sheetId] : this.getters.getSheetIds();
|
|
44842
44932
|
for (const sheetId of sheetIds) {
|
|
44843
|
-
for (const table of this.
|
|
44933
|
+
for (const table of this.getCoreTables(sheetId)) {
|
|
44844
44934
|
this.applyRangeChangeOnTable(sheetId, table, applyChange);
|
|
44845
44935
|
}
|
|
44846
44936
|
}
|
|
@@ -44856,15 +44946,16 @@ class TablePlugin extends CorePlugin {
|
|
|
44856
44946
|
? "TableOverlap" /* CommandResult.TableOverlap */
|
|
44857
44947
|
: "Success" /* CommandResult.Success */, (cmd) => this.checkTableConfigUpdateIsValid(cmd.config));
|
|
44858
44948
|
case "UPDATE_TABLE":
|
|
44859
|
-
const updatedTable = this.
|
|
44949
|
+
const updatedTable = this.getTableFromZone(cmd.sheetId, cmd.zone);
|
|
44860
44950
|
if (!updatedTable) {
|
|
44861
44951
|
return "TableNotFound" /* CommandResult.TableNotFound */;
|
|
44862
44952
|
}
|
|
44863
44953
|
return this.checkValidations(cmd, this.checkUpdatedTableZoneIsValid, (cmd) => this.checkTableConfigUpdateIsValid(cmd.config));
|
|
44864
44954
|
case "ADD_MERGE":
|
|
44865
|
-
for (const
|
|
44866
|
-
|
|
44867
|
-
|
|
44955
|
+
for (const table of this.getCoreTables(cmd.sheetId)) {
|
|
44956
|
+
const tableZone = table.range.zone;
|
|
44957
|
+
for (const merge of cmd.target) {
|
|
44958
|
+
if (overlap(tableZone, merge)) {
|
|
44868
44959
|
return "MergeInTable" /* CommandResult.MergeInTable */;
|
|
44869
44960
|
}
|
|
44870
44961
|
}
|
|
@@ -44886,8 +44977,11 @@ class TablePlugin extends CorePlugin {
|
|
|
44886
44977
|
}
|
|
44887
44978
|
case "DUPLICATE_SHEET": {
|
|
44888
44979
|
const newTables = {};
|
|
44889
|
-
for (const table of this.
|
|
44890
|
-
newTables[table.id] =
|
|
44980
|
+
for (const table of this.getCoreTables(cmd.sheetId)) {
|
|
44981
|
+
newTables[table.id] =
|
|
44982
|
+
table.type === "dynamic"
|
|
44983
|
+
? this.copyDynamicTableForSheet(cmd.sheetIdTo, table)
|
|
44984
|
+
: this.copyStaticTableForSheet(cmd.sheetIdTo, table);
|
|
44891
44985
|
}
|
|
44892
44986
|
this.history.update("tables", cmd.sheetIdTo, newTables);
|
|
44893
44987
|
break;
|
|
@@ -44898,14 +44992,17 @@ class TablePlugin extends CorePlugin {
|
|
|
44898
44992
|
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, union.zone);
|
|
44899
44993
|
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
44900
44994
|
const id = this.uuidGenerator.uuidv4();
|
|
44901
|
-
const
|
|
44995
|
+
const config = cmd.config || DEFAULT_TABLE_CONFIG;
|
|
44996
|
+
const newTable = cmd.tableType === "dynamic"
|
|
44997
|
+
? this.createDynamicTable(id, union, config)
|
|
44998
|
+
: this.createStaticTable(id, cmd.tableType, union, config);
|
|
44902
44999
|
this.history.update("tables", cmd.sheetId, newTable.id, newTable);
|
|
44903
45000
|
break;
|
|
44904
45001
|
}
|
|
44905
45002
|
case "REMOVE_TABLE": {
|
|
44906
45003
|
const tables = {};
|
|
44907
|
-
for (const table of this.
|
|
44908
|
-
if (cmd.target.every((zone) => !intersection(
|
|
45004
|
+
for (const table of this.getCoreTables(cmd.sheetId)) {
|
|
45005
|
+
if (cmd.target.every((zone) => !intersection(table.range.zone, zone))) {
|
|
44909
45006
|
tables[table.id] = table;
|
|
44910
45007
|
}
|
|
44911
45008
|
}
|
|
@@ -44913,23 +45010,15 @@ class TablePlugin extends CorePlugin {
|
|
|
44913
45010
|
break;
|
|
44914
45011
|
}
|
|
44915
45012
|
case "UPDATE_TABLE": {
|
|
44916
|
-
|
|
44917
|
-
if (table) {
|
|
44918
|
-
const newTableRange = cmd.newTableRange
|
|
44919
|
-
? this.getters.getRangeFromRangeData(cmd.newTableRange)
|
|
44920
|
-
: undefined;
|
|
44921
|
-
if (newTableRange) {
|
|
44922
|
-
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, newTableRange.zone);
|
|
44923
|
-
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
44924
|
-
}
|
|
44925
|
-
const newTable = this.updateTable(table, newTableRange, cmd.config);
|
|
44926
|
-
this.history.update("tables", cmd.sheetId, table.id, newTable);
|
|
44927
|
-
}
|
|
45013
|
+
this.updateTable(cmd);
|
|
44928
45014
|
break;
|
|
44929
45015
|
}
|
|
44930
45016
|
case "UPDATE_CELL": {
|
|
44931
45017
|
const sheetId = cmd.sheetId;
|
|
44932
|
-
for (const table of this.
|
|
45018
|
+
for (const table of this.getCoreTables(sheetId)) {
|
|
45019
|
+
if (table.type === "dynamic") {
|
|
45020
|
+
continue;
|
|
45021
|
+
}
|
|
44933
45022
|
const direction = this.canUpdateCellCmdExtendTable(cmd, table);
|
|
44934
45023
|
if (direction === "down") {
|
|
44935
45024
|
this.extendTableDown(sheetId, table);
|
|
@@ -44953,62 +45042,24 @@ class TablePlugin extends CorePlugin {
|
|
|
44953
45042
|
}
|
|
44954
45043
|
}
|
|
44955
45044
|
}
|
|
44956
|
-
|
|
44957
|
-
return this.getTables(sheetId)
|
|
44958
|
-
.filter((table) => table.config.hasFilters)
|
|
44959
|
-
.map((table) => table.filters)
|
|
44960
|
-
.flat();
|
|
44961
|
-
}
|
|
44962
|
-
getTables(sheetId) {
|
|
45045
|
+
getCoreTables(sheetId) {
|
|
44963
45046
|
return this.tables[sheetId] ? Object.values(this.tables[sheetId]).filter(isDefined$1) : [];
|
|
44964
45047
|
}
|
|
44965
|
-
|
|
44966
|
-
|
|
44967
|
-
if (!table || !table.config.hasFilters) {
|
|
44968
|
-
return undefined;
|
|
44969
|
-
}
|
|
44970
|
-
return table.filters.find((filter) => filter.col === position.col);
|
|
44971
|
-
}
|
|
44972
|
-
getFilterId(position) {
|
|
44973
|
-
return this.getFilter(position)?.id;
|
|
44974
|
-
}
|
|
44975
|
-
getTable({ sheetId, col, row }) {
|
|
44976
|
-
return this.getTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
44977
|
-
}
|
|
44978
|
-
/** Get the filter tables that are fully inside the given zone */
|
|
44979
|
-
getTablesInZone(sheetId, zone) {
|
|
44980
|
-
return this.getTables(sheetId).filter((table) => isZoneInside(table.range.zone, zone));
|
|
45048
|
+
getCoreTable({ sheetId, col, row }) {
|
|
45049
|
+
return this.getCoreTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
44981
45050
|
}
|
|
44982
45051
|
getTablesOverlappingZones(sheetId, zones) {
|
|
44983
|
-
return this.
|
|
44984
|
-
}
|
|
44985
|
-
getFilterHeaders(sheetId) {
|
|
44986
|
-
const headers = [];
|
|
44987
|
-
for (const table of this.getTables(sheetId)) {
|
|
44988
|
-
if (!table.config.hasFilters) {
|
|
44989
|
-
continue;
|
|
44990
|
-
}
|
|
44991
|
-
const zone = table.range.zone;
|
|
44992
|
-
const row = zone.top;
|
|
44993
|
-
for (let col = zone.left; col <= zone.right; col++) {
|
|
44994
|
-
headers.push({ col, row });
|
|
44995
|
-
}
|
|
44996
|
-
}
|
|
44997
|
-
return headers;
|
|
44998
|
-
}
|
|
44999
|
-
isFilterHeader({ sheetId, col, row }) {
|
|
45000
|
-
const headers = this.getFilterHeaders(sheetId);
|
|
45001
|
-
return headers.some((header) => header.col === col && header.row === row);
|
|
45052
|
+
return this.getCoreTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
|
|
45002
45053
|
}
|
|
45003
45054
|
/** Extend a table down one row */
|
|
45004
45055
|
extendTableDown(sheetId, table) {
|
|
45005
45056
|
const newRange = this.getters.extendRange(table.range, "ROW", 1);
|
|
45006
|
-
this.history.update("tables", sheetId, table.id, this.
|
|
45057
|
+
this.history.update("tables", sheetId, table.id, this.updateStaticTable(table, newRange));
|
|
45007
45058
|
}
|
|
45008
45059
|
/** Extend a table right one col */
|
|
45009
45060
|
extendTableRight(sheetId, table) {
|
|
45010
45061
|
const newRange = this.getters.extendRange(table.range, "COL", 1);
|
|
45011
|
-
this.history.update("tables", sheetId, table.id, this.
|
|
45062
|
+
this.history.update("tables", sheetId, table.id, this.updateStaticTable(table, newRange));
|
|
45012
45063
|
}
|
|
45013
45064
|
/**
|
|
45014
45065
|
* Check if an UpdateCell command should cause the given table to be extended by one row or col.
|
|
@@ -45045,12 +45096,22 @@ class TablePlugin extends CorePlugin {
|
|
|
45045
45096
|
const cellContent = this.getters.getCell(cellPosition)?.content;
|
|
45046
45097
|
if (cellContent ||
|
|
45047
45098
|
this.getters.isInMerge(cellPosition) ||
|
|
45048
|
-
this.
|
|
45099
|
+
this.getTablesOverlappingZones(sheetId, [positionToZone(position)]).length) {
|
|
45049
45100
|
return "none";
|
|
45050
45101
|
}
|
|
45051
45102
|
}
|
|
45052
45103
|
return direction;
|
|
45053
45104
|
}
|
|
45105
|
+
getTableFromZone(sheetId, zone) {
|
|
45106
|
+
for (const table of this.getCoreTables(sheetId)) {
|
|
45107
|
+
const tableZone = table.range.zone;
|
|
45108
|
+
// Only check top left to match dynamic tables
|
|
45109
|
+
if (tableZone.left === zone.left && tableZone.top === zone.top) {
|
|
45110
|
+
return table;
|
|
45111
|
+
}
|
|
45112
|
+
}
|
|
45113
|
+
return undefined;
|
|
45114
|
+
}
|
|
45054
45115
|
checkUpdatedTableZoneIsValid(cmd) {
|
|
45055
45116
|
if (!cmd.newTableRange) {
|
|
45056
45117
|
return "Success" /* CommandResult.Success */;
|
|
@@ -45060,7 +45121,11 @@ class TablePlugin extends CorePlugin {
|
|
|
45060
45121
|
if (zoneIsInSheet !== "Success" /* CommandResult.Success */) {
|
|
45061
45122
|
return zoneIsInSheet;
|
|
45062
45123
|
}
|
|
45063
|
-
const
|
|
45124
|
+
const updatedTable = this.getTableFromZone(cmd.sheetId, cmd.zone);
|
|
45125
|
+
if (!updatedTable) {
|
|
45126
|
+
return "TableNotFound" /* CommandResult.TableNotFound */;
|
|
45127
|
+
}
|
|
45128
|
+
const overlappingTables = this.getTablesOverlappingZones(cmd.sheetId, [newTableZone]).filter((table) => table.id !== updatedTable.id);
|
|
45064
45129
|
return overlappingTables.length ? "TableOverlap" /* CommandResult.TableOverlap */ : "Success" /* CommandResult.Success */;
|
|
45065
45130
|
}
|
|
45066
45131
|
checkTableConfigUpdateIsValid(config) {
|
|
@@ -45078,7 +45143,7 @@ class TablePlugin extends CorePlugin {
|
|
|
45078
45143
|
}
|
|
45079
45144
|
return "Success" /* CommandResult.Success */;
|
|
45080
45145
|
}
|
|
45081
|
-
|
|
45146
|
+
createStaticTable(id, type, tableRange, config, filters) {
|
|
45082
45147
|
const zone = tableRange.zone;
|
|
45083
45148
|
if (!filters) {
|
|
45084
45149
|
filters = [];
|
|
@@ -45093,9 +45158,51 @@ class TablePlugin extends CorePlugin {
|
|
|
45093
45158
|
range: tableRange,
|
|
45094
45159
|
filters,
|
|
45095
45160
|
config,
|
|
45161
|
+
type,
|
|
45162
|
+
};
|
|
45163
|
+
}
|
|
45164
|
+
createDynamicTable(id, tableRange, config) {
|
|
45165
|
+
const zone = zoneToTopLeft(tableRange.zone);
|
|
45166
|
+
return {
|
|
45167
|
+
id,
|
|
45168
|
+
range: this.getters.getRangeFromZone(tableRange.sheetId, zone),
|
|
45169
|
+
config,
|
|
45170
|
+
type: "dynamic",
|
|
45096
45171
|
};
|
|
45097
45172
|
}
|
|
45098
|
-
updateTable(
|
|
45173
|
+
updateTable(cmd) {
|
|
45174
|
+
const table = this.getTableFromZone(cmd.sheetId, cmd.zone);
|
|
45175
|
+
if (!table) {
|
|
45176
|
+
return;
|
|
45177
|
+
}
|
|
45178
|
+
const newTableRange = cmd.newTableRange
|
|
45179
|
+
? this.getters.getRangeFromRangeData(cmd.newTableRange)
|
|
45180
|
+
: undefined;
|
|
45181
|
+
if (newTableRange) {
|
|
45182
|
+
const mergesInTarget = this.getters.getMergesInZone(cmd.sheetId, newTableRange.zone);
|
|
45183
|
+
this.dispatch("REMOVE_MERGE", { sheetId: cmd.sheetId, target: mergesInTarget });
|
|
45184
|
+
}
|
|
45185
|
+
const range = newTableRange || table.range;
|
|
45186
|
+
const newConfig = this.updateTableConfig(cmd.config, table.config);
|
|
45187
|
+
const newTableType = cmd.tableType ?? table.type;
|
|
45188
|
+
if ((newTableType === "dynamic" && table.type !== "dynamic") ||
|
|
45189
|
+
(newTableType !== "dynamic" && table.type === "dynamic")) {
|
|
45190
|
+
const newTable = newTableType === "dynamic"
|
|
45191
|
+
? this.createDynamicTable(table.id, range, newConfig)
|
|
45192
|
+
: this.createStaticTable(table.id, newTableType, range, newConfig);
|
|
45193
|
+
this.history.update("tables", cmd.sheetId, table.id, newTable);
|
|
45194
|
+
}
|
|
45195
|
+
else {
|
|
45196
|
+
const updatedTable = table.type === "dynamic"
|
|
45197
|
+
? this.updateDynamicTable(table, range, newConfig)
|
|
45198
|
+
: this.updateStaticTable(table, range, newConfig, newTableType);
|
|
45199
|
+
this.history.update("tables", cmd.sheetId, table.id, updatedTable);
|
|
45200
|
+
}
|
|
45201
|
+
}
|
|
45202
|
+
updateStaticTable(table, newRange, configUpdate, newTableType = table.type) {
|
|
45203
|
+
if (newTableType === "dynamic") {
|
|
45204
|
+
throw new Error("Cannot use updateStaticTable to update a dynamic table");
|
|
45205
|
+
}
|
|
45099
45206
|
const tableRange = newRange ? newRange : table.range;
|
|
45100
45207
|
const tableZone = tableRange.zone;
|
|
45101
45208
|
const newConfig = this.updateTableConfig(configUpdate, table.config);
|
|
@@ -45116,8 +45223,16 @@ class TablePlugin extends CorePlugin {
|
|
|
45116
45223
|
range: tableRange,
|
|
45117
45224
|
config,
|
|
45118
45225
|
filters: filters.length ? filters : table.filters,
|
|
45226
|
+
type: newTableType,
|
|
45119
45227
|
};
|
|
45120
45228
|
}
|
|
45229
|
+
updateDynamicTable(table, newRange, newConfig) {
|
|
45230
|
+
const range = newRange
|
|
45231
|
+
? this.getters.getRangeFromZone(newRange.sheetId, zoneToTopLeft(newRange.zone))
|
|
45232
|
+
: table.range;
|
|
45233
|
+
const config = newConfig ? newConfig : table.config;
|
|
45234
|
+
return { ...table, range, config };
|
|
45235
|
+
}
|
|
45121
45236
|
/**
|
|
45122
45237
|
* Update the old config of a table with the new partial config from an UpdateTable command.
|
|
45123
45238
|
*
|
|
@@ -45139,35 +45254,29 @@ class TablePlugin extends CorePlugin {
|
|
|
45139
45254
|
}
|
|
45140
45255
|
createFilterFromZone(id, sheetId, zone, config) {
|
|
45141
45256
|
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
45142
|
-
return
|
|
45143
|
-
}
|
|
45144
|
-
createFilter(id, range, config) {
|
|
45145
|
-
const zone = range.zone;
|
|
45146
|
-
if (zone.left !== zone.right) {
|
|
45147
|
-
throw new Error("Can only define a filter on a single column");
|
|
45148
|
-
}
|
|
45149
|
-
const contentZone = getTableContentZone(zone, config);
|
|
45150
|
-
const filteredRange = contentZone
|
|
45151
|
-
? this.getters.getRangeFromZone(range.sheetId, contentZone)
|
|
45152
|
-
: undefined;
|
|
45153
|
-
return {
|
|
45154
|
-
id,
|
|
45155
|
-
rangeWithHeaders: range,
|
|
45156
|
-
col: zone.left,
|
|
45157
|
-
filteredRange,
|
|
45158
|
-
};
|
|
45257
|
+
return createFilter(id, range, config, this.getters.getRangeFromZone);
|
|
45159
45258
|
}
|
|
45160
|
-
|
|
45259
|
+
copyStaticTableForSheet(sheetId, table) {
|
|
45161
45260
|
const newRange = this.getters.getRangeFromZone(sheetId, table.range.zone);
|
|
45162
45261
|
const newFilters = table.filters.map((filter) => {
|
|
45163
45262
|
const newFilterRange = this.getters.getRangeFromZone(sheetId, filter.rangeWithHeaders.zone);
|
|
45164
|
-
return
|
|
45263
|
+
return createFilter(filter.id, newFilterRange, table.config, this.getters.getRangeFromZone);
|
|
45165
45264
|
});
|
|
45166
45265
|
return {
|
|
45167
45266
|
id: table.id,
|
|
45168
45267
|
range: newRange,
|
|
45169
45268
|
filters: newFilters,
|
|
45170
45269
|
config: deepCopy(table.config),
|
|
45270
|
+
type: table.type,
|
|
45271
|
+
};
|
|
45272
|
+
}
|
|
45273
|
+
copyDynamicTableForSheet(sheetId, table) {
|
|
45274
|
+
const newRange = this.getters.getRangeFromZone(sheetId, table.range.zone);
|
|
45275
|
+
return {
|
|
45276
|
+
id: table.id,
|
|
45277
|
+
range: newRange,
|
|
45278
|
+
config: deepCopy(table.config),
|
|
45279
|
+
type: "dynamic",
|
|
45171
45280
|
};
|
|
45172
45281
|
}
|
|
45173
45282
|
applyRangeChangeOnTable(sheetId, table, applyChange) {
|
|
@@ -45182,6 +45291,11 @@ class TablePlugin extends CorePlugin {
|
|
|
45182
45291
|
default:
|
|
45183
45292
|
newTableRange = tableRangeChange.range;
|
|
45184
45293
|
}
|
|
45294
|
+
if (table.type === "dynamic") {
|
|
45295
|
+
const newTable = this.updateDynamicTable(table, newTableRange);
|
|
45296
|
+
this.history.update("tables", sheetId, table.id, newTable);
|
|
45297
|
+
return;
|
|
45298
|
+
}
|
|
45185
45299
|
const filters = [];
|
|
45186
45300
|
for (const filter of table.filters) {
|
|
45187
45301
|
const filterRangeChange = applyChange(filter.rangeWithHeaders);
|
|
@@ -45193,7 +45307,7 @@ class TablePlugin extends CorePlugin {
|
|
|
45193
45307
|
break;
|
|
45194
45308
|
default:
|
|
45195
45309
|
const newFilterRange = filterRangeChange.range;
|
|
45196
|
-
const newFilter =
|
|
45310
|
+
const newFilter = createFilter(filter.id, newFilterRange, table.config, this.getters.getRangeFromZone);
|
|
45197
45311
|
filters.push(newFilter);
|
|
45198
45312
|
}
|
|
45199
45313
|
}
|
|
@@ -45208,7 +45322,7 @@ class TablePlugin extends CorePlugin {
|
|
|
45208
45322
|
}
|
|
45209
45323
|
filters.sort((f1, f2) => f1.col - f2.col);
|
|
45210
45324
|
}
|
|
45211
|
-
const newTable = this.
|
|
45325
|
+
const newTable = this.createStaticTable(table.id, table.type, newTableRange, table.config, filters);
|
|
45212
45326
|
this.history.update("tables", sheetId, table.id, newTable);
|
|
45213
45327
|
}
|
|
45214
45328
|
// ---------------------------------------------------------------------------
|
|
@@ -45219,16 +45333,20 @@ class TablePlugin extends CorePlugin {
|
|
|
45219
45333
|
for (const tableData of sheet.tables || []) {
|
|
45220
45334
|
const uuid = this.uuidGenerator.uuidv4();
|
|
45221
45335
|
const tableConfig = tableData.config || DEFAULT_TABLE_CONFIG;
|
|
45222
|
-
const
|
|
45223
|
-
const
|
|
45336
|
+
const range = this.getters.getRangeFromSheetXC(sheet.id, tableData.range);
|
|
45337
|
+
const tableType = tableData.type || "static";
|
|
45338
|
+
const table = tableType === "dynamic"
|
|
45339
|
+
? this.createDynamicTable(uuid, range, tableConfig)
|
|
45340
|
+
: this.createStaticTable(uuid, tableType, range, tableConfig);
|
|
45224
45341
|
this.history.update("tables", sheet.id, table.id, table);
|
|
45225
45342
|
}
|
|
45226
45343
|
}
|
|
45227
45344
|
}
|
|
45228
45345
|
export(data) {
|
|
45229
45346
|
for (const sheet of data.sheets) {
|
|
45230
|
-
for (const table of this.
|
|
45231
|
-
const
|
|
45347
|
+
for (const table of this.getCoreTables(sheet.id)) {
|
|
45348
|
+
const range = zoneToXc(table.range.zone);
|
|
45349
|
+
const tableData = { range, type: table.type };
|
|
45232
45350
|
if (!deepEquals(table.config, DEFAULT_TABLE_CONFIG)) {
|
|
45233
45351
|
tableData.config = table.config;
|
|
45234
45352
|
}
|
|
@@ -46944,14 +47062,18 @@ class Evaluator {
|
|
|
46944
47062
|
if (!this.spreadingRelations.isArrayFormula(position)) {
|
|
46945
47063
|
return [];
|
|
46946
47064
|
}
|
|
46947
|
-
|
|
47065
|
+
if (this.evaluatedCells.get(position)?.type === CellValueType.error) {
|
|
47066
|
+
return [position];
|
|
47067
|
+
}
|
|
47068
|
+
const spreadPositions = Array.from(this.spreadingRelations.getArrayResultPositions(position));
|
|
47069
|
+
return [position, ...spreadPositions];
|
|
46948
47070
|
}
|
|
46949
47071
|
getEvaluatedPositions() {
|
|
46950
47072
|
return this.evaluatedCells.keys();
|
|
46951
47073
|
}
|
|
46952
47074
|
getArrayFormulaSpreadingOn(position) {
|
|
46953
47075
|
if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
|
|
46954
|
-
return undefined;
|
|
47076
|
+
return this.spreadingRelations.isArrayFormula(position) ? position : undefined;
|
|
46955
47077
|
}
|
|
46956
47078
|
const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
|
|
46957
47079
|
return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
|
|
@@ -47080,6 +47202,7 @@ class Evaluator {
|
|
|
47080
47202
|
if (!this.blockedArrayFormulas.has(position)) {
|
|
47081
47203
|
this.invalidateSpreading(position);
|
|
47082
47204
|
}
|
|
47205
|
+
this.spreadingRelations.removeNode(position);
|
|
47083
47206
|
const cell = this.getters.getCell(position);
|
|
47084
47207
|
if (cell === undefined) {
|
|
47085
47208
|
return EMPTY_CELL;
|
|
@@ -47190,7 +47313,6 @@ class Evaluator {
|
|
|
47190
47313
|
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
|
|
47191
47314
|
this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
|
|
47192
47315
|
}
|
|
47193
|
-
this.spreadingRelations.removeNode(position);
|
|
47194
47316
|
}
|
|
47195
47317
|
// ----------------------------------------------------------
|
|
47196
47318
|
// COMMON FUNCTIONALITY
|
|
@@ -48288,6 +48410,181 @@ class EvaluationDataValidationPlugin extends UIPlugin {
|
|
|
48288
48410
|
}
|
|
48289
48411
|
}
|
|
48290
48412
|
|
|
48413
|
+
class DynamicTablesPlugin extends UIPlugin {
|
|
48414
|
+
static getters = [
|
|
48415
|
+
"canCreateDynamicTableOnZones",
|
|
48416
|
+
"doesZonesContainFilter",
|
|
48417
|
+
"getFilter",
|
|
48418
|
+
"getFilters",
|
|
48419
|
+
"getTable",
|
|
48420
|
+
"getTables",
|
|
48421
|
+
"getTablesOverlappingZones",
|
|
48422
|
+
"getFilterId",
|
|
48423
|
+
"getFilterHeaders",
|
|
48424
|
+
"isFilterHeader",
|
|
48425
|
+
];
|
|
48426
|
+
tables = {};
|
|
48427
|
+
handle(cmd) {
|
|
48428
|
+
if (invalidateEvaluationCommands.has(cmd.type) ||
|
|
48429
|
+
(cmd.type === "UPDATE_CELL" && "content" in cmd) ||
|
|
48430
|
+
cmd.type === "EVALUATE_CELLS") {
|
|
48431
|
+
this.tables = {};
|
|
48432
|
+
return;
|
|
48433
|
+
}
|
|
48434
|
+
switch (cmd.type) {
|
|
48435
|
+
case "CREATE_TABLE":
|
|
48436
|
+
case "REMOVE_TABLE":
|
|
48437
|
+
case "UPDATE_TABLE":
|
|
48438
|
+
case "DELETE_CONTENT":
|
|
48439
|
+
this.tables = {};
|
|
48440
|
+
break;
|
|
48441
|
+
}
|
|
48442
|
+
}
|
|
48443
|
+
finalize() {
|
|
48444
|
+
for (const sheetId of this.getters.getSheetIds()) {
|
|
48445
|
+
if (!this.tables[sheetId]) {
|
|
48446
|
+
this.tables[sheetId] = this.computeTables(sheetId);
|
|
48447
|
+
}
|
|
48448
|
+
}
|
|
48449
|
+
}
|
|
48450
|
+
computeTables(sheetId) {
|
|
48451
|
+
const tables = [];
|
|
48452
|
+
const coreTables = this.getters.getCoreTables(sheetId);
|
|
48453
|
+
// First we create the static tables, so we can use them to compute collision with dynamic tables
|
|
48454
|
+
for (const table of coreTables) {
|
|
48455
|
+
if (table.type === "dynamic")
|
|
48456
|
+
continue;
|
|
48457
|
+
tables.push(table);
|
|
48458
|
+
}
|
|
48459
|
+
const staticTables = [...tables];
|
|
48460
|
+
// Then we create the dynamic tables
|
|
48461
|
+
for (const coreTable of coreTables) {
|
|
48462
|
+
if (coreTable.type !== "dynamic")
|
|
48463
|
+
continue;
|
|
48464
|
+
const table = this.coreTableToTable(sheetId, coreTable);
|
|
48465
|
+
let tableZone = table.range.zone;
|
|
48466
|
+
// Reduce the zone to avoid collision with static tables. Per design, dynamic tables can't overlap with other
|
|
48467
|
+
// dynamic tables, because formulas cannot spread on the same area, so we don't need to check for that.
|
|
48468
|
+
for (const staticTable of staticTables) {
|
|
48469
|
+
if (overlap(tableZone, staticTable.range.zone)) {
|
|
48470
|
+
tableZone = { ...tableZone, right: staticTable.range.zone.left - 1 };
|
|
48471
|
+
}
|
|
48472
|
+
}
|
|
48473
|
+
tables.push({ ...table, range: this.getters.getRangeFromZone(sheetId, tableZone) });
|
|
48474
|
+
}
|
|
48475
|
+
return tables;
|
|
48476
|
+
}
|
|
48477
|
+
getFilters(sheetId) {
|
|
48478
|
+
return this.getTables(sheetId)
|
|
48479
|
+
.filter((table) => table.config.hasFilters)
|
|
48480
|
+
.map((table) => table.filters)
|
|
48481
|
+
.flat();
|
|
48482
|
+
}
|
|
48483
|
+
getTables(sheetId) {
|
|
48484
|
+
return this.tables[sheetId] || [];
|
|
48485
|
+
}
|
|
48486
|
+
getFilter(position) {
|
|
48487
|
+
const table = this.getTable(position);
|
|
48488
|
+
if (!table || !table.config.hasFilters) {
|
|
48489
|
+
return undefined;
|
|
48490
|
+
}
|
|
48491
|
+
return table.filters.find((filter) => filter.col === position.col);
|
|
48492
|
+
}
|
|
48493
|
+
getFilterId(position) {
|
|
48494
|
+
return this.getFilter(position)?.id;
|
|
48495
|
+
}
|
|
48496
|
+
getTable({ sheetId, col, row }) {
|
|
48497
|
+
return this.getTables(sheetId).find((table) => isInside(col, row, table.range.zone));
|
|
48498
|
+
}
|
|
48499
|
+
getTablesOverlappingZones(sheetId, zones) {
|
|
48500
|
+
return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
|
|
48501
|
+
}
|
|
48502
|
+
doesZonesContainFilter(sheetId, zones) {
|
|
48503
|
+
return this.getTablesOverlappingZones(sheetId, zones).some((table) => table.config.hasFilters);
|
|
48504
|
+
}
|
|
48505
|
+
getFilterHeaders(sheetId) {
|
|
48506
|
+
const headers = [];
|
|
48507
|
+
for (const table of this.getTables(sheetId)) {
|
|
48508
|
+
if (!table.config.hasFilters) {
|
|
48509
|
+
continue;
|
|
48510
|
+
}
|
|
48511
|
+
const zone = table.range.zone;
|
|
48512
|
+
const row = zone.top;
|
|
48513
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
48514
|
+
headers.push({ sheetId, col, row });
|
|
48515
|
+
}
|
|
48516
|
+
}
|
|
48517
|
+
return headers;
|
|
48518
|
+
}
|
|
48519
|
+
isFilterHeader({ sheetId, col, row }) {
|
|
48520
|
+
const headers = this.getFilterHeaders(sheetId);
|
|
48521
|
+
return headers.some((header) => header.col === col && header.row === row);
|
|
48522
|
+
}
|
|
48523
|
+
/**
|
|
48524
|
+
* Check if we can create a dynamic table on the given zones.
|
|
48525
|
+
* - The zones must be continuous
|
|
48526
|
+
* - The union of the zones must be either:
|
|
48527
|
+
* - A single cell that contains an array formula
|
|
48528
|
+
* - All the spread cells of a single array formula
|
|
48529
|
+
*/
|
|
48530
|
+
canCreateDynamicTableOnZones(sheetId, zones) {
|
|
48531
|
+
if (!areZonesContinuous(zones)) {
|
|
48532
|
+
return false;
|
|
48533
|
+
}
|
|
48534
|
+
const unionZone = union(...zones);
|
|
48535
|
+
const topLeft = { col: unionZone.left, row: unionZone.top, sheetId };
|
|
48536
|
+
const parentSpreadingCell = this.getters.getArrayFormulaSpreadingOn(topLeft);
|
|
48537
|
+
if (!parentSpreadingCell) {
|
|
48538
|
+
return false;
|
|
48539
|
+
}
|
|
48540
|
+
else if (deepEquals(parentSpreadingCell, topLeft) && getZoneArea(unionZone) === 1) {
|
|
48541
|
+
return true;
|
|
48542
|
+
}
|
|
48543
|
+
const spreadPositions = this.getters.getSpreadPositionsOf(parentSpreadingCell);
|
|
48544
|
+
return deepEquals(unionZone, unionPositionsToZone(spreadPositions));
|
|
48545
|
+
}
|
|
48546
|
+
coreTableToTable(sheetId, table) {
|
|
48547
|
+
if (table.type !== "dynamic") {
|
|
48548
|
+
return table;
|
|
48549
|
+
}
|
|
48550
|
+
const tableZone = table.range.zone;
|
|
48551
|
+
const tablePosition = { sheetId, col: tableZone.left, row: tableZone.top };
|
|
48552
|
+
const spreadPositions = this.getters.getSpreadPositionsOf(tablePosition);
|
|
48553
|
+
const zone = spreadPositions.length ? unionPositionsToZone(spreadPositions) : table.range.zone;
|
|
48554
|
+
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
48555
|
+
const filters = this.getDynamicTableFilters(sheetId, table, zone);
|
|
48556
|
+
return { id: table.id, range, filters, config: table.config };
|
|
48557
|
+
}
|
|
48558
|
+
getDynamicTableFilters(sheetId, table, tableZone) {
|
|
48559
|
+
const filters = [];
|
|
48560
|
+
const { top, bottom, left, right } = tableZone;
|
|
48561
|
+
for (let col = left; col <= right; col++) {
|
|
48562
|
+
const tableColIndex = col - left;
|
|
48563
|
+
const zone = { left: col, right: col, top, bottom };
|
|
48564
|
+
const filter = createFilter(this.getDynamicTableFilterId(table.id, tableColIndex), this.getters.getRangeFromZone(sheetId, zone), table.config, this.getters.getRangeFromZone);
|
|
48565
|
+
filters.push(filter);
|
|
48566
|
+
}
|
|
48567
|
+
return filters;
|
|
48568
|
+
}
|
|
48569
|
+
getDynamicTableFilterId(tableId, tableCol) {
|
|
48570
|
+
return tableId + "_" + tableCol;
|
|
48571
|
+
}
|
|
48572
|
+
exportForExcel(data) {
|
|
48573
|
+
for (const sheet of data.sheets) {
|
|
48574
|
+
for (const tableData of sheet.tables) {
|
|
48575
|
+
const zone = toZone(tableData.range);
|
|
48576
|
+
const topLeft = { sheetId: sheet.id, col: zone.left, row: zone.top };
|
|
48577
|
+
const coreTable = this.getters.getCoreTable(topLeft);
|
|
48578
|
+
const table = this.getTable(topLeft);
|
|
48579
|
+
if (coreTable?.type !== "dynamic" || !table) {
|
|
48580
|
+
continue;
|
|
48581
|
+
}
|
|
48582
|
+
tableData.range = zoneToXc(table.range.zone);
|
|
48583
|
+
}
|
|
48584
|
+
}
|
|
48585
|
+
}
|
|
48586
|
+
}
|
|
48587
|
+
|
|
48291
48588
|
class HeaderSizeUIPlugin extends UIPlugin {
|
|
48292
48589
|
static getters = ["getRowSize", "getHeaderSize"];
|
|
48293
48590
|
tallestCellInRow = {};
|
|
@@ -51335,10 +51632,11 @@ class TableAutofillPlugin extends UIPlugin {
|
|
|
51335
51632
|
handle(cmd) {
|
|
51336
51633
|
switch (cmd.type) {
|
|
51337
51634
|
case "AUTOFILL_TABLE_COLUMN":
|
|
51338
|
-
const table = this.getters.
|
|
51635
|
+
const table = this.getters.getCoreTable(cmd);
|
|
51339
51636
|
const cell = this.getters.getCell(cmd);
|
|
51340
|
-
if (!table ||
|
|
51637
|
+
if (!table?.config.automaticAutofill || table.type === "dynamic" || !cell?.isFormula) {
|
|
51341
51638
|
return;
|
|
51639
|
+
}
|
|
51342
51640
|
const { col, row } = cmd;
|
|
51343
51641
|
const tableContentZone = getTableContentZone(table.range.zone, table.config);
|
|
51344
51642
|
if (tableContentZone && isInside(col, row, tableContentZone)) {
|
|
@@ -52067,9 +52365,6 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
52067
52365
|
case "START":
|
|
52068
52366
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
52069
52367
|
this.filterValues[sheetId] = {};
|
|
52070
|
-
for (const filter of this.getters.getFilters(sheetId)) {
|
|
52071
|
-
this.filterValues[sheetId][filter.id] = [];
|
|
52072
|
-
}
|
|
52073
52368
|
}
|
|
52074
52369
|
break;
|
|
52075
52370
|
case "CREATE_SHEET":
|
|
@@ -52090,16 +52385,7 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
52090
52385
|
this.updateHiddenRows();
|
|
52091
52386
|
break;
|
|
52092
52387
|
case "DUPLICATE_SHEET":
|
|
52093
|
-
|
|
52094
|
-
for (const newFilter of this.getters.getFilters(cmd.sheetIdTo)) {
|
|
52095
|
-
const zone = newFilter.rangeWithHeaders.zone;
|
|
52096
|
-
filterValues[newFilter.id] = this.getFilterHiddenValues({
|
|
52097
|
-
sheetId: cmd.sheetId,
|
|
52098
|
-
col: zone.left,
|
|
52099
|
-
row: zone.top,
|
|
52100
|
-
});
|
|
52101
|
-
}
|
|
52102
|
-
this.filterValues[cmd.sheetIdTo] = filterValues;
|
|
52388
|
+
this.filterValues[cmd.sheetIdTo] = deepCopy(this.filterValues[cmd.sheetId]);
|
|
52103
52389
|
break;
|
|
52104
52390
|
// If we don't handle DELETE_SHEET, on one hand we will have some residual data, on the other hand we keep the data
|
|
52105
52391
|
// on DELETE_SHEET followed by undo
|
|
@@ -54043,8 +54329,9 @@ const coreViewsPluginRegistry = new Registry()
|
|
|
54043
54329
|
.add("evaluation_chart", EvaluationChartPlugin)
|
|
54044
54330
|
.add("evaluation_cf", EvaluationConditionalFormatPlugin)
|
|
54045
54331
|
.add("row_size", HeaderSizeUIPlugin)
|
|
54046
|
-
.add("
|
|
54047
|
-
.add("
|
|
54332
|
+
.add("data_validation_ui", EvaluationDataValidationPlugin)
|
|
54333
|
+
.add("dynamic_tables", DynamicTablesPlugin)
|
|
54334
|
+
.add("custom_colors", CustomColorsPlugin);
|
|
54048
54335
|
|
|
54049
54336
|
const clickableCellRegistry = new Registry();
|
|
54050
54337
|
clickableCellRegistry.add("link", {
|
|
@@ -60134,6 +60421,6 @@ const constants = {
|
|
|
60134
60421
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
60135
60422
|
|
|
60136
60423
|
|
|
60137
|
-
__info__.version = "17.
|
|
60138
|
-
__info__.date = "2024-03-25T09:
|
|
60139
|
-
__info__.hash = "
|
|
60424
|
+
__info__.version = "17.3.0-alpha.1";
|
|
60425
|
+
__info__.date = "2024-03-25T09:43:36.072Z";
|
|
60426
|
+
__info__.hash = "4095c41";
|