Skip to content

Commit 4908bfe

Browse files
authored
Merge pull request #155 from glideapps/fix-ffp-results
Don't return non-primitives from Excel
2 parents 5dc6fa9 + ad9c437 commit 4908bfe

1 file changed

Lines changed: 43 additions & 25 deletions

File tree

src/columns/fast-formula-parser.ts

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as glide from "../glide";
22

33
import FormulaParser, { FormulaHelpers, Types } from "fast-formula-parser";
44

5+
let data: any[][] = [];
6+
57
function convertCell(cell: any): any {
68
try {
79
if (typeof cell === "string") {
@@ -16,38 +18,50 @@ function convertCell(cell: any): any {
1618
}
1719
}
1820

19-
const run: glide.Column = (formula, ...params) => {
20-
const data: any[][] = params.map(p => [p.value]);
21-
22-
const parser = new FormulaParser({
23-
functions: {
24-
UPPER: text => {
25-
text = FormulaHelpers.accept(text, Types.STRING);
26-
return text.toUpperCase();
27-
},
28-
},
29-
onCell: ({ _, row, col }) => {
30-
return convertCell(data[row - 1][col - 1]);
21+
// We keep a single instance of this because it caches parsed formulas. Making
22+
// a new one for each invocation makes running lots of these about 2 order of
23+
// magnitude slower.
24+
const parser = new FormulaParser({
25+
functions: {
26+
UPPER: text => {
27+
text = FormulaHelpers.accept(text, Types.STRING);
28+
return text.toUpperCase();
3129
},
32-
onRange: (ref: { from: { row: number; col: number }; to: { row: number; col: number } }) => {
33-
const arr: any[][] = [];
34-
for (let row = ref.from.row; row <= ref.to.row; row++) {
35-
const innerArr: any[] = [];
36-
if (data[row - 1]) {
37-
for (let col = ref.from.col; col <= ref.to.col; col++) {
38-
innerArr.push(convertCell(data[row - 1][col - 1]));
39-
}
30+
},
31+
onCell: ({ _, row, col }) => {
32+
return convertCell(data[row - 1][col - 1]);
33+
},
34+
onRange: (ref: { from: { row: number; col: number }; to: { row: number; col: number } }) => {
35+
const arr: any[][] = [];
36+
for (let row = ref.from.row; row <= ref.to.row; row++) {
37+
const innerArr: any[] = [];
38+
if (data[row - 1]) {
39+
for (let col = ref.from.col; col <= ref.to.col; col++) {
40+
innerArr.push(convertCell(data[row - 1][col - 1]));
4041
}
41-
arr.push(innerArr);
4242
}
43-
return arr;
44-
},
45-
});
43+
arr.push(innerArr);
44+
}
45+
return arr;
46+
},
47+
});
4648

49+
const run: glide.Column = (formula, ...params) => {
4750
if (formula?.value === undefined) return undefined;
51+
52+
data = params.map(p => [p.value]);
53+
4854
const position = { row: 1, col: 1, sheet: 0 };
4955
try {
50-
return parser.parse(formula.value, position);
56+
const v = parser.parse(formula.value, position);
57+
// fast-formula-parser can return non-primitives such as arrays, but
58+
// also error objects, none of which we want to, or are allowed to,
59+
// return.
60+
if (typeof v === "number" || typeof v === "string" || typeof v === "boolean") {
61+
return v;
62+
} else {
63+
return undefined;
64+
}
5165
} catch (err) {}
5266
};
5367

@@ -100,5 +114,9 @@ export default glide.column({
100114
{ params: { formula: "SUM(A1, A2)", A1: 4, A2: "4" }, expectedResult: 8 },
101115
{ params: { formula: "SUM(A1, A2, 5)", A1: "5", A2: "10" }, expectedResult: 20 },
102116
{ params: { formula: 'UPPER("hello")' }, expectedResult: "HELLO" },
117+
{
118+
params: { formula: 'IF(ISBLANK(A1),"",REPLACE(A1,FIND(" ",A1),1,""))', A1: "Unknown" },
119+
expectedResult: undefined,
120+
},
103121
],
104122
});

0 commit comments

Comments
 (0)