itsmitchellcollins
itsmitchellcollins

Reputation: 23

How do I remove the extra comma in this CSV generator for loop

I have a group of objects nested inside of an array.

I understand why the for loop is adding a comma at the end of the rows, but I'm having trouble finding out a better way to write this (brand-new to programming) which would not have the comma inside of the loop.

Is there a better way to write this?

function createCSV() {
    
    // CREATE THE CSV VARIABLE
    let csvContent = "data:text/csv;charset=utf-8,"
    let headers = "date,account,vendor,amount,recurring,description,notes"
    csvContent += headers + "\r\n"
    
    // ITERATE THE ARRAY INTO THE CSV SEPARATED BY COMMAS
    adjustments.forEach(element => {

        // EACH ARRAY ITEM
        let row
        
        //EACH OBJECT PROPERTY
        for (const property in element) {
            row += element[property]
            row += ','
          }

        csvContent += row + "\r\n";
    });

    // DOWNLOAD THE CSV
    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "empower_data.csv");
    document.body.appendChild(link); // Required for FF
    link.click();
    console.log('CSV DOWNLOADED')
}

Upvotes: 2

Views: 336

Answers (2)

Jaromanda X
Jaromanda X

Reputation: 1

use array and array join

function createCSV() {
    let csvContent = "data:text/csv;charset=utf-8,";
    let headers = "date,account,vendor,amount,recurring,description,notes";
    csvContent += headers + "\r\n";

    adjustments.forEach(element => {
        // begin changes
        let row = [];
        for (const property in element) {
            row.push(element[property]);
        }
        csvContent += row.join(',') + "\r\n";
        // end changes
    });

    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "empower_data.csv");
    document.body.appendChild(link);
    link.click();
    console.log('CSV DOWNLOADED');
}

better yet - replace all that with

function createCSV() {
    let csvContent = "data:text/csv;charset=utf-8,";
    let headers = "date,account,vendor,amount,recurring,description,notes";
    csvContent += headers + "\r\n";

    adjustments.forEach(element => {
        // begin changes
        csvContent += Object.values(element).join(',') + "\r\n";
        // end changes
    });

    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "empower_data.csv");
    document.body.appendChild(link);
    link.click();
    console.log('CSV DOWNLOADED');
}

or for really neat code

function createCSV() {
    let csvContent = "data:text/csv;charset=utf-8,";
    let headers = "date,account,vendor,amount,recurring,description,notes";

    csvContent += headers + "\r\n";
    // begin changes
    csvContent += adjustments.map(
        element => Object.values(element).join(',')
    ).join('\r\n');
    // end changes
    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "empower_data.csv");
    document.body.appendChild(link);
    link.click();
    console.log('CSV DOWNLOADED');
}

As a final note: since object properties don't have a defined "order" - you may want to do something like this

function createCSV() {
    const properties = ['date','account','vendor','amount','recurring','description','notes'];
    let csvContent = "data:text/csv;charset=utf-8,";
    let headers = "date,account,vendor,amount,recurring,description,notes";

    csvContent += headers + "\r\n";
    // begin changes
    csvContent += adjustments.map(element => properties.map(prop => element[prop]).join(',')).join('\r\n');
    // end changes
    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "empower_data.csv");
    document.body.appendChild(link);
    link.click();
    console.log('CSV DOWNLOADED');
}

In the above, I assume the property names in the object are the same as the CSV column headers, but, of course, that's not necessarily the case (I simply don't know)

Upvotes: 2

throrin19
throrin19

Reputation: 18207

The best approach for that is to use array instead of string concatenation and finish this with array.join() :

function createCSV() {
    
    // CREATE THE CSV VARIABLE
    let csvContent = "data:text/csv;charset=utf-8,"
    let headers = "date,account,vendor,amount,recurring,description,notes"
    csvContent += headers + "\r\n"
    
    // ITERATE THE ARRAY INTO THE CSV SEPARATED BY COMMAS
    adjustments.forEach(element => {

        // EACH ARRAY ITEM
        const row = [];
        
        //EACH OBJECT PROPERTY
        for (const property in element) {
            row.push(element[property]);
        }

        csvContent += row.join(',') + "\r\n";
    });

    // DOWNLOAD THE CSV
    var encodedUri = encodeURI(csvContent);
    var link = document.createElement("a");
    link.setAttribute("href", encodedUri);
    link.setAttribute("download", "empower_data.csv");
    document.body.appendChild(link); // Required for FF
    link.click();
    console.log('CSV DOWNLOADED')
}

Upvotes: 2

Related Questions