How to add header to csv file in more efficient way - javascript

I have a function which writes values to a csv file from an array in some response, but before that I need to provide headers with the field name in the first line for each tab so I have written the headers in using csv += '/t header 1',csv += '/t header 2' and so on.
Here is my block of code
function exportToCsv(fName, rows) {
var csv = 'branch';
csv += '\t customerId';
csv += '\t customerName';
csv += '\t LOAN ID/UT unique ID';
csv += '\n';
for (var i = 0; i < rows.length; i++) {
var row = Object.values(rows[i]);
for (var j = 0; j < row.length; j++) {
var val = '';
val = row[j] === null ? '' : row[j].toString();
if (j > 0)
csv += '\t';
csv += val;
}
csv += '\n';
}
}
Is there any efficient way to write those five lines in above function? The current code is working but I'm looking for a more efficient way to replace these lines.
Also note I have just mentioned a few header names here but I actually have 20 - 30 headers fields.
Please share your thoughts.

If the keys in your row object are the same as the headers you can just use .join to string them into a csvheader. Otherwise, you could use a mapping array to convert a row key into the appropriate header for the CSV. For example:
const row = {
branch: 'Main',
customerId: 45,
customerName: 'Bill',
'LOAN ID/UT unique ID': 'X456Y01'
}
let csvheader = Object.keys(row).join('\t');
console.log(csvheader);
const row2 = {
branch: 'Main',
Id: 45,
Name: 'Bill',
LoanId: 'X456Y01'
};
const map = {
branch: 'branch',
Id: 'customerId',
Name: 'customerName',
LoanId: 'LOAN ID/UT unique ID'
}
csvheader = Object.keys(row2).map(v => map[v]).join('\t');
console.log(csvheader);

I'm not sure with what you mean by efficient (can be processing time, or less lines of code, readability, etc.)
For reference, here's a library that is usually used as a convenience method for processing/generating CSV files. I think this can also be imported to be used in javascript, not just node.js.
https://csv.js.org/stringify/api/
They have options that can be used like putting some headers or even delimiters.
Sample code from their site
const stringify = require('csv-stringify')
const assert = require('assert')
stringify([
[ '1', '2', '3', '4' ],
[ 'a', 'b', 'c', 'd' ]
], function(err, output){
assert.equal(output, '1,2,3,4\na,b,c,d\n')
});
with the headers option: (source: https://csv.js.org/stringify/options/columns/)
stringify( [
{ a: '1', b: '2' }
], {
columns: [ { key: 'a' }, { key: 'b' } ]
}, function(err, data){
assert.equal(data, '1,2\n')
})

Related

calculate list of the sums of each column from csv

I'm trying to calculate sums of each columns of csv. I'm able to read a csv in js using readfile method. I also was able to loop through it and parsed data into array of objects. Now I just to figure out a way to add up all the column elements, that's where I'm struggling. My csv object is in array of object format which looks like this.
[
{ item: '18', count: '180' },
{ item: '19', count: '163' },
{ item: '20', count: '175' },
{ item: '', count: undefined }
]
CSV input is like this:
item,count
18,180
19,163
20,175
I want to add 18 + 19 + 20 and final answer should look like this [57,518].
Here's I've done so far, I just need help to make this better and column wise adding logic in JS, please help.
const fs = require('fs')
let result = []
var dataArray = []
fs.readFile(filename, 'utf8', function (err, data) {
dataArray = data.split(/\r?\n/);
// console.log("dataArray", dataArray)
var headers = dataArray[0].split(",");
for (var i = 1; i < dataArray.length; i++) {
var obj = {};
console.log("dataArray", dataArray)
var currentline = dataArray[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
})
You can iterate through each row of your csv and sum up values of items and count using array#reduce and array#forEach.
const fs = require('fs').promises;
const fileName = 'data.csv'
const calculateSum = async () => {
const data = await fs.readFile(fileName, 'utf-8');
const dataArray = data.split(/\r?\n/);
const header = dataArray[0].split(',')
const result = dataArray.slice(1).reduce((sum, arr) => {
arr.split(',').forEach((v, i) => {
sum[i] = (sum[i] || 0) + Number(v.trim());
})
return sum;
}, []);
console.log(result);
}
Generic function
let dataArray = [
{ item: '18', count: '180' },
{ item: '19', count: '163' },
{ item: '20', count: '175' },
{ item: '', count: undefined }
]
const sums = dataArray.reduce((sum, tableRow) => {
Object.keys(tableRow).forEach((obj) => {
if (Number(tableRow[obj])) sum[obj] = (sum[obj] || 0) + Number(tableRow[obj]);
})
return sum;
}, []);
console.log(sums) // [ item: 57, count: 518 ]

How to sum all values in column?

I'm using exceljs and i must sum all values from my column, how can i do this?
at issue on github, i found one solution, but not work for me:
workSheet.getCell(`B${endRow}`).value = { formula: `SUM(B4:B${endRow-1})` };
because vscode throw me: Type '{ formula: string; }' is not assignable to type 'CellValue'. Type '{ formula: string; }' is missing the following properties from type 'CellSharedFormulaValue': sharedFormula, date1904
can somebody tell me how to sum each values from column?
Ciao, try to modify your code like this:
workSheet.getCell(`B${endRow}`).value = { formula: `SUM(B4:B${endRow-1})`, date1904: false };
Im a bit late im adding this for anyone who came across the same issue.
point number one your array object values must be of type number not string.
I created a method to do that for me which is convertStringToNumber(data);
Example data
[{ItemPrice: 69.99, name: "Kellogs Cornflakes", brand: "Kellogs", Quantity_Purchased: 2, QaunititySaleValue: 139.98}, {ItemPrice: 19.99, name: "Castle Lite", brand: "Castle", Quantity_Purchased: 2, QaunititySaleValue: 39.98}]
Code
async createExcel(data, fileName) {
let xlsData = this.convertStringToNumber(data);
const fs = require('fs')
const workbook = new Excel.Workbook();
const worksheet = workbook.addWorksheet(fileName);
worksheet.columns = [
{ header: 'name', key: 'name', width: 10 },
{ header: 'brand', key: 'brand', width: 32 },
{ header: 'Quantity_Purchased', key: 'Quantity_Purchased', width: 15, },
{ header: 'ItemPrice', key: 'ItemPrice', width: 15, },
{ header: 'QaunititySaleValue', key: 'QaunititySaleValue', width: 15, }
];
worksheet.addRows(xlsData);
const endRow = worksheet.lastRow._number + 1;
worksheet.getCell(`C${endRow}`).value = { formula: `SUM(C2:C${endRow - 1})` };
worksheet.getCell(`D${endRow}`).value = { formula: `SUM(D2:D${endRow - 1})` };
worksheet.getCell(`E${endRow}`).value = { formula: `SUM(E2:E${endRow - 1})` };
// save under export.xlsx
let buffResult = await workbook.xlsx.writeBuffer();
fs.writeFileSync(fileName + ".xlsx", buffResult); }
convertStringToNumber(objects) {
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && obj[prop] !== null && !isNaN(obj[prop])) {
obj[prop] = +obj[prop];
}
}
}
return objects; }
Output

