最近写了一个脚本使用JS读取Excel的数据后进行随机组合排列后再写入Excel文件。使用到了node-xlsx 库用于操作Excel文件。为什么没有使用大名鼎鼎的js-xlsx,是因为发现node-xlsx其实是依赖于js-xlsx的,它对js-xlsx接口进行了封装对使用者更友好些,特别是读取Excel文件解析后的数据格式更友好些。
读取xlsx文件
1 2 3 4 5 6 7
| #!/usr/local/bin node const xlsx = require("node-xlsx"); const fs = require('fs'); const path = require('path');
const XLSX = path.join(__dirname, '随机名单.xlsx'); let xlsxData = xlsx.parse(fs.readFileSync(XLSX));
|
读取后的数据是个数组类型,每个数组项代表Excel中的一张表。name
是表名,data
是表数据。
如上图,data
数据格式是个数组,每个数组项式是表中的一行数据。
如上图,如果有单元格合并,解析的数据会留空位置(undefined
)对应表格中的被合并的单元格。
写xlsx文件
1 2 3 4 5 6 7 8 9 10
| const xlsx = require("node-xlsx"); const fs = require('fs'); const path = require('path');
const data = [[1, 2, 3], [true, false, null, 'sheetjs'], ['foo', 'bar', new Date('2014-02-19T14:30Z'), '0.3'], ['baz', null, 'qux']]; const range = {s: {c: 0, r:0 }, e: {c:0, r:3}}; const option = {'!merges': [ range ]};
var buffer = xlsx.build([{name: "mySheetName", data: data}], option); fs.writeFileSync(path.join(__dirname,'./test.xlsx'), buffer);
|
在js-xlsx中,一个单元格的对象的位置有{c:C, r:R}
表示,c
表示列(column)的位置,r
表示行(row)位置。
A1
的单元格坐标是{c:0,r:0}
。
{s:{c:C, r: R}, e: {c:C1, r:R1}}
表示单元格区间,s
表示起始单元格,e
表示最后一个单元格。
{s: {c: 0, r: 0}, e: {c: 0, r: 3}}
表示A1:A4
单元格区间。
发送excel文件
发送excel文件到浏览器端的关键是设置好 header 的 Content-Type 值。
对于excel,Content-Type有如下两种:
1 2 3 4 5
| application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
下面以restify为例写一段demo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| et restify = require('restify'), xlsx = require('node-xlsx');
let app = restify.createServer({ name: 'demo-xlsx', version: '1.0.0' });
app.get('/test', function(req, res, next) { const data = [[1, 2, 3], [true, false, null, 'sheetjs'], ['foo', 'bar', new Date('2014-02-19T14:30Z'), '0.3'], ['baz', null, 'qux']]; return sendExcel(res, data, 'sheet表名', 'myfile'); });
app.listen(8001, function() { console.log(app.name, 'Start listening at %s', app.url); });
function sendExcel(res, xlsxData, sheetName, xlsxFileName) { try { let buffer = xlsx.build([{name: sheetName, data: xlsxData}]); let xlsxContentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
res.setHeader('Content-Type', xlsxContentType); res.setHeader('Content-Disposition', `attachment; filename=${xlsxFileName}.xlsx`); res.writeHead(200); res.end(buffer); } catch (err) { console.log('mistake to build excel'); } }
|