UNPKG

xlrd-parser

Version:

High performance Excel file parser based on the xlrd library from www.python-excel.org.

328 lines (267 loc) 10.8 kB
var async = require('async'), expect = require('chai').expect, xlrd = require('../lib/xlrd'), sampleFiles = [ // OO XML workbook (Excel 2003 and later) 'test/sample.xlsx', // Legacy binary format (before Excel 2003) 'test/sample.xls' ]; describe('xlrd', function () { describe('parse()', function () { it('should load a workbook/sheet/row/cell structure', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; expect(workbook).not.be.null; expect(workbook.file).to.equal(file); expect(workbook.meta.user).to.equal('Nicolas Mercier-Gaboury'); expect(workbook.meta.sheets.length).to.equal(2); expect(workbook.meta.sheets).to.contain('Sheet1').and.to.contain('second sheet'); expect(workbook.sheets).to.be.an('array').and.have.length(workbook.meta.sheets.length); workbook.sheets.forEach(function (sheet, index) { expect(sheet).to.have.property('index', index); expect(sheet).to.have.property('name', index === 0 ? 'Sheet1' : 'second sheet'); expect(sheet).to.have.property('bounds').and.to.be.an('object'); expect(sheet).to.have.property('visibility', 'visible'); expect(sheet).to.have.property('rows').and.have.length(sheet.bounds.rows); expect(sheet).to.equal(workbook.sheets[index]).and.to.equal(workbook.sheets[sheet.name]); if (index === 0) { expect(sheet.bounds).to.have.property('columns', 8); expect(sheet.bounds).to.have.property('rows', 51); } else if (index === 1) { expect(sheet.bounds).to.have.property('columns', 3); expect(sheet.bounds).to.have.property('rows', 1384); } sheet.rows.forEach(function (row) { expect(row).to.be.an('array').and.have.length(sheet.bounds.columns); expect(row).to.have.deep.property('[0].row'); expect(row).to.have.deep.property('[0].column'); expect(row).to.have.deep.property('[0].address'); expect(row).to.have.deep.property('[0].value'); }); }); return next(); }); }, done); }); it('should parse cell addresses', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; var rows = workbook.sheets[0].rows; expect(rows[0][0]).to.have.property('address', 'A1'); expect(rows[0][4]).to.have.property('address', 'E1'); expect(rows[5][0]).to.have.property('address', 'A6'); expect(rows[5][4]).to.have.property('address', 'E6'); expect(rows[50][0]).to.have.property('address', 'A51'); expect(rows[50][4]).to.have.property('address', 'E51'); return next(); }); }, done); }); it('should parse numeric values', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; var row1 = workbook.sheets[0].rows[1], row2 = workbook.sheets[0].rows[2], row3 = workbook.sheets[0].rows[3], row4 = workbook.sheets[0].rows[4], row5 = workbook.sheets[0].rows[5]; [row1, row2, row3, row4, row5].forEach(function (row) { expect(row[0].value).to.be.a('number'); expect(row[1].value).to.be.a('number'); }) expect(row1[0].value).to.equal(1); expect(row1[1].value).to.equal(1.0001); expect(row2[0].value).to.equal(2); expect(row2[1].value).to.equal(2); expect(row3[0].value).to.equal(3); expect(row3[1].value).to.equal(3.00967676764465); expect(row4[0].value).to.equal(4); expect(row4[1].value).to.equal(0); expect(row5[0].value).to.equal(5); expect(row5[1].value).to.equal(5.00005); return next(); }); }, done); }); it('should parse string values', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; var cell1 = workbook.sheets[0].rows[1][2], cell2 = workbook.sheets[0].rows[2][2], cell3 = workbook.sheets[0].rows[3][2], cell4 = workbook.sheets[0].rows[4][2], cell5 = workbook.sheets[0].rows[5][2]; [cell1, cell2, cell3, cell4, cell5].forEach(function (cell) { expect(cell.value).to.be.a('string'); }); expect(cell1.value).to.equal('Some text'); expect(cell2.value).to.equal('{ "property": "value" }'); expect(cell3.value).to.equal('ÉéÀàçÇùÙ'); expect(cell4.value).to.equal('some "quoted" text'); expect(cell5.value).to.equal('more \'quoted\' "text"'); return next(); }); }, done); }); it('should parse date values', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; var row1 = workbook.sheets[0].rows[1], row2 = workbook.sheets[0].rows[2], row3 = workbook.sheets[0].rows[3], row4 = workbook.sheets[0].rows[4], row5 = workbook.sheets[0].rows[5]; [row1, row2, row3, row4, row5].forEach(function (row) { expect(row[3].value).to.be.a('date'); expect(row[4].value).to.be.a('date'); }); expect(row1[3].value).to.eql(new Date(2013, 0, 1, 0, 0, 0)); expect(row1[4].value).to.eql(new Date(2013, 0, 1, 12, 54, 21)); expect(row2[3].value).to.eql(new Date(2013, 0, 2, 0, 0, 0)); //expect(row2[4].value).to.eql(new Date(0, 0, 0, 0, 0, 34)); expect(row3[4].value).to.eql(new Date(2013, 0, 3, 3, 45, 20)); expect(row4[4].value).to.eql(new Date(2013, 0, 4, 0, 0, 0)); expect(row5[4].value).to.eql(new Date(2013, 0, 5, 16, 0, 0)); return next(); }); }, done); }); it('should parse empty cells as nulls', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; workbook.sheets[0].rows.splice(1).forEach(function (row) { expect(row[5].value).to.be.null; }); return next(); }); }, done); }); it('should parse cells with errors', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; var row1 = workbook.sheets[0].rows[1]; var row2 = workbook.sheets[0].rows[2]; var row3 = workbook.sheets[0].rows[3]; expect(row1[6].value).to.be.an.instanceof(Error).and.have.property('errorCode', '#DIV/0!'); expect(row2[6].value).to.be.an.instanceof(Error).and.have.property('errorCode', '#NAME?'); expect(row3[6].value).to.be.an.instanceof(Error).and.have.property('errorCode', '#VALUE!'); return next(); }); }, done); }); it('should parse cells with booleans', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, function (err, workbook) { if (err) throw err; var row1 = workbook.sheets[0].rows[1]; var row2 = workbook.sheets[0].rows[2]; expect(row1[7].value).to.be.true; expect(row2[7].value).to.be.false; return next(); }); }, done); }); it('should parse only the selected sheet by index', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, { sheet: 0 }, function (err, workbook) { if (err) throw err; expect(workbook.sheets).to.have.length(1); expect(workbook.sheets[0]).to.have.property('index', 0); expect(workbook.sheets[0]).to.have.property('name', 'Sheet1'); return next(); }); }, done); }); it('should parse only the selected sheet by name', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, { sheet: 'Sheet1' }, function (err, workbook) { if (err) throw err; expect(workbook.sheets).to.have.length(1); expect(workbook.sheets[0]).to.have.property('index', 0); expect(workbook.sheets[0]).to.have.property('name', 'Sheet1'); return next(); }); }, done); }); it('should parse only metadata', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, { meta: true }, function (err, workbook) { if (err) throw err; expect(workbook.sheets).to.be.undefined; return next(); }); }, done); }); it('should parse up to 10 rows on the first sheet', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.parse(file, { sheet: 0, maxRows: 10 }, function (err, workbook) { if (err) throw err; expect(workbook.sheets[0]).to.have.property('name', 'Sheet1'); expect(workbook.sheets[0].rows).to.have.length(10); return next(); }); }, done); }); it('should fail if the file does not exist', function (done) { xlrd.parse('unknown.xlsx', function (err, workbook) { expect(workbook).to.not.be.ok; expect(err).to.be.an.instanceof(Error).and.have.property('id', 'file_not_found'); return done(); }); }); it('should fail if the file is not a valid workbook', function (done) { xlrd.parse('package.json', function (err, workbook) { expect(workbook).to.not.be.ok; expect(err).to.be.an.instanceof(Error).and.have.property('id', 'open_workbook_failed'); return done(); }); }); }); describe('stream()', function () { it('should emit a single "open" event when file is ready', function (done) { async.eachSeries(sampleFiles, function (file, next) { xlrd.stream(file).on('open', function (workbook) { expect(workbook).to.be.an('object').and.have.property('file', file); return next(); }).on('error', function (err) { throw err; }); }, done); }); it('should emit "data" events as data is being received', function (done) { async.eachSeries(sampleFiles, function (file, next) { var events = [], total = {}; xlrd.stream(file).on('open', function (workbook) { expect(workbook).not.be.null; expect(workbook.file).to.equal(file); expect(workbook.meta).not.be.null; expect(workbook.sheets).to.be.undefined; }).on('data',function (data) { events.push(data); }).on('error',function (err) { throw err; }).on('close', function () { expect(events).to.have.length.above(0); expect(events).to.have.deep.property('[0].workbook').and.have.property('file', file); expect(events).to.have.deep.property('[0].sheet'); expect(events).to.have.deep.property('[0].rows').and.have.length.above(0); events.forEach(function (data) { total[data.sheet.name] = (total[data.sheet.name] || 0) + data.rows.length; }); expect(total['Sheet1']).to.equal(51); expect(total['second sheet']).to.equal(1384); return next(); }); }, done); }); }); });