mirror of
https://github.com/dream-num/univer.git
synced 2026-08-28 23:01:30 +08:00
feat: add a Copy Formula Only menu item to the right-click menu (#6287)
This commit is contained in:
@@ -173,7 +173,7 @@ export { Styles } from './sheets/styles';
|
||||
|
||||
export * from './sheets/typedef';
|
||||
export type { IPosition } from './sheets/typedef';
|
||||
export { addLinkToDocumentModel, isNotNullOrUndefined, isRangesEqual, isUnitRangesEqual } from './sheets/util';
|
||||
export { addLinkToDocumentModel, getEmptyCell, isNotNullOrUndefined, isRangesEqual, isUnitRangesEqual } from './sheets/util';
|
||||
export { createDocumentModelWithStyle } from './sheets/util';
|
||||
export { SheetViewModel } from './sheets/view-model';
|
||||
export { getWorksheetUID, Workbook } from './sheets/workbook';
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import type { Nullable } from '../shared';
|
||||
import type { CellValueType, TextDirection } from '../types/enum';
|
||||
import type { IDocumentData, IPaddingData, IStyleBase, IStyleData, ITextRotation, ITextStyle } from '../types/interfaces';
|
||||
import type { IRange, IUnitRange } from './typedef';
|
||||
import type { ICellData, IRange, IUnitRange } from './typedef';
|
||||
import { DEFAULT_EMPTY_DOCUMENT_VALUE } from '../common/const';
|
||||
import { BuildTextUtils, DocumentDataModel } from '../docs';
|
||||
import { TextX } from '../docs/data-model/text-x/text-x';
|
||||
@@ -215,3 +215,16 @@ export function addLinkToDocumentModel(documentModel: DocumentDataModel, linkUrl
|
||||
export function isNotNullOrUndefined<T>(value: T | null | undefined): value is T {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
export function getEmptyCell(): ICellData {
|
||||
return {
|
||||
p: null,
|
||||
s: null,
|
||||
v: null,
|
||||
t: null,
|
||||
f: null,
|
||||
si: null,
|
||||
ref: null,
|
||||
xf: null,
|
||||
};
|
||||
}
|
||||
|
||||
+4
-4
@@ -34,7 +34,7 @@ import {
|
||||
rangeToDiscreteRange,
|
||||
} from '@univerjs/sheets';
|
||||
import { AddConditionalRuleMutation, AddConditionalRuleMutationUndoFactory, ConditionalFormattingRuleModel, ConditionalFormattingViewModel, DeleteConditionalRuleMutation, DeleteConditionalRuleMutationUndoFactory, SetConditionalRuleMutation, setConditionalRuleMutationUndoFactory, SHEET_CONDITIONAL_FORMATTING_PLUGIN } from '@univerjs/sheets-conditional-formatting';
|
||||
import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME, virtualizeDiscreteRanges } from '@univerjs/sheets-ui';
|
||||
import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME_PASTE, virtualizeDiscreteRanges } from '@univerjs/sheets-ui';
|
||||
|
||||
export class ConditionalFormattingCopyPasteController extends Disposable {
|
||||
private _copyInfo: Nullable<{
|
||||
@@ -138,9 +138,9 @@ export class ConditionalFormattingCopyPasteController extends Disposable {
|
||||
}
|
||||
|
||||
const specialPastes: IPasteHookValueType[] = [
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME.DEFAULT_PASTE,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_BESIDES_BORDER,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_BESIDES_BORDER,
|
||||
];
|
||||
|
||||
if (
|
||||
|
||||
@@ -19,7 +19,7 @@ import type { IDiscreteRange, IPasteHookValueType } from '@univerjs/sheets-ui';
|
||||
import { Disposable, Inject, Injector, ObjectMatrix, queryObjectMatrix, Rectangle } from '@univerjs/core';
|
||||
import { rangeToDiscreteRange } from '@univerjs/sheets';
|
||||
import { DATA_VALIDATION_PLUGIN_NAME, getDataValidationDiffMutations, SheetDataValidationModel } from '@univerjs/sheets-data-validation';
|
||||
import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME, virtualizeDiscreteRanges } from '@univerjs/sheets-ui';
|
||||
import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME_PASTE, virtualizeDiscreteRanges } from '@univerjs/sheets-ui';
|
||||
|
||||
export class DataValidationCopyPasteController extends Disposable {
|
||||
private _copyInfo: Nullable<{
|
||||
@@ -96,10 +96,10 @@ export class DataValidationCopyPasteController extends Disposable {
|
||||
}
|
||||
|
||||
const specialPastes: IPasteHookValueType[] = [
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA,
|
||||
];
|
||||
|
||||
if (specialPastes.includes(copyInfo.pasteType)) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
discreteRangeToRange,
|
||||
ISheetClipboardService,
|
||||
ISheetSelectionRenderService,
|
||||
PREDEFINED_HOOK_NAME,
|
||||
PREDEFINED_HOOK_NAME_PASTE,
|
||||
SheetSkeletonManagerService,
|
||||
virtualizeDiscreteRanges,
|
||||
} from '@univerjs/sheets-ui';
|
||||
@@ -85,10 +85,10 @@ function focusDocument() {
|
||||
}
|
||||
|
||||
const specialPastes: IPasteHookValueType[] = [
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA,
|
||||
];
|
||||
|
||||
export class SheetsDrawingCopyPasteController extends Disposable {
|
||||
@@ -188,7 +188,7 @@ export class SheetsDrawingCopyPasteController extends Disposable {
|
||||
|
||||
onPasteUnrecognized: (pasteTo: ISheetDiscreteRangeLocation) => {
|
||||
if (this._copyInfo) {
|
||||
return this._generateSingleDrawingPasteMutations({ pasteTo, pasteType: PREDEFINED_HOOK_NAME.DEFAULT_PASTE }, COPY_TYPE.COPY);
|
||||
return this._generateSingleDrawingPasteMutations({ pasteTo, pasteType: PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE }, COPY_TYPE.COPY);
|
||||
} else {
|
||||
return { undos: [], redos: [] };
|
||||
}
|
||||
@@ -196,7 +196,7 @@ export class SheetsDrawingCopyPasteController extends Disposable {
|
||||
|
||||
onPasteFiles: (pasteTo: ISheetDiscreteRangeLocation, files) => {
|
||||
if (this._copyInfo) {
|
||||
return this._generateSingleDrawingPasteMutations({ pasteTo, pasteType: PREDEFINED_HOOK_NAME.DEFAULT_PASTE }, COPY_TYPE.COPY);
|
||||
return this._generateSingleDrawingPasteMutations({ pasteTo, pasteType: PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE }, COPY_TYPE.COPY);
|
||||
} else {
|
||||
// Paste image from external
|
||||
const images = files.filter((file) => file.type.includes('image'));
|
||||
|
||||
@@ -16,7 +16,18 @@
|
||||
|
||||
import type { ICommand } from '@univerjs/core';
|
||||
import { CommandType, ICommandService } from '@univerjs/core';
|
||||
import { PREDEFINED_HOOK_NAME, SheetPasteCommand } from '@univerjs/sheets-ui';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME_COPY, PREDEFINED_HOOK_NAME_PASTE, SheetPasteCommand } from '@univerjs/sheets-ui';
|
||||
|
||||
export const SheetCopyFormulaOnlyCommand: ICommand = {
|
||||
id: 'sheet.command.copy-formula-only',
|
||||
type: CommandType.COMMAND,
|
||||
handler: async (accessor) => {
|
||||
const sheetClipboardService = accessor.get(ISheetClipboardService);
|
||||
return sheetClipboardService.copy({
|
||||
copyHookType: PREDEFINED_HOOK_NAME_COPY.SPECIAL_COPY_FORMULA_ONLY,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const SheetOnlyPasteFormulaCommand: ICommand = {
|
||||
id: 'sheet.command.paste-formula',
|
||||
@@ -24,7 +35,7 @@ export const SheetOnlyPasteFormulaCommand: ICommand = {
|
||||
handler: async (accessor) => {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
return commandService.executeCommand(SheetPasteCommand.id, {
|
||||
value: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA,
|
||||
value: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ import type { ICellDataWithSpanInfo } from '@univerjs/sheets-ui';
|
||||
import { ICommandService, IUniverInstanceService, ObjectMatrix } from '@univerjs/core';
|
||||
import { FormulaDataModel, LexerTreeBuilder } from '@univerjs/engine-formula';
|
||||
import { SetRangeValuesMutation } from '@univerjs/sheets';
|
||||
import { COPY_TYPE, ISheetSelectionRenderService, PREDEFINED_HOOK_NAME, SheetSelectionRenderService } from '@univerjs/sheets-ui';
|
||||
import { COPY_TYPE, ISheetSelectionRenderService, PREDEFINED_HOOK_NAME_PASTE, SheetSelectionRenderService } from '@univerjs/sheets-ui';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { getSetCellFormulaMutations } from '../formula-clipboard.controller';
|
||||
import { createCommandTestBed } from './create-command-test-bed';
|
||||
@@ -99,7 +99,7 @@ describe('Test paste with formula', () => {
|
||||
cols: [2, 3],
|
||||
},
|
||||
copyType: COPY_TYPE.COPY,
|
||||
pasteType: PREDEFINED_HOOK_NAME.DEFAULT_PASTE,
|
||||
pasteType: PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE,
|
||||
};
|
||||
|
||||
const pasteFrom = {
|
||||
@@ -329,7 +329,7 @@ describe('Test paste with formula', () => {
|
||||
rows: [0, 1, 2, 3],
|
||||
cols: [5, 6, 7, 8],
|
||||
},
|
||||
pasteType: PREDEFINED_HOOK_NAME.DEFAULT_PASTE,
|
||||
pasteType: PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE,
|
||||
};
|
||||
|
||||
const pasteFrom = {
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { IAccessor, ICellData, IMutationInfo, Workbook } from '@univerjs/core';
|
||||
import type { IAccessor, ICellData, ICellDataWithSpanAndDisplay, IMutationInfo, IRange, Nullable, Workbook, Worksheet } from '@univerjs/core';
|
||||
import type { ISetRangeValuesMutationParams } from '@univerjs/sheets';
|
||||
import type { ICellDataWithSpanInfo, ICopyPastePayload, IDiscreteRange, IPasteHookValueType, ISheetClipboardHook, ISheetDiscreteRangeLocation } from '@univerjs/sheets-ui';
|
||||
import {
|
||||
DEFAULT_EMPTY_DOCUMENT_VALUE,
|
||||
Disposable,
|
||||
generateRandomId,
|
||||
getEmptyCell,
|
||||
Inject,
|
||||
Injector,
|
||||
isFormulaId,
|
||||
@@ -31,13 +32,13 @@ import {
|
||||
} from '@univerjs/core';
|
||||
import { FormulaDataModel, LexerTreeBuilder } from '@univerjs/engine-formula';
|
||||
import { SetRangeValuesMutation, SetRangeValuesUndoMutationFactory } from '@univerjs/sheets';
|
||||
import { COPY_TYPE, ISheetClipboardService, PREDEFINED_HOOK_NAME } from '@univerjs/sheets-ui';
|
||||
import { COPY_TYPE, ISheetClipboardService, PREDEFINED_HOOK_NAME_COPY, PREDEFINED_HOOK_NAME_PASTE } from '@univerjs/sheets-ui';
|
||||
|
||||
export const DEFAULT_PASTE_FORMULA = 'default-paste-formula';
|
||||
|
||||
export class FormulaClipboardController extends Disposable {
|
||||
constructor(
|
||||
@IUniverInstanceService private readonly _currentUniverSheet: IUniverInstanceService,
|
||||
@IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService,
|
||||
@Inject(LexerTreeBuilder) private readonly _lexerTreeBuilder: LexerTreeBuilder,
|
||||
@ISheetClipboardService private readonly _sheetClipboardService: ISheetClipboardService,
|
||||
@Inject(Injector) private readonly _injector: Injector,
|
||||
@@ -53,13 +54,88 @@ export class FormulaClipboardController extends Disposable {
|
||||
}
|
||||
|
||||
private _registerClipboardHook() {
|
||||
this.disposeWithMe(this._sheetClipboardService.addClipboardHook(this._copyFormulaOnlyHook()));
|
||||
this.disposeWithMe(this._sheetClipboardService.addClipboardHook(this._pasteFormulaHook()));
|
||||
this.disposeWithMe(this._sheetClipboardService.addClipboardHook(this._pasteWithFormulaHook()));
|
||||
}
|
||||
|
||||
private _copyFormulaOnlyHook(): ISheetClipboardHook {
|
||||
const self = this;
|
||||
let currentSheet: Nullable<Worksheet> = null;
|
||||
|
||||
return {
|
||||
id: PREDEFINED_HOOK_NAME_COPY.SPECIAL_COPY_FORMULA_ONLY,
|
||||
priority: 10,
|
||||
onBeforeCopy(unitId, subUnitId) {
|
||||
currentSheet = self._getWorksheet(unitId, subUnitId);
|
||||
},
|
||||
onCopyCellContent(row: number, col: number): string {
|
||||
if (!currentSheet) return '';
|
||||
|
||||
const cell = currentSheet.getCellRaw(row, col);
|
||||
if (!cell) return '';
|
||||
|
||||
if (isFormulaString(cell.f)) return cell.f as string;
|
||||
if (isFormulaId(cell.si)) {
|
||||
const formulaDataModel = self._formulaDataModel;
|
||||
const formulaString = formulaDataModel.getFormulaStringByCell(row, col, currentSheet.getSheetId(), currentSheet.getUnitId());
|
||||
return formulaString || '';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
onAfterCopy() {
|
||||
currentSheet = null;
|
||||
},
|
||||
getFilteredOutRows(unitId: string, subUnitId: string, range: IRange) {
|
||||
const worksheet = self._getWorksheet(unitId, subUnitId);
|
||||
if (!worksheet) return [];
|
||||
|
||||
const { startRow, endRow } = range;
|
||||
const res: number[] = [];
|
||||
|
||||
for (let r = startRow; r <= endRow; r++) {
|
||||
if (worksheet.getRowFiltered(r)) {
|
||||
res.push(r);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
},
|
||||
handleMatrixOnCell(
|
||||
row: number,
|
||||
column: number,
|
||||
rowIndexInMatrix: number,
|
||||
columnIndexInMatrix: number,
|
||||
matrix: ObjectMatrix<ICellDataWithSpanAndDisplay>,
|
||||
matrixFragment: ObjectMatrix<ICellDataWithSpanInfo>,
|
||||
plainMatrix: ObjectMatrix<ICellDataWithSpanAndDisplay>
|
||||
) {
|
||||
const cellData = matrix.getValue(row, column);
|
||||
if (currentSheet && cellData && (isFormulaString(cellData.f) || isFormulaId(cellData.si))) {
|
||||
const formulaString = isFormulaString(cellData.f)
|
||||
? (cellData.f as string)
|
||||
: self._formulaDataModel.getFormulaStringByCell(row, column, currentSheet.getSheetId(), currentSheet.getUnitId()) as string;
|
||||
matrixFragment.setValue(rowIndexInMatrix, columnIndexInMatrix, {
|
||||
...getEmptyCell(),
|
||||
f: formulaString,
|
||||
});
|
||||
plainMatrix.setValue(rowIndexInMatrix, columnIndexInMatrix, {
|
||||
...getEmptyCell(),
|
||||
f: formulaString,
|
||||
displayV: formulaString,
|
||||
});
|
||||
} else {
|
||||
matrix.setValue(row, column, getEmptyCell());
|
||||
matrixFragment.setValue(rowIndexInMatrix, columnIndexInMatrix, getEmptyCell());
|
||||
plainMatrix.setValue(rowIndexInMatrix, columnIndexInMatrix, getEmptyCell());
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private _pasteFormulaHook(): ISheetClipboardHook {
|
||||
return {
|
||||
id: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA,
|
||||
id: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA,
|
||||
priority: 10,
|
||||
specialPasteInfo: { label: 'specialPaste.formula' },
|
||||
onPasteCells: (pasteFrom, pasteTo, data, payload) => this._onPasteCells(pasteFrom, pasteTo, data, payload, true),
|
||||
@@ -74,6 +150,24 @@ export class FormulaClipboardController extends Disposable {
|
||||
};
|
||||
}
|
||||
|
||||
private _getWorkbook(unitId?: string): Nullable<Workbook> {
|
||||
if (unitId) {
|
||||
return this._univerInstanceService.getUnit<Workbook>(unitId, UniverInstanceType.UNIVER_SHEET);
|
||||
}
|
||||
|
||||
return this._univerInstanceService.getCurrentUnitOfType<Workbook>(UniverInstanceType.UNIVER_SHEET);
|
||||
}
|
||||
|
||||
private _getWorksheet(unitId?: string, subUnitId?: string): Nullable<Worksheet> {
|
||||
const workbook = this._getWorkbook(unitId);
|
||||
|
||||
if (subUnitId) {
|
||||
return workbook?.getSheetBySheetId(subUnitId);
|
||||
}
|
||||
|
||||
return workbook?.getActiveSheet();
|
||||
}
|
||||
|
||||
private _onPasteCells(
|
||||
pasteFrom: ISheetDiscreteRangeLocation | null,
|
||||
pasteTo: ISheetDiscreteRangeLocation,
|
||||
@@ -83,8 +177,8 @@ export class FormulaClipboardController extends Disposable {
|
||||
) {
|
||||
// Intercept scenarios where formulas do not need to be processed, and only process default paste and paste formulas only
|
||||
const specialPastes: IPasteHookValueType[] = [
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_COL_WIDTH,
|
||||
];
|
||||
if (specialPastes.includes(payload.pasteType)) {
|
||||
return {
|
||||
@@ -93,9 +187,9 @@ export class FormulaClipboardController extends Disposable {
|
||||
};
|
||||
}
|
||||
|
||||
const workbook = this._currentUniverSheet.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET)!;
|
||||
const unitId = pasteTo.unitId || workbook.getUnitId();
|
||||
const subUnitId = pasteTo.subUnitId || workbook.getActiveSheet()?.getSheetId();
|
||||
const workbook = this._getWorkbook();
|
||||
const unitId = pasteTo.unitId || workbook?.getUnitId();
|
||||
const subUnitId = pasteTo.subUnitId || workbook?.getActiveSheet()?.getSheetId();
|
||||
|
||||
if (!unitId || !subUnitId) {
|
||||
return {
|
||||
@@ -201,11 +295,11 @@ function getValueMatrix(
|
||||
return getValueMatrixOfPasteFromIsNull(unitId, subUnitId, range, matrix, formulaDataModel);
|
||||
}
|
||||
|
||||
if (copyInfo.pasteType === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE) {
|
||||
if (copyInfo.pasteType === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE) {
|
||||
return getSpecialPasteValueValueMatrix(unitId, subUnitId, range, matrix, formulaDataModel, pasteFrom);
|
||||
}
|
||||
|
||||
if (copyInfo.pasteType === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA) {
|
||||
if (copyInfo.pasteType === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA) {
|
||||
return getSpecialPasteFormulaValueMatrix(unitId, subUnitId, range, matrix, lexerTreeBuilder, formulaDataModel, pasteFrom);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import { IRenderManagerService } from '@univerjs/engine-render';
|
||||
|
||||
import { SheetsUIPart } from '@univerjs/sheets-ui';
|
||||
import { ComponentManager, connectInjector, IMenuManagerService, IShortcutService, IUIPartsService } from '@univerjs/ui';
|
||||
import { SheetOnlyPasteFormulaCommand } from '../commands/commands/formula-clipboard.command';
|
||||
import { SheetCopyFormulaOnlyCommand, SheetOnlyPasteFormulaCommand } from '../commands/commands/formula-clipboard.command';
|
||||
import { SelectEditorFormulaOperation } from '../commands/operations/editor-formula.operation';
|
||||
import { HelpFunctionOperation } from '../commands/operations/help-function.operation';
|
||||
import { InsertFunctionOperation } from '../commands/operations/insert-function.operation';
|
||||
@@ -71,6 +71,7 @@ export class FormulaUIController extends Disposable {
|
||||
|
||||
private _registerCommands(): void {
|
||||
[
|
||||
SheetCopyFormulaOnlyCommand,
|
||||
SheetOnlyPasteFormulaCommand,
|
||||
InsertFunctionOperation,
|
||||
MoreFunctionsOperation,
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
|
||||
import type { MenuSchemaType } from '@univerjs/ui';
|
||||
import { PASTE_SPECIAL_MENU_ID } from '@univerjs/sheets-ui';
|
||||
import { COPY_SPECIAL_MENU_ID, PASTE_SPECIAL_MENU_ID } from '@univerjs/sheets-ui';
|
||||
import { RibbonFormulasGroup } from '@univerjs/ui';
|
||||
import { SheetOnlyPasteFormulaCommand } from '../commands/commands/formula-clipboard.command';
|
||||
import { SheetCopyFormulaOnlyCommand, SheetOnlyPasteFormulaCommand } from '../commands/commands/formula-clipboard.command';
|
||||
import { InsertFunctionOperation } from '../commands/operations/insert-function.operation';
|
||||
import { MoreFunctionsOperation } from '../commands/operations/more-functions.operation';
|
||||
import {
|
||||
CopyFormulaOnlyMenuItemFactory,
|
||||
InsertAVERAGEFunctionMenuItemFactory,
|
||||
InsertCOUNTFunctionMenuItemFactory,
|
||||
InsertMAXFunctionMenuItemFactory,
|
||||
@@ -59,6 +60,12 @@ export const menuSchema: MenuSchemaType = {
|
||||
menuItemFactory: MoreFunctionsMenuItemFactory,
|
||||
},
|
||||
},
|
||||
[COPY_SPECIAL_MENU_ID]: {
|
||||
[SheetCopyFormulaOnlyCommand.id]: {
|
||||
order: 0,
|
||||
menuItemFactory: CopyFormulaOnlyMenuItemFactory,
|
||||
},
|
||||
},
|
||||
[PASTE_SPECIAL_MENU_ID]: {
|
||||
[SheetOnlyPasteFormulaCommand.id]: {
|
||||
order: 4,
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
import type { IAccessor, Workbook } from '@univerjs/core';
|
||||
import type { IMenuItem } from '@univerjs/ui';
|
||||
import { IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
|
||||
import { RangeProtectionPermissionEditPoint, WorkbookEditablePermission, WorksheetEditPermission, WorksheetSetCellValuePermission } from '@univerjs/sheets';
|
||||
import { RangeProtectionPermissionEditPoint, RangeProtectionPermissionViewPoint, WorkbookCopyPermission, WorkbookEditablePermission, WorksheetCopyPermission, WorksheetEditPermission, WorksheetSetCellValuePermission } from '@univerjs/sheets';
|
||||
import { getCurrentRangeDisable$ } from '@univerjs/sheets-ui';
|
||||
import { getMenuHiddenObservable, IClipboardInterfaceService, MenuItemType } from '@univerjs/ui';
|
||||
import { combineLatestWith, map, Observable, of, switchMap } from 'rxjs';
|
||||
import { SheetOnlyPasteFormulaCommand } from '../commands/commands/formula-clipboard.command';
|
||||
import { SheetCopyFormulaOnlyCommand, SheetOnlyPasteFormulaCommand } from '../commands/commands/formula-clipboard.command';
|
||||
import { InsertFunctionOperation } from '../commands/operations/insert-function.operation';
|
||||
import { MoreFunctionsOperation } from '../commands/operations/more-functions.operation';
|
||||
|
||||
@@ -207,6 +207,22 @@ function menuClipboardDisabledObservable(injector: IAccessor): Observable<boolea
|
||||
);
|
||||
}
|
||||
|
||||
// Right click menu - Copy Formula Only
|
||||
export function CopyFormulaOnlyMenuItemFactory(accessor: IAccessor): IMenuItem {
|
||||
return {
|
||||
id: SheetCopyFormulaOnlyCommand.id,
|
||||
type: MenuItemType.BUTTON,
|
||||
title: 'formula.operation.copyFormulaOnly',
|
||||
disabled$: getCurrentRangeDisable$(accessor, {
|
||||
workbookTypes: [WorkbookCopyPermission],
|
||||
worksheetTypes: [WorksheetCopyPermission],
|
||||
rangeTypes: [RangeProtectionPermissionViewPoint],
|
||||
}),
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET),
|
||||
};
|
||||
}
|
||||
|
||||
// Right click menu - Paste Formula
|
||||
export function PasteFormulaMenuItemFactory(accessor: IAccessor): IMenuItem {
|
||||
return {
|
||||
id: SheetOnlyPasteFormulaCommand.id,
|
||||
@@ -220,5 +236,6 @@ export function PasteFormulaMenuItemFactory(accessor: IAccessor): IMenuItem {
|
||||
})),
|
||||
map(([d1, d2]) => d1 || d2)
|
||||
),
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import './global.css';
|
||||
|
||||
export { SheetOnlyPasteFormulaCommand } from './commands/commands/formula-clipboard.command';
|
||||
export { SheetCopyFormulaOnlyCommand, SheetOnlyPasteFormulaCommand } from './commands/commands/formula-clipboard.command';
|
||||
export { SelectEditorFormulaOperation } from './commands/operations/editor-formula.operation';
|
||||
export { HelpFunctionOperation } from './commands/operations/help-function.operation';
|
||||
export { InsertFunctionOperation } from './commands/operations/insert-function.operation';
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: 'SINTAXI',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: 'Copia només la fórmula',
|
||||
pasteFormula: 'Enganxa la fórmula',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -113,6 +113,7 @@ const locale = {
|
||||
syntax: 'SYNTAX',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: 'Copy Formula Only',
|
||||
pasteFormula: 'Paste Formula',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: 'SINTAXIS',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: 'Copiar solo fórmula',
|
||||
pasteFormula: 'Pegar fórmula',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: 'سینتکس',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: 'کپی فقط فرمول',
|
||||
pasteFormula: 'چسباندن فرمول',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: 'SYNTAXE',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: 'Copier uniquement la formule',
|
||||
pasteFormula: 'Coller la formule',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: '構文',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: '数式のみをコピー',
|
||||
pasteFormula: '数式を貼り付け',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: '구문',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: '수식만 복사',
|
||||
pasteFormula: '수식 붙여넣기',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -114,6 +114,7 @@ const locale: typeof enUS = {
|
||||
syntax: 'СИНТАКСИС',
|
||||
},
|
||||
operation: {
|
||||
copyFormulaOnly: 'Копировать только формулу',
|
||||
pasteFormula: 'Вставить Формулу',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -118,6 +118,7 @@ const locale: typeof enUS = {
|
||||
},
|
||||
|
||||
operation: {
|
||||
copyFormulaOnly: 'Chỉ sao chép công thức',
|
||||
pasteFormula: 'Chỉ dán công thức',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -118,6 +118,7 @@ const locale: typeof enUS = {
|
||||
},
|
||||
|
||||
operation: {
|
||||
copyFormulaOnly: '仅复制公式',
|
||||
pasteFormula: '仅粘贴公式',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -118,6 +118,7 @@ const locale: typeof enUS = {
|
||||
},
|
||||
|
||||
operation: {
|
||||
copyFormulaOnly: '僅複製公式',
|
||||
pasteFormula: '僅貼上公式',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@ import type { IDiscreteRange, IPasteHookValueType, ISheetDiscreteRangeLocation }
|
||||
import { Disposable, generateRandomId, Inject, Injector, ObjectMatrix, Range, Rectangle } from '@univerjs/core';
|
||||
import { rangeToDiscreteRange } from '@univerjs/sheets';
|
||||
import { AddHyperLinkMutation, HyperLinkModel, RemoveHyperLinkMutation } from '@univerjs/sheets-hyper-link';
|
||||
import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME, virtualizeDiscreteRanges } from '@univerjs/sheets-ui';
|
||||
import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME_PASTE, virtualizeDiscreteRanges } from '@univerjs/sheets-ui';
|
||||
import { isLegalLink } from '../common/util';
|
||||
import { SheetsHyperLinkResolverService } from '../services/resolver.service';
|
||||
import { SHEET_HYPER_LINK_UI_PLUGIN } from '../types/const';
|
||||
@@ -154,10 +154,10 @@ export class SheetsHyperLinkCopyPasteController extends Disposable {
|
||||
}
|
||||
|
||||
const specialPastes: IPasteHookValueType[] = [
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_COL_WIDTH,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA,
|
||||
];
|
||||
|
||||
if (specialPastes.includes(copyInfo.pasteType)) {
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
|
||||
import type { IAccessor, ICommand, IMultiCommand } from '@univerjs/core';
|
||||
import type { IPasteHookKeyType } from '../../services/clipboard/type';
|
||||
import { CommandType, ICommandService } from '@univerjs/core';
|
||||
import { CopyCommand, CutCommand, IClipboardInterfaceService, PasteCommand, SheetPasteShortKeyCommandName } from '@univerjs/ui';
|
||||
|
||||
import { whenSheetFocused } from '../../controllers/shortcuts/utils';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME } from '../../services/clipboard/clipboard.service';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME_PASTE } from '../../services/clipboard/clipboard.service';
|
||||
|
||||
const SHEET_CLIPBOARD_PRIORITY = 998;
|
||||
|
||||
@@ -101,7 +101,9 @@ export const SheetPasteValueCommand: ICommand = {
|
||||
type: CommandType.COMMAND,
|
||||
handler: async (accessor) => {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
return commandService.executeCommand(SheetPasteCommand.id, { value: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE });
|
||||
return commandService.executeCommand(SheetPasteCommand.id, {
|
||||
value: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -111,7 +113,7 @@ export const SheetPasteFormatCommand: ICommand = {
|
||||
handler: async (accessor) => {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
return commandService.executeCommand(SheetPasteCommand.id, {
|
||||
value: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
value: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -122,7 +124,7 @@ export const SheetPasteColWidthCommand: ICommand = {
|
||||
handler: async (accessor) => {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
return commandService.executeCommand(SheetPasteCommand.id, {
|
||||
value: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_COL_WIDTH,
|
||||
value: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_COL_WIDTH,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -133,7 +135,7 @@ export const SheetPasteBesidesBorderCommand: ICommand = {
|
||||
handler: async (accessor) => {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
return commandService.executeCommand(SheetPasteCommand.id, {
|
||||
value: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_BESIDES_BORDER,
|
||||
value: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_BESIDES_BORDER,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -141,7 +143,7 @@ export const SheetPasteBesidesBorderCommand: ICommand = {
|
||||
export const SheetOptionalPasteCommand: ICommand = {
|
||||
id: 'sheet.command.optional-paste',
|
||||
type: CommandType.COMMAND,
|
||||
handler: async (accessor, { type }: { type: keyof typeof PREDEFINED_HOOK_NAME }) => {
|
||||
handler: async (accessor, { type }: { type: IPasteHookKeyType }) => {
|
||||
const clipboardService = accessor.get(ISheetClipboardService);
|
||||
|
||||
return clipboardService.rePasteWithPasteType(type);
|
||||
|
||||
@@ -97,7 +97,7 @@ import {
|
||||
SheetPasteValueCommand,
|
||||
} from '../../commands/commands/clipboard.command';
|
||||
import { SetScrollOperation } from '../../commands/operations/scroll.operation';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME } from '../../services/clipboard/clipboard.service';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME_COPY, PREDEFINED_HOOK_NAME_PASTE } from '../../services/clipboard/clipboard.service';
|
||||
import { SheetSkeletonManagerService } from '../../services/sheet-skeleton-manager.service';
|
||||
import { ClipboardPopupMenu } from '../../views/clipboard/ClipboardPopupMenu';
|
||||
import { SHEETS_UI_PLUGIN_CONFIG_KEY } from '../config.schema';
|
||||
@@ -239,7 +239,7 @@ export class SheetClipboardController extends RxDisposable {
|
||||
const self = this;
|
||||
let currentSheet: Worksheet | null = null;
|
||||
return {
|
||||
id: PREDEFINED_HOOK_NAME.DEFAULT_COPY,
|
||||
id: PREDEFINED_HOOK_NAME_COPY.DEFAULT_COPY,
|
||||
isDefaultHook: true,
|
||||
onBeforeCopy(unitId, subUnitId) {
|
||||
currentSheet = self._getWorksheet(unitId, subUnitId);
|
||||
@@ -308,13 +308,13 @@ export class SheetClipboardController extends RxDisposable {
|
||||
onAfterCopy() {
|
||||
currentSheet = null;
|
||||
},
|
||||
getFilteredOutRows(range: IRange) {
|
||||
getFilteredOutRows(unitId: string, subUnitId: string, range: IRange) {
|
||||
const worksheet = self._getWorksheet(unitId, subUnitId);
|
||||
if (!worksheet) return [];
|
||||
|
||||
const { startRow, endRow } = range;
|
||||
const worksheet = self._instanceService.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET)?.getActiveSheet();
|
||||
const res: number[] = [];
|
||||
if (!worksheet) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for (let r = startRow; r <= endRow; r++) {
|
||||
if (worksheet.getRowFiltered(r)) {
|
||||
res.push(r);
|
||||
@@ -334,7 +334,7 @@ export class SheetClipboardController extends RxDisposable {
|
||||
let currentSheet: Worksheet | null = null;
|
||||
|
||||
return {
|
||||
id: PREDEFINED_HOOK_NAME.DEFAULT_PASTE,
|
||||
id: PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE,
|
||||
isDefaultHook: true,
|
||||
onBeforePaste({ unitId: unitId_, subUnitId: subUnitId_, range }) {
|
||||
currentSheet = self._getWorksheet(unitId_, subUnitId_);
|
||||
@@ -700,7 +700,7 @@ export class SheetClipboardController extends RxDisposable {
|
||||
const self = this;
|
||||
|
||||
const specialPasteValueHook: ISheetClipboardHook = {
|
||||
id: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE,
|
||||
id: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE,
|
||||
specialPasteInfo: {
|
||||
label: 'specialPaste.value',
|
||||
},
|
||||
@@ -711,7 +711,7 @@ export class SheetClipboardController extends RxDisposable {
|
||||
},
|
||||
};
|
||||
const specialPasteFormatHook: ISheetClipboardHook = {
|
||||
id: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT,
|
||||
id: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT,
|
||||
specialPasteInfo: {
|
||||
label: 'specialPaste.format',
|
||||
},
|
||||
@@ -757,7 +757,7 @@ export class SheetClipboardController extends RxDisposable {
|
||||
};
|
||||
|
||||
const specialPasteColWidthHook: ISheetClipboardHook = {
|
||||
id: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_COL_WIDTH,
|
||||
id: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_COL_WIDTH,
|
||||
specialPasteInfo: {
|
||||
label: 'specialPaste.colWidth',
|
||||
},
|
||||
@@ -841,7 +841,7 @@ export class SheetClipboardController extends RxDisposable {
|
||||
};
|
||||
|
||||
const specialPasteBesidesBorder: ISheetClipboardHook = {
|
||||
id: PREDEFINED_HOOK_NAME.SPECIAL_PASTE_BESIDES_BORDER,
|
||||
id: PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_BESIDES_BORDER,
|
||||
specialPasteInfo: {
|
||||
label: 'specialPaste.besidesBorder',
|
||||
},
|
||||
|
||||
@@ -117,7 +117,9 @@ import {
|
||||
BoldMenuItemFactory,
|
||||
CancelFrozenMenuItemFactory,
|
||||
ColAutoWidthMenuItemFactory,
|
||||
COPY_SPECIAL_MENU_ID,
|
||||
CopyMenuItemFactory,
|
||||
CopySpacialMenuItemFactory,
|
||||
CutMenuItemFactory,
|
||||
FitContentMenuItemFactory,
|
||||
FontFamilySelectorMenuItemFactory,
|
||||
@@ -132,7 +134,6 @@ import {
|
||||
PASTE_SPECIAL_MENU_ID,
|
||||
PasteBesidesBorderMenuItemFactory,
|
||||
PasteColWidthMenuItemFactory,
|
||||
// PasteColWidthMenuItemFactory,
|
||||
PasteFormatMenuItemFactory,
|
||||
PasteMenuItemFactory,
|
||||
PasteSpacialMenuItemFactory,
|
||||
@@ -302,6 +303,10 @@ export const menuSchema: MenuSchemaType = {
|
||||
order: 2,
|
||||
menuItemFactory: PasteMenuItemFactory,
|
||||
},
|
||||
[COPY_SPECIAL_MENU_ID]: {
|
||||
order: 2.5,
|
||||
menuItemFactory: CopySpacialMenuItemFactory,
|
||||
},
|
||||
[PASTE_SPECIAL_MENU_ID]: {
|
||||
order: 3,
|
||||
menuItemFactory: PasteSpacialMenuItemFactory,
|
||||
@@ -443,6 +448,10 @@ export const menuSchema: MenuSchemaType = {
|
||||
order: 2,
|
||||
menuItemFactory: PasteMenuItemFactory,
|
||||
},
|
||||
[COPY_SPECIAL_MENU_ID]: {
|
||||
order: 2.5,
|
||||
menuItemFactory: CopySpacialMenuItemFactory,
|
||||
},
|
||||
[PASTE_SPECIAL_MENU_ID]: {
|
||||
order: 3,
|
||||
menuItemFactory: PasteSpacialMenuItemFactory,
|
||||
@@ -564,6 +573,10 @@ export const menuSchema: MenuSchemaType = {
|
||||
order: 2,
|
||||
menuItemFactory: PasteMenuItemFactory,
|
||||
},
|
||||
[COPY_SPECIAL_MENU_ID]: {
|
||||
order: 2.5,
|
||||
menuItemFactory: CopySpacialMenuItemFactory,
|
||||
},
|
||||
[PASTE_SPECIAL_MENU_ID]: {
|
||||
order: 3,
|
||||
menuItemFactory: PasteSpacialMenuItemFactory,
|
||||
|
||||
@@ -941,6 +941,19 @@ export function PasteMenuItemFactory(accessor: IAccessor): IMenuButtonItem {
|
||||
};
|
||||
}
|
||||
|
||||
// Right click menu - Copy Special
|
||||
export const COPY_SPECIAL_MENU_ID = 'sheet.menu.copy-special';
|
||||
export function CopySpacialMenuItemFactory(accessor: IAccessor): IMenuSelectorItem {
|
||||
return {
|
||||
id: COPY_SPECIAL_MENU_ID,
|
||||
type: MenuItemType.SUBITEMS,
|
||||
icon: 'CopyDoubleIcon',
|
||||
title: 'rightClick.copySpecial',
|
||||
hidden$: getObservableWithExclusiveRange$(accessor, getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET)),
|
||||
};
|
||||
}
|
||||
|
||||
// Right click menu - Paste Special
|
||||
export const PASTE_SPECIAL_MENU_ID = 'sheet.menu.paste-special';
|
||||
export function PasteSpacialMenuItemFactory(accessor: IAccessor): IMenuSelectorItem {
|
||||
return {
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@ import { SetRangeBoldCommand, SetRangeItalicCommand, SetRangeStrickThroughComman
|
||||
import { ApplyFormatPainterCommand } from '../../commands/commands/set-format-painter.command';
|
||||
import { SetCellEditVisibleOperation } from '../../commands/operations/cell-edit.operation';
|
||||
import { IAutoFillService } from '../../services/auto-fill/auto-fill.service';
|
||||
import { PREDEFINED_HOOK_NAME } from '../../services/clipboard/clipboard.service';
|
||||
import { PREDEFINED_HOOK_NAME_PASTE } from '../../services/clipboard/clipboard.service';
|
||||
import { UNIVER_SHEET_PERMISSION_ALERT_DIALOG, UNIVER_SHEET_PERMISSION_ALERT_DIALOG_ID } from '../../views/permission/error-msg-dialog/interface';
|
||||
|
||||
type ICellPermission = Record<UnitAction, boolean> & { ruleId?: string; ranges?: IRange[] };
|
||||
@@ -202,13 +202,13 @@ export class SheetPermissionCheckUIController extends Disposable {
|
||||
}
|
||||
|
||||
private _permissionCheckByPaste(params: ISheetPasteParams) {
|
||||
if (params.value === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_VALUE || params.value === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMULA) {
|
||||
if (params.value === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_VALUE || params.value === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMULA) {
|
||||
return this._sheetPermissionCheckController.permissionCheckWithRanges({
|
||||
workbookTypes: [WorkbookEditablePermission],
|
||||
rangeTypes: [RangeProtectionPermissionEditPoint],
|
||||
worksheetTypes: [WorksheetSetCellStylePermission, WorksheetEditPermission],
|
||||
});
|
||||
} else if (params.value === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT) {
|
||||
} else if (params.value === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT) {
|
||||
return this._sheetPermissionCheckController.permissionCheckWithRanges({
|
||||
workbookTypes: [WorkbookEditablePermission],
|
||||
rangeTypes: [RangeProtectionPermissionEditPoint],
|
||||
|
||||
@@ -106,7 +106,7 @@ export { EMBEDDING_FORMULA_EDITOR, isEmbeddingFormulaEditor } from './controller
|
||||
export { isRangeSelector, RANGE_SELECTOR_SYMBOLS } from './controllers/editor/utils/is-range-selector';
|
||||
export { HoverRenderController } from './controllers/hover-render.controller';
|
||||
export { menuSchema as SheetsUIMenuSchema } from './controllers/menu.schema';
|
||||
export { PASTE_SPECIAL_MENU_ID, SheetMenuPosition } from './controllers/menu/menu';
|
||||
export { COPY_SPECIAL_MENU_ID, PASTE_SPECIAL_MENU_ID, SheetMenuPosition } from './controllers/menu/menu';
|
||||
export { deriveStateFromActiveSheet$, getCurrentExclusiveRangeInterest$, getCurrentRangeDisable$, getObservableWithExclusiveRange$ } from './controllers/menu/menu-util';
|
||||
export { SheetPermissionCheckUIController } from './controllers/permission/sheet-permission-check-ui.controller';
|
||||
export { HeaderFreezeRenderController } from './controllers/render-controllers/freeze.render-controller';
|
||||
@@ -132,9 +132,9 @@ export { type ICanvasPopup, SheetCanvasPopManagerService } from './services/canv
|
||||
export { CellAlertManagerService, CellAlertType, type ICellAlert } from './services/cell-alert-manager.service';
|
||||
export { type IDropdownParam, ISheetCellDropdownManagerService, SheetCellDropdownManagerService } from './services/cell-dropdown-manager.service';
|
||||
export { CellPopupManagerService } from './services/cell-popup-manager.service';
|
||||
export { getMatrixPlainText, ISheetClipboardService, PREDEFINED_HOOK_NAME, SheetClipboardService } from './services/clipboard/clipboard.service';
|
||||
export { getMatrixPlainText, ISheetClipboardService, PREDEFINED_HOOK_NAME, PREDEFINED_HOOK_NAME_COPY, PREDEFINED_HOOK_NAME_PASTE, SheetClipboardService } from './services/clipboard/clipboard.service';
|
||||
export { COPY_TYPE } from './services/clipboard/type';
|
||||
export type { ICellDataWithSpanInfo, ICopyPastePayload, IPasteHookValueType, ISheetClipboardHook, ISheetDiscreteRangeLocation } from './services/clipboard/type';
|
||||
export type { ICellDataWithSpanInfo, ICopyHookKeyType, ICopyHookValueType, ICopyPastePayload, IPasteHookKeyType, IPasteHookValueType, ISheetClipboardHook, ISheetDiscreteRangeLocation } from './services/clipboard/type';
|
||||
export { getRepeatRange, mergeSetRangeValues } from './services/clipboard/utils';
|
||||
export { DragManagerService, type IDragCellPosition } from './services/drag-manager.service';
|
||||
export { EditorBridgeService, IEditorBridgeService, type IEditorBridgeServiceVisibleParam } from './services/editor-bridge.service';
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'Copiar',
|
||||
cut: 'Retallar',
|
||||
paste: 'Enganxar',
|
||||
copySpecial: 'Còpia especial',
|
||||
pasteSpecial: 'Enganxat especial',
|
||||
pasteValue: 'Enganxar només els valors',
|
||||
pasteFormat: 'Enganxar només el format',
|
||||
|
||||
@@ -186,6 +186,7 @@ const locale = {
|
||||
copy: 'Copy',
|
||||
cut: 'Cut',
|
||||
paste: 'Paste',
|
||||
copySpecial: 'Copy Special',
|
||||
pasteSpecial: 'Paste Special',
|
||||
pasteValue: 'Paste Value',
|
||||
pasteFormat: 'Paste Format',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'Copiar',
|
||||
cut: 'Cortar',
|
||||
paste: 'Pegar',
|
||||
copySpecial: 'Copiar especial',
|
||||
pasteSpecial: 'Pegado especial',
|
||||
pasteValue: 'Pegar solo valores',
|
||||
pasteFormat: 'Pegar solo formato',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'کپی',
|
||||
cut: 'برش',
|
||||
paste: 'چسباندن',
|
||||
copySpecial: 'کپی ویژه',
|
||||
pasteSpecial: 'چسباندن ویژه',
|
||||
pasteValue: 'چسباندن مقدار',
|
||||
pasteFormat: 'چسباندن قالب',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'Copier',
|
||||
cut: 'Couper',
|
||||
paste: 'Coller',
|
||||
copySpecial: 'Collage spécial',
|
||||
pasteSpecial: 'Collage spécial',
|
||||
pasteValue: 'Coller la valeur',
|
||||
pasteFormat: 'Coller le format',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'コピー',
|
||||
cut: '切り取り',
|
||||
paste: '貼り付け',
|
||||
copySpecial: '選択的にコピー',
|
||||
pasteSpecial: '形式を選択して貼り付け',
|
||||
pasteValue: '値を貼り付け',
|
||||
pasteFormat: '書式を貼り付け',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: '복사',
|
||||
cut: '자르기',
|
||||
paste: '붙여넣기',
|
||||
copySpecial: '선택하여 복사',
|
||||
pasteSpecial: '선택하여 붙여넣기',
|
||||
pasteValue: '값 붙여넣기',
|
||||
pasteFormat: '서식 붙여넣기',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'Копировать',
|
||||
cut: 'Вырезать',
|
||||
paste: 'Вставить',
|
||||
copySpecial: 'Выборочная копия',
|
||||
pasteSpecial: 'Специальная вставка',
|
||||
pasteValue: 'Вставить значение',
|
||||
pasteFormat: 'Вставить формат',
|
||||
|
||||
@@ -188,6 +188,7 @@ const locale: typeof enUS = {
|
||||
copy: 'Sao chép',
|
||||
cut: 'Cắt',
|
||||
paste: 'Dán',
|
||||
copySpecial: 'Sao chép đặc biệt',
|
||||
pasteSpecial: 'Dán đặc biệt',
|
||||
pasteValue: 'Chỉ dán giá trị',
|
||||
pasteFormat: 'Chỉ dán định dạng',
|
||||
|
||||
@@ -189,6 +189,7 @@ const locale: typeof enUS = {
|
||||
copy: '复制',
|
||||
cut: '剪切',
|
||||
paste: '粘贴',
|
||||
copySpecial: '选择性复制',
|
||||
pasteSpecial: '选择性粘贴',
|
||||
pasteValue: '仅粘贴值',
|
||||
pasteFormat: '仅粘贴格式',
|
||||
|
||||
@@ -189,6 +189,7 @@ const locale: typeof enUS = {
|
||||
copy: '複製',
|
||||
cut: '剪下',
|
||||
paste: '貼上',
|
||||
copySpecial: '選擇性複製',
|
||||
pasteSpecial: '選擇性貼上',
|
||||
pasteValue: '僅貼上值',
|
||||
pasteFormat: '僅貼上格式',
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
} from '@univerjs/sheets';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { discreteRangeToRange } from '../../../controllers/utils/range-tools';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME } from '../clipboard.service';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME_PASTE } from '../clipboard.service';
|
||||
import { COPY_TYPE } from '../type';
|
||||
import { clipboardTestBed } from './clipboard-test-bed';
|
||||
import { MockClipboard } from './mock-clipboard';
|
||||
@@ -1136,7 +1136,7 @@ describe('Test clipboard', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
(sheetClipboardService as any)._pasteInternal(copyId, PREDEFINED_HOOK_NAME.DEFAULT_PASTE);
|
||||
(sheetClipboardService as any)._pasteInternal(copyId, PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE);
|
||||
|
||||
expect(getValues(24, 0, 24, 0)![0][0]).toBe(null);
|
||||
expect(getValues(24, 1, 24, 1)![0][0]!.v).toBe('A25');
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import type {
|
||||
ICellData,
|
||||
ICellDataWithSpanAndDisplay,
|
||||
IDisposable,
|
||||
IMutationInfo,
|
||||
@@ -30,6 +29,7 @@ import type { IDiscreteRange } from '../../controllers/utils/range-tools';
|
||||
import type {
|
||||
ICellDataWithSpanInfo,
|
||||
IClipboardPropertyItem,
|
||||
ICopyOptions,
|
||||
IPasteHookKeyType,
|
||||
IPasteHookValueType,
|
||||
IPasteOptionCache,
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
Disposable,
|
||||
ErrorService,
|
||||
extractPureTextFromCell,
|
||||
getEmptyCell,
|
||||
ICommandService,
|
||||
ILogService,
|
||||
Inject,
|
||||
@@ -60,7 +61,6 @@ import {
|
||||
UniverInstanceType,
|
||||
} from '@univerjs/core';
|
||||
import { IRenderManagerService, withCurrentTypeOfRenderer } from '@univerjs/engine-render';
|
||||
|
||||
import {
|
||||
getPrimaryForRange,
|
||||
rangeToDiscreteRange,
|
||||
@@ -70,13 +70,11 @@ import {
|
||||
SheetsSelectionsService,
|
||||
} from '@univerjs/sheets';
|
||||
import { FILE__BMP_CLIPBOARD_MIME_TYPE, FILE__JPEG_CLIPBOARD_MIME_TYPE, FILE__WEBP_CLIPBOARD_MIME_TYPE, FILE_PNG_CLIPBOARD_MIME_TYPE, HTML_CLIPBOARD_MIME_TYPE, IClipboardInterfaceService, imageMimeTypeSet, INotificationService, IPlatformService, PLAIN_TEXT_CLIPBOARD_MIME_TYPE } from '@univerjs/ui';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { virtualizeDiscreteRanges } from '../../controllers/utils/range-tools';
|
||||
import { IMarkSelectionService } from '../mark-selection/mark-selection.service';
|
||||
import { SheetSkeletonManagerService } from '../sheet-skeleton-manager.service';
|
||||
import { createCopyPasteSelectionStyle } from '../utils/selection-util';
|
||||
|
||||
import { cloneCellDataWithSpanInfo } from './clone';
|
||||
import { CopyContentCache, extractId, genId } from './copy-content-cache';
|
||||
import { HtmlToUSMService } from './html-to-usm/converter';
|
||||
@@ -87,8 +85,11 @@ import { COPY_TYPE } from './type';
|
||||
import { USMToHtmlService } from './usm-to-html/convertor';
|
||||
import { convertTextToTable, discreteRangeContainsRange, htmlContainsImage, htmlIsFromExcel, mergeSetRangeValues, rangeIntersectWithDiscreteRange, spilitLargeSetRangeValuesMutations } from './utils';
|
||||
|
||||
export const PREDEFINED_HOOK_NAME = {
|
||||
export const PREDEFINED_HOOK_NAME_COPY = {
|
||||
DEFAULT_COPY: 'default-copy',
|
||||
SPECIAL_COPY_FORMULA_ONLY: 'special-copy-formula-only',
|
||||
} as const;
|
||||
export const PREDEFINED_HOOK_NAME_PASTE = {
|
||||
DEFAULT_PASTE: 'default-paste',
|
||||
SPECIAL_PASTE_VALUE: 'special-paste-value',
|
||||
SPECIAL_PASTE_FORMAT: 'special-paste-format',
|
||||
@@ -96,6 +97,10 @@ export const PREDEFINED_HOOK_NAME = {
|
||||
SPECIAL_PASTE_BESIDES_BORDER: 'special-paste-besides-border',
|
||||
SPECIAL_PASTE_FORMULA: 'special-paste-formula',
|
||||
} as const;
|
||||
export const PREDEFINED_HOOK_NAME = {
|
||||
...PREDEFINED_HOOK_NAME_COPY,
|
||||
...PREDEFINED_HOOK_NAME_PASTE,
|
||||
} as const;
|
||||
|
||||
const IMAGE_MIME_TO_EXTENSION = {
|
||||
[FILE_PNG_CLIPBOARD_MIME_TYPE]: 'png',
|
||||
@@ -129,7 +134,7 @@ export interface ISheetClipboardService {
|
||||
getPasteOptionsCache: () => IPasteOptionCache | null;
|
||||
updatePasteOptionsCache(cache: IPasteOptionCache | null): void;
|
||||
|
||||
copy(): Promise<boolean>;
|
||||
copy(options?: ICopyOptions): Promise<boolean>;
|
||||
cut(): Promise<boolean>;
|
||||
paste(item: ClipboardItem, pasteType?: string): Promise<boolean>; // get content from a ClipboardItem and paste it.
|
||||
legacyPaste(html?: string, text?: string, files?: File[]): Promise<boolean>; // paste a HTML string or plain text directly.
|
||||
@@ -137,7 +142,7 @@ export interface ISheetClipboardService {
|
||||
rePasteWithPasteType(type: IPasteHookKeyType): boolean;
|
||||
disposePasteOptionsCache(): void;
|
||||
|
||||
generateCopyContent(workbookId: string, worksheetId: string, range: IRange, copyType?: COPY_TYPE): Nullable<ICopyContent>;
|
||||
generateCopyContent(workbookId: string, worksheetId: string, range: IRange, options?: ICopyOptions): Nullable<ICopyContent>;
|
||||
copyContentCache(): CopyContentCache; // return the cache content for inner copy/cut/paste.
|
||||
addClipboardHook(hook: ISheetClipboardHook): IDisposable; // add a hook to the clipboard service
|
||||
getClipboardHooks(): ISheetClipboardHook[]; // get all hooks
|
||||
@@ -217,30 +222,33 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
return this._copyContentCache;
|
||||
}
|
||||
|
||||
generateCopyContent(workbookId: string, worksheetId: string, range: IRange, copyType: COPY_TYPE = COPY_TYPE.COPY): Nullable<ICopyContent> {
|
||||
const hooks = this._clipboardHooks;
|
||||
generateCopyContent(workbookId: string, worksheetId: string, range: IRange, { copyType = COPY_TYPE.COPY, copyHookType = PREDEFINED_HOOK_NAME_COPY.DEFAULT_COPY } = {}): Nullable<ICopyContent> {
|
||||
const hooks = this._clipboardHooks.filter((h) => h.id === copyHookType);
|
||||
hooks.forEach((h) => h.onBeforeCopy?.(workbookId, worksheetId, range, copyType));
|
||||
const copyContent = this._generateCopyContent(workbookId, worksheetId, range, this._clipboardHooks);
|
||||
const copyContent = this._generateCopyContent(workbookId, worksheetId, range, hooks, copyHookType);
|
||||
hooks.forEach((h) => h.onAfterCopy?.());
|
||||
|
||||
return copyContent;
|
||||
}
|
||||
|
||||
async copy(copyType = COPY_TYPE.COPY): Promise<boolean> {
|
||||
async copy({
|
||||
copyType = COPY_TYPE.COPY,
|
||||
copyHookType = PREDEFINED_HOOK_NAME_COPY.DEFAULT_COPY,
|
||||
} = {}): Promise<boolean> {
|
||||
const selection = this._selectionManagerService.getCurrentLastSelection();
|
||||
if (!selection) {
|
||||
return false; // maybe we should notify user that there is no selection
|
||||
}
|
||||
|
||||
const workbook = this._univerInstanceService.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET)!;
|
||||
const worksheet = workbook.getActiveSheet();
|
||||
if (!worksheet) {
|
||||
const workbook = this._univerInstanceService.getCurrentUnitForType<Workbook>(UniverInstanceType.UNIVER_SHEET);
|
||||
const worksheet = workbook?.getActiveSheet();
|
||||
if (!workbook || !worksheet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const workbookId = workbook.getUnitId();
|
||||
const worksheetId = worksheet.getSheetId();
|
||||
|
||||
const copyContent = this.generateCopyContent(workbookId, worksheetId, selection.range, copyType);
|
||||
const copyContent = this.generateCopyContent(workbookId, worksheetId, selection.range, { copyType, copyHookType });
|
||||
|
||||
if (!copyContent) {
|
||||
return false;
|
||||
@@ -271,10 +279,12 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
}
|
||||
|
||||
async cut(): Promise<boolean> {
|
||||
return this.copy(COPY_TYPE.CUT);
|
||||
return this.copy({
|
||||
copyType: COPY_TYPE.CUT,
|
||||
});
|
||||
}
|
||||
|
||||
async paste(item: ClipboardItem, pasteType = PREDEFINED_HOOK_NAME.DEFAULT_PASTE): Promise<boolean> {
|
||||
async paste(item: ClipboardItem, pasteType = PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE): Promise<boolean> {
|
||||
const types = item.types;
|
||||
const text =
|
||||
types.indexOf(PLAIN_TEXT_CLIPBOARD_MIME_TYPE) !== -1
|
||||
@@ -333,15 +343,15 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
const isFromExcel = htmlIsFromExcel(html ?? '');
|
||||
|
||||
if (files && !isFromExcel) {
|
||||
return this._pasteFiles(files, PREDEFINED_HOOK_NAME.DEFAULT_PASTE);
|
||||
return this._pasteFiles(files, PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE);
|
||||
} else if (html) {
|
||||
return this._pasteHTML(html, PREDEFINED_HOOK_NAME.DEFAULT_PASTE);
|
||||
return this._pasteHTML(html, PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE);
|
||||
} else if (text) {
|
||||
// Converts text with tabs and newlines into an HTML table
|
||||
if (/[\n\t]/.test(text)) {
|
||||
return this._pasteHTML(convertTextToTable(text), PREDEFINED_HOOK_NAME.DEFAULT_PASTE);
|
||||
return this._pasteHTML(convertTextToTable(text), PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE);
|
||||
} else {
|
||||
return this._pastePlainText(text, PREDEFINED_HOOK_NAME.DEFAULT_PASTE);
|
||||
return this._pastePlainText(text, PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE);
|
||||
}
|
||||
} else {
|
||||
return this._pasteUnrecognized();
|
||||
@@ -369,7 +379,7 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
cellMatrix,
|
||||
colProperties,
|
||||
rowProperties,
|
||||
}, target, PREDEFINED_HOOK_NAME[type] as IPasteHookValueType, source);
|
||||
}, target, PREDEFINED_HOOK_NAME_PASTE[type], source);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -407,7 +417,7 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
return this._clipboardHooks;
|
||||
}
|
||||
|
||||
private _generateCopyContent(unitId: string, subUnitId: string, range: IRange, hooks: ISheetClipboardHook[]): Nullable<ICopyContent> {
|
||||
private _generateCopyContent(unitId: string, subUnitId: string, range: IRange, hooks: ISheetClipboardHook[], copyHookType = PREDEFINED_HOOK_NAME_COPY.DEFAULT_COPY): Nullable<ICopyContent> {
|
||||
const workbook = this._univerInstanceService.getUniverSheetInstance(unitId);
|
||||
const worksheet = workbook?.getSheetBySheetId(subUnitId);
|
||||
|
||||
@@ -417,7 +427,7 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
|
||||
// get filtered out rows those are filtered out by plugins (e.g. filter feature)
|
||||
const filteredRows = hooks.reduce((acc, cur) => {
|
||||
const rows = cur.getFilteredOutRows?.(range);
|
||||
const rows = cur.getFilteredOutRows?.(unitId, subUnitId, range);
|
||||
rows?.forEach((r) => acc.add(r));
|
||||
return acc;
|
||||
}, new Set<number>());
|
||||
@@ -438,23 +448,27 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
}
|
||||
discreteRange.rows.push(r);
|
||||
for (let c = startColumn; c <= endColumn; c++) {
|
||||
const cellData = matrix.getValue(r, c);
|
||||
if (cellData) {
|
||||
const newCellData = cloneCellDataWithSpanAndDisplay(cellData)!;
|
||||
plainMatrix.setValue(rowIndex - startRow, c - startColumn, {
|
||||
...getEmptyCell(),
|
||||
...newCellData,
|
||||
});
|
||||
|
||||
delete newCellData.displayV;
|
||||
matrixFragment.setValue(rowIndex - startRow, c - startColumn, {
|
||||
...getEmptyCell(),
|
||||
...newCellData,
|
||||
});
|
||||
if (copyHookType !== PREDEFINED_HOOK_NAME_COPY.DEFAULT_COPY) {
|
||||
hooks.forEach((h) => h.handleMatrixOnCell?.(r, c, rowIndex - startRow, c - startColumn, matrix, matrixFragment, plainMatrix));
|
||||
} else {
|
||||
plainMatrix.setValue(rowIndex - startRow, c - startColumn, getEmptyCell());
|
||||
matrixFragment.setValue(rowIndex - startRow, c - startColumn, getEmptyCell());
|
||||
matrix.setValue(r, c, getEmptyCell());
|
||||
const cellData = matrix.getValue(r, c);
|
||||
if (cellData) {
|
||||
const newCellData = cloneCellDataWithSpanAndDisplay(cellData)!;
|
||||
plainMatrix.setValue(rowIndex - startRow, c - startColumn, {
|
||||
...getEmptyCell(),
|
||||
...newCellData,
|
||||
});
|
||||
|
||||
delete newCellData.displayV;
|
||||
matrixFragment.setValue(rowIndex - startRow, c - startColumn, {
|
||||
...getEmptyCell(),
|
||||
...newCellData,
|
||||
});
|
||||
} else {
|
||||
plainMatrix.setValue(rowIndex - startRow, c - startColumn, getEmptyCell());
|
||||
matrixFragment.setValue(rowIndex - startRow, c - startColumn, getEmptyCell());
|
||||
matrix.setValue(r, c, getEmptyCell());
|
||||
}
|
||||
}
|
||||
}
|
||||
rowIndex += 1;
|
||||
@@ -774,7 +788,7 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
// if hooks are not special or default, it will be executed in any case.
|
||||
// other hooks will be executed only when the paste type is the same as the hook name, including the default one
|
||||
const filteredHooks: ISheetClipboardHook[] = enabledHooks.filter(
|
||||
(h) => (!h.specialPasteInfo && h.id !== PREDEFINED_HOOK_NAME.DEFAULT_PASTE) || pasteType === h.id
|
||||
(h) => (!h.specialPasteInfo && h.id !== PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE) || pasteType === h.id
|
||||
);
|
||||
filteredHooks.forEach((h) => {
|
||||
if (rowProperties) {
|
||||
@@ -899,9 +913,9 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
|
||||
const rowSpan = mainCell?.rowSpan || 1;
|
||||
const colSpan = mainCell?.colSpan || 1;
|
||||
|
||||
const shouldExpandPrimary = pasteType === PREDEFINED_HOOK_NAME.DEFAULT_PASTE
|
||||
|| pasteType === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_BESIDES_BORDER
|
||||
|| pasteType === PREDEFINED_HOOK_NAME.SPECIAL_PASTE_FORMAT;
|
||||
const shouldExpandPrimary = pasteType === PREDEFINED_HOOK_NAME_PASTE.DEFAULT_PASTE
|
||||
|| pasteType === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_BESIDES_BORDER
|
||||
|| pasteType === PREDEFINED_HOOK_NAME_PASTE.SPECIAL_PASTE_FORMAT;
|
||||
|
||||
if (shouldExpandPrimary && (rowSpan > 1 || colSpan > 1)) {
|
||||
const mergeRange = {
|
||||
@@ -1357,14 +1371,3 @@ function isMultipleCells(cellMatrix: ObjectMatrix<ICellDataWithSpanAndDisplay>):
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
function getEmptyCell(): ICellData {
|
||||
return {
|
||||
p: null,
|
||||
v: null,
|
||||
s: null,
|
||||
f: null,
|
||||
si: null,
|
||||
t: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ICellData, IDocumentData, IMutationInfo, IRange, ObjectMatrix } from '@univerjs/core';
|
||||
import type { ICellData, ICellDataWithSpanAndDisplay, IDocumentData, IMutationInfo, IRange, ObjectMatrix } from '@univerjs/core';
|
||||
import type { IDiscreteRange } from '../../controllers/utils/range-tools';
|
||||
import type { PREDEFINED_HOOK_NAME } from './clipboard.service';
|
||||
import type { PREDEFINED_HOOK_NAME_COPY, PREDEFINED_HOOK_NAME_PASTE } from './clipboard.service';
|
||||
|
||||
export enum COPY_TYPE {
|
||||
COPY = 'COPY',
|
||||
@@ -255,9 +255,29 @@ export interface ISheetClipboardHook {
|
||||
* The callback would be called before the clipboard service decides what region need to be copied from or pasted to.
|
||||
* It would jump over these filtered rows when copying or pasting.
|
||||
*/
|
||||
getFilteredOutRows?(range: IRange): number[];
|
||||
getFilteredOutRows?(unitId: string, subUnitId: string, range: IRange): number[];
|
||||
|
||||
/**
|
||||
* Handle matrix on each cell of copy operation.
|
||||
*/
|
||||
handleMatrixOnCell?(
|
||||
row: number,
|
||||
column: number,
|
||||
rowIndexInMatrix: number,
|
||||
columnIndexInMatrix: number,
|
||||
matrix: ObjectMatrix<ICellDataWithSpanAndDisplay>,
|
||||
matrixFragment: ObjectMatrix<ICellDataWithSpanInfo>,
|
||||
plainMatrix: ObjectMatrix<ICellDataWithSpanAndDisplay>
|
||||
): void;
|
||||
}
|
||||
|
||||
export interface ICopyOptions {
|
||||
copyType?: COPY_TYPE;
|
||||
copyHookType?: ICopyHookValueType;
|
||||
}
|
||||
export type ICopyHookKeyType = keyof typeof PREDEFINED_HOOK_NAME_COPY;
|
||||
export type ICopyHookValueType = typeof PREDEFINED_HOOK_NAME_COPY[ICopyHookKeyType];
|
||||
|
||||
export interface IPasteOptionCache {
|
||||
target: IPasteTarget;
|
||||
source?: IPasteSource;
|
||||
@@ -266,8 +286,6 @@ export interface IPasteOptionCache {
|
||||
colProperties?: IClipboardPropertyItem[];
|
||||
pasteType: IPasteHookValueType;
|
||||
}
|
||||
|
||||
export type IPasteSource = ISheetDiscreteRangeLocation & { copyId: string; copyType: COPY_TYPE };
|
||||
export type IPasteHookKeyType = Exclude<keyof typeof PREDEFINED_HOOK_NAME, 'default-copy'>;
|
||||
export type IPasteHookValueTypeWithoutDefaultCopy = typeof PREDEFINED_HOOK_NAME[IPasteHookKeyType];
|
||||
export type IPasteHookValueType = Exclude<IPasteHookValueTypeWithoutDefaultCopy, 'default-copy'>;
|
||||
export type IPasteHookKeyType = keyof typeof PREDEFINED_HOOK_NAME_PASTE;
|
||||
export type IPasteHookValueType = typeof PREDEFINED_HOOK_NAME_PASTE[IPasteHookKeyType];
|
||||
|
||||
@@ -25,7 +25,7 @@ import { useState } from 'react';
|
||||
import { SheetOptionalPasteCommand } from '../../commands/commands/clipboard.command';
|
||||
import { useActiveWorkbook } from '../../components/hook';
|
||||
import { getSheetObject } from '../../controllers/utils/component-tools';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME } from '../../services/clipboard/clipboard.service';
|
||||
import { ISheetClipboardService, PREDEFINED_HOOK_NAME_PASTE } from '../../services/clipboard/clipboard.service';
|
||||
import { ISheetSelectionRenderService } from '../../services/selection/base-selection-render.service';
|
||||
import { SheetSkeletonManagerService } from '../../services/sheet-skeleton-manager.service';
|
||||
|
||||
@@ -151,7 +151,7 @@ export const ClipboardPopupMenu = () => {
|
||||
type: 'checkbox',
|
||||
value: item.value,
|
||||
label: localeService.t(item.label),
|
||||
checked: pasteOptionsCache?.pasteType === PREDEFINED_HOOK_NAME[item.value as IPasteHookKeyType],
|
||||
checked: pasteOptionsCache?.pasteType === PREDEFINED_HOOK_NAME_PASTE[item.value as IPasteHookKeyType],
|
||||
onSelect: () => handleClick(item.value),
|
||||
}))}
|
||||
open={visible}
|
||||
|
||||
Reference in New Issue
Block a user