remove blank lines when uploading csv files angular - javascript

I got a csv-reader directive and let's user upload a csv file. I noticed that when I upload a file with spaces between words for example:
abc
abc
abc
abc
abc
this gets shown. I want to delete all the blank lines Not sure what to do.
var reader = new FileReader();
reader.onload = function(e) {
var contents = e.target.result;
var rows = contents.split('\n');
// Check if the last row is empty. This works
if(rows[rows.length-1] ===''){
rows.pop()
}
}
// this doesn't work for some reason. It doesn't detect the '' in the middle of the arrays.
for( var i=rows.length-1;i>0;i--){
if(rows[i] === ''){
rows.splice(i,1)
}
}

Try using Array.prototype.filter()
var rows = contents.split('\n').filter(function(str){
return str;
});

From what you have shown it looks like you want to check if each item in the csvModel is an empty string, rather than newValue
Something like:
for( var i=0 ;i< $scope.csvModel.length; i++){
if (csvModel[i] == "") {
$scope.csvModel.splice(i,1);
}
}

var text = [];
var target = $event.target || $event.srcElement;
var files = target.files;
if(Constants.validateHeaderAndRecordLengthFlag){
if(!this._fileUtil.isCSVFile(files[0])){
alert("Please import valid .csv file.");
this.fileReset();
}
}
var input = $event.target;
var reader = new FileReader();
reader.readAsText(input.files[0], 'UTF-8');
reader.onload = (data) => {
let csvData = reader.result;
let csvRecordsArray = csvData.split(/\r\n|\n/);
if (csvRecordsArray[csvRecordsArray.length - 1] === '') {
csvRecordsArray.pop();
}
var headerLength = -1;
if(Constants.isHeaderPresentFlag){
let headersRow = this._fileUtil.getHeaderArray(csvRecordsArray, Constants.tokenDelimeter);
headerLength = headersRow.length;
}
this.csvRecords = this._fileUtil.getDataRecordsArrayFromCSVFile(csvRecordsArray,
headerLength, Constants.validateHeaderAndRecordLengthFlag, Constants.tokenDelimeter);
if(this.csvRecords===null){
this.csvRecords=[];
}
else if(this.csvRecords!==null) {
if ((JSON.stringify(this.csvRecords[0])) === (JSON.stringify(this.csvFormate))) {
alert("format matches");
this.displayCsvContent = true;
for (let i = 0; i < this.csvRecords.length; i++) {
if (i !== 0) {
this.csvRecords[i].push(this.recordInsertedFlag);
}
}
}
else {
alert("format not matches");
}
}
if(this.csvRecords == null){
this.displayCsvContent=false;
//If control reached here it means csv file contains error, reset file.
this.fileReset();
}
};
reader.onerror = function () {
alert('Unable to read ' + input.files[0]);
};

Related

JQuery FileReader onload not firing

I have a multiple file uploading. When I upload the images and binding to the model as follows not firing the FileReader onload function. It skip and fire remain
Here is my code
imageSelect: function (e) {
var dataModel = bindViewModel.selected.attachments;
var reader = new FileReader();
reader.onload = function () {
var uploadImg = new Image();
uploadImg.onload = function () {
for (var i = 0; i < e.files.length; i++) {
if (e.files[i].size < 1048576) {
var attachmentName = e.files[i].name;
var attachment = { id: i, citationId: bindViewModel.selected.id, attachmentName: attachmentName, attachmentUrl: reader.result };
dataModel.push(attachment);
if (dataModel[0].attachmentName == "" && dataModel[0].attachmentUrl == "") {
dataModel.splice($.inArray(dataModel[0], dataModel), 1);
}
uploadImg.src = reader.result;
reader.readAsDataURL(e.files[i].rawFile);
}
else {
app.ShowNotifications("Error", 'The ' + e.files[i].name + ' size greater than 1MB. \r\n Maximum allowed file size is 1MB.', "error");
}
}
};
};
}
Any one can have to help me?

sheetjs excel to json - adding extra <tr> for each row

