mirror of
https://github.com/dream-num/univer.git
synced 2026-09-24 15:32:18 +08:00
fix: ignore custom metadata when checking empty cells (#6957)
This commit is contained in:
@@ -102,6 +102,7 @@ describe('Test cell data', () => {
|
||||
expect(isNullCell({ si: null })).toBeTruthy();
|
||||
expect(isNullCell({ si: undefined })).toBeTruthy();
|
||||
expect(isNullCell({ si: '' })).toBeTruthy();
|
||||
expect(isNullCell({ custom: { key: 'value' } })).toBeTruthy();
|
||||
|
||||
expect(isNullCell({ v: 1 })).toBeFalsy();
|
||||
expect(isNullCell({ p: DOCUMENT_DATA })).toBeFalsy();
|
||||
|
||||
@@ -356,7 +356,7 @@ export function isNullCell(cell: Nullable<ICellData>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { v, f, si, p, custom } = cell;
|
||||
const { v, f, si, p } = cell;
|
||||
|
||||
if (!(v == null || (typeof v === 'string' && v.length === 0))) {
|
||||
return false;
|
||||
@@ -370,10 +370,6 @@ export function isNullCell(cell: Nullable<ICellData>) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (custom != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ICellData, Nullable } from '@univerjs/core';
|
||||
|
||||
/**
|
||||
* Examine if a cell is empty (null) in the formula-related modules. This is not
|
||||
* interchangable with {@link isNullCell} from the core package, because for
|
||||
* formulas, "custom" field is meaningless.
|
||||
*/
|
||||
export function isNullCellForFormula(cell: Nullable<ICellData>) {
|
||||
if (cell == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { v, f, si, p } = cell;
|
||||
|
||||
if (!(v == null || (typeof v === 'string' && v.length === 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((f != null && f.length > 0) || (si != null && si.length > 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -17,10 +17,9 @@
|
||||
import type { ICellData, IRange, Nullable } from '@univerjs/core';
|
||||
import type { IArrayFormulaRangeType, IRuntimeUnitDataType, IUnitData, IUnitSheetNameMap, IUnitStylesData } from '../../basics/common';
|
||||
import type { BaseValueObject, IArrayValueObject } from '../value-object/base-value-object';
|
||||
import { CellValueType, isTextFormat, moveRangeByOffset, ObjectMatrix } from '@univerjs/core';
|
||||
import { CellValueType, isNullCell, isTextFormat, moveRangeByOffset, ObjectMatrix } from '@univerjs/core';
|
||||
import { FormulaAstLRU } from '../../basics/cache-lru';
|
||||
import { ERROR_TYPE_SET, ErrorType } from '../../basics/error-type';
|
||||
import { isNullCellForFormula } from '../../basics/is-null-cell';
|
||||
import { ObjectClassType } from '../../basics/object-class-type';
|
||||
import { getCellValue } from '../utils/cell';
|
||||
import { getRuntimeFeatureCell } from '../utils/get-runtime-feature-cell';
|
||||
@@ -173,7 +172,7 @@ export class BaseReferenceObject extends ObjectClassType {
|
||||
|
||||
const cell = this.getCellData(r, c)!;
|
||||
let result: Nullable<boolean> = false;
|
||||
if (isNullCellForFormula(cell)) {
|
||||
if (isNullCell(cell)) {
|
||||
result = callback(null, r, c);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,10 @@ import type { BaseReferenceObject, FunctionVariantType } from '../engine/referen
|
||||
import type { ArrayValueObject } from '../engine/value-object/array-value-object';
|
||||
import type { BaseValueObject } from '../engine/value-object/base-value-object';
|
||||
import type { StringValueObject } from '../engine/value-object/primitive-object';
|
||||
import { createIdentifier, Disposable, ObjectMatrix } from '@univerjs/core';
|
||||
import { createIdentifier, Disposable, isNullCell, ObjectMatrix } from '@univerjs/core';
|
||||
import { isInDirtyRange } from '../basics/dirty';
|
||||
import { ErrorType } from '../basics/error-type';
|
||||
import { CELL_INVERTED_INDEX_CACHE } from '../basics/inverted-index-cache';
|
||||
import { isNullCellForFormula } from '../basics/is-null-cell';
|
||||
import { FORMULA_REF_TO_ARRAY_CACHE } from '../engine/reference-object/base-reference-object';
|
||||
import { getRuntimeFeatureCell } from '../engine/utils/get-runtime-feature-cell';
|
||||
import { clearNumberFormatTypeCache, clearStringToNumberPatternCache } from '../engine/utils/numfmt-kit';
|
||||
@@ -853,10 +852,10 @@ export class FormulaRuntimeService extends Disposable implements IFormulaRuntime
|
||||
const isPreviousCellOfCurrentArrayFormula = this._arrayCellHasData(arrayDataCell) &&
|
||||
this._isInArrayFormulaRange(previousArrayFormulaRange, r, c) &&
|
||||
(currentCell == null || this._isSameCellValue(currentCell, arrayDataCell));
|
||||
const hasRuntimeCell = !isNullCellForFormula(cell);
|
||||
const hasRuntimeCell = !isNullCell(cell);
|
||||
const isInOtherArrayFormulaRange = this._isInOtherArrayFormulaRange(formulaUnitId, formulaSheetId, formulaRow, formulaColumn, r, c);
|
||||
const currentCellBlocks = !isNullCellForFormula(currentCell) && !isPreviousCellOfCurrentArrayFormula;
|
||||
const featureCellBlocks = !isNullCellForFormula(featureCell);
|
||||
const currentCellBlocks = !isNullCell(currentCell) && !isPreviousCellOfCurrentArrayFormula;
|
||||
const featureCellBlocks = !isNullCell(featureCell);
|
||||
|
||||
// arrayDataCell may display 0 as {v: null}. Although it is an empty cell, it is considered to have a value.
|
||||
if (
|
||||
|
||||
@@ -91,6 +91,7 @@ const workbookDataFactory = (): IWorkbookData => ({
|
||||
0: { v: 'A1' },
|
||||
1: { v: 'very-long-text-for-overflow-path', s: 'style-bg-border' },
|
||||
2: { v: 'wrapped line text', s: 'style-bg-border' },
|
||||
4: { s: 'style-bg-border', custom: { key: 'value' } },
|
||||
},
|
||||
1: {
|
||||
1: { v: 'rotate-text', s: 'style-rotate' },
|
||||
@@ -255,6 +256,9 @@ describe('spreadsheet integration', () => {
|
||||
}));
|
||||
expect(skeleton.rowColumnSegment.endRow).toBeGreaterThanOrEqual(0);
|
||||
expect(skeleton.stylesCache.fontMatrix.getSizeOf()).toBeGreaterThan(0);
|
||||
expect(skeleton.stylesCache.border?.getValue(0, 4)).toBeTruthy();
|
||||
expect(skeleton.stylesCache.fontMatrix.getValue(0, 4)).toBeUndefined();
|
||||
expect(skeleton.overflowCache.getValue(0, 4)).toBeUndefined();
|
||||
|
||||
const autoHeights = skeleton.calculateAutoHeightInRange([{ startRow: 0, endRow: 6, startColumn: 0, endColumn: 3, rangeType: RANGE_TYPE.NORMAL }]);
|
||||
expect(autoHeights.length).toBeGreaterThan(0);
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { IWorkbookData, Univer } from '@univerjs/core';
|
||||
import { BorderStyleTypes, CellValueType, ICommandService, IUniverInstanceService, LocaleType, RANGE_TYPE } from '@univerjs/core';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { SetRangeValuesMutation } from '../../mutations/set-range-values.mutation';
|
||||
import { SetRangeCustomMetadataCommand } from '../set-range-custom-metadata.command';
|
||||
import { createCommandTestBed } from './create-command-test-bed';
|
||||
|
||||
const WORKBOOK_DATA: IWorkbookData = {
|
||||
id: 'test',
|
||||
appVersion: '3.0.0-alpha',
|
||||
locale: LocaleType.ZH_CN,
|
||||
name: '',
|
||||
sheetOrder: ['sheet1'],
|
||||
styles: {},
|
||||
sheets: {
|
||||
sheet1: {
|
||||
id: 'sheet1',
|
||||
name: 'sheet1',
|
||||
cellData: {
|
||||
0: {
|
||||
2: {
|
||||
s: {
|
||||
bd: {
|
||||
t: { s: BorderStyleTypes.THIN, cl: { rgb: '#000000' } },
|
||||
r: { s: BorderStyleTypes.THIN, cl: { rgb: '#000000' } },
|
||||
b: { s: BorderStyleTypes.THIN, cl: { rgb: '#000000' } },
|
||||
l: { s: BorderStyleTypes.THIN, cl: { rgb: '#000000' } },
|
||||
},
|
||||
},
|
||||
t: CellValueType.STRING,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('SetRangeCustomMetadataCommand', () => {
|
||||
let univer: Univer;
|
||||
let commandService: ICommandService;
|
||||
let univerInstanceService: IUniverInstanceService;
|
||||
|
||||
beforeEach(() => {
|
||||
const testBed = createCommandTestBed(WORKBOOK_DATA);
|
||||
univer = testBed.univer;
|
||||
commandService = testBed.get(ICommandService);
|
||||
univerInstanceService = testBed.get(IUniverInstanceService);
|
||||
|
||||
commandService.registerCommand(SetRangeCustomMetadataCommand);
|
||||
commandService.registerCommand(SetRangeValuesMutation);
|
||||
});
|
||||
|
||||
afterEach(() => univer.dispose());
|
||||
|
||||
it('preserves existing cell type and border style when setting metadata on a styled empty cell', async () => {
|
||||
const result = await commandService.executeCommand(SetRangeCustomMetadataCommand.id, {
|
||||
unitId: 'test',
|
||||
subUnitId: 'sheet1',
|
||||
range: {
|
||||
startRow: 0,
|
||||
endRow: 0,
|
||||
startColumn: 2,
|
||||
endColumn: 2,
|
||||
rangeType: RANGE_TYPE.NORMAL,
|
||||
},
|
||||
customMetadata: {
|
||||
custom: { key: 'value' },
|
||||
},
|
||||
});
|
||||
|
||||
const workbook = univerInstanceService.getUniverSheetInstance('test')!;
|
||||
const cell = workbook.getSheetBySheetId('sheet1')!.getCellRaw(0, 2);
|
||||
const style = workbook.getStyles().getStyleByCell(cell);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(cell?.custom).toEqual({ key: 'value' });
|
||||
expect(cell?.t).toBe(CellValueType.STRING);
|
||||
expect(style).toMatchObject({
|
||||
bd: {
|
||||
t: { s: BorderStyleTypes.THIN },
|
||||
r: { s: BorderStyleTypes.THIN },
|
||||
b: { s: BorderStyleTypes.THIN },
|
||||
l: { s: BorderStyleTypes.THIN },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user