0

I have data in the following format,

const data = {
    "Class-1": [{
        "section": "A",
        "total": "45",
        "boys": "31",
        "girls": "14",
        "subjects": 3,
        "class-teacher": "ABC"
    }, {
        "section": "B",
        "total": "30",
        "boys": "20",
        "girls": "10",
        "subjects": 3,
        "class-teacher": "XYZ"
    }],
    "Class-2": [{
        "section": "A",
        "total": "40",
        "boys": "25",
        "girls": "15",
        "subjects": 4,
        "class-teacher": "ABC2"
    }],
    "Class-3": [{
        "section": "A",
        "total": "44",
        "boys": "29",
        "girls": "15",
        "subjects": 4,
        "class-teacher": "ABC3"
    }, {
        "section": "B",
        "total": "40",
        "boys": "29",
        "girls": "11",
        "subjects": 4,
        "class-teacher": "XYZ1"
    }],
    "Class-4": [{
        "section": "A",
        "total": "50",
        "boys": "30",
        "girls": "20",
        "subjects": 5,
        "class-teacher": "ABC4"
    }]
}

I want to export the above data in a CSV file with JavaScript, something like as shown below, Expected

I tried using d3-dsv (this), but not able to achieve the desired result. With d3-dsv, if I am flattening the data into an immediate array of objects, I am not getting the classes- Class-1, Class-2, Class-3, and Class-4.

With d3-dsv, if I give data in the following format, I get output as attached below, Data format-

[{
    "section": "A",
    "total": "45",
    "boys": "31",
    "girls": "14",
    "subjects": 3,
    "class-teacher": "ABC"
}, {
    "section": "B",
    "total": "30",
    "boys": "20",
    "girls": "10",
    "subjects": 3,
    "class-teacher": "XYZ"
}, {
    "section": "A",
    "total": "40",
    "boys": "25",
    "girls": "15",
    "subjects": 4,
    "class-teacher": "ABC2"
}, {
    "section": "A",
    "total": "44",
    "boys": "29",
    "girls": "15",
    "subjects": 4,
    "class-teacher": "ABC3"
}, {
    "section": "B",
    "total": "40",
    "boys": "29",
    "girls": "11",
    "subjects": 4,
    "class-teacher": "XYZ1"
}, {
    "section": "A",
    "total": "50",
    "boys": "30",
    "girls": "20",
    "subjects": 5,
    "class-teacher": "ABC4"
}]

Output in CSV- Output

Vivek kumar
  • 1,632
  • 1
  • 14
  • 29

2 Answers2

3

Iterate Object.entries() and each iteration create the sub heading row and iterate it's array to push the data rows

const headings = ['section', 'total','boys', 'girls', 'subjects', 'class-teacher'];

const rows = [headings];

Object.entries(data).forEach(([k, arr])=>{
    const subHeadRow = Array.from(headings, (el,i) => i ? '' : k); 
    rows.push(subHeadRow)
    arr.forEach(o => rows.push(Object.values(o)));
});

const csv = rows.map(row => row.map(JSON.stringify)).join('\r\n')

console.log(csv)
<script>
const data={"Class-1":[{section:"A",total:"45",boys:"31",girls:"14",subjects:3,"class-teacher":"ABC"},{section:"B",total:"30",boys:"20",girls:"10",subjects:3,"class-teacher":"XYZ"}],"Class-2":[{section:"A",total:"40",boys:"25",girls:"15",subjects:4,"class-teacher":"ABC2"}],"Class-3":[{section:"A",total:"44",boys:"29",girls:"15",subjects:4,"class-teacher":"ABC3"},{section:"B",total:"40",boys:"29",girls:"11",subjects:4,"class-teacher":"XYZ1"}],"Class-4":[{section:"A",total:"50",boys:"30",girls:"20",subjects:5,"class-teacher":"ABC4"}]};
</script>
charlietfl
  • 164,229
  • 13
  • 110
  • 143
2

Per @charlieftl, you don't need D3 to do this. But if you want to use the d3-dsv library then look at d3.csvFormatBody which will take an array of objects and just provide csv formatted row data i.e. no headers.

In the example below, for the 1st row, the headers come from the 1st array item of the 1st key.

Then iterate the keys of the data and for each key output it (e.g. Class-1) on a row, then the rows underneath are from the array property.

// linefeed
const lf = `\r\n`;
// keys of object are Class-1, Class-2 etc
const keys = Object.keys(data);
// get headers from 1st array item of 1st key
const headers = Object.keys(data[keys[0]][0]);
// initialise the csv output with the headers
let csv = `${headers}${lf}`;
// for each key, add the Class-N then the rows (with no headers)
keys.forEach(key => csv += `${key}${lf}${d3.csvFormatBody(data[key])}${lf}`);
// output
console.log(csv);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<script>
const data={"Class-1":[{section:"A",total:"45",boys:"31",girls:"14",subjects:3,"class-teacher":"ABC"},{section:"B",total:"30",boys:"20",girls:"10",subjects:3,"class-teacher":"XYZ"}],"Class-2":[{section:"A",total:"40",boys:"25",girls:"15",subjects:4,"class-teacher":"ABC2"}],"Class-3":[{section:"A",total:"44",boys:"29",girls:"15",subjects:4,"class-teacher":"ABC3"},{section:"B",total:"40",boys:"29",girls:"11",subjects:4,"class-teacher":"XYZ1"}],"Class-4":[{section:"A",total:"50",boys:"30",girls:"20",subjects:5,"class-teacher":"ABC4"}]};
</script>
Robin Mackenzie
  • 14,370
  • 7
  • 36
  • 44