How to load a local csv file into a JavaScript array - javascript

I am able to display the content from a csv file on a web page ( based on what I have found on this site), but how do I read the csv values into an array in JavaScript?
Let's say if I have a file in this CSV format:
Red, Green, Blue,,
Orange, Yellow, Black,,
Indigo, purple, navy,, ...
I appreciate any help.

function UploadCSV() {
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
if (regex.test($("#fileUpload").val().toLowerCase())) {
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function (e) {
try{
var table = $("<table />");
var rows = e.target.result.split("\n");
for (var i = 0; i < rows.length; i++) {
var row = $("<tr />");
var cells = rows[i].split("|");
if (cells.length > 1) {
for (var j = 0; j < cells.length; j++) {
var cell = $("<td />");
var td = cells[j].replace(/[^\x00-\x7F]/g, "");
cell.text(td);
row.append(cell);
}
table.append(row);
}
}
$("#dvCSV").html('');
$("#dvCSV").append(table);
}
catch(e)
{
$('#meessageBar1').text(e.message);
$('#meessageBar1').fadeIn("slow", function () {
setTimeout(messageBar1Remove, 2000);
});
}
}
reader.readAsText($("#fileUpload")[0].files[0]);
} else {
$('#meessageBar1').text('This browser does not support HTML5.');
$('#meessageBar1').fadeIn("slow", function () {
setTimeout(messageBar1Remove, 2000);
});
}
}
}
This is a snippet I used to read data from a PIPE ('|') seperated csv file data into HTML table, you can var cells = rows[i].split("|"); change this line whatever your csv file use as seperator. Here I attach each cell data of each row into of a table row, you can omit this and simply insert whole data into an array. If this helps you, please mark it as accepted answer. Thank you.

Related

How to make a simple catalog that is updated using external file?

I want to make product catalog, suppose 1-4 products in a row, and each product will be in a box with its details and price mentioned. I would like to be able to easily create the catalog based on a XML/CSV File which I can update.. Can any one point me in the right direction on how to achieve it. I am currently familiar with HTML/CSS.. I can pick up on Javascript if required.
Once finished the page will have a header, and then products displayed below.. I intend to print the page to PDF to share with other users..
First of all you should read your file and load from javascript.
Then once loaded, you parse it into JSON object
After this, you can preview the contents inside the HTML
(this is important because we'll use this html table to generate the pdf)
Using the library jsPDF and it's plugin AutoTable we generate a pdf file with the HTML table we generated previously.
This are the sample CSV file I used to test the example
Product,Price,Barcode
Sample product 1,100,802760000926
Sample product 2,95,802760000926
Sample product 3,20,802760000926
You can try it in my fiddle:
https://jsfiddle.net/rogeliomonter/2f9m0qse/
let myList = {};
/*Function to load from CSV file*/
function openFile(event) {
var input = event.target;
var node = document.getElementById('output');
node.innerText = '';
var reader = new FileReader();
reader.onload = function () {
text = reader.result;
//set to myList variable to be used later
myList = JSON.parse(csvJSON(reader.result));
buildHtmlTable('#output');
};
reader.readAsText(input.files[0]);
};
/*this function generates the HTML table*/
function buildHtmlTable(selector) {
var columns = addAllColumnHeaders(myList, selector);
for (var i = 0; i < myList.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) cellValue = "";
row$.append($('<td/>').html(cellValue));
}
$(selector).append(row$);
}
}
/*Supports the function that generates the HTML table*/
function addAllColumnHeaders(myList, selector) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$(selector).append(headerTr$);
return columnSet;
}
/*Converts CSV values into JSON object*/
function csvJSON(csv) {
var lines = csv.split("\n");
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
//return result; //JavaScript object
return JSON.stringify(result); //JSON
}
/*Uses jsPDF libary to generate a PDF File from the HTML table*/
function download() {
// Default export is a4 paper, portrait, using millimeters for units
const doc = new jsPDF();
doc.text("My List", 10, 10);
var columns = ["Product", "Price", "Barcode"];
//Here we use the id of the table
doc.autoTable({ html: '#output' })
doc.save("myList.pdf");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.4/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.5.6/jspdf.plugin.autotable.min.js"></script>
<input type='file' accept='text/csv' onchange='openFile(event)'>
<br>
<!-- the HTML table that will have the csv table -->
<table id='output' border="1"></table>
<br>
<button onclick="download()">Generate PDF</button>

Javascript to read CSV and create two HTML tables

In below code I am trying to create two HTML dynamic tables, but it doesn't work.
One table with ID "Table" and another one with ID "Tabled".
<script type="text/javascript">
function Upload() {
const columns = [0, 3] // represents allowed column 1 and 3 in index form
const dccolumns = [0, 3] // represents allowed column 1 and 3 in index form
var fileUpload = document.getElementById("fileUpload");
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.txt)$/;
if (regex.test(fileUpload.value.toLowerCase())) {
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function (e) {
var table = document.createElement("table");
table.id = 'table'
var tabledc = document.createElement("tabled");
tabled.id = 'tabled'
var rows = e.target.result.split("\n");
for (var i = 0; i < rows.length; i++) { var cells = rows[i].split(","); if (cells.length > 1) {
var row = table.insertRow(-1);
for (var j = 0; j < cells.length; j++) {
// ignore columns that are not allowed
if (!columns.includes(j)) {
continue
}
var rc = cells[j];
if (rc == "SUMMARY") {
var cell = row.insertCell(-1);
cell.innerHTML = cells[j];
alert(rc);
}
}
}
}
var dvCSV = document.getElementById("dvCSV");
dvCSV.innerHTML = "";
dvCSV.appendChild(table);
var alld = document.getElementById("alld");
alld.innerHTML = "";
alld.appendChild(tabled);
}
reader.readAsText(fileUpload.files[0]);
} else {
alert("This browser does not support HTML5.");
}
} else {
alert("Please upload a valid CSV file.");
}
}
When I run above code it just updates table in "Table", but not in "Tabled". I am not sure what wrong I am doing here.
Thanks

