From ace8f93ba930bbc06c1c6580adc4534863b2d278 Mon Sep 17 00:00:00 2001 From: zhangw Date: Tue, 26 Nov 2024 16:52:08 +0800 Subject: [PATCH] refactor(data-validation): data validation validator (#4141) --- packages/core/src/index.ts | 2 +- packages/core/src/shared/r-tree.ts | 2 + .../src/types/interfaces/i-data-validation.ts | 12 +-- .../data-validator-registry.service.ts | 2 +- .../src/validators/base-data-validator.ts | 99 +++++++++++++------ .../controllers/dv-auto-fill.controller.ts | 5 +- packages/sheets-data-validation/package.json | 1 - .../commands/data-validation.command.ts | 5 +- .../dv-formula-ref-range.controller.ts | 9 +- .../controllers/dv-ref-range.controller.ts | 11 +-- .../src/facade/f-data-validation-builder.ts | 4 +- .../src/facade/f-data-validation.ts | 2 +- .../src/models/rule-matrix.ts | 96 +++++++----------- .../src/models/sheet-data-validation-model.ts | 2 +- .../src/services/dv-cache.service.ts | 35 ++++--- .../src/services/dv-custom-formula.service.ts | 9 +- .../src/services/dv-formula.service.ts | 9 +- .../src/utils/formula.ts | 16 +-- .../src/validators/any-validator.ts | 2 + .../src/validators/checkbox-validator.ts | 2 + .../src/validators/date-validator.ts | 74 +------------- .../src/validators/decimal-validator.ts | 75 +------------- .../src/validators/list-multiple-validator.ts | 1 + .../src/validators/list-validator.ts | 15 +-- .../src/validators/text-length-validator.ts | 96 +----------------- .../src/validators/whole-validator.ts | 82 +-------------- .../sheets-hyper-link-ui/src/utils/index.ts | 14 +-- pnpm-lock.yaml | 3 - 28 files changed, 205 insertions(+), 480 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 8a413e2e6b..0d387de11e 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -190,7 +190,7 @@ export * from './types/interfaces'; export * from './types/interfaces'; export type { ICellCustomRender, ICellRenderContext } from './types/interfaces/i-cell-custom-render'; export type { IDataValidationRule, IDataValidationRuleBase, IDataValidationRuleInfo, IDataValidationRuleOptions, ISheetDataValidationRule } from './types/interfaces/i-data-validation'; -export { type IRTreeItem, RTree } from './shared/r-tree'; +export { type BBox, type IRTreeItem, RBush, RTree } from './shared/r-tree'; export { type IUniverConfig, Univer } from './univer'; export { isNodeEnv } from './shared/tools'; diff --git a/packages/core/src/shared/r-tree.ts b/packages/core/src/shared/r-tree.ts index d936c72c26..6c0f6cb482 100644 --- a/packages/core/src/shared/r-tree.ts +++ b/packages/core/src/shared/r-tree.ts @@ -361,3 +361,5 @@ export class RTree { } } } + +export { type BBox, RBush }; diff --git a/packages/core/src/types/interfaces/i-data-validation.ts b/packages/core/src/types/interfaces/i-data-validation.ts index 608f373371..3030154856 100644 --- a/packages/core/src/types/interfaces/i-data-validation.ts +++ b/packages/core/src/types/interfaces/i-data-validation.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import type { DataValidationOperator } from '../enum/data-validation-operator'; -import type { DataValidationType } from '../enum/data-validation-type'; -import type { DataValidationImeMode } from '../enum/data-validation-ime-mode'; -import type { DataValidationErrorStyle } from '../enum/data-validation-error-style'; -import type { DataValidationRenderMode } from '../enum/data-validation-render-mode'; import type { IRange } from '../../sheets/typedef'; +import type { DataValidationErrorStyle } from '../enum/data-validation-error-style'; +import type { DataValidationImeMode } from '../enum/data-validation-ime-mode'; +import type { DataValidationOperator } from '../enum/data-validation-operator'; +import type { DataValidationRenderMode } from '../enum/data-validation-render-mode'; +import type { DataValidationType } from '../enum/data-validation-type'; // TODO@weird94: should be moved outside of the or package @@ -27,7 +27,7 @@ export interface IDataValidationRuleBase { /** * data validation type */ - type: DataValidationType; + type: DataValidationType | string; allowBlank?: boolean; /** * data validation creteria diff --git a/packages/data-validation/src/services/data-validator-registry.service.ts b/packages/data-validation/src/services/data-validator-registry.service.ts index 32f19ff8b5..3e20707b97 100644 --- a/packages/data-validation/src/services/data-validator-registry.service.ts +++ b/packages/data-validation/src/services/data-validator-registry.service.ts @@ -57,7 +57,7 @@ export class DataValidatorRegistryService { } } - register(validator: BaseDataValidator) { + register(validator: BaseDataValidator) { this._validatorMap.set(validator.id, validator); if (Array.isArray(validator.scopes)) { diff --git a/packages/data-validation/src/validators/base-data-validator.ts b/packages/data-validation/src/validators/base-data-validator.ts index 39b47b757d..2befa46994 100644 --- a/packages/data-validation/src/validators/base-data-validator.ts +++ b/packages/data-validation/src/validators/base-data-validator.ts @@ -59,12 +59,14 @@ export interface IFormulaValidResult { formula2?: string; } -export abstract class BaseDataValidator { +export abstract class BaseDataValidator { abstract id: string; abstract title: string; abstract operators: DataValidationOperator[]; abstract scopes: string[] | string; + offsetFormulaByRange = true; + // #region UI related formulaInput: string | undefined = undefined; @@ -127,7 +129,7 @@ export abstract class BaseDataValidator { return false; } - abstract parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string, row: number, column: number): Promise; + abstract parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string, row: number, column: number): Promise>; abstract validatorFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): IFormulaValidResult; @@ -142,41 +144,82 @@ export abstract class BaseDataValidator { return true; }; - transform(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): IValidatorCellInfo { - return cellInfo as IValidatorCellInfo; + transform(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): IValidatorCellInfo { + return cellInfo as IValidatorCellInfo; }; - async validatorIsEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + async validatorIsEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { + const { formula1 } = formula; + const { value: cellValue } = cellInfo; + if (Number.isNaN(formula1)) { + return true; + } - async validatorIsNotEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + return cellValue === formula1; + } - async validatorIsBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + async validatorIsNotEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1 } = formula; + if (Number.isNaN(formula1)) { + return true; + } - async validatorIsNotBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + return cellInfo.value !== formula1; + } - async validatorIsGreaterThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + async validatorIsBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1, formula2 } = formula; + if (Number.isNaN(formula1) || Number.isNaN(formula2)) { + return true; + } - async validatorIsGreaterThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + const start = Math.min(formula1, formula2); + const end = Math.max(formula1, formula2); + return cellInfo.value >= start && cellInfo.value <= end; + } - async validatorIsLessThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + async validatorIsNotBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1, formula2 } = formula; + if (Number.isNaN(formula1) || Number.isNaN(formula2)) { + return true; + } + const start = Math.min(formula1, formula2); + const end = Math.max(formula1, formula2); + return cellInfo.value < start || cellInfo.value > end; + } - async validatorIsLessThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - return true; - }; + async validatorIsGreaterThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1 } = formula; + if (Number.isNaN(formula1)) { + return true; + } + return cellInfo.value > formula1; + } + + async validatorIsGreaterThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1 } = formula; + if (Number.isNaN(formula1)) { + return true; + } + return cellInfo.value >= formula1; + } + + async validatorIsLessThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1 } = formula; + if (Number.isNaN(formula1)) { + return true; + } + return cellInfo.value < formula1; + } + + async validatorIsLessThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { + const { formula1 } = formula; + if (Number.isNaN(formula1)) { + return true; + } + + return cellInfo.value <= formula1; + } async validator(cellInfo: IValidatorCellInfo, rule: IDataValidationRule): Promise { const { value: cellValue, unitId, subUnitId } = cellInfo; diff --git a/packages/sheets-data-validation-ui/src/controllers/dv-auto-fill.controller.ts b/packages/sheets-data-validation-ui/src/controllers/dv-auto-fill.controller.ts index 65bef57f0d..0daae1e4b0 100644 --- a/packages/sheets-data-validation-ui/src/controllers/dv-auto-fill.controller.ts +++ b/packages/sheets-data-validation-ui/src/controllers/dv-auto-fill.controller.ts @@ -101,9 +101,6 @@ export class DataValidationAutoFillController extends Disposable { redos: redoMutations, }; }; - const disabledDataVallation = [ - DataValidationType.CHECKBOX, - ]; const hook: ISheetAutoFillHook = { id: DATA_VALIDATION_PLUGIN_NAME, onBeforeFillData: (location) => { @@ -111,7 +108,7 @@ export class DataValidationAutoFillController extends Disposable { for (const row of sourceRange.rows) { for (const col of sourceRange.cols) { const dv = this._sheetDataValidationModel.getRuleByLocation(unitId, subUnitId, row, col); - if (dv && disabledDataVallation.indexOf(dv.type) > -1) { + if (dv && dv.type === DataValidationType.CHECKBOX) { this._autoFillService.setDisableApplyType(APPLY_TYPE.SERIES, true); return; } diff --git a/packages/sheets-data-validation/package.json b/packages/sheets-data-validation/package.json index a70e5ef210..4f3ac0a239 100644 --- a/packages/sheets-data-validation/package.json +++ b/packages/sheets-data-validation/package.json @@ -68,7 +68,6 @@ "rxjs": ">=7.0.0" }, "dependencies": { - "@flatten-js/interval-tree": "^1.1.3", "@univerjs/core": "workspace:*", "@univerjs/data-validation": "workspace:*", "@univerjs/engine-formula": "workspace:*", diff --git a/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts b/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts index 4f4c6d6c6a..4ff763e4c3 100644 --- a/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts +++ b/packages/sheets-data-validation/src/commands/commands/data-validation.command.ts @@ -23,7 +23,7 @@ import { AddDataValidationMutation, DataValidatorRegistryService, getRuleOptions import { LexerTreeBuilder } from '@univerjs/engine-formula'; import { getSheetCommandTarget, SetRangeValuesMutation, SetRangeValuesUndoMutationFactory } from '@univerjs/sheets'; import { SheetDataValidationModel } from '../../models/sheet-data-validation-model'; -import { isCustomFormulaType } from '../../utils/formula'; +import { shouldOffsetFormulaByRange } from '../../utils/formula'; import { getStringCellValue } from '../../utils/get-cell-data-origin'; import { CHECKBOX_FORMULA_1, CHECKBOX_FORMULA_2, type CheckboxValidator } from '../../validators'; @@ -57,6 +57,7 @@ export function getDataValidationDiffMutations( fillDefaultValue = true ) { const lexerTreeBuilder = accessor.get(LexerTreeBuilder); + const validatorRegistryService = accessor.get(DataValidatorRegistryService); const redoMutations: IMutationInfo[] = []; const undoMutations: IMutationInfo[] = []; const sheetDataValidationModel = accessor.get(SheetDataValidationModel); @@ -115,7 +116,7 @@ export function getDataValidationDiffMutations( }); break; case 'update': { - if (isCustomFormulaType(diff.rule.type)) { + if (shouldOffsetFormulaByRange(diff.rule.type, validatorRegistryService)) { const originRow = diff.oldRanges[0].startRow; const originColumn = diff.oldRanges[0].startColumn; const newRow = diff.newRanges[0].startRow; diff --git a/packages/sheets-data-validation/src/controllers/dv-formula-ref-range.controller.ts b/packages/sheets-data-validation/src/controllers/dv-formula-ref-range.controller.ts index f8edf5552d..da8e967d79 100644 --- a/packages/sheets-data-validation/src/controllers/dv-formula-ref-range.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv-formula-ref-range.controller.ts @@ -17,17 +17,18 @@ import type { IDisposable, IMutationInfo, ISheetDataValidationRule } from '@univerjs/core'; import type { IUpdateDataValidationMutationParams } from '@univerjs/data-validation'; import { Disposable, generateRandomId, Inject, toDisposable } from '@univerjs/core'; -import { AddDataValidationMutation, RemoveDataValidationMutation, UpdateDataValidationMutation, UpdateRuleType } from '@univerjs/data-validation'; +import { AddDataValidationMutation, DataValidatorRegistryService, RemoveDataValidationMutation, UpdateDataValidationMutation, UpdateRuleType } from '@univerjs/data-validation'; import { FormulaRefRangeService } from '@univerjs/sheets-formula'; import { SheetDataValidationModel } from '../models/sheet-data-validation-model'; -import { isCustomFormulaType } from '../utils/formula'; +import { shouldOffsetFormulaByRange } from '../utils/formula'; export class DataValidationFormulaRefRangeController extends Disposable { private _disposableMap: Map = new Map(); constructor( @Inject(SheetDataValidationModel) private _dataValidationModel: SheetDataValidationModel, - @Inject(FormulaRefRangeService) private _formulaRefRangeService: FormulaRefRangeService + @Inject(FormulaRefRangeService) private _formulaRefRangeService: FormulaRefRangeService, + @Inject(DataValidatorRegistryService) private _validatorRegistryService: DataValidatorRegistryService ) { super(); this._initRefRange(); @@ -38,7 +39,7 @@ export class DataValidationFormulaRefRangeController extends Disposable { } registerRule = (unitId: string, subUnitId: string, rule: ISheetDataValidationRule) => { - if (!isCustomFormulaType(rule.type)) { + if (!shouldOffsetFormulaByRange(rule.type, this._validatorRegistryService)) { return; } diff --git a/packages/sheets-data-validation/src/controllers/dv-ref-range.controller.ts b/packages/sheets-data-validation/src/controllers/dv-ref-range.controller.ts index 28c5caa90b..ea81e89510 100644 --- a/packages/sheets-data-validation/src/controllers/dv-ref-range.controller.ts +++ b/packages/sheets-data-validation/src/controllers/dv-ref-range.controller.ts @@ -18,14 +18,13 @@ import type { ISheetDataValidationRule } from '@univerjs/core'; import type { IRemoveDataValidationMutationParams, IUpdateDataValidationMutationParams } from '@univerjs/data-validation'; import type { EffectRefRangeParams } from '@univerjs/sheets'; import { Disposable, Inject, Injector, isRangesEqual, toDisposable } from '@univerjs/core'; -import { RemoveDataValidationMutation, UpdateDataValidationMutation, UpdateRuleType } from '@univerjs/data-validation'; +import { DataValidatorRegistryService, RemoveDataValidationMutation, UpdateDataValidationMutation, UpdateRuleType } from '@univerjs/data-validation'; import { handleCommonDefaultRangeChangeWithEffectRefCommands, RefRangeService } from '@univerjs/sheets'; import { FormulaRefRangeService } from '@univerjs/sheets-formula'; import { removeDataValidationUndoFactory } from '../commands/commands/data-validation.command'; import { SheetDataValidationModel } from '../models/sheet-data-validation-model'; -import { DataValidationCustomFormulaService } from '../services/dv-custom-formula.service'; import { DataValidationFormulaService } from '../services/dv-formula.service'; -import { isCustomFormulaType } from '../utils/formula'; +import { shouldOffsetFormulaByRange } from '../utils/formula'; export class DataValidationRefRangeController extends Disposable { private _disposableMap: Map void>> = new Map(); @@ -34,9 +33,9 @@ export class DataValidationRefRangeController extends Disposable { @Inject(SheetDataValidationModel) private _dataValidationModel: SheetDataValidationModel, @Inject(Injector) private _injector: Injector, @Inject(RefRangeService) private _refRangeService: RefRangeService, - @Inject(DataValidationCustomFormulaService) private _dataValidationCustomFormulaService: DataValidationCustomFormulaService, @Inject(DataValidationFormulaService) private _dataValidationFormulaService: DataValidationFormulaService, - @Inject(FormulaRefRangeService) private _formulaRefRangeService: FormulaRefRangeService + @Inject(FormulaRefRangeService) private _formulaRefRangeService: FormulaRefRangeService, + @Inject(DataValidatorRegistryService) private _validatorRegistryService: DataValidatorRegistryService ) { super(); this._initRefRange(); @@ -47,7 +46,7 @@ export class DataValidationRefRangeController extends Disposable { } registerRule = (unitId: string, subUnitId: string, rule: ISheetDataValidationRule) => { - if (isCustomFormulaType(rule.type)) { + if (shouldOffsetFormulaByRange(rule.type, this._validatorRegistryService)) { return; } this.register(unitId, subUnitId, rule); diff --git a/packages/sheets-data-validation/src/facade/f-data-validation-builder.ts b/packages/sheets-data-validation/src/facade/f-data-validation-builder.ts index aca9164279..4fb4d79e25 100644 --- a/packages/sheets-data-validation/src/facade/f-data-validation-builder.ts +++ b/packages/sheets-data-validation/src/facade/f-data-validation-builder.ts @@ -73,7 +73,7 @@ export class FDataValidationBuilder { * * @returns {DataValidationType} The data validation type */ - getCriteriaType(): DataValidationType { + getCriteriaType(): DataValidationType | string { return this._rule.type; } @@ -438,7 +438,7 @@ export class FDataValidationBuilder { * operator is a DataValidationOperator enum value, formula1 is the first formula, and formula2 is the second formula. * @return The current instance of the FDataValidationBuilder class, allowing for method chaining. */ - withCriteriaValues(type: DataValidationType, values: [DataValidationOperator, string, string]): this { + withCriteriaValues(type: DataValidationType | string, values: [DataValidationOperator, string, string]): this { this._rule.type = type; this._rule.operator = values[0]; this._rule.formula1 = values[1]; diff --git a/packages/sheets-data-validation/src/facade/f-data-validation.ts b/packages/sheets-data-validation/src/facade/f-data-validation.ts index c60747a234..9aa84cee95 100644 --- a/packages/sheets-data-validation/src/facade/f-data-validation.ts +++ b/packages/sheets-data-validation/src/facade/f-data-validation.ts @@ -46,7 +46,7 @@ export class FDataValidation { * * @returns The data validation type */ - getCriteriaType(): DataValidationType { + getCriteriaType(): DataValidationType | string { return this.rule.type; }; diff --git a/packages/sheets-data-validation/src/models/rule-matrix.ts b/packages/sheets-data-validation/src/models/rule-matrix.ts index 1085af945e..008f34f686 100644 --- a/packages/sheets-data-validation/src/models/rule-matrix.ts +++ b/packages/sheets-data-validation/src/models/rule-matrix.ts @@ -14,14 +14,13 @@ * limitations under the License. */ -import type { IRange, ISheetDataValidationRule, IUniverInstanceService, Workbook } from '@univerjs/core'; -import IntervalTree from '@flatten-js/interval-tree'; -import { debounce, Range, Rectangle, Tools, UniverInstanceType } from '@univerjs/core'; +import type { BBox, IRange, ISheetDataValidationRule, IUniverInstanceService, Workbook } from '@univerjs/core'; -interface IRuleItem { +import { debounce, Range, RBush, Rectangle, Tools, UniverInstanceType } from '@univerjs/core'; + +interface IRuleItem extends BBox { ruleId: string; - startRow: number; - endRow: number; + } export type RangeMutation = { @@ -41,7 +40,7 @@ export type RangeMutation = { export class RuleMatrix { private _map: Map; - private _tree = new Map>(); + private _tree = new RBush(); private _dirty = true; constructor( @@ -59,33 +58,20 @@ export class RuleMatrix { if (!this._dirty || this._disableTree) { return; } - const map = new Map(); + this._tree.clear(); + const items: IRuleItem[] = []; this._map.forEach((ranges, ruleId) => { ranges.forEach((range) => { - for (let col = range.startColumn; col <= range.endColumn; col++) { - let items = map.get(col); - if (!items) { - items = []; - map.set(col, items); - } - items.push({ - startRow: range.startRow, - endRow: range.endRow, - ruleId, - }); - } + items.push({ + minX: range.startRow, + maxX: range.endRow, + minY: range.startColumn, + maxY: range.endColumn, + ruleId, + }); }); }); - const treeMap = new Map>(); - map.forEach((items, col) => { - const tree = new IntervalTree(); - items.forEach((item) => { - tree.insert([item.startRow, item.endRow], item.ruleId); - }); - - treeMap.set(col, tree); - }); - this._tree = treeMap; + this._tree.load(items); this._dirty = false; }; @@ -95,13 +81,12 @@ export class RuleMatrix { return this._univerInstanceService.getUnit(this._unitId, UniverInstanceType.UNIVER_SHEET)?.getSheetBySheetId(this._subUnitId); } - addRule(rule: ISheetDataValidationRule) { + private _addRule(ruleId: string, _ranges: IRange[]) { if (!this._worksheet) { return; } - const ruleId = rule.uid; - const ranges = rule.ranges.map((range) => Range.transformRange(range, this._worksheet!)); + const ranges = _ranges.map((range) => Range.transformRange(range, this._worksheet!)); this._map.forEach((value, key) => { const newRanges = Rectangle.subtractMulti(value, ranges); @@ -117,6 +102,10 @@ export class RuleMatrix { this._debonceBuildTree(); } + addRule(rule: ISheetDataValidationRule) { + this._addRule(rule.uid, rule.ranges); + } + removeRange(_ranges: IRange[]) { if (!this._worksheet) { return; @@ -134,30 +123,19 @@ export class RuleMatrix { this._debonceBuildTree(); } - removeRule(rule: ISheetDataValidationRule) { - this._map.delete(rule.uid); + private _removeRule(ruleId: string) { + this._map.delete(ruleId); this._dirty = true; this._debonceBuildTree(); } - updateRange(ruleId: string, _newRanges: IRange[]) { - if (!this._worksheet) { - return; - } - this._map.delete(ruleId); - const ranges = _newRanges.map((range) => Range.transformRange(range, this._worksheet!)); + removeRule(rule: ISheetDataValidationRule) { + this._removeRule(rule.uid); + } - this._map.forEach((value, key) => { - const newRanges = Rectangle.subtractMulti(value, ranges); - if (newRanges.length === 0) { - this._map.delete(key); - } else { - this._map.set(key, newRanges); - } - }); - this._map.set(ruleId, ranges); - this._dirty = true; - this._debonceBuildTree(); + updateRange(ruleId: string, _newRanges: IRange[]) { + this._removeRule(ruleId); + this._addRule(ruleId, _newRanges); } addRangeRules(rules: { id: string;ranges: IRange[] }[]) { @@ -277,11 +255,13 @@ export class RuleMatrix { if (this._dirty) { this._buildTree(); } - const tree = this._tree.get(col); - if (!tree) { - return undefined; - } - const result = tree.search([row, row]); - return result.length > 0 ? result[0] : undefined; + + const result = this._tree.search({ + minX: row, + maxX: row, + minY: col, + maxY: col, + }); + return result.length > 0 ? result[0].ruleId : undefined; } } diff --git a/packages/sheets-data-validation/src/models/sheet-data-validation-model.ts b/packages/sheets-data-validation/src/models/sheet-data-validation-model.ts index 59ec897daa..c817bfc66d 100644 --- a/packages/sheets-data-validation/src/models/sheet-data-validation-model.ts +++ b/packages/sheets-data-validation/src/models/sheet-data-validation-model.ts @@ -182,7 +182,7 @@ export class SheetDataValidationModel extends Disposable { this._dataValidationCustomFormulaService.deleteByRuleId(unitId, subUnitId, oldRule.uid); } - getValidator(type: DataValidationType) { + getValidator(type: DataValidationType | string) { return this._dataValidatorRegistryService.getValidatorItem(type); } diff --git a/packages/sheets-data-validation/src/services/dv-cache.service.ts b/packages/sheets-data-validation/src/services/dv-cache.service.ts index 3e1164c662..aae288918f 100644 --- a/packages/sheets-data-validation/src/services/dv-cache.service.ts +++ b/packages/sheets-data-validation/src/services/dv-cache.service.ts @@ -15,8 +15,9 @@ */ import type { DataValidationStatus, IRange, ISheetDataValidationRule, Nullable } from '@univerjs/core'; -import { Disposable, ICommandService, Inject, ObjectMatrix, Range } from '@univerjs/core'; -import { type ISetRangeValuesMutationParams, SetRangeValuesMutation } from '@univerjs/sheets'; +import type { IRemoveSheetMutationParams, ISetRangeValuesMutationParams } from '@univerjs/sheets'; +import { Disposable, ICommandService, Inject, IUniverInstanceService, ObjectMatrix, Range, UniverInstanceType } from '@univerjs/core'; +import { RemoveSheetMutation, SetRangeValuesMutation } from '@univerjs/sheets'; import { Subject } from 'rxjs'; export class DataValidationCacheService extends Disposable { @@ -26,10 +27,12 @@ export class DataValidationCacheService extends Disposable { readonly dirtyRanges$ = this._dirtyRanges$.asObservable(); constructor( - @Inject(ICommandService) private readonly _commandService: ICommandService + @Inject(ICommandService) private readonly _commandService: ICommandService, + @Inject(IUniverInstanceService) private readonly _univerInstanceService: IUniverInstanceService ) { super(); this._initDirtyRanges(); + this._initSheetRemove(); } private _initDirtyRanges() { @@ -45,6 +48,21 @@ export class DataValidationCacheService extends Disposable { })); } + private _initSheetRemove() { + this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => { + if (commandInfo.id === RemoveSheetMutation.id) { + const { unitId, subUnitId } = commandInfo.params as IRemoveSheetMutationParams; + this._cacheMatrix.get(unitId)?.delete(subUnitId); + } + })); + + this.disposeWithMe(this._univerInstanceService.unitDisposed$.subscribe((univerInstance) => { + if (univerInstance.type === UniverInstanceType.UNIVER_SHEET) { + this._cacheMatrix.delete(univerInstance.getUnitId()); + } + })); + } + private _ensureCache(unitId: string, subUnitId: string) { let unitMap = this._cacheMatrix.get(unitId); @@ -86,12 +104,6 @@ export class DataValidationCacheService extends Disposable { this._dirtyRanges$.next({ unitId, subUnitId, ranges }); } - markCellDirty(unitId: string, subUnitId: string, row: number, col: number) { - const cache = this._ensureCache(unitId, subUnitId); - cache.setValue(row, col, undefined); - this._dirtyRanges$.next({ unitId, subUnitId, ranges: [{ startRow: row, startColumn: col, endRow: row, endColumn: col }] }); - } - private _deleteRange(unitId: string, subUnitId: string, ranges: IRange[]) { const cache = this._ensureCache(unitId, subUnitId); ranges.forEach((range) => { @@ -106,9 +118,4 @@ export class DataValidationCacheService extends Disposable { const cache = this._ensureCache(unitId, subUnitId); return cache.getValue(row, col); } - - setValue(unitId: string, subUnitId: string, row: number, col: number, value: DataValidationStatus) { - const cache = this._ensureCache(unitId, subUnitId); - return cache.setValue(row, col, value); - } } diff --git a/packages/sheets-data-validation/src/services/dv-custom-formula.service.ts b/packages/sheets-data-validation/src/services/dv-custom-formula.service.ts index 5ed5187ed2..ff972a95c2 100644 --- a/packages/sheets-data-validation/src/services/dv-custom-formula.service.ts +++ b/packages/sheets-data-validation/src/services/dv-custom-formula.service.ts @@ -16,9 +16,9 @@ import type { IRange, ISheetDataValidationRule } from '@univerjs/core'; import { Disposable, Inject, isFormulaString, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; -import { DataValidationModel } from '@univerjs/data-validation'; +import { DataValidationModel, DataValidatorRegistryService } from '@univerjs/data-validation'; import { RegisterOtherFormulaService } from '@univerjs/sheets-formula'; -import { getFormulaCellData, isCustomFormulaType } from '../utils/formula'; +import { getFormulaCellData, shouldOffsetFormulaByRange } from '../utils/formula'; import { DataValidationCacheService } from './dv-cache.service'; interface IFormulaData { @@ -43,7 +43,8 @@ export class DataValidationCustomFormulaService extends Disposable { @IUniverInstanceService private readonly _instanceSrv: IUniverInstanceService, @Inject(RegisterOtherFormulaService) private _registerOtherFormulaService: RegisterOtherFormulaService, @Inject(DataValidationModel) private readonly _dataValidationModel: DataValidationModel, - @Inject(DataValidationCacheService) private readonly _dataValidationCacheService: DataValidationCacheService + @Inject(DataValidationCacheService) private readonly _dataValidationCacheService: DataValidationCacheService, + @Inject(DataValidatorRegistryService) private readonly _validatorRegistryService: DataValidatorRegistryService ) { super(); @@ -156,7 +157,7 @@ export class DataValidationCustomFormulaService extends Disposable { } addRule(unitId: string, subUnitId: string, rule: ISheetDataValidationRule) { - if (isCustomFormulaType(rule.type)) { + if (shouldOffsetFormulaByRange(rule.type, this._validatorRegistryService)) { const { ranges, formula1, formula2, uid: ruleId } = rule; this._addFormulaByRange(unitId, subUnitId, ruleId, formula1, formula2, ranges); } diff --git a/packages/sheets-data-validation/src/services/dv-formula.service.ts b/packages/sheets-data-validation/src/services/dv-formula.service.ts index a90d7a370d..d6f8dd48dc 100644 --- a/packages/sheets-data-validation/src/services/dv-formula.service.ts +++ b/packages/sheets-data-validation/src/services/dv-formula.service.ts @@ -17,9 +17,9 @@ import type { ISheetDataValidationRule, Nullable } from '@univerjs/core'; import type { IFormulaInfo, IOtherFormulaResult } from '@univerjs/sheets-formula'; import { DataValidationType, Disposable, Inject, isFormulaString, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; -import { DataValidationModel } from '@univerjs/data-validation'; +import { DataValidationModel, DataValidatorRegistryService } from '@univerjs/data-validation'; import { RegisterOtherFormulaService } from '@univerjs/sheets-formula'; -import { isCustomFormulaType } from '../utils/formula'; +import { shouldOffsetFormulaByRange } from '../utils/formula'; import { DataValidationCacheService } from './dv-cache.service'; type RuleId = string; @@ -33,7 +33,8 @@ export class DataValidationFormulaService extends Disposable { @IUniverInstanceService private readonly _instanceService: IUniverInstanceService, @Inject(RegisterOtherFormulaService) private _registerOtherFormulaService: RegisterOtherFormulaService, @Inject(DataValidationCacheService) private readonly _dataValidationCacheService: DataValidationCacheService, - @Inject(DataValidationModel) private readonly _dataValidationModel: DataValidationModel + @Inject(DataValidationModel) private readonly _dataValidationModel: DataValidationModel, + @Inject(DataValidatorRegistryService) private readonly _validatorRegistryService: DataValidatorRegistryService ) { super(); this._initFormulaResultHandler(); @@ -87,7 +88,7 @@ export class DataValidationFormulaService extends Disposable { } addRule(unitId: string, subUnitId: string, rule: ISheetDataValidationRule) { - if (!isCustomFormulaType(rule.type) && rule.type !== DataValidationType.CHECKBOX) { + if (!shouldOffsetFormulaByRange(rule.type, this._validatorRegistryService) && rule.type !== DataValidationType.CHECKBOX) { const { formula1, formula2, uid: ruleId } = rule; const isFormula1Legal = isFormulaString(formula1); const isFormula2Legal = isFormulaString(formula2); diff --git a/packages/sheets-data-validation/src/utils/formula.ts b/packages/sheets-data-validation/src/utils/formula.ts index ffd87963b4..131f1b9b11 100644 --- a/packages/sheets-data-validation/src/utils/formula.ts +++ b/packages/sheets-data-validation/src/utils/formula.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { DataValidationType, type ICellData, type Nullable } from '@univerjs/core'; +import type { DataValidationType, ICellData, Nullable } from '@univerjs/core'; +import type { DataValidatorRegistryService } from '@univerjs/data-validation'; import { ERROR_TYPE_SET } from '@univerjs/engine-formula'; export function getFormulaResult(result: Nullable[][]>) { @@ -32,14 +33,7 @@ export function isLegalFormulaResult(res: string) { /** * Judge if the data-validation's formula need to be offseted by ranges */ -export function isCustomFormulaType(type: DataValidationType) { - // types not in this list is formula type - const invalidTypes = [ - DataValidationType.LIST, - DataValidationType.LIST_MULTIPLE, - DataValidationType.CHECKBOX, - DataValidationType.ANY, - ]; - - return !invalidTypes.includes(type); +export function shouldOffsetFormulaByRange(type: DataValidationType | string, validatorRegistryService: DataValidatorRegistryService) { + const validator = validatorRegistryService.getValidatorItem(type); + return validator?.offsetFormulaByRange ?? false; } diff --git a/packages/sheets-data-validation/src/validators/any-validator.ts b/packages/sheets-data-validation/src/validators/any-validator.ts index 2b34438103..dd7d02cf60 100644 --- a/packages/sheets-data-validation/src/validators/any-validator.ts +++ b/packages/sheets-data-validation/src/validators/any-validator.ts @@ -25,6 +25,8 @@ export class AnyValidator extends BaseDataValidator { override operators: DataValidationOperator[] = []; override scopes: string | string[] = ['sheet']; + override readonly offsetFormulaByRange = false; + override async parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): Promise { return { formula1: rule.formula1, diff --git a/packages/sheets-data-validation/src/validators/checkbox-validator.ts b/packages/sheets-data-validation/src/validators/checkbox-validator.ts index 6360609c48..1289f885be 100644 --- a/packages/sheets-data-validation/src/validators/checkbox-validator.ts +++ b/packages/sheets-data-validation/src/validators/checkbox-validator.ts @@ -54,6 +54,8 @@ export class CheckboxValidator extends BaseDataValidator { override operators: DataValidationOperator[] = []; override scopes: string | string[] = ['sheet']; + override readonly offsetFormulaByRange = false; + private _formulaService = this.injector.get(DataValidationFormulaService); override skipDefaultFontRender = (rule: ISheetDataValidationRule, cellValue: Nullable, pos: { unitId: string; subUnitId: string; row: number; column: number }) => { diff --git a/packages/sheets-data-validation/src/validators/date-validator.ts b/packages/sheets-data-validation/src/validators/date-validator.ts index 2387707a6c..937126953f 100644 --- a/packages/sheets-data-validation/src/validators/date-validator.ts +++ b/packages/sheets-data-validation/src/validators/date-validator.ts @@ -46,7 +46,7 @@ const transformDate2SerialNumber = (value: Nullable) => { return numfmt.parseDate(dayjs(value).format('YYYY-MM-DD HH:mm:ss'))?.v as number | undefined; }; -export class DateValidator extends BaseDataValidator { +export class DateValidator extends BaseDataValidator { id: string = DataValidationType.DATE; title: string = 'dataValidation.date.title'; operators: DataValidationOperator[] = [ @@ -156,78 +156,6 @@ export class DateValidator extends BaseDataValidator { }; } - override async validatorIsEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (Number.isNaN(formula1)) { - return true; - } - - return cellValue === formula1; - } - - override async validatorIsNotEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - - return cellInfo.value !== formula1; - } - - override async validatorIsBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1, formula2 } = formula; - if (Number.isNaN(formula1) || Number.isNaN(formula2)) { - return true; - } - - const start = Math.min(formula1, formula2); - const end = Math.max(formula1, formula2); - return cellInfo.value >= start && cellInfo.value <= end; - } - - override async validatorIsNotBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1, formula2 } = formula; - if (Number.isNaN(formula1) || Number.isNaN(formula2)) { - return true; - } - const start = Math.min(formula1, formula2); - const end = Math.max(formula1, formula2); - return cellInfo.value < start || cellInfo.value > end; - } - - override async validatorIsGreaterThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value > formula1; - } - - override async validatorIsGreaterThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value >= formula1; - } - - override async validatorIsLessThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value < formula1; - } - - override async validatorIsLessThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value <= formula1; - } - override get operatorNames() { return this.operators.map((operator) => this.localeService.t(DateOperatorNameMap[operator])); } diff --git a/packages/sheets-data-validation/src/validators/decimal-validator.ts b/packages/sheets-data-validation/src/validators/decimal-validator.ts index 8dfce5bec0..4bd2fc0f23 100644 --- a/packages/sheets-data-validation/src/validators/decimal-validator.ts +++ b/packages/sheets-data-validation/src/validators/decimal-validator.ts @@ -40,7 +40,7 @@ export function getCellValueNumber(cellValue: CellValue) { return +cellValue; } -export class DecimalValidator extends BaseDataValidator { +export class DecimalValidator extends BaseDataValidator { private readonly _customFormulaService = this.injector.get(DataValidationCustomFormulaService); id: string = DataValidationType.DECIMAL; private readonly _lexerTreeBuilder = this.injector.get(LexerTreeBuilder); @@ -126,79 +126,6 @@ export class DecimalValidator extends BaseDataValidator { }; } - override async validatorIsEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (Number.isNaN(formula1)) { - return true; - } - - return cellValue === formula1; - } - - override async validatorIsNotEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - - return cellInfo.value !== formula1; - } - - override async validatorIsBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1, formula2 } = formula; - if (Number.isNaN(formula1) || Number.isNaN(formula2)) { - return true; - } - - const start = Math.min(formula1, formula2); - const end = Math.max(formula1, formula2); - return cellInfo.value >= start && cellInfo.value <= end; - } - - override async validatorIsNotBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1, formula2 } = formula; - if (Number.isNaN(formula1) || Number.isNaN(formula2)) { - return true; - } - const start = Math.min(formula1, formula2); - const end = Math.max(formula1, formula2); - return cellInfo.value < start || cellInfo.value > end; - } - - override async validatorIsGreaterThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value > formula1; - } - - override async validatorIsGreaterThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value >= formula1; - } - - override async validatorIsLessThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value < formula1; - } - - override async validatorIsLessThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - - return cellInfo.value <= formula1; - } - override generateRuleErrorMessage(rule: IDataValidationRuleBase, position: ISheetLocationBase) { if (!rule.operator) { return this.titleStr; diff --git a/packages/sheets-data-validation/src/validators/list-multiple-validator.ts b/packages/sheets-data-validation/src/validators/list-multiple-validator.ts index f61e1883d6..45ea313a0b 100644 --- a/packages/sheets-data-validation/src/validators/list-multiple-validator.ts +++ b/packages/sheets-data-validation/src/validators/list-multiple-validator.ts @@ -20,6 +20,7 @@ import { ListValidator } from './list-validator'; export class ListMultipleValidator extends ListValidator { override id: string = DataValidationType.LIST_MULTIPLE; override title: string = 'dataValidation.listMultiple.title'; + override readonly offsetFormulaByRange = false; override skipDefaultFontRender = () => { return true; diff --git a/packages/sheets-data-validation/src/validators/list-validator.ts b/packages/sheets-data-validation/src/validators/list-validator.ts index 7feac8588a..2ed6222ae1 100644 --- a/packages/sheets-data-validation/src/validators/list-validator.ts +++ b/packages/sheets-data-validation/src/validators/list-validator.ts @@ -93,6 +93,8 @@ export class ListValidator extends BaseDataValidator { private _lexer = this.injector.get(LexerTreeBuilder); private _univerInstanceService = this.injector.get(IUniverInstanceService); + override readonly offsetFormulaByRange = false; + id: string = DataValidationType.LIST; title: string = 'dataValidation.list.title'; operators: DataValidationOperator[] = []; @@ -146,24 +148,25 @@ export class ListValidator extends BaseDataValidator { return deserializeListOptions(cellString); } - override async parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): Promise> { - const { formula1 = '' } = rule; + override async parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): Promise> { const results = await this.formulaService.getRuleFormulaResult(unitId, subUnitId, rule.uid); const formulaResult1 = getFormulaResult(results?.[0]?.result?.[0][0]); const isFormulaValid = isLegalFormulaResult(String(formulaResult1)); return { - formula1: isFormulaString(formula1) ? getRuleFormulaResultSet(results?.[0]?.result?.[0][0]) : deserializeListOptions(formula1), + formula1: undefined, formula2: undefined, isFormulaValid, }; } override async isValidType(cellInfo: IValidatorCellInfo>, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { value } = cellInfo; - const { formula1 = [] } = formula; + const { value, unitId, subUnitId } = cellInfo; + const { formula1 = '' } = rule; + const results = await this.formulaService.getRuleFormulaResult(unitId, subUnitId, rule.uid); + const formula1Result = isFormulaString(formula1) ? getRuleFormulaResultSet(results?.[0]?.result?.[0][0]) : deserializeListOptions(formula1); const selected = this.parseCellValue(value!); - return selected.every((i) => formula1.includes(i)); + return selected.every((i) => formula1Result.includes(i)); } override generateRuleName() { diff --git a/packages/sheets-data-validation/src/validators/text-length-validator.ts b/packages/sheets-data-validation/src/validators/text-length-validator.ts index b30e93352d..e68c123659 100644 --- a/packages/sheets-data-validation/src/validators/text-length-validator.ts +++ b/packages/sheets-data-validation/src/validators/text-length-validator.ts @@ -26,7 +26,7 @@ import { isLegalFormulaResult } from '../utils/formula'; import { FORMULA1, FORMULA2 } from './const'; import { getTransformedFormula } from './util'; -export class TextLengthValidator extends BaseDataValidator { +export class TextLengthValidator extends BaseDataValidator { id: string = DataValidationType.TEXT_LENGTH; title: string = 'dataValidation.textLength.title'; private readonly _lexerTreeBuilder = this.injector.get(LexerTreeBuilder); @@ -50,7 +50,7 @@ export class TextLengthValidator extends BaseDataValidator { return !Tools.isBlank(formula) && (isFormulaString(formula) || (!Number.isNaN(+formula) && Number.isInteger(+formula))); } - override validatorFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): IFormulaValidResult { + override validatorFormula(rule: IDataValidationRule, _unitId: string, _subUnitId: string): IFormulaValidResult { const operator = rule.operator; if (!operator) { return { @@ -83,11 +83,7 @@ export class TextLengthValidator extends BaseDataValidator { return +formula; } - private _isValidFormula(formula: number) { - return !Number.isNaN(formula); - } - - override async parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string, row: number, column: number): Promise> { + override async parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string, row: number, column: number): Promise> { const formulaResult1 = await this._customFormulaService.getCellFormulaValue(unitId, subUnitId, rule.uid, row, column); const formulaResult2 = await this._customFormulaService.getCellFormula2Value(unitId, subUnitId, rule.uid, row, column); const { formula1, formula2 } = rule; @@ -108,95 +104,11 @@ export class TextLengthValidator extends BaseDataValidator { }; } - override async isValidType(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { + override async isValidType(cellInfo: IValidatorCellInfo, _formula: IFormulaResult, _rule: IDataValidationRule) { const { value: cellValue } = cellInfo; return typeof cellValue === 'string' || typeof cellValue === 'number'; } - override async validatorIsEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1 } = formula; - if (!Tools.isDefine(formula1)) { - return false; - } - - return cellInfo.value === formula1; - } - - override async validatorIsNotEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1 } = formula; - if (!Tools.isDefine(formula1)) { - return false; - } - - return cellInfo.value !== formula1; - } - - override async validatorIsBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1, formula2 } = formula; - const { value: cellValue } = cellInfo; - if (!this._isValidFormula(formula1) || !this._isValidFormula(formula2)) { - return false; - } - - const max = Math.max(formula1, formula2); - const min = Math.min(formula1, formula2); - - return cellValue >= min && cellValue <= max; - } - - override async validatorIsNotBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1, formula2 } = formula; - const { value: cellValue } = cellInfo; - if (!this._isValidFormula(formula1) || !this._isValidFormula(formula2)) { - return false; - } - - const max = Math.max(formula1, formula2); - const min = Math.min(formula1, formula2); - - return cellValue < min || cellValue > max; - } - - override async validatorIsGreaterThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (!this._isValidFormula(formula1)) { - return false; - } - - return cellValue > formula1; - } - - override async validatorIsGreaterThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (!this._isValidFormula(formula1)) { - return false; - } - - return cellValue >= formula1; - } - - override async validatorIsLessThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (!this._isValidFormula(formula1)) { - return false; - } - - return cellValue < formula1; - } - - override async validatorIsLessThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule): Promise { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (!this._isValidFormula(formula1)) { - return false; - } - - return cellValue <= formula1; - } - override generateRuleErrorMessage(rule: IDataValidationRuleBase, pos: ISheetLocationBase) { if (!rule.operator) { return this.titleStr; diff --git a/packages/sheets-data-validation/src/validators/whole-validator.ts b/packages/sheets-data-validation/src/validators/whole-validator.ts index a921f349b6..1c291dd97d 100644 --- a/packages/sheets-data-validation/src/validators/whole-validator.ts +++ b/packages/sheets-data-validation/src/validators/whole-validator.ts @@ -28,7 +28,7 @@ import { FORMULA1, FORMULA2 } from './const'; import { getCellValueNumber } from './decimal-validator'; import { getTransformedFormula } from './util'; -export class WholeValidator extends BaseDataValidator { +export class WholeValidator extends BaseDataValidator { private readonly _customFormulaService = this.injector.get(DataValidationCustomFormulaService); private readonly _lexerTreeBuilder = this.injector.get(LexerTreeBuilder); @@ -52,13 +52,13 @@ export class WholeValidator extends BaseDataValidator { return !Tools.isBlank(formula) && (isFormulaString(formula) || (!Number.isNaN(+formula) && Number.isInteger(+formula))); } - override async isValidType(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { + override async isValidType(cellInfo: IValidatorCellInfo, _formula: IFormulaResult, _rule: IDataValidationRule) { const { value: cellValue } = cellInfo; const num = getCellValueNumber(cellValue); return !Number.isNaN(num) && Number.isInteger(num); } - override transform(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { + override transform(cellInfo: IValidatorCellInfo, _formula: IFormulaResult, _rule: IDataValidationRule) { const { value: cellValue } = cellInfo; return { ...cellInfo, @@ -92,7 +92,7 @@ export class WholeValidator extends BaseDataValidator { return info; } - override validatorFormula(rule: IDataValidationRuleBase, unitId: string, subUnitId: string): IFormulaValidResult { + override validatorFormula(rule: IDataValidationRuleBase, _unitId: string, _subUnitId: string): IFormulaValidResult { const operator = rule.operator; if (!operator) { return { @@ -117,80 +117,6 @@ export class WholeValidator extends BaseDataValidator { }; } - override async validatorIsEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, rule: IDataValidationRule) { - const { formula1 } = formula; - const { value: cellValue } = cellInfo; - if (Number.isNaN(formula1)) { - return true; - } - - return cellValue === formula1; - } - - override async validatorIsNotEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - - return cellInfo.value !== formula1; - } - - override async validatorIsBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1, formula2 } = formula; - if (Number.isNaN(formula1) || Number.isNaN(formula2)) { - return true; - } - - const start = Math.min(formula1, formula2); - const end = Math.max(formula1, formula2); - return cellInfo.value >= start && cellInfo.value <= end; - } - - override async validatorIsNotBetween(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1, formula2 } = formula; - if (Number.isNaN(formula1) || Number.isNaN(formula2)) { - return true; - } - - const start = Math.min(formula1, formula2); - const end = Math.max(formula1, formula2); - return cellInfo.value < start || cellInfo.value > end; - } - - override async validatorIsGreaterThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value > formula1; - } - - override async validatorIsGreaterThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value >= formula1; - } - - override async validatorIsLessThan(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - return cellInfo.value < formula1; - } - - override async validatorIsLessThanOrEqual(cellInfo: IValidatorCellInfo, formula: IFormulaResult, _rule: IDataValidationRule) { - const { formula1 } = formula; - if (Number.isNaN(formula1)) { - return true; - } - - return cellInfo.value <= formula1; - } - override generateRuleErrorMessage(rule: IDataValidationRuleBase, position: ISheetLocationBase) { if (!rule.operator) { return this.titleStr; diff --git a/packages/sheets-hyper-link-ui/src/utils/index.ts b/packages/sheets-hyper-link-ui/src/utils/index.ts index 1667d836cf..4899d9cd87 100644 --- a/packages/sheets-hyper-link-ui/src/utils/index.ts +++ b/packages/sheets-hyper-link-ui/src/utils/index.ts @@ -20,19 +20,21 @@ import { DocSelectionManagerService } from '@univerjs/docs'; import { SheetsSelectionsService } from '@univerjs/sheets'; import { SheetDataValidationModel } from '@univerjs/sheets-data-validation'; +const disables = new Set([ + DataValidationType.CHECKBOX, + DataValidationType.LIST, + DataValidationType.LIST_MULTIPLE, +]); + export const getShouldDisableCellLink = (accessor: IAccessor, worksheet: Worksheet, row: number, col: number) => { const cell = worksheet.getCell(row, col); if (cell?.f || cell?.si) { return true; } - const disables = [ - DataValidationType.CHECKBOX, - DataValidationType.LIST, - DataValidationType.LIST_MULTIPLE, - ]; + const dataValidationModel = accessor.has(SheetDataValidationModel) ? accessor.get(SheetDataValidationModel) : null; const rule = dataValidationModel?.getRuleByLocation(worksheet.getUnitId(), worksheet.getSheetId(), row, col); - if (rule && disables.includes(rule.type)) { + if (rule && disables.has(rule.type)) { return true; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b0ea256ba..2fa6cdb1a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2044,9 +2044,6 @@ importers: packages/sheets-data-validation: dependencies: - '@flatten-js/interval-tree': - specifier: ^1.1.3 - version: 1.1.3 '@univerjs/core': specifier: workspace:* version: link:../core