Search code examples
javascriptarraysjsonobjectexport-to-csv

Generate a csv file from a javascript array of objects


I know this is a question already answered but couldn't find the solution that works for me.

I've a HTML button that, when clicked, generate an array of objects in typescript(which basically javascript) and i want to generate a csv file that will be downloaded.

Here is the example of the javascript array of objects:

    var items = [
              { "name": "Item 1", "color": "Green", "size": "X-Large" },
              { "name": "Item 2", "color": "Green", "size": "X-Large" },
              { "name": "Item 3", "color": "Green", "size": "X-Large" }];

    // Loop the array of objects
for(let row = 0; row < items.length; row++){
    let keysAmount = Object.keys(items[row]).length
    let keysCounter = 0

    // If this is the first row, generate the headings
    if(row === 0){

       // Loop each property of the object
       for(let key in items[row]){

                           // This is to not add a comma at the last cell
                           // The '\n' adds a new line
           csv += key + (keysCounter+1 < keysAmount ? ',' : '\r\n' )
           keysCounter++
       }
    }else{
       for(let key in items[row]){
           csv += items[row][key] + (keysCounter+1 < keysAmount ? ',' : '\r\n' )
           keysCounter++
       }
    }

    keysCounter = 0
}
console.log(csv)

var hiddenElement = document.createElement('a');
        hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
        hiddenElement.target = '_blank';
        hiddenElement.download = 'people.csv';
        hiddenElement.click();

I tried this example code but in my case it create the csv file, but doesn't insert the csv string correctly in the csv file, the csv string is has rows of element separated by a comma and each row is determined by a new line, but here all the data of each row sits in one cell of the csv file, how can I make so that each value of each row sits in a different cell?

here is the csv string that it:

    name,color,size
Item 2,Green,X-Large
Item 3,Green,X-Large

Solution

  • CSV is just a file with each cell separated by a comma and each row separated by a new line. You want to name each column as the key of the object. If I understood correctly:

    { "name": "Item 1", "color": "Green", "size": "X-Large" }
    

    Will be:

    ---------------------------
    | name   | color |   size  |
    ---------------------------
    | Item 1 | Green | X-Large |
    ---------------------------
    

    UPDATE: This is the updated version.

    So you can loop your array and generate the csv accordingly using the File API from HTML5:

    let csv
    
    // Loop the array of objects
    for(let row = 0; row < items.length; row++){
        let keysAmount = Object.keys(items[row]).length
        let keysCounter = 0
    
        // If this is the first row, generate the headings
        if(row === 0){
    
           // Loop each property of the object
           for(let key in items[row]){
    
                               // This is to not add a comma at the last cell
                               // The '\r\n' adds a new line
               csv += key + (keysCounter+1 < keysAmount ? ',' : '\r\n' )
               keysCounter++
           }
        }else{
           for(let key in items[row]){
               csv += items[row][key] + (keysCounter+1 < keysAmount ? ',' : '\r\n' )
               keysCounter++
           }
        }
    
        keysCounter = 0
    }
    
    // Once we are done looping, download the .csv by creating a link
    let link = document.createElement('a')
    link.id = 'download-csv'
    link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(csv));
    link.setAttribute('download', 'yourfiletextgoeshere.csv');
    document.body.appendChild(link)
    document.querySelector('#download-csv').click()
    

    BTW If you are using TypeScript, then the last line document.querySelector('#download-csv').click() MUST be <HTMLElement>document.querySelector('#download-csv').click() Let me know if it worked for you.

    Fiddle for TypeScript and javascript (it changes just the last line): https://jsfiddle.net/0p8revuh/4/

    UPDATE: To see the file propertly formated in excel, a cell for each comma separated value, do the following:

    1. You will see your data in several rows. Just click on the 'A' column to select all the rows: enter image description here

    2. Go to your excel and click on Data at the top: enter image description here

    3. Click on Text to columns: enter image description here

    4. Select delimited: enter image description here

    5. Click on next and active comma: enter image description here

    6. Click on next and finish. Now you should be able to see your data propertly formated.