0 numeral not recognized when copying data from sheet to a file

I'm trying to create a my own CSV file using info in a google sheet. The info copies correctly, however any time there is a 0 in a cell, it gets ignored and I get a blank spot in my CSV file. Any suggestions? Code below.
function saveAsCSV() {
var filename = "trainingImport"; // CSV file name
var folder = "1vzTFeLwwR35XluyE39Uk9mzbLVJHE3XB"; // Folder ID
var sprdSheet = SpreadsheetApp.getActiveSpreadsheet();
var outPut = sprdSheet.getSheetByName("Output");
var range = outPut.getDataRange();
var values = range.getValues();
var csv = "";
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values.length[i]; j++) {
if (values[i][j]) {
row = row + values[i][j];
}
if (outPut.getRange((i+1),(j+2)).isBlank()) {
break;
}
row = row + ",";
}
csv += row + " \n";
}
var url = DriveApp.getFolderById(folder)
.createFile(filename, csv, MimeType.CSV)
.getDownloadUrl()
.replace("?e=download&gd=true","");
return url;
}
The problem lies in the if statement just in the inner for loop:
if (values[i][j]) {
row = row + values[i][j];
}
The statement will be false, if values[i][j] is 0, beacause 0 is falsy.
That means, that when converted to a Boolean, 0 acts like literal false, this also applies to empty strings, null, undefined and NaN.
If you change it to
if (values[i][j] || values[i][j] === 0) {
row = row + values[i][j];
}
0 will be added to the row.

Deleting a file in Google Script .setTrashed 'You do not have authorization to perform that action.'

