node.js读写excel文件
需求
在上一篇推送,我提到了这样一个需求:
A上传一份任务文件(文件类型不限)到网站上,B看到后下载文件,按照文件里的要求完成任务之后,B要把任务完成情况汇总到一个Excel 文档中,上传到网站上(此时只能上传xls格式的excel文档),然后网站在后台对这份Excel文档的数据进行处理,生成一份新的Excel文档。
所以,我写了一篇分享《node.js实现上传与下载文件》。而这次,我想针对这个需求分享下:node.js读写excel文件。
实现
思路
-
有哪些外部模块支持读写Excel
-
引入模块
-
编写业务逻辑函数
支持读写Excel的node.js模块
上npm搜索过,发现支持读写excel文件的模块有很多,但是都各有缺陷,有些仅支持xls/xlsx的一种格式,有些仅支持读取数据,有些仅支持导出文件。例如:
-
node-xlsx: 基于Node.js解析excel文件数据及生成excel文件,仅支持xlsx格式文件;
-
excel-parser: 基于Node.js解析excel文件数据,支持xls及xlsx格式文件;
-
excel-export : 基于Node.js将数据生成导出excel文件,生成文件格式为xlsx;
-
node-xlrd: 基于node.js从excel文件中提取数据,仅支持xls格式文件。
在我的项目中,我使用的是noe-xlrd模块及excel-export模块,用于提取上传上来的excel文件里的数据,以及生成新的excel文件。
引入模块
编辑项目工程里的package.json文件:
{ "name": "appname", "virsion": "0.0.1", "dependencies": { "express": "~4.8.8", "node-xlrd": "0.2.4", "excel-export": "0.4.1" } }
执行node命令安装模块
npm install
编写业务逻辑函数
1.解析excel文件数据
var xl = require('node-xlrd'); exports.read = function(req, res, next){ var path = 'test.xls'; var datas = []; xl.open(path, function(err,bk){ if(err) {console.log(err.name, err.message); return;} var shtCount = bk.sheet.count; for(var sIdx = 0; sIdx < shtCount; sIdx++ ){ console.log('sheet "%d" ', sIdx); console.log(' check loaded : %s', bk.sheet.loaded(sIdx) ); var sht = bk.sheets[sIdx], rCount = sht.row.count, cCount = sht.column.count; console.log(' name = %s; index = %d; rowCount = %d; columnCount = %d', sht.name, sIdx, rCount, cCount); for(var rIdx = 0; rIdx < rCount; rIdx++){ // rIdx:行数;cIdx:列数 var data = []; for(var cIdx = 0; cIdx < cCount; cIdx++){ try{ data[cIdx] = sht.cell(rIdx,cIdx); console.log(' cell : row = %d, col = %d, value = "%s"', rIdx, cIdx, sht.cell(rIdx,cIdx)); }catch(e){ console.log(e.message); } } datas[rIdx] = data; } } req.datas = datas; }); };
解析出来的数据有不同的数据类型:string、number。可以用typeof sht.cell(rIdx,cIdx)检测数据类型。
2.将处理后的数据生成新的excel文件
var excelPort = require('excel-export'); exports.write = function(req, res, next){ var datas = req.datas; var conf = {}; var filename = 'filename'; //只支持字母和数字命名 conf.cols = [ {caption:'名称', type:'string', width:20}, {caption:'简介', type:'string', width:40}, {caption:'报酬', type:'string', width:20}, {caption:'时间', type:'date', width:40}, {caption:'人员', type:'string', width:30}, {caption:'编号', type:'string', width:30}, {caption:'金额', type:'number', width:30}, {caption:'手机号', type:'string', width:30} ]; var array = []; array[0] = [ datas[0][0], datas[0][1], datas[0][2], datas[0][3], datas[0][4], datas[0][5], datas[0][6], datas[0][7] ]; conf.rows = array[0]; var result = excelPort.execute(conf); var random = Math.floor(Math.random()*10000+0); var uploadDir = 'public/upload/pay/'; var filePath = uploadDir + filename + random + ".xlsx"; fs.writeFile(filePath, result, 'binary',function(err){ if(err){ console.log(err); } }); }
caption设置首行各单元格内容,type设置的是每一列的数据类型,width设置单元格大小。
rows 赋值的是每一行的数据,每个数据都要与所在列所设置的数据格式一致,否则会报错,生成后的表格该单元格会显示NaN。
总结
在读取解析完excel文件里的数据后,一般要根据项目需求对数据进行处理。进行数据处理时,要格外注意所解析到的数据的数据类型,以及要生成新的表格时,处理后的数据的数据类型是否符合所设置的数据类型。否则,bug不断....