fix(sheet): sheet name quote (#4198)

Co-authored-by: GitHub Actions <actions@github.com>
This commit is contained in:
Dushusir
2025-01-07 16:13:31 +08:00
committed by GitHub
co-authored by GitHub Actions
parent b413d6809e
commit f42c01a2ed
17 changed files with 457 additions and 29 deletions
@@ -156,3 +156,137 @@ test('diff facade sheet hooks', async () => {
const screenshot = await page.locator(SHEET_MAIN_CANVAS_ID).screenshot();
await expect(screenshot).toMatchSnapshot(filename, { maxDiffPixels: 5 });
});
test('diff set force string cell', async () => {
const browser = await chromium.launch({
headless: !!isCI, // Set to false to see the browser window
});
const context = await browser.newContext({
viewport: { width: 1280, height: 1280 },
deviceScaleFactor: 2, // Set your desired DPR
});
const page = await context.newPage();
await page.goto('http://localhost:3000/sheets/');
await page.waitForTimeout(2000);
await page.evaluate(() => window.E2EControllerAPI.loadDefaultStyleSheet());
await page.waitForTimeout(2000);
await page.evaluate(async () => {
const activeWorkbook = window.univerAPI.getActiveWorkbook();
const activeSheet = activeWorkbook.getActiveSheet();
const sheetId = activeSheet.getSheetId();
const unitId = activeWorkbook.getId();
await window.univerAPI.executeCommand('sheet.operation.set-selections', {
selections: [
{
range: {
startRow: 0,
startColumn: 7,
endRow: 0,
endColumn: 7,
rangeType: 0,
unitId,
sheetId,
},
primary: {
actualRow: 0,
actualColumn: 7,
isMerged: false,
isMergedMainCell: false,
startRow: 0,
startColumn: 7,
endRow: 0,
endColumn: 7,
},
style: {
strokeWidth: 1,
stroke: '#274fee',
fill: 'rgba(39,79,238,0.07)',
widgets: {},
widgetSize: 6,
widgetStrokeWidth: 1,
widgetStroke: '#ffffff',
autofillSize: 6,
autofillStrokeWidth: 1,
autofillStroke: '#ffffff',
rowHeaderFill: 'rgba(39,79,238,0.07)',
rowHeaderStroke: '#274fee',
rowHeaderStrokeWidth: 1,
columnHeaderFill: 'rgba(39,79,238,0.07)',
columnHeaderStroke: '#274fee',
columnHeaderStrokeWidth: 1,
expandCornerSize: 40,
},
},
],
unitId,
subUnitId: sheetId,
type: 2,
});
activeWorkbook.startEditing();
await window.univerAPI.getActiveDocument().appendText("'1");
activeWorkbook.endEditing(true);
});
const filename = generateSnapshotName('set-force-string-cell');
const screenshot = await page.locator(SHEET_MAIN_CANVAS_ID).screenshot();
await expect(screenshot).toMatchSnapshot(filename, { maxDiffPixels: 5 });
await page.waitForTimeout(2000);
await browser.close();
});
test('diff set text format number cell', async () => {
const browser = await chromium.launch({
headless: !!isCI, // Set to false to see the browser window
});
const context = await browser.newContext({
viewport: { width: 1280, height: 1280 },
deviceScaleFactor: 2, // Set your desired DPR
});
const page = await context.newPage();
await page.goto('http://localhost:3000/sheets/');
await page.waitForTimeout(2000);
await page.evaluate(() => window.E2EControllerAPI.loadDefaultStyleSheet());
await page.waitForTimeout(2000);
await page.evaluate(async () => {
await window.univerAPI.executeCommand('sheet.command.numfmt.set.numfmt', {
values: [
{
row: 0,
col: 7,
pattern: '@@@',
type: 'text',
},
],
});
await window.univerAPI.getActiveWorkbook().getActiveSheet().getRange('H1').setValue(2);
await window.univerAPI.getActiveWorkbook().getActiveSheet().getRange('I1').setValue(3);
await window.univerAPI.executeCommand('sheet.command.numfmt.set.numfmt', {
values: [
{
row: 0,
col: 8,
pattern: '@@@',
type: 'text',
},
],
});
});
const filename = generateSnapshotName('set-text-format-number-cell');
const screenshot = await page.locator(SHEET_MAIN_CANVAS_ID).screenshot();
await expect(screenshot).toMatchSnapshot(filename, { maxDiffPixels: 5 });
await page.waitForTimeout(2000);
await browser.close();
});
@@ -1456,7 +1456,18 @@ export class LexerTreeBuilder extends Disposable {
} else {
const nextCurrentString = formulaStringArray[cur + 1];
if (nextCurrentString && nextCurrentString === matchToken.SINGLE_QUOTATION) {
// handle 'Sheet'1'!A1
// Add the first single quotation
this._pushSegment(currentString);
this._addSequenceArray(sequenceArray, currentString, cur);
cur++;
// Add the second single quotation
this._pushSegment(nextCurrentString);
this._addSequenceArray(sequenceArray, nextCurrentString, cur);
cur++;
continue;
} else {
this._closeSingleQuotation();
}
@@ -101,6 +101,19 @@ describe('Test Reference', () => {
});
it('serializeRangeToRefString', () => {
expect(
serializeRangeToRefString({
range: {
startColumn: 0,
endColumn: 10,
startRow: 5,
endRow: 10,
rangeType: RANGE_TYPE.COLUMN,
},
sheetName: '',
unitId: '',
})
).toEqual('A:K');
expect(
serializeRangeToRefString({
range: {
@@ -140,6 +153,45 @@ describe('Test Reference', () => {
unitId: 'workbook-1',
})
).toEqual("'[workbook-1]sheet1'!16:16");
expect(
serializeRangeToRefString({
range: {
startColumn: Number.NaN,
endColumn: Number.NaN,
startRow: 15,
endRow: 15,
rangeType: RANGE_TYPE.ROW,
},
sheetName: "sheet'1",
unitId: '',
})
).toEqual("'sheet''1'!16:16");
expect(
serializeRangeToRefString({
range: {
startColumn: Number.NaN,
endColumn: Number.NaN,
startRow: 15,
endRow: 15,
rangeType: RANGE_TYPE.ROW,
},
sheetName: "sheet''1",
unitId: '',
})
).toEqual("'sheet''''1'!16:16");
expect(
serializeRangeToRefString({
range: {
startColumn: Number.NaN,
endColumn: Number.NaN,
startRow: 15,
endRow: 15,
rangeType: RANGE_TYPE.ROW,
},
sheetName: "sheet'1",
unitId: 'workbook-1',
})
).toEqual("'[workbook-1]sheet''1'!16:16");
});
it('deserializeRangeWithSheet', () => {
@@ -259,7 +311,7 @@ describe('Test Reference', () => {
'12a',
'💩a',
'❤️b',
"Sheet'",
"Sheet'1",
'!Sheet',
'!Sheet',
'Sheet1(副本)',
@@ -305,11 +357,40 @@ describe('Test Reference', () => {
unitId: '',
});
// with single quote
expect(handleRefStringInfo("'sheet''1'!A1")).toStrictEqual({
refBody: 'A1',
sheetName: "sheet'1",
unitId: '',
});
// with double quote
expect(handleRefStringInfo("'sheet''''1'!A1")).toStrictEqual({
refBody: 'A1',
sheetName: "sheet''1",
unitId: '',
});
expect(handleRefStringInfo("'[Book-1.xlsx]Sheet1'!$A$4")).toStrictEqual({
refBody: '$A$4',
sheetName: 'Sheet1',
unitId: 'Book-1.xlsx',
});
// with single quote
expect(handleRefStringInfo("'[Book''1.xlsx]Sheet1'!$A$4")).toStrictEqual({
refBody: '$A$4',
sheetName: 'Sheet1',
unitId: "Book'1.xlsx",
});
// with double quote
expect(handleRefStringInfo("'[Book''''1.xlsx]Sheet1'!$A$4")).toStrictEqual({
refBody: '$A$4',
sheetName: 'Sheet1',
unitId: "Book''1.xlsx",
});
expect(handleRefStringInfo("'[Book-1.xlsx]sheet-1'!$A$4")).toStrictEqual({
refBody: '$A$4',
sheetName: 'sheet-1',
@@ -153,10 +153,7 @@ export function serializeRange(range: IRange): string {
* @param range
*/
export function serializeRangeWithSheet(sheetName: string, range: IRange): string {
if (needsQuoting(sheetName)) {
return `'${sheetName}'!${serializeRange(range)}`;
}
return `${sheetName}!${serializeRange(range)}`;
return `${addQuotesBothSides(sheetName)}!${serializeRange(range)}`;
}
/**
@@ -167,7 +164,7 @@ export function serializeRangeWithSheet(sheetName: string, range: IRange): strin
*/
export function serializeRangeWithSpreadsheet(unit: string, sheetName: string, range: IRange): string {
if (needsQuoting(unit) || needsQuoting(sheetName)) {
return `'[${unit}]${sheetName}'!${serializeRange(range)}`;
return `'[${quoteSheetName(unit)}]${quoteSheetName(sheetName)}'!${serializeRange(range)}`;
}
return `[${unit}]${sheetName}!${serializeRange(range)}`;
@@ -206,7 +203,7 @@ export function handleRefStringInfo(refString: string) {
if (unitIdMatch != null) {
unitId = unitIdMatch[0].trim();
unitId = unitId.slice(1, unitId.length - 1);
unitId = unquoteSheetName(unitId.slice(1, unitId.length - 1));
refString = refString.replace(UNIT_NAME_REGEX_PRECOMPILING, '');
}
@@ -218,6 +215,8 @@ export function handleRefStringInfo(refString: string) {
if (sheetName[0] === "'" && sheetName[sheetName.length - 1] === "'") {
sheetName = sheetName.substring(1, sheetName.length - 1);
}
sheetName = unquoteSheetName(sheetName);
refBody = refString.substring(sheetNameIndex + 1);
} else {
refBody = refString;
@@ -426,6 +425,31 @@ export function needsQuoting(name: string) {
return false;
}
/**
* Add quotes to the sheet name
*/
export function addQuotesBothSides(name: string) {
return needsQuoting(name) ? `'${quoteSheetName(name)}'` : name;
}
/**
* Add a single quote before the single quote
* @param name
* @returns Quoted name
*/
function quoteSheetName(name: string) {
return name.replace(/'/g, "''");
}
/**
* Replace double single quotes with single quotes
* @param name
* @returns Unquoted name
*/
function unquoteSheetName(name: string) {
return name.replace(/''/g, "'");
}
function isA1Notation(name: string) {
const match = name.match(/[1-9][0-9]{0,6}/);
// Excel has a limit on the number of rows and columns: targetRow > 1048576 || targetColumn > 16384, Univer has no limit
@@ -17,16 +17,16 @@
import { describe, expect, it } from 'vitest';
import { ErrorType } from '../../../../basics/error-type';
import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object';
import { ErrorValueObject } from '../../../../engine/value-object/base-value-object';
import {
BooleanValueObject,
NumberValueObject,
StringValueObject,
} from '../../../../engine/value-object/primitive-object';
import { getObjectValue } from '../../../__tests__/create-function-test-bed';
import { FUNCTION_NAMES_LOOKUP } from '../../function-names';
import { Address } from '../index';
import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object';
import { getObjectValue } from '../../../__tests__/create-function-test-bed';
describe('Test address', () => {
const testFunction = new Address(FUNCTION_NAMES_LOOKUP.ADDRESS);
@@ -65,6 +65,10 @@ describe('Test address', () => {
expect(calculate(2, 3, 1, false, '[Book1]Sheet1')).toBe("'[Book1]Sheet1'!R2C3");
});
it('Absolute reference to sheet name with single quote', async () => {
expect(calculate(1, 1, 1, true, "Sheet'1")).toBe("'Sheet''1'!$A$1");
});
it('Absolute reference to another worksheet', async () => {
expect(calculate(2, 3, 1, false, 'EXCEL SHEET')).toBe("'EXCEL SHEET'!R2C3");
});
@@ -14,16 +14,16 @@
* limitations under the License.
*/
import { AbsoluteRefType, type IRange } from '@univerjs/core';
import type { ArrayValueObject } from '../../../engine/value-object/array-value-object';
import { AbsoluteRefType, type IRange } from '@univerjs/core';
import { ErrorType } from '../../../basics/error-type';
import { expandArrayValueObject } from '../../../engine/utils/array-object';
import { serializeRangeToR1C1 } from '../../../engine/utils/r1c1-reference';
import { needsQuoting, serializeRange } from '../../../engine/utils/reference';
import { addQuotesBothSides, serializeRange } from '../../../engine/utils/reference';
import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object';
import { BooleanValueObject, NumberValueObject, StringValueObject } from '../../../engine/value-object/primitive-object';
import { BaseFunction } from '../../base-function';
import type { ArrayValueObject } from '../../../engine/value-object/array-value-object';
import { expandArrayValueObject } from '../../../engine/utils/array-object';
export class Address extends BaseFunction {
override minParams = 2;
@@ -132,7 +132,7 @@ export class Address extends BaseFunction {
const absType = transformAbsoluteRefType(absNumberValue);
const a1Value = this.getZeroOrOneByOneDefault(a1);
const sheetTextValue = `${sheetText.getValue()}`;
const sheetName = needsQuoting(sheetTextValue) ? `'${sheetTextValue}'` : sheetTextValue;
const sheetName = addQuotesBothSides(sheetTextValue);
const range: IRange = {
startRow: row,
@@ -27,8 +27,6 @@ export interface IFUniverSheetsFormulaMixin {
* @returns {IDisposable} The disposable instance.
*/
registerFunction(config: IRegisterFunctionParams): IDisposable;
// TODO@Dushusir: this API should be implemented on FFormula.
}
export class FUniverSheetsFormulaMixin extends FUniver implements IFUniverSheetsFormulaMixin {
@@ -0,0 +1,120 @@
/**
* Copyright 2023-present DreamNum Inc.
*
* 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 type { Workbook } from '@univerjs/core';
import type { IRenderContext, IRenderModule } from '@univerjs/engine-render';
import { Disposable, Inject, isRealNum, LocaleService } from '@univerjs/core';
import { FormulaDataModel } from '@univerjs/engine-formula';
import { DEFAULT_TEXT_FORMAT } from '@univerjs/engine-numfmt';
import { INumfmtService } from '@univerjs/sheets';
import { CellAlertManagerService, CellAlertType, HoverManagerService } from '@univerjs/sheets-ui';
import { IZenZoneService } from '@univerjs/ui';
import { debounceTime } from 'rxjs';
const ALERT_KEY = 'SHEET_NUMFMT_ALERT';
export class NumfmtAlertRenderController extends Disposable implements IRenderModule {
constructor(
private readonly _context: IRenderContext<Workbook>,
@Inject(HoverManagerService) private readonly _hoverManagerService: HoverManagerService,
@Inject(CellAlertManagerService) private readonly _cellAlertManagerService: CellAlertManagerService,
@Inject(LocaleService) private readonly _localeService: LocaleService,
@Inject(FormulaDataModel) private readonly _formulaDataModel: FormulaDataModel,
@IZenZoneService private readonly _zenZoneService: IZenZoneService,
@Inject(INumfmtService) private _numfmtService: INumfmtService
) {
super();
this._init();
}
private _init() {
this._initCellAlertPopup();
this._initZenService();
}
private _initCellAlertPopup() {
this.disposeWithMe(this._hoverManagerService.currentCell$.pipe(debounceTime(100)).subscribe((cellPos) => {
if (cellPos) {
const location = cellPos.location;
const workbook = this._context.unit;
const worksheet = workbook.getActiveSheet();
if (!worksheet) return;
const unitId = location.unitId;
const sheetId = location.subUnitId;
let numfmtValue;
const cellData = worksheet.getCell(location.row, location.col);
if (cellData?.s) {
const style = workbook.getStyles().get(cellData.s);
if (style?.n) {
numfmtValue = style.n;
}
}
if (!numfmtValue) {
numfmtValue = this._numfmtService.getValue(unitId, sheetId, location.row, location.col);
}
if (!numfmtValue) {
this._hideAlert();
return;
}
// Preventing blank object
if (numfmtValue.pattern === DEFAULT_TEXT_FORMAT && cellData?.v && isRealNum(cellData.v)) {
const currentAlert = this._cellAlertManagerService.currentAlert.get(ALERT_KEY);
const currentLoc = currentAlert?.alert?.location;
if (
currentLoc &&
currentLoc.row === location.row &&
currentLoc.col === location.col &&
currentLoc.subUnitId === location.subUnitId &&
currentLoc.unitId === location.unitId
) {
return;
}
this._cellAlertManagerService.showAlert({
type: CellAlertType.ERROR,
title: this._localeService.t('info.error'),
message: this._localeService.t('info.forceStringInfo'),
location,
width: 200,
height: 74,
key: ALERT_KEY,
});
return;
}
}
this._hideAlert();
}));
}
private _initZenService() {
this.disposeWithMe(this._zenZoneService.visible$.subscribe((visible) => {
if (visible) {
this._hideAlert();
}
}));
}
private _hideAlert() {
this._cellAlertManagerService.removeAlert(ALERT_KEY);
}
}
@@ -169,7 +169,8 @@ export class NumfmtEditorController extends Disposable {
return next(value);
}
if (currentNumfmtValue?.pattern === DEFAULT_TEXT_FORMAT) {
// if the cell is text format or force string, do not convert the value
if (currentNumfmtValue?.pattern === DEFAULT_TEXT_FORMAT || value.t === CellValueType.FORCE_STRING) {
return next(value);
}
+16 -1
View File
@@ -14,12 +14,15 @@
* limitations under the License.
*/
import type { Dependency } from '@univerjs/core';
import type { IUniverSheetsNumfmtUIConfig } from './controllers/config.schema';
import { DependentOn, IConfigService, Inject, Injector, merge, Plugin, registerDependencies, touchDependencies, UniverInstanceType } from '@univerjs/core';
import { IRenderManagerService } from '@univerjs/engine-render';
import { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';
import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
import { UI_PLUGIN_CONFIG_KEY } from '@univerjs/ui';
import { defaultPluginConfig } from './controllers/config.schema';
import { NumfmtAlertRenderController } from './controllers/numfmt-alert-render.controller';
import { SheetNumfmtUIController } from './controllers/numfmt.controller';
import { NumfmtEditorController } from './controllers/numfmt.editor.controller';
import { NumfmtMenuController } from './controllers/numfmt.menu.controller';
@@ -35,7 +38,8 @@ export class UniverSheetsNumfmtUIPlugin extends Plugin {
constructor(
private readonly _config: Partial<IUniverSheetsNumfmtUIConfig> = defaultPluginConfig,
@Inject(Injector) override readonly _injector: Injector,
@IConfigService private readonly _configService: IConfigService
@IConfigService private readonly _configService: IConfigService,
@IRenderManagerService private readonly _renderManagerService: IRenderManagerService
) {
super();
@@ -62,10 +66,21 @@ export class UniverSheetsNumfmtUIPlugin extends Plugin {
}
override onRendered(): void {
this._registerRenderModules();
touchDependencies(this._injector, [
[SheetNumfmtUIController],
[NumfmtEditorController],
[NumfmtMenuController],
]);
}
private _registerRenderModules(): void {
const modules: Dependency[] = [
[NumfmtAlertRenderController],
];
modules.forEach((m) => {
this.disposeWithMe(this._renderManagerService.registerRenderModule(UniverInstanceType.UNIVER_SHEET, m));
});
}
}
+1
View File
@@ -68,6 +68,7 @@
},
"dependencies": {
"@univerjs/core": "workspace:*",
"@univerjs/engine-numfmt": "workspace:*",
"@univerjs/sheets": "workspace:*"
},
"devDependencies": {
@@ -26,6 +26,7 @@ import {
ICommandService,
Inject,
InterceptorEffectEnum,
isRealNum,
IUniverInstanceService,
LocaleService,
ObjectMatrix,
@@ -33,6 +34,7 @@ import {
ThemeService,
UniverInstanceType,
} from '@univerjs/core';
import { DEFAULT_TEXT_FORMAT } from '@univerjs/engine-numfmt';
import { InterceptCellContentPriority, INTERCEPTOR_POINT, INumfmtService, SetNumfmtMutation, SetRangeValuesMutation, SheetInterceptorService } from '@univerjs/sheets';
import { of, skip, switchMap } from 'rxjs';
import { getPatternPreviewIgnoreGeneral } from '../utils/pattern';
@@ -52,6 +54,13 @@ export class SheetsNumfmtCellContentController extends Disposable {
// eslint-disable-next-line max-lines-per-function
private _initInterceptorCellContent() {
const TEXT_FORMAT_MARK = {
tl: {
size: 6,
color: '#409f11',
},
};
const renderCache = new ObjectMatrix<{ result: ICellData; parameters: string | number }>();
this.disposeWithMe(this._sheetInterceptorService.intercept(INTERCEPTOR_POINT.CELL_CONTENT, {
effect: InterceptorEffectEnum.Value | InterceptorEffectEnum.Style,
@@ -64,11 +73,6 @@ export class SheetsNumfmtCellContentController extends Disposable {
return next(cell);
}
// just handle number
if (originCellValue.t !== CellValueType.NUMBER || originCellValue.v == null || Number.isNaN(originCellValue.v)) {
return next(cell);
}
if (cell?.s) {
const style = location.workbook.getStyles().get(cell.s);
if (style?.n) {
@@ -79,10 +83,27 @@ export class SheetsNumfmtCellContentController extends Disposable {
if (!numfmtValue) {
numfmtValue = this._numfmtService.getValue(unitId, sheetId, location.row, location.col);
}
if (!numfmtValue) {
return next(cell);
}
// Add error marker to text format number
if (numfmtValue.pattern === DEFAULT_TEXT_FORMAT && originCellValue.v && isRealNum(originCellValue.v)) {
return next({
...cell,
markers: {
...cell?.markers,
...TEXT_FORMAT_MARK,
},
});
}
// just handle number
if (originCellValue.t !== CellValueType.NUMBER || originCellValue.v == null || Number.isNaN(originCellValue.v)) {
return next(cell);
}
let numfmtRes: string = '';
const cache = renderCache.getValue(location.row, location.col);
if (cache && cache.parameters === `${originCellValue.v}_${numfmtValue.pattern}`) {
@@ -17,6 +17,7 @@
import type { Workbook } from '@univerjs/core';
import type { IRenderContext, IRenderModule } from '@univerjs/engine-render';
import { CellValueType, Disposable, Inject, isRealNum, LocaleService } from '@univerjs/core';
import { IZenZoneService } from '@univerjs/ui';
import { CellAlertManagerService, CellAlertType } from '../services/cell-alert-manager.service';
import { HoverManagerService } from '../services/hover-manager.service';
@@ -27,7 +28,8 @@ export class ForceStringAlertRenderController extends Disposable implements IRen
private readonly _context: IRenderContext<Workbook>,
@Inject(HoverManagerService) private readonly _hoverManagerService: HoverManagerService,
@Inject(CellAlertManagerService) private readonly _cellAlertManagerService: CellAlertManagerService,
@Inject(LocaleService) private readonly _localeService: LocaleService
@Inject(LocaleService) private readonly _localeService: LocaleService,
@IZenZoneService private readonly _zenZoneService: IZenZoneService
) {
super();
this._init();
@@ -35,6 +37,7 @@ export class ForceStringAlertRenderController extends Disposable implements IRen
private _init() {
this._initCellAlertPopup();
this._initZenService();
}
private _initCellAlertPopup() {
@@ -73,7 +76,19 @@ export class ForceStringAlertRenderController extends Disposable implements IRen
}
}
this._cellAlertManagerService.removeAlert(ALERT_KEY);
this._hideAlert();
}));
}
private _initZenService() {
this.disposeWithMe(this._zenZoneService.visible$.subscribe((visible) => {
if (visible) {
this._hideAlert();
}
}));
}
private _hideAlert() {
this._cellAlertManagerService.removeAlert(ALERT_KEY);
}
}
@@ -193,6 +193,10 @@ export class BasicWorksheetController extends Disposable implements IDisposable
SetNumfmtMutation,
ReorderRangeMutation,
EmptyMutation,
SetRowHiddenMutation, // formula SUBTOTAL
SetRowVisibleMutation,
SetColHiddenMutation,
SetColVisibleMutation,
] as IMutation<object>[]).forEach((mutation) => {
this._commandService.registerCommand(mutation);
this._dataSyncPrimaryController?.registerSyncingMutations(mutation);
@@ -240,8 +244,6 @@ export class BasicWorksheetController extends Disposable implements IDisposable
SetBorderPositionCommand,
SetBorderStyleCommand,
SetColHiddenCommand,
SetColHiddenMutation,
SetColVisibleMutation,
SetColWidthCommand,
SetColDataCommand,
SetColDataMutation,
@@ -252,8 +254,6 @@ export class BasicWorksheetController extends Disposable implements IDisposable
SetRangeValuesCommand,
SetRowHeightCommand,
SetRowHiddenCommand,
SetRowHiddenMutation,
SetRowVisibleMutation,
SetRowDataCommand,
SetRowDataMutation,
SetSelectedColsVisibleCommand,
+3
View File
@@ -2686,6 +2686,9 @@ importers:
'@univerjs/core':
specifier: workspace:*
version: link:../core
'@univerjs/engine-numfmt':
specifier: workspace:*
version: link:../engine-numfmt
'@univerjs/sheets':
specifier: workspace:*
version: link:../sheets