Convert excel to json but with only one header - javascript

I am trying to write an html with JS program that will convert an excel file into json which is does bit it does not format it the way I need to. So basically it spits out when finished
[
{
"imei": "357271093291264"
},
{
"imei": "353094106032150"
},
{
"imei": "353112106434588"
}
]
but what I need is.
[
{
"imei": "357271093291264", "353094106032150", "353112106434588"
}
]
So it is taking imei from cell A1 and using it over and over. I just need it
to keep adding on as I go down the rows.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/read-excel-file#4.x/bundle/read-excel-file.min.js"></script>
</head>
<body>
<div style="margin: auto;width: 50;margin-top: 80px;padding: 30px;background-color: #dedede;">
<h2>Excel to JSON Converter</h2>
<input type="file" id="input" />
<br> <br>
<textarea name="json-data" id="json-data" rows="25" style="width: 100%;"></textarea>
<br><br>
<button id="dl-json">Download JSON File</button>
</div>
<script>
var input = document.getElementById('input');
input.addEventListener('change', function(){
readXlsxFile(input.files[0]).then(function(data){
var i = 0;
var headers = [];
var json_object = [];
data.map((row, index)=> {
if (i == 0){
headers = row;
}
if (i > 0){
var temp = {};
for (var x = 0; x < row.length; x++){
temp[headers[x]] = row[x];
}
json_object.push(temp);
}
i++;
});
document.getElementById('json-data').value = JSON.stringify(json_object, null, 2)
});
document.getElementById('dl-json').onclick = function() {
var json_str = document.getElementById('json-data').value;
downloadObjectAsJson(json_str, '');
}
function downloadObjectAsJson(str, filename){
var data_str = "data:text/json;charset=utf-8," + encodeURIComponent(str);
var anchor = document.createElement('a');
anchor.setAttribute("href", data_str);
anchor.setAttribute("download", filename + ".json");
}
});
</script>
</body>
</html>
I have tried playing around with it and pulling out certain parts and setting different variables to certain values.

The shape of your output doesn't seem to make sense. Do you want the first element in your output array to be a key:value pair such as "headerText":"row2Value", and then the rest just strings?
If so, this should work for you:
var input = document.getElementById("input");
input.addEventListener("change", function () {
readXlsxFile(input.files[0]).then(function (data) {
let exportData = [];
for (i = 1; i < data.length; i++) {
i === 1
? exportData.push({ imei: data[i].toString() })
: exportData.push(data[i].toString());
}
document.getElementById("json-data").value = JSON.stringify(exportData);
});
document.getElementById("dl-json").onclick = function () {
var json_str = document.getElementById("json-data").value;
downloadObjectAsJson(json_str, "");
};
function downloadObjectAsJson(str, filename) {
var data_str =
"data:text/json;charset=utf-8," + encodeURIComponent(str);
var anchor = document.createElement("a");
anchor.setAttribute("href", data_str);
anchor.setAttribute("download", filename + ".json");
}
});
If you only need the key, then an array of values, this will work better for you:
readXlsxFile(input.files[0]).then(function (data) {
let exportData = [];
for (i = 1; i < data.length; i++) {
exportData.push(data[i].toString());
}
document.getElementById("json-data").value = JSON.stringify({
imei: exportData,
});
});

Related

How do I read a cvs file in javascript and store them in map?

