const nodeExcel = require('excel-export')
const objectPath = require('object-path')
const transform = function (json, config) {
const conf = transform.prepareJson(json, config)
const result = nodeExcel.execute(conf)
return result
}
// get a xls type based on js type
function getType (obj, type) {
if (type) {
return type
}
const 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
const defaultValue = object[path] || null
return objectPath.get(object, path, defaultValue)
}
// prepare json to be in the correct format for excel-export
transform.prepareJson = function (json, config) {
const res = {}
const conf = config || {}
const jsonArr = [].concat(json)
let fields = conf.fields || Object.keys(jsonArr[0] || {})
let 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) {
let 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') {
// eslint-disable-next-line no-control-regex
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) {
const 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