I want to modify some cells in a CSV file and first read the file and get the data of the part I want. However there is a problem when it saves in that it flattens the rows and also turns the ; characters into , also adding an extra comma to the line I modify.
How can I modify and save a certain cell's data?
var fs = require('fs');
var parse = require('csv-parse');
var parser = parse({delimiter: ';'}, function(err, data){
var row0 = '' + data[0];
var index = row0.split(',')[0];
data[0] = index + ';' + 'Modified Cell Here' + ',' + row0.split(',')[2];
fs.writeFile("./Sample.csv", data, function(err) { if(err) { return console.log(err); }});
console.log(data);
});
fs.createReadStream(__dirname+'/Sample.csv').pipe(parser);
The Sample.csv is:
0;123,abc
1;456,efg
2;789,hij
In the modified Sample.csv it returns as:
0;Modified Cell Here,abc,1,456,efg,2,789,hij
I was expecting this:
0;Modified Cell Here,abc
1;456,efg
2;789,hij
I suspect you could join the array back with a newline before writing
snip::
data[0] = index + ';' + 'Modified Cell Here' + ',' + row0.split(',')[2];
var outputData = data.join('\n') ;
fs.writeFile("./Sample.csv", outputData, function(err) { if(err) { return console.log(err); }});
::snip
Related
I am using the below function to convert a JSON object to a CSV file and download it. This part is doing fine.
const JSONToCSVConvertor = (JSONData, ReportTitle, ShowLabel) => {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData =
typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = '';
//This loop will extract the label from 1st index of on array
for (var index in arrData[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length; i++) {
var row = '';
//2nd loop will extract each column and convert it in string comma-seprated
for (var index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV === '') {
alert('Invalid data');
return;
}
//Generate a file name
var fileName = '';
//this will remove the blank-spaces from the title and replace it with an underscore
fileName += ReportTitle.replace(/ /g, '_');
//Initialize file format you want csv or xls
var uri = 'data:text/csv;charset=utf-8,' + escape(CSV);
// generate a temp <a /> tag
var link = document.createElement('a');
link.href = uri;
//set the visibility hidden so it will not effect on your web-layout
link.style = 'visibility:hidden';
link.download = fileName + '.csv';
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// console.log('finish download one file');
};
Right now I am trying to create a zip file based on the JSON objects. I am planning to use the JSZip library.
for (var i = 0; i < 5; i++) {
zip.file('file' + i + '.csv', escape(CSV));
}
zip.generateAsync({ type: 'base64' }).then((base64) => {
window.location = 'data:application/zip;base64,' + base64;
});
escape(CSV) in the above code snippet is the proper CSV file format. This code snippet does not create a zip file and does not throw any error code. It only brings my current page to about:blank#blocked.
But if I change the second parameter of zip.file() to 'csv data', it works and gives me a zip file.
My solution is
to download the CSV files using the JSONToCSVConvertor function
using the JSZip library to read the CSV files from the local repository and zip them.
I think this way is not the best way to do it, because I have to download multiple CSV files before zipping them.
To answer my question I follow this article to solve my issue
https://huynvk.dev/blog/download-files-and-zip-them-in-your-browsers-using-javascript
What are some alternatives to create a report with additional header/footer information at the top and bottom of the page without entirely revamping the table library for display? I'm currently using Jquery/Bootgrid to load the data into tables
The following function is a working implementation for exporting the list of search results. A CSV file would be available for download.But due to limitations with the "msSaveOrOpenBlob" / CSV format, I cannot include the header/footer information. To clarify, the report does not need to be in CSV format, common formats which can be displayed in a table form will do.
function getVisCol(visibleCol){
$("#searchresult th").each(function(){
visibleCol.push($(this).data('columnId'));
});
}
$(".exportBtn").on('click', function(){
//exportExcel();
form = {
'userId' : $("#inputid").val(),
'name' : $("#inputname").val(),
'age' : $("#inputage").val(),
'country' : $("#inputcountry").val()
}
$.ajax({
type : 'POST',
contentType : "application/json",
url : retrieveUserForExport,
data: JSON.stringify(form),
beforeSend: function(xhr) {
xhr.setRequestHeader(csrfHeader, csrfToken);
},
success:function(jd, textStatus, jqXHR) {
myQuery = JSON.stringify(jd);
var visCol = [];
getVisCol(visCol);
JSONToCSVConvertor(myQuery, "ExportFile", true, visCol);
}
});
});
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel, ignoreColumns) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '' + '\r\n\n';
//Set Report title in first row or line
//CSV += ReportTitle ;
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
//This loop will extract the label from 1st index of on array
for (var index in arrData[0]) {
if(ignoreColumns.indexOf(index) > -1)
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
console.log("CSV value: " + CSV);
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length; i++) {
var row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var index in arrData[i]) {
if(ignoreColumns.indexOf(index) > -1)
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
console.log("CSV2 value: " + CSV);
}
if (CSV == '') {
alert("Invalid data");
return;
}
//Generate a file name
var fileName = "Report_";
//this will remove the blank-spaces from the title and replace it with an underscore
fileName += ReportTitle.replace(/ /g,"_");
//Initialize file format you want csv or xls
var uri = 'data:text/csv;charset=utf-8,' + escape(CSV);
// Now the little tricky part.
// you can use either>> window.open(uri);
// but this will not work in some browsers
// or you will not get the correct file extension
if(window.navigator.msSaveOrOpenBlob) {
var textFileAsBlob = new Blob([CSV], {
type: 'text/plain'
});
//window.navigator.msSaveOrOpenBlob(textFileAsBlob, fileName + ".csv");
} else {
//this trick will generate a temp <a /> tag
var link = document.createElement("a");
link.href = uri;
//set the visibility hidden so it will not effect on your web-layout
link.style = "visibility:hidden";
link.download = fileName + ".csv";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
I am using node.js to develop firebase cloud functions. I need to connect to google maps api to get the distance between two Latlng points. I am making an https get request and receiving a response with a JSon object. The problem is that the received object is empty with a status: INVALID_REQUEST in most cases. However, in some rare cases it returns the desired value. I have tried the path and host of my request on the browser and the json object is retrieved successfully there. I do not know exactly where my problem is. Is it in the callback? the path? something else?
I am giving my code and the output of it.
My code is :
function getStatusCode(options, callback) {
https.get(options, function(http_res) {
var data = "";
console.log('inside the https request');
http_res.on("data", function (chunk) {
data += chunk;
console.log("I am reading the data");
console.log(data);
// callback(http_res.statusCode, data)
});
http_res.on("end", function () {
console.log("I am in the ON_END listener");
console.log('data contains: >> ' + data + ' I am in the ONEND listener')
callback(http_res.statusCode, data)
});
});
}
and I am calling it as follows:
console.log('startingPoints ' + startingPoints);
console.log('lat and lng are: '+lat+" , "+lng);
var options = {
host: 'maps.googleapis.com',
path: '/maps/api/distancematrix/json?units=imperial&origins='+startingPoints+'&destinations='+lat+','+lng+'&key=MY_GOOGLEMAPSAPI_KEY',
method: get
};
getStatusCode(options, function(statusCode, data){
console.log('The status code is : '+statusCode);
console.log('and data is : '+data);
// parsing json object:
jData = JSON.parse(data);
rows = jData.rows;
console.log('the length of the rows array is >> ' + rows.length + ', the length of the techs array is >> ' + techs.length);
min = -1;
for(var i = 0; i < rows.length; i++){
console.log('the array of techs + the equivalent values of the array of row >>' + techs[i] + ' and ' + rows[i].elements[0].distance.value);
if( min < 0 || rows[i].elements[0].distance.value < rows[min].elements[0].distance.value)
min = i;
console.log('minimum distance tech in the loop; the id is >> ' + techs[min] + ", and the distance is >> " + rows[min].elements[0].distance.value);
}
console.log('the min value before return is >> ' + min);
and the retrieved json object is:
{
"destination_addresses" : [],
"origin_addresses" : [],
"rows" : [],
"status" : "INVALID_REQUEST"
}
any idea please,,
I have found a solution. precisely, found my problem. The problem was not within google-map-api. It was with assignment of the starting_points variable.
I have my selenium test set up to take screenshots, but they are not saving to the directory which I have specified. Can anybody show me what I am missing?
Here is how I am configuring the screenshots in the test:
function writeScreenshot(data, name) {
var fs = require('fs');
name = name || 'ss.png';
var screenshotPath = mkdirp(configuration.readSettings('screenshotDirectory') + fileNameURL + "/", function(err){});
fs.writeFileSync(screenshotPath + name, data, 'base64');
};
and then I take the screenshot:
driver.takeScreenshot().then(function(data) {
var screenshotFile = os + '_' + osVersion + '_' + browser + '_' + browserVersion + '.png';
writeScreenshot(data, screenshotFile);
});
The screenshots end up being saved instead in the projects root directory and with the file name preceded by 'undefined'. (ex. undefinedWindows_8_chrome_46.png)
It does, however, create the folders shown here: var screenshotPath = mkdirp(configuration.readSettings('screenshotDirectory') + fileNameURL + "/", function(err){});
So why is this happening?
mkdirp() is an async method. That is why you pass a callback. You will need to change your code to something like the following:
function writeScreenshot(data, name) {
var fs = require('fs');
name = name || 'ss.png';
var screenshotPath = configuration.readSettings('screenshotDirectory') + fileNameURL + "/";
mkdirp(screenshotPath, function(err){
if (err) {
// something else happened while creating the dir. You decide what to do
return;
}
// Otherwise (if dir was created)
fs.writeFileSync(screenshotPath + name, data, 'base64');
});
};
mkdirp() function is asynchronous - it creates a directory and returns nothing - this is why you having that leading undefined in the filename.
Save the file in the callback:
var screenshotPath = configuration.readSettings('screenshotDirectory') + fileNameURL + "/";
mkdirp(screenshotPath, function (err) {
if (!err) {
fs.writeFileSync(screenshotPath + name, data, 'base64');
} else {
// handle error
}
});
Or, synchronously create the directory and write to it this way:
var screenshotPath = configuration.readSettings('screenshotDirectory') + fileNameURL + "/";
if (mkdirp.sync(screenshotPath)) {
fs.writeFileSync(screenshotPath + name, data, 'base64');
}
i want log my user command
function saveLog (nick, command) {
var file = 'log/' + nick + '.log';
var datetime = '[' + getDateTime() + '] ';
var text = datetime + command + '\r\n';
fs.writeFile(file, text, function (err) {
if (err) return console.log(err);
console.log(text);
});
}
the function i made is fine, but
it didnt save the log in new line, its just replace text / rewrite the file.
whats im missing ?
thanks
fs.writeFile writes a WHOLE NEW file. What your are looking for is fs.appendFile which will make the file if it doesn't exist and append to it. Documentation here.
function saveLog (nick, command) {
var file = 'log/' + nick + '.log';
var datetime = '[' + getDateTime() + '] ';
var text = datetime + command + '\r\n';
fs.appendFile(file, text, function (err) {
if (err) return console.log(err);
console.log('successfully appended "' + text + '"');
});
}