Skip to content
This repository was archived by the owner on Jul 15, 2021. It is now read-only.

Commit 8233275

Browse files
committed
Merge branch 'release/1.0.7'
2 parents 0815832 + e440af3 commit 8233275

File tree

12 files changed

+456
-178
lines changed

12 files changed

+456
-178
lines changed

dist/formula-parser.js

Lines changed: 239 additions & 146 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/formula-parser.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/formula-parser.min.js

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/formula-parser.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gulpfile.babel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function lintGulpfile() {
6767
}
6868

6969
function build() {
70-
return gulp.src(path.join('src', config.entryFileName + '.js'))
70+
return gulp.src(path.join(config.entryFileName + '.js'))
7171
.pipe($.plumber())
7272
.pipe(webpackStream({
7373
output: {

index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {Parser, SUPPORTED_FORMULAS} from './src/parser';
2+
import {default as error} from './src/error';
3+
import {extractLabel, toLabel, columnIndexToLabel, columnLabelToIndex, rowIndexToLabel, rowLabelToIndex} from './src/helper/cell';
4+
5+
export {
6+
SUPPORTED_FORMULAS,
7+
Parser,
8+
error,
9+
extractLabel,
10+
toLabel,
11+
columnIndexToLabel,
12+
columnLabelToIndex,
13+
rowIndexToLabel,
14+
rowLabelToIndex
15+
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hot-formula-parser",
3-
"version": "1.0.6",
3+
"version": "1.0.7",
44
"description": "Formula parser",
55
"main": "dist/formula-parser.js",
66
"scripts": {
@@ -72,7 +72,7 @@
7272
"yargs": "^4.7.1"
7373
},
7474
"babelBoilerplateOptions": {
75-
"entryFileName": "parser",
75+
"entryFileName": "index",
7676
"mainVarName": "formulaParser"
7777
},
7878
"dependencies": {

src/helper/cell.js

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export function extractLabel(label) {
1414

1515
return [
1616
{
17-
index: parseInt(row, 10) - 1,
17+
index: rowLabelToIndex(row),
1818
label: row,
1919
isAbsolute: rowAbs === '$',
2020
},
@@ -26,6 +26,20 @@ export function extractLabel(label) {
2626
];
2727
}
2828

29+
/**
30+
* Convert row and column indexes into cell label.
31+
*
32+
* @param {Object} row Object with `index` and `isAbsolute` properties.
33+
* @param {Object} column Object with `index` and `isAbsolute` properties.
34+
* @returns {String} Returns cell label.
35+
*/
36+
export function toLabel(row, column) {
37+
const rowLabel = (row.isAbsolute ? '$' : '') + rowIndexToLabel(row.index);
38+
const columnLabel = (column.isAbsolute ? '$' : '') + columnIndexToLabel(column.index);
39+
40+
return columnLabel + rowLabel;
41+
}
42+
2943
const COLUMN_LABEL_BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
3044
const COLUMN_LABEL_BASE_LENGTH = COLUMN_LABEL_BASE.length;
3145

@@ -64,3 +78,37 @@ export function columnIndexToLabel(column) {
6478

6579
return result.toUpperCase();
6680
}
81+
82+
/**
83+
* Convert row label to index.
84+
*
85+
* @param {String} label Row label (eq. '1', '5')
86+
* @returns {Number} Returns -1 if label is not recognized otherwise proper row index.
87+
*/
88+
export function rowLabelToIndex(label) {
89+
let result = parseInt(label, 10);
90+
91+
if (isNaN(result)) {
92+
result = -1;
93+
} else {
94+
result = Math.max(result - 1, -1);
95+
}
96+
97+
return result;
98+
}
99+
100+
/**
101+
* Convert row index to label.
102+
*
103+
* @param {Number} row Row index.
104+
* @returns {String} Returns row label (eq. '1', '7').
105+
*/
106+
export function rowIndexToLabel(row) {
107+
let result = '';
108+
109+
if (row >= 0) {
110+
result = `${row + 1}`;
111+
}
112+
113+
return result;
114+
}

src/parser.js

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {Parser as GrammarParser} from './grammar-parser/grammar-parser';
44
import {trimEdges} from './helper/string';
55
import {toNumber, invertNumber} from './helper/number';
66
import {default as errorParser, ERROR, ERROR_NAME} from './error';
7-
import {extractLabel} from './helper/cell';
7+
import {extractLabel, toLabel} from './helper/cell';
88

99
export {default as SUPPORTED_FORMULAS} from './supported-formulas';
1010

@@ -132,30 +132,41 @@ class Parser extends Emitter {
132132
}
133133

134134
/**
135-
* Retrieve value by its label (`B3`, `B$3`, `B$3`, `$B$3`).
135+
* Retrieve value by its label (`B3:A1`, `B$3:A1`, `B$3:$A1`, `$B$3:A$1`).
136136
*
137-
* @param {String} firstLabel Coordinates of the first cell.
138-
* @param {String} lastLabel Coordinates of the last cell.
137+
* @param {String} startLabel Coordinates of the first cell.
138+
* @param {String} endLabel Coordinates of the last cell.
139139
* @returns {Array} Returns an array of mixed values.
140140
* @private
141141
*/
142-
_callRangeValue(firstLabel, lastLabel) {
143-
const [firstRow, firstColumn] = extractLabel(firstLabel);
144-
const [lastRow, lastColumn] = extractLabel(lastLabel);
145-
146-
const firstCell = {
147-
label: firstLabel,
148-
row: firstRow,
149-
column: firstColumn,
150-
};
151-
const lastCell = {
152-
label: lastLabel,
153-
row: lastRow,
154-
column: lastColumn,
155-
};
142+
_callRangeValue(startLabel, endLabel) {
143+
const [startRow, startColumn] = extractLabel(startLabel);
144+
const [endRow, endColumn] = extractLabel(endLabel);
145+
let startCell = {};
146+
let endCell = {};
147+
148+
if (startRow.index <= endRow.index) {
149+
startCell.row = startRow;
150+
endCell.row = endRow;
151+
} else {
152+
startCell.row = endRow;
153+
endCell.row = startRow;
154+
}
155+
156+
if (startColumn.index <= endColumn.index) {
157+
startCell.column = startColumn;
158+
endCell.column = endColumn;
159+
} else {
160+
startCell.column = endColumn;
161+
endCell.column = startColumn;
162+
}
163+
164+
startCell.label = toLabel(startCell.row, startCell.column);
165+
endCell.label = toLabel(endCell.row, endCell.column);
166+
156167
let value = [];
157168

158-
this.emit('callRangeValue', firstCell, lastCell, (_value = []) => {
169+
this.emit('callRangeValue', startCell, endCell, (_value = []) => {
159170
value = _value;
160171
});
161172

test/unit/helper/cell.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {extractLabel, columnIndexToLabel, columnLabelToIndex} from '../../../src/helper/cell';
1+
import {extractLabel, toLabel, columnIndexToLabel, columnLabelToIndex, rowIndexToLabel, rowLabelToIndex} from '../../../src/helper/cell';
22

33
describe('.extractLabel()', () => {
44
it('should correctly extract coordinates', () => {
@@ -70,6 +70,16 @@ describe('.extractLabel()', () => {
7070
});
7171
});
7272

73+
describe('.toLabel()', () => {
74+
it('should correctly convert coords to label ', () => {
75+
expect(toLabel({index: 0, isAbsolute: false}, {index: 0, isAbsolute: false})).to.eq('A1');
76+
expect(toLabel({index: 0, isAbsolute: true}, {index: 0, isAbsolute: false})).to.eq('A$1');
77+
expect(toLabel({index: 0, isAbsolute: true}, {index: 0, isAbsolute: true})).to.eq('$A$1');
78+
expect(toLabel({index: 44, isAbsolute: true}, {index: 20, isAbsolute: true})).to.eq('$U$45');
79+
expect(toLabel({index: 1, isAbsolute: false}, {index: 20, isAbsolute: true})).to.eq('$U2');
80+
});
81+
});
82+
7383
describe('.columnIndexToLabel()', () => {
7484
it('should correctly convert column index to label ', () => {
7585
expect(columnIndexToLabel(-100)).to.eq('');
@@ -95,3 +105,25 @@ describe('.columnLabelToIndex()', () => {
95105
expect(columnLabelToIndex('NTQ')).to.eq(10000);
96106
});
97107
});
108+
109+
describe('.rowIndexToLabel()', () => {
110+
it('should correctly convert row index to label ', () => {
111+
expect(rowIndexToLabel(-100)).to.eq('');
112+
expect(rowIndexToLabel(-1)).to.eq('');
113+
expect(rowIndexToLabel(0)).to.eq('1');
114+
expect(rowIndexToLabel(1)).to.eq('2');
115+
expect(rowIndexToLabel(10)).to.eq('11');
116+
expect(rowIndexToLabel(100)).to.eq('101');
117+
});
118+
});
119+
120+
describe('.rowLabelToIndex()', () => {
121+
it('should correctly convert row label to index', () => {
122+
expect(rowLabelToIndex('')).to.eq(-1);
123+
expect(rowLabelToIndex('0')).to.eq(-1);
124+
expect(rowLabelToIndex('1')).to.eq(0);
125+
expect(rowLabelToIndex('2')).to.eq(1);
126+
expect(rowLabelToIndex('100')).to.eq(99);
127+
expect(rowLabelToIndex('92')).to.eq(91);
128+
});
129+
});

test/unit/index.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import * as lib from '../../index';
2+
3+
describe('Public API', () => {
4+
it('Parser should be defined', () => {
5+
expect(lib.Parser).to.be.a('function');
6+
});
7+
8+
it('SUPPORTED_FORMULAS should be defined', () => {
9+
expect(lib.SUPPORTED_FORMULAS).to.be.a('array');
10+
});
11+
12+
it('error should be defined', () => {
13+
expect(lib.error).to.be.a('function');
14+
});
15+
16+
it('extractLabel should be defined', () => {
17+
expect(lib.extractLabel).to.be.a('function');
18+
});
19+
20+
it('toLabel should be defined', () => {
21+
expect(lib.toLabel).to.be.a('function');
22+
});
23+
24+
it('columnIndexToLabel should be defined', () => {
25+
expect(lib.columnIndexToLabel).to.be.a('function');
26+
});
27+
28+
it('columnLabelToIndex should be defined', () => {
29+
expect(lib.columnLabelToIndex).to.be.a('function');
30+
});
31+
32+
it('rowIndexToLabel should be defined', () => {
33+
expect(lib.rowIndexToLabel).to.be.a('function');
34+
});
35+
36+
it('rowLabelToIndex should be defined', () => {
37+
expect(lib.rowLabelToIndex).to.be.a('function');
38+
});
39+
});

test/unit/parser.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,5 +290,45 @@ describe('Parser', () => {
290290
expect(parser._callRangeValue('A$1', '$D4')).to.deep.equal([['a', 'b'], ['z', 'd']]);
291291
expect(parser._callRangeValue('$A$1', '$E$5')).to.deep.equal([[true, false], [true, true]]);
292292
});
293+
294+
it('should convert coordinates in top-left bottom-right format (from bottom-left to top-right)', () => {
295+
const obj = {cb: function() {}};
296+
297+
spy(obj, 'cb');
298+
299+
parser.on('callRangeValue', obj.cb);
300+
parser._callRangeValue('$A$9', 'B2');
301+
302+
const startCell = {
303+
row: {index: 1, isAbsolute: false, label: '2'},
304+
column: {index: 0, isAbsolute: true, label: 'A'},
305+
};
306+
const endCell = {
307+
row: {index: 8, isAbsolute: true, label: '9'},
308+
column: {index: 1, isAbsolute: false, label: 'B'},
309+
};
310+
311+
sinon.assert.calledWithMatch(obj.cb, startCell, endCell);
312+
});
313+
314+
it('should convert coordinates in top-left bottom-right format (from top-right to bottom-left)', () => {
315+
const obj = {cb: function() {}};
316+
317+
spy(obj, 'cb');
318+
319+
parser.on('callRangeValue', obj.cb);
320+
parser._callRangeValue('B$2', 'A$8');
321+
322+
const startCell = {
323+
row: {index: 1, isAbsolute: true, label: '2'},
324+
column: {index: 0, isAbsolute: false, label: 'A'},
325+
};
326+
const endCell = {
327+
row: {index: 7, isAbsolute: true, label: '8'},
328+
column: {index: 1, isAbsolute: false, label: 'B'},
329+
};
330+
331+
sinon.assert.calledWithMatch(obj.cb, startCell, endCell);
332+
});
293333
});
294334
});

0 commit comments

Comments
 (0)