I couldn't find anything on SO that matched my question. I'm using Sheetjs plugin to convert an excel sheet into json, and displaying it using jquery in the browser. I'm able to do the conversion and display, but I have a use-case where I need to validate each of the json rows with data returned from a jquery ajax 'GET' call.
I'm able to perform that validation as well. Once each excel json row is validated against the values from the ajax response, based on a set of rules, the excel json row is marked either a success row or an error row. For success rows, I perform no action. For error row, I need to add an additional key/value pair in the json element, denoting the error type, and the error description. Further, this error row, when displayed in the browser needs to have a css style with a color:red for red text, to indicate an error.
I haven't seen anything in Sheetjs documentation that might allow me to do this, but I'm pretty sure it can be done. In the code below, I have to modify the helper function called BindTable() in order to add the css style to set the text color to red IF it is an error row. I also have to somehow add a for each of the error rows in order to display the error type and error description.
In the below code, I need to be able to display the invalidRequests JSON object with the css style applied to display the text in red color. Or, if there is a way to directly manipulate the exceljson JSON object to somehow append the key/value pairs of MSG1/message to each of the error rows, that would be even better. I realize that due to the nature of this question, I can't create a jsfiddle, but any ideas/suggestion/comments would be extremely helpful, even if it doesn't provide the complete solution.
Expected format:
author1 JOHN DOE USA N.AMERICA
ERROR: THIS AUTHOR NAME ALREADY EXISTS IN THE SYSTEM!
This is the code that I currently have:
//Excel Reader
function ExcelToTable(event) {
event.preventDefault();
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.xlsx|.xls)$/;
/*Checks whether the file is a valid excel file*/
if (regex.test($("#excelfile").val().toLowerCase())) {
var xlsxflag = false; /*Flag for checking whether excel is .xls
format or .xlsx format*/
if ($("#excelfile").val().toLowerCase().indexOf(".xlsx") > 0) {
xlsxflag = true;
}
/*Checks whether the browser supports HTML5*/
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function (e) {
var data = e.target.result;
//pre-process data
var binary = "";
var bytes = new Uint8Array(data);
var length = bytes.byteLength;
for(var i=0;i<length;i++){
binary += String.fromCharCode(bytes[i]);
}
// /pre-process data
/*Converts the excel data in to object*/
if (xlsxflag) {
// var workbook = XLSX.read(data, { type: 'binary' });
var workbook = XLSX.read(binary, {type: 'binary'});
}
else {
var workbook = XLS.read(binary, { type: 'binary' });
}
/*Gets all the sheetnames of excel in to a variable*/
var sheet_name_list = workbook.SheetNames;
// console.log('Sheet name list : ' + sheet_name_list);
var cnt = 0; /*This is used for restricting the script to
consider only first sheet of excel*/
// sheet_name_list.forEach(function (y) { /*Iterate through
all sheets*/
/*Convert the cell value to Json*/
if (xlsxflag) {
exceljson =
XLSX.utils.sheet_to_json(workbook.Sheets['CUSTOM_EXCEL_TAB'],{defval:
"NULL"});
var emptyAuthorCells =[];
var invalidCountryCells = [];
Object.keys(exceljson).forEach(function(value, key) {
if(exceljson[key].AUTHOR == 'ADD'){
}
else if(exceljson[key].AUTHOR == 'NULL'){
emptyAuthorCells.push({'MARKET':
exceljson[key].MARKET, 'REGION':exceljson[key].REGION,
'PARTNER':exceljson[key].PARTNER, 'AUTHOR': exceljson[key].AUTHOR });
}
//check effective end date
if((exceljson[key].DATE_ENDING != '') ||
(exceljson[key].DATE_ENDING <= getTodayDate())){
invalidCountryCells.push({
'MARKET': exceljson[key].MARKET,
'REGION':exceljson[key].REGION, 'PARTNER':exceljson[key].PARTNER, 'AUTHOR':
exceljson[key].AUTHOR
});
}
});
var emptyActionCellsMessage = "There were " +
emptyAuthorCells.length + " rows with Author=Null <br />";
var completedActionCellsMessage = " Success! There
were " + emptyAuthorCells.length + " rows with authro=Null <br />";
var invalidDateMsg = "There are missing or incorrect
date values.";
var validCompareDataMessage = "Success! All data has been successfully validated!";
var invalidCompareDataMessage = "Validation Failed!
Data does not match Rules.";
}
else {
var exceljson =
XLS.utils.sheet_to_row_object_array(workbook.Sheets[y]);
}
var conflictRows = [];
var returnedRows = [];
var errorReturnedRows = [];
if(emptyAuthorCells.length == 0){
var uniqueAuthor = $.unique(exceljson.map(function
(d){
return d.MARKET;
}));
var doAllValidations = function(){
var ajaxList = [];
var ajxIndex = 1;
$.each(uniqueAuthor, function (index, value){
var jqResponse =
$.ajax({
type: "get",
url: "authorlist.cfm?method=getlist&name=" +
value,
dataType: "json"
});
ajaxList.push(jqResponse);
jqResponse.then(
function( apiResponse ){
$.each (apiResponse, function (cc) {
if(apiResponse[cc].hasOwnProperty('SUCCESS')){
errorReturnedRows.push({
'success':
apiResponse[cc].SUCCESS,
'message':
apiResponse[cc].MESSAGE,
'country_code' : value
});
}
else{
returnedRows.push(apiResponse[cc]);
}
// }
// }
});
}
);
});
return ajaxList;
};
// /LOOP OVER country_code
}
var invalidRequests = [];
var validRequests = [];
$(function() {
var ajaxCalls = doAllValidations();
//begin apply
$.when.apply($, ajaxCalls).done(function(){
//console.log(ajaxList);
$('#hidReturnedRows').val();
$('#hidReturnedRows').val(JSON.stringify(returnedRows));
if (exceljson.length > 0 && cnt == 0) {
if((emptyAuthorCells.length != 0) ||
(errorReturnedRows.length!=0) ) {
//data is invalid
console.log("data is invalid");
$('#displayErrors tr
td.previewSuccessClass').html("");
$('#displayErrors tr
td.previewErrorsClass').html(emptyActionCellsMessage);
$('#export-file').addClass('hidebtn');
}
else{
//outer loop
var found = false;
var book_found = false;
var response_validation_errors = [];
var message = "The author's zone is
incorrect";
var message2 = "This book already
exists";
$.each(exceljson, function(x, ej){
// console.log("inside outer
loop");
found = false;
$.each(returnedRows, function(y,
rr){
//compare inner row with outer
row to make sure they're the same
if(rr.AUTHOR_ID == ej.ID &&
rr.AUTHOR_NAME == ej.NAME)
{
if((rr.AUTHOR ==
ej.NATIVE_AUTHOR) && (rr.BOOK_QUALITY == ej.AUTHOR_ZONE)){
// console.log("found!");
found = true;
}
}
});
if(found){
invalidRequests.push({
"AUTHOR": ej.NAME,
"AUTHOR_ZONE":
ej.AUTHOR_ZONE,
"COUNTRY": ej.COUNTRY
});
}
else{
validRequests.push(ej);
}
});
// /outer loop
}
BindTable(exceljson, '#exceltable');
cnt++;
}
})();
//end apply
});
};
if (xlsxflag) {/*If excel file is .xlsx extension than creates a
Array Buffer from excel*/
reader.readAsArrayBuffer($("#excelfile")[0].files[0]);
}
else {
reader.readAsBinaryString($("#excelfile")[0].files[0]);
}
}
else {
alert("Sorry! Your browser does not support HTML5!");
}
}
else {
alert("Please upload a valid Excel file!");
}
}
//Helper funcs
function BindTable(jsondata, tableid, invalidreqs) {/*Function used to convert the JSON
array to Html Table*/
var columns = BindTableHeader(jsondata, tableid); /*Gets all the column
headings of Excel*/
//ADDED .map() & .find() INSTEAD OF NESTED LOOPS
jsondata.map(a => {
// SEARCH FOR AN ELEMENT IN invalidreqs THAT MATCH THE
// CRITERIA TESTED FOR IN THE FUNCTION
if (invalidreqs.find(b => {
return a.AUTHOR == b.AUTHOR && a.BOOKNAME == b.BOOKNAME && a.COUNTRY ==
b.COUNTRY;
})) {
a.MSG = "THIS ROW ALREADY EXISTS";
}
});
console.log (jsondata);
//THE BELOW CODE NEEDS TO BE CHANGED
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = jsondata[i][columns[colIndex]];
row$.append($('<td/>').html(cellValue));
}
//console.log("before table append");
$(tableid).append(row$);
if( has_error ){
row$.addClass( 'response-errors' );//add class to make text red
var error_row = $('<tr/>');
var error_cell = $('<td/>');
error_cell.attr('colspan', column.length); //set cols to span lenght of row
error_cell.html("SET ERROR MESSAGE TO DISPLAY BASED ON invalidreq object");
error_row.append( error_cell );
$( tableid ).append( error_row );
}
}
// /Outer loop
}
function BindTableHeader(jsondata, tableid) {/*Function used to get all
column names from JSON and bind the html table header*/
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < jsondata.length; i++) {
var rowHash = jsondata[i];
for (var key in rowHash) {
if (rowHash.hasOwnProperty(key)) {
if ($.inArray(key, columnSet) == -1) {/*Adding each unique
column names to a variable array*/
columnSet.push(key);
// console.log(key);
headerTr$.append($('<th/>').html(key));
}
}
}
}
$(tableid).append(headerTr$);
return columnSet;
}
Ok so what you want to do is:
1) Assign the row index to the invalidRequests object, on line 191 like this:
invalidRequests.push({
"AUTHOR": ej.NAME,
"AUTHOR_ZONE": ej.AUTHOR_ZONE,
"COUNTRY": ej.COUNTRY,
"index": x,
"MSG1": "Put the error message here"
});
Now it is very easy to determine which row has an error.
Since the invalidRequests is a private object of the ExcelTable function, you will need to
2) pass it on to the BindTable function like this:
BindTable(exceljson, '#exceltable', invalidRequests);
3) modify the BindTable function to check for invalidRequests and handle them:
function BindTable(jsondata, tableid, invalidreqs) {
var columns = BindTableHeader(jsondata, tableid);
for (var i = 0; i < jsondata.length; i++) {
//look for rows with error
var has_error = false
var invalidreq
for(var u=0;u<invalidreqs.length;u++){
if(i==invalidreqs[u].index){
//found invalid request belonging to current row, set flag
has_error = true
invalidreq = invalidreqs[u] // and store the current invalidrequest infos on temp obj
//break - not really needed
}
}
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = jsondata[i][columns[colIndex]];
row$.append($('<td/>').html(cellValue));
}
$(tableid).append(row$);
if(has_error){
row$.addClass('error') // add css class which will make the text red or whatever
var error_row = $('<tr/>') // create error row
var error_cell = $('<td/>')
error_cell.attr('colspan',columns.length) // set column to span over all columns of table
error_cell.html(invalidreq.MSG1)
error_row.append(error_cell)
$(tableid).append(error_row);
}
}
}
Please note it is not clear, nor specified in your code, in which column the error should appear. Try to implement that yourself by pushing that info into the invalidRequests object and reading it out on BindTable.

