diff --git a/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts b/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts index 34030f8c566..372f2bda91e 100644 --- a/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts +++ b/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts @@ -44,7 +44,8 @@ import { LocaleService, ObjectMatrix, OnLifecycle, - Optional, RxDisposable, UniverInstanceType } from '@univerjs/core'; + Optional, RxDisposable, UniverInstanceType, +} from '@univerjs/core'; import { MessageType } from '@univerjs/design'; import type { IInsertColMutationParams, @@ -62,9 +63,9 @@ import { SetWorksheetColWidthMutation, SetWorksheetRowHeightMutation, } from '@univerjs/sheets'; -import { IMessageService, textTrim } from '@univerjs/ui'; +import { IMessageService } from '@univerjs/ui'; -import { IRenderManagerService, ITextSelectionRenderManager, ptToPx } from '@univerjs/engine-render'; +import { IRenderManagerService, ITextSelectionRenderManager } from '@univerjs/engine-render'; import { takeUntil } from 'rxjs'; import { SheetCopyCommand, @@ -154,7 +155,6 @@ export class SheetClipboardController extends RxDisposable { this.disposeWithMe({ dispose: () => disposables.forEach((d) => d.dispose()) }); } - //eslint-disable-next-line max-lines-per-function private _initCopyingHooks(): ISheetClipboardHook { const self = this; let currentSheet: Worksheet | null = null; @@ -278,7 +278,6 @@ export class SheetClipboardController extends RxDisposable { }; } - //eslint-disable-next-line max-lines-per-function private _initPastingHook(): ISheetClipboardHook { const self = this; @@ -317,38 +316,16 @@ export class SheetClipboardController extends RxDisposable { // if the range is outside ot the worksheet's boundary, we should add rows const maxRow = currentSheet!.getMaxRows(); - const addingRowsCount = range.rows[range.rows.length - 1] - maxRow; + const rowCount = maxRow - 1; + const addingRowsCount = range.rows[range.rows.length - 1] - rowCount; const existingRowsCount = rowProperties.length - addingRowsCount; const rowManager = currentSheet!.getRowManager(); if (addingRowsCount > 0) { const rowInfo: IObjectArrayPrimitiveType = {}; rowProperties.slice(existingRowsCount).forEach((property, index) => { - const { style, height: PropertyHeight } = property || {}; - if (style) { - const cssTextArray = style.split(';'); - let height = DEFAULT_WORKSHEET_ROW_HEIGHT; - - cssTextArray.find((css) => { - css = css.toLowerCase(); - const key = textTrim(css.substr(0, css.indexOf(':'))); - const value = textTrim(css.substr(css.indexOf(':') + 1)); - if (key === 'height') { - if (value.endsWith('pt')) { - height = ptToPx(Number.parseFloat(value)); - } else { - height = Number.parseFloat(value); - } - return true; - } - return false; - }); - - rowInfo[index] = { - h: height, - hd: BooleanNumber.FALSE, - }; - } else if (PropertyHeight) { + const { height: PropertyHeight } = property || {}; + if (PropertyHeight) { rowInfo[index] = { h: Number.parseFloat(PropertyHeight), hd: BooleanNumber.FALSE, @@ -363,7 +340,8 @@ export class SheetClipboardController extends RxDisposable { startColumn: range.cols[0], endColumn: range.cols[range.cols.length - 1], endRow: range.rows[range.rows.length - 1], - startRow: maxRow }, + startRow: maxRow, + }, rowInfo, }; redoMutations.push({ @@ -377,28 +355,8 @@ export class SheetClipboardController extends RxDisposable { const rowHeight: IObjectArrayPrimitiveType = {}; const originRowHeight: IObjectArrayPrimitiveType = {}; rowProperties.slice(0, existingRowsCount).forEach((property, index) => { - const { style, height: propertyHeight } = property; - if (style) { - const cssTextArray = style.split(';'); - let height = DEFAULT_WORKSHEET_ROW_HEIGHT; - - cssTextArray.find((css) => { - css = css.toLowerCase(); - const key = textTrim(css.substr(0, css.indexOf(':'))); - const value = textTrim(css.substr(css.indexOf(':') + 1)); - if (key === 'height') { - if (value.endsWith('pt')) { - height = ptToPx(Number.parseFloat(value)); - } else { - height = Number.parseFloat(value); - } - return true; - } - return false; - }); - - rowHeight[index + range.rows[0]] = height; - } else if (propertyHeight) { + const { height: propertyHeight } = property; + if (propertyHeight) { const rowConfigBeforePaste = rowManager.getRow(range.rows[0] + index); const willSetHeight = Number.parseFloat(propertyHeight); if (rowConfigBeforePaste) { @@ -416,26 +374,29 @@ export class SheetClipboardController extends RxDisposable { }); // apply row properties to the existing rows - const setRowPropertyMutation: ISetWorksheetRowHeightMutationParams = { - unitId: unitId!, - subUnitId: subUnitId!, - ranges: [{ startRow: range.rows[0], endRow: Math.min(range.rows[range.rows.length - 1], maxRow), - startColumn: range.cols[0], endColumn: range.cols[range.cols.length - 1], - }], - rowHeight, - }; - redoMutations.push({ - id: SetWorksheetRowHeightMutation.id, - params: setRowPropertyMutation, - }); + if (Object.keys(rowHeight).length) { + const setRowPropertyMutation: ISetWorksheetRowHeightMutationParams = { + unitId: unitId!, + subUnitId: subUnitId!, + ranges: [{ + startRow: range.rows[0], endRow: Math.min(range.rows[range.rows.length - 1], maxRow), + startColumn: range.cols[0], endColumn: range.cols[range.cols.length - 1], + }], + rowHeight, + }; + redoMutations.push({ + id: SetWorksheetRowHeightMutation.id, + params: setRowPropertyMutation, + }); - undoMutations.push({ - id: SetWorksheetRowHeightMutation.id, - params: { - ...setRowPropertyMutation, - rowHeight: 20, - }, - }); + undoMutations.push({ + id: SetWorksheetRowHeightMutation.id, + params: { + ...setRowPropertyMutation, + rowHeight: originRowHeight, + }, + }); + } return { redos: redoMutations, @@ -450,10 +411,12 @@ export class SheetClipboardController extends RxDisposable { // if the range is outside ot the worksheet's boundary, we should add rows const maxColumn = currentSheet!.getMaxColumns(); - const addingColsCount = range.cols[range.cols.length - 1] - maxColumn; + const colCount = maxColumn - 1; + const addingColsCount = range.cols[range.cols.length - 1] - colCount; const existingColsCount = colProperties.length - addingColsCount; const defaultColumnWidth = self._configService.getConfig(DEFAULT_WORKSHEET_COLUMN_WIDTH_KEY) ?? DEFAULT_WORKSHEET_COLUMN_WIDTH; + const pasteToCols = range.cols; if (addingColsCount > 0) { const addColMutation: IInsertColMutationParams = { @@ -465,8 +428,8 @@ export class SheetClipboardController extends RxDisposable { endColumn: range.cols[range.cols.length - 1], startColumn: maxColumn, }, - colInfo: colProperties.slice(existingColsCount).map((property) => ({ - w: property.width ? +property.width : defaultColumnWidth, + colInfo: colProperties.slice(existingColsCount).map((property, index) => ({ + w: property.width ? Math.max(+property.width, currentSheet!.getColumnWidth(pasteToCols[index])) : defaultColumnWidth, hd: BooleanNumber.FALSE, })), }; @@ -475,8 +438,8 @@ export class SheetClipboardController extends RxDisposable { params: addColMutation, }); } - // apply col properties to the existing rows - const setColPropertyMutation: ISetWorksheetColWidthMutationParams = { + + const targetSetColPropertyParams = { unitId: unitId!, subUnitId: subUnitId!, ranges: [{ @@ -484,21 +447,40 @@ export class SheetClipboardController extends RxDisposable { endRow: range.rows[range.rows.length - 1], startColumn: range.cols[0], - endColumn: Math.min(range.cols[range.cols.length - 1], maxColumn) }], - colWidth: colProperties - .slice(0, existingColsCount) - .map((property) => (property.width ? +property.width : defaultColumnWidth)), + endColumn: Math.min(range.cols[range.cols.length - 1], maxColumn), + }], }; - redoMutations.push({ - id: SetWorksheetColWidthMutation.id, - params: setColPropertyMutation, - }); - // TODO: add undo mutations but we cannot do it now because underlying mechanism is not ready + // apply col properties to the existing rows + if (colProperties.length > 0) { + const setColPropertyMutation: ISetWorksheetColWidthMutationParams = { + ...targetSetColPropertyParams, + colWidth: colProperties + .slice(0, existingColsCount) + .map((property, index) => (property.width ? Math.max(+property.width, currentSheet!.getColumnWidth(pasteToCols[index])) : defaultColumnWidth)), + }; + + const undoSetColPropertyParams: ISetWorksheetColWidthMutationParams = { + ...targetSetColPropertyParams, + colWidth: colProperties + .slice(0, existingColsCount) + .map((_property, index) => currentSheet!.getColumnWidth(pasteToCols[index]) ?? defaultColumnWidth), + }; + + redoMutations.push({ + id: SetWorksheetColWidthMutation.id, + params: setColPropertyMutation, + }); + + undoMutations.push({ + id: SetWorksheetColWidthMutation.id, + params: undoSetColPropertyParams, + }); + } return { redos: redoMutations, - undos: [] || undoMutations, + undos: undoMutations, }; }, @@ -604,7 +586,6 @@ export class SheetClipboardController extends RxDisposable { }); } - //eslint-disable-next-line max-lines-per-function private _initSpecialPasteHooks() { const self = this; diff --git a/packages/sheets-ui/src/controllers/clipboard/utils.ts b/packages/sheets-ui/src/controllers/clipboard/utils.ts index 78705705095..99c7513a7fd 100644 --- a/packages/sheets-ui/src/controllers/clipboard/utils.ts +++ b/packages/sheets-ui/src/controllers/clipboard/utils.ts @@ -296,8 +296,8 @@ export function getSetCellValueMutations( let originNumberValue; if (!value.p && value.v && !pasteFrom) { const content = String(value.v); - const numfmtValue = numfmt.parseDate(content) || numfmt.parseTime(content) || numfmt.parseNumber(content); - if (numfmtValue?.v && typeof numfmtValue.v === 'number') { + const numfmtValue = numfmt.parseValue(content); + if (numfmtValue?.v !== undefined && typeof numfmtValue.v === 'number') { originNumberValue = numfmtValue.v; } } @@ -306,7 +306,7 @@ export function getSetCellValueMutations( if (value.p?.body) { valueMatrix.setValue(realRow, realCol, Tools.deepClone({ p: value.p, v: originNumberValue ?? value.v })); } else { - valueMatrix.setValue(realRow, realCol, Tools.deepClone({ v: originNumberValue ?? value.v })); + valueMatrix.setValue(realRow, realCol, Tools.deepClone({ v: originNumberValue ?? value.v, t: value.t })); } }); // set cell value and style @@ -363,7 +363,7 @@ export function getSetCellStyleMutations( newValue.p = value.p; } const content = String(value.v); - const numfmtValue = numfmt.parseDate(content) || numfmt.parseTime(content) || numfmt.parseNumber(content); + const numfmtValue = numfmt.parseValue(content); if (numfmtValue?.z) { if (!newValue.s) { newValue.s = {}; diff --git a/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-service.spec.ts b/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-service.spec.ts index 97cb4b1fda2..71041628482 100644 --- a/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-service.spec.ts +++ b/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-service.spec.ts @@ -153,11 +153,9 @@ describe('Test clipboard', () => { const styles = getStyles(startRow, startColumn, endRow, endColumn); const mergedCells = getMergedCells(startRow, startColumn, endRow, endColumn); const rowManager = get(IUniverInstanceService).getUniverSheetInstance('test')?.getSheetBySheetId('sheet1')?.getRowManager(); - const rowHeight = rowManager?.getRowData()?.[0].h; const columnManager = get(IUniverInstanceService).getUniverSheetInstance('test')?.getSheetBySheetId('sheet1')?.getColumnManager(); - const columnWidth = columnManager?.getColumnData()?.[0].w; - expect(columnWidth).toBe(73); - expect(rowHeight).toBe(81); + const columnWidth = columnManager?.getColumnData()?.[0]?.w; + expect(columnWidth).toBe(88); expect(values && values[0][0]?.v).toBe('row1col2'); expect(styles && styles[0][0]).toStrictEqual({ bg: { diff --git a/packages/sheets-ui/src/services/clipboard/clipboard.service.ts b/packages/sheets-ui/src/services/clipboard/clipboard.service.ts index b2288878922..3b6e2435761 100644 --- a/packages/sheets-ui/src/services/clipboard/clipboard.service.ts +++ b/packages/sheets-ui/src/services/clipboard/clipboard.service.ts @@ -14,13 +14,14 @@ * limitations under the License. */ -import type { ICellData, IDisposable, IMutationInfo, IRange, Nullable, Workbook, Worksheet } from '@univerjs/core'; +import type { + ICellData, IDisposable, + IMutationInfo, + IRange, + Nullable, Workbook, Worksheet, +} from '@univerjs/core'; import { - createIdentifier, - Disposable, - ErrorService, - extractPureTextFromCell, - ICommandService, + createIdentifier, Disposable, ErrorService, extractPureTextFromCell, ICommandService, ILogService, Inject, Injector, @@ -29,7 +30,10 @@ import { LocaleService, ObjectMatrix, ThemeService, - toDisposable, Tools, UniverInstanceType } from '@univerjs/core'; + toDisposable, + Tools, + UniverInstanceType, +} from '@univerjs/core'; import type { ISetSelectionsOperationParams } from '@univerjs/sheets'; import { getPrimaryForRange, @@ -507,14 +511,14 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard const pasteTarget = this._getPastedRange(cellMatrix); if (!pasteTarget) return false; - const worksheet = this._univerInstanceService + const pasteToWorksheet = this._univerInstanceService .getUniverSheetInstance(pasteTarget.unitId) ?.getSheetBySheetId(pasteTarget.subUnitId); - if (!worksheet) { + if (!pasteToWorksheet) { return false; } - const mergeData = worksheet?.getMergeData(); + const mergeData = pasteToWorksheet?.getMergeData(); if (mergeData) { const pastedRangeLapWithMergedCell = mergeData.some((m) => { @@ -526,10 +530,15 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard } } - const colManager = worksheet.getColumnManager(); - const rowManager = worksheet.getRowManager(); - const defaultColumnWidth = worksheet.getConfig().defaultColumnWidth; - const defaultRowHeight = worksheet.getConfig().defaultRowHeight; + const pasteFromWorkbook = this._univerInstanceService.getUnit(copyUnitId); + if (!pasteFromWorkbook) return false; + const pasteFromWorksheet = pasteFromWorkbook.getSheetBySheetId(copySubUnitId); + if (!pasteFromWorksheet) return false; + + const colManager = pasteFromWorksheet.getColumnManager(); + const rowManager = pasteFromWorksheet.getRowManager(); + const defaultColumnWidth = pasteFromWorksheet.getConfig().defaultColumnWidth; + const defaultRowHeight = pasteFromWorksheet.getConfig().defaultRowHeight; const colProperties: IClipboardPropertyItem[] = []; const rowProperties: IClipboardPropertyItem[] = []; diff --git a/packages/sheets-ui/src/services/clipboard/html-to-usm/converter.ts b/packages/sheets-ui/src/services/clipboard/html-to-usm/converter.ts index ffc11e7e3f9..9cf6feaef54 100644 --- a/packages/sheets-ui/src/services/clipboard/html-to-usm/converter.ts +++ b/packages/sheets-ui/src/services/clipboard/html-to-usm/converter.ts @@ -678,7 +678,23 @@ function parseColGroup(raw: string): IClipboardPropertyItem[] | null { return null; } - return Array.from(colMatches).map((colMatch) => parseProperties(colMatch[1])); + const colPropertiesWithSpan = Array.from(colMatches).map((colMatch) => parseProperties(colMatch[1])); + + const colProperties: IClipboardPropertyItem[] = []; + colPropertiesWithSpan.forEach((propertiesWithSpan) => { + const span = Number(propertiesWithSpan.span); + if (span) { + for (let i = 0; i < span; i++) { + const propertiesWithoutSpan = { ...propertiesWithSpan }; + delete propertiesWithoutSpan.span; + colProperties.push(propertiesWithoutSpan); + } + } else { + colProperties.push(propertiesWithSpan); + } + }); + + return colProperties; } function childNodeToHTML(node: ChildNode) {