XLSX parser for parsing excel - javascript

I am trying to parse xlsx file and save as a table (Along the lines of Excel to JSON javascript code? which is working fine for xls files). However, I am unable to convert to json and display as a table. Please find below the code snippet. Can anyone please guide how to close on this.
function filePicked(oEvent) {
// Get The File From The Input
var oFile = oEvent.target.files[0];
var sFilename = oFile.name;
// Create A File Reader HTML5
var reader = new FileReader();
// Ready The Event For When A File Gets Selected
reader.onload = function(e) {
var data = e.target.result;
var cfb = XLSX.read(data, {type: 'binary'});
var wb = XLSX.parse_xlscfb(cfb);
wb.SheetNames.forEach(function(sheetName) {
// Obtain The Current Row As CSV
//var sCSV = XLSX.utils.make_csv(wb.Sheets[sheetName]);
var data = XLSX.utils.make_json(wb.Sheets[sheetName], {header:1});
alert(data.length);
//var columns = data[0].split(",");
$.each(data, function( indexR, valueR ) {
var sRow = "<tr>";
$.each(data[indexR], function( indexC, valueC ) {
sRow = sRow + "<td>" + valueC + "</td>";
});
sRow = sRow + "</tr>";
$("#my_file_output").append(sRow);
});
});
};
// Tell JS To Start Reading The File.. You could delay this if desired
reader.readAsBinaryString(oFile);
}

use this code :
note: use jszip.js and xlsx.js library
reader.onload = function(evt) {
debugger;
var data = evt.target.result;
//var xlsx = XLSX.read(data, {type: 'binary'});
var arr = String.fromCharCode.apply(null, new Uint8Array(data));
var xlsx = XLSX.read(btoa(arr), {
type: 'base64'
});
result = xlsx.Strings;
result = {};
xlsx.SheetNames.forEach(function(sheetName) {
var rObjArr = XLSX.utils.sheet_to_row_object_array(xlsx.Sheets[sheetName]);
if (rObjArr.length > 0) {
result[sheetName] = rObjArr;
}
});
return result;
// that.b64toBlob(xlsx, "binary");
};
reader.readAsArrayBuffer(file);
use readAsArrayBuffer method which will support on all browser.

Related

Parse Excel file and create a hash structure(key/value)

I have an Excel file with the following template.
Name, Surname, Class
Alex, Smith, B1,
Maria, Smith, B2
The Excel file has multiple sheets with data in different languages.
I want to read from the Excel file and to create a hash structure (key/value) because I want to add later more information in each entry.
I have achieved to set the keys names for each entry but I cannot understand how I can import the values for each entry.
You can see the required format of the structure here:
var arr = [{
"name":{default:"Alex", cellId:"B1"},
"surname":{default:"Smith", cellId:"B2"},
"class":{default: "B1", cellId:"B3"}
},
{
"name":{default:"Maria", cellId:"C1"},
"surname":{default:"Smith", cellId:"C2"},
"class":{default: "B1", cellId:"C3"}
} ]
$("#btn").on("change", function(e) {
e.preventDefault();
var files = e.target.files;
var i, f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {
type: "buffer",
blankRows: true,
defval: ' '
});
var sheet_name_list = workbook.SheetNames;
var theQuestionLanguage = sheet_name_list; //english
var theExcelDataArray = [];
var test;
var data = [];
var headers = {};
sheet_name_list.forEach(function(y) {
var worksheet = workbook.Sheets[y];
var headers = {};
var data = [];
for (z in worksheet) {
//parse out the column, row, and value
var col = z.substring(0, 1);
var row = parseInt(z.substring(1));
var value = worksheet[z].v;
//store header names
if (row == 1 && !headers[value]) {
headers[value] = {};
}
console.log(headers);
if ((headers[value]) && (row !== 1)) {
headers[value].default = "value"
console.log("headers");
}
}
//drop those first two rows which are empty
});
};
reader.readAsArrayBuffer(f);
}
});
First of all, Save As your Excel file in CSV format.
After that, go to this website : Let's go. In this website you can add for information in your each entry and convert them into key/value pair.
I hope this this above information will help you.

How to transfer image to Google Drive and save its URL to a Google Sheet in a single script?