Why does my redirect is not working?

my script calls my redirect function to early, so the last file of a batch upload is failing. I have been search the whole morning an tried different approaches, but without success.
function uploadFile(something, callback) {
var fileInput = $('#fileList1');
//var reader = new FileReader();
console.log(fileInput);
if ( trim( fileInput.val() ).length == 0 ) {
return;
}
var fileList = [];
count = fileInput[0].files.length;
for(i = 0; i < count; i++){
loadFile(fileInput[0].files[i]);
}
function loadFile(file){
var reader = new FileReader();
var fileName = getFileNameWithExtension( file);
var file = file;
while(reader.onprogress){
console.log("reading");
}
reader.onload = function(event) {
var val = reader.result;
var text = val.split(',')[1];
saveFile( fileName, text, parentId );
if (!--count){
redirect();
}
}
reader.onerror = function(event) {
console.error("File could not be read! Code " + reader.error.message);
}
reader.readAsDataURL(file);
}
}
function redirect(){
window.location.href = '/{!tempID}';
return false;
}
Can someone give me a hint?
#
Hello, i have rewritten my methods a bit based on your suggestions. But the redirect is still called to early,...before all uploads are done.
function uploadFile() {
var fileInput = $('#fileList1');
console.log(fileInput);
if ( trim( fileInput.val() ).length == 0 ) {
return;
}
var countTwo = 0;
count = fileInput[0].files.length;
for(var i = 0; i < count; i++){
loadFile(fileInput[0].files[i], function(val){
console.log(val);
if(val === 3){
setTimeout(()=>{redirect();}, 5000);
}
});
}
function loadFile(file, callback){
var reader = new FileReader();
var fileName = getFileNameWithExtension( file);
var file = file;
while(reader.onprogress){
console.log("reading");
}
reader.onload = function(event) {
var val = reader.result;
var text = val.split(',')[1];
saveFile( fileName, text, parentId );
console.log(" ct " + countTwo + " c " + count-1);
countTwo++;
if(!--count) callback(countTwo);
}
reader.onerror = function(event) {
console.error("File could not be read! Code " + reader.error.message);
}
reader.readAsDataURL(file);
}
}
Method 1: (Recommended)
Detect when your uploading ends. And in that callback, call redirect.
Method 2:
// define your TIMEOUT first
setTimeout(()=>{redirect();}, TIMEOUT);
reader.onload = function(event) {
var val = reader.result;
var text = val.split(',')[1];
saveFile( fileName, text, parentId );
if (!--count){
setTimeout(()=>{redirect();}, 0);
}
}

