@a3s-lab/office 0.35.0 → 0.37.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/README.md +34 -10
- package/dist/0~7048.js +590 -3
- package/dist/0~spreadsheet-editor.js +515 -44
- package/dist/0~work-office-diagnostics.js +1 -1
- package/dist/3266.js +549 -10
- package/dist/4121.js +2202 -1942
- package/dist/8715.js +299 -299
- package/dist/core.js +41 -4
- package/dist/internal/features/work/editors/spreadsheet-calculation-model.d.ts +1 -1
- package/dist/internal/features/work/editors/spreadsheet-calculation-projection.d.ts +5 -2
- package/dist/internal/features/work/editors/spreadsheet-table-calculated-columns.d.ts +42 -0
- package/dist/internal/features/work/editors/spreadsheet-table-totals.d.ts +39 -0
- package/dist/internal/features/work/editors/spreadsheet-table.d.ts +11 -1
- package/dist/internal/features/work/work-types.d.ts +20 -1
- package/dist/internal/kernel/office-kernel-protocol.d.ts +1 -1
- package/dist/internal/kernel/office-kernel-spreadsheet-fallback-formula.d.ts +11 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-protocol.d.ts +18 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-structured-reference.d.ts +48 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +598 -3
- package/dist/styles.css +120 -0
- package/docs/latest/en/browser-editor-architecture.md +27 -8
- package/package.json +4 -1
|
@@ -6,7 +6,7 @@ import { Fragment as external_react_Fragment, cloneElement, memo, useCallback, u
|
|
|
6
6
|
import { convertSpanToShareString, genarate, indexToColumnChar, update as core_update } from "@fortune-sheet/core";
|
|
7
7
|
import { freezeImportedSpreadsheetCell, normalizeXlsxSemanticColorOrigin, spreadsheetMatrixProfile, withXlsxPatternFill, withoutEditableRange, normalizeSpreadsheetConditionalVisualOptions, xlsxSemanticColorMatchesValue, withXlsxGradientFill, effectiveSpreadsheetPageSetup, attachSpreadsheetShownCommentCells, normalizeXlsxPatternFill, withEditableRange, sameSpreadsheetHistoryValue, isSpreadsheetConditionalComparisonOperator, spreadsheetConditionalIconForValue, defaultSpreadsheetConditionalIconThresholds, xlsxPatternFillTypes, sheetProtectionAuthority, normalizeXlsxGradientFill, xlsxGradientFillFallbackColor, editableRangeCellCount, unlockedCellCount, registerDerivedSpreadsheetMatrix, editableRangeRequiresCredentials, SPREADSHEET_CONDITIONAL_COMPARISON_OPERATORS, normalizeSpreadsheetConditionalIconSetFormat, defaultSpreadsheetDataBarOptions, spreadsheetConditionalThresholdValue, normalizeSheetProtectionAuthority, withSheetProtection, spreadsheetProtectionKey, defaultSpreadsheetColorScaleThresholds, protectedSheetCount, SPREADSHEET_CONDITIONAL_ICON_SETS, withSheetSelectionPermissions, spreadsheetConditionalComparisonNeedsUpperValue, drawSpreadsheetConditionalIcon, spreadsheetConditionalThresholdsEqual } from "./9333.js";
|
|
8
8
|
import { workSpreadsheetChartSupportsGrouping, spreadsheetFormulaRangesForSelection, createSpreadsheetChartFromSelection, normalizeWorkSpreadsheetDataLabelPosition, normalizeSpreadsheetPrintTitleColumns, normalizeSpreadsheetPrintTitleRows, formulaHasStructuredReference, normalizeWorkSpreadsheetErrorBars, defaultPivotValueCaption, workSpreadsheetChartSupportsBarSpacing, normalizeWorkSpreadsheetChartGrouping, spreadsheetGridSize, normalizeWorkSpreadsheetChartAxisGroup, normalizeWorkSpreadsheetScatterStyle, cloneSparseMatrix, spreadsheetPivotAggregationLabel, workSpreadsheetChartAxisIsCategoryAxis, reconcileSpreadsheetChartPreviews, normalizeWorkSpreadsheetChartAxes, normalizeWorkSpreadsheetDoughnutHoleSize, normalizeWorkSpreadsheetChartLegendPosition, spreadsheetChartCount, workSpreadsheetChartTypeLabel, sparseArrayEntries, normalizeWorkSpreadsheetTrendline, effectiveSpreadsheetCalculationSettings, spreadsheetPivotIntersects, normalizeWorkSpreadsheetDataLabels, spreadsheetPivotOutputContains, normalizeSpreadsheetPrintArea, spreadsheetCellAddress, formatSpreadsheetCellRanges, normalizeWorkSpreadsheetChartLayout, spreadsheetFormulaRangeForCell, workSpreadsheetChartAxisIsValueAxis, normalizeWorkSpreadsheetChartSmoothLines, spreadsheetPivotFilterValueKey, normalizeWorkSpreadsheetBubbleScale, normalizeWorkSpreadsheetChartSeriesStyle, volatileSpreadsheetFormulaFunctions, sparseArrayIndexes, normalizeWorkSpreadsheetBubbleSizeRepresents, workSpreadsheetChartSupportsTrendlines, normalizeWorkSpreadsheetChartLegendOverlay, parseSpreadsheetChartReference, workSpreadsheetChartGroupingIsStacked, normalizeWorkSpreadsheetChartGapWidth, workSpreadsheetChartSupportsSmoothLines, refreshSpreadsheetPivotTables, createSpreadsheetPivotFromSelection, reconcileSpreadsheetPivots, spreadsheetPivotCount, sparseMatrixColumnCount, workSpreadsheetChartSupportsErrorBars, formulaHasExternalReference, isValidSpreadsheetDefinedName, spreadsheetPivotValidation, deleteSpreadsheetPivotTable, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartSupportsSeriesAnalysis, parseSpreadsheetCellRanges, spreadsheetPivotFilterItems, spreadsheetPivotFields, normalizeWorkSpreadsheetChartOverlap, spreadsheetFormulaRangeConflict, spreadsheetSheetsWithChartPreviews, workSpreadsheetChartUsesNumericXAxis, workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartSupportsAxes, normalizeWorkSpreadsheetCombinationSeriesType, normalizeWorkSpreadsheetRadarStyle } from "./8715.js";
|
|
9
|
-
import {
|
|
9
|
+
import { reconcileSpreadsheetTableCalculatedColumns, isSpreadsheetTextOrientationId, spreadsheetTextOrientationFromChoice, xlsxRichTextCellText, spreadsheetTextOrientationFromAngle, replaceOfficeSpreadsheetCollaboration as replaceWorkOfficeSpreadsheetCollaboration, spreadsheetCellValueWithDiagonalBorder, spreadsheetUnderlineCellValue, normalizeSpreadsheetDataValidationErrorStyle, readOfficeSpreadsheetCollaboration as readWorkOfficeSpreadsheetCollaboration, spreadsheetTableTotalsFunctionLabel, withDefaultSpreadsheetTableTotalsLabel, normalizeXlsxRichTextEditSource, spreadsheetTableTotalsColumnPatch, normalizeXlsxRichTextColor, isHighSurrogate, xlsxNativeFillCellKeys, createOfficeSpreadsheetCollaborationBinding as createWorkOfficeSpreadsheetCollaborationBinding, SPREADSHEET_TABLE_TOTALS_FUNCTIONS, boundedSpreadsheetDataValidationText, normalizeXlsxRichTextCell, activeXlsxNativeFill, spreadsheetUnderlineStyle, normalizeSpreadsheetDateValidationBoundary, deleteXlsxNativeFills, spreadsheetTextOrientationCellStyle, spreadsheetTextOrientationChoiceFromCell, normalizeXlsxRichTextRun, spreadsheetDiagonalBorderFromCellValue, sameXlsxRichTextRunStyle, isLowSurrogate, spreadsheetTableTotalsRowHasContent, reconcileSpreadsheetTableTotalsColumns, spreadsheetTextOrientationFromCell, coalesceXlsxRichTextRuns, fillSpreadsheetTableCalculatedColumns, synchronizeSpreadsheetTableTotalsRow, validXlsxRichText, patchSpreadsheetRichTextFontRuns, isSpreadsheetUnderlineStyle, spreadsheetVisibleTextRotationFromCell } from "./3266.js";
|
|
10
10
|
import { moveOfficeMenuFocus, stepOfficeZoom, useOfficeRemoteParticipants, Popover, Dialog, officePresenceColor, useOfficePublishPresenceLocation, button_Button, icon_button_IconButton, moveOfficeGridMenuFocus, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom } from "./0~8136.js";
|
|
11
11
|
import { isOfficeKernelSpreadsheetError, normalizeCssColor, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, createOfficeId as createWorkId } from "./4121.js";
|
|
12
12
|
import { useOfficeTaskPaneEscape, OfficeCheckbox, CommittedOfficeNumberField, useOfficeDialog, useOfficeTaskPaneModal, createOfficeKernelClient, officeFontFamilies, CollectionState, OfficeNumberField, handleOfficeTaskPaneKeyDown } from "./0~7048.js";
|
|
@@ -3769,12 +3769,23 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3769
3769
|
const sheetOperations = operations.filter((operation)=>operation.id === source.id);
|
|
3770
3770
|
let tables = source.tables;
|
|
3771
3771
|
const reconcileColumns = new Set();
|
|
3772
|
+
const calculatedColumnRows = new Map();
|
|
3773
|
+
const editedTotalsColumns = new Map();
|
|
3772
3774
|
if (!operations.length) for (const table of tables)reconcileColumns.add(table.id);
|
|
3773
3775
|
for (const operation of sheetOperations){
|
|
3774
3776
|
const structure = spreadsheetTableStructureChangeFromOperation(operation);
|
|
3775
3777
|
if (structure) {
|
|
3778
|
+
transformCalculatedColumnRows(calculatedColumnRows, structure);
|
|
3776
3779
|
const transformed = [];
|
|
3777
3780
|
for (const table of tables){
|
|
3781
|
+
if ('row' === structure.axis && 'insert' === structure.kind) {
|
|
3782
|
+
const insertedRows = rowsInsertedIntoSpreadsheetTableBody(table, structure);
|
|
3783
|
+
if (insertedRows.length) {
|
|
3784
|
+
const rows = calculatedColumnRows.get(table.id) ?? new Set();
|
|
3785
|
+
for (const row of insertedRows)rows.add(row);
|
|
3786
|
+
calculatedColumnRows.set(table.id, rows);
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3778
3789
|
const next = transformSpreadsheetTableStructure(table, structure);
|
|
3779
3790
|
if (next) {
|
|
3780
3791
|
transformed.push(next);
|
|
@@ -3786,15 +3797,33 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3786
3797
|
}
|
|
3787
3798
|
const coordinate = spreadsheetCellCoordinateFromOperation(operation);
|
|
3788
3799
|
if (!coordinate) continue;
|
|
3789
|
-
const table = tables.find((candidate)=>candidate
|
|
3790
|
-
if (table)
|
|
3800
|
+
const table = tables.find((candidate)=>spreadsheetTableContainsCell(candidate, coordinate.row, coordinate.column));
|
|
3801
|
+
if (table) {
|
|
3802
|
+
reconcileColumns.add(table.id);
|
|
3803
|
+
if (table.totalsRow && coordinate.row === table.range.row[1]) {
|
|
3804
|
+
const offset = coordinate.column - table.range.column[0];
|
|
3805
|
+
if (offset >= 0 && offset < table.columns.length) {
|
|
3806
|
+
const offsets = editedTotalsColumns.get(table.id) ?? new Set();
|
|
3807
|
+
offsets.add(offset);
|
|
3808
|
+
editedTotalsColumns.set(table.id, offsets);
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3791
3812
|
}
|
|
3792
3813
|
const updates = [];
|
|
3793
3814
|
const readCell = spreadsheetSheetCellReader(sheet);
|
|
3794
3815
|
tables = tables.map((table)=>{
|
|
3795
3816
|
if (!reconcileColumns.has(table.id)) return table;
|
|
3796
3817
|
const columns = canonicalSpreadsheetTableColumns(table, readCell);
|
|
3797
|
-
|
|
3818
|
+
const calculatedColumns = reconcileSpreadsheetTableCalculatedColumns(sheet, {
|
|
3819
|
+
...table,
|
|
3820
|
+
columns
|
|
3821
|
+
});
|
|
3822
|
+
const reconciledColumns = reconcileSpreadsheetTableTotalsColumns(sheet, {
|
|
3823
|
+
...table,
|
|
3824
|
+
columns: calculatedColumns
|
|
3825
|
+
}, editedTotalsColumns.get(table.id));
|
|
3826
|
+
if (table.headerRow) for (const [offset, column] of reconciledColumns.entries()){
|
|
3798
3827
|
const cellColumn = table.range.column[0] + offset;
|
|
3799
3828
|
if (spreadsheetCellText(readCell(table.range.row[0], cellColumn)) !== column.name) updates.push({
|
|
3800
3829
|
column: cellColumn,
|
|
@@ -3802,14 +3831,26 @@ function reconcileSpreadsheetTablesAfterFortune(sheets, sourceSheets, operations
|
|
|
3802
3831
|
row: table.range.row[0]
|
|
3803
3832
|
});
|
|
3804
3833
|
}
|
|
3805
|
-
return sameSpreadsheetTableColumns(table.columns,
|
|
3834
|
+
return sameSpreadsheetTableColumns(table.columns, reconciledColumns) ? table : {
|
|
3806
3835
|
...table,
|
|
3807
|
-
columns
|
|
3836
|
+
columns: reconciledColumns
|
|
3808
3837
|
};
|
|
3809
3838
|
});
|
|
3810
|
-
|
|
3839
|
+
let withCalculatedColumns = sheet;
|
|
3840
|
+
for (const table of tables){
|
|
3841
|
+
const rows = calculatedColumnRows.get(table.id);
|
|
3842
|
+
if (rows?.size) withCalculatedColumns = fillSpreadsheetTableCalculatedColumns(withCalculatedColumns, table, [
|
|
3843
|
+
...rows
|
|
3844
|
+
]);
|
|
3845
|
+
}
|
|
3846
|
+
const withHeaders = stampSpreadsheetTableHeaderCells(withCalculatedColumns, updates);
|
|
3847
|
+
let withTotals = withHeaders;
|
|
3848
|
+
for (const table of tables){
|
|
3849
|
+
const previous = source.tables.find((candidate)=>candidate.id === table.id);
|
|
3850
|
+
withTotals = synchronizeSpreadsheetTableTotalsRow(withTotals, previous, table);
|
|
3851
|
+
}
|
|
3811
3852
|
return {
|
|
3812
|
-
...
|
|
3853
|
+
...withTotals,
|
|
3813
3854
|
tables: tables.length ? tables : void 0
|
|
3814
3855
|
};
|
|
3815
3856
|
});
|
|
@@ -3870,6 +3911,39 @@ function transformSpreadsheetTableStructure(table, change) {
|
|
|
3870
3911
|
filters: filtersAfterSpreadsheetTableColumnDeletion(table.filters, transformed.offset, removed)
|
|
3871
3912
|
};
|
|
3872
3913
|
}
|
|
3914
|
+
function spreadsheetTableContainsCell(table, row, column) {
|
|
3915
|
+
return row >= table.range.row[0] && row <= table.range.row[1] && column >= table.range.column[0] && column <= table.range.column[1];
|
|
3916
|
+
}
|
|
3917
|
+
function rowsInsertedIntoSpreadsheetTableBody(table, change) {
|
|
3918
|
+
if ('row' !== change.axis) return [];
|
|
3919
|
+
const transformed = transformSpreadsheetTableAxisForInsertion(table.range.row, change);
|
|
3920
|
+
if (!transformed.inside) return [];
|
|
3921
|
+
const insertion = change.index + ('rightbottom' === change.direction ? 1 : 0);
|
|
3922
|
+
const bodyStart = table.range.row[0] + Number(table.headerRow);
|
|
3923
|
+
if (insertion < bodyStart) return [];
|
|
3924
|
+
return Array.from({
|
|
3925
|
+
length: change.count
|
|
3926
|
+
}, (_, offset)=>insertion + offset);
|
|
3927
|
+
}
|
|
3928
|
+
function transformCalculatedColumnRows(rowsByTable, change) {
|
|
3929
|
+
if ('row' !== change.axis || !rowsByTable.size) return;
|
|
3930
|
+
if ('insert' === change.kind) {
|
|
3931
|
+
const insertion = change.index + ('rightbottom' === change.direction ? 1 : 0);
|
|
3932
|
+
for (const [tableId, rows] of rowsByTable){
|
|
3933
|
+
const next = new Set();
|
|
3934
|
+
for (const row of rows)next.add(row >= insertion ? row + change.count : row);
|
|
3935
|
+
rowsByTable.set(tableId, next);
|
|
3936
|
+
}
|
|
3937
|
+
return;
|
|
3938
|
+
}
|
|
3939
|
+
const count = change.end - change.start + 1;
|
|
3940
|
+
for (const [tableId, rows] of rowsByTable){
|
|
3941
|
+
const next = new Set();
|
|
3942
|
+
for (const row of rows)if (row < change.start) next.add(row);
|
|
3943
|
+
else if (row > change.end) next.add(row - count);
|
|
3944
|
+
rowsByTable.set(tableId, next);
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3873
3947
|
function transformSpreadsheetTableAxisForInsertion(axis, change) {
|
|
3874
3948
|
const start = axis[0] ?? 0;
|
|
3875
3949
|
const end = axis[1] ?? start;
|
|
@@ -3967,6 +4041,7 @@ function canonicalSpreadsheetTableColumns(table, readCell) {
|
|
|
3967
4041
|
}
|
|
3968
4042
|
observed.add(candidate.toLocaleLowerCase());
|
|
3969
4043
|
return {
|
|
4044
|
+
...table.columns[offset] ?? {},
|
|
3970
4045
|
name: candidate
|
|
3971
4046
|
};
|
|
3972
4047
|
});
|
|
@@ -4092,7 +4167,7 @@ function truncateSpreadsheetTableColumnName(value, maximum) {
|
|
|
4092
4167
|
return Array.from(value).slice(0, maximum).join('');
|
|
4093
4168
|
}
|
|
4094
4169
|
function sameSpreadsheetTableColumns(left, right) {
|
|
4095
|
-
return left.length === right.length && left.every((column, index)=>column.name === right[index]?.name);
|
|
4170
|
+
return left.length === right.length && left.every((column, index)=>column.name === right[index]?.name && column.calculatedFormula === right[index]?.calculatedFormula && column.totalsFunction === right[index]?.totalsFunction && column.totalsLabel === right[index]?.totalsLabel && column.totalsFormula === right[index]?.totalsFormula);
|
|
4096
4171
|
}
|
|
4097
4172
|
function spreadsheet_table_reconciliation_isRecord(value) {
|
|
4098
4173
|
return Boolean(value && 'object' == typeof value && !Array.isArray(value));
|
|
@@ -9324,7 +9399,8 @@ function createSpreadsheetTableDialogSource(content, target) {
|
|
|
9324
9399
|
sheetName: sheet.name,
|
|
9325
9400
|
value: {
|
|
9326
9401
|
headerRow: request.headerRow,
|
|
9327
|
-
rangeReference
|
|
9402
|
+
rangeReference,
|
|
9403
|
+
totalsRow: false
|
|
9328
9404
|
}
|
|
9329
9405
|
};
|
|
9330
9406
|
}
|
|
@@ -9336,13 +9412,25 @@ function validateSpreadsheetTableRequest(content, request) {
|
|
|
9336
9412
|
const sheet = content.sheets.find((candidate)=>candidate.id === request.sheetId);
|
|
9337
9413
|
if (!sheet) return tableError('sheet-not-found');
|
|
9338
9414
|
if (sheet.isPivotTable || sheet.pivotTables?.length) return tableError('pivot-table');
|
|
9339
|
-
const
|
|
9340
|
-
if (!
|
|
9415
|
+
const bodyRange = spreadsheet_cell_range_normalizeSpreadsheetCellRange(request.range);
|
|
9416
|
+
if (!bodyRange) return tableError('invalid-range');
|
|
9417
|
+
const totalsRow = true === request.totalsRow;
|
|
9418
|
+
const range = totalsRow ? {
|
|
9419
|
+
row: [
|
|
9420
|
+
bodyRange.row[0],
|
|
9421
|
+
bodyRange.row[1] + 1
|
|
9422
|
+
],
|
|
9423
|
+
column: [
|
|
9424
|
+
...bodyRange.column
|
|
9425
|
+
]
|
|
9426
|
+
} : bodyRange;
|
|
9341
9427
|
const name = request.name.trim();
|
|
9342
9428
|
if (!validSpreadsheetTableName(name)) return tableError('invalid-name');
|
|
9343
9429
|
if (spreadsheetTableNameExists(content, name)) return tableError('name-conflict');
|
|
9344
9430
|
const bounds = spreadsheetSheetBounds(sheet);
|
|
9345
|
-
|
|
9431
|
+
const configuredRows = Number(sheet.row);
|
|
9432
|
+
const lastAllowedRow = Number.isFinite(configuredRows) && configuredRows > 0 ? bounds.lastRow : Math.max(bounds.lastRow, range.row[1]);
|
|
9433
|
+
if (bodyRange.row[0] > lastAllowedRow || bodyRange.row[1] > lastAllowedRow || bodyRange.column[0] > bounds.lastColumn || bodyRange.column[1] > bounds.lastColumn || range.row[1] >= OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) return tableError('out-of-bounds');
|
|
9346
9434
|
const height = range.row[1] - range.row[0] + 1;
|
|
9347
9435
|
if (height <= Number(request.headerRow)) return tableError('invalid-range');
|
|
9348
9436
|
if (spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 100000) return tableError('range-too-large');
|
|
@@ -9361,8 +9449,27 @@ function validateSpreadsheetTableRequest(content, request) {
|
|
|
9361
9449
|
number: 2
|
|
9362
9450
|
};
|
|
9363
9451
|
if (!validSpreadsheetTableStyle(style)) return tableError('invalid-style');
|
|
9364
|
-
const columns = spreadsheetTableColumnNames(sheet,
|
|
9452
|
+
const columns = spreadsheetTableColumnNames(sheet, bodyRange, request.headerRow);
|
|
9365
9453
|
if (!columns.length || columns.some((column)=>!validTableColumnName(column))) return tableError('invalid-column-name');
|
|
9454
|
+
const totalsColumns = spreadsheetTableTotalsColumnPatch(columns.map((name)=>({
|
|
9455
|
+
name
|
|
9456
|
+
})), request.totalsColumns);
|
|
9457
|
+
if (!totalsColumns) return tableError('invalid-totals');
|
|
9458
|
+
const candidate = {
|
|
9459
|
+
id: '__validation__',
|
|
9460
|
+
name,
|
|
9461
|
+
range,
|
|
9462
|
+
columns: withDefaultSpreadsheetTableTotalsLabel(totalsColumns, totalsRow),
|
|
9463
|
+
filters: [],
|
|
9464
|
+
headerRow: request.headerRow,
|
|
9465
|
+
totalsRow,
|
|
9466
|
+
style,
|
|
9467
|
+
showFirstColumn: false,
|
|
9468
|
+
showLastColumn: false,
|
|
9469
|
+
showRowStripes: 'none' !== style.family,
|
|
9470
|
+
showColumnStripes: false
|
|
9471
|
+
};
|
|
9472
|
+
if (totalsRow && spreadsheetTableTotalsRowHasContent(sheet, candidate)) return tableError('totals-row-content');
|
|
9366
9473
|
return {
|
|
9367
9474
|
columns,
|
|
9368
9475
|
name,
|
|
@@ -9378,27 +9485,38 @@ function applySpreadsheetTable(content, request) {
|
|
|
9378
9485
|
family: 'medium',
|
|
9379
9486
|
number: 2
|
|
9380
9487
|
};
|
|
9381
|
-
const
|
|
9488
|
+
const totalsRow = true === request.totalsRow;
|
|
9489
|
+
const totalsColumns = spreadsheetTableTotalsColumnPatch(validation.columns.map((name)=>({
|
|
9490
|
+
name
|
|
9491
|
+
})), request.totalsColumns);
|
|
9492
|
+
if (!totalsColumns) return null;
|
|
9493
|
+
const tableWithoutCalculatedColumns = {
|
|
9382
9494
|
id: createWorkId('spreadsheet-table'),
|
|
9383
9495
|
name: validation.name,
|
|
9384
9496
|
range: cloneRange(validation.range),
|
|
9385
|
-
columns:
|
|
9386
|
-
name
|
|
9387
|
-
})),
|
|
9497
|
+
columns: withDefaultSpreadsheetTableTotalsLabel(totalsColumns, totalsRow),
|
|
9388
9498
|
filters: [],
|
|
9389
9499
|
headerRow: request.headerRow,
|
|
9390
|
-
totalsRow
|
|
9500
|
+
totalsRow,
|
|
9391
9501
|
style,
|
|
9392
9502
|
showFirstColumn: false,
|
|
9393
9503
|
showLastColumn: false,
|
|
9394
9504
|
showRowStripes: 'none' !== style.family,
|
|
9395
9505
|
showColumnStripes: false
|
|
9396
9506
|
};
|
|
9507
|
+
const table = {
|
|
9508
|
+
...tableWithoutCalculatedColumns,
|
|
9509
|
+
columns: reconcileSpreadsheetTableCalculatedColumns(validation.sheet, tableWithoutCalculatedColumns)
|
|
9510
|
+
};
|
|
9397
9511
|
const nextSheet = request.headerRow ? stampSpreadsheetTableHeaders(validation.sheet, validation.range, validation.columns) : validation.sheet;
|
|
9512
|
+
const sizedSheet = ensureSpreadsheetTableRowCapacity(nextSheet, rangeEndRow(table));
|
|
9513
|
+
const synchronizedSheet = synchronizeSpreadsheetTableTotalsRow(sizedSheet, void 0, table, {
|
|
9514
|
+
force: totalsRow
|
|
9515
|
+
});
|
|
9398
9516
|
return replaceSpreadsheetTableSheet(content, {
|
|
9399
|
-
...
|
|
9517
|
+
...synchronizedSheet,
|
|
9400
9518
|
tables: [
|
|
9401
|
-
...
|
|
9519
|
+
...synchronizedSheet.tables ?? [],
|
|
9402
9520
|
table
|
|
9403
9521
|
]
|
|
9404
9522
|
});
|
|
@@ -9416,20 +9534,46 @@ function updateSpreadsheetTable(content, sheetId, tableId, patch) {
|
|
|
9416
9534
|
const showRowStripes = patch.showRowStripes ?? table.showRowStripes;
|
|
9417
9535
|
const showColumnStripes = patch.showColumnStripes ?? table.showColumnStripes;
|
|
9418
9536
|
if ('none' === style.family && (showFirstColumn || showLastColumn || showRowStripes || showColumnStripes)) return null;
|
|
9419
|
-
const
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9537
|
+
const totalsRow = patch.totalsRow ?? table.totalsRow;
|
|
9538
|
+
const range = cloneRange(table.range);
|
|
9539
|
+
if (totalsRow !== table.totalsRow) range.row[1] += totalsRow ? 1 : -1;
|
|
9540
|
+
if (range.row[0] < 0 || range.row[1] < range.row[0] || range.row[1] >= OFFICE_KERNEL_SPREADSHEET_MAX_ROWS || range.row[1] - range.row[0] + 1 <= Number(table.headerRow) + Number(totalsRow)) return null;
|
|
9541
|
+
const totalsColumns = spreadsheetTableTotalsColumnPatch(table.columns, patch.totalsColumns);
|
|
9542
|
+
if (!totalsColumns) return null;
|
|
9543
|
+
const nextColumns = withDefaultSpreadsheetTableTotalsLabel(totalsColumns, totalsRow);
|
|
9544
|
+
const nextTable = {
|
|
9545
|
+
...table,
|
|
9546
|
+
name,
|
|
9547
|
+
...void 0 === patch.name ? {} : {
|
|
9548
|
+
displayName: void 0
|
|
9549
|
+
},
|
|
9550
|
+
range,
|
|
9551
|
+
columns: nextColumns,
|
|
9552
|
+
totalsRow,
|
|
9553
|
+
style,
|
|
9554
|
+
showFirstColumn,
|
|
9555
|
+
showLastColumn,
|
|
9556
|
+
showRowStripes,
|
|
9557
|
+
showColumnStripes
|
|
9558
|
+
};
|
|
9559
|
+
if (totalsRow && !table.totalsRow && spreadsheetTableTotalsRowHasContent(sheet, nextTable)) return null;
|
|
9560
|
+
if (totalsRow && !table.totalsRow) {
|
|
9561
|
+
const totalsGrowthRange = {
|
|
9562
|
+
row: [
|
|
9563
|
+
table.range.row[1] + 1,
|
|
9564
|
+
range.row[1]
|
|
9565
|
+
],
|
|
9566
|
+
column: [
|
|
9567
|
+
...range.column
|
|
9568
|
+
]
|
|
9569
|
+
};
|
|
9570
|
+
if (spreadsheet_cell_range_spreadsheetCellRangeArea(range) > 100000 || spreadsheetTableGrowthConflicts(sheet, tableId, totalsGrowthRange)) return null;
|
|
9571
|
+
}
|
|
9572
|
+
const tables = sheet.tables?.map((candidate)=>candidate.id === tableId ? nextTable : candidate);
|
|
9573
|
+
const sizedSheet = ensureSpreadsheetTableRowCapacity(sheet, rangeEndRow(nextTable));
|
|
9574
|
+
const synchronizedSheet = synchronizeSpreadsheetTableTotalsRow(sizedSheet, table, nextTable);
|
|
9431
9575
|
return replaceSpreadsheetTableSheet(content, {
|
|
9432
|
-
...
|
|
9576
|
+
...synchronizedSheet,
|
|
9433
9577
|
tables
|
|
9434
9578
|
});
|
|
9435
9579
|
}
|
|
@@ -9577,6 +9721,16 @@ function spreadsheetTableIntersectsMerge(sheet, range) {
|
|
|
9577
9721
|
]
|
|
9578
9722
|
}));
|
|
9579
9723
|
}
|
|
9724
|
+
function spreadsheetTableGrowthConflicts(sheet, tableId, growthRange) {
|
|
9725
|
+
if (spreadsheetTableIntersectsMerge(sheet, growthRange) || (sheet.tables ?? []).some((candidate)=>candidate.id !== tableId && spreadsheetCellRangesIntersect(candidate.range, growthRange)) || !canMutateSpreadsheetCellRanges(sheet, [
|
|
9726
|
+
growthRange
|
|
9727
|
+
])) return true;
|
|
9728
|
+
const autoFilter = spreadsheet_cell_range_normalizeSpreadsheetCellRange(sheet.filter_select ?? {
|
|
9729
|
+
row: [],
|
|
9730
|
+
column: []
|
|
9731
|
+
});
|
|
9732
|
+
return Boolean(autoFilter && spreadsheetCellRangesIntersect(autoFilter, growthRange));
|
|
9733
|
+
}
|
|
9580
9734
|
function replaceSpreadsheetTableSheet(content, nextSheet) {
|
|
9581
9735
|
return {
|
|
9582
9736
|
...content,
|
|
@@ -9617,6 +9771,7 @@ function tableError(code) {
|
|
|
9617
9771
|
'invalid-name': '表格名称必须是有效且不类似单元格引用的标识符。',
|
|
9618
9772
|
'invalid-range': '表格至少需要一行数据。',
|
|
9619
9773
|
'invalid-style': '表格样式身份无效。',
|
|
9774
|
+
'invalid-totals': '汇总行函数、标签或公式无效。',
|
|
9620
9775
|
'merged-range': '请先取消表格区域内的合并单元格。',
|
|
9621
9776
|
'name-conflict': '表格名称已被其他表格或名称使用。',
|
|
9622
9777
|
'out-of-bounds': '表格区域超出当前工作表边界。',
|
|
@@ -9624,7 +9779,8 @@ function tableError(code) {
|
|
|
9624
9779
|
'protected-range': '受保护或只读区域不能创建表格。',
|
|
9625
9780
|
'range-too-large': `一次最多可创建 ${100000..toLocaleString()} 个单元格的表格。`,
|
|
9626
9781
|
'sheet-not-found': '找不到目标工作表。',
|
|
9627
|
-
'table-overlap': '表格区域不能与其他表格重叠。'
|
|
9782
|
+
'table-overlap': '表格区域不能与其他表格重叠。',
|
|
9783
|
+
'totals-row-content': '汇总行目标单元格已有内容,请先清空后再启用。'
|
|
9628
9784
|
};
|
|
9629
9785
|
return {
|
|
9630
9786
|
code,
|
|
@@ -9632,6 +9788,20 @@ function tableError(code) {
|
|
|
9632
9788
|
ok: false
|
|
9633
9789
|
};
|
|
9634
9790
|
}
|
|
9791
|
+
function rangeEndRow(table) {
|
|
9792
|
+
return table.range.row[1];
|
|
9793
|
+
}
|
|
9794
|
+
function ensureSpreadsheetTableRowCapacity(sheet, lastRow) {
|
|
9795
|
+
if (!Number.isSafeInteger(lastRow) || lastRow < 0) return sheet;
|
|
9796
|
+
const configured = Number(sheet.row);
|
|
9797
|
+
if (!Number.isFinite(configured) || configured <= 0) return sheet;
|
|
9798
|
+
const required = lastRow + 1;
|
|
9799
|
+
if (required <= configured) return sheet;
|
|
9800
|
+
return {
|
|
9801
|
+
...sheet,
|
|
9802
|
+
row: Math.min(OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, required)
|
|
9803
|
+
};
|
|
9804
|
+
}
|
|
9635
9805
|
function createSpreadsheetTableExtension() {
|
|
9636
9806
|
return createOfficeEditorExtension({
|
|
9637
9807
|
name: 'spreadsheetTables',
|
|
@@ -9684,7 +9854,8 @@ function updateSpreadsheetTableCommand(context, sheetId, tableId, patch) {
|
|
|
9684
9854
|
if (!context.editable) return false;
|
|
9685
9855
|
const next = updateSpreadsheetTable(context.content, sheetId, tableId, patch);
|
|
9686
9856
|
if (!next) return false;
|
|
9687
|
-
context.
|
|
9857
|
+
const selection = context.workbook?.getSelection()?.at(-1) ?? (context.selection?.sheetId === sheetId ? context.selection.selection : void 0);
|
|
9858
|
+
context.onChange(spreadsheetContentWithSelection(next, sheetId, selection));
|
|
9688
9859
|
return true;
|
|
9689
9860
|
}
|
|
9690
9861
|
function canConvertSpreadsheetTableToRange(context, sheetId, tableId) {
|
|
@@ -10444,9 +10615,9 @@ function createSpreadsheetFormulaDiagnostics(content, { summary, locations }) {
|
|
|
10444
10615
|
});
|
|
10445
10616
|
if (summary.structuredReferenceCells) diagnostics.push({
|
|
10446
10617
|
code: 'formula.structured-references',
|
|
10447
|
-
severity: '
|
|
10618
|
+
severity: 'info',
|
|
10448
10619
|
title: '结构化引用',
|
|
10449
|
-
message: `${summary.structuredReferenceCells}
|
|
10620
|
+
message: `${summary.structuredReferenceCells} 个公式使用表格结构化引用;浏览器内核支持有界表名、显示名称、连续列范围以及常见标题、数据、汇总和当前行选择。不连续、外部或高级形式会保留公式与缓存值,交由兼容应用重算。`,
|
|
10450
10621
|
locations: locations.structured
|
|
10451
10622
|
});
|
|
10452
10623
|
if (summary.unsupportedFunctions.length) diagnostics.push({
|
|
@@ -13548,6 +13719,16 @@ function SpreadsheetTableDesignRibbon({ can, commands, sheetId, table }) {
|
|
|
13548
13719
|
})
|
|
13549
13720
|
]
|
|
13550
13721
|
}),
|
|
13722
|
+
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
13723
|
+
label: "汇总行",
|
|
13724
|
+
priority: "high",
|
|
13725
|
+
children: /*#__PURE__*/ jsx(SpreadsheetTableTotalsMenu, {
|
|
13726
|
+
can: can,
|
|
13727
|
+
commands: commands,
|
|
13728
|
+
sheetId: sheetId,
|
|
13729
|
+
table: table
|
|
13730
|
+
})
|
|
13731
|
+
}),
|
|
13551
13732
|
/*#__PURE__*/ jsx(WorkOfficeRibbonGroup, {
|
|
13552
13733
|
label: "表格样式",
|
|
13553
13734
|
priority: "high",
|
|
@@ -13617,6 +13798,225 @@ function SpreadsheetTableDesignRibbon({ can, commands, sheetId, table }) {
|
|
|
13617
13798
|
]
|
|
13618
13799
|
});
|
|
13619
13800
|
}
|
|
13801
|
+
const totalsFunctionOptions = [
|
|
13802
|
+
{
|
|
13803
|
+
value: 'none',
|
|
13804
|
+
label: '不汇总'
|
|
13805
|
+
},
|
|
13806
|
+
...SPREADSHEET_TABLE_TOTALS_FUNCTIONS.map((value)=>({
|
|
13807
|
+
value,
|
|
13808
|
+
label: spreadsheetTableTotalsFunctionLabel(value)
|
|
13809
|
+
}))
|
|
13810
|
+
];
|
|
13811
|
+
function SpreadsheetTableTotalsMenu({ can, commands, sheetId, table }) {
|
|
13812
|
+
const [drafts, setDrafts] = useState({});
|
|
13813
|
+
useEffect(()=>{
|
|
13814
|
+
const next = {};
|
|
13815
|
+
table.columns.forEach((column, offset)=>{
|
|
13816
|
+
next[offset] = {
|
|
13817
|
+
formula: column.totalsFormula ?? '',
|
|
13818
|
+
label: column.totalsLabel ?? ''
|
|
13819
|
+
};
|
|
13820
|
+
});
|
|
13821
|
+
setDrafts(next);
|
|
13822
|
+
}, [
|
|
13823
|
+
table.id,
|
|
13824
|
+
table.columns
|
|
13825
|
+
]);
|
|
13826
|
+
const patchColumn = (offset, patch)=>{
|
|
13827
|
+
const designPatch = {
|
|
13828
|
+
totalsColumns: {
|
|
13829
|
+
[offset]: patch
|
|
13830
|
+
}
|
|
13831
|
+
};
|
|
13832
|
+
if (!can.updateTable(sheetId, table.id, designPatch) || !commands.updateTable(sheetId, table.id, designPatch)) showToast('汇总行设置无效,请检查函数、标签或公式。', 'error');
|
|
13833
|
+
};
|
|
13834
|
+
const toggleTotalsRow = ()=>{
|
|
13835
|
+
const patch = {
|
|
13836
|
+
totalsRow: !table.totalsRow
|
|
13837
|
+
};
|
|
13838
|
+
if (!can.updateTable(sheetId, table.id, patch) || !commands.updateTable(sheetId, table.id, patch)) showToast(table.totalsRow ? '无法关闭汇总行。' : '汇总行目标区域已有内容,请先清空该行。', 'error');
|
|
13839
|
+
};
|
|
13840
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
13841
|
+
label: "汇总行",
|
|
13842
|
+
panelLabel: "表格汇总行设置",
|
|
13843
|
+
panelRole: "dialog",
|
|
13844
|
+
portal: true,
|
|
13845
|
+
className: "work-spreadsheet-table-totals-root",
|
|
13846
|
+
panelClassName: "work-spreadsheet-table-totals-menu",
|
|
13847
|
+
placement: "bottom-end",
|
|
13848
|
+
trigger: (triggerProps, { open })=>/*#__PURE__*/ jsxs("button", {
|
|
13849
|
+
...triggerProps,
|
|
13850
|
+
className: `with-label work-spreadsheet-table-totals-trigger${open || table.totalsRow ? ' active' : ''}`,
|
|
13851
|
+
"aria-pressed": table.totalsRow,
|
|
13852
|
+
title: "设置表格汇总行",
|
|
13853
|
+
children: [
|
|
13854
|
+
/*#__PURE__*/ jsx(Calculator, {
|
|
13855
|
+
size: 19
|
|
13856
|
+
}),
|
|
13857
|
+
/*#__PURE__*/ jsx("span", {
|
|
13858
|
+
children: "汇总行"
|
|
13859
|
+
})
|
|
13860
|
+
]
|
|
13861
|
+
}),
|
|
13862
|
+
children: (close)=>/*#__PURE__*/ jsxs("div", {
|
|
13863
|
+
className: "work-spreadsheet-table-totals-content",
|
|
13864
|
+
children: [
|
|
13865
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
13866
|
+
ariaLabel: "启用汇总行",
|
|
13867
|
+
checked: table.totalsRow,
|
|
13868
|
+
disabled: !table.totalsRow && !can.updateTable(sheetId, table.id, {
|
|
13869
|
+
totalsRow: true
|
|
13870
|
+
}),
|
|
13871
|
+
onCheckedChange: ()=>{
|
|
13872
|
+
toggleTotalsRow();
|
|
13873
|
+
},
|
|
13874
|
+
children: "启用汇总行"
|
|
13875
|
+
}),
|
|
13876
|
+
/*#__PURE__*/ jsx("p", {
|
|
13877
|
+
className: "work-spreadsheet-table-totals-hint",
|
|
13878
|
+
children: "汇总行位于表格末尾,函数会随筛选结果更新。"
|
|
13879
|
+
}),
|
|
13880
|
+
/*#__PURE__*/ jsx("div", {
|
|
13881
|
+
className: "work-spreadsheet-table-totals-columns",
|
|
13882
|
+
children: table.columns.map((column, offset)=>{
|
|
13883
|
+
const selected = column.totalsFormula ? 'custom' : column.totalsFunction ?? 'none';
|
|
13884
|
+
const draft = drafts[offset] ?? {
|
|
13885
|
+
formula: column.totalsFormula ?? '',
|
|
13886
|
+
label: column.totalsLabel ?? ''
|
|
13887
|
+
};
|
|
13888
|
+
const formulaEnabled = 'custom' === selected;
|
|
13889
|
+
const labelEnabled = 'none' === selected;
|
|
13890
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
13891
|
+
className: "work-spreadsheet-table-totals-column",
|
|
13892
|
+
children: [
|
|
13893
|
+
/*#__PURE__*/ jsx("strong", {
|
|
13894
|
+
children: column.name
|
|
13895
|
+
}),
|
|
13896
|
+
/*#__PURE__*/ jsxs("label", {
|
|
13897
|
+
children: [
|
|
13898
|
+
/*#__PURE__*/ jsx("span", {
|
|
13899
|
+
children: "函数"
|
|
13900
|
+
}),
|
|
13901
|
+
/*#__PURE__*/ jsx("select", {
|
|
13902
|
+
"aria-label": `${column.name} 汇总函数`,
|
|
13903
|
+
"data-selected-value": selected,
|
|
13904
|
+
disabled: !table.totalsRow,
|
|
13905
|
+
value: selected,
|
|
13906
|
+
onChange: (event)=>{
|
|
13907
|
+
const value = event.currentTarget.value;
|
|
13908
|
+
if ('none' === value) patchColumn(offset, {
|
|
13909
|
+
totalsFunction: null,
|
|
13910
|
+
totalsFormula: null
|
|
13911
|
+
});
|
|
13912
|
+
else if ('custom' === value) {
|
|
13913
|
+
const formula = draft.formula || `=SUM(${table.name}[${escapeTotalsColumnName(column.name)}])`;
|
|
13914
|
+
setDrafts((current)=>({
|
|
13915
|
+
...current,
|
|
13916
|
+
[offset]: {
|
|
13917
|
+
...draft,
|
|
13918
|
+
formula
|
|
13919
|
+
}
|
|
13920
|
+
}));
|
|
13921
|
+
patchColumn(offset, {
|
|
13922
|
+
totalsFunction: 'custom',
|
|
13923
|
+
totalsFormula: formula,
|
|
13924
|
+
totalsLabel: null
|
|
13925
|
+
});
|
|
13926
|
+
} else patchColumn(offset, {
|
|
13927
|
+
totalsFunction: value,
|
|
13928
|
+
totalsFormula: null,
|
|
13929
|
+
totalsLabel: null
|
|
13930
|
+
});
|
|
13931
|
+
},
|
|
13932
|
+
children: totalsFunctionOptions.map((option)=>/*#__PURE__*/ jsx("option", {
|
|
13933
|
+
value: option.value,
|
|
13934
|
+
children: option.label
|
|
13935
|
+
}, option.value))
|
|
13936
|
+
})
|
|
13937
|
+
]
|
|
13938
|
+
}),
|
|
13939
|
+
/*#__PURE__*/ jsxs("label", {
|
|
13940
|
+
children: [
|
|
13941
|
+
/*#__PURE__*/ jsx("span", {
|
|
13942
|
+
children: "标签"
|
|
13943
|
+
}),
|
|
13944
|
+
/*#__PURE__*/ jsx("input", {
|
|
13945
|
+
"aria-label": `${column.name} 汇总标签`,
|
|
13946
|
+
disabled: !table.totalsRow || !labelEnabled,
|
|
13947
|
+
value: draft.label,
|
|
13948
|
+
onChange: (event)=>{
|
|
13949
|
+
const value = event.currentTarget.value;
|
|
13950
|
+
setDrafts((current)=>({
|
|
13951
|
+
...current,
|
|
13952
|
+
[offset]: {
|
|
13953
|
+
...draft,
|
|
13954
|
+
label: value
|
|
13955
|
+
}
|
|
13956
|
+
}));
|
|
13957
|
+
},
|
|
13958
|
+
onBlur: ()=>{
|
|
13959
|
+
if (!labelEnabled) return;
|
|
13960
|
+
patchColumn(offset, {
|
|
13961
|
+
totalsLabel: draft.label.trim() || null
|
|
13962
|
+
});
|
|
13963
|
+
},
|
|
13964
|
+
onKeyDown: (event)=>{
|
|
13965
|
+
if ('Enter' === event.key) event.currentTarget.blur();
|
|
13966
|
+
}
|
|
13967
|
+
})
|
|
13968
|
+
]
|
|
13969
|
+
}),
|
|
13970
|
+
/*#__PURE__*/ jsxs("label", {
|
|
13971
|
+
children: [
|
|
13972
|
+
/*#__PURE__*/ jsx("span", {
|
|
13973
|
+
children: "自定义公式"
|
|
13974
|
+
}),
|
|
13975
|
+
/*#__PURE__*/ jsx("input", {
|
|
13976
|
+
"aria-label": `${column.name} 汇总公式`,
|
|
13977
|
+
disabled: !table.totalsRow || !formulaEnabled,
|
|
13978
|
+
placeholder: "=SUM(Table[Column])",
|
|
13979
|
+
value: draft.formula,
|
|
13980
|
+
onChange: (event)=>{
|
|
13981
|
+
const value = event.currentTarget.value;
|
|
13982
|
+
setDrafts((current)=>({
|
|
13983
|
+
...current,
|
|
13984
|
+
[offset]: {
|
|
13985
|
+
...draft,
|
|
13986
|
+
formula: value
|
|
13987
|
+
}
|
|
13988
|
+
}));
|
|
13989
|
+
},
|
|
13990
|
+
onBlur: ()=>{
|
|
13991
|
+
if (!formulaEnabled) return;
|
|
13992
|
+
patchColumn(offset, {
|
|
13993
|
+
totalsFunction: 'custom',
|
|
13994
|
+
totalsFormula: draft.formula.trim() || null
|
|
13995
|
+
});
|
|
13996
|
+
},
|
|
13997
|
+
onKeyDown: (event)=>{
|
|
13998
|
+
if ('Enter' === event.key) event.currentTarget.blur();
|
|
13999
|
+
}
|
|
14000
|
+
})
|
|
14001
|
+
]
|
|
14002
|
+
})
|
|
14003
|
+
]
|
|
14004
|
+
}, `${table.id}-${offset}`);
|
|
14005
|
+
})
|
|
14006
|
+
}),
|
|
14007
|
+
/*#__PURE__*/ jsx("button", {
|
|
14008
|
+
type: "button",
|
|
14009
|
+
className: "work-spreadsheet-table-totals-close",
|
|
14010
|
+
onClick: close,
|
|
14011
|
+
children: "完成"
|
|
14012
|
+
})
|
|
14013
|
+
]
|
|
14014
|
+
})
|
|
14015
|
+
});
|
|
14016
|
+
}
|
|
14017
|
+
function escapeTotalsColumnName(value) {
|
|
14018
|
+
return value.replaceAll(']', ']]');
|
|
14019
|
+
}
|
|
13620
14020
|
function SpreadsheetTableNameControl({ can, commands, sheetId, table }) {
|
|
13621
14021
|
const [name, setName] = useState(table.name);
|
|
13622
14022
|
useEffect(()=>setName(table.name), [
|
|
@@ -21908,10 +22308,15 @@ function compileSpreadsheetKernelWorkbook(sheets, fallbackCells = []) {
|
|
|
21908
22308
|
cellCount += cells.length;
|
|
21909
22309
|
sheetIds.add(id);
|
|
21910
22310
|
sheetNames.add(normalizedName);
|
|
22311
|
+
const tables = spreadsheetKernelTables(sheet.tables);
|
|
22312
|
+
if (null === tables) return null;
|
|
21911
22313
|
sourceSheets.push({
|
|
21912
22314
|
id,
|
|
21913
22315
|
name,
|
|
21914
|
-
cells
|
|
22316
|
+
cells,
|
|
22317
|
+
...tables.length ? {
|
|
22318
|
+
tables
|
|
22319
|
+
} : {}
|
|
21915
22320
|
});
|
|
21916
22321
|
}
|
|
21917
22322
|
const compiled = sourceSheets.map((sheet)=>({
|
|
@@ -21954,7 +22359,8 @@ function spreadsheetKernelSourceState(sheets) {
|
|
|
21954
22359
|
sourceCells,
|
|
21955
22360
|
structureKey: JSON.stringify(sheets.map((sheet)=>({
|
|
21956
22361
|
id: sheet.id,
|
|
21957
|
-
name: sheet.name
|
|
22362
|
+
name: sheet.name,
|
|
22363
|
+
tables: sheet.tables ?? []
|
|
21958
22364
|
})))
|
|
21959
22365
|
};
|
|
21960
22366
|
}
|
|
@@ -21972,7 +22378,18 @@ function spreadsheetStructureKey(sheets) {
|
|
|
21972
22378
|
names.add(normalizedName);
|
|
21973
22379
|
structure.push({
|
|
21974
22380
|
id,
|
|
21975
|
-
name
|
|
22381
|
+
name,
|
|
22382
|
+
tables: (sheet.tables ?? []).map((table)=>({
|
|
22383
|
+
name: table.name,
|
|
22384
|
+
displayName: table.displayName,
|
|
22385
|
+
startRow: table.range.row[0],
|
|
22386
|
+
endRow: table.range.row[1],
|
|
22387
|
+
startColumn: table.range.column[0],
|
|
22388
|
+
endColumn: table.range.column[1],
|
|
22389
|
+
columns: table.columns.map((column)=>column.name),
|
|
22390
|
+
headerRow: table.headerRow,
|
|
22391
|
+
totalsRow: table.totalsRow
|
|
22392
|
+
}))
|
|
21976
22393
|
});
|
|
21977
22394
|
}
|
|
21978
22395
|
return JSON.stringify(structure);
|
|
@@ -22055,6 +22472,49 @@ function spreadsheetKernelInputCell(cell, fallback) {
|
|
|
22055
22472
|
const { formula: _formula, ...cachedCell } = cell;
|
|
22056
22473
|
return cachedCell;
|
|
22057
22474
|
}
|
|
22475
|
+
function spreadsheetKernelTables(tables) {
|
|
22476
|
+
if (!tables?.length) return [];
|
|
22477
|
+
const names = new Map();
|
|
22478
|
+
const ranges = [];
|
|
22479
|
+
for (const [tableIndex, table] of tables.entries()){
|
|
22480
|
+
const [startRow, endRow] = table.range.row;
|
|
22481
|
+
const [startColumn, endColumn] = table.range.column;
|
|
22482
|
+
if (!table.name?.trim() || utf8ByteLength(table.name) > SPREADSHEET_KERNEL_MAX_IDENTIFIER_BYTES || void 0 !== table.displayName && (!table.displayName.trim() || utf8ByteLength(table.displayName) > SPREADSHEET_KERNEL_MAX_IDENTIFIER_BYTES) || !isSpreadsheetCoordinateIndex(startRow, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !isSpreadsheetCoordinateIndex(endRow, OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !isSpreadsheetCoordinateIndex(startColumn, 16384) || !isSpreadsheetCoordinateIndex(endColumn, 16384) || startRow > endRow || startColumn > endColumn || table.columns.length !== endColumn - startColumn + 1) return null;
|
|
22483
|
+
for (const alias of [
|
|
22484
|
+
table.name,
|
|
22485
|
+
table.displayName
|
|
22486
|
+
]){
|
|
22487
|
+
if (!alias) continue;
|
|
22488
|
+
const normalized = alias.toLocaleLowerCase();
|
|
22489
|
+
const previous = names.get(normalized);
|
|
22490
|
+
if (void 0 !== previous && previous !== tableIndex) return null;
|
|
22491
|
+
names.set(normalized, tableIndex);
|
|
22492
|
+
}
|
|
22493
|
+
const columnNames = new Set();
|
|
22494
|
+
for (const column of table.columns){
|
|
22495
|
+
if (!column.name?.trim() || utf8ByteLength(column.name) > SPREADSHEET_KERNEL_MAX_IDENTIFIER_BYTES) return null;
|
|
22496
|
+
const normalized = column.name.toLocaleLowerCase();
|
|
22497
|
+
if (columnNames.has(normalized)) return null;
|
|
22498
|
+
columnNames.add(normalized);
|
|
22499
|
+
}
|
|
22500
|
+
const next = {
|
|
22501
|
+
name: table.name,
|
|
22502
|
+
...table.displayName ? {
|
|
22503
|
+
displayName: table.displayName
|
|
22504
|
+
} : {},
|
|
22505
|
+
startRow,
|
|
22506
|
+
endRow,
|
|
22507
|
+
startColumn,
|
|
22508
|
+
endColumn,
|
|
22509
|
+
columns: table.columns.map((column)=>column.name),
|
|
22510
|
+
headerRow: Boolean(table.headerRow),
|
|
22511
|
+
totalsRow: Boolean(table.totalsRow)
|
|
22512
|
+
};
|
|
22513
|
+
if (ranges.some((previous)=>next.startRow <= previous.endRow && next.endRow >= previous.startRow && next.startColumn <= previous.endColumn && next.endColumn >= previous.startColumn)) return null;
|
|
22514
|
+
ranges.push(next);
|
|
22515
|
+
}
|
|
22516
|
+
return ranges;
|
|
22517
|
+
}
|
|
22058
22518
|
function spreadsheetSheetsWithKernelChanges(sheets, changes) {
|
|
22059
22519
|
const changesBySheet = new Map();
|
|
22060
22520
|
for (const change of changes.values()){
|
|
@@ -22313,7 +22773,7 @@ function spreadsheetCalculationOps(sheets, calculatedCells) {
|
|
|
22313
22773
|
});
|
|
22314
22774
|
}
|
|
22315
22775
|
function sameSpreadsheetStructure(previous, current) {
|
|
22316
|
-
return previous.length === current.length && previous.every((sheet, index)=>sheet.id === current[index]?.id && sheet.name === current[index]?.name);
|
|
22776
|
+
return previous.length === current.length && previous.every((sheet, index)=>sheet.id === current[index]?.id && sheet.name === current[index]?.name && JSON.stringify(sheet.tables ?? []) === JSON.stringify(current[index]?.tables ?? []));
|
|
22317
22777
|
}
|
|
22318
22778
|
function cellWithCalculatedValue(cell, value) {
|
|
22319
22779
|
const next = {
|
|
@@ -25266,6 +25726,15 @@ function SpreadsheetTableDialog({ source, restoreFocusTarget, onApply, onClose,
|
|
|
25266
25726
|
headerRow
|
|
25267
25727
|
})),
|
|
25268
25728
|
children: "表包含标题"
|
|
25729
|
+
}),
|
|
25730
|
+
/*#__PURE__*/ jsx(OfficeCheckbox, {
|
|
25731
|
+
ariaLabel: "启用汇总行",
|
|
25732
|
+
checked: true === value.totalsRow,
|
|
25733
|
+
onCheckedChange: (totalsRow)=>setValue((current)=>({
|
|
25734
|
+
...current,
|
|
25735
|
+
totalsRow
|
|
25736
|
+
})),
|
|
25737
|
+
children: "启用汇总行"
|
|
25269
25738
|
})
|
|
25270
25739
|
]
|
|
25271
25740
|
})
|
|
@@ -25353,7 +25822,8 @@ function useSpreadsheetTable({ commandsRef, contentRef, focusGrid, getGridFocusT
|
|
|
25353
25822
|
headerRow: value.headerRow,
|
|
25354
25823
|
name: source.name,
|
|
25355
25824
|
range,
|
|
25356
|
-
sheetId: source.sheetId
|
|
25825
|
+
sheetId: source.sheetId,
|
|
25826
|
+
totalsRow: true === value.totalsRow
|
|
25357
25827
|
}) ?? false;
|
|
25358
25828
|
appliedRef.current = handled;
|
|
25359
25829
|
} finally{
|
|
@@ -25374,7 +25844,8 @@ function spreadsheetTableValidationMessage(content, source, value) {
|
|
|
25374
25844
|
headerRow: value.headerRow,
|
|
25375
25845
|
name: source.name,
|
|
25376
25846
|
range,
|
|
25377
|
-
sheetId: source.sheetId
|
|
25847
|
+
sheetId: source.sheetId,
|
|
25848
|
+
totalsRow: true === value.totalsRow
|
|
25378
25849
|
});
|
|
25379
25850
|
}
|
|
25380
25851
|
const MAXIMUM_BUFFERED_SPREADSHEET_OPERATIONS = 10001;
|