Skip to content

Commit 77159f0

Browse files
committed
Tests and bug fixes
1 parent 9226446 commit 77159f0

File tree

2 files changed

+168
-9
lines changed

2 files changed

+168
-9
lines changed

src/xlsx.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ export class ExcelWorkbook {
1616

1717
function extract(sheet, {range, headers}) {
1818
let [[c0, r0], [c1, r1]] = parseRange(range, sheet);
19-
const output = new Array(r1 - r0).fill({});
20-
2119
const headerRow = headers && sheet._rows[r0++];
2220
const seen = new Set();
2321
const names = [];
@@ -30,13 +28,14 @@ function extract(sheet, {range, headers}) {
3028
return names[n];
3129
}
3230

33-
for (let r = r0; r < r1; r++) {
31+
const output = new Array(r1 - r0 + 1).fill({});
32+
for (let r = r0; r <= r1; r++) {
3433
const _row = sheet._rows[r];
3534
if (!_row || !_row.hasValues) continue;
3635
const row = (output[r - r0] = {});
37-
for (let c = c0; c < c1; c++) {
36+
for (let c = c0; c <= c1; c++) {
3837
const value = valueOf(_row._cells[c]);
39-
if (value) row[name(c)] = value;
38+
if (value !== null && value !== undefined) row[name(c)] = value;
4039
}
4140
}
4241

@@ -58,15 +57,19 @@ function valueOf(cell) {
5857

5958
function parseRange(specifier = [], {columnCount, rowCount}) {
6059
if (typeof specifier === "string") {
61-
const [[c0 = 0, r0 = 0] = [], [c1 = columnCount, r1 = rowCount] = []] =
62-
specifier.split(":").map(NN);
60+
const [
61+
[c0 = 0, r0 = 0] = [],
62+
[c1 = columnCount - 1, r1 = rowCount - 1] = [],
63+
] = specifier.split(":").map(NN);
6364
return [
6465
[c0, r0],
6566
[c1, r1],
6667
];
6768
} else if (typeof specifier === "object") {
68-
const [[c0 = 0, r0 = 0] = [], [c1 = columnCount, r1 = rowCount] = []] =
69-
specifier;
69+
const [
70+
[c0 = 0, r0 = 0] = [],
71+
[c1 = columnCount - 1, r1 = rowCount - 1] = [],
72+
] = specifier;
7073
return [
7174
[c0, r0],
7275
[c1, r1],

test/xlsx-test.js

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import {test} from "tap";
2+
import {ExcelWorkbook} from "../src/xlsx.js";
3+
4+
function mockWorkbook(contents) {
5+
return {
6+
worksheets: Object.keys(contents).map((name) => ({name})),
7+
getWorksheet(name) {
8+
const _rows = contents[name];
9+
return {
10+
_rows: _rows.map((row) => ({
11+
_cells: row.map((cell) => ({value: cell})),
12+
hasValues: !!row.length,
13+
})),
14+
rowCount: _rows.length,
15+
columnCount: Math.max(..._rows.map((r) => r.length)),
16+
};
17+
},
18+
};
19+
}
20+
21+
test("FileAttachment.xlsx reads sheet names", (t) => {
22+
const workbook = new ExcelWorkbook(mockWorkbook({Sheet1: []}));
23+
t.same(workbook.sheetNames(), ["Sheet1"]);
24+
t.end();
25+
});
26+
27+
test("FileAttachment.xlsx reads sheets", (t) => {
28+
const workbook = new ExcelWorkbook(
29+
mockWorkbook({
30+
Sheet1: [
31+
["one", "two", "three"],
32+
[1, 2, 3],
33+
],
34+
})
35+
);
36+
t.same(workbook.sheet(0), [
37+
{A: "one", B: "two", C: "three"},
38+
{A: 1, B: 2, C: 3},
39+
]);
40+
t.end();
41+
});
42+
43+
test("FileAttachment.xlsx reads sheets with different types", (t) => {
44+
const workbook = new ExcelWorkbook(
45+
mockWorkbook({
46+
Sheet1: [
47+
["one", {richText: [{text: "two"}, {text: "three"}]}],
48+
[
49+
{text: "link", hyperlink: "https://example.com"},
50+
2,
51+
{formula: "=B2*5", result: 10},
52+
],
53+
],
54+
})
55+
);
56+
t.same(workbook.sheet(0), [
57+
{A: "one", B: "twothree"},
58+
{A: `<a href="https://example.com">link</a>`, B: 2, C: 10},
59+
]);
60+
t.end();
61+
});
62+
63+
test("FileAttachment.xlsx reads sheets with headers", (t) => {
64+
const workbook = new ExcelWorkbook(
65+
mockWorkbook({
66+
Sheet1: [
67+
["one", "one", "one", "two"],
68+
[1, null, 3, 4],
69+
[5, 6, 7, 8],
70+
],
71+
})
72+
);
73+
t.same(workbook.sheet(0, {headers: true}), [
74+
{one: 1, one_: 3, two: 4},
75+
{one: 5, one__: 6, one_: 7, two: 8},
76+
]);
77+
t.end();
78+
});
79+
80+
test("FileAttachment.xlsx reads sheet ranges", (t) => {
81+
const workbook = new ExcelWorkbook(
82+
mockWorkbook({
83+
Sheet1: [
84+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
85+
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
86+
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
87+
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
88+
],
89+
})
90+
);
91+
92+
// undefined
93+
// ""
94+
// []
95+
const entireSheet = [
96+
{A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9},
97+
{A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, G: 16, H: 17, I: 18, J: 19},
98+
{A: 20, B: 21, C: 22, D: 23, E: 24, F: 25, G: 26, H: 27, I: 28, J: 29},
99+
{A: 30, B: 31, C: 32, D: 33, E: 34, F: 35, G: 36, H: 37, I: 38, J: 39},
100+
];
101+
t.same(workbook.sheet(0), entireSheet);
102+
t.same(workbook.sheet(0, {range: ""}), entireSheet);
103+
t.same(workbook.sheet(0, {range: []}), entireSheet);
104+
105+
// "B2:C3"
106+
// [[1,1],[2,2]]
107+
t.same(workbook.sheet(0, {range: "B2:C3"}), [
108+
{B: 11, C: 12},
109+
{B: 21, C: 22},
110+
]);
111+
t.same(
112+
workbook.sheet(0, {
113+
range: [
114+
[1, 1],
115+
[2, 2],
116+
],
117+
}),
118+
[
119+
{B: 11, C: 12},
120+
{B: 21, C: 22},
121+
]
122+
);
123+
124+
// ":C3"
125+
// [,[2,2]]
126+
t.same(workbook.sheet(0, {range: ":C3"}), [
127+
{A: 0, B: 1, C: 2},
128+
{A: 10, B: 11, C: 12},
129+
{A: 20, B: 21, C: 22},
130+
]);
131+
t.same(workbook.sheet(0, {range: [undefined, [2, 2]]}), [
132+
{A: 0, B: 1, C: 2},
133+
{A: 10, B: 11, C: 12},
134+
{A: 20, B: 21, C: 22},
135+
]);
136+
137+
// "B2"
138+
// [[1,1]]
139+
t.same(workbook.sheet(0, {range: "B2"}), [
140+
{B: 11, C: 12, D: 13, E: 14, F: 15, G: 16, H: 17, I: 18, J: 19},
141+
{B: 21, C: 22, D: 23, E: 24, F: 25, G: 26, H: 27, I: 28, J: 29},
142+
{B: 31, C: 32, D: 33, E: 34, F: 35, G: 36, H: 37, I: 38, J: 39},
143+
]);
144+
t.same(workbook.sheet(0, {range: [[1, 1]]}), [
145+
{B: 11, C: 12, D: 13, E: 14, F: 15, G: 16, H: 17, I: 18, J: 19},
146+
{B: 21, C: 22, D: 23, E: 24, F: 25, G: 26, H: 27, I: 28, J: 29},
147+
{B: 31, C: 32, D: 33, E: 34, F: 35, G: 36, H: 37, I: 38, J: 39},
148+
]);
149+
150+
// "2"
151+
// [[,1]]
152+
t.same(workbook.sheet(0, {range: "2"}), entireSheet.slice(1));
153+
t.same(workbook.sheet(0, {range: [[undefined, 1]]}), entireSheet.slice(1));
154+
155+
t.end();
156+
});

0 commit comments

Comments
 (0)