Skip to content

Commit fcc3e21

Browse files
Copilotmathiasrw
andauthored
Fix async callback for XLSX export to close #107 (#2328)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mathiasrw <[email protected]>
1 parent 27486ca commit fcc3e21

File tree

2 files changed

+344
-2
lines changed

2 files changed

+344
-2
lines changed

src/833xlsx.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ alasql.into.XLSX = function (filename, opts, data, columns, cb) {
4545
alasql.utils.loadBinaryFile(opts.sourcefilename, !!cb, function (data) {
4646
wb = XLSX.read(data, {type: 'binary', ...alasql.options.excel, ...opts});
4747
doExport();
48+
if (cb) res = cb(res);
4849
});
4950
} else {
5051
doExport();
52+
/* Return result */
53+
if (cb) res = cb(res);
5154
}
5255

53-
/* Return result */
54-
if (cb) res = cb(res);
5556
return res;
5657

5758
/**

test/test107-B.js

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
var fs = require('fs');
5+
} else {
6+
__dirname = '.';
7+
}
8+
9+
describe('Test 107-B - Update existing Excel spreadsheet with sourcefilename and range', function () {
10+
if (typeof exports === 'object') {
11+
it('1. Create initial XLSX file with data', function (done) {
12+
var data = [
13+
{a: 1, b: 2, c: 3},
14+
{a: 4, b: 5, c: 6},
15+
{a: 7, b: 8, c: 9},
16+
];
17+
alasql('SELECT * INTO XLSX("' + __dirname + '/test107-B-base.xlsx", {headers:true}) FROM ?', [
18+
data,
19+
]);
20+
// Verify file was created and read back content
21+
assert(fs.existsSync(__dirname + '/test107-B-base.xlsx'));
22+
alasql(
23+
'SELECT * FROM XLSX("' + __dirname + '/test107-B-base.xlsx", {headers:true})',
24+
[],
25+
function (res) {
26+
assert.deepEqual(res, data);
27+
done();
28+
}
29+
);
30+
});
31+
32+
it('2. Update existing file at specific range with sourcefilename', function (done) {
33+
var updateData = [
34+
{x: 100, y: 200, z: 300},
35+
{x: 400, y: 500, z: 600},
36+
];
37+
38+
alasql(
39+
'SELECT * INTO XLSX("' +
40+
__dirname +
41+
'/test107-B-updated.xlsx", {sourcefilename:"' +
42+
__dirname +
43+
'/test107-B-base.xlsx", sheetid:"Sheet 1", range:"E5", headers:true}) FROM ?',
44+
[updateData],
45+
function (res) {
46+
assert(res == 1);
47+
// Verify updated file was created
48+
assert(fs.existsSync(__dirname + '/test107-B-updated.xlsx'));
49+
// Read back and verify content - check that original data is preserved at A1:C3
50+
alasql(
51+
'SELECT * FROM XLSX("' +
52+
__dirname +
53+
'/test107-B-updated.xlsx", {headers:true, sheetid:"Sheet 1", range:"A1:C4"})',
54+
[],
55+
function (original) {
56+
// Original data should still be there
57+
var expectedOriginal = [
58+
{a: 1, b: 2, c: 3},
59+
{a: 4, b: 5, c: 6},
60+
{a: 7, b: 8, c: 9},
61+
];
62+
assert.deepEqual(original, expectedOriginal);
63+
// Read the new data at E5:G6
64+
alasql(
65+
'SELECT * FROM XLSX("' +
66+
__dirname +
67+
'/test107-B-updated.xlsx", {headers:true, sheetid:"Sheet 1", range:"E5:G7"})',
68+
[],
69+
function (updated) {
70+
var expectedUpdated = [
71+
{x: 100, y: 200, z: 300},
72+
{x: 400, y: 500, z: 600},
73+
];
74+
assert.deepEqual(updated, expectedUpdated);
75+
done();
76+
}
77+
);
78+
}
79+
);
80+
}
81+
);
82+
});
83+
84+
it('3. Update existing file without headers at range B3', function (done) {
85+
var updateData = [
86+
{hour: 10, minute: 30, second: 45},
87+
{hour: 11, minute: 45, second: 20},
88+
];
89+
90+
alasql(
91+
'SELECT * INTO XLSX("' +
92+
__dirname +
93+
'/test107-B-no-headers.xlsx", {sourcefilename:"' +
94+
__dirname +
95+
'/test107-B-base.xlsx", sheetid:"Sheet 1", range:"B3", headers:false}) FROM ?',
96+
[updateData],
97+
function (res) {
98+
assert(res == 1);
99+
assert(fs.existsSync(__dirname + '/test107-B-no-headers.xlsx'));
100+
// Read back the data at B3:D4 (no headers, so will be read as columns B, C, D)
101+
alasql(
102+
'SELECT * FROM XLSX("' +
103+
__dirname +
104+
'/test107-B-no-headers.xlsx", {headers:false, sheetid:"Sheet 1", range:"B3:D4"})',
105+
[],
106+
function (result) {
107+
var expectedResult = [
108+
{B: 10, C: 30, D: 45},
109+
{B: 11, C: 45, D: 20},
110+
];
111+
assert.deepEqual(result, expectedResult);
112+
done();
113+
}
114+
);
115+
}
116+
);
117+
});
118+
119+
it('4. Overwrite same file with sourcefilename pointing to itself', function (done) {
120+
// First create a file
121+
var initialData = [{name: 'John', age: 25}];
122+
alasql('SELECT * INTO XLSX("' + __dirname + '/test107-B-self.xlsx", {headers:true}) FROM ?', [
123+
initialData,
124+
]);
125+
126+
// Then update it in place
127+
var newData = [{value: 999, status: 'updated'}];
128+
alasql(
129+
'SELECT * INTO XLSX("' +
130+
__dirname +
131+
'/test107-B-self.xlsx", {sourcefilename:"' +
132+
__dirname +
133+
'/test107-B-self.xlsx", sheetid:"Sheet 1", range:"D10", headers:true}) FROM ?',
134+
[newData],
135+
function (res) {
136+
assert(res == 1);
137+
assert(fs.existsSync(__dirname + '/test107-B-self.xlsx'));
138+
// Read back and verify both original and new data exist
139+
alasql(
140+
'SELECT * FROM XLSX("' +
141+
__dirname +
142+
'/test107-B-self.xlsx", {headers:true, sheetid:"Sheet 1", range:"A1:B2"})',
143+
[],
144+
function (original) {
145+
// Original data should be at A1:B1
146+
var expectedOriginal = [{name: 'John', age: 25}];
147+
assert.deepEqual(original, expectedOriginal);
148+
// Read the new data at D10:E10
149+
alasql(
150+
'SELECT * FROM XLSX("' +
151+
__dirname +
152+
'/test107-B-self.xlsx", {headers:true, sheetid:"Sheet 1", range:"D10:E11"})',
153+
[],
154+
function (updated) {
155+
var expectedUpdated = [{value: 999, status: 'updated'}];
156+
assert.deepEqual(updated, expectedUpdated);
157+
done();
158+
}
159+
);
160+
}
161+
);
162+
}
163+
);
164+
});
165+
166+
it('5. Add data to new sheet in existing file', function (done) {
167+
var newSheetData = [
168+
{col1: 'A', col2: 'B'},
169+
{col1: 'C', col2: 'D'},
170+
];
171+
172+
alasql(
173+
'SELECT * INTO XLSX("' +
174+
__dirname +
175+
'/test107-B-newsheet.xlsx", {sourcefilename:"' +
176+
__dirname +
177+
'/test107-B-base.xlsx", sheetid:"NewSheet", range:"A1", headers:true}) FROM ?',
178+
[newSheetData],
179+
function (res) {
180+
assert(res == 1);
181+
assert(fs.existsSync(__dirname + '/test107-B-newsheet.xlsx'));
182+
// Verify the new sheet has the correct data
183+
alasql(
184+
'SELECT * FROM XLSX("' +
185+
__dirname +
186+
'/test107-B-newsheet.xlsx", {headers:true, sheetid:"NewSheet"})',
187+
[],
188+
function (result) {
189+
assert.deepEqual(result, newSheetData);
190+
// Also verify original sheet still exists
191+
alasql(
192+
'SELECT * FROM XLSX("' +
193+
__dirname +
194+
'/test107-B-newsheet.xlsx", {headers:true, sheetid:"Sheet 1"})',
195+
[],
196+
function (original) {
197+
assert.equal(original.length, 3);
198+
assert.equal(original[0].a, 1);
199+
done();
200+
}
201+
);
202+
}
203+
);
204+
}
205+
);
206+
});
207+
208+
it('6. Test with various range positions (AA5)', function (done) {
209+
var testData = [{test: 'value'}];
210+
211+
// Test range AA5 (multi-letter column)
212+
alasql(
213+
'SELECT * INTO XLSX("' +
214+
__dirname +
215+
'/test107-B-range-AA5.xlsx", {sourcefilename:"' +
216+
__dirname +
217+
'/test107-B-base.xlsx", sheetid:"Sheet 1", range:"AA5", headers:false}) FROM ?',
218+
[testData],
219+
function (res) {
220+
assert(res == 1);
221+
assert(fs.existsSync(__dirname + '/test107-B-range-AA5.xlsx'));
222+
// Read back the data at AA5 (column 27)
223+
alasql(
224+
'SELECT * FROM XLSX("' +
225+
__dirname +
226+
'/test107-B-range-AA5.xlsx", {headers:false, sheetid:"Sheet 1", range:"AA5:AA5"})',
227+
[],
228+
function (result) {
229+
var expectedResult = [{AA: 'value'}];
230+
assert.deepEqual(result, expectedResult);
231+
done();
232+
}
233+
);
234+
}
235+
);
236+
});
237+
238+
it('7. Test async/promise flow for sourcefilename and range', async function () {
239+
// Create test data
240+
var testData = [
241+
{name: 'Alice', score: 95},
242+
{name: 'Bob', score: 87},
243+
];
244+
245+
// Write initial file using promise
246+
await alasql.promise(
247+
'SELECT * INTO XLSX("' + __dirname + '/test107-B-async.xlsx", {headers:true}) FROM ?',
248+
[testData]
249+
);
250+
251+
// Update file at specific range using promise
252+
var updateData = [{extra: 'data', value: 123}];
253+
await alasql.promise(
254+
'SELECT * INTO XLSX("' +
255+
__dirname +
256+
'/test107-B-async.xlsx", {sourcefilename:"' +
257+
__dirname +
258+
'/test107-B-async.xlsx", sheetid:"Sheet 1", range:"D5", headers:true}) FROM ?',
259+
[updateData]
260+
);
261+
262+
// Read back and verify using promise
263+
var original = await alasql.promise(
264+
'SELECT * FROM XLSX("' +
265+
__dirname +
266+
'/test107-B-async.xlsx", {headers:true, sheetid:"Sheet 1", range:"A1:B3"})',
267+
[]
268+
);
269+
assert.deepEqual(original, testData);
270+
271+
// Read the updated data
272+
var updated = await alasql.promise(
273+
'SELECT * FROM XLSX("' +
274+
__dirname +
275+
'/test107-B-async.xlsx", {headers:true, sheetid:"Sheet 1", range:"D5:E6"})',
276+
[]
277+
);
278+
assert.deepEqual(updated, updateData);
279+
});
280+
281+
it('8. Test promise-based flow with new sheet creation', async function () {
282+
var sheet1Data = [{id: 1, value: 'first'}];
283+
var sheet2Data = [{id: 2, value: 'second'}];
284+
285+
// Create initial file
286+
await alasql.promise(
287+
'SELECT * INTO XLSX("' + __dirname + '/test107-B-promise.xlsx", {headers:true}) FROM ?',
288+
[sheet1Data]
289+
);
290+
291+
// Add new sheet using sourcefilename
292+
await alasql.promise(
293+
'SELECT * INTO XLSX("' +
294+
__dirname +
295+
'/test107-B-promise.xlsx", {sourcefilename:"' +
296+
__dirname +
297+
'/test107-B-promise.xlsx", sheetid:"Sheet2", range:"A1", headers:true}) FROM ?',
298+
[sheet2Data]
299+
);
300+
301+
// Verify Sheet 1
302+
var result1 = await alasql.promise(
303+
'SELECT * FROM XLSX("' +
304+
__dirname +
305+
'/test107-B-promise.xlsx", {headers:true, sheetid:"Sheet 1"})',
306+
[]
307+
);
308+
assert.deepEqual(result1, sheet1Data);
309+
310+
// Verify Sheet 2
311+
var result2 = await alasql.promise(
312+
'SELECT * FROM XLSX("' +
313+
__dirname +
314+
'/test107-B-promise.xlsx", {headers:true, sheetid:"Sheet2"})',
315+
[]
316+
);
317+
assert.deepEqual(result2, sheet2Data);
318+
});
319+
320+
// Cleanup test files after all tests
321+
after(function () {
322+
var testFiles = [
323+
'test107-B-base.xlsx',
324+
'test107-B-updated.xlsx',
325+
'test107-B-no-headers.xlsx',
326+
'test107-B-self.xlsx',
327+
'test107-B-newsheet.xlsx',
328+
'test107-B-range-AA5.xlsx',
329+
'test107-B-async.xlsx',
330+
'test107-B-promise.xlsx',
331+
];
332+
333+
testFiles.forEach(function (file) {
334+
var filePath = __dirname + '/' + file;
335+
if (fs.existsSync(filePath)) {
336+
fs.unlinkSync(filePath);
337+
}
338+
});
339+
});
340+
}
341+
});

0 commit comments

Comments
 (0)