I am trying to create a csv file from a Google spreadsheet every day or so. for some reason, I can delete files using the .setTrashed(True) and the file will delete, but i get an error saying 'You do not have authorization to perform that action. '
here is my code. any help would be appreciated.
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// create a folder from the name of the spreadsheet
var folder = DocsList.getFolder(ss.getName().toLowerCase().replace(/ /g,'_'));
for (var i = 0 ; i < sheets.length ; i++) {
var sheet = sheets[i];
// append ".csv" extension to the sheet name
fileName = sheet.getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName, sheet);
// update a file in the Docs List with the given name and the csv data
var folder = DocsList.getFolder('fitbitdata_mk3');
folder.createFile(fileName, csvFile);
deleteDocByName('Sheet1.csv');
Logger.log('deleted');
// folder.createFile(fileName, csvFile); //i put it before the delete
}
Browser.msgBox('UPDATED Files are waiting in a folder named ' + folder.getName());
}
function deleteDocByName(fileName){
var docs=DocsList.find(fileName)
for(n=0;n<docs.length;++n){
if(docs[n].getName() == fileName){
var ID = docs[n].getId()
DocsList.getFileById(ID).setTrashed(true)
}
}
}
function convertRangeToCsvFile_(csvFileName, sheet) {
// get available data range in the spreadsheet
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var csvFile = undefined;
// loop through the data in the range and build a string with the csv data
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// join each row's columns
// add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
I had the same problem. Please star the issue on the issue tracker here.
https://code.google.com/p/google-apps-script-issues/issues/detail?id=4145&colspec=Stars%20Opened%20ID%20Type%20Status%20Summary%20Component%20Owner

HTML5 File API: onload too slow

I new to JavaScript an jQuery and Google doesn't lead to an answer. I am writing a online Ebook reader. This is the code for a library where the user can input multiple epub files and relevant information(like Author) should be displayed in a table. To do this I need to extract the ePub file. The jsZip library works perfect. The contents must be displayed in a table which is dynamically created(since I don't know the amount of files).
The problem is that the for loops is to fast and creates all the cells with only the name and filesize within them and after the for loop completes the onload of the FileReader executes and adds all the contents into the very last cell. In this code the alert("A") happens as many times as files that were inputted before alert("B") happens. Is there some way that I can make the loops wait until the onload of the FileReader is done?
function handleFileSelect(evt) {
var files = evt.target.files;
var rows = Math.ceil(files.length/3);
var a = 0;
var root = document.getElementById('mainTable');
var tab=document.createElement('table');
tab.style.textAlign = "center";
var row, cell;
var tbo=document.createElement('tbody');
for(var i = 0; i != rows; i++)
{
row=document.createElement('tr');
for(var j = 0; (j < 3);j++)
{
cell = document.createElement('td');
cell.height = "300px";
cell.width = "300px"
if(a <indexes.length)
{
var f = files[a];
var str = f.name;
str = str.substring(0, str.length - 5);
str = "File Name: " + str;
cell.appendChild(document.createTextNode(str));
cell.appendChild(document.createElement('br'));
str = "File Size: " + Math.round(f.size/1024) + " KB";
cell.appendChild(document.createTextNode(str));
cell.appendChild(document.createElement('br'));
var reader = new FileReader();
reader.onload = (function(theFile)
{
return function(e)
{
alert("B");
var zip = new JSZip(e.target.result);
$.each(zip.files, function (index, zipEntry)
{
cell.appendChild(document.createTextNode(zipEntry.name));
cell.appendChild(document.createElement('br'));
//row.appendChild(cell);
});
}
})(f);
reader.readAsArrayBuffer(f);
alert("A");
a++;
}
row.appendChild(cell);
}
tbo.appendChild(row);
}
tab.appendChild(tbo);
root.appendChild(tab);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
Your problem is that the variable cell used within your onload handler will refer to the last value assigned to cell in the outer loop. You can get around this by putting the file processing in a separate function which will create it's own scope.
function read_zip_file(f, cell) {
var reader = new FileReader();
reader.onload = (function(theFile)
{
return function(e)
{
alert("B");
var zip = new JSZip(e.target.result);
$.each(zip.files, function (index, zipEntry)
{
cell.appendChild(document.createTextNode(zipEntry.name));
cell.appendChild(document.createElement('br'));
//row.appendChild(cell);
});
}
})(f);
reader.readAsArrayBuffer(f);
}
Then within the outer loop you can call:
read_zip_file(f, cell);

Categories