@a3s-lab/office 0.15.0 → 0.16.0
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/COLLABORATION_ROADMAP.md +15 -5
- package/README.md +22 -1
- package/dist/0~6090.js +7 -8
- package/dist/0~spreadsheet-editor.js +2106 -438
- package/dist/2180.js +370 -34
- package/dist/4104.js +657 -22
- package/dist/5184.js +1 -1
- package/dist/8715.js +156 -156
- package/dist/internal/collaboration/office-spreadsheet-collaboration-records.d.ts +2 -0
- package/dist/internal/collaboration/office-spreadsheet-collaboration-validation-support.d.ts +6 -0
- package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +21 -1
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +4 -2
- package/dist/internal/features/work/editors/spreadsheet-table-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-table-conversion.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-table-dialog.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-table-limits.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-table-reconciliation.d.ts +21 -0
- package/dist/internal/features/work/editors/spreadsheet-table-render.d.ts +16 -0
- package/dist/internal/features/work/editors/spreadsheet-table-ribbon.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-table-style.d.ts +31 -0
- package/dist/internal/features/work/editors/spreadsheet-table.d.ts +55 -0
- package/dist/internal/features/work/editors/use-spreadsheet-table.d.ts +23 -0
- package/dist/internal/features/work/work-types.d.ts +100 -0
- package/dist/internal/features/work/work-xlsx-interop.d.ts +2 -0
- package/dist/internal/features/work/work-xlsx-table-filters.d.ts +3 -0
- package/dist/internal/features/work/work-xlsx-tables.d.ts +4 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +189 -0
- package/dist/work-spreadsheet-package-scan.worker.js +3 -2
- package/docs/latest/en/browser-editor-architecture.md +43 -0
- package/package.json +4 -1
|
@@ -10,13 +10,13 @@ import { moveOfficeMenuFocus, stepOfficeZoom, useOfficeRemoteParticipants, Popov
|
|
|
10
10
|
import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
11
11
|
import { isOfficeShortcutBlocked, OfficeColorPicker } from "./0~3635.js";
|
|
12
12
|
import { createOfficeEditorExtension, useOfficeEditorRuntime, useOfficeEditorKeyboardShortcuts } from "./0~3557.js";
|
|
13
|
+
import { OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, createOfficeId as createWorkId, isOfficeKernelSpreadsheetError } from "./5184.js";
|
|
13
14
|
import { showToast } from "./6489.js";
|
|
14
15
|
import { unsupportedSpreadsheetFormulaFunctions } from "./0~work-spreadsheet-formula-support.js";
|
|
15
16
|
import { WorkspaceContextMenu, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, Tabs, WorkOfficeStatusBar, Dialog, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkOfficeRibbonGroup, WorkOfficeRibbonButton, WorkOfficePreviewBar } from "./0~4595.js";
|
|
16
17
|
import { useOfficeDraft, InlineNotice } from "./0~345.js";
|
|
17
18
|
import { spreadsheetAgentMenuItems, SpreadsheetChartSeriesStyleEditor, normalizeOptionalOfficeNumber, normalizeRequiredOfficeNumber, SpreadsheetErrorBarEditor, useOfficeHistory, spreadsheetAgentSelection, SpreadsheetTrendlineEditor, applySpreadsheetAgentProposalChanges } from "./0~3539.js";
|
|
18
19
|
import { useOfficeEditorFocusOrigin, useOfficeCollaborationLocationNavigator, StateView } from "./432.js";
|
|
19
|
-
import { OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, createOfficeId as createWorkId, isOfficeKernelSpreadsheetError } from "./5184.js";
|
|
20
20
|
var spreadsheet_editor_namespaceObject = {};
|
|
21
21
|
__webpack_require__.r(spreadsheet_editor_namespaceObject);
|
|
22
22
|
__webpack_require__.d(spreadsheet_editor_namespaceObject, {
|
|
@@ -1357,6 +1357,349 @@ function isSpreadsheetCoordinate(value) {
|
|
|
1357
1357
|
function positiveSpreadsheetDimension(value) {
|
|
1358
1358
|
return 'number' == typeof value && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
1359
1359
|
}
|
|
1360
|
+
function canApplySpreadsheetTableStructureChange(sheet, change) {
|
|
1361
|
+
if (!sheet || !validSpreadsheetTableStructureChange(change)) return false;
|
|
1362
|
+
for (const table of sheet.tables ?? []){
|
|
1363
|
+
if ('delete' === change.kind && 'row' === change.axis && spreadsheetTableDeleteRemovesSemanticRow(table, change.start, change.end)) return false;
|
|
1364
|
+
if (!transformSpreadsheetTableStructure(table, change)) return false;
|
|
1365
|
+
}
|
|
1366
|
+
return true;
|
|
1367
|
+
}
|
|
1368
|
+
function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations = []) {
|
|
1369
|
+
return sheets.map((sheet, index)=>{
|
|
1370
|
+
const source = sourceSheetForReconciliation(sheet, sourceSheets, index);
|
|
1371
|
+
if (!source?.tables?.length) return sheet;
|
|
1372
|
+
const sheetOperations = operations.filter((operation)=>operation.id === source.id);
|
|
1373
|
+
let tables = source.tables;
|
|
1374
|
+
const reconcileColumns = new Set();
|
|
1375
|
+
if (!operations.length) for (const table of tables)reconcileColumns.add(table.id);
|
|
1376
|
+
for (const operation of sheetOperations){
|
|
1377
|
+
const structure = spreadsheetTableStructureChangeFromOperation(operation);
|
|
1378
|
+
if (structure) {
|
|
1379
|
+
const transformed = [];
|
|
1380
|
+
for (const table of tables){
|
|
1381
|
+
const next = transformSpreadsheetTableStructure(table, structure);
|
|
1382
|
+
if (next) {
|
|
1383
|
+
transformed.push(next);
|
|
1384
|
+
if (next !== table) reconcileColumns.add(table.id);
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
tables = transformed;
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
const coordinate = spreadsheetCellCoordinateFromOperation(operation);
|
|
1391
|
+
if (!coordinate) continue;
|
|
1392
|
+
const table = tables.find((candidate)=>candidate.headerRow && candidate.range.row[0] === coordinate.row && coordinate.column >= candidate.range.column[0] && coordinate.column <= candidate.range.column[1]);
|
|
1393
|
+
if (table) reconcileColumns.add(table.id);
|
|
1394
|
+
}
|
|
1395
|
+
const updates = [];
|
|
1396
|
+
const readCell = spreadsheetSheetCellReader(sheet);
|
|
1397
|
+
tables = tables.map((table)=>{
|
|
1398
|
+
if (!reconcileColumns.has(table.id)) return table;
|
|
1399
|
+
const columns = canonicalSpreadsheetTableColumns(table, readCell);
|
|
1400
|
+
if (table.headerRow) for (const [offset, column] of columns.entries()){
|
|
1401
|
+
const cellColumn = table.range.column[0] + offset;
|
|
1402
|
+
if (spreadsheetCellText(readCell(table.range.row[0], cellColumn)) !== column.name) updates.push({
|
|
1403
|
+
column: cellColumn,
|
|
1404
|
+
name: column.name,
|
|
1405
|
+
row: table.range.row[0]
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
return sameSpreadsheetTableColumns(table.columns, columns) ? table : {
|
|
1409
|
+
...table,
|
|
1410
|
+
columns
|
|
1411
|
+
};
|
|
1412
|
+
});
|
|
1413
|
+
const withHeaders = stampSpreadsheetTableHeaderCells(sheet, updates);
|
|
1414
|
+
return {
|
|
1415
|
+
...withHeaders,
|
|
1416
|
+
tables: tables.length ? tables : void 0
|
|
1417
|
+
};
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
function transformSpreadsheetTableStructure(table, change) {
|
|
1421
|
+
if (!validSpreadsheetTableStructureChange(change)) return null;
|
|
1422
|
+
const axis = 'row' === change.axis ? table.range.row : table.range.column;
|
|
1423
|
+
const transformed = 'insert' === change.kind ? transformSpreadsheetTableAxisForInsertion(axis, change) : transformSpreadsheetTableAxisForDeletion(axis, change);
|
|
1424
|
+
if (!transformed) return null;
|
|
1425
|
+
const range = {
|
|
1426
|
+
row: 'row' === change.axis ? transformed.axis : [
|
|
1427
|
+
...table.range.row
|
|
1428
|
+
],
|
|
1429
|
+
column: 'column' === change.axis ? transformed.axis : [
|
|
1430
|
+
...table.range.column
|
|
1431
|
+
]
|
|
1432
|
+
};
|
|
1433
|
+
const height = range.row[1] - range.row[0] + 1;
|
|
1434
|
+
if (height <= Number(table.headerRow) + Number(table.totalsRow)) return null;
|
|
1435
|
+
if ('column' !== change.axis || !transformed.inside) {
|
|
1436
|
+
if (range.row[0] === table.range.row[0] && range.row[1] === table.range.row[1] && range.column[0] === table.range.column[0] && range.column[1] === table.range.column[1]) return table;
|
|
1437
|
+
return {
|
|
1438
|
+
...table,
|
|
1439
|
+
range
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
if ('insert' === change.kind) {
|
|
1443
|
+
const columns = [
|
|
1444
|
+
...table.columns
|
|
1445
|
+
];
|
|
1446
|
+
columns.splice(transformed.offset, 0, ...Array.from({
|
|
1447
|
+
length: change.count
|
|
1448
|
+
}, ()=>({
|
|
1449
|
+
name: ''
|
|
1450
|
+
})));
|
|
1451
|
+
return {
|
|
1452
|
+
...table,
|
|
1453
|
+
range,
|
|
1454
|
+
columns,
|
|
1455
|
+
filters: table.filters.map((filter)=>filter.column >= transformed.offset ? {
|
|
1456
|
+
...filter,
|
|
1457
|
+
column: filter.column + change.count
|
|
1458
|
+
} : filter)
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
if (!('removed' in transformed)) return null;
|
|
1462
|
+
const removed = transformed.removed;
|
|
1463
|
+
if ('number' != typeof removed) return null;
|
|
1464
|
+
const columns = [
|
|
1465
|
+
...table.columns
|
|
1466
|
+
];
|
|
1467
|
+
columns.splice(transformed.offset, removed);
|
|
1468
|
+
if (!columns.length) return null;
|
|
1469
|
+
return {
|
|
1470
|
+
...table,
|
|
1471
|
+
range,
|
|
1472
|
+
columns,
|
|
1473
|
+
filters: filtersAfterSpreadsheetTableColumnDeletion(table.filters, transformed.offset, removed)
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
function transformSpreadsheetTableAxisForInsertion(axis, change) {
|
|
1477
|
+
const start = axis[0] ?? 0;
|
|
1478
|
+
const end = axis[1] ?? start;
|
|
1479
|
+
const insertion = change.index + ('rightbottom' === change.direction ? 1 : 0);
|
|
1480
|
+
if (insertion <= start) return {
|
|
1481
|
+
axis: [
|
|
1482
|
+
start + change.count,
|
|
1483
|
+
end + change.count
|
|
1484
|
+
],
|
|
1485
|
+
inside: false,
|
|
1486
|
+
offset: 0
|
|
1487
|
+
};
|
|
1488
|
+
if (insertion <= end) return {
|
|
1489
|
+
axis: [
|
|
1490
|
+
start,
|
|
1491
|
+
end + change.count
|
|
1492
|
+
],
|
|
1493
|
+
inside: true,
|
|
1494
|
+
offset: insertion - start
|
|
1495
|
+
};
|
|
1496
|
+
return {
|
|
1497
|
+
axis: [
|
|
1498
|
+
start,
|
|
1499
|
+
end
|
|
1500
|
+
],
|
|
1501
|
+
inside: false,
|
|
1502
|
+
offset: 0
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
function transformSpreadsheetTableAxisForDeletion(axis, change) {
|
|
1506
|
+
const start = axis[0] ?? 0;
|
|
1507
|
+
const end = axis[1] ?? start;
|
|
1508
|
+
const count = change.end - change.start + 1;
|
|
1509
|
+
if (change.end < start) return {
|
|
1510
|
+
axis: [
|
|
1511
|
+
start - count,
|
|
1512
|
+
end - count
|
|
1513
|
+
],
|
|
1514
|
+
inside: false,
|
|
1515
|
+
offset: 0,
|
|
1516
|
+
removed: 0
|
|
1517
|
+
};
|
|
1518
|
+
if (change.start > end) return {
|
|
1519
|
+
axis: [
|
|
1520
|
+
start,
|
|
1521
|
+
end
|
|
1522
|
+
],
|
|
1523
|
+
inside: false,
|
|
1524
|
+
offset: 0,
|
|
1525
|
+
removed: 0
|
|
1526
|
+
};
|
|
1527
|
+
const overlapStart = Math.max(start, change.start);
|
|
1528
|
+
const overlapEnd = Math.min(end, change.end);
|
|
1529
|
+
const removed = overlapEnd - overlapStart + 1;
|
|
1530
|
+
const remaining = end - start + 1 - removed;
|
|
1531
|
+
if (remaining <= 0) return null;
|
|
1532
|
+
const deletedBeforeStart = Math.max(0, Math.min(change.end, start - 1) - change.start + 1);
|
|
1533
|
+
const nextStart = start - deletedBeforeStart;
|
|
1534
|
+
return {
|
|
1535
|
+
axis: [
|
|
1536
|
+
nextStart,
|
|
1537
|
+
nextStart + remaining - 1
|
|
1538
|
+
],
|
|
1539
|
+
inside: true,
|
|
1540
|
+
offset: overlapStart - start,
|
|
1541
|
+
removed
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
function filtersAfterSpreadsheetTableColumnDeletion(filters, offset, removed) {
|
|
1545
|
+
const end = offset + removed - 1;
|
|
1546
|
+
return filters.flatMap((filter)=>{
|
|
1547
|
+
if (filter.column >= offset && filter.column <= end) return [];
|
|
1548
|
+
return [
|
|
1549
|
+
filter.column > end ? {
|
|
1550
|
+
...filter,
|
|
1551
|
+
column: filter.column - removed
|
|
1552
|
+
} : filter
|
|
1553
|
+
];
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
function canonicalSpreadsheetTableColumns(table, readCell) {
|
|
1557
|
+
const width = table.range.column[1] - table.range.column[0] + 1;
|
|
1558
|
+
const observed = new Set();
|
|
1559
|
+
return Array.from({
|
|
1560
|
+
length: width
|
|
1561
|
+
}, (_, offset)=>{
|
|
1562
|
+
const raw = table.headerRow ? spreadsheetCellText(readCell(table.range.row[0], table.range.column[0] + offset)).trim() : table.columns[offset]?.name.trim() ?? '';
|
|
1563
|
+
const base = validSpreadsheetTableColumnName(raw) ? raw : `Column${offset + 1}`;
|
|
1564
|
+
let candidate = base;
|
|
1565
|
+
let suffix = 2;
|
|
1566
|
+
while(observed.has(candidate.toLocaleLowerCase())){
|
|
1567
|
+
const suffixText = String(suffix);
|
|
1568
|
+
candidate = `${truncateSpreadsheetTableColumnName(base, 255 - suffixText.length)}${suffixText}`;
|
|
1569
|
+
suffix += 1;
|
|
1570
|
+
}
|
|
1571
|
+
observed.add(candidate.toLocaleLowerCase());
|
|
1572
|
+
return {
|
|
1573
|
+
name: candidate
|
|
1574
|
+
};
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
function spreadsheetTableDeleteRemovesSemanticRow(table, start, end) {
|
|
1578
|
+
return Boolean(table.headerRow && start <= table.range.row[0] && end >= table.range.row[0] || table.totalsRow && start <= table.range.row[1] && end >= table.range.row[1]);
|
|
1579
|
+
}
|
|
1580
|
+
function spreadsheetTableStructureChangeFromOperation(operation) {
|
|
1581
|
+
if (!spreadsheet_table_reconciliation_isRecord(operation.value)) return null;
|
|
1582
|
+
if ('insertRowCol' === operation.op) {
|
|
1583
|
+
const { count, direction, index, type } = operation.value;
|
|
1584
|
+
const change = {
|
|
1585
|
+
axis: 'column' === type ? 'column' : 'row',
|
|
1586
|
+
count: Number(count),
|
|
1587
|
+
direction: 'rightbottom' === direction ? 'rightbottom' : 'lefttop',
|
|
1588
|
+
index: Number(index),
|
|
1589
|
+
kind: 'insert'
|
|
1590
|
+
};
|
|
1591
|
+
return ('column' === type || 'row' === type) && ('lefttop' === direction || 'rightbottom' === direction) && validSpreadsheetTableStructureChange(change) ? change : null;
|
|
1592
|
+
}
|
|
1593
|
+
if ('deleteRowCol' === operation.op) {
|
|
1594
|
+
const { end, start, type } = operation.value;
|
|
1595
|
+
const change = {
|
|
1596
|
+
axis: 'column' === type ? 'column' : 'row',
|
|
1597
|
+
end: Number(end),
|
|
1598
|
+
kind: 'delete',
|
|
1599
|
+
start: Number(start)
|
|
1600
|
+
};
|
|
1601
|
+
return ('column' === type || 'row' === type) && validSpreadsheetTableStructureChange(change) ? change : null;
|
|
1602
|
+
}
|
|
1603
|
+
return null;
|
|
1604
|
+
}
|
|
1605
|
+
function spreadsheetCellCoordinateFromOperation(operation) {
|
|
1606
|
+
if ('data' !== operation.path[0] || operation.path.length < 3) return null;
|
|
1607
|
+
const row = operation.path[1];
|
|
1608
|
+
const column = operation.path[2];
|
|
1609
|
+
return Number.isSafeInteger(row) && Number(row) >= 0 && Number.isSafeInteger(column) && Number(column) >= 0 ? {
|
|
1610
|
+
column: Number(column),
|
|
1611
|
+
row: Number(row)
|
|
1612
|
+
} : null;
|
|
1613
|
+
}
|
|
1614
|
+
function validSpreadsheetTableStructureChange(change) {
|
|
1615
|
+
if ('insert' === change.kind) return Number.isSafeInteger(change.index) && change.index >= 0 && Number.isSafeInteger(change.count) && change.count > 0;
|
|
1616
|
+
return Number.isSafeInteger(change.start) && change.start >= 0 && Number.isSafeInteger(change.end) && change.end >= change.start;
|
|
1617
|
+
}
|
|
1618
|
+
function sourceSheetForReconciliation(sheet, sourceSheets, index) {
|
|
1619
|
+
return (sheet.id ? sourceSheets.find((candidate)=>candidate.id === sheet.id) : void 0) ?? sourceSheets[index];
|
|
1620
|
+
}
|
|
1621
|
+
function spreadsheetSheetCellReader(sheet) {
|
|
1622
|
+
if (void 0 !== sheet.data) return (row, column)=>sheet.data?.[row]?.[column] ?? null;
|
|
1623
|
+
const cells = new Map((sheet.celldata ?? []).map((entry)=>[
|
|
1624
|
+
`${entry.r}:${entry.c}`,
|
|
1625
|
+
entry.v
|
|
1626
|
+
]));
|
|
1627
|
+
return (row, column)=>cells.get(`${row}:${column}`) ?? null;
|
|
1628
|
+
}
|
|
1629
|
+
function stampSpreadsheetTableHeaderCells(sheet, updates) {
|
|
1630
|
+
if (!updates.length) return sheet;
|
|
1631
|
+
if (void 0 !== sheet.data) {
|
|
1632
|
+
const data = [];
|
|
1633
|
+
data.length = sheet.data.length;
|
|
1634
|
+
for (const [row, value] of sparseArrayEntries(sheet.data))data[row] = value;
|
|
1635
|
+
const mutableRows = new Map();
|
|
1636
|
+
for (const update of updates){
|
|
1637
|
+
let row = mutableRows.get(update.row);
|
|
1638
|
+
if (!row) {
|
|
1639
|
+
const source = data[update.row];
|
|
1640
|
+
row = [];
|
|
1641
|
+
row.length = source?.length ?? 0;
|
|
1642
|
+
for (const column of sparseArrayIndexes(source))row[column] = source?.[column];
|
|
1643
|
+
mutableRows.set(update.row, row);
|
|
1644
|
+
data[update.row] = row;
|
|
1645
|
+
}
|
|
1646
|
+
row[update.column] = stampSpreadsheetTableHeaderCell(row[update.column], update.name);
|
|
1647
|
+
}
|
|
1648
|
+
return {
|
|
1649
|
+
...sheet,
|
|
1650
|
+
data
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
const celldata = [
|
|
1654
|
+
...sheet.celldata ?? []
|
|
1655
|
+
];
|
|
1656
|
+
const indexes = new Map(celldata.map((entry, index)=>[
|
|
1657
|
+
`${entry.r}:${entry.c}`,
|
|
1658
|
+
index
|
|
1659
|
+
]));
|
|
1660
|
+
for (const update of updates){
|
|
1661
|
+
const key = `${update.row}:${update.column}`;
|
|
1662
|
+
const index = indexes.get(key);
|
|
1663
|
+
const source = void 0 === index ? void 0 : celldata[index];
|
|
1664
|
+
const entry = {
|
|
1665
|
+
r: update.row,
|
|
1666
|
+
c: update.column,
|
|
1667
|
+
v: stampSpreadsheetTableHeaderCell(source?.v, update.name)
|
|
1668
|
+
};
|
|
1669
|
+
if (void 0 === index) {
|
|
1670
|
+
indexes.set(key, celldata.length);
|
|
1671
|
+
celldata.push(entry);
|
|
1672
|
+
} else celldata[index] = entry;
|
|
1673
|
+
}
|
|
1674
|
+
return {
|
|
1675
|
+
...sheet,
|
|
1676
|
+
celldata
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
function stampSpreadsheetTableHeaderCell(cell, name) {
|
|
1680
|
+
return {
|
|
1681
|
+
...cell ?? {},
|
|
1682
|
+
m: name,
|
|
1683
|
+
v: name
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
function spreadsheetCellText(cell) {
|
|
1687
|
+
const value = cell?.m ?? cell?.v;
|
|
1688
|
+
return null == value ? '' : String(value);
|
|
1689
|
+
}
|
|
1690
|
+
function validSpreadsheetTableColumnName(name) {
|
|
1691
|
+
const characters = Array.from(name);
|
|
1692
|
+
return name.trim() === name && characters.length >= 1 && characters.length <= 255 && !characters.some((character)=>/\p{Cc}/u.test(character) || '\uFFFE' === character || '\uFFFF' === character);
|
|
1693
|
+
}
|
|
1694
|
+
function truncateSpreadsheetTableColumnName(value, maximum) {
|
|
1695
|
+
return Array.from(value).slice(0, maximum).join('');
|
|
1696
|
+
}
|
|
1697
|
+
function sameSpreadsheetTableColumns(left, right) {
|
|
1698
|
+
return left.length === right.length && left.every((column, index)=>column.name === right[index]?.name);
|
|
1699
|
+
}
|
|
1700
|
+
function spreadsheet_table_reconciliation_isRecord(value) {
|
|
1701
|
+
return Boolean(value && 'object' == typeof value && !Array.isArray(value));
|
|
1702
|
+
}
|
|
1360
1703
|
const spreadsheetFontSizes = [
|
|
1361
1704
|
9,
|
|
1362
1705
|
10,
|
|
@@ -1622,7 +1965,7 @@ function spreadsheetSheetsFromFortune(sheets, sourceSheets, operations = []) {
|
|
|
1622
1965
|
incremental: true,
|
|
1623
1966
|
operationCount: operations.length
|
|
1624
1967
|
});
|
|
1625
|
-
return incremental.sheets;
|
|
1968
|
+
return reconcileSpreadsheetTablesAfterFortune(incremental.sheets, sourceSheets, operations);
|
|
1626
1969
|
}
|
|
1627
1970
|
const projected = sheets.map((sheet, index)=>{
|
|
1628
1971
|
const source = (sheet.id ? sourceSheets.find((candidate)=>candidate.id === sheet.id) : void 0) ?? sourceSheets[index];
|
|
@@ -1651,7 +1994,7 @@ function spreadsheetSheetsFromFortune(sheets, sourceSheets, operations = []) {
|
|
|
1651
1994
|
incremental: false,
|
|
1652
1995
|
operationCount: operations.length
|
|
1653
1996
|
});
|
|
1654
|
-
return projected;
|
|
1997
|
+
return reconcileSpreadsheetTablesAfterFortune(projected, sourceSheets, operations);
|
|
1655
1998
|
}
|
|
1656
1999
|
function recordSpreadsheetControlledProjectionMeasure(start, end, detail) {
|
|
1657
2000
|
try {
|
|
@@ -2289,6 +2632,12 @@ const spreadsheetRibbonTabs = [
|
|
|
2289
2632
|
label: '视图'
|
|
2290
2633
|
}
|
|
2291
2634
|
];
|
|
2635
|
+
const spreadsheetTableDesignRibbonTab = {
|
|
2636
|
+
id: 'tableDesign',
|
|
2637
|
+
label: '表格设计',
|
|
2638
|
+
compactLabel: '设计',
|
|
2639
|
+
contextual: true
|
|
2640
|
+
};
|
|
2292
2641
|
const spreadsheetCommandCatalog = {
|
|
2293
2642
|
undo: {
|
|
2294
2643
|
id: 'history.undo',
|
|
@@ -3058,6 +3407,22 @@ const spreadsheetCommandCatalog = {
|
|
|
3058
3407
|
group: 'charts'
|
|
3059
3408
|
}
|
|
3060
3409
|
},
|
|
3410
|
+
table: {
|
|
3411
|
+
id: 'insert.table',
|
|
3412
|
+
label: '表格',
|
|
3413
|
+
location: {
|
|
3414
|
+
area: 'ribbon',
|
|
3415
|
+
tab: 'insert',
|
|
3416
|
+
group: 'tables'
|
|
3417
|
+
},
|
|
3418
|
+
shortcut: {
|
|
3419
|
+
label: 'Cmd/Ctrl+T',
|
|
3420
|
+
aria: 'Control+T Meta+T',
|
|
3421
|
+
editor: [
|
|
3422
|
+
'Mod-t'
|
|
3423
|
+
]
|
|
3424
|
+
}
|
|
3425
|
+
},
|
|
3061
3426
|
hyperlink: {
|
|
3062
3427
|
id: 'insert.hyperlink',
|
|
3063
3428
|
label: '超链接',
|
|
@@ -5048,11 +5413,15 @@ function canApplySpreadsheetCellMerge(sheet, range, command) {
|
|
|
5048
5413
|
const merged = spreadsheetMergesIntersectingRange(sheet, normalized);
|
|
5049
5414
|
if ('unmerge-cells' === command || 'unmerge-and-fill' === command) return merged.length > 0;
|
|
5050
5415
|
if (merged.length > 0) return false;
|
|
5416
|
+
if (spreadsheetMergeIntersectsTable(sheet, normalized)) return false;
|
|
5051
5417
|
const rowCount = normalized.row[1] - normalized.row[0] + 1;
|
|
5052
5418
|
const columnCount = normalized.column[1] - normalized.column[0] + 1;
|
|
5053
5419
|
if ('merge-across' === command) return columnCount > 1;
|
|
5054
5420
|
return rowCount * columnCount > 1;
|
|
5055
5421
|
}
|
|
5422
|
+
function spreadsheetMergeIntersectsTable(sheet, range) {
|
|
5423
|
+
return (sheet.tables ?? []).some((table)=>table.range.row[0] <= range.row[1] && table.range.row[1] >= range.row[0] && table.range.column[0] <= range.column[1] && table.range.column[1] >= range.column[0]);
|
|
5424
|
+
}
|
|
5056
5425
|
function spreadsheetCellMergeApiCalls(sheet, sheetId, range, command) {
|
|
5057
5426
|
if (!canApplySpreadsheetCellMerge(sheet, range, command) || !sheet) return [];
|
|
5058
5427
|
const normalized = normalizeSpreadsheetCellMergeRange(range);
|
|
@@ -5991,147 +6360,1040 @@ function spreadsheetSelectionAfterStructureDeletion(selection, axis, extent, sta
|
|
|
5991
6360
|
}
|
|
5992
6361
|
};
|
|
5993
6362
|
}
|
|
5994
|
-
function
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6363
|
+
function spreadsheetAutoFilterRange(sheet, selection) {
|
|
6364
|
+
const range = spreadsheetSelectionOrCurrentRegion(sheet, selection);
|
|
6365
|
+
if (!range || !validSpreadsheetAutoFilterRange(sheet, range)) return null;
|
|
6366
|
+
return range;
|
|
6367
|
+
}
|
|
6368
|
+
function spreadsheetSelectionOrCurrentRegion(sheet, selection) {
|
|
6369
|
+
if (sheet.isPivotTable || sheet.pivotTables?.length) return null;
|
|
6370
|
+
const normalized = normalizeAutoFilterSelection(selection);
|
|
6371
|
+
return normalized.row[0] !== normalized.row[1] ? normalized : spreadsheetCurrentRegion(sheet, normalized);
|
|
6372
|
+
}
|
|
6373
|
+
function spreadsheetAutoFilterHeaderColumn(sheet, selection) {
|
|
6374
|
+
const range = normalizedFilterSelection(sheet?.filter_select);
|
|
6375
|
+
if (!sheet || !range) return null;
|
|
6376
|
+
const row = spreadsheet_auto_filter_finiteIndex(selection.row_focus, selection.row[0]);
|
|
6377
|
+
const column = spreadsheet_auto_filter_finiteIndex(selection.column_focus, selection.column[0]);
|
|
6378
|
+
if (row !== range.row[0] || column < range.column[0] || column > range.column[1]) return null;
|
|
6379
|
+
return column;
|
|
6380
|
+
}
|
|
6381
|
+
function toggleSpreadsheetAutoFilter(content, sheetId, selection) {
|
|
6382
|
+
const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
|
|
6383
|
+
const sheet = content.sheets[sheetIndex];
|
|
6384
|
+
if (!sheet) return null;
|
|
6385
|
+
const nextSheet = sheet.filter_select ? spreadsheetSheetWithoutAutoFilter(sheet) : spreadsheetSheetWithAutoFilter(sheet, selection);
|
|
6386
|
+
if (!nextSheet) return null;
|
|
6387
|
+
const sheets = [
|
|
6388
|
+
...content.sheets
|
|
6389
|
+
];
|
|
6390
|
+
sheets[sheetIndex] = {
|
|
6391
|
+
...nextSheet,
|
|
6392
|
+
luckysheet_select_save: [
|
|
6393
|
+
finiteSpreadsheetSelection(selection)
|
|
6394
|
+
]
|
|
6395
|
+
};
|
|
6396
|
+
return {
|
|
6397
|
+
...content,
|
|
6398
|
+
sheets
|
|
6399
|
+
};
|
|
6400
|
+
}
|
|
6401
|
+
function spreadsheetSheetWithAutoFilter(sheet, selection) {
|
|
6402
|
+
const range = spreadsheetAutoFilterRange(sheet, selection);
|
|
6403
|
+
if (!range) return null;
|
|
6404
|
+
return {
|
|
6405
|
+
...sheet,
|
|
6406
|
+
filter: {},
|
|
6407
|
+
filter_select: {
|
|
6408
|
+
row: [
|
|
6409
|
+
...range.row
|
|
6410
|
+
],
|
|
6411
|
+
column: [
|
|
6412
|
+
...range.column
|
|
6413
|
+
]
|
|
6414
|
+
}
|
|
6415
|
+
};
|
|
6416
|
+
}
|
|
6417
|
+
function spreadsheetSheetWithoutAutoFilter(sheet) {
|
|
6418
|
+
const hiddenByFilter = spreadsheetFilterHiddenRows(sheet.filter);
|
|
6419
|
+
const rowhidden = {
|
|
6420
|
+
...sheet.config?.rowhidden
|
|
6421
|
+
};
|
|
6422
|
+
for (const row of hiddenByFilter)delete rowhidden[row];
|
|
6423
|
+
const config = sheet.config ? {
|
|
6424
|
+
...sheet.config,
|
|
6425
|
+
rowhidden
|
|
6426
|
+
} : void 0;
|
|
6427
|
+
const { filter: _filter, filter_select: _selection, ...remaining } = sheet;
|
|
6428
|
+
return {
|
|
6429
|
+
...remaining,
|
|
6430
|
+
config
|
|
6431
|
+
};
|
|
6432
|
+
}
|
|
6433
|
+
function spreadsheetFilterHiddenRows(filter) {
|
|
6434
|
+
const rows = new Set();
|
|
6435
|
+
for (const value of Object.values(filter ?? {})){
|
|
6436
|
+
if (!value || 'object' != typeof value) continue;
|
|
6437
|
+
const rowhidden = value.rowhidden;
|
|
6438
|
+
if (rowhidden && 'object' == typeof rowhidden) for (const row of Object.keys(rowhidden))rows.add(row);
|
|
6439
|
+
}
|
|
6440
|
+
return rows;
|
|
6441
|
+
}
|
|
6442
|
+
function spreadsheetCurrentRegion(sheet, selection) {
|
|
6443
|
+
const cells = spreadsheetCellReader(sheet);
|
|
6444
|
+
const bounds = spreadsheetUsedBounds(sheet);
|
|
6445
|
+
let startRow = selection.row[0];
|
|
6446
|
+
let endRow = selection.row[1];
|
|
6447
|
+
let startColumn = selection.column[0];
|
|
6448
|
+
let endColumn = selection.column[1];
|
|
6449
|
+
if (startRow > bounds.lastRow || startColumn > bounds.lastColumn || !spreadsheet_auto_filter_spreadsheetCellHasContent(cells(startRow, startColumn))) return null;
|
|
6450
|
+
let changed = true;
|
|
6451
|
+
while(changed){
|
|
6452
|
+
changed = false;
|
|
6453
|
+
while(startColumn > 0 && spreadsheetColumnHasContent(cells, startColumn - 1, startRow, endRow)){
|
|
6454
|
+
startColumn -= 1;
|
|
6455
|
+
changed = true;
|
|
6456
|
+
}
|
|
6457
|
+
while(endColumn < bounds.lastColumn && spreadsheetColumnHasContent(cells, endColumn + 1, startRow, endRow)){
|
|
6458
|
+
endColumn += 1;
|
|
6459
|
+
changed = true;
|
|
6460
|
+
}
|
|
6461
|
+
while(startRow > 0 && spreadsheetRowHasContent(cells, startRow - 1, startColumn, endColumn)){
|
|
6462
|
+
startRow -= 1;
|
|
6463
|
+
changed = true;
|
|
6464
|
+
}
|
|
6465
|
+
while(endRow < bounds.lastRow && spreadsheetRowHasContent(cells, endRow + 1, startColumn, endColumn)){
|
|
6466
|
+
endRow += 1;
|
|
6467
|
+
changed = true;
|
|
6468
|
+
}
|
|
6469
|
+
}
|
|
6470
|
+
return {
|
|
6471
|
+
row: [
|
|
6472
|
+
startRow,
|
|
6473
|
+
endRow
|
|
6474
|
+
],
|
|
6475
|
+
column: [
|
|
6476
|
+
startColumn,
|
|
6477
|
+
endColumn
|
|
6478
|
+
]
|
|
6479
|
+
};
|
|
6480
|
+
}
|
|
6481
|
+
function validSpreadsheetAutoFilterRange(sheet, range) {
|
|
6482
|
+
if (range.row[1] <= range.row[0]) return false;
|
|
6483
|
+
if (spreadsheetAutoFilterIntersectsTable(sheet, range)) return false;
|
|
6484
|
+
const cells = spreadsheetCellReader(sheet);
|
|
6485
|
+
if (!spreadsheetRowHasContent(cells, range.row[0], range.column[0], range.column[1])) return false;
|
|
6486
|
+
let dataFound = false;
|
|
6487
|
+
for(let row = range.row[0] + 1; row <= range.row[1]; row += 1)if (spreadsheetRowHasContent(cells, row, range.column[0], range.column[1])) {
|
|
6488
|
+
dataFound = true;
|
|
6489
|
+
break;
|
|
6490
|
+
}
|
|
6491
|
+
return dataFound && !spreadsheetRangeIntersectsMerge(sheet, range);
|
|
6492
|
+
}
|
|
6493
|
+
function spreadsheetAutoFilterIntersectsTable(sheet, range) {
|
|
6494
|
+
return (sheet.tables ?? []).some((table)=>table.range.row[0] <= range.row[1] && table.range.row[1] >= range.row[0] && table.range.column[0] <= range.column[1] && table.range.column[1] >= range.column[0]);
|
|
6495
|
+
}
|
|
6496
|
+
function spreadsheetRangeIntersectsMerge(sheet, range) {
|
|
6497
|
+
return Object.values(sheet.config?.merge ?? {}).some((merge)=>{
|
|
6498
|
+
const endRow = merge.r + Math.max(merge.rs, 1) - 1;
|
|
6499
|
+
const endColumn = merge.c + Math.max(merge.cs, 1) - 1;
|
|
6500
|
+
return merge.r <= range.row[1] && endRow >= range.row[0] && merge.c <= range.column[1] && endColumn >= range.column[0];
|
|
6501
|
+
});
|
|
6502
|
+
}
|
|
6503
|
+
function spreadsheetRowHasContent(cellAt, row, startColumn, endColumn) {
|
|
6504
|
+
for(let column = startColumn; column <= endColumn; column += 1)if (spreadsheet_auto_filter_spreadsheetCellHasContent(cellAt(row, column))) return true;
|
|
6505
|
+
return false;
|
|
6506
|
+
}
|
|
6507
|
+
function spreadsheetColumnHasContent(cellAt, column, startRow, endRow) {
|
|
6508
|
+
for(let row = startRow; row <= endRow; row += 1)if (spreadsheet_auto_filter_spreadsheetCellHasContent(cellAt(row, column))) return true;
|
|
6509
|
+
return false;
|
|
6510
|
+
}
|
|
6511
|
+
function spreadsheet_auto_filter_spreadsheetCellHasContent(cell) {
|
|
6512
|
+
if (!cell) return false;
|
|
6513
|
+
return [
|
|
6514
|
+
cell.v,
|
|
6515
|
+
cell.m,
|
|
6516
|
+
cell.f
|
|
6517
|
+
].some((value)=>null != value && '' !== value);
|
|
6518
|
+
}
|
|
6519
|
+
function spreadsheetCellReader(sheet) {
|
|
6520
|
+
if (sheet.data) return (row, column)=>sheet.data?.[row]?.[column] ?? null;
|
|
6521
|
+
const cells = new Map((sheet.celldata ?? []).map((cell)=>[
|
|
6522
|
+
`${cell.r}:${cell.c}`,
|
|
6523
|
+
cell.v
|
|
6524
|
+
]));
|
|
6525
|
+
return (row, column)=>cells.get(`${row}:${column}`) ?? null;
|
|
6526
|
+
}
|
|
6527
|
+
function spreadsheetUsedBounds(sheet) {
|
|
6528
|
+
let lastRow = Math.max((sheet.data?.length ?? 1) - 1, 0);
|
|
6529
|
+
let lastColumn = Math.max(sparseMatrixColumnCount(sheet.data) - 1, 0);
|
|
6530
|
+
for (const cell of sheet.celldata ?? []){
|
|
6531
|
+
lastRow = Math.max(lastRow, cell.r);
|
|
6532
|
+
lastColumn = Math.max(lastColumn, cell.c);
|
|
6533
|
+
}
|
|
6534
|
+
return {
|
|
6535
|
+
lastColumn,
|
|
6536
|
+
lastRow
|
|
6537
|
+
};
|
|
6538
|
+
}
|
|
6539
|
+
function normalizeAutoFilterSelection(selection) {
|
|
6540
|
+
const startRow = spreadsheet_auto_filter_finiteIndex(selection.row[0], 0);
|
|
6541
|
+
const endRow = spreadsheet_auto_filter_finiteIndex(selection.row[1], startRow);
|
|
6542
|
+
const startColumn = spreadsheet_auto_filter_finiteIndex(selection.column[0], 0);
|
|
6543
|
+
const endColumn = spreadsheet_auto_filter_finiteIndex(selection.column[1], startColumn);
|
|
6544
|
+
return {
|
|
6545
|
+
row: [
|
|
6546
|
+
Math.min(startRow, endRow),
|
|
6547
|
+
Math.max(startRow, endRow)
|
|
6548
|
+
],
|
|
6549
|
+
column: [
|
|
6550
|
+
Math.min(startColumn, endColumn),
|
|
6551
|
+
Math.max(startColumn, endColumn)
|
|
6552
|
+
]
|
|
6553
|
+
};
|
|
6554
|
+
}
|
|
6555
|
+
function normalizedFilterSelection(selection) {
|
|
6556
|
+
if (!selection?.row?.length || !selection.column?.length) return null;
|
|
6557
|
+
return normalizeAutoFilterSelection(selection);
|
|
6558
|
+
}
|
|
6559
|
+
function spreadsheet_auto_filter_finiteIndex(value, fallback) {
|
|
6560
|
+
return 'number' == typeof value && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : fallback;
|
|
6561
|
+
}
|
|
6562
|
+
const ACCENTS = [
|
|
6563
|
+
'#64748b',
|
|
6564
|
+
'#2563eb',
|
|
6565
|
+
'#0f766e',
|
|
6566
|
+
'#7c3aed',
|
|
6567
|
+
'#c2410c',
|
|
6568
|
+
'#be123c',
|
|
6569
|
+
'#15803d'
|
|
6570
|
+
];
|
|
6571
|
+
const DARK_ACCENTS = [
|
|
6572
|
+
'#1e293b',
|
|
6573
|
+
'#1e3a8a',
|
|
6574
|
+
'#134e4a',
|
|
6575
|
+
'#4c1d95',
|
|
6576
|
+
'#7c2d12',
|
|
6577
|
+
'#881337',
|
|
6578
|
+
'#14532d',
|
|
6579
|
+
'#0f172a',
|
|
6580
|
+
'#312e81',
|
|
6581
|
+
'#3f3f46',
|
|
6582
|
+
'#422006'
|
|
6583
|
+
];
|
|
6584
|
+
let cachedChoices = null;
|
|
6585
|
+
function spreadsheetTableStyleChoices() {
|
|
6586
|
+
cachedChoices ??= Object.freeze([
|
|
6587
|
+
...tableStyleFamilyChoices('light', 21),
|
|
6588
|
+
...tableStyleFamilyChoices('medium', 28),
|
|
6589
|
+
...tableStyleFamilyChoices('dark', 11)
|
|
6590
|
+
]);
|
|
6591
|
+
return cachedChoices;
|
|
6592
|
+
}
|
|
6593
|
+
function spreadsheetTableStylePalette(style) {
|
|
6594
|
+
if ('none' === style.family) return null;
|
|
6595
|
+
const maximum = 'light' === style.family ? 21 : 'medium' === style.family ? 28 : 11;
|
|
6596
|
+
if (!Number.isInteger(style.number) || style.number < 1 || style.number > maximum) return null;
|
|
6597
|
+
if ('light' === style.family) return lightPalette(style.number);
|
|
6598
|
+
if ('medium' === style.family) return mediumPalette(style.number);
|
|
6599
|
+
return darkPalette(style.number);
|
|
6600
|
+
}
|
|
6601
|
+
function createSpreadsheetTableRenderResolver(tables) {
|
|
6602
|
+
const renderable = tables.filter((table)=>spreadsheetTableStylePalette(table.style)).slice().sort((left, right)=>left.range.row[0] - right.range.row[0] || left.range.column[0] - right.range.column[0]);
|
|
6603
|
+
let cachedRow = -1;
|
|
6604
|
+
let rowTables = [];
|
|
6605
|
+
return (row, column)=>{
|
|
6606
|
+
if (row !== cachedRow) {
|
|
6607
|
+
cachedRow = row;
|
|
6608
|
+
rowTables = renderable.filter((table)=>row >= table.range.row[0] && row <= table.range.row[1]);
|
|
6609
|
+
}
|
|
6610
|
+
const table = rowTables.find((candidate)=>column >= candidate.range.column[0] && column <= candidate.range.column[1]);
|
|
6611
|
+
return table ? spreadsheetTableCellRenderStyle(table, row, column) : null;
|
|
6612
|
+
};
|
|
6613
|
+
}
|
|
6614
|
+
function spreadsheetTableCellRenderStyle(table, row, column) {
|
|
6615
|
+
const palette = spreadsheetTableStylePalette(table.style);
|
|
6616
|
+
if (!palette) return null;
|
|
6617
|
+
const header = table.headerRow && row === table.range.row[0];
|
|
6618
|
+
const totals = table.totalsRow && row === table.range.row[1];
|
|
6619
|
+
const dataStart = table.range.row[0] + Number(table.headerRow);
|
|
6620
|
+
const dataIndex = Math.max(0, row - dataStart);
|
|
6621
|
+
const secondary = table.showRowStripes && dataIndex % 2 === 1;
|
|
6622
|
+
let background = header ? palette.header : totals ? palette.total : secondary ? palette.secondaryRow : palette.primaryRow;
|
|
6623
|
+
if (!header && !totals && table.showColumnStripes && (column - table.range.column[0]) % 2 === 1) background = mixHex(background, palette.stripeColumn, 0.42);
|
|
6624
|
+
const firstColumn = column === table.range.column[0];
|
|
6625
|
+
const lastColumn = column === table.range.column[1];
|
|
6626
|
+
return {
|
|
6627
|
+
background,
|
|
6628
|
+
bold: header || totals || table.showFirstColumn && firstColumn || table.showLastColumn && lastColumn,
|
|
6629
|
+
borderColor: palette.border,
|
|
6630
|
+
role: header ? 'header' : totals ? 'totals' : 'body',
|
|
6631
|
+
tableId: table.id,
|
|
6632
|
+
textColor: header ? palette.headerText : totals ? palette.totalText : palette.text
|
|
6633
|
+
};
|
|
6634
|
+
}
|
|
6635
|
+
function tableStyleFamilyChoices(family, count) {
|
|
6636
|
+
return Array.from({
|
|
6637
|
+
length: count
|
|
6638
|
+
}, (_, index)=>{
|
|
6639
|
+
const number = index + 1;
|
|
6640
|
+
const style = {
|
|
6641
|
+
family,
|
|
6642
|
+
number
|
|
6643
|
+
};
|
|
6644
|
+
return {
|
|
6645
|
+
label: `${familyLabel(family)} ${number}`,
|
|
6646
|
+
ooxmlName: `TableStyle${capitalize(family)}${number}`,
|
|
6647
|
+
palette: spreadsheetTableStylePalette(style),
|
|
6648
|
+
style
|
|
6649
|
+
};
|
|
6650
|
+
});
|
|
6651
|
+
}
|
|
6652
|
+
function lightPalette(number) {
|
|
6653
|
+
const accent = ACCENTS[(number - 1) % ACCENTS.length] ?? ACCENTS[0];
|
|
6654
|
+
const variant = Math.floor((number - 1) / ACCENTS.length);
|
|
6655
|
+
const headerWeight = [
|
|
6656
|
+
0.84,
|
|
6657
|
+
0.73,
|
|
6658
|
+
0.62
|
|
6659
|
+
][variant] ?? 0.72;
|
|
6660
|
+
return {
|
|
6661
|
+
border: mixHex(accent, '#ffffff', 0.5),
|
|
6662
|
+
header: mixHex(accent, '#ffffff', headerWeight),
|
|
6663
|
+
headerText: mixHex(accent, '#0f172a', 0.38),
|
|
6664
|
+
primaryRow: '#ffffff',
|
|
6665
|
+
secondaryRow: mixHex(accent, '#ffffff', 0.9 - 0.025 * variant),
|
|
6666
|
+
stripeColumn: mixHex(accent, '#ffffff', 0.82),
|
|
6667
|
+
text: '#1f2937',
|
|
6668
|
+
total: mixHex(accent, '#ffffff', 0.78),
|
|
6669
|
+
totalText: '#172033'
|
|
6670
|
+
};
|
|
6671
|
+
}
|
|
6672
|
+
function mediumPalette(number) {
|
|
6673
|
+
const accent = ACCENTS[(number - 1) % ACCENTS.length] ?? ACCENTS[0];
|
|
6674
|
+
const variant = Math.floor((number - 1) / ACCENTS.length);
|
|
6675
|
+
const header = mixHex(accent, '#111827', 0.08 * variant);
|
|
6676
|
+
return {
|
|
6677
|
+
border: mixHex(accent, '#ffffff', 0.34),
|
|
6678
|
+
header,
|
|
6679
|
+
headerText: '#ffffff',
|
|
6680
|
+
primaryRow: '#ffffff',
|
|
6681
|
+
secondaryRow: mixHex(accent, '#ffffff', 0.86 - 0.02 * variant),
|
|
6682
|
+
stripeColumn: mixHex(accent, '#ffffff', 0.76),
|
|
6683
|
+
text: '#172033',
|
|
6684
|
+
total: mixHex(accent, '#ffffff', 0.72),
|
|
6685
|
+
totalText: mixHex(accent, '#111827', 0.48)
|
|
6686
|
+
};
|
|
6687
|
+
}
|
|
6688
|
+
function darkPalette(number) {
|
|
6689
|
+
const accent = DARK_ACCENTS[number - 1] ?? DARK_ACCENTS[0];
|
|
6690
|
+
return {
|
|
6691
|
+
border: mixHex(accent, '#ffffff', 0.32),
|
|
6692
|
+
header: accent,
|
|
6693
|
+
headerText: '#ffffff',
|
|
6694
|
+
primaryRow: mixHex(accent, '#ffffff', 0.9),
|
|
6695
|
+
secondaryRow: mixHex(accent, '#ffffff', 0.78),
|
|
6696
|
+
stripeColumn: mixHex(accent, '#ffffff', 0.68),
|
|
6697
|
+
text: '#172033',
|
|
6698
|
+
total: mixHex(accent, '#ffffff', 0.62),
|
|
6699
|
+
totalText: mixHex(accent, '#111827', 0.34)
|
|
6700
|
+
};
|
|
6701
|
+
}
|
|
6702
|
+
function mixHex(left, right, rightWeight) {
|
|
6703
|
+
const weight = Math.min(1, Math.max(0, rightWeight));
|
|
6704
|
+
const leftRgb = parseHex(left);
|
|
6705
|
+
const rightRgb = parseHex(right);
|
|
6706
|
+
return `#${leftRgb.map((value, index)=>Math.round(value * (1 - weight) + (rightRgb[index] ?? value) * weight).toString(16).padStart(2, '0')).join('')}`;
|
|
6707
|
+
}
|
|
6708
|
+
function parseHex(value) {
|
|
6709
|
+
const hex = value.replace(/^#/, '');
|
|
6710
|
+
return [
|
|
6711
|
+
0,
|
|
6712
|
+
2,
|
|
6713
|
+
4
|
|
6714
|
+
].map((offset)=>Number.parseInt(hex.slice(offset, offset + 2), 16));
|
|
6715
|
+
}
|
|
6716
|
+
function familyLabel(family) {
|
|
6717
|
+
if ('light' === family) return '浅色';
|
|
6718
|
+
if ('medium' === family) return '中等';
|
|
6719
|
+
return '深色';
|
|
6720
|
+
}
|
|
6721
|
+
function capitalize(value) {
|
|
6722
|
+
return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
|
|
6723
|
+
}
|
|
6724
|
+
const MAX_TABLE_CONVERSION_DENSE_FOOTPRINT = 1000000;
|
|
6725
|
+
function canMaterializeSpreadsheetTableAppearance(table) {
|
|
6726
|
+
return 'none' === table.style.family || spreadsheet_cell_range_spreadsheetCellRangeArea(table.range) <= 100000;
|
|
6727
|
+
}
|
|
6728
|
+
function materializeSpreadsheetTableAppearance(content, sheetId, table) {
|
|
6729
|
+
if (!canMaterializeSpreadsheetTableAppearance(table)) return null;
|
|
6730
|
+
if ('none' === table.style.family) return content;
|
|
6731
|
+
const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
|
|
6732
|
+
const sheet = content.sheets[sheetIndex];
|
|
6733
|
+
const palette = spreadsheetTableStylePalette(table.style);
|
|
6734
|
+
if (!sheet || !palette) return null;
|
|
6735
|
+
const resolve = createSpreadsheetTableRenderResolver([
|
|
6736
|
+
table
|
|
6737
|
+
]);
|
|
6738
|
+
const styledSheet = shouldMaterializeSpreadsheetTableAsSparseCells(sheet, table) ? materializeSpreadsheetTableSparseCells(sheet, table, resolve) : materializeSpreadsheetTableMatrix(sheet, table, resolve);
|
|
6739
|
+
const sheets = [
|
|
6740
|
+
...content.sheets
|
|
6741
|
+
];
|
|
6742
|
+
sheets[sheetIndex] = styledSheet;
|
|
6743
|
+
return setSpreadsheetCellBorders({
|
|
6744
|
+
...content,
|
|
6745
|
+
sheets
|
|
6746
|
+
}, sheetId, table.range, {
|
|
6747
|
+
target: 'all',
|
|
6748
|
+
color: palette.border,
|
|
6749
|
+
style: 'thin'
|
|
6750
|
+
});
|
|
6751
|
+
}
|
|
6752
|
+
function shouldMaterializeSpreadsheetTableAsSparseCells(sheet, table) {
|
|
6753
|
+
if (void 0 === sheet.data) return true;
|
|
6754
|
+
const [startRow, endRow] = table.range.row;
|
|
6755
|
+
const requiredRowLength = table.range.column[1] + 1;
|
|
6756
|
+
let footprint = 0;
|
|
6757
|
+
let presentTableRows = 0;
|
|
6758
|
+
for (const [rowIndex, row] of sparseArrayEntries(sheet.data)){
|
|
6759
|
+
if (rowIndex >= startRow && rowIndex <= endRow) {
|
|
6760
|
+
presentTableRows += 1;
|
|
6761
|
+
footprint += Math.max(row.length, requiredRowLength);
|
|
6762
|
+
} else footprint += row.length;
|
|
6763
|
+
if (footprint > MAX_TABLE_CONVERSION_DENSE_FOOTPRINT) return true;
|
|
6764
|
+
}
|
|
6765
|
+
footprint += (endRow - startRow + 1 - presentTableRows) * requiredRowLength;
|
|
6766
|
+
return footprint > MAX_TABLE_CONVERSION_DENSE_FOOTPRINT;
|
|
6767
|
+
}
|
|
6768
|
+
function materializeSpreadsheetTableMatrix(sheet, table, resolve) {
|
|
6769
|
+
const source = sheet.data ?? [];
|
|
6770
|
+
const data = [];
|
|
6771
|
+
data.length = Math.max(source.length, table.range.row[1] + 1);
|
|
6772
|
+
for (const [row, value] of sparseArrayEntries(source))data[row] = value;
|
|
6773
|
+
for(let row = table.range.row[0]; row <= table.range.row[1]; row += 1){
|
|
6774
|
+
const sourceRow = source[row];
|
|
6775
|
+
const values = [];
|
|
6776
|
+
values.length = Math.max(sourceRow?.length ?? 0, table.range.column[1] + 1);
|
|
6777
|
+
for (const column of sparseArrayIndexes(sourceRow))values[column] = sourceRow?.[column];
|
|
6778
|
+
for(let column = table.range.column[0]; column <= table.range.column[1]; column += 1){
|
|
6779
|
+
const style = resolve(row, column);
|
|
6780
|
+
if (style) values[column] = spreadsheetCellWithTableAppearance(values[column], style);
|
|
6781
|
+
}
|
|
6782
|
+
data[row] = values;
|
|
6783
|
+
}
|
|
6784
|
+
return {
|
|
6785
|
+
...sheet,
|
|
6786
|
+
data
|
|
6787
|
+
};
|
|
6788
|
+
}
|
|
6789
|
+
function materializeSpreadsheetTableSparseCells(sheet, table, resolve) {
|
|
6790
|
+
const celldata = [];
|
|
6791
|
+
if (void 0 !== sheet.data) for (const [row, values] of sparseArrayEntries(sheet.data))for (const column of sparseArrayIndexes(values)){
|
|
6792
|
+
const cell = values[column];
|
|
6793
|
+
if (null != cell) celldata.push({
|
|
6794
|
+
c: column,
|
|
6795
|
+
r: row,
|
|
6796
|
+
v: cell
|
|
6797
|
+
});
|
|
6798
|
+
}
|
|
6799
|
+
else celldata.push(...sheet.celldata ?? []);
|
|
6800
|
+
const indexes = new Map(celldata.map((entry, index)=>[
|
|
6801
|
+
`${entry.r}:${entry.c}`,
|
|
6802
|
+
index
|
|
6803
|
+
]));
|
|
6804
|
+
for(let row = table.range.row[0]; row <= table.range.row[1]; row += 1)for(let column = table.range.column[0]; column <= table.range.column[1]; column += 1){
|
|
6805
|
+
const style = resolve(row, column);
|
|
6806
|
+
if (!style) continue;
|
|
6807
|
+
const key = `${row}:${column}`;
|
|
6808
|
+
const index = indexes.get(key);
|
|
6809
|
+
const cell = spreadsheetCellWithTableAppearance(void 0 === index ? void 0 : celldata[index]?.v, style);
|
|
6810
|
+
if (void 0 === index) {
|
|
6811
|
+
indexes.set(key, celldata.length);
|
|
6812
|
+
celldata.push({
|
|
6813
|
+
c: column,
|
|
6814
|
+
r: row,
|
|
6815
|
+
v: cell
|
|
6816
|
+
});
|
|
6817
|
+
} else celldata[index] = {
|
|
6818
|
+
c: column,
|
|
6819
|
+
r: row,
|
|
6820
|
+
v: cell
|
|
6821
|
+
};
|
|
6822
|
+
}
|
|
6823
|
+
celldata.sort((left, right)=>left.r - right.r || left.c - right.c);
|
|
6824
|
+
const { data: _data, ...metadata } = sheet;
|
|
6825
|
+
return {
|
|
6826
|
+
...metadata,
|
|
6827
|
+
celldata
|
|
6828
|
+
};
|
|
6829
|
+
}
|
|
6830
|
+
function spreadsheetCellWithTableAppearance(cell, style) {
|
|
6831
|
+
return {
|
|
6832
|
+
...cell ?? {},
|
|
6833
|
+
bg: style.background,
|
|
6834
|
+
fc: style.textColor,
|
|
6835
|
+
...style.bold ? {
|
|
6836
|
+
bl: 1
|
|
6837
|
+
} : {}
|
|
6838
|
+
};
|
|
6839
|
+
}
|
|
6840
|
+
function createSpreadsheetTableDialogSource(content, target) {
|
|
6841
|
+
const sheet = content.sheets.find((candidate)=>candidate.id === target.sheetId);
|
|
6842
|
+
if (!sheet) return null;
|
|
6843
|
+
const range = spreadsheetSelectionOrCurrentRegion(sheet, target.selection);
|
|
6844
|
+
if (!range) return null;
|
|
6845
|
+
let request = {
|
|
6846
|
+
headerRow: true,
|
|
6847
|
+
name: nextSpreadsheetTableName(content),
|
|
6848
|
+
range,
|
|
6849
|
+
sheetId: target.sheetId
|
|
6850
|
+
};
|
|
6851
|
+
if (!validateSpreadsheetTableRequest(content, request).ok) {
|
|
6852
|
+
request = {
|
|
6853
|
+
...request,
|
|
6854
|
+
headerRow: false
|
|
6855
|
+
};
|
|
6856
|
+
if (!validateSpreadsheetTableRequest(content, request).ok) return null;
|
|
6857
|
+
}
|
|
6858
|
+
const rangeReference = formatSpreadsheetCellRanges([
|
|
6859
|
+
range
|
|
6860
|
+
]);
|
|
6861
|
+
return {
|
|
6862
|
+
name: request.name,
|
|
6863
|
+
range,
|
|
6864
|
+
rangeReference,
|
|
6865
|
+
sheetId: target.sheetId,
|
|
6866
|
+
sheetName: sheet.name,
|
|
6867
|
+
value: {
|
|
6868
|
+
headerRow: request.headerRow,
|
|
6869
|
+
rangeReference
|
|
6870
|
+
}
|
|
6871
|
+
};
|
|
6872
|
+
}
|
|
6873
|
+
function spreadsheetTableRangeFromText(value) {
|
|
6874
|
+
const ranges = parseSpreadsheetCellRanges(value);
|
|
6875
|
+
return ranges?.length === 1 ? ranges[0] ?? null : null;
|
|
6876
|
+
}
|
|
6877
|
+
function validateSpreadsheetTableRequest(content, request) {
|
|
6878
|
+
const sheet = content.sheets.find((candidate)=>candidate.id === request.sheetId);
|
|
6879
|
+
if (!sheet) return tableError('sheet-not-found');
|
|
6880
|
+
if (sheet.isPivotTable || sheet.pivotTables?.length) return tableError('pivot-table');
|
|
6881
|
+
const range = spreadsheet_cell_range_normalizeSpreadsheetCellRange(request.range);
|
|
6882
|
+
if (!range) return tableError('invalid-range');
|
|
6883
|
+
const name = request.name.trim();
|
|
6884
|
+
if (!validSpreadsheetTableName(name)) return tableError('invalid-name');
|
|
6885
|
+
if (spreadsheetTableNameExists(content, name)) return tableError('name-conflict');
|
|
6886
|
+
const bounds = spreadsheetSheetBounds(sheet);
|
|
6887
|
+
if (range.row[1] > bounds.lastRow || range.column[1] > bounds.lastColumn) return tableError('out-of-bounds');
|
|
6888
|
+
const height = range.row[1] - range.row[0] + 1;
|
|
6889
|
+
if (height <= Number(request.headerRow)) return tableError('invalid-range');
|
|
6890
|
+
if (spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 100000) return tableError('range-too-large');
|
|
6891
|
+
if (spreadsheetTableIntersectsMerge(sheet, range)) return tableError('merged-range');
|
|
6892
|
+
if ((sheet.tables ?? []).some((table)=>spreadsheetCellRangesIntersect(table.range, range))) return tableError('table-overlap');
|
|
6893
|
+
const autoFilter = spreadsheet_cell_range_normalizeSpreadsheetCellRange(sheet.filter_select ?? {
|
|
6894
|
+
row: [],
|
|
6895
|
+
column: []
|
|
6896
|
+
});
|
|
6897
|
+
if (autoFilter && spreadsheetCellRangesIntersect(autoFilter, range)) return tableError('auto-filter-overlap');
|
|
6898
|
+
if (!canMutateSpreadsheetCellRanges(sheet, [
|
|
6899
|
+
range
|
|
6900
|
+
])) return tableError('protected-range');
|
|
6901
|
+
const style = request.style ?? {
|
|
6902
|
+
family: 'medium',
|
|
6903
|
+
number: 2
|
|
6904
|
+
};
|
|
6905
|
+
if (!validSpreadsheetTableStyle(style)) return tableError('invalid-style');
|
|
6906
|
+
const columns = spreadsheetTableColumnNames(sheet, range, request.headerRow);
|
|
6907
|
+
if (!columns.length || columns.some((column)=>!validTableColumnName(column))) return tableError('invalid-column-name');
|
|
6908
|
+
return {
|
|
6909
|
+
columns,
|
|
6910
|
+
name,
|
|
6911
|
+
ok: true,
|
|
6912
|
+
range,
|
|
6913
|
+
sheet
|
|
6914
|
+
};
|
|
6915
|
+
}
|
|
6916
|
+
function applySpreadsheetTable(content, request) {
|
|
6917
|
+
const validation = validateSpreadsheetTableRequest(content, request);
|
|
6918
|
+
if (!validation.ok) return null;
|
|
6919
|
+
const style = request.style ?? {
|
|
6920
|
+
family: 'medium',
|
|
6921
|
+
number: 2
|
|
6922
|
+
};
|
|
6923
|
+
const table = {
|
|
6924
|
+
id: createWorkId('spreadsheet-table'),
|
|
6925
|
+
name: validation.name,
|
|
6926
|
+
range: cloneRange(validation.range),
|
|
6927
|
+
columns: validation.columns.map((name)=>({
|
|
6928
|
+
name
|
|
6929
|
+
})),
|
|
6930
|
+
filters: [],
|
|
6931
|
+
headerRow: request.headerRow,
|
|
6932
|
+
totalsRow: false,
|
|
6933
|
+
style,
|
|
6934
|
+
showFirstColumn: false,
|
|
6935
|
+
showLastColumn: false,
|
|
6936
|
+
showRowStripes: 'none' !== style.family,
|
|
6937
|
+
showColumnStripes: false
|
|
6938
|
+
};
|
|
6939
|
+
const nextSheet = request.headerRow ? stampSpreadsheetTableHeaders(validation.sheet, validation.range, validation.columns) : validation.sheet;
|
|
6940
|
+
return replaceSpreadsheetTableSheet(content, {
|
|
6941
|
+
...nextSheet,
|
|
6942
|
+
tables: [
|
|
6943
|
+
...nextSheet.tables ?? [],
|
|
6944
|
+
table
|
|
6945
|
+
]
|
|
6946
|
+
});
|
|
6947
|
+
}
|
|
6948
|
+
function updateSpreadsheetTable(content, sheetId, tableId, patch) {
|
|
6949
|
+
const sheet = content.sheets.find((candidate)=>candidate.id === sheetId);
|
|
6950
|
+
const table = sheet?.tables?.find((candidate)=>candidate.id === tableId);
|
|
6951
|
+
if (!sheet || !table) return null;
|
|
6952
|
+
const name = patch.name?.trim() ?? table.name;
|
|
6953
|
+
if (!validSpreadsheetTableName(name) || spreadsheetTableNameExists(content, name, tableId)) return null;
|
|
6954
|
+
const style = patch.style ?? table.style;
|
|
6955
|
+
if (!validSpreadsheetTableStyle(style)) return null;
|
|
6956
|
+
const showFirstColumn = patch.showFirstColumn ?? table.showFirstColumn;
|
|
6957
|
+
const showLastColumn = patch.showLastColumn ?? table.showLastColumn;
|
|
6958
|
+
const showRowStripes = patch.showRowStripes ?? table.showRowStripes;
|
|
6959
|
+
const showColumnStripes = patch.showColumnStripes ?? table.showColumnStripes;
|
|
6960
|
+
if ('none' === style.family && (showFirstColumn || showLastColumn || showRowStripes || showColumnStripes)) return null;
|
|
6961
|
+
const tables = sheet.tables?.map((candidate)=>candidate.id === tableId ? {
|
|
6962
|
+
...candidate,
|
|
6963
|
+
name,
|
|
6964
|
+
...void 0 === patch.name ? {} : {
|
|
6965
|
+
displayName: void 0
|
|
6966
|
+
},
|
|
6967
|
+
style,
|
|
6968
|
+
showFirstColumn,
|
|
6969
|
+
showLastColumn,
|
|
6970
|
+
showRowStripes,
|
|
6971
|
+
showColumnStripes
|
|
6972
|
+
} : candidate);
|
|
6973
|
+
return replaceSpreadsheetTableSheet(content, {
|
|
6974
|
+
...sheet,
|
|
6975
|
+
tables
|
|
6976
|
+
});
|
|
6977
|
+
}
|
|
6978
|
+
function convertSpreadsheetTableToRange(content, sheetId, tableId) {
|
|
6979
|
+
const sheet = content.sheets.find((candidate)=>candidate.id === sheetId);
|
|
6980
|
+
const table = sheet?.tables?.find((candidate)=>candidate.id === tableId);
|
|
6981
|
+
if (!sheet || !table || spreadsheetTableHasStructuredReferences(content, table)) return null;
|
|
6982
|
+
const remaining = sheet.tables?.filter((candidate)=>candidate.id !== tableId);
|
|
6983
|
+
const withoutTable = replaceSpreadsheetTableSheet(content, {
|
|
6984
|
+
...sheet,
|
|
6985
|
+
tables: remaining?.length ? remaining : void 0
|
|
6986
|
+
});
|
|
6987
|
+
return materializeSpreadsheetTableAppearance(withoutTable, sheetId, table);
|
|
6988
|
+
}
|
|
6989
|
+
function spreadsheetTableAtCell(sheet, row, column) {
|
|
6990
|
+
if (!sheet) return null;
|
|
6991
|
+
return (sheet.tables ?? []).find((table)=>spreadsheetCellRangeContains(table.range, row, column)) ?? null;
|
|
6992
|
+
}
|
|
6993
|
+
function spreadsheetTableFailureMessage(content, request) {
|
|
6994
|
+
const validation = validateSpreadsheetTableRequest(content, request);
|
|
6995
|
+
return validation.ok ? null : validation.message;
|
|
6996
|
+
}
|
|
6997
|
+
function nextSpreadsheetTableName(content) {
|
|
6998
|
+
for(let index = 1; index <= 65536; index += 1){
|
|
6999
|
+
const candidate = `Table${index}`;
|
|
7000
|
+
if (!spreadsheetTableNameExists(content, candidate)) return candidate;
|
|
7001
|
+
}
|
|
7002
|
+
return 'Table65536';
|
|
7003
|
+
}
|
|
7004
|
+
function spreadsheetTableNameExists(content, name, exceptTableId) {
|
|
7005
|
+
const normalized = name.toLocaleLowerCase();
|
|
7006
|
+
return content.sheets.some((sheet)=>(sheet.tables ?? []).some((table)=>table.id !== exceptTableId && [
|
|
7007
|
+
table.name,
|
|
7008
|
+
table.displayName
|
|
7009
|
+
].some((candidate)=>candidate?.toLocaleLowerCase() === normalized))) || (content.namedRanges ?? []).some((range)=>range.name.trim().toLocaleLowerCase() === normalized);
|
|
7010
|
+
}
|
|
7011
|
+
function validSpreadsheetTableName(name) {
|
|
7012
|
+
return isValidSpreadsheetDefinedName(name) && !name.startsWith('_xlnm.') && ![
|
|
7013
|
+
'r',
|
|
7014
|
+
'c'
|
|
7015
|
+
].includes(name.toLocaleLowerCase());
|
|
7016
|
+
}
|
|
7017
|
+
function validSpreadsheetTableStyle(style) {
|
|
7018
|
+
if ('none' === style.family) return true;
|
|
7019
|
+
if (!Number.isInteger(style.number)) return false;
|
|
7020
|
+
if ('light' === style.family) return style.number >= 1 && style.number <= 21;
|
|
7021
|
+
if ('medium' === style.family) return style.number >= 1 && style.number <= 28;
|
|
7022
|
+
return style.number >= 1 && style.number <= 11;
|
|
7023
|
+
}
|
|
7024
|
+
function spreadsheetTableColumnNames(sheet, range, headerRow) {
|
|
7025
|
+
const observed = new Set();
|
|
7026
|
+
const names = [];
|
|
7027
|
+
for(let column = range.column[0]; column <= range.column[1]; column += 1){
|
|
7028
|
+
const raw = headerRow ? spreadsheet_table_spreadsheetCellText(sheet, range.row[0], column).trim() : '';
|
|
7029
|
+
const base = validTableColumnName(raw) ? raw : `Column${column - range.column[0] + 1}`;
|
|
7030
|
+
let candidate = base;
|
|
7031
|
+
let suffix = 2;
|
|
7032
|
+
while(observed.has(candidate.toLocaleLowerCase())){
|
|
7033
|
+
const suffixText = String(suffix);
|
|
7034
|
+
candidate = `${truncateTableColumnName(base, 255 - suffixText.length)}${suffixText}`;
|
|
7035
|
+
suffix += 1;
|
|
7036
|
+
}
|
|
7037
|
+
observed.add(candidate.toLocaleLowerCase());
|
|
7038
|
+
names.push(candidate);
|
|
7039
|
+
}
|
|
7040
|
+
return names;
|
|
7041
|
+
}
|
|
7042
|
+
function validTableColumnName(name) {
|
|
7043
|
+
const characters = Array.from(name);
|
|
7044
|
+
return name.trim() === name && characters.length >= 1 && characters.length <= 255 && !characters.some((character)=>/\p{Cc}/u.test(character) || '\uFFFE' === character || '\uFFFF' === character);
|
|
7045
|
+
}
|
|
7046
|
+
function truncateTableColumnName(value, maximum) {
|
|
7047
|
+
return Array.from(value).slice(0, maximum).join('');
|
|
7048
|
+
}
|
|
7049
|
+
function spreadsheet_table_spreadsheetCellText(sheet, row, column) {
|
|
7050
|
+
const cell = sheet.data?.[row]?.[column] ?? sheet.celldata?.find((candidate)=>candidate.r === row && candidate.c === column)?.v;
|
|
7051
|
+
const value = cell?.m ?? cell?.v;
|
|
7052
|
+
return null == value ? '' : String(value);
|
|
7053
|
+
}
|
|
7054
|
+
function stampSpreadsheetTableHeaders(sheet, range, names) {
|
|
7055
|
+
if (void 0 !== sheet.data) {
|
|
7056
|
+
const data = cloneSparseMatrixShell(sheet.data);
|
|
7057
|
+
const sourceRow = sheet.data[range.row[0]];
|
|
7058
|
+
const row = cloneSparseRow(sourceRow);
|
|
7059
|
+
for (const [offset, name] of names.entries()){
|
|
7060
|
+
const column = range.column[0] + offset;
|
|
7061
|
+
row[column] = stampHeaderCell(sourceRow?.[column], name);
|
|
7062
|
+
}
|
|
7063
|
+
data[range.row[0]] = row;
|
|
7064
|
+
return {
|
|
7065
|
+
...sheet,
|
|
7066
|
+
data
|
|
7067
|
+
};
|
|
7068
|
+
}
|
|
7069
|
+
const byCoordinate = new Map((sheet.celldata ?? []).map((entry)=>[
|
|
7070
|
+
`${entry.r}_${entry.c}`,
|
|
7071
|
+
entry
|
|
7072
|
+
]));
|
|
7073
|
+
for (const [offset, name] of names.entries()){
|
|
7074
|
+
const column = range.column[0] + offset;
|
|
7075
|
+
const key = `${range.row[0]}_${column}`;
|
|
7076
|
+
const source = byCoordinate.get(key);
|
|
7077
|
+
byCoordinate.set(key, {
|
|
7078
|
+
r: range.row[0],
|
|
7079
|
+
c: column,
|
|
7080
|
+
v: stampHeaderCell(source?.v, name)
|
|
7081
|
+
});
|
|
7082
|
+
}
|
|
7083
|
+
return {
|
|
7084
|
+
...sheet,
|
|
7085
|
+
celldata: [
|
|
7086
|
+
...byCoordinate.values()
|
|
7087
|
+
]
|
|
7088
|
+
};
|
|
7089
|
+
}
|
|
7090
|
+
function cloneSparseMatrixShell(source) {
|
|
7091
|
+
const data = [];
|
|
7092
|
+
data.length = source.length;
|
|
7093
|
+
for (const [row, value] of sparseArrayEntries(source))data[row] = value;
|
|
7094
|
+
return data;
|
|
7095
|
+
}
|
|
7096
|
+
function cloneSparseRow(source) {
|
|
7097
|
+
const row = [];
|
|
7098
|
+
if (!source) return row;
|
|
7099
|
+
row.length = source.length;
|
|
7100
|
+
for (const column of sparseArrayIndexes(source))row[column] = source[column];
|
|
7101
|
+
return row;
|
|
7102
|
+
}
|
|
7103
|
+
function stampHeaderCell(source, name) {
|
|
7104
|
+
return {
|
|
7105
|
+
...source ?? {},
|
|
7106
|
+
m: name,
|
|
7107
|
+
v: name
|
|
7108
|
+
};
|
|
7109
|
+
}
|
|
7110
|
+
function spreadsheetTableIntersectsMerge(sheet, range) {
|
|
7111
|
+
return Object.values(sheet.config?.merge ?? {}).some((merge)=>spreadsheetCellRangesIntersect(range, {
|
|
7112
|
+
row: [
|
|
7113
|
+
merge.r,
|
|
7114
|
+
merge.r + Math.max(1, merge.rs) - 1
|
|
7115
|
+
],
|
|
7116
|
+
column: [
|
|
7117
|
+
merge.c,
|
|
7118
|
+
merge.c + Math.max(1, merge.cs) - 1
|
|
7119
|
+
]
|
|
7120
|
+
}));
|
|
7121
|
+
}
|
|
7122
|
+
function replaceSpreadsheetTableSheet(content, nextSheet) {
|
|
7123
|
+
return {
|
|
7124
|
+
...content,
|
|
7125
|
+
sheets: content.sheets.map((sheet)=>sheet.id === nextSheet.id ? nextSheet : sheet)
|
|
7126
|
+
};
|
|
7127
|
+
}
|
|
7128
|
+
function spreadsheetTableHasStructuredReferences(content, table) {
|
|
7129
|
+
const aliases = [
|
|
7130
|
+
table.name,
|
|
7131
|
+
table.displayName
|
|
7132
|
+
].filter((value)=>Boolean(value));
|
|
7133
|
+
const patterns = aliases.map((alias)=>new RegExp(`${escapeRegExp(alias)}\\s*\\[`, 'i'));
|
|
7134
|
+
const matches = (value)=>'string' == typeof value && patterns.some((pattern)=>pattern.test(value));
|
|
7135
|
+
for (const sheet of content.sheets){
|
|
7136
|
+
for (const [, row] of sparseArrayEntries(sheet.data))for (const [, cell] of sparseArrayEntries(row))if (matches(cell?.f)) return true;
|
|
7137
|
+
for (const entry of sheet.celldata ?? [])if (matches(entry.v?.f)) return true;
|
|
7138
|
+
if (Object.values(sheet.formulaMetadata?.sourceFormulas ?? {}).some(matches) || matches(JSON.stringify(sheet.dataValidationRanges ?? [])) || matches(JSON.stringify(sheet.luckysheet_conditionformat_save ?? [])) || matches(JSON.stringify(sheet.charts ?? []))) return true;
|
|
7139
|
+
}
|
|
7140
|
+
return (content.namedRanges ?? []).some((range)=>matches(range.reference));
|
|
7141
|
+
}
|
|
7142
|
+
function escapeRegExp(value) {
|
|
7143
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
7144
|
+
}
|
|
7145
|
+
function cloneRange(range) {
|
|
7146
|
+
return {
|
|
7147
|
+
row: [
|
|
7148
|
+
...range.row
|
|
7149
|
+
],
|
|
7150
|
+
column: [
|
|
7151
|
+
...range.column
|
|
7152
|
+
]
|
|
7153
|
+
};
|
|
7154
|
+
}
|
|
7155
|
+
function tableError(code) {
|
|
7156
|
+
const messages = {
|
|
7157
|
+
'auto-filter-overlap': '表格区域不能与工作表自动筛选区域重叠。',
|
|
7158
|
+
'invalid-column-name': '表格列名必须唯一且不超过 255 个字符。',
|
|
7159
|
+
'invalid-name': '表格名称必须是有效且不类似单元格引用的标识符。',
|
|
7160
|
+
'invalid-range': '表格至少需要一行数据。',
|
|
7161
|
+
'invalid-style': '表格样式身份无效。',
|
|
7162
|
+
'merged-range': '请先取消表格区域内的合并单元格。',
|
|
7163
|
+
'name-conflict': '表格名称已被其他表格或名称使用。',
|
|
7164
|
+
'out-of-bounds': '表格区域超出当前工作表边界。',
|
|
7165
|
+
'pivot-table': '数据透视表工作表不能创建普通表格。',
|
|
7166
|
+
'protected-range': '受保护或只读区域不能创建表格。',
|
|
7167
|
+
'range-too-large': `一次最多可创建 ${100000..toLocaleString()} 个单元格的表格。`,
|
|
7168
|
+
'sheet-not-found': '找不到目标工作表。',
|
|
7169
|
+
'table-overlap': '表格区域不能与其他表格重叠。'
|
|
7170
|
+
};
|
|
7171
|
+
return {
|
|
7172
|
+
code,
|
|
7173
|
+
message: messages[code],
|
|
7174
|
+
ok: false
|
|
7175
|
+
};
|
|
7176
|
+
}
|
|
7177
|
+
function createSpreadsheetTableExtension() {
|
|
7178
|
+
return createOfficeEditorExtension({
|
|
7179
|
+
name: 'spreadsheetTables',
|
|
7180
|
+
addCommands: ()=>({
|
|
7181
|
+
openTable: {
|
|
7182
|
+
canExecute: canOpenSpreadsheetTable,
|
|
7183
|
+
execute: openSpreadsheetTable
|
|
7184
|
+
},
|
|
7185
|
+
applyTable: {
|
|
7186
|
+
canExecute: (context, request)=>context.editable && validateSpreadsheetTableRequest(context.content, request).ok,
|
|
7187
|
+
execute: applySpreadsheetTableCommand
|
|
7188
|
+
},
|
|
7189
|
+
updateTable: {
|
|
7190
|
+
canExecute: canUpdateSpreadsheetTable,
|
|
7191
|
+
execute: updateSpreadsheetTableCommand
|
|
7192
|
+
},
|
|
7193
|
+
convertTableToRange: {
|
|
7194
|
+
canExecute: canConvertSpreadsheetTableToRange,
|
|
7195
|
+
execute: convertSpreadsheetTableToRangeCommand
|
|
7196
|
+
}
|
|
7197
|
+
}),
|
|
7198
|
+
addKeyboardShortcuts: ()=>({
|
|
7199
|
+
[spreadsheetCommandCatalog.table.shortcut.editor["0"]]: ({ can, commands }, event)=>runSpreadsheetTableShortcut(event, can.openTable, commands.openTable)
|
|
7200
|
+
})
|
|
7201
|
+
});
|
|
7202
|
+
}
|
|
7203
|
+
function canOpenSpreadsheetTable(context) {
|
|
7204
|
+
const target = liveSpreadsheetTableTarget(context);
|
|
7205
|
+
const sheet = context.content.sheets.find((candidate)=>candidate.id === target?.sheetId);
|
|
7206
|
+
const focus = target?.selection;
|
|
7207
|
+
const row = focus?.row_focus ?? focus?.row[0] ?? 0;
|
|
7208
|
+
const column = focus?.column_focus ?? focus?.column[0] ?? 0;
|
|
7209
|
+
return Boolean(context.editable && context.table.canOpen && context.workbook && target && target.sheetId === context.activeSheetId && sheet && !sheet.isPivotTable && !sheet.pivotTables?.length && !spreadsheetTableAtCell(sheet, row, column));
|
|
7210
|
+
}
|
|
7211
|
+
function openSpreadsheetTable(context) {
|
|
7212
|
+
const target = liveSpreadsheetTableTarget(context);
|
|
7213
|
+
return Boolean(target && canOpenSpreadsheetTable(context) && context.table.open(target));
|
|
7214
|
+
}
|
|
7215
|
+
function applySpreadsheetTableCommand(context, request) {
|
|
7216
|
+
if (!context.editable) return false;
|
|
7217
|
+
const next = applySpreadsheetTable(context.content, request);
|
|
7218
|
+
if (!next) return false;
|
|
7219
|
+
context.onChange(next);
|
|
7220
|
+
return true;
|
|
7221
|
+
}
|
|
7222
|
+
function canUpdateSpreadsheetTable(context, sheetId, tableId, patch) {
|
|
7223
|
+
return Boolean(context.editable && updateSpreadsheetTable(context.content, sheetId, tableId, patch));
|
|
7224
|
+
}
|
|
7225
|
+
function updateSpreadsheetTableCommand(context, sheetId, tableId, patch) {
|
|
7226
|
+
if (!context.editable) return false;
|
|
7227
|
+
const next = updateSpreadsheetTable(context.content, sheetId, tableId, patch);
|
|
7228
|
+
if (!next) return false;
|
|
7229
|
+
context.onChange(next);
|
|
7230
|
+
return true;
|
|
7231
|
+
}
|
|
7232
|
+
function canConvertSpreadsheetTableToRange(context, sheetId, tableId) {
|
|
7233
|
+
return Boolean(context.editable && context.content.sheets.find((sheet)=>sheet.id === sheetId)?.tables?.some((table)=>table.id === tableId && canMaterializeSpreadsheetTableAppearance(table)));
|
|
7234
|
+
}
|
|
7235
|
+
function convertSpreadsheetTableToRangeCommand(context, sheetId, tableId) {
|
|
7236
|
+
if (!context.editable) return false;
|
|
7237
|
+
const next = convertSpreadsheetTableToRange(context.content, sheetId, tableId);
|
|
7238
|
+
if (!next) return false;
|
|
7239
|
+
context.onChange(next);
|
|
7240
|
+
return true;
|
|
7241
|
+
}
|
|
7242
|
+
function liveSpreadsheetTableTarget(context) {
|
|
7243
|
+
if (!context.workbook || !context.targetSheetId) return null;
|
|
7244
|
+
const selection = context.workbook.getSelection()?.at(-1) ?? context.fallbackRange;
|
|
7245
|
+
return {
|
|
7246
|
+
sheetId: context.targetSheetId,
|
|
7247
|
+
selection: finiteSpreadsheetSelection(selection)
|
|
7248
|
+
};
|
|
7249
|
+
}
|
|
7250
|
+
function runSpreadsheetTableShortcut(event, canExecute, execute) {
|
|
7251
|
+
if (event.repeat || event.isComposing || isOfficeShortcutBlocked(event.target) || isSpreadsheetNativeTextUndoTarget(event.target) || !isSpreadsheetGridKeyboardTarget(event.target)) return false;
|
|
7252
|
+
if (!event.repeat && canExecute()) execute();
|
|
7253
|
+
return true;
|
|
7254
|
+
}
|
|
7255
|
+
function createSpreadsheetEditorExtensions() {
|
|
7256
|
+
return [
|
|
7257
|
+
createOfficeEditorExtension({
|
|
7258
|
+
name: 'spreadsheetDocument',
|
|
7259
|
+
addCommands: ()=>({
|
|
7260
|
+
setSpreadsheetContent: {
|
|
7261
|
+
canExecute: (context)=>context.editable,
|
|
7262
|
+
execute: (context, content)=>{
|
|
7263
|
+
if (!context.editable) return false;
|
|
7264
|
+
context.onChange(content);
|
|
7265
|
+
return true;
|
|
7266
|
+
}
|
|
7267
|
+
}
|
|
7268
|
+
})
|
|
7269
|
+
}),
|
|
7270
|
+
createSpreadsheetCellFormatExtension(),
|
|
7271
|
+
createSpreadsheetCellBorderExtension(),
|
|
7272
|
+
createSpreadsheetCellStyleExtension(),
|
|
7273
|
+
createSpreadsheetNumberFormatExtension(),
|
|
7274
|
+
createSpreadsheetNavigationExtension(),
|
|
7275
|
+
createSpreadsheetDataValidationExtension(),
|
|
7276
|
+
createSpreadsheetHyperlinkExtension(),
|
|
7277
|
+
createSpreadsheetTableExtension(),
|
|
7278
|
+
createSpreadsheetAutoSumExtension(),
|
|
7279
|
+
createSpreadsheetCellFillExtension(),
|
|
7280
|
+
createOfficeEditorExtension({
|
|
7281
|
+
name: 'spreadsheetFormatPainter',
|
|
7282
|
+
addCommands: ()=>({
|
|
7283
|
+
activateFormatPainter: {
|
|
7284
|
+
canExecute: ({ formatPainter })=>formatPainter.canActivate,
|
|
7285
|
+
execute: ({ formatPainter }, mode)=>formatPainter.canActivate && formatPainter.activate(mode)
|
|
7286
|
+
},
|
|
7287
|
+
applyFormatPainter: {
|
|
7288
|
+
canExecute: ({ formatPainter })=>formatPainter.active,
|
|
7289
|
+
execute: ({ formatPainter }, target)=>formatPainter.active && formatPainter.applySelection(target)
|
|
7290
|
+
},
|
|
7291
|
+
cancelFormatPainter: {
|
|
7292
|
+
canExecute: ({ formatPainter })=>formatPainter.active,
|
|
7293
|
+
execute: ({ formatPainter })=>formatPainter.active && formatPainter.cancel()
|
|
7294
|
+
}
|
|
7295
|
+
})
|
|
7296
|
+
}),
|
|
7297
|
+
createOfficeEditorExtension({
|
|
7298
|
+
name: 'spreadsheetAutoFilter',
|
|
7299
|
+
addCommands: ()=>({
|
|
7300
|
+
openAutoFilterMenu: {
|
|
7301
|
+
canExecute: ({ autoFilter })=>autoFilter.canOpenMenu,
|
|
7302
|
+
execute: ({ autoFilter })=>autoFilter.canOpenMenu && autoFilter.openMenu()
|
|
7303
|
+
},
|
|
7304
|
+
toggleAutoFilter: {
|
|
7305
|
+
canExecute: ({ autoFilter })=>autoFilter.canToggle,
|
|
7306
|
+
execute: ({ autoFilter })=>autoFilter.canToggle && autoFilter.toggle()
|
|
7307
|
+
}
|
|
7308
|
+
})
|
|
7309
|
+
}),
|
|
7310
|
+
createOfficeEditorExtension({
|
|
7311
|
+
name: 'spreadsheetClipboard',
|
|
7312
|
+
addCommands: ()=>({
|
|
7313
|
+
copySelection: {
|
|
7314
|
+
canExecute: ({ clipboard })=>clipboard.canCopySelection,
|
|
7315
|
+
execute: ({ clipboard })=>clipboard.canCopySelection && clipboard.copySelection()
|
|
7316
|
+
},
|
|
7317
|
+
cutSelection: {
|
|
7318
|
+
canExecute: ({ clipboard })=>clipboard.canCutSelection,
|
|
7319
|
+
execute: ({ clipboard })=>clipboard.canCutSelection && clipboard.cutSelection()
|
|
7320
|
+
},
|
|
7321
|
+
pasteSelection: {
|
|
7322
|
+
canExecute: ({ clipboard })=>clipboard.canPasteSelection,
|
|
7323
|
+
execute: ({ clipboard })=>clipboard.canPasteSelection && clipboard.pasteSelection()
|
|
7324
|
+
},
|
|
7325
|
+
pasteSpecial: {
|
|
7326
|
+
canExecute: ({ clipboard }, content)=>clipboard.canPasteSpecial(content),
|
|
7327
|
+
execute: ({ clipboard }, content)=>clipboard.canPasteSpecial(content) && clipboard.pasteSpecial(content)
|
|
7328
|
+
},
|
|
7329
|
+
openPasteSpecial: {
|
|
7330
|
+
canExecute: ({ clipboard })=>clipboard.canOpenPasteSpecial,
|
|
7331
|
+
execute: ({ clipboard })=>clipboard.canOpenPasteSpecial && clipboard.openPasteSpecial()
|
|
7332
|
+
}
|
|
7333
|
+
})
|
|
7334
|
+
}),
|
|
7335
|
+
createOfficeEditorExtension({
|
|
7336
|
+
name: 'spreadsheetHistory',
|
|
7337
|
+
addCommands: ()=>({
|
|
7338
|
+
redo: {
|
|
7339
|
+
canExecute: (context)=>context.editable && (context.history?.canRedo ?? false),
|
|
7340
|
+
execute: (context)=>context.history?.redo() ?? false
|
|
7341
|
+
},
|
|
7342
|
+
undo: {
|
|
7343
|
+
canExecute: (context)=>context.editable && (context.history?.canUndo ?? false),
|
|
7344
|
+
execute: (context)=>context.history?.undo() ?? false
|
|
7345
|
+
}
|
|
7346
|
+
})
|
|
7347
|
+
}),
|
|
7348
|
+
createOfficeEditorExtension({
|
|
7349
|
+
name: 'spreadsheetSheets',
|
|
7350
|
+
addCommands: ()=>({
|
|
7351
|
+
activateSheet: {
|
|
7352
|
+
canExecute: (context, sheetId)=>{
|
|
7353
|
+
const sheet = context.content.sheets.find((candidate)=>candidate.id === sheetId);
|
|
7354
|
+
return Boolean(sheet && (context.editable || context.view && 1 !== sheet.hide));
|
|
7355
|
+
},
|
|
7356
|
+
execute: (context, sheetId)=>{
|
|
7357
|
+
const sheet = context.content.sheets.find((candidate)=>candidate.id === sheetId);
|
|
7358
|
+
if (!sheet) return false;
|
|
7359
|
+
if (context.view && 1 !== sheet.hide) return context.view?.activateSheet(sheetId) ?? false;
|
|
7360
|
+
if (!context.editable) return false;
|
|
7361
|
+
return applySpreadsheetSheetChange(context, activateSpreadsheetSheet(context.content, sheetId));
|
|
7362
|
+
}
|
|
7363
|
+
},
|
|
7364
|
+
addSheet: {
|
|
7365
|
+
canExecute: (context)=>context.editable,
|
|
7366
|
+
execute: (context)=>applySpreadsheetSheetChange(context, addSpreadsheetSheet(context.content))
|
|
7367
|
+
},
|
|
7368
|
+
deleteSheet: {
|
|
7369
|
+
canExecute: (context, sheetId)=>Boolean(context.editable && context.content.sheets.length > 1 && context.content.sheets.some((sheet)=>sheet.id === sheetId)),
|
|
7370
|
+
execute: (context, sheetId)=>applySpreadsheetSheetChange(context, deleteSpreadsheetSheet(context.content, sheetId))
|
|
7371
|
+
},
|
|
7372
|
+
duplicateSheet: {
|
|
7373
|
+
canExecute: (context, sheetId)=>context.editable && context.content.sheets.some((sheet)=>sheet.id === sheetId),
|
|
7374
|
+
execute: (context, sheetId)=>applySpreadsheetSheetChange(context, duplicateSpreadsheetSheet(context.content, sheetId))
|
|
7375
|
+
},
|
|
7376
|
+
hideSheet: {
|
|
7377
|
+
canExecute: (context, sheetId)=>context.editable && context.content.sheets.filter((sheet)=>1 !== sheet.hide).length > 1 && context.content.sheets.some((sheet)=>sheet.id === sheetId && 1 !== sheet.hide),
|
|
7378
|
+
execute: (context, sheetId)=>applySpreadsheetSheetChange(context, hideSpreadsheetSheet(context.content, sheetId, true))
|
|
7379
|
+
},
|
|
7380
|
+
moveSheet: {
|
|
7381
|
+
canExecute: (context, sheetId, direction)=>Boolean(context.editable && moveSpreadsheetSheet(context.content, sheetId, direction)),
|
|
7382
|
+
execute: (context, sheetId, direction)=>applySpreadsheetSheetChange(context, moveSpreadsheetSheet(context.content, sheetId, direction))
|
|
7383
|
+
},
|
|
7384
|
+
renameSheet: {
|
|
7385
|
+
canExecute: (context, sheetId, name)=>Boolean(context.editable && renameSpreadsheetSheet(context.content, sheetId, name)),
|
|
7386
|
+
execute: (context, sheetId, name)=>applySpreadsheetSheetChange(context, renameSpreadsheetSheet(context.content, sheetId, name))
|
|
7387
|
+
},
|
|
7388
|
+
setSheetColor: {
|
|
7389
|
+
canExecute: (context, sheetId, color)=>Boolean(context.editable && setSpreadsheetSheetColor(context.content, sheetId, color)),
|
|
7390
|
+
execute: (context, sheetId, color)=>applySpreadsheetSheetChange(context, setSpreadsheetSheetColor(context.content, sheetId, color))
|
|
7391
|
+
}
|
|
7392
|
+
})
|
|
7393
|
+
}),
|
|
7394
|
+
createOfficeEditorExtension({
|
|
7395
|
+
name: 'spreadsheetKeyboardShortcuts',
|
|
7396
|
+
addKeyboardShortcuts: ()=>({
|
|
6135
7397
|
'Mod-a': ({ can, commands }, event)=>selectSpreadsheetFormulaBarContents(event) || runSpreadsheetSelectionScopeShortcut(event, can.selectCellRange, commands.selectCellRange, 'all'),
|
|
6136
7398
|
'Mod-b': ({ can, commands, context }, event)=>runSpreadsheetCellFormatShortcut(event, context, can.setCellFormat, commands.setCellFormat, 'bl'),
|
|
6137
7399
|
'Mod-c': ({ can, commands }, event)=>runSpreadsheetClipboardShortcut(event, can.copySelection, commands.copySelection),
|
|
@@ -6283,9 +7545,16 @@ function canInsertSelectedStructure(context, axis, _position) {
|
|
|
6283
7545
|
const [start, end] = spreadsheetStructureRange(range, axis);
|
|
6284
7546
|
const count = end - start + 1;
|
|
6285
7547
|
const maximum = 'row' === axis ? 10000 : 1000;
|
|
6286
|
-
return spreadsheetStructureExtent(context, axis) + count < maximum
|
|
7548
|
+
return spreadsheetStructureExtent(context, axis) + count < maximum && canApplySpreadsheetTableStructureChange(context.content.sheets.find((sheet)=>sheet.id === context.targetSheetId), {
|
|
7549
|
+
axis,
|
|
7550
|
+
count,
|
|
7551
|
+
direction: 'before' === _position ? 'lefttop' : 'rightbottom',
|
|
7552
|
+
index: 'before' === _position ? start : end,
|
|
7553
|
+
kind: 'insert'
|
|
7554
|
+
});
|
|
6287
7555
|
}
|
|
6288
7556
|
function insertSelectedStructure(context, axis, position) {
|
|
7557
|
+
if (!canInsertSelectedStructure(context, axis, position)) return false;
|
|
6289
7558
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
6290
7559
|
const [start, end] = spreadsheetStructureRange(liveRange(context), axis);
|
|
6291
7560
|
const before = 'before' === position;
|
|
@@ -6301,9 +7570,15 @@ function insertSelectedStructure(context, axis, position) {
|
|
|
6301
7570
|
function canDeleteSelectedStructure(context, axis) {
|
|
6302
7571
|
if (!canEditSelectedCells(context)) return false;
|
|
6303
7572
|
const [start, end] = spreadsheetStructureRange(liveRange(context), axis);
|
|
6304
|
-
return end - start + 1 < spreadsheetStructureExtent(context, axis)
|
|
7573
|
+
return end - start + 1 < spreadsheetStructureExtent(context, axis) && canApplySpreadsheetTableStructureChange(context.content.sheets.find((sheet)=>sheet.id === context.targetSheetId), {
|
|
7574
|
+
axis,
|
|
7575
|
+
end,
|
|
7576
|
+
kind: 'delete',
|
|
7577
|
+
start
|
|
7578
|
+
});
|
|
6305
7579
|
}
|
|
6306
7580
|
function deleteSelectedStructure(context, axis) {
|
|
7581
|
+
if (!canDeleteSelectedStructure(context, axis)) return false;
|
|
6307
7582
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
6308
7583
|
const range = liveRange(context);
|
|
6309
7584
|
const [start, end] = spreadsheetStructureRange(range, axis);
|
|
@@ -8654,89 +9929,350 @@ function SpreadsheetPrintSettingsPanel({ content, onChange }) {
|
|
|
8654
9929
|
/*#__PURE__*/ jsxs("div", {
|
|
8655
9930
|
className: "actions",
|
|
8656
9931
|
children: [
|
|
8657
|
-
error && /*#__PURE__*/ jsx(InlineNotice, {
|
|
8658
|
-
className: "work-office-form-error",
|
|
8659
|
-
tone: "danger",
|
|
8660
|
-
role: "alert",
|
|
8661
|
-
children: error
|
|
8662
|
-
}),
|
|
8663
|
-
/*#__PURE__*/ jsx(button_Button, {
|
|
8664
|
-
tone: "secondary",
|
|
8665
|
-
disabled: dirty || !savedArea && !savedTitles && !savedPageBreaks && !savedPageSetup,
|
|
8666
|
-
onClick: clearSettings,
|
|
8667
|
-
children: "清除"
|
|
8668
|
-
}),
|
|
8669
|
-
/*#__PURE__*/ jsx(button_Button, {
|
|
8670
|
-
tone: "secondary",
|
|
8671
|
-
disabled: !dirty,
|
|
8672
|
-
onClick: cancelDraft,
|
|
8673
|
-
children: "取消更改"
|
|
9932
|
+
error && /*#__PURE__*/ jsx(InlineNotice, {
|
|
9933
|
+
className: "work-office-form-error",
|
|
9934
|
+
tone: "danger",
|
|
9935
|
+
role: "alert",
|
|
9936
|
+
children: error
|
|
9937
|
+
}),
|
|
9938
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
9939
|
+
tone: "secondary",
|
|
9940
|
+
disabled: dirty || !savedArea && !savedTitles && !savedPageBreaks && !savedPageSetup,
|
|
9941
|
+
onClick: clearSettings,
|
|
9942
|
+
children: "清除"
|
|
9943
|
+
}),
|
|
9944
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
9945
|
+
tone: "secondary",
|
|
9946
|
+
disabled: !dirty,
|
|
9947
|
+
onClick: cancelDraft,
|
|
9948
|
+
children: "取消更改"
|
|
9949
|
+
}),
|
|
9950
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
9951
|
+
type: "submit",
|
|
9952
|
+
tone: "primary",
|
|
9953
|
+
disabled: !sheetId || !dirty,
|
|
9954
|
+
children: "保存打印设置"
|
|
9955
|
+
})
|
|
9956
|
+
]
|
|
9957
|
+
})
|
|
9958
|
+
]
|
|
9959
|
+
});
|
|
9960
|
+
}
|
|
9961
|
+
function spreadsheetPrintSettingsDraft(content, sheetId, empty = false) {
|
|
9962
|
+
const area = empty ? void 0 : content.printAreas?.find((item)=>item.sheetId === sheetId);
|
|
9963
|
+
const titles = empty ? void 0 : content.printTitles?.find((item)=>item.sheetId === sheetId);
|
|
9964
|
+
const pageBreaks = empty ? void 0 : content.pageBreaks?.find((item)=>item.sheetId === sheetId);
|
|
9965
|
+
const pageSetup = empty ? void 0 : content.pageSetups?.find((item)=>item.sheetId === sheetId);
|
|
9966
|
+
return {
|
|
9967
|
+
reference: area?.reference ?? '',
|
|
9968
|
+
titleRows: titles?.rows ?? '',
|
|
9969
|
+
titleColumns: titles?.columns ?? '',
|
|
9970
|
+
rowPageBreaks: formatSpreadsheetRowPageBreaks(pageBreaks?.rows),
|
|
9971
|
+
columnPageBreaks: formatSpreadsheetColumnPageBreaks(pageBreaks?.columns),
|
|
9972
|
+
pageSetup: effectiveSpreadsheetPageSetup(pageSetup)
|
|
9973
|
+
};
|
|
9974
|
+
}
|
|
9975
|
+
function spreadsheetMaximumRow(sheet) {
|
|
9976
|
+
return Math.max(0, (sheet?.row ?? 1) - 1, (sheet?.data?.length ?? 1) - 1);
|
|
9977
|
+
}
|
|
9978
|
+
function spreadsheetMaximumColumn(sheet) {
|
|
9979
|
+
let maximum = Math.max(0, (sheet?.column ?? 1) - 1);
|
|
9980
|
+
for (const row of sheet?.data ?? [])maximum = Math.max(maximum, row.length - 1);
|
|
9981
|
+
return maximum;
|
|
9982
|
+
}
|
|
9983
|
+
function PageMarginField({ label, value, onChange }) {
|
|
9984
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
9985
|
+
className: "work-office-field",
|
|
9986
|
+
children: [
|
|
9987
|
+
/*#__PURE__*/ jsx("span", {
|
|
9988
|
+
children: label
|
|
9989
|
+
}),
|
|
9990
|
+
/*#__PURE__*/ jsx(CommittedOfficeNumberField, {
|
|
9991
|
+
ariaLabel: label,
|
|
9992
|
+
min: 0,
|
|
9993
|
+
max: 100,
|
|
9994
|
+
step: 0.01,
|
|
9995
|
+
value: value,
|
|
9996
|
+
normalizeValue: (nextValue)=>normalizePrintDecimal(nextValue, 0, 100),
|
|
9997
|
+
onValueCommit: onChange
|
|
9998
|
+
})
|
|
9999
|
+
]
|
|
10000
|
+
});
|
|
10001
|
+
}
|
|
10002
|
+
function normalizePrintInteger(value, minimum, maximum) {
|
|
10003
|
+
if (!value.trim()) return null;
|
|
10004
|
+
const number = Number(value);
|
|
10005
|
+
return Number.isFinite(number) ? Math.min(maximum, Math.max(minimum, Math.round(number))) : null;
|
|
10006
|
+
}
|
|
10007
|
+
function normalizePrintDecimal(value, minimum, maximum) {
|
|
10008
|
+
if (!value.trim()) return null;
|
|
10009
|
+
const number = Number(value);
|
|
10010
|
+
return Number.isFinite(number) ? Math.min(maximum, Math.max(minimum, Math.round(100 * number) / 100)) : null;
|
|
10011
|
+
}
|
|
10012
|
+
function validPageSetup(pageSetup) {
|
|
10013
|
+
const validInteger = (value, minimum, maximum)=>Number.isInteger(value) && value >= minimum && value <= maximum;
|
|
10014
|
+
return validInteger(pageSetup.scale, 10, 400) && validInteger(pageSetup.fitToWidth, 0, 32767) && validInteger(pageSetup.fitToHeight, 0, 32767) && validInteger(pageSetup.pageNumberStart, 1, 32767) && Object.values(pageSetup.margins).every((margin)=>Number.isFinite(margin) && margin >= 0 && margin <= 100);
|
|
10015
|
+
}
|
|
10016
|
+
function SpreadsheetTableDesignRibbon({ can, commands, sheetId, table }) {
|
|
10017
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
10018
|
+
children: [
|
|
10019
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
10020
|
+
label: "属性",
|
|
10021
|
+
priority: "high",
|
|
10022
|
+
children: [
|
|
10023
|
+
/*#__PURE__*/ jsx(SpreadsheetTableNameControl, {
|
|
10024
|
+
can: can,
|
|
10025
|
+
commands: commands,
|
|
10026
|
+
sheetId: sheetId,
|
|
10027
|
+
table: table
|
|
10028
|
+
}),
|
|
10029
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
10030
|
+
label: "转换为区域",
|
|
10031
|
+
disabled: !can.convertTableToRange(sheetId, table.id),
|
|
10032
|
+
onClick: ()=>{
|
|
10033
|
+
if (!commands.convertTableToRange(sheetId, table.id)) showToast('无法转换为区域。请先移除引用此表格的结构化引用。', 'error');
|
|
10034
|
+
},
|
|
10035
|
+
children: /*#__PURE__*/ jsx(TableProperties, {
|
|
10036
|
+
size: 19
|
|
10037
|
+
})
|
|
10038
|
+
})
|
|
10039
|
+
]
|
|
10040
|
+
}),
|
|
10041
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
10042
|
+
label: "表格样式",
|
|
10043
|
+
priority: "high",
|
|
10044
|
+
children: /*#__PURE__*/ jsx(SpreadsheetTableStyleGallery, {
|
|
10045
|
+
commands: commands,
|
|
10046
|
+
sheetId: sheetId,
|
|
10047
|
+
table: table
|
|
10048
|
+
})
|
|
10049
|
+
}),
|
|
10050
|
+
/*#__PURE__*/ jsxs(WorkOfficeRibbonGroup, {
|
|
10051
|
+
label: "表格样式选项",
|
|
10052
|
+
children: [
|
|
10053
|
+
/*#__PURE__*/ jsx(SpreadsheetTableOption, {
|
|
10054
|
+
label: "首列",
|
|
10055
|
+
active: table.showFirstColumn,
|
|
10056
|
+
icon: /*#__PURE__*/ jsx(Columns3, {
|
|
10057
|
+
size: 17
|
|
10058
|
+
}),
|
|
10059
|
+
disabled: !can.updateTable(sheetId, table.id, {
|
|
10060
|
+
showFirstColumn: !table.showFirstColumn
|
|
10061
|
+
}),
|
|
10062
|
+
onToggle: ()=>commands.updateTable(sheetId, table.id, {
|
|
10063
|
+
showFirstColumn: !table.showFirstColumn
|
|
10064
|
+
})
|
|
10065
|
+
}),
|
|
10066
|
+
/*#__PURE__*/ jsx(SpreadsheetTableOption, {
|
|
10067
|
+
label: "末列",
|
|
10068
|
+
active: table.showLastColumn,
|
|
10069
|
+
icon: /*#__PURE__*/ jsx(Columns3, {
|
|
10070
|
+
size: 17
|
|
10071
|
+
}),
|
|
10072
|
+
disabled: !can.updateTable(sheetId, table.id, {
|
|
10073
|
+
showLastColumn: !table.showLastColumn
|
|
10074
|
+
}),
|
|
10075
|
+
onToggle: ()=>commands.updateTable(sheetId, table.id, {
|
|
10076
|
+
showLastColumn: !table.showLastColumn
|
|
10077
|
+
})
|
|
10078
|
+
}),
|
|
10079
|
+
/*#__PURE__*/ jsx(SpreadsheetTableOption, {
|
|
10080
|
+
label: "行条纹",
|
|
10081
|
+
active: table.showRowStripes,
|
|
10082
|
+
icon: /*#__PURE__*/ jsx(Rows3, {
|
|
10083
|
+
size: 17
|
|
10084
|
+
}),
|
|
10085
|
+
disabled: !can.updateTable(sheetId, table.id, {
|
|
10086
|
+
showRowStripes: !table.showRowStripes
|
|
10087
|
+
}),
|
|
10088
|
+
onToggle: ()=>commands.updateTable(sheetId, table.id, {
|
|
10089
|
+
showRowStripes: !table.showRowStripes
|
|
10090
|
+
})
|
|
10091
|
+
}),
|
|
10092
|
+
/*#__PURE__*/ jsx(SpreadsheetTableOption, {
|
|
10093
|
+
label: "列条纹",
|
|
10094
|
+
active: table.showColumnStripes,
|
|
10095
|
+
icon: /*#__PURE__*/ jsx(Columns3, {
|
|
10096
|
+
size: 17
|
|
10097
|
+
}),
|
|
10098
|
+
disabled: !can.updateTable(sheetId, table.id, {
|
|
10099
|
+
showColumnStripes: !table.showColumnStripes
|
|
10100
|
+
}),
|
|
10101
|
+
onToggle: ()=>commands.updateTable(sheetId, table.id, {
|
|
10102
|
+
showColumnStripes: !table.showColumnStripes
|
|
10103
|
+
})
|
|
10104
|
+
})
|
|
10105
|
+
]
|
|
10106
|
+
})
|
|
10107
|
+
]
|
|
10108
|
+
});
|
|
10109
|
+
}
|
|
10110
|
+
function SpreadsheetTableNameControl({ can, commands, sheetId, table }) {
|
|
10111
|
+
const [name, setName] = useState(table.name);
|
|
10112
|
+
useEffect(()=>setName(table.name), [
|
|
10113
|
+
table.id,
|
|
10114
|
+
table.name
|
|
10115
|
+
]);
|
|
10116
|
+
const commit = ()=>{
|
|
10117
|
+
const candidate = name.trim();
|
|
10118
|
+
if (!candidate || candidate === table.name) return void setName(table.name);
|
|
10119
|
+
const patch = {
|
|
10120
|
+
name: candidate
|
|
10121
|
+
};
|
|
10122
|
+
if (!can.updateTable(sheetId, table.id, patch) || !commands.updateTable(sheetId, table.id, patch)) {
|
|
10123
|
+
setName(table.name);
|
|
10124
|
+
showToast('表格名称无效或已被使用。', 'error');
|
|
10125
|
+
}
|
|
10126
|
+
};
|
|
10127
|
+
return /*#__PURE__*/ jsxs("label", {
|
|
10128
|
+
className: "work-spreadsheet-table-name",
|
|
10129
|
+
children: [
|
|
10130
|
+
/*#__PURE__*/ jsx("span", {
|
|
10131
|
+
children: "表格名称"
|
|
10132
|
+
}),
|
|
10133
|
+
/*#__PURE__*/ jsx("input", {
|
|
10134
|
+
type: "text",
|
|
10135
|
+
"aria-label": "表格名称",
|
|
10136
|
+
autoCapitalize: "none",
|
|
10137
|
+
spellCheck: false,
|
|
10138
|
+
value: name,
|
|
10139
|
+
onBlur: commit,
|
|
10140
|
+
onChange: (event)=>setName(event.currentTarget.value),
|
|
10141
|
+
onKeyDown: (event)=>{
|
|
10142
|
+
if ('Enter' === event.key) {
|
|
10143
|
+
event.preventDefault();
|
|
10144
|
+
commit();
|
|
10145
|
+
} else if ('Escape' === event.key) {
|
|
10146
|
+
event.preventDefault();
|
|
10147
|
+
setName(table.name);
|
|
10148
|
+
}
|
|
10149
|
+
}
|
|
10150
|
+
})
|
|
10151
|
+
]
|
|
10152
|
+
});
|
|
10153
|
+
}
|
|
10154
|
+
function SpreadsheetTableStyleGallery({ commands, sheetId, table }) {
|
|
10155
|
+
const choices = spreadsheetTableStyleChoices();
|
|
10156
|
+
const selected = choices.find((choice)=>spreadsheetTableUsesStyle(table.style, choice.style));
|
|
10157
|
+
const families = [
|
|
10158
|
+
{
|
|
10159
|
+
id: 'light',
|
|
10160
|
+
label: '浅色'
|
|
10161
|
+
},
|
|
10162
|
+
{
|
|
10163
|
+
id: 'medium',
|
|
10164
|
+
label: '中等'
|
|
10165
|
+
},
|
|
10166
|
+
{
|
|
10167
|
+
id: 'dark',
|
|
10168
|
+
label: '深色'
|
|
10169
|
+
}
|
|
10170
|
+
];
|
|
10171
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
10172
|
+
label: "表格样式",
|
|
10173
|
+
panelLabel: "表格样式库",
|
|
10174
|
+
panelRole: "menu",
|
|
10175
|
+
portal: true,
|
|
10176
|
+
className: "work-spreadsheet-table-style-root",
|
|
10177
|
+
panelClassName: "work-spreadsheet-table-style-menu",
|
|
10178
|
+
focusFirstOnOpen: true,
|
|
10179
|
+
onPanelKeyDown: moveSpreadsheetTableStyleFocus,
|
|
10180
|
+
trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs("button", {
|
|
10181
|
+
...triggerProps,
|
|
10182
|
+
type: "button",
|
|
10183
|
+
className: `with-label work-spreadsheet-table-style-trigger${open ? ' active' : ''}`,
|
|
10184
|
+
title: `表格样式(当前:${selected?.label ?? '无'})`,
|
|
10185
|
+
children: [
|
|
10186
|
+
/*#__PURE__*/ jsx(SpreadsheetTableStylePreview, {
|
|
10187
|
+
choice: selected ?? choices[0]
|
|
8674
10188
|
}),
|
|
8675
|
-
/*#__PURE__*/ jsx(
|
|
8676
|
-
|
|
8677
|
-
tone: "primary",
|
|
8678
|
-
disabled: !sheetId || !dirty,
|
|
8679
|
-
children: "保存打印设置"
|
|
10189
|
+
/*#__PURE__*/ jsx("span", {
|
|
10190
|
+
children: "表格样式"
|
|
8680
10191
|
})
|
|
8681
10192
|
]
|
|
10193
|
+
}),
|
|
10194
|
+
children: (close)=>/*#__PURE__*/ jsx(Fragment, {
|
|
10195
|
+
children: families.map((family)=>/*#__PURE__*/ jsxs("fieldset", {
|
|
10196
|
+
className: "work-spreadsheet-table-style-family",
|
|
10197
|
+
"data-office-menu-grid": true,
|
|
10198
|
+
"aria-label": family.label,
|
|
10199
|
+
children: [
|
|
10200
|
+
/*#__PURE__*/ jsx("span", {
|
|
10201
|
+
children: family.label
|
|
10202
|
+
}),
|
|
10203
|
+
/*#__PURE__*/ jsx("div", {
|
|
10204
|
+
children: choices.filter((choice)=>choice.style.family === family.id).map((choice)=>{
|
|
10205
|
+
const checked = spreadsheetTableUsesStyle(table.style, choice.style);
|
|
10206
|
+
return /*#__PURE__*/ jsx("button", {
|
|
10207
|
+
type: "button",
|
|
10208
|
+
role: "menuitemradio",
|
|
10209
|
+
tabIndex: -1,
|
|
10210
|
+
"aria-label": `应用表格样式:${choice.label}`,
|
|
10211
|
+
"aria-checked": checked,
|
|
10212
|
+
title: choice.label,
|
|
10213
|
+
onClick: ()=>{
|
|
10214
|
+
close();
|
|
10215
|
+
commands.updateTable(sheetId, table.id, {
|
|
10216
|
+
style: choice.style
|
|
10217
|
+
});
|
|
10218
|
+
},
|
|
10219
|
+
children: /*#__PURE__*/ jsx(SpreadsheetTableStylePreview, {
|
|
10220
|
+
choice: choice
|
|
10221
|
+
})
|
|
10222
|
+
}, choice.ooxmlName);
|
|
10223
|
+
})
|
|
10224
|
+
})
|
|
10225
|
+
]
|
|
10226
|
+
}, family.id))
|
|
8682
10227
|
})
|
|
8683
|
-
]
|
|
8684
10228
|
});
|
|
8685
10229
|
}
|
|
8686
|
-
function
|
|
8687
|
-
const
|
|
8688
|
-
const
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
for (const row of sheet?.data ?? [])maximum = Math.max(maximum, row.length - 1);
|
|
8706
|
-
return maximum;
|
|
8707
|
-
}
|
|
8708
|
-
function PageMarginField({ label, value, onChange }) {
|
|
8709
|
-
return /*#__PURE__*/ jsxs("div", {
|
|
8710
|
-
className: "work-office-field",
|
|
10230
|
+
function moveSpreadsheetTableStyleFocus(event) {
|
|
10231
|
+
const active = document.activeElement;
|
|
10232
|
+
const group = [
|
|
10233
|
+
...event.currentTarget.querySelectorAll('[data-office-menu-grid]')
|
|
10234
|
+
].find((candidate)=>candidate.contains(active));
|
|
10235
|
+
const grid = group?.querySelector(':scope > div');
|
|
10236
|
+
const template = grid ? getComputedStyle(grid).gridTemplateColumns : '';
|
|
10237
|
+
const repeated = template.match(/^repeat\(\s*(\d+)/)?.[1];
|
|
10238
|
+
const resolved = template.split(/\s+/).filter((value)=>value && 'none' !== value).length;
|
|
10239
|
+
const columns = repeated ? Number(repeated) : resolved || 7;
|
|
10240
|
+
return moveOfficeGridMenuFocus(event, Math.max(1, columns));
|
|
10241
|
+
}
|
|
10242
|
+
function spreadsheetTableUsesStyle(tableStyle, choice) {
|
|
10243
|
+
return 'none' !== tableStyle.family && tableStyle.family === choice.family && tableStyle.number === choice.number;
|
|
10244
|
+
}
|
|
10245
|
+
function SpreadsheetTableStylePreview({ choice }) {
|
|
10246
|
+
return /*#__PURE__*/ jsxs("span", {
|
|
10247
|
+
className: "work-spreadsheet-table-style-preview",
|
|
10248
|
+
"aria-hidden": "true",
|
|
8711
10249
|
children: [
|
|
8712
|
-
/*#__PURE__*/ jsx("
|
|
8713
|
-
|
|
10250
|
+
/*#__PURE__*/ jsx("i", {
|
|
10251
|
+
style: {
|
|
10252
|
+
backgroundColor: choice.palette.header
|
|
10253
|
+
}
|
|
8714
10254
|
}),
|
|
8715
|
-
/*#__PURE__*/ jsx(
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
10255
|
+
/*#__PURE__*/ jsx("i", {
|
|
10256
|
+
style: {
|
|
10257
|
+
backgroundColor: choice.palette.primaryRow
|
|
10258
|
+
}
|
|
10259
|
+
}),
|
|
10260
|
+
/*#__PURE__*/ jsx("i", {
|
|
10261
|
+
style: {
|
|
10262
|
+
backgroundColor: choice.palette.secondaryRow
|
|
10263
|
+
}
|
|
8723
10264
|
})
|
|
8724
10265
|
]
|
|
8725
10266
|
});
|
|
8726
10267
|
}
|
|
8727
|
-
function
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
return Number.isFinite(number) ? Math.min(maximum, Math.max(minimum, Math.round(100 * number) / 100)) : null;
|
|
8736
|
-
}
|
|
8737
|
-
function validPageSetup(pageSetup) {
|
|
8738
|
-
const validInteger = (value, minimum, maximum)=>Number.isInteger(value) && value >= minimum && value <= maximum;
|
|
8739
|
-
return validInteger(pageSetup.scale, 10, 400) && validInteger(pageSetup.fitToWidth, 0, 32767) && validInteger(pageSetup.fitToHeight, 0, 32767) && validInteger(pageSetup.pageNumberStart, 1, 32767) && Object.values(pageSetup.margins).every((margin)=>Number.isFinite(margin) && margin >= 0 && margin <= 100);
|
|
10268
|
+
function SpreadsheetTableOption({ active, disabled, icon, label, onToggle }) {
|
|
10269
|
+
return /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
10270
|
+
label: label,
|
|
10271
|
+
active: active,
|
|
10272
|
+
disabled: disabled,
|
|
10273
|
+
onClick: onToggle,
|
|
10274
|
+
children: icon
|
|
10275
|
+
});
|
|
8740
10276
|
}
|
|
8741
10277
|
const defaultSpreadsheetFreezePanesSelection = {
|
|
8742
10278
|
row: [
|
|
@@ -8750,7 +10286,11 @@ const defaultSpreadsheetFreezePanesSelection = {
|
|
|
8750
10286
|
row_focus: 0,
|
|
8751
10287
|
column_focus: 0
|
|
8752
10288
|
};
|
|
8753
|
-
function SpreadsheetEditorRibbon({ activeTab, autoFilterActive = false, can, commands, content, fileActions, findOpen, formatPainterMode = null, freezePanesActive = false, freezePanesSelection = defaultSpreadsheetFreezePanesSelection, gridLinesVisible, panelId, onTabChange, onTogglePanel, panel, toolbarCell, toolbarCellBorders }) {
|
|
10289
|
+
function SpreadsheetEditorRibbon({ activeTab, activeTable = null, activeTableSheetId, autoFilterActive = false, can, commands, content, fileActions, findOpen, formatPainterMode = null, freezePanesActive = false, freezePanesSelection = defaultSpreadsheetFreezePanesSelection, gridLinesVisible, panelId, onTabChange, onTogglePanel, panel, toolbarCell, toolbarCellBorders }) {
|
|
10290
|
+
const ribbonTabs = activeTable ? [
|
|
10291
|
+
...spreadsheetRibbonTabs,
|
|
10292
|
+
spreadsheetTableDesignRibbonTab
|
|
10293
|
+
] : spreadsheetRibbonTabs;
|
|
8754
10294
|
const formulaCount = useMemo(()=>spreadsheetFormulaCount(content), [
|
|
8755
10295
|
content
|
|
8756
10296
|
]);
|
|
@@ -8759,7 +10299,7 @@ function SpreadsheetEditorRibbon({ activeTab, autoFilterActive = false, can, com
|
|
|
8759
10299
|
]);
|
|
8760
10300
|
return /*#__PURE__*/ jsx(WorkOfficeRibbon, {
|
|
8761
10301
|
ariaLabel: "表格功能区",
|
|
8762
|
-
tabs:
|
|
10302
|
+
tabs: ribbonTabs,
|
|
8763
10303
|
defaultTab: "home",
|
|
8764
10304
|
activeTab: activeTab,
|
|
8765
10305
|
onTabChange: onTabChange,
|
|
@@ -8991,6 +10531,20 @@ function SpreadsheetEditorRibbon({ activeTab, autoFilterActive = false, can, com
|
|
|
8991
10531
|
}),
|
|
8992
10532
|
insert: /*#__PURE__*/ jsxs(Fragment, {
|
|
8993
10533
|
children: [
|
|
10534
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
10535
|
+
label: "表格",
|
|
10536
|
+
priority: "high",
|
|
10537
|
+
children: /*#__PURE__*/ jsx(WorkOfficeRibbonButton, {
|
|
10538
|
+
label: spreadsheetCommandCatalog.table.label,
|
|
10539
|
+
title: `${spreadsheetCommandCatalog.table.label}(${spreadsheetCommandCatalog.table.shortcut.label})`,
|
|
10540
|
+
"aria-keyshortcuts": spreadsheetCommandCatalog.table.shortcut.aria,
|
|
10541
|
+
disabled: !can.openTable(),
|
|
10542
|
+
onClick: commands.openTable,
|
|
10543
|
+
children: /*#__PURE__*/ jsx(Table2, {
|
|
10544
|
+
size: 19
|
|
10545
|
+
})
|
|
10546
|
+
})
|
|
10547
|
+
}),
|
|
8994
10548
|
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
8995
10549
|
label: "链接",
|
|
8996
10550
|
priority: "high",
|
|
@@ -9188,7 +10742,13 @@ function SpreadsheetEditorRibbon({ activeTab, autoFilterActive = false, can, com
|
|
|
9188
10742
|
})
|
|
9189
10743
|
})
|
|
9190
10744
|
]
|
|
9191
|
-
})
|
|
10745
|
+
}),
|
|
10746
|
+
tableDesign: activeTable && activeTableSheetId ? /*#__PURE__*/ jsx(SpreadsheetTableDesignRibbon, {
|
|
10747
|
+
can: can,
|
|
10748
|
+
commands: commands,
|
|
10749
|
+
sheetId: activeTableSheetId,
|
|
10750
|
+
table: activeTable
|
|
10751
|
+
}) : null
|
|
9192
10752
|
}
|
|
9193
10753
|
});
|
|
9194
10754
|
}
|
|
@@ -12086,6 +13646,59 @@ function SheetMenuButton({ icon, label, danger = false, disabled = false, onClic
|
|
|
12086
13646
|
]
|
|
12087
13647
|
});
|
|
12088
13648
|
}
|
|
13649
|
+
const pendingContextRestores = new WeakMap();
|
|
13650
|
+
function beginSpreadsheetTableCellRender(_cell, tableStyle, conditionalStyle, context) {
|
|
13651
|
+
if (tableStyle) context.fillStyle = tableStyle.background;
|
|
13652
|
+
if (conditionalStyle?.cellColor) context.fillStyle = conditionalStyle.cellColor;
|
|
13653
|
+
if (!tableStyle || pendingContextRestores.has(context) || 'function' != typeof context.fillText) return;
|
|
13654
|
+
const fillText = context.fillText;
|
|
13655
|
+
pendingContextRestores.set(context, {
|
|
13656
|
+
fillText,
|
|
13657
|
+
fillTextOwned: Object.hasOwn(context, 'fillText')
|
|
13658
|
+
});
|
|
13659
|
+
const textColor = conditionalStyle?.textColor ?? tableStyle.textColor;
|
|
13660
|
+
context.fillText = (text, x, y, maxWidth)=>{
|
|
13661
|
+
const previousFillStyle = context.fillStyle;
|
|
13662
|
+
const previousFont = context.font;
|
|
13663
|
+
context.fillStyle = textColor;
|
|
13664
|
+
if (tableStyle.bold) context.font = boldSpreadsheetTableCanvasFont(context.font);
|
|
13665
|
+
try {
|
|
13666
|
+
if (void 0 === maxWidth) fillText.call(context, text, x, y);
|
|
13667
|
+
else fillText.call(context, text, x, y, maxWidth);
|
|
13668
|
+
} finally{
|
|
13669
|
+
context.fillStyle = previousFillStyle;
|
|
13670
|
+
context.font = previousFont;
|
|
13671
|
+
}
|
|
13672
|
+
};
|
|
13673
|
+
}
|
|
13674
|
+
function finishSpreadsheetTableCellRender(_cell, cellInfo, tableStyle, context) {
|
|
13675
|
+
if (tableStyle) drawSpreadsheetTableCellBorder(cellInfo, tableStyle, context);
|
|
13676
|
+
const restore = pendingContextRestores.get(context);
|
|
13677
|
+
if (!restore) return;
|
|
13678
|
+
if (restore.fillTextOwned) context.fillText = restore.fillText;
|
|
13679
|
+
else delete context.fillText;
|
|
13680
|
+
pendingContextRestores.delete(context);
|
|
13681
|
+
}
|
|
13682
|
+
function boldSpreadsheetTableCanvasFont(font) {
|
|
13683
|
+
return /(?:^|\s)(?:bold|[6-9]00)(?:\s|$)/i.test(font) ? font : `bold ${font}`;
|
|
13684
|
+
}
|
|
13685
|
+
function drawSpreadsheetTableCellBorder(cellInfo, tableStyle, context) {
|
|
13686
|
+
const left = Math.round(cellInfo.startX) + 0.5;
|
|
13687
|
+
const top = Math.round(cellInfo.startY) + 0.5;
|
|
13688
|
+
const right = Math.round(cellInfo.endX) - 0.5;
|
|
13689
|
+
const bottom = Math.round(cellInfo.endY) - 0.5;
|
|
13690
|
+
context.save();
|
|
13691
|
+
context.beginPath();
|
|
13692
|
+
context.strokeStyle = tableStyle.borderColor;
|
|
13693
|
+
context.lineWidth = 'header' === tableStyle.role ? 1 : 0.75;
|
|
13694
|
+
context.moveTo(left, top);
|
|
13695
|
+
context.lineTo(right, top);
|
|
13696
|
+
context.lineTo(right, bottom);
|
|
13697
|
+
context.lineTo(left, bottom);
|
|
13698
|
+
context.closePath();
|
|
13699
|
+
context.stroke();
|
|
13700
|
+
context.restore();
|
|
13701
|
+
}
|
|
12089
13702
|
function validateSpreadsheetChartSeriesTrendlines(series, seriesIndex) {
|
|
12090
13703
|
for (const [trendlineIndex, trendline] of (series.trendlines ?? []).entries()){
|
|
12091
13704
|
const prefix = `系列 ${seriesIndex + 1} 的趋势线 ${trendlineIndex + 1}`;
|
|
@@ -16195,220 +17808,28 @@ function NamedRangeManager({ content, onChange }) {
|
|
|
16195
17808
|
onClick: cancelDraft,
|
|
16196
17809
|
children: "取消更改"
|
|
16197
17810
|
}),
|
|
16198
|
-
/*#__PURE__*/ jsx(button_Button, {
|
|
16199
|
-
type: "submit",
|
|
16200
|
-
tone: "primary",
|
|
16201
|
-
disabled: Boolean(draft.id) && !dirty,
|
|
16202
|
-
children: "保存名称"
|
|
16203
|
-
})
|
|
16204
|
-
]
|
|
16205
|
-
})
|
|
16206
|
-
]
|
|
16207
|
-
})
|
|
16208
|
-
]
|
|
16209
|
-
});
|
|
16210
|
-
}
|
|
16211
|
-
function rangeDraft(range) {
|
|
16212
|
-
return {
|
|
16213
|
-
id: range?.id,
|
|
16214
|
-
name: range?.name ?? '',
|
|
16215
|
-
reference: range?.reference ?? '',
|
|
16216
|
-
scopeSheetId: range?.scopeSheetId ?? '',
|
|
16217
|
-
comment: range?.comment ?? ''
|
|
16218
|
-
};
|
|
16219
|
-
}
|
|
16220
|
-
function spreadsheetAutoFilterRange(sheet, selection) {
|
|
16221
|
-
if (sheet.isPivotTable || sheet.pivotTables?.length) return null;
|
|
16222
|
-
const normalized = normalizeAutoFilterSelection(selection);
|
|
16223
|
-
const range = normalized.row[0] !== normalized.row[1] ? normalized : spreadsheetCurrentRegion(sheet, normalized);
|
|
16224
|
-
if (!range || !validSpreadsheetAutoFilterRange(sheet, range)) return null;
|
|
16225
|
-
return range;
|
|
16226
|
-
}
|
|
16227
|
-
function spreadsheetAutoFilterHeaderColumn(sheet, selection) {
|
|
16228
|
-
const range = normalizedFilterSelection(sheet?.filter_select);
|
|
16229
|
-
if (!sheet || !range) return null;
|
|
16230
|
-
const row = spreadsheet_auto_filter_finiteIndex(selection.row_focus, selection.row[0]);
|
|
16231
|
-
const column = spreadsheet_auto_filter_finiteIndex(selection.column_focus, selection.column[0]);
|
|
16232
|
-
if (row !== range.row[0] || column < range.column[0] || column > range.column[1]) return null;
|
|
16233
|
-
return column;
|
|
16234
|
-
}
|
|
16235
|
-
function toggleSpreadsheetAutoFilter(content, sheetId, selection) {
|
|
16236
|
-
const sheetIndex = content.sheets.findIndex((sheet)=>sheet.id === sheetId);
|
|
16237
|
-
const sheet = content.sheets[sheetIndex];
|
|
16238
|
-
if (!sheet) return null;
|
|
16239
|
-
const nextSheet = sheet.filter_select ? spreadsheetSheetWithoutAutoFilter(sheet) : spreadsheetSheetWithAutoFilter(sheet, selection);
|
|
16240
|
-
if (!nextSheet) return null;
|
|
16241
|
-
const sheets = [
|
|
16242
|
-
...content.sheets
|
|
16243
|
-
];
|
|
16244
|
-
sheets[sheetIndex] = {
|
|
16245
|
-
...nextSheet,
|
|
16246
|
-
luckysheet_select_save: [
|
|
16247
|
-
finiteSpreadsheetSelection(selection)
|
|
16248
|
-
]
|
|
16249
|
-
};
|
|
16250
|
-
return {
|
|
16251
|
-
...content,
|
|
16252
|
-
sheets
|
|
16253
|
-
};
|
|
16254
|
-
}
|
|
16255
|
-
function spreadsheetSheetWithAutoFilter(sheet, selection) {
|
|
16256
|
-
const range = spreadsheetAutoFilterRange(sheet, selection);
|
|
16257
|
-
if (!range) return null;
|
|
16258
|
-
return {
|
|
16259
|
-
...sheet,
|
|
16260
|
-
filter: {},
|
|
16261
|
-
filter_select: {
|
|
16262
|
-
row: [
|
|
16263
|
-
...range.row
|
|
16264
|
-
],
|
|
16265
|
-
column: [
|
|
16266
|
-
...range.column
|
|
16267
|
-
]
|
|
16268
|
-
}
|
|
16269
|
-
};
|
|
16270
|
-
}
|
|
16271
|
-
function spreadsheetSheetWithoutAutoFilter(sheet) {
|
|
16272
|
-
const hiddenByFilter = spreadsheetFilterHiddenRows(sheet.filter);
|
|
16273
|
-
const rowhidden = {
|
|
16274
|
-
...sheet.config?.rowhidden
|
|
16275
|
-
};
|
|
16276
|
-
for (const row of hiddenByFilter)delete rowhidden[row];
|
|
16277
|
-
const config = sheet.config ? {
|
|
16278
|
-
...sheet.config,
|
|
16279
|
-
rowhidden
|
|
16280
|
-
} : void 0;
|
|
16281
|
-
const { filter: _filter, filter_select: _selection, ...remaining } = sheet;
|
|
16282
|
-
return {
|
|
16283
|
-
...remaining,
|
|
16284
|
-
config
|
|
16285
|
-
};
|
|
16286
|
-
}
|
|
16287
|
-
function spreadsheetFilterHiddenRows(filter) {
|
|
16288
|
-
const rows = new Set();
|
|
16289
|
-
for (const value of Object.values(filter ?? {})){
|
|
16290
|
-
if (!value || 'object' != typeof value) continue;
|
|
16291
|
-
const rowhidden = value.rowhidden;
|
|
16292
|
-
if (rowhidden && 'object' == typeof rowhidden) for (const row of Object.keys(rowhidden))rows.add(row);
|
|
16293
|
-
}
|
|
16294
|
-
return rows;
|
|
16295
|
-
}
|
|
16296
|
-
function spreadsheetCurrentRegion(sheet, selection) {
|
|
16297
|
-
const cells = spreadsheetCellReader(sheet);
|
|
16298
|
-
const bounds = spreadsheetUsedBounds(sheet);
|
|
16299
|
-
let startRow = selection.row[0];
|
|
16300
|
-
let endRow = selection.row[1];
|
|
16301
|
-
let startColumn = selection.column[0];
|
|
16302
|
-
let endColumn = selection.column[1];
|
|
16303
|
-
if (startRow > bounds.lastRow || startColumn > bounds.lastColumn || !spreadsheet_auto_filter_spreadsheetCellHasContent(cells(startRow, startColumn))) return null;
|
|
16304
|
-
let changed = true;
|
|
16305
|
-
while(changed){
|
|
16306
|
-
changed = false;
|
|
16307
|
-
while(startColumn > 0 && spreadsheetColumnHasContent(cells, startColumn - 1, startRow, endRow)){
|
|
16308
|
-
startColumn -= 1;
|
|
16309
|
-
changed = true;
|
|
16310
|
-
}
|
|
16311
|
-
while(endColumn < bounds.lastColumn && spreadsheetColumnHasContent(cells, endColumn + 1, startRow, endRow)){
|
|
16312
|
-
endColumn += 1;
|
|
16313
|
-
changed = true;
|
|
16314
|
-
}
|
|
16315
|
-
while(startRow > 0 && spreadsheetRowHasContent(cells, startRow - 1, startColumn, endColumn)){
|
|
16316
|
-
startRow -= 1;
|
|
16317
|
-
changed = true;
|
|
16318
|
-
}
|
|
16319
|
-
while(endRow < bounds.lastRow && spreadsheetRowHasContent(cells, endRow + 1, startColumn, endColumn)){
|
|
16320
|
-
endRow += 1;
|
|
16321
|
-
changed = true;
|
|
16322
|
-
}
|
|
16323
|
-
}
|
|
16324
|
-
return {
|
|
16325
|
-
row: [
|
|
16326
|
-
startRow,
|
|
16327
|
-
endRow
|
|
16328
|
-
],
|
|
16329
|
-
column: [
|
|
16330
|
-
startColumn,
|
|
16331
|
-
endColumn
|
|
17811
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
17812
|
+
type: "submit",
|
|
17813
|
+
tone: "primary",
|
|
17814
|
+
disabled: Boolean(draft.id) && !dirty,
|
|
17815
|
+
children: "保存名称"
|
|
17816
|
+
})
|
|
17817
|
+
]
|
|
17818
|
+
})
|
|
17819
|
+
]
|
|
17820
|
+
})
|
|
16332
17821
|
]
|
|
16333
|
-
};
|
|
16334
|
-
}
|
|
16335
|
-
function validSpreadsheetAutoFilterRange(sheet, range) {
|
|
16336
|
-
if (range.row[1] <= range.row[0]) return false;
|
|
16337
|
-
const cells = spreadsheetCellReader(sheet);
|
|
16338
|
-
if (!spreadsheetRowHasContent(cells, range.row[0], range.column[0], range.column[1])) return false;
|
|
16339
|
-
let dataFound = false;
|
|
16340
|
-
for(let row = range.row[0] + 1; row <= range.row[1]; row += 1)if (spreadsheetRowHasContent(cells, row, range.column[0], range.column[1])) {
|
|
16341
|
-
dataFound = true;
|
|
16342
|
-
break;
|
|
16343
|
-
}
|
|
16344
|
-
return dataFound && !spreadsheetRangeIntersectsMerge(sheet, range);
|
|
16345
|
-
}
|
|
16346
|
-
function spreadsheetRangeIntersectsMerge(sheet, range) {
|
|
16347
|
-
return Object.values(sheet.config?.merge ?? {}).some((merge)=>{
|
|
16348
|
-
const endRow = merge.r + Math.max(merge.rs, 1) - 1;
|
|
16349
|
-
const endColumn = merge.c + Math.max(merge.cs, 1) - 1;
|
|
16350
|
-
return merge.r <= range.row[1] && endRow >= range.row[0] && merge.c <= range.column[1] && endColumn >= range.column[0];
|
|
16351
17822
|
});
|
|
16352
17823
|
}
|
|
16353
|
-
function
|
|
16354
|
-
for(let column = startColumn; column <= endColumn; column += 1)if (spreadsheet_auto_filter_spreadsheetCellHasContent(cellAt(row, column))) return true;
|
|
16355
|
-
return false;
|
|
16356
|
-
}
|
|
16357
|
-
function spreadsheetColumnHasContent(cellAt, column, startRow, endRow) {
|
|
16358
|
-
for(let row = startRow; row <= endRow; row += 1)if (spreadsheet_auto_filter_spreadsheetCellHasContent(cellAt(row, column))) return true;
|
|
16359
|
-
return false;
|
|
16360
|
-
}
|
|
16361
|
-
function spreadsheet_auto_filter_spreadsheetCellHasContent(cell) {
|
|
16362
|
-
if (!cell) return false;
|
|
16363
|
-
return [
|
|
16364
|
-
cell.v,
|
|
16365
|
-
cell.m,
|
|
16366
|
-
cell.f
|
|
16367
|
-
].some((value)=>null != value && '' !== value);
|
|
16368
|
-
}
|
|
16369
|
-
function spreadsheetCellReader(sheet) {
|
|
16370
|
-
if (sheet.data) return (row, column)=>sheet.data?.[row]?.[column] ?? null;
|
|
16371
|
-
const cells = new Map((sheet.celldata ?? []).map((cell)=>[
|
|
16372
|
-
`${cell.r}:${cell.c}`,
|
|
16373
|
-
cell.v
|
|
16374
|
-
]));
|
|
16375
|
-
return (row, column)=>cells.get(`${row}:${column}`) ?? null;
|
|
16376
|
-
}
|
|
16377
|
-
function spreadsheetUsedBounds(sheet) {
|
|
16378
|
-
let lastRow = Math.max((sheet.data?.length ?? 1) - 1, 0);
|
|
16379
|
-
let lastColumn = Math.max(sparseMatrixColumnCount(sheet.data) - 1, 0);
|
|
16380
|
-
for (const cell of sheet.celldata ?? []){
|
|
16381
|
-
lastRow = Math.max(lastRow, cell.r);
|
|
16382
|
-
lastColumn = Math.max(lastColumn, cell.c);
|
|
16383
|
-
}
|
|
16384
|
-
return {
|
|
16385
|
-
lastColumn,
|
|
16386
|
-
lastRow
|
|
16387
|
-
};
|
|
16388
|
-
}
|
|
16389
|
-
function normalizeAutoFilterSelection(selection) {
|
|
16390
|
-
const startRow = spreadsheet_auto_filter_finiteIndex(selection.row[0], 0);
|
|
16391
|
-
const endRow = spreadsheet_auto_filter_finiteIndex(selection.row[1], startRow);
|
|
16392
|
-
const startColumn = spreadsheet_auto_filter_finiteIndex(selection.column[0], 0);
|
|
16393
|
-
const endColumn = spreadsheet_auto_filter_finiteIndex(selection.column[1], startColumn);
|
|
17824
|
+
function rangeDraft(range) {
|
|
16394
17825
|
return {
|
|
16395
|
-
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
Math.min(startColumn, endColumn),
|
|
16401
|
-
Math.max(startColumn, endColumn)
|
|
16402
|
-
]
|
|
17826
|
+
id: range?.id,
|
|
17827
|
+
name: range?.name ?? '',
|
|
17828
|
+
reference: range?.reference ?? '',
|
|
17829
|
+
scopeSheetId: range?.scopeSheetId ?? '',
|
|
17830
|
+
comment: range?.comment ?? ''
|
|
16403
17831
|
};
|
|
16404
17832
|
}
|
|
16405
|
-
function normalizedFilterSelection(selection) {
|
|
16406
|
-
if (!selection?.row?.length || !selection.column?.length) return null;
|
|
16407
|
-
return normalizeAutoFilterSelection(selection);
|
|
16408
|
-
}
|
|
16409
|
-
function spreadsheet_auto_filter_finiteIndex(value, fallback) {
|
|
16410
|
-
return 'number' == typeof value && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : fallback;
|
|
16411
|
-
}
|
|
16412
17833
|
function useSpreadsheetAutoFilter({ canvasRef, content, editable, mountRevision, onChange, selection, sheetId, workbook = null }) {
|
|
16413
17834
|
const contentRef = useRef(content);
|
|
16414
17835
|
const editableRef = useRef(editable);
|
|
@@ -19984,6 +21405,206 @@ function spreadsheetHyperlinkValidationMessage(content, source, value) {
|
|
|
19984
21405
|
function spreadsheetHyperlinkFailureMessage(content, source, value, fallback) {
|
|
19985
21406
|
return spreadsheetHyperlinkValidationMessage(content, source, value) ?? fallback;
|
|
19986
21407
|
}
|
|
21408
|
+
function SpreadsheetTableDialog({ source, restoreFocusTarget, onApply, onClose, onValidate }) {
|
|
21409
|
+
const [value, setValue] = useState(source.value);
|
|
21410
|
+
const [touched, setTouched] = useState(false);
|
|
21411
|
+
const formId = useId();
|
|
21412
|
+
const validationError = onValidate(value);
|
|
21413
|
+
const visibleError = touched ? validationError : null;
|
|
21414
|
+
const submit = (event)=>{
|
|
21415
|
+
event.preventDefault();
|
|
21416
|
+
setTouched(true);
|
|
21417
|
+
if (validationError) return;
|
|
21418
|
+
if (onApply(value)) onClose();
|
|
21419
|
+
};
|
|
21420
|
+
return /*#__PURE__*/ jsx(Dialog, {
|
|
21421
|
+
title: "创建表格",
|
|
21422
|
+
description: source.sheetName,
|
|
21423
|
+
className: "work-spreadsheet-table-dialog",
|
|
21424
|
+
restoreFocusTarget: restoreFocusTarget,
|
|
21425
|
+
onClose: onClose,
|
|
21426
|
+
footer: /*#__PURE__*/ jsxs(Fragment, {
|
|
21427
|
+
children: [
|
|
21428
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
21429
|
+
tone: "quiet",
|
|
21430
|
+
onClick: onClose,
|
|
21431
|
+
children: "取消"
|
|
21432
|
+
}),
|
|
21433
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
21434
|
+
tone: "primary",
|
|
21435
|
+
type: "submit",
|
|
21436
|
+
form: formId,
|
|
21437
|
+
disabled: Boolean(validationError),
|
|
21438
|
+
children: "确定"
|
|
21439
|
+
})
|
|
21440
|
+
]
|
|
21441
|
+
}),
|
|
21442
|
+
children: /*#__PURE__*/ jsxs("form", {
|
|
21443
|
+
id: formId,
|
|
21444
|
+
onSubmit: submit,
|
|
21445
|
+
children: [
|
|
21446
|
+
/*#__PURE__*/ jsxs("div", {
|
|
21447
|
+
className: "work-spreadsheet-table-scope",
|
|
21448
|
+
children: [
|
|
21449
|
+
/*#__PURE__*/ jsx("span", {
|
|
21450
|
+
"aria-hidden": "true",
|
|
21451
|
+
children: /*#__PURE__*/ jsx(Table2, {
|
|
21452
|
+
size: 18
|
|
21453
|
+
})
|
|
21454
|
+
}),
|
|
21455
|
+
/*#__PURE__*/ jsxs("div", {
|
|
21456
|
+
children: [
|
|
21457
|
+
/*#__PURE__*/ jsx("strong", {
|
|
21458
|
+
children: source.name
|
|
21459
|
+
}),
|
|
21460
|
+
/*#__PURE__*/ jsx("small", {
|
|
21461
|
+
children: "将连续数据区域转换为原生工作表表格"
|
|
21462
|
+
})
|
|
21463
|
+
]
|
|
21464
|
+
})
|
|
21465
|
+
]
|
|
21466
|
+
}),
|
|
21467
|
+
/*#__PURE__*/ jsx(field_Field, {
|
|
21468
|
+
label: "表格区域",
|
|
21469
|
+
required: true,
|
|
21470
|
+
error: visibleError ?? void 0,
|
|
21471
|
+
description: "输入一个连续区域,例如 A1:C20。",
|
|
21472
|
+
children: /*#__PURE__*/ jsx("input", {
|
|
21473
|
+
type: "text",
|
|
21474
|
+
autoCapitalize: "none",
|
|
21475
|
+
autoFocus: true,
|
|
21476
|
+
spellCheck: false,
|
|
21477
|
+
value: value.rangeReference,
|
|
21478
|
+
onBlur: ()=>setTouched(true),
|
|
21479
|
+
onChange: (event)=>{
|
|
21480
|
+
const rangeReference = event.currentTarget.value;
|
|
21481
|
+
setValue((current)=>({
|
|
21482
|
+
...current,
|
|
21483
|
+
rangeReference
|
|
21484
|
+
}));
|
|
21485
|
+
setTouched(true);
|
|
21486
|
+
}
|
|
21487
|
+
})
|
|
21488
|
+
}),
|
|
21489
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
21490
|
+
ariaLabel: "表包含标题",
|
|
21491
|
+
checked: value.headerRow,
|
|
21492
|
+
onCheckedChange: (headerRow)=>setValue((current)=>({
|
|
21493
|
+
...current,
|
|
21494
|
+
headerRow
|
|
21495
|
+
})),
|
|
21496
|
+
children: "表包含标题"
|
|
21497
|
+
})
|
|
21498
|
+
]
|
|
21499
|
+
})
|
|
21500
|
+
});
|
|
21501
|
+
}
|
|
21502
|
+
function useSpreadsheetTable({ commandsRef, contentRef, focusGrid, getGridFocusTarget, getLiveSelection, preview }) {
|
|
21503
|
+
const [source, setSource] = useState(null);
|
|
21504
|
+
const invokerRef = useRef(null);
|
|
21505
|
+
const selectionRef = useRef(null);
|
|
21506
|
+
const applyingRef = useRef(false);
|
|
21507
|
+
const appliedRef = useRef(false);
|
|
21508
|
+
useEffect(()=>{
|
|
21509
|
+
if (!preview) return;
|
|
21510
|
+
setSource(null);
|
|
21511
|
+
invokerRef.current = null;
|
|
21512
|
+
selectionRef.current = null;
|
|
21513
|
+
applyingRef.current = false;
|
|
21514
|
+
appliedRef.current = false;
|
|
21515
|
+
}, [
|
|
21516
|
+
preview
|
|
21517
|
+
]);
|
|
21518
|
+
const open = useCallback((target)=>{
|
|
21519
|
+
if (preview || source) return false;
|
|
21520
|
+
const nextSource = createSpreadsheetTableDialogSource(contentRef.current, target);
|
|
21521
|
+
if (!nextSource) {
|
|
21522
|
+
showToast('请选择包含标题和至少一行数据的连续、未合并区域。', 'error');
|
|
21523
|
+
return false;
|
|
21524
|
+
}
|
|
21525
|
+
const grid = getGridFocusTarget();
|
|
21526
|
+
invokerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : grid;
|
|
21527
|
+
selectionRef.current = {
|
|
21528
|
+
sheetId: target.sheetId,
|
|
21529
|
+
selection: finiteSpreadsheetSelection(getLiveSelection() ?? target.selection)
|
|
21530
|
+
};
|
|
21531
|
+
appliedRef.current = false;
|
|
21532
|
+
setSource(nextSource);
|
|
21533
|
+
return true;
|
|
21534
|
+
}, [
|
|
21535
|
+
contentRef,
|
|
21536
|
+
getGridFocusTarget,
|
|
21537
|
+
getLiveSelection,
|
|
21538
|
+
preview,
|
|
21539
|
+
source
|
|
21540
|
+
]);
|
|
21541
|
+
const close = useCallback(()=>{
|
|
21542
|
+
const invoker = invokerRef.current;
|
|
21543
|
+
const grid = getGridFocusTarget();
|
|
21544
|
+
const restoreGrid = appliedRef.current || invoker === grid;
|
|
21545
|
+
setSource(null);
|
|
21546
|
+
requestAnimationFrame(()=>{
|
|
21547
|
+
if (restoreGrid || !invoker?.isConnected) focusGrid(invoker);
|
|
21548
|
+
else invoker.focus({
|
|
21549
|
+
preventScroll: true
|
|
21550
|
+
});
|
|
21551
|
+
if (invokerRef.current === invoker) invokerRef.current = null;
|
|
21552
|
+
selectionRef.current = null;
|
|
21553
|
+
appliedRef.current = false;
|
|
21554
|
+
});
|
|
21555
|
+
}, [
|
|
21556
|
+
focusGrid,
|
|
21557
|
+
getGridFocusTarget
|
|
21558
|
+
]);
|
|
21559
|
+
const commandPort = useMemo(()=>({
|
|
21560
|
+
canOpen: !preview && null === source,
|
|
21561
|
+
open
|
|
21562
|
+
}), [
|
|
21563
|
+
open,
|
|
21564
|
+
preview,
|
|
21565
|
+
source
|
|
21566
|
+
]);
|
|
21567
|
+
const selectionForChange = useCallback(()=>applyingRef.current ? selectionRef.current : null, []);
|
|
21568
|
+
return {
|
|
21569
|
+
commandPort,
|
|
21570
|
+
selectionForChange,
|
|
21571
|
+
dialog: source ? /*#__PURE__*/ jsx(SpreadsheetTableDialog, {
|
|
21572
|
+
source: source,
|
|
21573
|
+
restoreFocusTarget: ()=>appliedRef.current ? getGridFocusTarget() : invokerRef.current?.isConnected ? invokerRef.current : getGridFocusTarget(),
|
|
21574
|
+
onApply: (value)=>{
|
|
21575
|
+
const range = spreadsheetTableRangeFromText(value.rangeReference);
|
|
21576
|
+
if (!range) return false;
|
|
21577
|
+
applyingRef.current = true;
|
|
21578
|
+
let handled = false;
|
|
21579
|
+
try {
|
|
21580
|
+
handled = commandsRef.current?.applyTable({
|
|
21581
|
+
headerRow: value.headerRow,
|
|
21582
|
+
name: source.name,
|
|
21583
|
+
range,
|
|
21584
|
+
sheetId: source.sheetId
|
|
21585
|
+
}) ?? false;
|
|
21586
|
+
appliedRef.current = handled;
|
|
21587
|
+
} finally{
|
|
21588
|
+
applyingRef.current = false;
|
|
21589
|
+
}
|
|
21590
|
+
if (!handled) showToast(spreadsheetTableValidationMessage(contentRef.current, source, value) ?? '无法创建表格。', 'error');
|
|
21591
|
+
return handled;
|
|
21592
|
+
},
|
|
21593
|
+
onClose: close,
|
|
21594
|
+
onValidate: (value)=>spreadsheetTableValidationMessage(contentRef.current, source, value)
|
|
21595
|
+
}) : null
|
|
21596
|
+
};
|
|
21597
|
+
}
|
|
21598
|
+
function spreadsheetTableValidationMessage(content, source, value) {
|
|
21599
|
+
const range = spreadsheetTableRangeFromText(value.rangeReference);
|
|
21600
|
+
if (!range) return '请输入一个连续区域。';
|
|
21601
|
+
return spreadsheetTableFailureMessage(content, {
|
|
21602
|
+
headerRow: value.headerRow,
|
|
21603
|
+
name: source.name,
|
|
21604
|
+
range,
|
|
21605
|
+
sheetId: source.sheetId
|
|
21606
|
+
});
|
|
21607
|
+
}
|
|
19987
21608
|
const MAXIMUM_BUFFERED_SPREADSHEET_OPERATIONS = 10001;
|
|
19988
21609
|
function useSpreadsheetWorkbookSync(content, synchronizeExternalWorkbook) {
|
|
19989
21610
|
const mountedContentRef = useRef(content);
|
|
@@ -20117,6 +21738,14 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20117
21738
|
getLiveSelections: getSpreadsheetDataValidationLiveSelections,
|
|
20118
21739
|
preview
|
|
20119
21740
|
});
|
|
21741
|
+
const spreadsheetTable = useSpreadsheetTable({
|
|
21742
|
+
commandsRef: spreadsheetCommandsRef,
|
|
21743
|
+
contentRef,
|
|
21744
|
+
focusGrid: focusSpreadsheetDialogGrid,
|
|
21745
|
+
getGridFocusTarget: getSpreadsheetDialogGridFocusTarget,
|
|
21746
|
+
getLiveSelection: getSpreadsheetHyperlinkLiveSelection,
|
|
21747
|
+
preview
|
|
21748
|
+
});
|
|
20120
21749
|
const officeDialog = useOfficeDialog();
|
|
20121
21750
|
const [findOpen, setFindOpen] = useState(false);
|
|
20122
21751
|
const [findFocusRequest, setFindFocusRequest] = useState(0);
|
|
@@ -20149,6 +21778,16 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20149
21778
|
]);
|
|
20150
21779
|
const conditionalStylesBySheetRef = useRef(conditionalStylesBySheet);
|
|
20151
21780
|
conditionalStylesBySheetRef.current = conditionalStylesBySheet;
|
|
21781
|
+
const tableStylesBySheet = useMemo(()=>new Map(materializedContent.sheets.flatMap((sheet)=>sheet.id ? [
|
|
21782
|
+
[
|
|
21783
|
+
sheet.id,
|
|
21784
|
+
createSpreadsheetTableRenderResolver(sheet.tables ?? [])
|
|
21785
|
+
]
|
|
21786
|
+
] : [])), [
|
|
21787
|
+
materializedContent.sheets
|
|
21788
|
+
]);
|
|
21789
|
+
const tableStylesBySheetRef = useRef(tableStylesBySheet);
|
|
21790
|
+
tableStylesBySheetRef.current = tableStylesBySheet;
|
|
20152
21791
|
useEffect(()=>{
|
|
20153
21792
|
setPreviewActiveSheetId(preview ? contentActiveSheetId : null);
|
|
20154
21793
|
}, [
|
|
@@ -20259,21 +21898,28 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20259
21898
|
endColumn: Math.max(selection.column[0], selection.column[1])
|
|
20260
21899
|
}).length);
|
|
20261
21900
|
},
|
|
20262
|
-
beforeRenderCell: (
|
|
21901
|
+
beforeRenderCell: (cell, cellInfo, context)=>{
|
|
21902
|
+
const tableStyle = tableStylesBySheetRef.current.get(activeSheetIdRef.current)?.(cellInfo.row, cellInfo.column) ?? null;
|
|
20263
21903
|
const style = conditionalStylesBySheetRef.current.get(activeSheetIdRef.current)?.get(`${cellInfo.row}_${cellInfo.column}`);
|
|
20264
|
-
|
|
21904
|
+
beginSpreadsheetTableCellRender(cell, tableStyle, style, context);
|
|
20265
21905
|
return true;
|
|
20266
21906
|
},
|
|
20267
21907
|
afterRenderCell: (cell, cellInfo, context)=>{
|
|
21908
|
+
const tableStyle = tableStylesBySheetRef.current.get(activeSheetIdRef.current)?.(cellInfo.row, cellInfo.column) ?? null;
|
|
20268
21909
|
const style = conditionalStylesBySheetRef.current.get(activeSheetIdRef.current)?.get(`${cellInfo.row}_${cellInfo.column}`);
|
|
20269
|
-
|
|
20270
|
-
|
|
20271
|
-
|
|
20272
|
-
|
|
20273
|
-
|
|
20274
|
-
|
|
20275
|
-
|
|
20276
|
-
|
|
21910
|
+
try {
|
|
21911
|
+
if (style?.icon || style?.dataBar) {
|
|
21912
|
+
const background = style.cellColor ?? tableStyle?.background ?? ('string' == typeof cell?.bg ? cell.bg : '#ffffff');
|
|
21913
|
+
if (style.dataBar) drawSpreadsheetConditionalDataBar(context, cellInfo, {
|
|
21914
|
+
...style.dataBar,
|
|
21915
|
+
showValue: style.dataBar.showValue && (style.icon?.showValue ?? true)
|
|
21916
|
+
}, cell, background, style.textColor);
|
|
21917
|
+
if (style.icon) drawSpreadsheetConditionalIcon(context, cellInfo, style.icon, background, style.dataBar ? false : !style.icon.showValue);
|
|
21918
|
+
if (cell?.ps) drawSpreadsheetCommentMarker(context, cellInfo);
|
|
21919
|
+
}
|
|
21920
|
+
} finally{
|
|
21921
|
+
finishSpreadsheetTableCellRender(cell, cellInfo, tableStyle, context);
|
|
21922
|
+
}
|
|
20277
21923
|
}
|
|
20278
21924
|
}), [
|
|
20279
21925
|
collaborationView
|
|
@@ -20393,6 +22039,17 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20393
22039
|
const toolbarColumn = toolbarSelection.column_focus ?? toolbarSelection.column[0];
|
|
20394
22040
|
const toolbarCell = spreadsheetCellAt(toolbarSheet, toolbarRow, toolbarColumn);
|
|
20395
22041
|
const toolbarCellBorders = spreadsheetCellBordersAt(toolbarSheet, toolbarRow, toolbarColumn);
|
|
22042
|
+
const toolbarContentSheet = materializedContent.sheets.find((sheet)=>sheet.id === toolbarSheetId);
|
|
22043
|
+
const activeTable = spreadsheetTableAtCell(toolbarContentSheet, toolbarRow, toolbarColumn);
|
|
22044
|
+
const activeTableId = activeTable?.id ?? null;
|
|
22045
|
+
useEffect(()=>{
|
|
22046
|
+
setRibbonTab((current)=>{
|
|
22047
|
+
if (activeTableId) return 'tableDesign' === current ? current : 'tableDesign';
|
|
22048
|
+
return 'tableDesign' === current ? 'home' : current;
|
|
22049
|
+
});
|
|
22050
|
+
}, [
|
|
22051
|
+
activeTableId
|
|
22052
|
+
]);
|
|
20396
22053
|
const selectedRange = spreadsheetSingleRange(toolbarSelection);
|
|
20397
22054
|
const multipleCellsSelected = selectedRange.row[0] !== selectedRange.row[1] || selectedRange.column[0] !== selectedRange.column[1];
|
|
20398
22055
|
const selectionSummary = multipleCellsSelected ? spreadsheetSelectionSummary(toolbarSheet, toolbarSelection) : null;
|
|
@@ -20633,12 +22290,18 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20633
22290
|
onChange: (next)=>{
|
|
20634
22291
|
const formatCellsSelection = formatCellsApplyingRef.current ? formatCellsSelectionRef.current : null;
|
|
20635
22292
|
const dataValidationSelection = spreadsheetDataValidation.selectionForChange();
|
|
22293
|
+
const tableSelection = spreadsheetTable.selectionForChange();
|
|
20636
22294
|
const hyperlinkSelection = spreadsheetHyperlink.selectionForChange();
|
|
20637
22295
|
const preservedSelection = formatCellsSelection ? {
|
|
20638
22296
|
sheetId: formatCellsSelection.sheetId,
|
|
20639
22297
|
selections: [
|
|
20640
22298
|
formatCellsSelection.selection
|
|
20641
22299
|
]
|
|
22300
|
+
} : tableSelection ? {
|
|
22301
|
+
sheetId: tableSelection.sheetId,
|
|
22302
|
+
selections: [
|
|
22303
|
+
tableSelection.selection
|
|
22304
|
+
]
|
|
20642
22305
|
} : dataValidationSelection ?? (hyperlinkSelection ? {
|
|
20643
22306
|
sheetId: hyperlinkSelection.sheetId,
|
|
20644
22307
|
selections: [
|
|
@@ -20650,6 +22313,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20650
22313
|
onChange(controlled);
|
|
20651
22314
|
},
|
|
20652
22315
|
selection: selectionState,
|
|
22316
|
+
table: spreadsheetTable.commandPort,
|
|
20653
22317
|
targetSheetGridSize,
|
|
20654
22318
|
targetSheetId: toolbarSheetId,
|
|
20655
22319
|
toolbarCell,
|
|
@@ -20853,6 +22517,8 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
20853
22517
|
}),
|
|
20854
22518
|
!preview && /*#__PURE__*/ jsx(SpreadsheetEditorRibbon, {
|
|
20855
22519
|
activeTab: ribbonTab,
|
|
22520
|
+
activeTable: activeTable,
|
|
22521
|
+
activeTableSheetId: activeTable ? toolbarSheetId : void 0,
|
|
20856
22522
|
autoFilterActive: autoFilterActive,
|
|
20857
22523
|
can: spreadsheetCan,
|
|
20858
22524
|
commands: spreadsheetRibbonCommands,
|
|
@@ -21075,6 +22741,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
21075
22741
|
}),
|
|
21076
22742
|
spreadsheetDataValidation.dialog,
|
|
21077
22743
|
spreadsheetHyperlink.dialog,
|
|
22744
|
+
spreadsheetTable.dialog,
|
|
21078
22745
|
spreadsheetClipboard.dialogSource && /*#__PURE__*/ jsx(SpreadsheetPasteSpecialDialog, {
|
|
21079
22746
|
source: spreadsheetClipboard.dialogSource,
|
|
21080
22747
|
restoreFocusTarget: spreadsheetClipboard.restoreDialogFocusTarget,
|
|
@@ -21187,6 +22854,7 @@ function spreadsheetCommandsWithGridFocus(commands, restoreFocus) {
|
|
|
21187
22854
|
cancelFormatPainter: afterSuccessfulCommand(commands.cancelFormatPainter),
|
|
21188
22855
|
clearSelectedCells: afterSuccessfulCommand(commands.clearSelectedCells),
|
|
21189
22856
|
copySelection: afterSuccessfulCommand(commands.copySelection),
|
|
22857
|
+
convertTableToRange: afterSuccessfulCommand(commands.convertTableToRange),
|
|
21190
22858
|
cutSelection: afterSuccessfulCommand(commands.cutSelection),
|
|
21191
22859
|
deleteSelectedStructure: afterSuccessfulCommand(commands.deleteSelectedStructure),
|
|
21192
22860
|
fillSelectedCells: afterSuccessfulCommand(commands.fillSelectedCells),
|