I want to replace string of a particular column from a .csv file in Nodejs
here is my .csv data:
ID,Name,openingBalance,closingBalance
"27G","HARRIS TODD",23.22,465.22
"28G","ANGELO RALPH",124.31,555.20
"28N","GRODKO STEVEN",45.22,
"29A","FOWLER ROBERT",65.25,666.00
"29G","PROVOST BRIAN",,253.11
"300","BECKMAN JUDITH",114.21,878.21
in the closingBalance column there is a blank which I need to be replace as 0.00
I am able to replace the whole data, but not for the specific column,
Can anyone please help?
I used this for replace string :
var fs = require('fs')
fs.readFile(someFile, 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
var result = data.replace(/string to be replaced/g, 'replacement');
fs.writeFile(someFile, result, 'utf8', function (err) {
if (err) return console.log(err);
});
});
You can use regular expression to replace blank cells, but that's easy only for first/last columns:
data.replace(/,$/gm, ',0.00');
See Regex101 for further details and playground
Other way is to parse CSV to AoA:
const csv = `ID,Name,openingBalance,closingBalance
"27G","HARRIS TODD",23.22,465.22
"28G","ANGELO RALPH",124.31,555.20
"28N","GRODKO STEVEN",45.22,
"29A","FOWLER ROBERT",65.25,666.00
"29G","PROVOST BRIAN",,253.11
"300","BECKMAN JUDITH",114.21,878.21`;
const aoa = csv
.split(/\r?\n/g)
.map((row) => {
let [ID, Name, openingBalance, closingBalance] = row.split(',');
// Fix empty values for "openingBalance" column
if (!openingBalance.trim()) {
openingBalance = '0.00';
}
// Fix empty values for "closingBalance" column
if (!closingBalance.trim()) {
closingBalance = '0.00';
}
return [ID, Name, openingBalance, closingBalance]
});
// now you have AoA with fixed values
console.log(aoa.map((row) => row.join(',')).join('\n'))
With this way, you can pre-moderate any column with any code.
You can use regex to find out blank cells for closingBalance column.
The cells for this particular column is the last one in each record which can be easily found by \n and $ in regex.
So to do this:
const result = data.replace(/(,)(?=(\n|$))/g, '$10.00');
of if you want to find out any blank cells, you can use the following regex:
/(,)(?=(,|\n|$))/g
Related
I'm trying to number format the caller cell for a custom function, specifically to replace the scientific notation with a numeric format for big numbers and then auto fit the column width.
An idea is to check the cell text for presence of "E", but the issue is that the formatting code seems to run before the result is written to the cell (which kind of makes sense, honestly), so I'm doing a comparison and set the cell format accordingly. Setting the cell format works fine (it doesn't need the result written to the cell), but auto fitting the column width doesn't.
Here is the custom function code:
getData returns a number (or an error string) from an API call
formatNumber should set the cell number format and autofit the column width, based on the returned number.
async function Test(symbol, metric, date, invocation) {
const address = invocation.address;
return await getData(symbol, metric, date)
.then(async (result) => {
if (!isNaN(result) && result > 99999999999) {
await formatNumber(address);
}
return result;
})
.catch((error) => {
console.log("error: " + error);
return error;
});
}
Here is the formatNumber code.
range.text returns #BUSY, which means the data is still retrieved from the API when the function runs. Due to this, autofitColumns will set the column size based on "#BUSY" string length.
async function formatNumber(address) {
await Excel.run(async (context) => {
const formats = [["#,##0"]];
const range = context.workbook.worksheets.getActiveWorksheet().getRange(address);
range.load("text");
await context.sync();
console.log("range.text: " + range.text);
range.load("numberFormat");
await context.sync();
range.numberFormat = formats;
range.format.autofitColumns();
await context.sync();
});
}
Any ideas?
Thank you for your time,
Adrian
The custom functions return value will be set to the cell after the function is returned.
I suggest your add-in register an onChanged event handler on the worksheet, and call format.autofitColumns() to handle the event;
I am trying to iterate through and existing smartsheet to get the rowIds (which I need for setting parent/child relationships).
I am struggling :-(
Obviously I don't get the required syntax on this one. Here is what I tried:
var options = {
Id: *******************
};
var row_ids = '';
// get the sheet
smartsheet.sheets.getSheet(options)
.then(function(sheetinfo) {
// iterate through the rows array and build comma-delimited list of row ids
for (rowIds in sheetinfo) {
row_ids += row_ids.concat(', ');
}
});
console.log(row_ids);
Any help would be most appreciated.
Bowow99
In the Get Sheet response, sheetInfo contains a collection of rows and each row object in that collection contains the property id. So to successfully implement the scenario you've described, you need to loop through the sheetInfo.rows array, and for each row in that array, append the value of its id property (followed by a comma) to create the comma-delimited string that you're attempting to build. At the end of this loop, there'll be an extra comma at the end (following the last row id you added to the string) -- so you'll need to remove it using the substring function.
The following code does what I've described above. Please note, I'm not a JavaScript expert -- so there may be a more efficient way to do this...but this code gets you the end result you're after: a comma-delimited string of the row Ids within the specified sheet.
var options = {
id: 8337220210845572 // Id of Sheet
};
var row_ids = '';
// Get sheet
smartsheet.sheets.getSheet(options)
.then(function(sheetInfo) {
// iterate through rows in the sheet and build comma-delimited string of row ids
for (var i=0; i < sheetInfo.rows.length; i++) {
row_ids += sheetInfo.rows[i].id + ',';
}
// remove the final (excess) comma from the end of the row_ids string
row_ids = row_ids.substring(0, row_ids.length-1);
console.log(row_ids);
})
.catch(function(error) {
console.log(error);
});
I have the following function which processes my csv file. Unfortunately the csv file has one column where it also uses the comma as thousand separator (I have no influence over this exported csv file and its structure). So in every file from a certain row there will be one extra column.
In the on('data', ()) method, I've already fixed this value by joining the two fields together and deleting the redundant field. But in the end, this still results in rows with an extra column. The 4th column will just be empty by doing this..
I would like to let every field 'shift' to the left when the field is deleted. Is it possible to manipulate this? Or do I need an extra function which processes the output and ignores all 'null' fields.
function readLines(file, options, cb){
let results = [];
fs.createReadStream(file)
.pipe(csv(options))
.on('data', (data) => {
if(Object.keys(data).length == 59){
data['2'] = data['2'] + data['3']
delete data['3']
}
results.push(data)
})
.on('end', () => {
cb(results)
});
}
I've fixed it by filtering the return object in the callback function:
cb(Object.values(results).map((r) => {
return r.filter((x) =>{
return x != null && x !== ""
})
}))
Probably not the most efficient, but the best I could come up with so far.
I need help converting an array of json into lines of text
This is the sample array
var links =
[
{
"file_name": "Night shot of Barcelona, Spain.jpg",
"url": "https://i.imgur.com/uMEags4.jpg",
"full_link": "https://www.reddit.com/r/pics/comments/f4ppj9/night_shot_of_barcelona_spain/",
"downloadId": "cln85w0k4zogv6a"
},
{
"file_name": "Nostalgia.jpg",
"url": "https://i.redd.it/lyxuxk2cemk41.jpg",
"full_link": "https://www.reddit.com/r/pics/comments/fdaaua/nostalgia/",
"downloadId": "cln85w0k4zogv6c"
}
]
I want this in a text format like this:
https://i.imgur.com/uMEags4.jpg
out=Night shot of Barcelona, Spain.jpg
https://i.redd.it/lyxuxk2cemk41.jpg
out=Nostalgia.jpg
There are about 10k objects in the array.I'm planning to download them using aria2c
I'm using a loop like this.
links.forEach((link) => {
})
but I don't know what the next steps are.
EDIT
I used #uday method. But I stored the string in a variable and then stored the string variable into a file
ultUrls.map((link, i) => {
txtstr += `${link.url}\n\tout=${link.file_name} \n\tdir=${dir}\n`
})
fs.writeFile(datapath + '\\'+ 'aria2clinks' + '\\' + textname, txtstr, function(err) {
if (err) {
console.log(err);
}
});
You can use map / forEach to loop through links and write to a file(s) using fs
const fs = require('fs')
links.map((link, i) => {
let data = `${link.url}\nout=${link.file_name} \n\n`
// if you want to write each json data in to new file // replace fileName_${i} as first arg in appendFile()
fs.appendFile('sample.txt', data, function (err) {
if (err) throw err;
});
})
output: sample.txt
https://i.redd.it/lyxuxk2cemk41.jpg
out=Nostalgia.jpg
https://i.imgur.com/uMEags4.jpg
out=Night shot of Barcelona, Spain.jpg
I'm new to Protractor and I'm trying to retrieve only the numeric values contained in the following element
<div class="balances">
<h3>Total Balance: EUR 718,846.67</h3>
</div>
I'm able to retrieve the whole text but would like to be able to print off just "718,846.67" (or should it be 718846.67") via my page object file
checkFigures (figures) {
browser.sleep(8000);
var checkBalance = element.all(by.css('balances'));
checkBalance.getText().then(function (text) {
console.log(text);
});
}
I came across this when someone posted a similar question but I have no idea how to implement it or what it is even doing
function toNumber(promiseOrValue) {
// if it is not a promise, then convert a value
if (!protractor.promise.isPromise(promiseOrValue)) {
return parseInt(promiseOrValue, 10);
}
// if promise - convert result to number
return promiseOrValue.then(function (stringNumber) {
return parseInt(stringNumber, 10);
});
}
This is just a javascript question, and easily acomplished with replace and a regular expression. This will remove all non numerics from the string. Alter the regular expression as needed.
checkFigures (figures) {
browser.sleep(8000);
var checkBalance = element.all(by.css('balances'));
checkBalance.getText().then(function (text) {
console.log(text.replace(/\D/g,''));
});
}