How to log contents of HTML5 drag and drop file that is 60MB+ without hanging for minutes?

I have a file that i want to drop on a page and read file contents. its a CSV with 9 columns. My drop command outputs file contents like this:
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.files[0];
var fileReader = new FileReader();
fileReader.onload = function (e) {
console.log(fileReader.result)
};
fileReader.onerror = function (e) {
throw 'Error reading CSV file';
};
// Start reading file
fileReader.readAsText(data);
return false;
}
When I drag and drop a simple file that is a couple kilobytes or 1MB, I can see the output of the contents of the file. However given a large CSV file, it takes many many minutes before it shows up. Is there a way to make it so that there is some streaming maybe where it does not look like its hanging?
With Screw-FileReader
You can get a ReadableStream and do it in a streaming fashion
'use strict'
var blob = new Blob(['111,222,333\naaa,bbb,ccc']) // simulate a file
var stream = blob.stream()
var reader = stream.getReader()
var headerString = ''
var forEachLine = function(row) {
var colums = row.split(',')
// append to DOM
console.log(colums)
}
var pump = function() {
return reader.read().then(function(result) {
var value = result.value
var done = result.done
if (done) {
// Do the last line
headerString && forEachLine(headerString)
return
}
for (var i = 0; i < value.length; i++) {
// Get the character for the current iteration
var char = String.fromCharCode(value[i])
// Check if the char is a new line
if (char.match(/[^\r\n]+/g) !== null) {
// Not a new line so lets append it to
// our header string and keep processing
headerString += char
} else {
// We found a new line character
forEachLine(headerString)
headerString = ''
}
}
return pump()
})
}
pump().then(function() {
console.log('done reading the csv')
})
<script src="https://cdn.rawgit.com/jimmywarting/Screw-FileReader/master/index.js"></script>
If you prefer using the old FileReader without dependencies, pipe's and transform
'use strict'
var blob = new Blob(['111,222,333\naaa,bbb,ccc']) // simulate a file
var fr = new FileReader()
var headerString = ''
var position = 0
var forEachLine = function forEachLine(row) {
var colums = row.split(',')
// append to DOM
console.log(colums)
}
var pump = function pump() {
return new Promise(function(resolve) {
var chunk = blob.slice(position, position + 524288)
position += 524288
fr.onload = function() {
var value = fr.result
var done = position >= blob.size
for (var i = 0; i < value.length; i++) {
var char = value[i]
// Check if the char is a new line
if (char.match(/[^\r\n]+/g) !== null) {
// Not a new line so lets append it to
// our header string and keep processing
headerString += char
} else {
// We found a new line character
forEachLine(headerString)
headerString = ''
}
}
if (done) {
// Send the last line
forEachLine(headerString)
return resolve() // done
}
return resolve(pump())
}
// Read the next chunk
fr.readAsText(chunk)
})
}
pump().then(function() {
console.log('done reading the csv')
})