say if I have csv file with :
Heading 1 , Heading 2 , Heading 3
Value 1 , Value2 , Value 3
All I want is to create a map that stores Heading 1 as a key and Heading 2 as value;
like map.set(value1 , value2)
How do I do this while I read the file in javascript ?
function processData(allText) {
var allTextLines = allText.split("\r");
for (var i=1; i<allTextLines.length; i++) {
var data = allTextLines[i].split(',');
console.log(data[0]);
map1.set(data[0] , data[1]);
}
}
so far I tried to do this . But it doesn't work. It doesn't read the file at all. Any help is appreciated.
Thanks
If you have a series of items separated by commas (,), the you can iterate the String and explode or split the items. This can be done with Vanilla JavaScript. The magic part is the for() loop; iterating it by 2 instead of by 1, which is most commonly seen.
$(function() {
var myString = "Header 1,Value 1,Header 2,Value 2,Header 3,Value 3";
var parts = myString.split(",");
var myData = {};
for (var i = 0; i < parts.length; i += 2) {
myData[parts[i]] = parts[i + 1];
}
console.log(myData);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If your file has multiple lines, and the first line is Headers, for example:
Header 1,Header 2,Header 3
Value 1,Value 2,Value 3
Value 4,Value 5,Value 6
You'll have to treat it differently. When it's brought into JS, it will be one big String, and you will have to first split it by End Of Line (EOL). This will create an Array of Strings that must be iterated. You will want to make an Array of Keys and then a Matrix of Values.
Since the file is Local, you will need to first get the File from the User. This is discussed here: How to read data From *.CSV file using javascript? and here: Reading in a local csv file in javascript? You will have to determine the best method for yourself.
One way is to use a File Input. There are drawbacks and caveats due to security and browsers, but it might work.
$(function() {
var fileInput = $("#getFile");
function toObj(keys, vals) {
var obj = {};
for (var i = 0; i < keys.length; i++) {
obj[keys[i]] = vals[i];
}
return obj;
}
function stringToObject(str, header) {
if (header == undefined) {
header = false;
}
var lines = str.split("\n");
var k = [],
m = [];
if (header) {
k = lines.splice(0, 1);
k = k[0].split(",");
}
$.each(lines, function(i, el) {
if (el.length) {
m.push(el.split(","));
}
});
if (k.length) {
var r = [];
$.each(m, function(i, el) {
r.push(toObj(k, el));
});
return r;
} else {
return m;
}
}
function readFile() {
var reader = new FileReader();
reader.onload = function() {
var newData = stringToObject(reader.result, $("#header").prop("checked"));
console.log(newData);
$("#out").html("<pre>" + reader.result + "</pre>");
};
reader.readAsBinaryString(fileInput[0].files[0]);
};
fileInput.change(readFile);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="file input">
<input type="checkbox" id="header" checked="checked"> <label>CSV Header</label><br />
<input type="file" id="getFile" />
</div>
<div id="out"></div>

Unexpected quoted property in dynamically created object

I try to load contents of the CSV file into the array of JavaScript objects. Unfortunately, structure of data is not flat, so to mitigate that, I use dot-separated property names as column headers in CSV file. Example CSV file looks as follows:
codes.code1,codes.code2,codes.code3,codes.code4,info.description.text,info.description.language
49074202,64,1443,1416,Test description: 49074202 64 1443 1416,EN
81905948,10,9721,5411,Test description: 81905948 10 9721 5411,EN
87262350,86,7050,4775,Test description: 87262350 86 7050 4775,EN
The object structure I would like to end up with looks like
{
codes: {
code1: "49074202",
code2: "64",
code3: "1443",
code4: "1416"
},
info: {
description: {
text: "Test description: 49074202 64 1443 1416",
language: "EN"
}
}
}
Following code can be used to recreate the problem (using CSV file with contents posted above).
<html>
<body>
<form>
<input type="file" id="files" onchange="loadFromFile()" />
<script>
function loadFromFile() {
var selectedFile = document.getElementById('files').files[0];
var reader = new FileReader();
reader.onload = loadRowsFromFile;
reader.readAsText(selectedFile);
};
function loadRowsFromFile(e) {
var rows = e.target.result.split("\n");
if (!rows || rows.length === 0) {
return;
}
var headers = rows[0].split(",");
var loadedData = [];
for (var i = 1; i < rows.length; i++) {
var columns = rows[i].split(",");
var rowData = {};
for (var j = 0; j < headers.length; j++) {
placeElementInHierarchy(rowData, headers[j], columns[j]);
}
loadedData.push(rowData);
}
console.log(loadedData);
}
function placeElementInHierarchy(rowData, propertyPath, value) {
var path = propertyPath.split(".");
var obj = rowData;
for (var i = 0; i < path.length; i++) {
if (i === path.length - 1) {
obj[path[i]] = value;
} else {
if (!obj[path[i]]) {
obj[path[i]] = {};
}
obj = obj[path[i]];
}
}
}
</script>
</form>
</body>
</html>
File parsing works properly, data is loaded correctly into the structure. However, for some reason the last processed property name is quoted. Structure of all rows I obtain looks like that:
{
codes: {
code1: "49074202",
code2: "64",
code3: "1443",
code4: "1416"
},
info: {
description:{
text: "Test description: 49074202 64 1443 1416",
"language": "EN"
}
}
}
The only lead I have right now is that if I remove the 'language' column from CSV file, then 'text' is being quoted instead - so the last processed property is for some reason quoted. Thanks in advance!
EDIT: Fixed mistakes in the expected structure.
EDIT2: What is interesting, following code (skipping file upload part), doesn't show such symptoms
<html>
<body>
<form>
<script>
(function() {
var csvData = 'codes.code1,codes.code2,codes.code3,codes.code4,info.description.text,info.description.language\n' +
'49074202,64,1443,1416,Test description: 49074202 64 1443 1416,EN\n' +
'81905948,10,9721,5411,Test description: 81905948 10 9721 5411,EN\n' +
'87262350,86,7050,4775,Test description: 87262350 86 7050 4775,EN';
loadRowsFromFile(csvData);
})();
function loadRowsFromFile(csvData) {
var rows = csvData.split("\n");
if (!rows || rows.length === 0) {
return;
}
var headers = rows[0].split(",");
var loadedData = [];
for (var i = 1; i < rows.length; i++) {
var columns = rows[i].split(",");
var rowData = {};
for (var j = 0; j < headers.length; j++) {
placeElementInHierarchy(rowData, headers[j], columns[j]);
}
loadedData.push(rowData);
}
console.log(loadedData);
}
function placeElementInHierarchy(rowData, propertyPath, value) {
var path = propertyPath.split(".");
var obj = rowData;
for (var i = 0; i < path.length; i++) {
if (i === path.length - 1) {
obj[path[i]] = value;
} else {
if (!obj[path[i]]) {
obj[path[i]] = {};
}
obj = obj[path[i]];
}
}
}
</script>
</form>
</body>
</html>
Okay. As you can see in screen above, your problem is generated by Carriage Return character \r on end of every line in the file. You can remove all your empty characters from string using
trim()
or you can use regexp to cut out just this type of characters.
Example is done here:
How to remove all line breaks from a string?

HtmlService: google.script.run not recognizing gs function

I'm currently trying to pass an array of values from a Google Sheet to the HtmlService where I will have the user choose an option and eventually pass it back to the .gs script. I have been using these two links as references:
1. Google Documentation
2. Stack Overflow example
When running the code, I looked at my console and noticed this error:
VM3051:4 Uncaught TypeError: google.script.run.withSuccessHandler(...).getVersionArray is not a function
It appears that getVersionArray() is not being passed correctly. When removing this function from the rest of that google.script.run call, the error goes away.
Also, per link two, I tried that code with the template and never even got a window to pop up, so I have been using the HtmlOutput example from the Google documentation link as a starting point. I have also tried the code with and without the SandboxMode declaration.
gs code:
function bugPieChart() {
getVersionArray();
openDialog();
function getVersionArray() {
var ss = SpreadsheetApp.getActive();
var valuesR = ss.getSheetByName("report").getRange('R1:R').getValues();
var valuesS = ss.getSheetByName("report").getRange('S1:S').getValues();
var versionRSArray = [];
for (var i = 0; i < valuesR.length; i++) {
versionRSArray.push(valuesR[i][0]);
}
for (var i = 0; i < valuesS.length; i++) {
versionRSArray.push(valuesS[i][0]);
}
versionRSArray.sort();
var uniqueArray = [];
uniqueArray.push(versionRSArray[0]);
for (var i in versionRSArray ) {
if((uniqueArray[uniqueArray.length-1]!=versionRSArray[i]) && (versionRSArray[i] !== "")) {
uniqueArray.push(versionRSArray[i]);
}
}
return uniqueArray;
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
var htmlOutput = html.setSandboxMode(HtmlService.SandboxMode.NATIVE);
return htmlOutput;
}
}
index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
$(function() {
google.script.run.withSuccessHandler(buildOptionsList)
.getVersionArray();
});
function buildOptionsList(uniqueArray) {
var list = $('#optionList');
list.empty();
for (var i = 0; i < uniqueArray.length; i++) {
list.append('<option value="' + uniqueArray[i].toLowerCase() + '">' + uniqueArray[i] + '</option>');
}
}
</script>
</head>
<body>
<select id="optionList">
<option>Loading...</option>
</select>
<input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>
I think your just missing a closing bracket on the function above it.
function bugPieChart() {
getVersionArray();
openDialog();
}
function getVersionArray() {
var ss = SpreadsheetApp.getActive();
var valuesR = ss.getSheetByName("report").getRange('R1:R').getValues();
var valuesS = ss.getSheetByName("report").getRange('S1:S').getValues();
var versionRSArray = [];
for (var i = 0; i < valuesR.length; i++) {
versionRSArray.push(valuesR[i][0]);
}
for (var i = 0; i < valuesS.length; i++) {
versionRSArray.push(valuesS[i][0]);
}
versionRSArray.sort();
var uniqueArray = [];
uniqueArray.push(versionRSArray[0]);
for (var i in versionRSArray ) {
if((uniqueArray[uniqueArray.length-1]!=versionRSArray[i]) && (versionRSArray[i] !== "")) {
uniqueArray.push(versionRSArray[i]);
}
}
return uniqueArray;
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
var htmlOutput = html.setSandboxMode(HtmlService.SandboxMode.NATIVE);
return htmlOutput;
}

onkeyup event on dynamic array

Good Evening,
I am having trouble setting up the onkeyup event. I am trying to get it to fire an objects method when a user enters text into the text field. It does not seem to find the object.
I have cut down on the code and have made the following sample:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script>
var ReportModule = new function () {
function ReportObj(id, title) {
this.id = id;
this.title = title;
this.result = "";
this.empno = "";
this.UpdateEmpno = function (empNo, resultBoxID) {
this.empno = empNo;
$(resultBoxID).update("Result: " + empNo);
};
};
var ReportObjArray = new Array();
var test1 = new ReportObj("box1", "First object");
var test2 = new ReportObj("box2", "Second object");
ReportObjArray.push(test1);
ReportObjArray.push(test2);
this.Initialize = function () {
for (i = 0; i < ReportObjArray.length; i++) {
var container = document.createElement("div");
container.id = ReportObjArray[i].id;
container.textContent = ReportObjArray[i].title;
$('#Container').append(container);
var empnoInput = document.createElement("input");
empnoInput.type = "text";
empnoInput.id = ReportObjArray[i].id + "_Empno";
empnoInput.onkeyup = function (event) {
// Update Report Objects empno field
ReportObjArray[i].UpdateEmpno(empnoInput.value,empnoInput.id); // <-------- Undefined here
};
$('#' + ReportObjArray[i].id).append(empnoInput);
var container2 = document.createElement("div");
container2.id = ReportObjArray[i].id + "_result";
container2.style.border = "1px solid black";
container2.style.width = "100px";
container2.textContent = "Result:";
$('#' + container.id).append(container2);
};
};
}
</script>
</head>
<body onload="ReportModule.Initialize()">
<div id="Container"></div>
</body>
</html>
Update: It works when searching for the object in the ReportObjArray and matching the correct object. However, I was wondering if there was a more efficient way instead of having to look through the array each time.
empnoInput.onkeyup = function (event) {
// Update Report Objects empno field
var target_id = document.getElementById(event.target.id).id;
for (j = 0; j < ReportObjArray.length; j++) {
if (target_id = ReportObjArray[j].id) {
ReportObjArray[j].UpdateEmpno(document.getElementById(event.target.id).value,empnoInput.id);
break;
}
}
};
Wrap your for loop code in a closure:
for (i = 0; i < ReportObjArray.length; i++) {
(function(i) {
// code
})(i);
}
Working JS Fiddle:
http://jsfiddle.net/23vkS/

using js to parse log and filter out something

I am quite new in javascript and I am trying to parse the log and filter out something. The log looks like:
v=5,ci=3,si=60,sv=1,ss=active,es=-,ai=a23-369b-4da3-b2da-630aee75f8c5,ip='99.114.107.39',rm=GET,rv=HTTP/1.1,rs=200,rt=0.787020,rr='/tag/febe1eab436e98eb4ed3711870496c91/st.js?l=http%3A%2F%2Fwww.michaels.com%2Fv
The output should be printed by splitting on ,, line by line and also filter out something that I don't need. e.g, I only need ip and rr attributes, so the output should look like:
ip='99.114.107.39'
rr='/tag/febe1eab436e98eb4ed3711870496c91/st.js?l=http%3A%2F%2Fwww.michaels.com%2Fv
The code I have is following, but it doesn't work:
<!doctype html>
<html>
<head>
<title>reading file</title>
<script>
function readText(obj){
var file = obj.files[0],
div=document.getElementById('main');
if(file){
div.innerHTML='';
var reader = new FileReader();
reader.onerror = function(event){
div.innerHTML='The file can\'t be read! Error ' + event.target.error.code;
}
reader.onload = function(event){
var cont = event.target.result.split(',');
for(var i=0; i<cont.length; i++){
var name = cont.split('=');
if (name[0]==="rr") {
div.innerHTML+=cont[i]+'<br />';
}
}
}
reader.readAsText(file);
}
}
window.onload=function(){
document.getElementById('ff').onchange=function(){readText(this);}
}
</script>
</head>
<body>
<input type="file" id="ff" />
<div id="main"></div>
</body>
</html>
Use javascript's split():
DEMO
Example:
window.onload = function () {
var text = "v=5,ci=3,si=60,sv=1,ss=active,es=-,ai=a23-369b-4da3-b2da-630aee75f8c5,ip='99.114.107.39',rm=GET,rv=HTTP/1.1,rs=200,rt=0.787020,rr='/tag/febe1eab436e98eb4ed3711870496c91/st.js?l=http%3A%2F%2Fwww.michaels.com%2Fv";
var ip = '',
rr = '';
var splits = text.split(',');
for (var i = 0; i < splits.length; i++) {
if (splits[i].indexOf('ip') > -1)
ip = splits[i];
else if (splits[i].indexOf('rr') > -1)
rr = splits[i];
}
document.getElementById('divIp').innerHTML = ip;
document.getElementById('divRr').innerHTML = rr;
};

Categories

Resources