100 lines
3.0 KiB
JavaScript
100 lines
3.0 KiB
JavaScript
var nodeExcel = require('excel-export');
|
|
|
|
var transform = function(json,config) {
|
|
var conf = transform.prepareJson(json,config);
|
|
var result = nodeExcel.execute(conf);
|
|
return result;
|
|
};
|
|
|
|
//get a xls type based on js type
|
|
function getType(obj,type) {
|
|
if (type) {
|
|
return type;
|
|
}
|
|
var t = typeof obj;
|
|
switch (t) {
|
|
case 'string':
|
|
case 'number':
|
|
return t;
|
|
case 'boolean':
|
|
return 'bool';
|
|
default:
|
|
return 'string';
|
|
}
|
|
}
|
|
|
|
//get a nested property from a JSON object given its key, i.e 'a.b.c'
|
|
function getByString(object, path) {
|
|
path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
|
|
path = path.replace(/^\./, ''); // strip a leading dot
|
|
var a = path.split('.');
|
|
while (a.length) {
|
|
var n = a.shift();
|
|
if (n in object) {
|
|
object = (object[n]==undefined)?null:object[n];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
return object;
|
|
}
|
|
|
|
|
|
//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;
|
|
}
|
|
};
|
|
});
|
|
//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);
|
|
res.setHeader('Content-Type', 'application/vnd.openxmlformats');
|
|
res.setHeader("Content-Disposition", "attachment; filename=" + fn);
|
|
res.end(xls, 'binary');
|
|
};
|
|
next();
|
|
};
|
|
|
|
module.exports = transform;
|