Skip to content

Instantly share code, notes, and snippets.

@vace
Created June 29, 2017 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vace/3aaffd45508b74901a0e553951ee7a5b to your computer and use it in GitHub Desktop.
Save vace/3aaffd45508b74901a0e553951ee7a5b to your computer and use it in GitHub Desktop.
csv encode and export
/**
* csv data encode
* var data = [[1850, 20, 0, 1, 1017281], [1850, 20, 0, 2, 1003841]];
* encode(data)
* encode(data,{ header: ["year", "age", "status", "sex", "population"] })
* encode([{age:xx,name:'xxx'}], {header:true})
* options:{ delimiter:'分隔符',newline:换行符,skip:头部跳过数量,header:Object或者arrat }
*/
const CELL_DELIMITERS = [',', ';', '\t', '|', '^']
const LINE_DELIMITERS = ['\r\n', '\r', '\n']
const STANDARD_ENCODE_OPTS = {
delimiter: CELL_DELIMITERS[0],
newline: LINE_DELIMITERS[0],
skip: 0,
limit: false,
header: false
}
const quoteMark = '"'
const doubleQuoteMark = '""'
const quoteRegex = /"/g
const getType = (obj) => Object.prototype.toString.call(obj).slice(8, -1)
const getLimit = (limit, len) => limit === false ? len : limit
function encodeCells (line, delimiter, newline) {
let row = line.slice(0)
for (let i = 0, len = row.length; i < len; i++) {
if (typeof row[i] !== 'string') {
continue
}
if (row[i].indexOf(quoteMark) !== -1) {
row[i] = row[i].replace(quoteRegex, doubleQuoteMark)
}
if (row[i].indexOf(delimiter) !== -1 || row[i].indexOf(newline) !== -1) {
row[i] = quoteMark + row[i] + quoteMark
}
}
return row.join(delimiter)
}
function encodeArrays (coll, opts, fn) {
let delimiter = opts.delimiter
let newline = opts.newline
if (opts.header && getType(opts.header) === 'Array') {
fn(encodeCells(opts.header, delimiter, newline))
}
for (let cur = 0, lim = getLimit(opts.limit, coll.length); cur < lim; cur++) {
fn(encodeCells(coll[cur], delimiter, newline))
}
return true
}
function encodeObjects (coll, opts, fn) {
let delimiter = opts.delimiter
let newline = opts.newline
let header
let row
header = []
row = []
for (let key in coll[0]) {
header.push(key)
row.push(coll[0][key])
}
if (opts.header === true) {
fn(encodeCells(header, delimiter, newline))
} else if (getType(opts.header) === 'Array') {
fn(encodeCells(opts.header, delimiter, newline))
}
fn(encodeCells(row, delimiter))
for (let cur = 1, lim = getLimit(opts.limit, coll.length); cur < lim; cur++) {
row = []
for (let key = 0, len = header.length; key < len; key++) {
row.push(coll[cur][header[key]])
}
fn(encodeCells(row, delimiter, newline))
}
return true
}
export function encodeCsv (coll, opts, fn) {
let lines
if (getType(opts) === 'Function') {
fn = opts
opts = {}
} else if (getType(fn) !== 'Function') {
lines = []
fn = lines.push.bind(lines)
}
opts = Object.assign({}, STANDARD_ENCODE_OPTS, opts)
if (opts.skip > 0) {
coll = coll.slice(opts.skip)
}
return (getType(coll[0]) === 'Array' ? encodeArrays : encodeObjects)(coll, opts, fn) &&
(lines.length > 0 ? lines.join(opts.newline) : true)
}
export function downloadCsv (csvFile, filename) {
filename = `${filename}.csv`
let blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' })
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename)
} else {
let link = document.createElement('a')
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob)
link.setAttribute('href', url)
link.setAttribute('download', filename)
link.style.visibility = 'hidden'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment