Dynamically Creating CSV Files on the Client

A reader posed an interesting question on one of my ColdFusion posts recently. The post (Creating an Excel File) demonstrated how to take form data on the front end and create an Excel file via ColdFusion when the form is submitted. The user wanted to know if this could be done entirely client-side.

The latest versions of Office use an XML based file format contained within a zip file. There is a good JS library for working with zips and as it turns out – there is a JS library for XLSX as well: https://github.com/stephen-hardy/xlsx.js. While this would possibly work, I thought there might be a simpler way using CSV, or comma-separated value files.

About two years ago I wrote a piece on exporting data from IndexedDB. It used string data and a data url to create a link to a virtual representation of the data. Combining this with the download attribute of the anchor tag, it is possible to push a download of a fake file to the user.

Therefore – all we need to do is create a CSV string. I built a simple, but ugly demo, that consists of a few rows of text fields.

The user can then enter values into the columns and get a CSV file by clicking the button. Let’s look at the JavaScript code.

$(document).ready(function() {
	var $link = $("#dataLink");
	var $nameFields = $(".nameField");
	var $cookieFields = $(".cookieField");
	
	$("#downloadLink").on("click", function(e) {
		var csv = "";
		//we should have the same amount of name/cookie fields
		for(var i=0; i<$nameFields.length; i++) {
			var name = $nameFields.eq(i).val();
			var cookies = $cookieFields.eq(i).val();
			if(name !== '' && cookies !== '') csv += name + "," + cookies + "\n";	
		}
		console.log(csv);
		
		$link.attr("href", 'data:Application/octet-stream,' + encodeURIComponent(csv))[0].click();
	});
});

The code begins with the click handler for the download button. All I have to do is generate my CSV string by looping over the rows of fields. To be fair, my CSV handling could be a bit nicer. A name can include a comma so I should probably wrap the value in quotes, but I think you get the idea.

Once we have the CSV, we then use the same method I used on the IndexedDB post and force the download. On my system, this creates a file that opens in Excel just fine.

It also worked in OpenOffice once I told it to use commas. Want to try it yourself? Hit the demo link below.

Edit: Big thanks to @Laurence below who figured out that I didn’t need a particular hack to get my click event working for downloads. That cut out about 50% of the code I had before. Thanks Laurence!

  • Manish

    Hey Raymond, I have been trying this code but seems to be working ONLY in Chrome and Firefox, it doesnt work in Internet Explorer. I verified in the Developer Tools and found the below error message:

    “The data area passed to a system call is too small.”

    Do you have any suggestions or any sample on fiddle that works with IE, would appreciate if you can share.

    Thanks in advance!!

    Regards,
    Manish

    • http://www.raymondcamdencom/ Raymond Camden

      Where did that call come from? In other words, where exactly does it break down?