From d9047630a8cd6bc52cc31ae965d090c829ee6604 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:55:05 +0000 Subject: [PATCH 1/4] Initial plan From c00f4fb164be32692d0c87426746cd015b669ccc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 01:07:30 +0000 Subject: [PATCH 2/4] Implement multi-sheet XLSX import support - Add support for importing all sheets using sheetid: "*" - Add support for importing specific sheets using sheetid: [sheet1, sheet2, ...] - Returns flat array with _sheet property added to each row - Maintains backward compatibility with single sheet imports - All existing XLSX tests pass Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> --- src/84from.js | 161 ++++++++++++++++++++------------- test/test-multisheet-import.js | 134 +++++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 61 deletions(-) create mode 100644 test/test-multisheet-import.js diff --git a/src/84from.js b/src/84from.js index 3eb6dea3c1..e40392b89a 100755 --- a/src/84from.js +++ b/src/84from.js @@ -440,6 +440,71 @@ function XLSXLSX(X, filename, opts, cb, idx, query) { return text; } } + + function processSheet(workbook, sheetid, sheetOpt) { + var range; + var sheetRes = []; + if (typeof sheetOpt.range === 'undefined') { + range = workbook.Sheets[sheetid]['!ref']; + } else { + range = sheetOpt.range; + if (workbook.Sheets[sheetid][range]) { + range = workbook.Sheets[sheetid][range]; + } + } + // if range has some value then data is present in the current sheet + // else current sheet is empty + if (range) { + var rg = range.split(':'); + var col0 = rg[0].match(/[A-Z]+/)[0]; + var row0 = +rg[0].match(/[0-9]+/)[0]; + var col1 = rg[1].match(/[A-Z]+/)[0]; + var row1 = +rg[1].match(/[0-9]+/)[0]; + + var hh = {}; + var xlscnCol0 = alasql.utils.xlscn(col0); + var xlscnCol1 = alasql.utils.xlscn(col1); + for (var j = xlscnCol0; j <= xlscnCol1; j++) { + var col = alasql.utils.xlsnc(j); + if (sheetOpt.headers) { + if (workbook.Sheets[sheetid][col + '' + row0]) { + hh[col] = getHeaderText(workbook.Sheets[sheetid][col + '' + row0].v); + } else { + hh[col] = getHeaderText(col); + } + } else { + hh[col] = col; + } + } + if (sheetOpt.headers) { + row0++; + } + for (var i = row0; i <= row1; i++) { + var row = {}; + for (var j = xlscnCol0; j <= xlscnCol1; j++) { + var col = alasql.utils.xlsnc(j); + if (workbook.Sheets[sheetid][col + '' + i]) { + row[hh[col]] = workbook.Sheets[sheetid][col + '' + i].v; + } + } + sheetRes.push(row); + } + } else { + sheetRes.push([]); + } + + // Remove last empty line (issue #548) + if ( + sheetRes.length > 0 && + sheetRes[sheetRes.length - 1] && + Object.keys(sheetRes[sheetRes.length - 1]).length == 0 + ) { + sheetRes.pop(); + } + + return sheetRes; + } + filename = alasql.utils.autoExtFilename(filename, 'xls', opts); alasql.utils.loadBinaryFile( filename, @@ -460,71 +525,45 @@ function XLSXLSX(X, filename, opts, cb, idx, query) { ...opts, }); } - // console.log(workbook); - var sheetid; - if (typeof opt.sheetid === 'undefined') { - sheetid = workbook.SheetNames[0]; - } else if (typeof opt.sheetid === 'number') { - sheetid = workbook.SheetNames[opt.sheetid]; - } else { - sheetid = opt.sheetid; - } - var range; - var res = []; - if (typeof opt.range === 'undefined') { - range = workbook.Sheets[sheetid]['!ref']; - } else { - range = opt.range; - if (workbook.Sheets[sheetid][range]) { - range = workbook.Sheets[sheetid][range]; - } - } - // if range has some value then data is present in the current sheet - // else current sheet is empty - if (range) { - var rg = range.split(':'); - var col0 = rg[0].match(/[A-Z]+/)[0]; - var row0 = +rg[0].match(/[0-9]+/)[0]; - var col1 = rg[1].match(/[A-Z]+/)[0]; - var row1 = +rg[1].match(/[0-9]+/)[0]; - // console.log(114,rg,col0,col1,row0,row1); - // console.log(114,rg,alasql.utils.xlscn(col0),alasql.utils.xlscn(col1)); - - var hh = {}; - var xlscnCol0 = alasql.utils.xlscn(col0); - var xlscnCol1 = alasql.utils.xlscn(col1); - for (var j = xlscnCol0; j <= xlscnCol1; j++) { - var col = alasql.utils.xlsnc(j); - if (opt.headers) { - if (workbook.Sheets[sheetid][col + '' + row0]) { - hh[col] = getHeaderText(workbook.Sheets[sheetid][col + '' + row0].v); - } else { - hh[col] = getHeaderText(col); - } - } else { - hh[col] = col; - } - } - if (opt.headers) { - row0++; - } - for (var i = row0; i <= row1; i++) { - var row = {}; - for (var j = xlscnCol0; j <= xlscnCol1; j++) { - var col = alasql.utils.xlsnc(j); - if (workbook.Sheets[sheetid][col + '' + i]) { - row[hh[col]] = workbook.Sheets[sheetid][col + '' + i].v; + + // Check if we should process multiple sheets + var shouldProcessMultipleSheets = + opt.sheetid === '*' || (Array.isArray(opt.sheetid) && opt.sheetid.length > 0); + + if (shouldProcessMultipleSheets) { + // Process multiple sheets and combine into a single array + res = []; + var sheetsToProcess = + opt.sheetid === '*' ? workbook.SheetNames : opt.sheetid; + + for (var s = 0; s < sheetsToProcess.length; s++) { + var currentSheetId = + opt.sheetid === '*' + ? sheetsToProcess[s] + : typeof sheetsToProcess[s] === 'number' + ? workbook.SheetNames[sheetsToProcess[s]] + : sheetsToProcess[s]; + + if (workbook.Sheets[currentSheetId]) { + var sheetData = processSheet(workbook, currentSheetId, opt); + // Add sheet name to each row + for (var r = 0; r < sheetData.length; r++) { + sheetData[r]._sheet = currentSheetId; } + res = res.concat(sheetData); } - res.push(row); } } else { - res.push([]); - } - - // Remove last empty line (issue #548) - if (res.length > 0 && res[res.length - 1] && Object.keys(res[res.length - 1]).length == 0) { - res.pop(); + // Process single sheet (original behavior) + var sheetid; + if (typeof opt.sheetid === 'undefined') { + sheetid = workbook.SheetNames[0]; + } else if (typeof opt.sheetid === 'number') { + sheetid = workbook.SheetNames[opt.sheetid]; + } else { + sheetid = opt.sheetid; + } + res = processSheet(workbook, sheetid, opt); } if (cb) { diff --git a/test/test-multisheet-import.js b/test/test-multisheet-import.js new file mode 100644 index 0000000000..54840ee94b --- /dev/null +++ b/test/test-multisheet-import.js @@ -0,0 +1,134 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('..'); + var path = require('path'); + var dirname = path.normalize(__dirname) + '/'; +} else { + var dirname = './'; +} + +describe('Test multi-sheet XLSX import', function () { + it('1. Import all sheets using sheetid: "*"', function (done) { + alasql( + 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:"*"})', + [], + function (data) { + // Should return a flat array with _sheet property on each row + assert(Array.isArray(data)); + assert(data.length > 0); + // Check that _sheet property exists + assert(data[0]._sheet); + // Should have rows from both sheets + var sheet1Rows = data.filter(function (row) { + return row._sheet === 'Sheet1'; + }); + var sheet2Rows = data.filter(function (row) { + return row._sheet === 'Sheet2'; + }); + assert(sheet1Rows.length === 3); + assert(sheet2Rows.length === 4); + done(); + } + ); + }); + + it('2. Import multiple specific sheets using sheetid array', function (done) { + alasql( + 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:?})', + [['Sheet1', 'Sheet2']], + function (data) { + // Should return a flat array with _sheet property + assert(Array.isArray(data)); + assert(data.length === 7); // 3 + 4 rows + assert(data[0]._sheet); + done(); + } + ); + }); + + it('3. Import specific sheets by index using sheetid array', function (done) { + alasql( + 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:?})', + [[0, 1]], + function (data) { + // Should return a flat array with _sheet property + assert(Array.isArray(data)); + assert(data.length === 7); // 3 + 4 rows + assert(data[0]._sheet === 'Sheet1'); + done(); + } + ); + }); + + it('4. Original single sheet behavior should still work', function (done) { + alasql( + 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true})', + [], + function (data) { + // Should return an array (original behavior) + assert(Array.isArray(data)); + assert(data.length === 3); + // Should not have _sheet property + assert(!data[0]._sheet); + done(); + } + ); + }); + + it('5. Original single sheet with explicit sheetid should still work', function (done) { + alasql( + 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:"Sheet2"})', + [], + function (data) { + // Should return an array (original behavior) + assert(Array.isArray(data)); + assert(data.length === 4); + assert(data[3].five === 800); + // Should not have _sheet property + assert(!data[0]._sheet); + done(); + } + ); + }); + + it('6. Query rows from specific sheet using WHERE clause', function (done) { + alasql( + 'select * from xlsx("' + + dirname + + 'test242.xlsx", {headers:true, sheetid:"*"}) WHERE _sheet = "Sheet2"', + [], + function (data) { + // Should only return rows from Sheet2 + assert(Array.isArray(data)); + assert(data.length === 4); + assert(data.every(function (row) { + return row._sheet === 'Sheet2'; + })); + done(); + } + ); + }); + + it('7. Count rows per sheet', function (done) { + // First get the data, then query it + alasql( + 'SELECT * FROM xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:"*"})', + [], + function (allData) { + // Now count using a separate query + var counts = alasql('SELECT [_sheet], COUNT(*) FROM ? GROUP BY [_sheet]', [allData]); + assert(Array.isArray(counts)); + assert(counts.length === 2); + var sheet1 = counts.find(function (row) { + return row._sheet === 'Sheet1'; + }); + var sheet2 = counts.find(function (row) { + return row._sheet === 'Sheet2'; + }); + assert(sheet1['COUNT(*)'] === 3); + assert(sheet2['COUNT(*)'] === 4); + done(); + } + ); + }); +}); From d356fda2be3cccf044642a4f1aac094f0f0f199c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 01:08:06 +0000 Subject: [PATCH 3/4] Format code with Prettier Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> --- src/84from.js | 3 +-- test/test-multisheet-import.js | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/84from.js b/src/84from.js index e40392b89a..2345a46df5 100755 --- a/src/84from.js +++ b/src/84from.js @@ -533,8 +533,7 @@ function XLSXLSX(X, filename, opts, cb, idx, query) { if (shouldProcessMultipleSheets) { // Process multiple sheets and combine into a single array res = []; - var sheetsToProcess = - opt.sheetid === '*' ? workbook.SheetNames : opt.sheetid; + var sheetsToProcess = opt.sheetid === '*' ? workbook.SheetNames : opt.sheetid; for (var s = 0; s < sheetsToProcess.length; s++) { var currentSheetId = diff --git a/test/test-multisheet-import.js b/test/test-multisheet-import.js index 54840ee94b..35e6bff318 100644 --- a/test/test-multisheet-import.js +++ b/test/test-multisheet-import.js @@ -101,9 +101,11 @@ describe('Test multi-sheet XLSX import', function () { // Should only return rows from Sheet2 assert(Array.isArray(data)); assert(data.length === 4); - assert(data.every(function (row) { - return row._sheet === 'Sheet2'; - })); + assert( + data.every(function (row) { + return row._sheet === 'Sheet2'; + }) + ); done(); } ); From 620505ffb38ee4d4f899f601073a7428fa7242a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 05:46:25 +0000 Subject: [PATCH 4/4] Rename test file to test848.js and create dedicated test848.xlsx file - Renamed test-multisheet-import.js to test848.js - Created dedicated test848.xlsx file (copied from test242.xlsx) - Updated all test references to use test848.xlsx instead of test242.xlsx - All 7 tests passing Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> --- test/{test-multisheet-import.js => test848.js} | 16 ++++++++-------- test/test848.xlsx | Bin 0 -> 38356 bytes 2 files changed, 8 insertions(+), 8 deletions(-) rename test/{test-multisheet-import.js => test848.js} (86%) create mode 100644 test/test848.xlsx diff --git a/test/test-multisheet-import.js b/test/test848.js similarity index 86% rename from test/test-multisheet-import.js rename to test/test848.js index 35e6bff318..24e5180b29 100644 --- a/test/test-multisheet-import.js +++ b/test/test848.js @@ -7,10 +7,10 @@ if (typeof exports === 'object') { var dirname = './'; } -describe('Test multi-sheet XLSX import', function () { +describe('Test 848 - Multi-sheet XLSX import', function () { it('1. Import all sheets using sheetid: "*"', function (done) { alasql( - 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:"*"})', + 'select * from xlsx("' + dirname + 'test848.xlsx", {headers:true, sheetid:"*"})', [], function (data) { // Should return a flat array with _sheet property on each row @@ -34,7 +34,7 @@ describe('Test multi-sheet XLSX import', function () { it('2. Import multiple specific sheets using sheetid array', function (done) { alasql( - 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:?})', + 'select * from xlsx("' + dirname + 'test848.xlsx", {headers:true, sheetid:?})', [['Sheet1', 'Sheet2']], function (data) { // Should return a flat array with _sheet property @@ -48,7 +48,7 @@ describe('Test multi-sheet XLSX import', function () { it('3. Import specific sheets by index using sheetid array', function (done) { alasql( - 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:?})', + 'select * from xlsx("' + dirname + 'test848.xlsx", {headers:true, sheetid:?})', [[0, 1]], function (data) { // Should return a flat array with _sheet property @@ -62,7 +62,7 @@ describe('Test multi-sheet XLSX import', function () { it('4. Original single sheet behavior should still work', function (done) { alasql( - 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true})', + 'select * from xlsx("' + dirname + 'test848.xlsx", {headers:true})', [], function (data) { // Should return an array (original behavior) @@ -77,7 +77,7 @@ describe('Test multi-sheet XLSX import', function () { it('5. Original single sheet with explicit sheetid should still work', function (done) { alasql( - 'select * from xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:"Sheet2"})', + 'select * from xlsx("' + dirname + 'test848.xlsx", {headers:true, sheetid:"Sheet2"})', [], function (data) { // Should return an array (original behavior) @@ -95,7 +95,7 @@ describe('Test multi-sheet XLSX import', function () { alasql( 'select * from xlsx("' + dirname + - 'test242.xlsx", {headers:true, sheetid:"*"}) WHERE _sheet = "Sheet2"', + 'test848.xlsx", {headers:true, sheetid:"*"}) WHERE _sheet = "Sheet2"', [], function (data) { // Should only return rows from Sheet2 @@ -114,7 +114,7 @@ describe('Test multi-sheet XLSX import', function () { it('7. Count rows per sheet', function (done) { // First get the data, then query it alasql( - 'SELECT * FROM xlsx("' + dirname + 'test242.xlsx", {headers:true, sheetid:"*"})', + 'SELECT * FROM xlsx("' + dirname + 'test848.xlsx", {headers:true, sheetid:"*"})', [], function (allData) { // Now count using a separate query diff --git a/test/test848.xlsx b/test/test848.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..44aea2dc866f807fbfe2a74d64bcdce8c7b5035a GIT binary patch literal 38356 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