I would like to transfer several images from ESP32 to Google Drive and, in the same script, record the image's URL along with date and time in a Google Sheet for future access.
The Script I am using to receive the image on the Google Drive side is as below:
function doPost(e) {
var myFoldername = e.parameter.myFoldername;
var myFile = e.parameter.myFile;
var myFilename = e.parameter.myFilename;
//var myFilename = Utilities.formatDate(new Date(), "GMT", "yyyyMMddHHmmss")+"-"+e.parameter.myFilename;
var myToken = e.parameter.myToken;
var contentType = myFile.substring(myFile.indexOf(":")+1, myFile.indexOf(";"));
var data = myFile.substring(myFile.indexOf(",")+1);
data = Utilities.base64Decode(data);
var blob = Utilities.newBlob(data, contentType, myFilename);
// Save a captured image to Google Drive.
var folder, folders = DriveApp.getFoldersByName(myFoldername);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(myFoldername);
}
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + myFilename);
var imageID = file.getUrl().substring(file.getUrl().indexOf("/d/")+3,file.getUrl().indexOf("view")-1);
var imageUrl = "https://drive.google.com/uc?authuser=0&id="+imageID;
// Send a link message to Line Notify.
var res = "Line Notify: ";
try {
var url = 'https://notify-api.line.me/api/notify';
var response = UrlFetchApp.fetch(url, {
'headers': {
'Authorization': 'Bearer ' + myToken,
},
'method': 'post',
'payload': {
'message': imageUrl
}
});
res += response.getContentText();
} catch(error) {
res += error;
}
//Here is where the code to save imageUrl to Google Sheet was added **********
return ContentService.createTextOutput(myFoldername+"/"+myFilename+"\n"+imageUrl+"\n"+res);
}
What do I have to add to save "imageUrl" to a Google Sheet?
I have tried to save it to the current sheet, that is the sheet this script is attached to but I get error.
In the line indicated above I added the code below that I cut from a script that only writes to the Goggle sheet (no image transfer) but it fails to save the image URL and complains of the line:
var sheet = getSpreadSheet();
//-------------------------------------------------------------------------------
var result = 'Ok'; // default result
if (e.parameter == 'undefined') {
result = 'No Parameters';
} else {
var alarm= e.parameter.alarm;
if (typeof alarm != 'undefined') {
sendEmail("alarm text:" + stripQuotes(alarm));
return ContentService.createTextOutput(result);
}
var sheet = getSpreadSheet(); //---> Error here
var lastRow = sheet.getLastRow();
var newRow = 1;
if (lastRow > 0) {
var lastVal = sheet.getRange(lastRow, 1).getValue();
//if there was no info for (sentEmailIfUnitIsOutForMinutes) checkIfDead() function will append row with 'dead' text
// so checking do we need to override it
if (lastVal == 'dead')
newRow = lastRow; //to overwrite "dead" value
else
newRow = lastRow + 1;
}
var rowData = [];
var namesOfParams=[];
for (var param in parseQuery(e.queryString))
namesOfParams.push(param);
//creatating headers if first row
if (newRow == 1) {
rowData[0] = "Date";
var i = 1;
for (var i=0; i<namesOfParams.length;i++ ) {
rowData[i+1] = namesOfParams[i];
}
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
rowData = [];
newRow++;
}
rowData[0] = Utilities.formatDate(new Date(), timeZone, dateTimeFormat);
for (var i=0; i<namesOfParams.length;i++ ) {
var value = stripQuotes(e.parameter[namesOfParams[i]]);
rowData[i+1] = value;
}
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
//---------------------------------------------------------------------------------
Help highly apreciated.
Thanks
Problem solved with the following script:
var timeZone = "GMT";
var dateTimeFormat = "dd/MM/yyyy HH:mm:ss";
var logSpreadSheetId = "1W1ypQEkfKNFSqhtfgbjbjFgzHO8LDaTv6mNWTP9h4M8";
// logSpreadSheetId is to be copied from the sheet's URL as follows: https://docs.google.com/spreadsheets/d/1W1ypQEkfKNFSqhtfgbjbjFgzHO8LDaTv6mNWTP9h4M8/edit#gid=0
function doPost(e) {
var myFoldername = e.parameter.myFoldername;
var myFile = e.parameter.myFile;
//var myFilename = e.parameter.myFilename;
//var myFilename = Utilities.formatDate(new Date(), timeZone, "ddMMyyyyHHmmss")+"-"+e.parameter.myFilename;
var myFilename = Utilities.formatDate(new Date(), timeZone, "ddMMyyyyHHmmss")+".jpg";
var myToken = e.parameter.myToken;
var contentType = myFile.substring(myFile.indexOf(":")+1, myFile.indexOf(";"));
var data = myFile.substring(myFile.indexOf(",")+1);
data = Utilities.base64Decode(data);
var blob = Utilities.newBlob(data, contentType, myFilename);
// Save a captured image to Google Drive.
var folder, folders = DriveApp.getFoldersByName(myFoldername);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(myFoldername);
}
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + myFilename);
var imageID = file.getUrl().substring(file.getUrl().indexOf("/d/")+3,file.getUrl().indexOf("view")-1);
var imageUrl = "https://drive.google.com/uc?authuser=0&id="+imageID;
addLog(myFilename,imageUrl);
return ContentService.createTextOutput(myFoldername+"/"+myFilename+"\n"+imageUrl+"\n"); //+res);
}
function addLog(myFilename,imageUrl) {
var spr = SpreadsheetApp.openById(logSpreadSheetId);
var sheet = spr.getSheets()[0];
var data = sheet.getDataRange().getValues();
var pos = sheet.getLastRow();
var rowData = [];
if(!pos>0){
pos = 1;
rowData[0] = "Date";
rowData[1] = "Image";
rowData[2] = "URL";
var newRange = sheet.getRange(pos, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
pos = pos +1;
rowData = [];
rowData[0] = Utilities.formatDate(new Date(), timeZone, dateTimeFormat);
rowData[1] = myFilename;
rowData[2] = imageUrl;
var newRange = sheet.getRange(pos, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
Also, for simplicity, the sheet and the script now sit on independent files as the script can refer to the sheet using its ID as in:
var logSpreadSheetId = "1W1ypQEkfKNFSqhtfgbjbjFgzHO8LDaTv6mNWTP9h4M8";.

Filereader read file using correct encoding when read as readAsArrayBuffer

I am working on reading .csv /xlsx file uploaded using javaScript and get the result as array containing each row . I was able to read the file and get data using FileReader and SheetJs with following code.
// code for the new excel reader
$scope.do_file = function(files)
{
$scope.fileContent = [];
var X = XLSX;
var global_wb;
var f = files[0];
var reader = new FileReader();
reader.onload = function(e)
{
var data = e.target.result;console.log(data);
global_wb = X.read(data, {type: 'array'});
var output = "";
var result = {};
global_wb.SheetNames.forEach(function(sheetName) {
var roa = X.utils.sheet_to_json(global_wb.Sheets[sheetName], {header:1});
if(roa.length) result[sheetName] = roa;
});
$scope.fileContent = result["Sheet1"];
if(!result["Sheet1"])
{
$scope.fileContent = result["contacts"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
}
};
reader.readAsArrayBuffer(f);
};
For reading most of the files the code works , but when file containing Hebrew text with Windows-1255 encoding i get gibberish data.
Looking in for more options i tried to read the file as text using reader.readAsText and change the encoding as necessary , check the following code:
function is_Hebrew(data)
{
var position = data.search(/[\u0590-\u05FF]/);
return position >= 0;
}
$scope.do_file = function(files)
{
var fullResult = [];
var file =files[0];
var reader = new FileReader();
reader.onload = function(e){
var data = e.target.result;
if(!is_Hebrew(data.toString()))
{
reader.readAsText(file,'ISO-8859-8');
}
};
reader.readAsText(file);
reader.onloadend = function(){
var lines = reader.result.split('\r\n');
console.log(lines);
lines.forEach(element => {
var cell = element.split(',');
fullResult.push(cell);
});
console.log(reader);
};
};
but the above code is not suitable as it does not read the file as each row identifying each cell. if any one of cell contains string with coma separated value (for example if a cell contains a string value such as "25,28,29" ) the array output gives wrong data as it considers each values as each cell.
So i decided to stick with first method but i am not able to change the encoding .Is there a possible way to change encoding in the first code where i have used the readAsArrayBuffer to read the file data ?
After going through lot of possible solutions i found that answer to the above question was to combine the above two methods. The first method for reading the xlsx files and second method for reading csv files. Also i have used an additional javaScript library called papaparse in the second method to solve the problem of reading data in each cell
$scope.is_Hebrew = function($data){
var position = $data.search(/[\u0590-\u05FF]/);
return position >= 0;
}
// code for the new excel reader
$scope.do_file = function(files)
{
var config = {
delimiter: "", // auto-detect
newline: "", // auto-detect
quoteChar: '"',
escapeChar: '"',
header: false,
trimHeader: false,
dynamicTyping: false,
preview: 0,
encoding: "",
worker: false,
comments: false,
step: undefined,
complete: undefined,
error: undefined,
download: false,
skipEmptyLines: false,
chunk: undefined,
fastMode: undefined,
beforeFirstChunk: undefined,
withCredentials: undefined
};
$scope.fileContent = [];
var f = files[0];
var fileExtension = f.name.replace(/^.*\./, '');
if(fileExtension == 'xlsx')
{
var X = XLSX;
var global_wb;
var reader = new FileReader();
reader.onload = function(e)
{
var data = e.target.result;
global_wb = X.read(data, {type: 'array'});
var result = {};
global_wb.SheetNames.forEach(function(sheetName) {
var roa = X.utils.sheet_to_json(global_wb.Sheets[sheetName], {header:1});
if(roa.length) result[sheetName] = roa;
});
$scope.fileContent = result["Sheet1"];
if(!result["Sheet1"])
{
$scope.fileContent = result["contacts"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
}
};
reader.readAsArrayBuffer(f);
}
else if(fileExtension == 'csv')
{
var reader = new FileReader();
reader.onload = function(e)
{
var data = e.target.result;
console.log(f);
console.log($scope.is_Hebrew(data.toString()));
if(!$scope.is_Hebrew(data.toString()))
{
reader.readAsText(f,'ISO-8859-8');
}
};
reader.readAsText(f);
reader.onloadend = function(e){
var c = Papa.parse(reader.result,[ config])
console.log(c);
$scope.fileContent = c["data"].filter(function(el) { return typeof el != "object" || Array.isArray(el) || Object.keys(el).length > 0; });
};
}
else
{
alert("File Not supported!");
}
$scope.fileContent.push([]);
};

How to parse, and iterate through, all rows from an Excel sheet file using JavaScript

I am trying to parse and read every cell from an Excel sheet; it seems that I am parsing the file but I just can't go through each cell and display them.
I am using the following code:
var workbook = XLSX.read('datasets/persons.xlsx', { type: 'binary' });
var sheet_name_list = workbook.SheetNames;
// console.log(sheet_name_list);
sheet_name_list.forEach(function (y) { /* iterate through sheets */
//Convert the cell value to Json
console.log(y);
var roa = XLSX.utils.sheet_to_json(workbook.Sheets[y]);
console.log(roa);
if (roa.length > 0) {
result = roa;
}
});
I am getting an empty array when I try to print console.log(roa), any idea how I should iterate through each cell from the file?
you can use
XLSX.utils.sheet_to_row_object_array(workbook.Sheets[y])
to parse each cells in excel file.
Here is full code use to display Excel sheet file using JavaScript and JQuery.
function handleFile(e) {
//alert(e);
var exceljsonObj = [];
var files = e.target.files;
var i, f;
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function (e) {
var data = e.target.result;
var result;
var workbook = XLSX.read(data, { type: 'binary' });
var sheet_name_list = workbook.SheetNames;
sheet_name_list.forEach(function (y) { /* iterate through sheets */
//var exceljsonObj = [];
var rowObject = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[y]);
exceljsonObj = rowObject;
for(var i=0;i<exceljsonObj.length;i++){
//var recordcount = exceljsonObj.length;
var data = exceljsonObj[i];
$('#myTable tbody:last-child').append("<tr><td>"+data.ID+"</td><td>"+data.Name+"</td><td>"+data.Months+"</td></tr>");
}
//alert(exceljsonObj.length);
$('#alermessage').each(function() {
//this points to item
alert('Record Count is '+exceljsonObj.length);
});
});
};
reader.readAsArrayBuffer(f);
}
}
$(document).ready(function(){
$('#files').change(handleFile);
});

Calling the contents within a list in JavaScript

So I have a website where the user puts a .csv file into a website and the website extracts it into a list in JavaScript. The full code that I am doing is to compare a .csv file that the user inputs into a website with the .csv file the website currently has. I want to be able to compare the two different files outside the function that I have below.
var a = [];
function compare(file) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event) {
var csv = event.target.result;
var data = $.csv.toArrays(csv);
number = data.length;
for (i = 1; i < data.length; i++) {
a.push({date: data[i][0], url: data[i][5], count: data[i][6]});
};
reader.onerror = function() {
alert('Unable to read ' + file.fileName);
};
}
var para = document.createElement("p");
var node = document.createTextNode(a[0].url);
para.appendChild(node);
var element = document.getElementById("demo");
element.appendChild(para);
At the end of this code snippet, I was testing to see if I can call upon the contents of the list a. However, I keep getting an "Uncaught TypeError: Cannot read property 'url' of undefined".
The error occurs at
var node = document.createTextNode(a[0].url);"
I think the problem is the async nature of the FileReader
function compare(file, callback) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function (event) {
var a = [];
var csv = event.target.result;
var data = $.csv.toArrays(csv);
number = data.length;
for (i = 1; i < data.length; i++) {
a.push({
date: data[i][0],
url: data[i][5],
count: data[i][6]
});
callback(a);
};
}
//misplaced it in the onload handler
reader.onerror = function () {
alert('Unable to read ' + file.fileName);
};
}
then need to use the callback to access a
//here compare is an async method so to use the value of a after calling compare we will have to depend on a callback
compare(e.target.files[0], function (a) {
var para = document.createElement("p");
var node = document.createTextNode(a[0].url);
para.appendChild(node);
var element = document.getElementById("demo");
element.appendChild(para);
});
Demo: Fiddle

Categories

Resources