JSON to excel conversion

I am converting JSON data to an excel file format. So far I have been able to create a file with the data.
I am looking forward to add a custom message to be displayed (image below) in the first row and thereafter data should be displayed in the file with column headers.
I have taken reference from this stackblitz link
How can I achieve this ?
New Issue
Missing headers firstName, lastName, email, phone
I assume when you say JSON, you mean a Javascript object that have been parsed from a JSON file.
in my example it's myObject.
We create a worksheet using XLSX.utils.json_to_sheet(myObject);
We add a row to the start of the worksheet using: XLSX.utils.sheet_add_aoa(myWorkSheet, [["Your Mesage Goes Here"]], { origin: 0 });
this will insert an aoa (array of arrays) to a new row at the position defined by origin.
{ origin: 0 } means first row
{ origin: 1 } means 2nd row
{ origin: -1 } means last row
in our case we add just one cell (A1) with the content: "Your Mesage Goes Here"
we merge the cells in range A1:D1 (4 cells) using myWorkSheet['!merges'] = [{ s: 'A1', e: 'D1' }];
The rest is self explanatory I think
Here's a working example
myObject = [
{ name: "Moran", role: "back" },
{ name: "Alain", role: "front" },
{ name: "Tony", role: "back" },
{ name: "Mike", role: "back" },
{ name: "Abo", role: "back" },
{ name: "Toni", role: "back" }
];
function exportWS() {
var myFile = "myFile.xlsx";
var myWorkSheet = XLSX.utils.json_to_sheet(myObject);
var myWorkBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(myWorkBook, myWorkSheet, "myWorkSheet");
XLSX.writeFile(myWorkBook, myFile);
}
function exportWSPlus() {
var myFile = "myFilePlus.xlsx";
var myWorkSheet = XLSX.utils.json_to_sheet(myObject);
XLSX.utils.sheet_add_aoa(myWorkSheet, [["Your Mesage Goes Here"]], { origin: 0 });
var merges = myWorkSheet['!merges'] = [{ s: 'A1', e: 'D1' }];
var myWorkBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(myWorkBook, myWorkSheet, "myWorkSheet");
XLSX.writeFile(myWorkBook, myFile);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.14.3/xlsx.full.min.js"></script>
<button type="button" onclick="exportWS()">Export Worksheet</button>
<button type="button" onclick="exportWSPlus()">Export Worksheet+</button>
feel free to ask any questions you may have.
I researched about this a lot and finally I could come up with a solution to this.
public exportAsExcelFile(json: Array<object>, excelFileName: string): void {
var worksheet: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet([
[`${excelFileName}`]]); // message to display
worksheet['!merges'] = [{ s: { r: 0, c: 0 }, e: { r: 0, c: 3 } }]; //for merging columns. s : start, e: end, c: column, r: row
XLSX.utils.sheet_add_json(worksheet, json, { origin: "A2" }); //origin for json data
const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
var range = XLSX.utils.decode_range(worksheet['!ref']);
for (var C = range.s.r; C <= range.e.r; ++C) {
var address = XLSX.utils.encode_col(C) + "1";
if (!worksheet[address]) continue;
worksheet[address].v = worksheet[address].v.charAt(0).toUpperCase() + worksheet[address].v.substr(1).toLowerCase();
}
}

Group json object in javascript

I want to group json array by first letter
This is my data records it quesry from sqlitedb
Ex :
[
{"pid":2,"ID":1,"title":"aasas as"},
{"pid":3,"ID":2,"title":"family"},
{"pid":4,"ID":3,"title":"fat111"}
]
I need this output
{
A: [{
title: "aasas as",
ID: 1
}],
F: [{
title: "family",
ID: 2
}, {
title: "fat111",
ID: 3
}]
}
Try this
var data = [
{"pid":2,"ID":1,"title":"aasas as"},
{"pid":3,"ID":2,"title":"family"},
{"pid":4,"ID":3,"title":"fat111"}
];
var result = {},
i,
len = data.length,
key;
for (i = 0; i < len; i++) {
key = data[i].title.substring(0, 1); // get first word from string
if (!result[key]) { // if key does not exists in result, create it
result[key] = [];
}
result[key].push(data[i]); // else push data
}
console.log(result);

Javascript: convert Object into array or JSON for Gephi / Sigma.Js

Hello I have the following Javascript code where I try to convert the object obtained from Neo4J database into a nice array or JSON (I'll be able to deal with one of the two) for further use with Gephi / Sigma.
But it doesn't work...
Any idea why?
var myObj = [
[ 'b7145841-962f-11e3-8b8e-abca0f9fdedd',
'painquotidien',
'b7145842-962f-11e3-8b8e-abca0f9fdedd',
'cafeamour',
'b7145843-962f-11e3-8b8e-abca0f9fdedd' ],
[ 'cce97c91-962f-11e3-8b8e-abca0f9fdedd',
'hotelamour',
'b7145842-962f-11e3-8b8e-abca0f9fdedd',
'cafeamour',
'19fe2713-9630-11e3-8b8e-abca0f9fdedd' ]
];
var nodes = {
id: '',
label: ''
};
var edges = {
source: '',
target: '',
id: ''
};
for (var i = 0; i < myObj.length; i++) {
nodes['id'].push(myObj[i][0]);
nodes['label'].push(myObj[i][1]);
nodes['id'].push(myObj[i][2]);
nodes['label'].push(myObj[i][3]);
edges['source'].push(myObj[i][0]);
edges['target'].push(myObj[i][2]);
edges['id'].push(myObj[i][4]);
}
Already searched on StackOverflow and elsewhere, but none of the solutions provided worked for me, probably because it's a multi-dimensional array that I need and of a slightly different structure than the object (see the code above).
Thank you for your help!
This code works:
var nodes_object = myObj;
var g = {
nodes: [],
edges: []
};
for (var i = 0; i < nodes_object.length; i++) {
g.nodes.push({
id: nodes_object[i][0],
label: nodes_object[i][1]
});
g.nodes.push({
id: nodes_object[i][2],
label: nodes_object[i][3]
});
g.edges.push({
source: nodes_object[i][0],
target: nodes_object[i][2],
id: nodes_object[i][4],
edge_context: nodes_object[i][5]
});
};

Categories