fix(formula): optimize the behavior when selecting merged cells during formula editing (#6270)

This commit is contained in:
wpxp123456
2025-12-10 10:58:00 +08:00
committed by GitHub
parent 4cd65e69bc
commit fa5bb4a5ac
3 changed files with 50 additions and 8 deletions
+24 -5
View File
@@ -40,7 +40,7 @@ import { DocumentDataModel } from '../docs/data-model/document-data-model';
import { IConfigService } from '../services/config/config.service';
import { IContextService } from '../services/context/context.service';
import { LocaleService } from '../services/locale/locale.service';
import { isCellCoverable, ObjectMatrix, searchArray, Tools } from '../shared';
import { isCellCoverable, ObjectMatrix, Rectangle, searchArray, Tools } from '../shared';
import { ImageCacheMap } from '../shared/cache/image-cache';
import { getIntersectRange } from '../shared/range';
import { Skeleton } from '../skeleton';
@@ -489,7 +489,8 @@ export class SheetSkeleton extends Skeleton {
* @param range
* @returns {IRange} expanded range because merge info.
*/
expandRangeByMerge(range: IRange): IRange {
// eslint-disable-next-line max-lines-per-function
expandRangeByMerge(range: IRange, inRefSelectionMode?: boolean): IRange {
let { startRow, startColumn, endRow, endColumn } = range;
const mergeData = this._worksheetData.mergeData;
if (!mergeData) {
@@ -502,7 +503,10 @@ export class SheetSkeleton extends Skeleton {
}
let isSearching = true;
const searchedMarge = new ObjectMatrix<boolean>();
const searchedMerge = new ObjectMatrix<boolean>();
let searchedMergeSize = 0;
let lastSearchedMergeCell: Nullable<IRange> = null;
// the loop breaks when there are not merged cells intersect with the current range
// NOTE: what about the performance issue?
@@ -517,7 +521,7 @@ export class SheetSkeleton extends Skeleton {
endColumn: mainEndColumn,
} = mergeData[i];
if (searchedMarge.getValue(mainStartRow, mainStartColumn)) {
if (searchedMerge.getValue(mainStartRow, mainStartColumn)) {
continue;
}
@@ -540,12 +544,27 @@ export class SheetSkeleton extends Skeleton {
startColumn = Math.min(startColumn, mainStartColumn);
endRow = Math.max(endRow, mainEndRow);
endColumn = Math.max(endColumn, mainEndColumn);
searchedMarge.setValue(mainStartRow, mainStartColumn, true);
searchedMerge.setValue(mainStartRow, mainStartColumn, true);
isSearching = true;
searchedMergeSize++;
lastSearchedMergeCell = rect2;
}
}
}
/**
* If the selected cell is merged cell, we need to adjust the selection range to the merged main cell in the formula reference selection scenario.
* Must ensure that only one merged cell is involved in the selection and that the merged cell fully contains the selection range.
*/
if (inRefSelectionMode && searchedMergeSize === 1 && Rectangle.contains(lastSearchedMergeCell!, range)) {
return {
startRow: lastSearchedMergeCell!.startRow,
startColumn: lastSearchedMergeCell!.startColumn,
endRow: lastSearchedMergeCell!.startRow,
endColumn: lastSearchedMergeCell!.startColumn,
};
}
return {
startRow,
startColumn,
@@ -325,9 +325,31 @@ export class RefSelectionsRenderService extends BaseSelectionRenderService imple
selectCell.endColumn = this._skeleton.getColumnCount() - 1;
}
const selectionWithStyle: ISelectionWithStyle = { range: selectCell, primary: selectCell, style: null };
let selectionWithStyle: ISelectionWithStyle = { range: selectCell, primary: selectCell, style: null };
// If the selected cell is merged cell, we need to adjust the selection range to the merged main cell in the formula reference selection scenario.
if (selectCell.isMerged || selectCell.isMergedMainCell) {
selectionWithStyle = {
range: {
...selectCell,
startRow: selectCell.startRow,
endRow: selectCell.startRow,
startColumn: selectCell.startColumn,
endColumn: selectCell.startColumn,
},
primary: {
...selectCell,
actualRow: selectCell.startRow,
actualColumn: selectCell.startColumn,
startRow: selectCell.startRow,
endRow: selectCell.startRow,
startColumn: selectCell.startColumn,
endColumn: selectCell.startColumn,
},
style: null,
};
}
selectionWithStyle.range.rangeType = rangeType;
// const selectionCellWithCoord = this._getSelectionWithCoordByOffset(offsetX, offsetY, scaleX, scaleY, scrollXY);
const selectionCellWithCoord = attachSelectionWithCoord(selectionWithStyle, this._skeleton);
this._startRangeWhenPointerDown = { ...selectionCellWithCoord.rangeWithCoord };
@@ -732,8 +732,9 @@ export class BaseSelectionRenderService extends Disposable implements ISheetSele
};
if (this._shouldDetectMergedCells) {
newSelectionRange = skeleton.expandRangeByMerge(newSelectionRange);
newSelectionRange = skeleton.expandRangeByMerge(newSelectionRange, this.inRefSelectionMode());
}
const newSelection: ISelectionWithStyle = { range: newSelectionRange, primary: undefined, style: null };
const newSelectionRangeWithCoord = attachSelectionWithCoord(newSelection, skeleton);
newSelectionRangeWithCoord.rangeWithCoord.unitId = unitId;