From dd79f5f5a18eefdefae4a3f9cf44f1816a9f5ecd Mon Sep 17 00:00:00 2001 From: wpxp123456 <2677556700@qq.com> Date: Mon, 15 Dec 2025 18:15:59 +0800 Subject: [PATCH] fix: fix defined name can't be duplicate with table name (#6312) --- packages/engine-formula/src/plugin.ts | 6 +-- .../commands/add-sheet-table.command.ts | 31 ++++++++++--- .../commands/set-sheet-table.command.ts | 30 +++++-------- packages/sheets-table/src/util.ts | 44 ++++++++++++++++++- .../views/defined-name/DefinedNameInput.tsx | 10 +++-- 5 files changed, 87 insertions(+), 34 deletions(-) diff --git a/packages/engine-formula/src/plugin.ts b/packages/engine-formula/src/plugin.ts index 2a82060462..5140249dba 100644 --- a/packages/engine-formula/src/plugin.ts +++ b/packages/engine-formula/src/plugin.ts @@ -24,7 +24,7 @@ import { FormulaController } from './controller/formula.controller'; import { SetDependencyController } from './controller/set-dependency.controller'; import { SetFeatureCalculationController } from './controller/set-feature-calculation.controller'; import { SetOtherFormulaController } from './controller/set-other-formula.controller'; -import { SetSuperTableController } from './controller/set-super-table.controller'; +// import { SetSuperTableController } from './controller/set-super-table.controller'; import { Lexer } from './engine/analysis/lexer'; import { LexerTreeBuilder } from './engine/analysis/lexer-tree-builder'; import { AstTreeBuilder } from './engine/analysis/parser'; @@ -87,7 +87,7 @@ export class UniverFormulaEnginePlugin extends Plugin { override onReady(): void { touchDependencies(this._injector, [ [FormulaController], - [SetSuperTableController], + // [SetSuperTableController], ]); if (!this._config?.notExecuteFormula) { @@ -125,7 +125,7 @@ export class UniverFormulaEnginePlugin extends Plugin { [FormulaDataModel], //Controllers [FormulaController], - [SetSuperTableController], + // [SetSuperTableController], [ComputingStatusReporterController], ]; diff --git a/packages/sheets-table/src/commands/commands/add-sheet-table.command.ts b/packages/sheets-table/src/commands/commands/add-sheet-table.command.ts index aaa7668867..06ed9c2668 100644 --- a/packages/sheets-table/src/commands/commands/add-sheet-table.command.ts +++ b/packages/sheets-table/src/commands/commands/add-sheet-table.command.ts @@ -16,8 +16,10 @@ import type { ICommand, IMutationInfo, IRange } from '@univerjs/core'; import type { ITableOptions } from '../../types/type'; -import { CommandType, generateRandomId, ICommandService, IUndoRedoService, LocaleService, sequenceExecute } from '@univerjs/core'; +import { CommandType, customNameCharacterCheck, generateRandomId, ICommandService, IUndoRedoService, IUniverInstanceService, LocaleService, sequenceExecute } from '@univerjs/core'; +import { IDefinedNamesService } from '@univerjs/engine-formula'; import { TableManager } from '../../model/table-manager'; +import { getExistingNamesSet } from '../../util'; import { AddSheetTableMutation } from '../mutations/add-sheet-table.mutation'; import { DeleteSheetTableMutation } from '../mutations/delete-sheet-table.mutation'; @@ -37,21 +39,38 @@ export const AddSheetTableCommand: ICommand = { if (!params) { return false; } + const undoRedoService = accessor.get(IUndoRedoService); const commandService = accessor.get(ICommandService); const localeService = accessor.get(LocaleService); + const tableManager = accessor.get(TableManager); const tableId = params.id ?? generateRandomId(); + const existingNamesSet = getExistingNamesSet(params.unitId, { + univerInstanceService: accessor.get(IUniverInstanceService), + tableManager, + definedNamesService: accessor.get(IDefinedNamesService), + }); + let tableName = params.name; - if (!tableName) { - const tableManager = accessor.get(TableManager); - const tableCount = tableManager.getTableList(params.unitId).length; - tableName = `${localeService.t('sheets-table.tablePrefix')}${tableCount + 1}`; + if (!tableName || !customNameCharacterCheck(tableName, existingNamesSet)) { + const prefix = localeService.t('sheets-table.tablePrefix'); + let index = tableManager.getTableList(params.unitId).length + 1; + + for (const name of existingNamesSet) { + if (name.startsWith(prefix)) { + const n = Number(name.slice(prefix.length)); + if (Number.isInteger(n) && n >= index) { + index = n + 1; + } + } + } + + tableName = `${prefix}${index}`; } const redos: IMutationInfo[] = []; const undos: IMutationInfo[] = []; - const tableManager = accessor.get(TableManager); const { unitId, subUnitId, range } = params; const header = tableManager.getColumnHeader(unitId, subUnitId, range, localeService.t('sheets-table.columnPrefix')); diff --git a/packages/sheets-table/src/commands/commands/set-sheet-table.command.ts b/packages/sheets-table/src/commands/commands/set-sheet-table.command.ts index 518a9f4879..6e3621b2d2 100644 --- a/packages/sheets-table/src/commands/commands/set-sheet-table.command.ts +++ b/packages/sheets-table/src/commands/commands/set-sheet-table.command.ts @@ -14,12 +14,14 @@ * limitations under the License. */ -import type { ICommand, Workbook } from '@univerjs/core'; +import type { ICommand } from '@univerjs/core'; import type { ITableSetConfig } from '../../types/type'; import type { ISetSheetTableMutationParams } from '../mutations/set-sheet-table.mutation'; -import { CommandType, customNameCharacterCheck, ICommandService, ILogService, IUndoRedoService, IUniverInstanceService, LocaleService, UniverInstanceType } from '@univerjs/core'; +import { CommandType, customNameCharacterCheck, ICommandService, ILogService, IUndoRedoService, IUniverInstanceService, LocaleService } from '@univerjs/core'; +import { IDefinedNamesService } from '@univerjs/engine-formula'; import { TableManager } from '../../model/table-manager'; import { IRangeOperationTypeEnum } from '../../types/type'; +import { getExistingNamesSet } from '../../util'; import { SetSheetTableMutation } from '../mutations/set-sheet-table.mutation'; export interface ISetSheetTableCommandParams extends ITableSetConfig { @@ -37,7 +39,6 @@ export const SetSheetTableCommand: ICommand = { } const { unitId, tableId, name, updateRange, rowColOperation, theme } = params; - const tableManager = accessor.get(TableManager); const table = tableManager.getTableById(unitId, tableId); @@ -45,26 +46,15 @@ export const SetSheetTableCommand: ICommand = { const oldTableConfig: ITableSetConfig = {}; const newTableConfig: ITableSetConfig = {}; - const localeService = accessor.get(LocaleService); - const univerInstanceService = accessor.get(IUniverInstanceService); - const workbook = univerInstanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_SHEET); - - const sheetNameSet = new Set(); - if (workbook) { - workbook.getSheets().forEach((sheet) => { - sheetNameSet.add(sheet.getName()); - }); - - // Add existing table names to the set to ensure uniqueness - const tableList = tableManager.getTableList(unitId); - tableList.forEach((tableItem) => { - sheetNameSet.add(tableItem.name); - }); - } + const existingNamesSet = getExistingNamesSet(unitId, { + univerInstanceService: accessor.get(IUniverInstanceService), + tableManager, + definedNamesService: accessor.get(IDefinedNamesService), + }); if (name) { - const isValidName = customNameCharacterCheck(name, sheetNameSet); + const isValidName = customNameCharacterCheck(name, existingNamesSet); if (!isValidName) { const logService = accessor.get(ILogService); logService.warn(localeService.t('sheets-table.tableNameError')); diff --git a/packages/sheets-table/src/util.ts b/packages/sheets-table/src/util.ts index 3c95d77e60..10a0ea1a9a 100644 --- a/packages/sheets-table/src/util.ts +++ b/packages/sheets-table/src/util.ts @@ -14,9 +14,11 @@ * limitations under the License. */ -import type { ICellData, IDocumentData, Nullable } from '@univerjs/core'; +import type { ICellData, IDocumentData, IUniverInstanceService, Nullable, Workbook } from '@univerjs/core'; +import type { IDefinedNamesService } from '@univerjs/engine-formula'; +import type { TableManager } from './model/table-manager'; import type { ITableConditionFilterItem, ITableFilterItem, ITableManualFilterItem } from './types/type'; -import { CellValueType } from '@univerjs/core'; +import { CellValueType, UniverInstanceType } from '@univerjs/core'; import { SheetsTableButtonStateEnum, SheetsTableSortStateEnum, TableColumnFilterTypeEnum } from './types/enum'; export function getColumnName(columnIndex: number, columnText: string): string { @@ -97,3 +99,41 @@ export function isManualFilter(filter: ITableFilterItem | undefined): filter is } return filter.filterType === TableColumnFilterTypeEnum.manual; } + +/** + * Get existing names including sheet names, table names and defined names to check for duplicates table name. + */ +export function getExistingNamesSet(unitId: string, options: { + univerInstanceService?: IUniverInstanceService; + tableManager?: TableManager; + definedNamesService?: IDefinedNamesService; +}): Set { + const { univerInstanceService, tableManager, definedNamesService } = options; + const existingNamesSet = new Set(); + + // The table names can't be duplicate with existing sheet names. + const workbook = univerInstanceService?.getUnit(unitId, UniverInstanceType.UNIVER_SHEET); + if (workbook) { + workbook.getSheets().forEach((sheet) => { + existingNamesSet.add(sheet.getName()); + }); + } + + // The table names can't be duplicate with existing table names. + const tableList = tableManager?.getTableList(unitId); + if (tableList && tableList.length > 0) { + tableList.forEach((tableItem) => { + existingNamesSet.add(tableItem.name); + }); + } + + // The table names can't be duplicate with existing defined names. + const definedNames = definedNamesService?.getDefinedNameMap(unitId); + if (definedNames) { + Object.values(definedNames).forEach((definedName) => { + existingNamesSet.add(definedName.name); + }); + } + + return existingNamesSet; +} diff --git a/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx b/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx index 0ec7640df5..96a9f8b634 100644 --- a/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx +++ b/packages/sheets-ui/src/views/defined-name/DefinedNameInput.tsx @@ -20,7 +20,7 @@ import type { ComponentType } from 'react'; import type { IRangeSelectorProps } from '../../basics/editor/range'; import { AbsoluteRefType, IUniverInstanceService, LocaleService, Tools, UniverInstanceType } from '@univerjs/core'; import { borderBottomClassName, borderClassName, Button, clsx, Input, Radio, RadioGroup, Select } from '@univerjs/design'; -import { IDefinedNamesService, IFunctionService, isReferenceStrings, isReferenceStringWithEffectiveColumn, LexerTreeBuilder, operatorToken } from '@univerjs/engine-formula'; +import { IDefinedNamesService, IFunctionService, isReferenceStrings, isReferenceStringWithEffectiveColumn, ISuperTableService, LexerTreeBuilder, operatorToken } from '@univerjs/engine-formula'; import { hasCJKText } from '@univerjs/engine-render'; import { ErrorIcon } from '@univerjs/icons'; import { SCOPE_WORKBOOK_VALUE_DEFINED_NAME } from '@univerjs/sheets'; @@ -50,12 +50,12 @@ export const DefinedNameInput = (props: IDefinedNameInputProps) => { localSheetId = SCOPE_WORKBOOK_VALUE_DEFINED_NAME, hidden = false, // 是否对用户隐藏,与excel兼容,暂时用不上。 id, - } = props; const univerInstanceService = useDependency(IUniverInstanceService); const workbook = univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET)!; const localeService = useDependency(LocaleService); const definedNamesService = useDependency(IDefinedNamesService); + const superTableService = useDependency(ISuperTableService); const functionService = useDependency(IFunctionService); const lexerTreeBuilder = useDependency(LexerTreeBuilder); const componentManager = useDependency(ComponentManager); @@ -135,7 +135,11 @@ export const DefinedNameInput = (props: IDefinedNameInputProps) => { return; } - if (definedNamesService.getValueByName(unitId, nameValue) != null && (id == null || id.length === 0)) { + // The defined name can't be duplicate with existing defined names and table names. + if ( + (definedNamesService.getValueByName(unitId, nameValue) || superTableService.getTableMap(unitId)?.has(nameValue)) && + (id === null || id === undefined || id.length === 0) + ) { setValidString(localeService.t('definedName.nameDuplicate')); return; }