JavaScript error with splitting string into array

I am running into an issue with splitting a string into an array. To help myself troubleshoot the problem, I included two alert() functions, but only one gets called. Therefore, I know that there is an issue splitting a string into an array (for a basic username/password check). Here is my JS code:
function check() {
var user = document.loginform.usr.value;
var pass = document.loginform.psw.value;
var valid = false;
var txt = new XMLHttpRequest();
var alltext = "";
var allLines = [];
var usrn = [];
var pswd = [];
txt.open("GET", "/c.txt", true);
alltext = txt.responseText;
allLines = alltext.split(/\r\n|\n/);
usrn = allLines[0].split(',');
alert("usrn split");
pswd = allLines[1].split(',');
alert("pswd split");
for (var i=0; i <usrn.length; i++) {
if ((user == usrn[i]) && (pass == pswd[i])) {
valid = true;
break;
}
}
if(valid) {
window.location = "test.html";
return false;
}else{
var div = document.getElementById("login");
div.innerHTML = '<font color="red" size=2><i>Invalid Username/Password!</i></font><br>' + div.innerHTML;
}
}
The file that contains the login credentials (c.txt) is as follows:
User1,User2
pass,password
When User1 enters his/her name into the form, the password should be "pass". However, the script gets stopped at "pswd = allLines[1].split(',');". Am I misunderstanding the lines array?
Any help is appreciated - thanks!
You need to either use a synchronous call by changing the line to
txt.open("GET", "/c.txt", false);
Or use the "onreadystatechange" event to get the response when the server returns it
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
alltext = txt.responseText;
allLines = alltext.split(/\r\n|\n/);
usrn = allLines[0].split(',');
alert("usrn split");
pswd = allLines[1].split(',');
alert("pswd split");
for (var i=0; i <usrn.length; i++) {
if ((user == usrn[i]) && (pass == pswd[i])) {
valid = true;
break;
}
}
if(valid) {
window.location = "test.html";
return false;
}else{
var div = document.getElementById("login");
div.innerHTML = '<font color="red" size=2><i>Invalid Username/Password!</i></font><br>' + div.innerHTML;
}
}
}
You need to call txt.send(). Also it is async so txt.responseText will most likely be null.
You can use onreadystatechanged like so to ensure that txt.responseText has a value:
txt.onreadystatechange = function() {
if (txt.readyState == 4) { // 4 = DONE
alert(txt.responseText);
}
}
Okay - after fiddling with the code and doing some more research, I got a working script. This script takes data from a form and checks it against a file (c.txt). If the form entries match a username/password combination in c.txt, it takes you to another webpage.
function check() {
var user = document.loginform.usr.value;
var pass = document.loginform.psw.value;
var valid = false;
var txt;
if(window.XMLHttpRequest){
txt = new XMLHttpRequest();
}else{
txt = new ActiveXObject("Microsoft.XMLHTTP");
}
var allLines = [];
var usrn = [];
var pswd = [];
txt.onreadystatechange=function() {
if(txt.readyState==4 && txt.status==200){
var alltext = txt.responseText;
allLines = alltext.split(/\r\n|\n/);
usrn = allLines[0].split(',');
pswd = allLines[1].split(',');
for (var i=0; i <usrn.length; i++) {
if ((user == usrn[i]) && (pass == pswd[i])) {
valid = true;
break;
}
}
if(valid) {
window.location = "test.html";
return false;
}else{
var div = document.getElementById("login");
div.innerHTML = '<font color="red" size=2><i>Invalid Username/Password!</i></font><br>' + div.innerHTML;
}
}
}
txt.open("GET", "c.txt", false);
txt.send();
}

Categories

Resources