diff --git a/.gitignore b/.gitignore index ae5e9a2..06ccec4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ +.idea/ example/output.xlsx \ No newline at end of file diff --git a/lib/json2xls.js b/lib/json2xls.js index e0a7a07..beafb34 100644 --- a/lib/json2xls.js +++ b/lib/json2xls.js @@ -1,9 +1,14 @@ var nodeExcel = require('excel-export'); +/** + * + * @param {array|object} json + * @param {array|object} config + * @returns {*} + */ var transform = function(json,config) { var conf = transform.prepareJson(json,config); - var result = nodeExcel.execute(conf); - return result; + return nodeExcel.execute(conf); }; //get a xls type based on js type @@ -31,7 +36,7 @@ function getByString(object, path) { while (a.length) { var n = a.shift(); if (n in object) { - object = (object[n]==undefined)?null:object[n]; + object = (object[n] === undefined) ? null : object[n]; } else { return null; } @@ -42,55 +47,59 @@ function getByString(object, path) { //prepare json to be in the correct format for excel-export transform.prepareJson = function(json,config) { - var res = {}; - var conf = config||{}; - var jsonArr = [].concat(json); - var fields = conf.fields || Object.keys(jsonArr[0]||{}); - var types = []; - if (!(fields instanceof Array)) { - types = Object.keys(fields).map(function(key) { - return fields[key]; - }); - fields = Object.keys(fields); - } - //cols - res.cols = fields.map(function(key,i) { - return { - caption: key, - type: getType(jsonArr[0][key],types[i]), - beforeCellWrite: function(row, cellData, eOpt){ - eOpt.cellType = getType(cellData,types[i]); - return cellData; - } - }; + var res = {}; + var conf = config||{}; + var jsonArr = [].concat(json); + var fields = conf.fields || Object.keys(jsonArr[0]||{}); + var types = []; + var headers = []; + if (!(fields instanceof Array)) { + types = Object.keys(fields).map(function(key) { + return fields[key]['type'] !== undefined ? fields[key]['type'] : fields[key]; }); - //rows - res.rows = jsonArr.map(function(row) { - return fields.map(function(key) { - var value = getByString(row,key); - //stringify objects - if(value && value.constructor == Object) value = JSON.stringify(value); - //replace illegal xml characters with a square - //see http://www.w3.org/TR/xml/#charsets - //#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] - if (typeof value === 'string') { - value = value.replace(/[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]/g,''); - } - return value; - }); + headers = Object.keys(fields).map(function(key) { + return fields[key]['header'] !== undefined ? fields[key]['header'] : key; }); - //add style xml if given - if (conf.style) { - res.stylesXmlFile = conf.style; - } - return res; + fields = Object.keys(fields); + } + //cols + res.cols = fields.map(function(key,i) { + return { + caption: headers[i], + type: getType(jsonArr[0][key],types[i]), + beforeCellWrite: function(row, cellData, eOpt){ + eOpt.cellType = getType(cellData,types[i]); + return cellData; + } + }; + }); + //rows + res.rows = jsonArr.map(function(row) { + return fields.map(function(key) { + var value = getByString(row,key); + //stringify objects + if(value && value.constructor == Object) value = JSON.stringify(value); + //replace illegal xml characters with a square + //see http://www.w3.org/TR/xml/#charsets + //#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + if (typeof value === 'string') { + value = value.replace(/[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]/g,''); + } + return value; + }); + }); + //add style xml if given + if (conf.style) { + res.stylesXmlFile = conf.style; + } + return res; }; -transform.middleware = function(req,res,next) { - res.xls = function(fn,data,config) { - var xls = transform(data,config); +transform.middleware = function(req, res, next) { + res.xls = function(fn, data, config) { + var xls = transform(data, config); res.setHeader('Content-Type', 'application/vnd.openxmlformats'); - res.setHeader("Content-Disposition", "attachment; filename=" + fn); + res.setHeader('Content-Disposition', 'attachment; filename=' + fn); res.end(xls, 'binary'); }; next(); diff --git a/readme.md b/readme.md index f8a2a68..e0c451b 100644 --- a/readme.md +++ b/readme.md @@ -62,6 +62,7 @@ The following options are supported: - fields: either an array or map containing field configuration: - array: a list of names of fields to be exported, in that order - object: a map of names of fields to be exported and the types of those fields. Supported types are 'number','string','bool' + - object: {'poo':{header:'Some Header for poo', type:'number'}} Example: @@ -83,4 +84,24 @@ Example: fields: {poo:'string'} }); + fs.writeFileSync('data.xlsx', xls, 'binary'); +Example with headers: + + var json2xls = require('json2xls'); + var json = { + foo: 'bar', + qux: 'moo', + poo: 123, + stux: new Date() + } + + //export only the field 'poo' + var xls = json2xls(json,{ + fields: { + 'poo':{header:'Some Header for poo', type:'number'}, + 'qux':{header:'Some Header for qux', type:'string'} + } + }); + + fs.writeFileSync('data.xlsx', xls, 'binary');