fix: fix issues related to remove rows (#5398)

This commit is contained in:
wpxp123456
2025-06-18 17:27:36 +08:00
committed by GitHub
parent c9218b3078
commit 54c0ef5a3f
14 changed files with 962 additions and 52 deletions
+17
View File
@@ -580,6 +580,23 @@ export class Worksheet {
return this._viewModel.getRowFiltered(row);
}
/**
* Get the filtered out rows in a given range. used for remove rows operation, etc.
* @param range - The range to get filtered rows from.
* @returns {number[]} An array of row indices that are filtered out within the specified range.
*/
getRangeFilterRows(range: IRange): number[] {
const rangeFilteredRows = [];
for (let r = range.startRow; r <= range.endRow; r++) {
if (this.getRowFiltered(r)) {
rangeFilteredRows.push(r);
}
}
return rangeFilteredRows;
}
/**
* Get cell matrix from a given range and pick out non-first cells of merged cells.
*
@@ -48,8 +48,18 @@ export interface IFormulaReferenceMoveParam {
from?: IRange;
to?: IRange;
sheetName?: string;
definedNameId?: string; // defined name id
definedName?: string; // new defined name
/**
* defined name id
*/
definedNameId?: string;
/**
* new defined name
*/
definedName?: string;
/**
* The filtered rows contained in the range, used for remove rows operation, etc.
*/
rangeFilteredRows?: number[];
}
const formulaReferenceSheetList = [
@@ -208,7 +218,7 @@ export function refRangeFormula(oldFormulaData: IFormulaData, newFormulaData: IF
const redoFormulaData: Record<string, Record<string, IObjectMatrixPrimitiveType<Nullable<ICellData>>>> = {};
const undoFormulaData: Record<string, Record<string, IObjectMatrixPrimitiveType<Nullable<ICellData>>>> = {};
const { type, unitId: targetUnitId, sheetId, range, from, to } = formulaReferenceMoveParam;
const { unitId: targetUnitId, sheetId } = formulaReferenceMoveParam;
// Iterate over all unitId in oldFormulaData
const allUnitIds = new Set([...Object.keys(oldFormulaData), ...Object.keys(newFormulaData)]);
@@ -237,7 +247,7 @@ export function refRangeFormula(oldFormulaData: IFormulaData, newFormulaData: IF
if (unitId !== targetUnitId || currentSheetId !== sheetId) {
rangeList = processFormulaRange(newFormulaMatrix);
} else {
rangeList = processFormulaChanges(oldFormulaMatrix, type, from, to, range);
rangeList = processFormulaChanges(oldFormulaMatrix, formulaReferenceMoveParam);
}
const sheetRedoFormulaData = getRedoFormulaData(rangeList, oldFormulaMatrix, newFormulaMatrix);
@@ -267,8 +277,9 @@ export function refRangeFormula(oldFormulaData: IFormulaData, newFormulaData: IF
};
}
function processFormulaChanges(oldFormulaMatrix: ObjectMatrix<Nullable<IFormulaDataItem>>, type: FormulaReferenceMoveType, from: Nullable<IRange>, to: Nullable<IRange>, range: Nullable<IRange>) {
function processFormulaChanges(oldFormulaMatrix: ObjectMatrix<Nullable<IFormulaDataItem>>, formulaReferenceMoveParam: IFormulaReferenceMoveParam) {
// When undoing and redoing, the traversal order may be different. Record the range list of all single formula offsets, and then retrieve the traversal as needed.
const { type, from, to, range } = formulaReferenceMoveParam;
const rangeList: IRangeChange[] = [];
oldFormulaMatrix.forValue((row, column, cell) => {
@@ -283,7 +294,7 @@ function processFormulaChanges(oldFormulaMatrix: ObjectMatrix<Nullable<IFormulaD
if ([FormulaReferenceMoveType.MoveRange, FormulaReferenceMoveType.MoveRows, FormulaReferenceMoveType.MoveCols].includes(type)) {
newCell = handleMove(type, from, to, oldCell);
} else if (range !== undefined && range !== null) { // Handle inserts and deletes
const result = handleInsertDelete(type, range, oldCell);
const result = handleInsertDelete(oldCell, formulaReferenceMoveParam);
// When removing a cell containing a formula, newCell is null, but the formula value of oldCell is required when undoing it, newCell can be null
newCell = result.newCell;
isReverse = result.isReverse;
@@ -332,7 +343,10 @@ function handleMove(type: FormulaReferenceMoveType, from: Nullable<IRange>, to:
}
}
function handleInsertDelete(type: FormulaReferenceMoveType, range: IRange, oldCell: IRange) {
function handleInsertDelete(oldCell: IRange, formulaReferenceMoveParam: IFormulaReferenceMoveParam) {
const { type, rangeFilteredRows } = formulaReferenceMoveParam;
const range = formulaReferenceMoveParam.range as IRange;
let newCell: IRange | null = null;
let isReverse = false;
@@ -346,7 +360,7 @@ function handleInsertDelete(type: FormulaReferenceMoveType, range: IRange, oldCe
isReverse = true;
break;
case FormulaReferenceMoveType.RemoveRow:
newCell = handleRefRemoveRow(range, oldCell);
newCell = handleRefRemoveRow(range, oldCell, rangeFilteredRows);
break;
case FormulaReferenceMoveType.RemoveColumn:
newCell = handleRefRemoveCol(range, oldCell);
@@ -432,13 +446,14 @@ function handleRefInsertCol(range: IRange, oldCell: IRange) {
return runRefRangeMutations(operators, oldCell);
}
function handleRefRemoveRow(range: IRange, oldCell: IRange) {
function handleRefRemoveRow(range: IRange, oldCell: IRange, rangeFilteredRows?: number[]) {
const operators = handleIRemoveRow(
{
id: EffectRefRangId.RemoveRowCommandId,
params: { range },
},
oldCell
oldCell,
rangeFilteredRows
);
return runRefRangeMutations(operators, oldCell);
@@ -66,7 +66,7 @@ export function getNewRangeByMoveParam(
currentFormulaUnitId: string,
currentFormulaSheetId: string
) {
const { type, unitId: userUnitId, sheetId: userSheetId, range, from, to } = formulaReferenceMoveParam;
const { type, unitId: userUnitId, sheetId: userSheetId, range, from, to, rangeFilteredRows } = formulaReferenceMoveParam;
const {
range: unitRange,
@@ -241,7 +241,8 @@ export function getNewRangeByMoveParam(
id: EffectRefRangId.RemoveRowCommandId,
params: { range },
},
sequenceRange
sequenceRange,
rangeFilteredRows
);
const result = runRefRangeMutations(operators, sequenceRange);
@@ -287,6 +287,7 @@ function handleRefRemoveRow(command: ICommandInfo<IRemoveRowColCommandParams>, w
range,
unitId,
sheetId,
rangeFilteredRows: workbook.getSheetBySheetId(sheetId)?.getRangeFilterRows(range) ?? [],
};
}
+4 -16
View File
@@ -141,7 +141,7 @@ export function getActiveWorksheet(instanceService: UniverInstanceService): [Nul
return [workbook, worksheet];
}
export function rangeToDiscreteRange(range: IRange, accessor: IAccessor, unitId?: string, subUnitId?: string, considerHide?: boolean): IDiscreteRange | null {
export function rangeToDiscreteRange(range: IRange, accessor: IAccessor, unitId?: string, subUnitId?: string): IDiscreteRange | null {
const univerInstanceService = accessor.get(IUniverInstanceService);
const workbook = unitId
? univerInstanceService.getUnit<Workbook>(unitId, UniverInstanceType.UNIVER_SHEET)
@@ -156,23 +156,11 @@ export function rangeToDiscreteRange(range: IRange, accessor: IAccessor, unitId?
const cols = [];
for (let r = startRow; r <= endRow; r++) {
if (!worksheet.getRowFiltered(r)) {
if (considerHide) {
if (worksheet.getRowRawVisible(r)) {
rows.push(r);
}
} else {
rows.push(r);
}
rows.push(r);
}
}
for (let c = startColumn; c <= endColumn; c++) {
if (considerHide) {
if (worksheet.getColVisible(c)) {
cols.push(c);
}
} else {
cols.push(c);
}
cols.push(c);
}
return {
rows,
@@ -185,7 +173,7 @@ export function getVisibleRanges(ranges: IRange[], accessor: IAccessor, unitId?:
const allCols: number[] = [];
for (const range of ranges) {
const discreteRange = rangeToDiscreteRange(range, accessor, unitId, subUnitId, true);
const discreteRange = rangeToDiscreteRange(range, accessor, unitId, subUnitId);
if (discreteRange) {
allRows.push(...discreteRange.rows);
@@ -106,33 +106,44 @@ export const RemoveRowByRangeCommand: ICommand<IRemoveRowByRangeCommandParams> =
cellValue: removedRows.getMatrix(),
};
const intercepted = sheetInterceptorService.onCommandExecute({
id: RemoveRowCommandId,
params: { range: visibleRange } as IRemoveRowColCommandParams,
});
redos.push(...(intercepted.preRedos ?? []));
redos.push({ id: RemoveRowMutation.id, params: removeRowsParams });
redos.push(...(intercepted.redos ?? []));
undos.push(...(intercepted.preUndos ?? []));
undos.push({ id: InsertRowMutation.id, params: undoRemoveRowsParams });
undos.push({ id: SetRangeValuesMutation.id, params: undoSetRangeValuesParams });
undos.push(...(intercepted.undos ?? []));
redoMutations.push(...redos);
undoMutations.unshift(...undos);
});
redoMutations.push(followSelectionOperation(range, workbook, worksheet));
const intercepted = sheetInterceptorService.onCommandExecute({
id: RemoveRowCommandId,
params: { range } as IRemoveRowColCommandParams,
});
const commandService = accessor.get(ICommandService);
const result = sequenceExecute(redoMutations, commandService);
const result = sequenceExecute(
[
...(intercepted.preRedos ?? []),
...redoMutations,
...intercepted.redos,
followSelectionOperation(range, workbook, worksheet),
],
commandService
);
if (result.result) {
const undoRedoService = accessor.get(IUndoRedoService);
undoRedoService.pushUndoRedo({
unitID: unitId,
undoMutations,
redoMutations,
undoMutations: [
...(intercepted.preUndos ?? []),
...undoMutations,
...intercepted.undos,
],
redoMutations: [
...(intercepted.preRedos ?? []),
...redoMutations,
...intercepted.redos,
],
});
return true;
}
+47 -10
View File
@@ -516,23 +516,60 @@ export const handleIRemoveCol = (param: IRemoveRowColCommand, targetRange: IRang
return operators;
};
export const handleIRemoveRow = (param: IRemoveRowColCommand, targetRange: IRange) => {
export const handleIRemoveRow = (param: IRemoveRowColCommand, targetRange: IRange, rangeFilteredRows?: number[]) => {
const range = param.params?.range;
if (!range) {
return [];
}
const operators: IOperator[] = [];
const result = handleBaseRemoveRange(rotateRange(range), rotateRange(targetRange));
if (!result) {
operators.push({ type: OperatorType.Delete });
// check the remove range contains the filtered rows, if so, we need to skip the filtered rows
if (rangeFilteredRows && rangeFilteredRows.length > 0) {
let startRow = range.startRow;
for (let r = range.startRow; r <= range.endRow; r++) {
if (rangeFilteredRows.includes(r)) {
if (r === startRow) {
startRow = r + 1;
continue;
}
_handleBaseRemoveRange({
...range,
startRow,
endRow: r - 1,
});
startRow = r + 1;
continue;
}
if (r === range.endRow) {
_handleBaseRemoveRange({
...range,
startRow,
endRow: range.endRow,
});
}
}
} else {
const { step, length } = result;
operators.push({
type: OperatorType.VerticalMove,
step,
length,
});
_handleBaseRemoveRange(range);
}
function _handleBaseRemoveRange(removeRange: IRange) {
const result = handleBaseRemoveRange(rotateRange(removeRange), rotateRange(targetRange));
if (!result) {
operators.push({ type: OperatorType.Delete });
} else {
const { step, length } = result;
operators.push({
type: OperatorType.VerticalMove,
step,
length,
});
}
}
return operators;
};
+3
View File
@@ -3545,6 +3545,9 @@ importers:
'@univerjs/sheets-data-validation':
specifier: workspace:*
version: link:../../packages/sheets-data-validation
'@univerjs/sheets-filter':
specifier: workspace:*
version: link:../../packages/sheets-filter
'@univerjs/sheets-formula':
specifier: workspace:*
version: link:../../packages/sheets-formula
+1
View File
@@ -19,6 +19,7 @@
"@univerjs/sheets": "workspace:*",
"@univerjs/sheets-conditional-formatting": "workspace:*",
"@univerjs/sheets-data-validation": "workspace:*",
"@univerjs/sheets-filter": "workspace:*",
"@univerjs/sheets-formula": "workspace:*",
"@univerjs/sheets-numfmt": "workspace:*",
"univer-examples": "workspace:*"
@@ -0,0 +1,327 @@
{
"id": "YoRIim",
"sheetOrder": [
"_P52izs4-QQtg1AbFSjwH"
],
"name": "",
"appVersion": "0.8.1",
"locale": "zhCN",
"styles": {},
"sheets": {
"_P52izs4-QQtg1AbFSjwH": {
"id": "_P52izs4-QQtg1AbFSjwH",
"name": "Sheet1",
"tabColor": "",
"hidden": 0,
"rowCount": 998,
"columnCount": 20,
"zoomRatio": 1,
"freeze": {
"xSplit": 0,
"ySplit": 0,
"startRow": -1,
"startColumn": -1
},
"scrollTop": 0,
"scrollLeft": 0,
"defaultColumnWidth": 88,
"defaultRowHeight": 24,
"mergeData": [],
"cellData": {
"0": {
"0": {
"v": 1,
"t": 2
},
"1": {
"v": 2,
"t": 2
},
"2": {
"v": 3,
"t": 2
},
"3": {
"v": 4,
"t": 2
},
"4": {
"v": 5,
"t": 2
},
"5": {
"v": 6,
"t": 2
},
"6": {
"v": 7,
"t": 2
}
},
"1": {
"0": {
"v": 3,
"t": 2
},
"1": {
"v": 4,
"t": 2
},
"2": {
"v": 5,
"t": 2
},
"3": {
"v": 6,
"t": 2
},
"4": {
"v": 7,
"t": 2
},
"5": {
"v": 8,
"t": 2
},
"6": {
"v": 9,
"t": 2
}
},
"2": {
"0": {
"v": 4,
"t": 2
},
"1": {
"v": 5,
"t": 2
},
"2": {
"v": 6,
"t": 2
},
"3": {
"v": 7,
"t": 2
},
"4": {
"v": 8,
"t": 2
},
"5": {
"v": 9,
"t": 2
},
"6": {
"v": 10,
"t": 2
}
},
"3": {
"0": {
"v": 6,
"t": 2
},
"1": {
"v": 7,
"t": 2
},
"2": {
"v": 8,
"t": 2
},
"3": {
"v": 9,
"t": 2
},
"4": {
"v": 10,
"t": 2
},
"5": {
"v": 11,
"t": 2
},
"6": {
"v": 12,
"t": 2
}
},
"4": {
"0": {
"v": 7,
"t": 2
},
"1": {
"v": 8,
"t": 2
},
"2": {
"v": 9,
"t": 2
},
"3": {
"v": 10,
"t": 2
},
"4": {
"v": 11,
"t": 2
},
"5": {
"v": 12,
"t": 2
},
"6": {
"v": 13,
"t": 2
}
},
"5": {
"0": {
"v": 8,
"t": 2
},
"1": {
"v": 9,
"t": 2
},
"2": {
"v": 10,
"t": 2
},
"3": {
"v": 11,
"t": 2
},
"4": {
"v": 12,
"t": 2
},
"5": {
"v": 13,
"t": 2
},
"6": {
"v": 14,
"t": 2
}
},
"6": {
"0": {
"v": 9,
"t": 2
},
"1": {
"v": 10,
"t": 2
},
"2": {
"v": 11,
"t": 2
},
"3": {
"v": 12,
"t": 2
},
"4": {
"v": 13,
"t": 2
},
"5": {
"v": 14,
"t": 2
},
"6": {
"v": 15,
"t": 2
}
},
"7": {
"0": {
"v": 10,
"t": 2
},
"1": {
"v": 11,
"t": 2
},
"2": {
"v": 12,
"t": 2
},
"3": {
"v": 13,
"t": 2
},
"4": {
"v": 14,
"t": 2
},
"5": {
"v": 15,
"t": 2
},
"6": {
"v": 16,
"t": 2
}
},
"9": {
"1": {
"f": "=SUM(B8)",
"v": 11,
"t": 2
}
}
},
"rowData": {},
"columnData": {
"5": {
"hd": 1
}
},
"showGridlines": 1,
"rowHeader": {
"width": 46,
"hidden": 0
},
"columnHeader": {
"height": 20,
"hidden": 0
},
"rightToLeft": 0
}
},
"resources": [
{
"name": "SHEET_RANGE_PROTECTION_PLUGIN",
"data": ""
},
{
"name": "SHEET_AuthzIoMockService_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_WORKSHEET_PROTECTION_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_WORKSHEET_PROTECTION_POINT_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_DEFINED_NAME_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_RANGE_THEME_MODEL_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_FILTER_PLUGIN",
"data": "{\"_P52izs4-QQtg1AbFSjwH\":{\"ref\":{\"startRow\":0,\"startColumn\":0,\"endRow\":3,\"endColumn\":6,\"rangeType\":0},\"filterColumns\":[{\"colId\":3,\"filters\":{\"filters\":[\"5\",\"8\",\"9\"]}}],\"cachedFilteredOut\":[1,2]}}"
}
]
}
@@ -0,0 +1,387 @@
{
"id": "YoRIim",
"sheetOrder": [
"_P52izs4-QQtg1AbFSjwH"
],
"name": "",
"appVersion": "0.8.1",
"locale": "zhCN",
"styles": {},
"sheets": {
"_P52izs4-QQtg1AbFSjwH": {
"id": "_P52izs4-QQtg1AbFSjwH",
"name": "Sheet1",
"tabColor": "",
"hidden": 0,
"rowCount": 1000,
"columnCount": 20,
"zoomRatio": 1,
"freeze": {
"xSplit": 0,
"ySplit": 0,
"startRow": -1,
"startColumn": -1
},
"scrollTop": 0,
"scrollLeft": 0,
"defaultColumnWidth": 88,
"defaultRowHeight": 24,
"mergeData": [],
"cellData": {
"0": {
"0": {
"v": 1,
"t": 2
},
"1": {
"v": 2,
"t": 2
},
"2": {
"v": 3,
"t": 2
},
"3": {
"v": 4,
"t": 2
},
"4": {
"v": 5,
"t": 2
},
"5": {
"v": 6,
"t": 2
},
"6": {
"v": 7,
"t": 2
}
},
"1": {
"0": {
"v": 2,
"t": 2
},
"1": {
"v": 3,
"t": 2
},
"2": {
"v": 4,
"t": 2
},
"3": {
"v": 5,
"t": 2
},
"4": {
"v": 6,
"t": 2
},
"5": {
"v": 7,
"t": 2
},
"6": {
"v": 8,
"t": 2
}
},
"2": {
"0": {
"v": 3,
"t": 2
},
"1": {
"v": 4,
"t": 2
},
"2": {
"v": 5,
"t": 2
},
"3": {
"v": 6,
"t": 2
},
"4": {
"v": 7,
"t": 2
},
"5": {
"v": 8,
"t": 2
},
"6": {
"v": 9,
"t": 2
}
},
"3": {
"0": {
"v": 4,
"t": 2
},
"1": {
"v": 5,
"t": 2
},
"2": {
"v": 6,
"t": 2
},
"3": {
"v": 7,
"t": 2
},
"4": {
"v": 8,
"t": 2
},
"5": {
"v": 9,
"t": 2
},
"6": {
"v": 10,
"t": 2
}
},
"4": {
"0": {
"v": 5,
"t": 2
},
"1": {
"v": 6,
"t": 2
},
"2": {
"v": 7,
"t": 2
},
"3": {
"v": 8,
"t": 2
},
"4": {
"v": 9,
"t": 2
},
"5": {
"v": 10,
"t": 2
},
"6": {
"v": 11,
"t": 2
}
},
"5": {
"0": {
"v": 6,
"t": 2
},
"1": {
"v": 7,
"t": 2
},
"2": {
"v": 8,
"t": 2
},
"3": {
"v": 9,
"t": 2
},
"4": {
"v": 10,
"t": 2
},
"5": {
"v": 11,
"t": 2
},
"6": {
"v": 12,
"t": 2
}
},
"6": {
"0": {
"v": 7,
"t": 2
},
"1": {
"v": 8,
"t": 2
},
"2": {
"v": 9,
"t": 2
},
"3": {
"v": 10,
"t": 2
},
"4": {
"v": 11,
"t": 2
},
"5": {
"v": 12,
"t": 2
},
"6": {
"v": 13,
"t": 2
}
},
"7": {
"0": {
"v": 8,
"t": 2
},
"1": {
"v": 9,
"t": 2
},
"2": {
"v": 10,
"t": 2
},
"3": {
"v": 11,
"t": 2
},
"4": {
"v": 12,
"t": 2
},
"5": {
"v": 13,
"t": 2
},
"6": {
"v": 14,
"t": 2
}
},
"8": {
"0": {
"v": 9,
"t": 2
},
"1": {
"v": 10,
"t": 2
},
"2": {
"v": 11,
"t": 2
},
"3": {
"v": 12,
"t": 2
},
"4": {
"v": 13,
"t": 2
},
"5": {
"v": 14,
"t": 2
},
"6": {
"v": 15,
"t": 2
}
},
"9": {
"0": {
"v": 10,
"t": 2
},
"1": {
"v": 11,
"t": 2
},
"2": {
"v": 12,
"t": 2
},
"3": {
"v": 13,
"t": 2
},
"4": {
"v": 14,
"t": 2
},
"5": {
"v": 15,
"t": 2
},
"6": {
"v": 16,
"t": 2
}
},
"11": {
"1": {
"f": "=SUM(B10)",
"v": 11,
"t": 2
}
}
},
"rowData": {},
"columnData": {
"5": {
"hd": 1
}
},
"showGridlines": 1,
"rowHeader": {
"width": 46,
"hidden": 0
},
"columnHeader": {
"height": 20,
"hidden": 0
},
"rightToLeft": 0
}
},
"resources": [
{
"name": "SHEET_RANGE_PROTECTION_PLUGIN",
"data": ""
},
{
"name": "SHEET_AuthzIoMockService_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_WORKSHEET_PROTECTION_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_WORKSHEET_PROTECTION_POINT_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_DEFINED_NAME_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_RANGE_THEME_MODEL_PLUGIN",
"data": "{}"
},
{
"name": "SHEET_FILTER_PLUGIN",
"data": "{\"_P52izs4-QQtg1AbFSjwH\":{\"ref\":{\"startRow\":0,\"startColumn\":0,\"endRow\":5,\"endColumn\":6,\"rangeType\":0},\"filterColumns\":[{\"colId\":3,\"filters\":{\"filters\":[\"5\",\"8\",\"9\"]}}],\"cachedFilteredOut\":[2,3]}}"
}
]
}
@@ -0,0 +1,98 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import fs from 'node:fs';
import path from 'node:path';
import { IUniverInstanceService, type IWorkbookData, LocaleType, Univer } from '@univerjs/core';
import { FUniver } from '@univerjs/core/facade';
import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula';
import zhCN from '@univerjs/mockdata/locales/zh-CN';
import { UniverSheetsPlugin } from '@univerjs/sheets';
import { UniverSheetsFilterPlugin } from '@univerjs/sheets-filter';
import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula';
import { expect } from 'vitest';
import { getTestFilePath, getTestName } from './util';
function createTestBed() {
const univer = new Univer({
locale: LocaleType.ZH_CN,
locales: {
[LocaleType.ZH_CN]: zhCN,
},
});
univer.registerPlugin(UniverFormulaEnginePlugin);
univer.registerPlugin(UniverSheetsPlugin);
univer.registerPlugin(UniverSheetsFormulaPlugin);
univer.registerPlugin(UniverSheetsFilterPlugin);
const injector = univer.__getInjector();
return {
univer,
get: injector.get.bind(injector),
api: FUniver.newAPI(univer),
};
}
export async function expectRemoveRowsOfFilterRowsResultMatchesSnapshot() {
const testBed = createTestBed();
const snapshotRootDir = path.join(import.meta.dirname, '../__snapshots__');
const testSnapshotPath = path.resolve(snapshotRootDir, `${getTestFilePath()}.json`);
if (!fs.existsSync(testSnapshotPath)) {
throw new Error(`Cannot find snapshot file for test "${getTestName()}".`);
}
const testSnapshotRaw = fs.readFileSync(testSnapshotPath, 'utf-8');
const testSnapshot = JSON.parse(testSnapshotRaw) as IWorkbookData;
const workbook = testBed.api.createWorkbook(testSnapshot);
const univerInstanceService = testBed.get(IUniverInstanceService);
univerInstanceService.focusUnit('YoRIim');
const worksheet = workbook.getActiveSheet();
// remove rows 2 to 5, where the 3 to 4 rows are filtered rows
worksheet.deleteRows(1, 4);
const resultSnapshot = workbook.save();
const snapshotFilePath = path.resolve(snapshotRootDir, `${getTestFilePath()}-result.json`);
if (fs.existsSync(snapshotFilePath)) {
const resultSnapshotFileString = fs.readFileSync(snapshotFilePath, 'utf-8');
expect(resultSnapshot).toMatchObject(JSON.parse(resultSnapshotFileString));
} else {
fs.writeFileSync(snapshotFilePath, JSON.stringify(resultSnapshot, null, 4));
// eslint-disable-next-line no-console
console.log(`Snapshot file created at: ${snapshotFilePath}`);
}
// perform undo operation
await testBed.api.undo();
// compare the result with the snapshot
const resultSnapshot_undo = workbook.save();
const snapshotFilePath_undo = path.resolve(snapshotRootDir, `${getTestFilePath()}.json`);
if (fs.existsSync(snapshotFilePath_undo)) {
const resultSnapshotFileString = fs.readFileSync(snapshotFilePath_undo, 'utf-8');
expect(resultSnapshot_undo).toMatchObject(JSON.parse(resultSnapshotFileString));
} else {
fs.writeFileSync(snapshotFilePath_undo, JSON.stringify(resultSnapshot_undo, null, 4));
// eslint-disable-next-line no-console
console.log(`Snapshot file created at: ${snapshotFilePath_undo}`);
}
}
@@ -20,7 +20,7 @@ import path from 'node:path';
import { expect } from 'vitest';
import { createFormulaTestBed } from './univer';
function getTestName(): string {
export function getTestName(): string {
const testName = expect.getState().currentTestName;
if (!testName) {
throw new Error('Cannot get test name. Maybe you call the method outside a test case?');
@@ -0,0 +1,24 @@
/**
* Copyright 2023-present DreamNum Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { describe, it } from 'vitest';
import { expectRemoveRowsOfFilterRowsResultMatchesSnapshot } from '../__testing__/test-remove-rows-of-filter-rows';
describe('Test remove rows', () => {
it('of filter rows', () => {
expectRemoveRowsOfFilterRowsResultMatchesSnapshot();
});
});