Skip to content

Commit

Permalink
fix(sheet): defined name move (#1888)
Browse files Browse the repository at this point in the history
* refactor(sheet): sequence node migration

* fix(sheet): scientific notation

* fix(formula): move for defined name

* fix(sheet): scientific notation

* fix(sheet): type error

* fix(sheet): type error
  • Loading branch information
DR-Univer committed Apr 13, 2024
1 parent a2c8cb6 commit be2fec3
Show file tree
Hide file tree
Showing 28 changed files with 507 additions and 221 deletions.
78 changes: 78 additions & 0 deletions packages/core/src/shared/__test__/range.spec.ts
@@ -0,0 +1,78 @@
/**
* 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 { describe, expect, it } from 'vitest';

import { AbsoluteRefType } from '../../types/interfaces/i-range';
import { moveRangeByOffset } from '../range';

describe('test moveRangeByOffset', () => {
it('test normal', () => {
const range = {
startRow: 1,
startColumn: 1,
endRow: 3,
endColumn: 3,
};
const newRange = moveRangeByOffset(range, 1, 1);
expect(newRange).toEqual({
startRow: 2,
startColumn: 2,
endRow: 4,
endColumn: 4,
});
});

it('test absolute', () => {
const range = {
startRow: 1,
startColumn: 1,
endRow: 3,
endColumn: 3,
startAbsoluteRefType: AbsoluteRefType.ROW,
endAbsoluteRefType: AbsoluteRefType.COLUMN,
};
const newRange = moveRangeByOffset(range, 1, 1);
expect(newRange).toEqual({
startRow: 1,
startColumn: 2,
endRow: 4,
endColumn: 3,
startAbsoluteRefType: AbsoluteRefType.ROW,
endAbsoluteRefType: AbsoluteRefType.COLUMN,
});
});

it('test ignoreAbsolute', () => {
const range = {
startRow: 1,
startColumn: 1,
endRow: 3,
endColumn: 3,
startAbsoluteRefType: AbsoluteRefType.ROW,
endAbsoluteRefType: AbsoluteRefType.COLUMN,
};
const newRange = moveRangeByOffset(range, 1, 1, true);
expect(newRange).toEqual({
startRow: 2,
startColumn: 2,
endRow: 4,
endColumn: 4,
startAbsoluteRefType: AbsoluteRefType.ROW,
endAbsoluteRefType: AbsoluteRefType.COLUMN,
});
});
});
2 changes: 2 additions & 0 deletions packages/core/src/shared/index.ts
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/


export * from './array-search';
export * from './blob';
export * from './color/color';
Expand All @@ -38,3 +39,4 @@ export * from './tools';
export * from './types';
export * from './debounce';
export { queryObjectMatrix } from './object-matrix-query';
export { moveRangeByOffset } from './range';
52 changes: 52 additions & 0 deletions packages/core/src/shared/range.ts
@@ -0,0 +1,52 @@
/**
* 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 { AbsoluteRefType, type IRange } from '../types/interfaces/i-range';
import { Rectangle } from './rectangle';

export function moveRangeByOffset(range: IRange, refOffsetX: number, refOffsetY: number, ignoreAbsolute = false): IRange {
let newRange = { ...range };

const startAbsoluteRefType = newRange.startAbsoluteRefType || AbsoluteRefType.NONE;
const endAbsoluteRefType = newRange.endAbsoluteRefType || AbsoluteRefType.NONE;

if (startAbsoluteRefType === AbsoluteRefType.ALL && endAbsoluteRefType === AbsoluteRefType.ALL) {
return newRange;
}

if (ignoreAbsolute || (startAbsoluteRefType === AbsoluteRefType.NONE && endAbsoluteRefType === AbsoluteRefType.NONE)) {
return Rectangle.moveOffset(newRange, refOffsetX, refOffsetY);
}

if (startAbsoluteRefType === AbsoluteRefType.NONE) {
newRange = { ...newRange, startRow: newRange.startRow + refOffsetY, startColumn: newRange.startColumn + refOffsetX };
} else if (startAbsoluteRefType === AbsoluteRefType.COLUMN) {
newRange = { ...newRange, startRow: newRange.startRow + refOffsetY };
} else if (startAbsoluteRefType === AbsoluteRefType.ROW) {
newRange = { ...newRange, startColumn: newRange.startColumn + refOffsetX };
}


if (endAbsoluteRefType === AbsoluteRefType.NONE) {
newRange = { ...newRange, endRow: newRange.endRow + refOffsetY, endColumn: newRange.endColumn + refOffsetX };
} else if (endAbsoluteRefType === AbsoluteRefType.COLUMN) {
newRange = { ...newRange, endRow: newRange.endRow + refOffsetY };
} else if (endAbsoluteRefType === AbsoluteRefType.ROW) {
newRange = { ...newRange, endColumn: newRange.endColumn + refOffsetX };
}

return newRange;
}
Expand Up @@ -16,11 +16,24 @@

import { describe, expect, it } from 'vitest';

import { AbsoluteRefType } from '@univerjs/core';
import type { LexerNode } from '../lexer-node';
import { LexerTreeBuilder } from '../lexer-tree-builder';
import { ErrorType } from '../../../basics/error-type';

function checkDefinedName(token: string) {
if (token === 'myName') {
return true;
}
return false;
}

function checkDefinedName2(token: string) {
if (token === 'DefinedName2') {
return true;
}
return false;
}

describe('lexer nodeMaker test', () => {
const lexerTreeBuilder = new LexerTreeBuilder();

Expand Down Expand Up @@ -244,7 +257,7 @@ describe('lexer nodeMaker test', () => {

describe('sequenceNodesBuilder', () => {
it('workbook ref build', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=[workbook-01]工作表11!G14:M20')).toStrictEqual([
expect(lexerTreeBuilder.sequenceNodesBuilder('=[workbook-01]工作表11!G14:M20', () => false)).toStrictEqual([
{
endIndex: 25,
nodeType: 4,
Expand All @@ -255,7 +268,7 @@ describe('lexer nodeMaker test', () => {
});

it('special workbook ref build', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=\'[workbook-01]工作表11\'!G14:M20,\'[workbook-01]工作表11\'!K27:N32')).toStrictEqual([
expect(lexerTreeBuilder.sequenceNodesBuilder('=\'[workbook-01]工作表11\'!G14:M20,\'[workbook-01]工作表11\'!K27:N32', () => false)).toStrictEqual([
{
endIndex: 27,
nodeType: 4,
Expand All @@ -273,7 +286,7 @@ describe('lexer nodeMaker test', () => {
});

it('cube', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=INDEX((A6:B6,C6:D7),1,1,2)')).toStrictEqual([
expect(lexerTreeBuilder.sequenceNodesBuilder('=INDEX((A6:B6,C6:D7),1,1,2)', () => false)).toStrictEqual([
{
endIndex: 4,
nodeType: 3,
Expand Down Expand Up @@ -322,7 +335,7 @@ describe('lexer nodeMaker test', () => {
});

it('No Parameter Function', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=today()+today()+column()')).toStrictEqual([
expect(lexerTreeBuilder.sequenceNodesBuilder('=today()+today()+column()', () => false)).toStrictEqual([
{
endIndex: 4,
nodeType: 3,
Expand Down Expand Up @@ -353,7 +366,7 @@ describe('lexer nodeMaker test', () => {
});

it('No Parameter Today', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=IF(TODAY()>1,"TRUE", "FALSE")')).toStrictEqual([
expect(lexerTreeBuilder.sequenceNodesBuilder('=IF(TODAY()>1,"TRUE", "FALSE")', () => false)).toStrictEqual([
{
endIndex: 1,
nodeType: 3,
Expand Down Expand Up @@ -393,42 +406,56 @@ describe('lexer nodeMaker test', () => {
')',
]);
});
});

describe('convertRefersToAbsolute', () => {
it('Formula All', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('=sum(A1:B1,A1:B1,A1:B1,A1:B1)', AbsoluteRefType.ALL, AbsoluteRefType.ALL);
expect(result).toStrictEqual('=sum($A$1:$B$1,$A$1:$B$1,$A$1:$B$1,$A$1:$B$1)');
});

it('Range All', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('A1:B1,A1:B1,A1:B1,A1:B1', AbsoluteRefType.ALL, AbsoluteRefType.ALL);
expect(result).toStrictEqual('$A$1:$B$1,$A$1:$B$1,$A$1:$B$1,$A$1:$B$1');
});

it('Formula Column', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('=sum(A1:B1,A1:B1,A1:B1,A1:B1)', AbsoluteRefType.COLUMN, AbsoluteRefType.COLUMN);
expect(result).toStrictEqual('=sum($A1:$B1,$A1:$B1,$A1:$B1,$A1:$B1)');
});

it('Range Column', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('A1:B1,A1:B1,A1:B1,A1:B1', AbsoluteRefType.COLUMN, AbsoluteRefType.COLUMN);
expect(result).toStrictEqual('$A1:$B1,$A1:$B1,$A1:$B1,$A1:$B1');
});

it('Formula Row', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('=sum(A1:B1,A1:B1,A1:B1,A1:B1)', AbsoluteRefType.ROW, AbsoluteRefType.ROW);
expect(result).toStrictEqual('=sum(A$1:B$1,A$1:B$1,A$1:B$1,A$1:B$1)');
});

it('Range Row', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('A1:B1,A1:B1,A1:B1,A1:B1', AbsoluteRefType.ROW, AbsoluteRefType.ROW);
expect(result).toStrictEqual('A$1:B$1,A$1:B$1,A$1:B$1,A$1:B$1');
it('Has defined name', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=myName+A1:B10', checkDefinedName.bind(this))).toStrictEqual([
{
endIndex: 5,
nodeType: 6,
startIndex: 0,
token: 'myName',
},
'+',
{
endIndex: 12,
nodeType: 4,
startIndex: 7,
token: 'A1:B10',
},
]);
});

it('Complex Formula', () => {
const result = lexerTreeBuilder.convertRefersToAbsolute('=SUM(A1:B10) + LAMBDA(x, y, x*y*x)(A1:B10, A10) + MAX(A1:B10,SUM(A2))', AbsoluteRefType.ALL, AbsoluteRefType.ALL);
expect(result).toStrictEqual('=SUM($A$1:$B$10) + LAMBDA(x, y, x*y*x)($A$1:$B$10,$A$10) + MAX($A$1:$B$10,SUM($A$2))');
it('Has defined name11', () => {
expect(lexerTreeBuilder.sequenceNodesBuilder('=SUM(DefinedName2+E22:E32,J21:J32)', checkDefinedName2.bind(this))).toStrictEqual([
{
endIndex: 2,
nodeType: 3,
startIndex: 0,
token: 'SUM',
},
'(',
{
endIndex: 15,
nodeType: 6,
startIndex: 4,
token: 'DefinedName2',
},
'+',
{
endIndex: 23,
nodeType: 4,
startIndex: 17,
token: 'E22:E32',
},
',',
{
endIndex: 31,
nodeType: 4,
startIndex: 25,
token: 'J21:J32',
},
')',
]);
});
});
});
Expand Up @@ -15,7 +15,7 @@
*/

import type { IWorkbookData, Univer, Workbook } from '@univerjs/core';
import { LocaleType } from '@univerjs/core';
import { AbsoluteRefType, IUniverInstanceService, LocaleType } from '@univerjs/core';
import type { Injector } from '@wendellhu/redi';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';

Expand Down Expand Up @@ -62,14 +62,15 @@ const TEST_WORKBOOK_DATA: IWorkbookData = {
styles: {},
};

describe('lexer nodeMaker test', () => {
describe('lexer test', () => {
let univer: Univer;
let lexer: Lexer;
let get: Injector['get'];
let workbook: Workbook;
let definedNamesService: IDefinedNamesService;
let formulaCurrentConfigService: IFormulaCurrentConfigService;
let lexerTreeBuilder: LexerTreeBuilder;
let univerInstanceService: IUniverInstanceService;

beforeEach(() => {
const testBed = createCommandTestBed(TEST_WORKBOOK_DATA);
Expand All @@ -78,17 +79,16 @@ describe('lexer nodeMaker test', () => {
get = testBed.get;

definedNamesService = get(IDefinedNamesService);

formulaCurrentConfigService = get(IFormulaCurrentConfigService);

lexerTreeBuilder = get(LexerTreeBuilder);
univerInstanceService = get(IUniverInstanceService);

formulaCurrentConfigService.setExecuteUnitId('test');
formulaCurrentConfigService.setExecuteSubUnitId('sheet1');

// runtimeService.setCurrent(0, 0, 4, 1, 'sheet1', 'test');

lexer = new Lexer(definedNamesService, lexerTreeBuilder, formulaCurrentConfigService);
lexer = new Lexer(definedNamesService, lexerTreeBuilder, formulaCurrentConfigService, univerInstanceService);
});

afterEach(() => {
Expand Down Expand Up @@ -116,4 +116,41 @@ describe('lexer nodeMaker test', () => {
);
});
});

describe('convertRefersToAbsolute', () => {
it('Formula All', () => {
const result = lexer.convertRefersToAbsolute('=sum(A1:B1,A1:B1,A1:B1,A1:B1)', AbsoluteRefType.ALL, AbsoluteRefType.ALL);
expect(result).toStrictEqual('=sum($A$1:$B$1,$A$1:$B$1,$A$1:$B$1,$A$1:$B$1)');
});

it('Range All', () => {
const result = lexer.convertRefersToAbsolute('A1:B1,A1:B1,A1:B1,A1:B1', AbsoluteRefType.ALL, AbsoluteRefType.ALL);
expect(result).toStrictEqual('$A$1:$B$1,$A$1:$B$1,$A$1:$B$1,$A$1:$B$1');
});

it('Formula Column', () => {
const result = lexer.convertRefersToAbsolute('=sum(A1:B1,A1:B1,A1:B1,A1:B1)', AbsoluteRefType.COLUMN, AbsoluteRefType.COLUMN);
expect(result).toStrictEqual('=sum($A1:$B1,$A1:$B1,$A1:$B1,$A1:$B1)');
});

it('Range Column', () => {
const result = lexer.convertRefersToAbsolute('A1:B1,A1:B1,A1:B1,A1:B1', AbsoluteRefType.COLUMN, AbsoluteRefType.COLUMN);
expect(result).toStrictEqual('$A1:$B1,$A1:$B1,$A1:$B1,$A1:$B1');
});

it('Formula Row', () => {
const result = lexer.convertRefersToAbsolute('=sum(A1:B1,A1:B1,A1:B1,A1:B1)', AbsoluteRefType.ROW, AbsoluteRefType.ROW);
expect(result).toStrictEqual('=sum(A$1:B$1,A$1:B$1,A$1:B$1,A$1:B$1)');
});

it('Range Row', () => {
const result = lexer.convertRefersToAbsolute('A1:B1,A1:B1,A1:B1,A1:B1', AbsoluteRefType.ROW, AbsoluteRefType.ROW);
expect(result).toStrictEqual('A$1:B$1,A$1:B$1,A$1:B$1,A$1:B$1');
});

it('Complex Formula', () => {
const result = lexer.convertRefersToAbsolute('=SUM(A1:B10) + LAMBDA(x, y, x*y*x)(A1:B10, A10) + MAX(A1:B10,SUM(A2))', AbsoluteRefType.ALL, AbsoluteRefType.ALL);
expect(result).toStrictEqual('=SUM($A$1:$B$10) + LAMBDA(x, y, x*y*x)($A$1:$B$10,$A$10) + MAX($A$1:$B$10,SUM($A$2))');
});
});
});

0 comments on commit be2fec3

Please sign in to comment.