Skip to content

Instantly share code, notes, and snippets.

@richcsmith
Last active March 27, 2018 18:35
Show Gist options
  • Save richcsmith/70b7b7eba5b9d8dcfe9dcfd7609eb682 to your computer and use it in GitHub Desktop.
Save richcsmith/70b7b7eba5b9d8dcfe9dcfd7609eb682 to your computer and use it in GitHub Desktop.
CSV Helper Functions
const generateId = () => Math.floor(Math.random() * Date.now())
/*
* This function accepts an array of objects as its only argument. It will use the keys
* from the first object (not recursively) to create the header row of the .csv file.
*
* Returns: a formatted string, which can be fed directly into `downloadFile()`
*/
const convertToCSV = (data = []) => {
let csvContent = 'data:text/csv;charset=utf-8,'
const headerRow = Object.keys(data[0]).join(',')
const rows = [headerRow]
data.forEach((p) => {
const row = Object.values(p).join(',')
rows.push(row)
})
rows.forEach((r) => {
csvContent += `\r\n`
csvContent += r
})
return csvContent
}
const downloadFile = (csvData = '') => {
const anchor = document.createElement('a')
anchor.setAttribute('href', encodeURI(csvData))
anchor.setAttribute('download', 'data.csv') // 'data.csv' can be any filename you want, but should end with `.csv`
anchor.click()
}
/*
* Accepts a `.csv` file upload event, parses the data, and returns a promise that resolves with an array of objects
*/
const uploadFile = (event) => new Promise((resolve) => {
const reader = new FileReader()
const file = event.target.files[0]
reader.readAsText(file)
reader.addEventListener('load', (event) => {
const lines = event.target.result.split('\n')
const headers = lines[0].split(',')
const rows = lines.slice(1, lines.length).map((l) => l.split(','))
const items = []
rows.forEach((row) => {
const id = generateId()
const parsed = { id }
headers.forEach((h, i) => {
parsed[h] = row[i]
})
items.push(parsed)
})
resolve(items)
})
})
/*
* Example `uploadFile()` usage
*/
let fileInput = null
const handleImportClick = () => {
if (fileInput) {
const input = findDOMNode(fileInput)
input.click()
}
}
const ImportButton = ({ dispatch }) => (
<Button
type="secondary"
id="upload"
onClick={handleImportClick}>
Import
<input
onChange={(e) => uploadFile(e).then((csv) => dispatch(importProducts(csv)))}
type="file"
ref={(c) => { fileInput = c }}
className="ImportButton-fileInput" />
</Button>
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment