Search code examples
javascriptfirebase-realtime-databaseexport-to-csv

how to write data into one csv file?


I am currently trying to write data from firebase into a csv file. It sort of works but I get three different files and I don't know how to fix this. I am just highly confused at this point of time.

Do you have any idea on how to fix this mess?

Here is my JSON:

{
  "records" : {
    "id1" : {
      "2020-08-11 15:40:13" : {
        "0" : "5"
      },
      "2020-08-11 16:35:09" : {
        "0" : "18"
      }
    },
    "id2" : {
      "2020-08-11 17:23:34" : {
        "0": "5"
      }
    },
    "id3" : {
      "2020-08-11 09:38:53" : {
        "0": "4"
      }
    },
    "id4" : {
      "2020-08-11 13:41:30" : {
        "0": "2"
      },
      "2020-08-11 13:41:44" : {
        "0": "3"
      }
    }
  }
}


Basically, I want to get all ids and write them into a column of the csv-file. The 'test'-entries are only a placeholder for other data-entries.

Here is what I have so far:

function downloadData(){
    var db = firebase.database().ref();
    var dbRef = db.child('records');
    
    dbRef.once('value', function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
            var childKey = childSnapshot.key;
            var b = [childKey, 'iwannasleep'];
            // console.log(childKey); 
            // console.log(b);

            var data = [b];
            console.log(data);



// ------------- export into csv ---------------


            var arrayHeader = ["user_id", "test"] 

            var csv = arrayHeader.join(',') + '\n';
            data.forEach( function(row) {
                csv += row.join(',');
                csv += "\n";
            });
        
            console.log(csv);

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

Solution

  • As RobIII commented, you're creating a download link inside the for loop, which means that you're creating a separate element for each row of data.

    You'll want to pull that out of the loop:

    var db = firebase.database().ref();
    var dbRef = db.child('dataRecordings');
    
    dbRef.once('value', function(snapshot) {
        var arrayHeader = ["user_id", "test"] 
        var csv = arrayHeader.join(',') + '\n';
    
        snapshot.forEach(function(childSnapshot) {
            var childKey = childSnapshot.key;
            var b = [childKey, 'iwannasleep'];
    
            var data = [b];
    
            data.forEach(function(row) {
                csv += row.join(',');
                csv += "\n";
            });    
        });
        var hiddenElement = document.createElement('a');
        hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);;
        hiddenElement.target = '_blank';
        hiddenElement.download = 'data.csv';
        hiddenElement.click();
    });
    

    Update: an example of what happens with the JSON in your question:

    const json = {
      "records" : {
        "id1" : {
          "2020-08-11 15:40:13" : {  "0" : "5" },
          "2020-08-11 16:35:09" : { "0" : "18" }
        },
        "id2" : {
          "2020-08-11 17:23:34" : { "0": "5" }
        },
        "id3" : {
          "2020-08-11 09:38:53" : { "0": "4" }
        },
        "id4" : {
          "2020-08-11 13:41:30" : { "0": "2" },
          "2020-08-11 13:41:44" : { "0": "3" }
        }
      }
    }
    
    var arrayHeader = ["user_id", "test"] 
    var csv = arrayHeader.join(',') + '\n';
    
    Object.keys(json.records).forEach((childKey) => {
        var b = [childKey, 'iwannasleep'];
    
        var data = [b];
    
        data.forEach(function(row) {
            csv += row.join(',');
            csv += "\n";
        });    
    });
    
    console.log(csv);