Parse Uploaded CSV file using D3.js

Viewed 5398

I'm new to d3.js so I know this might seem as a silly question to some so please bear with me. I'm trying to parse a csv file which a user uploads and print it's output in the console. I'm able to parse the CSV file when I provide the absolute path of the CSV file but when I try doing the same with file upload functionality I'm not getting any output in the console..

Working Javascript Code..

    var dataset = [];
    d3.csv("sample.csv", function(data) {
    dataset = data.map(function(d) { return [ d["Title"], d["Category"], d["ASIN/ISBN"], d["Item Total"] ]; });
    console.log(dataset[0]);
    console.log(dataset.length);
    }); 

Console Output...

["Men's Brooks Ghost 8 Running Shoe Black/High Risk Red/Silver Size 11.5 M US", "Shoes", "B00QH1KYV6", "$120.00 "]
 8

New HTML code..

    <input type="file" id="csvfile" name="uploadCSV"/>
    <br/>
    <button onclick="howdy()">submit</button>

Modified Javascript Code(not working)..

    var myfile = $("#csvfile").prop('files')[0];
    var reader = new FileReader();

    reader.onload = function(e) {
    var text = reader.result;
    }

    reader.readAsDataURL(myfile);

     var dataset = [];
    d3.csv(reader.result , function(data) {
    dataset = data.map(function(d) { return [ d["Title"], d["Category"], d["ASIN/ISBN"], d["Item Total"] ]; });
    console.log(dataset[0]);
    console.log(dataset.length);
    })

Since there was no official documentation on how to handle user uploaded CSV file I can't figure out where I'm going wrong..Is there a way I can use HTML5 file reader?? Please help..

3 Answers

This is for d3-csv@3

<!-- https://www.jsdelivr.com/package/npm/d3-dsv -->
<script src="https://cdn.jsdelivr.net/npm/d3-dsv@3.0.1/dist/d3-dsv.min.js" integrity="sha256-IrzYc2a3nTkfvgAyowm/WKmIGdVCMCcccPtz+Y2y6VI=" crossorigin="anonymous"></script>
<input type="file" accept=".csv">
<button>test button</button>

<script>
const testData = `owner,repo,"branch name"
foo,demo,master
boo,"js awesome",sha1123456
`
document.querySelector(`input`).onchange = async e => {
  const input = e.target
  const file = input.files[0]
  const reader = new FileReader()
  reader.readAsText(new Blob(
    [file],
    {"type": file.type}
  ))
  const fileContent = await new Promise(resolve => {
    reader.onloadend = (event) => {
      resolve(event.target.result)
    }
  })
  const csvData = d3.csvParse(fileContent)
  console.log(csvData)
}

document.querySelector(`button`).onclick = e => {
  const csvData =  d3.csvParse(testData)
  console.log(csvData)
}
</script>


The below link may help you know the implementation of csvParse


If you just load the CSV only then do not import the whole JS. (instead of the d3-csv.js)

https://cdn.jsdelivr.net/npm/d3@7.0.1/dist/d3.min.js

https://cdn.jsdelivr.net/npm/d3-dsv@3.0.1/dist/d3-dsv.min.js

This is an old question and I think we have to clarify some points.

  1. How to load a local csv file
  2. How to link the loaded file with D3

1. Load a file is very simple just check this example:

const fileInput = document.getElementById('csv')
const readFile = e => {
  const reader = new FileReader()
  reader.onload = () => {
    document.getElementById('out').textContent = reader.result
  }
  reader.readAsBinaryString(fileInput.files[0])
}

fileInput.onchange = readFile
<div>
  <p>Select local CSV File:</p>
  <input id="csv" type="file" accept=".csv">
</div>
<pre id="out"><p>File contents will appear here</p></pre>

Here we have a simple input element with type="file" attribute, this lets us to pick a csv file. Then the readFile() function will be triggered whenever a file is selected and will call the onload function after reading the file as a binary string.

2. I recommend to use readAsDataURL() to integrate it with d3 like this:

const fileInput = document.getElementById('csv')
const previewCSVData = async dataurl => {
  const d = await d3.csv(dataurl)
  console.log(d)
}

const readFile = e => {
  const file = fileInput.files[0]
  const reader = new FileReader()
  reader.onload = () => {
    const dataUrl = reader.result;
    previewCSVData(dataUrl)
  }
  reader.readAsDataURL(file)
}

fileInput.onchange = readFile
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div>
  <p>Select local CSV File:</p>
  <input id="csv" type="file" accept=".csv">
</div>
<pre id="out"><p>File contents will appear here</p></pre>

To integrate the loaded file we call previewCSVData() and pass the file then we parse it using d3.csv() method. Also lets use await because it is an asynchronous call.

Note:

d3.csv internally uses fetch and works for any type of URL, (httpURL, dataURL, blobURL, etc...)

Related