I am trying to make a web app that will import excel file and pass it to google sheets. The idea is that different people will be uploading theirs table (format is the same) through web app to my spreadsheet where I will do the rest of the job.
For now I got this:
js code;
function doGet(e) {
Logger.log(e.parameter);
return HtmlService.createHtmlOutputFromFile("index");
}
function toroku(userInfo){
var url = "https://docs.google.com/spreadsheets/d/1gCMXhBTba-8PNeN5lk5wrumUGe_f4xNdip1DPCpaRSw/edit#gid=0";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("upload");
ws.appendRow([userInfo.table]);
}
And html;
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/jszip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/xlsx.js"></script>
<script>
var ExcelToJSON = function() {
this.parseExcel = function(file) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {
type: 'binary'
});
workbook.SheetNames.forEach(function(sheetName) {
// Here is your object
var XL_row_object = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
var json_object = JSON.stringify(XL_row_object);
console.log(JSON.parse(json_object));
jQuery( '#xlx_json' ).val( json_object );
})
};
reader.onerror = function(ex) {
console.log(ex);
};
reader.readAsBinaryString(file);
};
};
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
var xl2json = new ExcelToJSON();
xl2json.parseExcel(files[0]);
}
</script>
<form enctype="multipart/form-data">
<input id="upload" type=file name="files[]">
</form>
<textarea class="form-control" rows=35 cols=120 id="xlx_json"></textarea>
<script>
document.getElementById('upload').addEventListener('change', handleFileSelect, false);
document.getElementById('upload').addEventListener('click', handleFileSelect).value
google.script.run.toroku(handleFileSelect);
document.getElementById("upload").value = "";
</script>
<div class="form-row">
<button id="btn">登録!</button>
</div>
<script>
document.getElementById("btn").addEventListener("click",doStuff);
function doStuff(){
var userInfo = {};
userInfo.table = document.getElementById("xlx_json").value;
google.script.run.toroku(userInfo);
document.getElementById("xlx_json").value = "";
}
</script>
</body>
</html>
It reads the data from the excel and imports it to google sheets, but I'm getting an array not a table.
This is what I am getting imported to google sheets:
[{"Product":"2132030501430 ","Customer":"A","Units":"1","Deliver":"1"},{"Product":"2188130546030 ","Customer":"B","Units":"2","Deliver":"3"},{"Product":"2132650259800 ","Customer":"A","Units":"1","Deliver":"5"},{"Product":"2138512138000 ","Customer":"B","Units":"0","Deliver":"6"},{"Product":"2132032500270 ","Customer":"A","Units":"-10","Deliver":"7"},{"Product":"2116104013159 ","Customer":"B","Units":"200","Deliver":"8"},{"Product":"2116102039910 ","Customer":"A","Deliver":"9"},{"Product":"2145710030310 ","Customer":"B","Deliver":"10"},{"Product":"2132630164760 ","Customer":"A","Deliver":"9"},{"Product":"2116105051990 ","Customer":"B","Units":"0","Deliver":"5"},{"Product":"2145721006510 ","Customer":"A","Units":"0","Deliver":"4"},{"Product":"2132030900430 ","Customer":"B","Units":"7","Deliver":"3"},{"Product":"2132031500270 ","Customer":"A","Units":"5","Deliver":"2"},{"Product":"2138506049100 ","Customer":"B","Units":"6","Deliver":"1"},{"Product":"2132042501730 ","Customer":"C","Units":"31","Deliver":"9"},{"Product":"2132030901470 ","Customer":"D","Units":"20","Deliver":"8"},{"Product":"2116101050089 ","Customer":"F","Units":"126","Deliver":"7"},{"Product":"2116104051870 ","Customer":"C","Units":"3","Deliver":"6"},{"Product":"2188131528030 ","Customer":"D","Units":"82","Deliver":"4"},{"Product":"2145718013050 ","Customer":"F","Deliver":"4"},{"Product":"2188140578030 ","Customer":"C","Units":"20","Deliver":"4"},{"Product":"2132640087170 ","Customer":"D","Deliver":"4"},{"Product":"2138506026000 ","Customer":"F","Units":"0","Deliver":"4"},{"Product":"2132042501770 ","Customer":"C","Units":"15","Deliver":"4"},{"Product":"2187106025940 ","Customer":"D","Units":"90","Deliver":"4"}]
My question is how can I convert it into a table?
should it be done on html side?
Also I would like to say that I am newbie in programing world so please tell me in the simplest way what should I do with this.
Best Regards!
I believe your goal as follows.
When a XLSX file on the local PC is selected, you want to retrieve the XLSX data and put to textarea using Javascript and xlsx.js.
When a bottom button is clicked, you want to send the values in textarea to Google Apps Script side, and want to put the values to the Google Spreadsheet.
From Excel file has only one sheet with one simple table, I understood that the XLSX data has only one sheet.
Modification points:
In your script, when there are multiple sheets in the XLSX data, the values of only the last sheet are sent to Google Apps Script. Because the values of other sheets are overwritten in workbook.SheetNames.forEach().
But from your replying, I could understand that you suppose that the XLSX data has only one sheet. So in this case, your script becomes more simple.
In your script, an error occurs at document.getElementById('upload').addEventListener('click', handleFileSelect).value.
In order to put the values to the Spreadsheet, I would like to propose to use setValues instead of appendRow. When setValues is used, the values of the multiple rows and columns can be put with one call.
In this case, the values are required to be 2 dimensional array.
When above points are reflected to your script, it becomes as follows.
Modified script:
Google Apps Script side:
function doGet(e) {
Logger.log(e.parameter);
return HtmlService.createHtmlOutputFromFile("index");
}
function toroku(userInfo){
var values = JSON.parse(userInfo.table);
var url = "https://docs.google.com/spreadsheets/d/1gCMXhBTba-8PNeN5lk5wrumUGe_f4xNdip1DPCpaRSw/edit#gid=0";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("upload");
ws.getRange(ws.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
}
HTML & Javascript side:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/jszip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/xlsx.js"></script>
<form enctype="multipart/form-data">
<input id="upload" type=file name="files[]">
</form>
<textarea class="form-control" rows=35 cols=120 id="xlx_json"></textarea>
<div class="form-row">
<button id="btn">登録!</button>
</div>
<script>
document.getElementById('upload').addEventListener('change', handleFileSelect, false);
document.getElementById("btn").addEventListener("click", doStuff);
var ExcelToJSON = function() {
this.parseExcel = function(file) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {type: 'binary'});
jQuery('#xlx_json').val(JSON.stringify(XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]], {header: 1})));
};
reader.onerror = function(ex) {
console.log(ex);
};
reader.readAsBinaryString(file);
};
};
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
var xl2json = new ExcelToJSON();
xl2json.parseExcel(files[0]);
}
function doStuff() {
var userInfo = {};
userInfo.table = document.getElementById("xlx_json").value;
google.script.run.toroku(userInfo);
document.getElementById("xlx_json").value = "";
}
</script>
</body>
</html>
Note:
When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
References:
appendRow(rowContents)
setValues(values)
Related
i've have an html file with two textboxes
1.orders
1.amount
i want that when i type a number in the orders text box
i will get the value from another column in my Google Sheet in the same row that match to to this order
this is my Code.gs code its not working
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('page');
}
function getCost(oneCode){
var url = "https://docs.google.com/spreadsheets/d/1333t7lvECnmOcCnTE6gnn_RN1wrPckWpIETiPUjkUnU/edit#gid=0";
var ss = SpreadsheetApp.openUrl(url);
var ws = ss.getSheetByName("Sheet1");
var data = ws.getRange(1,1,ws.getLastRow(),2).getValues();
var ordersList = data.map(function(r){ return r[0]; });
var amountList = data.map(function(r){ return r[1]; });
var position = ordersLis.indexOf(oneCode);
if(position > -1){
return amountList[position];
} else {
return "not found";
}
}
========================
this the html code
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<script>
document.getElementById("one").addEventlistener("input",doThis);
function doThis(){
var oneCode = document.getElementById("one").value;
google.script.run.withSuccessHandler(updateAmount).getCost(oneCode);
}
function updateAmount(cost){
document.getElementById("two").value = cost;
}
</script>
<body>
<div>
<input id="one" type="text">
<label for="one">orders</label>
</div>
<div>
<input disabled id="two" type="text">
<label for="two">amount</label>
</div>
</body>
</html>
I would like to propose the following modification.
Modification points:
At HTML&Javascript side,
addEventlistener is addEventListener.
When your script is used, please modify document.getElementById("one").addEventListener("input",doThis); to as follows. Because when document.addEventListener("DOMContentLoaded", function) is not used, an error occurs at addEventListener.
document.addEventListener("DOMContentLoaded", function(){
document.getElementById("one").addEventListener("input",doThis);
});
When input is used as the event type, when the inputted text is 130, 1, 13 and 130 are sent. By this, google.script.run.withSuccessHandler(updateAmount).getCost(oneCode) is run 3 times. So I think that change might be suitable for this situation.
At Google Apps Script side,
At var ss = SpreadsheetApp.openUrl(url);, openUrl is openByUrl.
I think that in your script, var position = ordersLis.indexOf(oneCode); is var position = ordersList.indexOf(oneCode);.
In your script, oneCode of getCost(oneCode) is the string type.
When above points are reflected to your script, it becomes as follows.
Modified script:
HTML&Javascript side:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<script>
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("one").addEventListener("change", doThis);
});
function doThis() {
var oneCode = document.getElementById("one").value;
google.script.run.withSuccessHandler(updateAmount).getCost(oneCode);
}
function updateAmount(cost) {
document.getElementById("two").value = cost;
}
</script>
<body>
<div>
<input id="one" type="text">
<label for="one">orders</label>
</div>
<div>
<input disabled id="two" type="text">
<label for="two">amount</label>
</div>
</body>
</html>
When <script>###</script> is bottom of HTML, I think that document.addEventListener("DOMContentLoaded", function() {}) is not required to be used.
Google Apps Script side:
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('page');
}
function getCost(oneCode){
var url = "https://docs.google.com/spreadsheets/d/1333t7lvECnmOcCnTE6gnn_RN1wrPckWpIETiPUjkUnU/edit#gid=0";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Sheet1");
var data = ws.getRange(1,1,ws.getLastRow(),2).getValues();
var ordersList = data.map(function(r){ return r[0].toString(); });
var amountList = data.map(function(r){ return r[1].toString(); });
var position = ordersList.indexOf(oneCode);
if(position > -1){
return amountList[position];
}
return "not found";
}
Usage:
From your script, it seems that you are using Web Apps. When you use this script, please copy and paste the above scripts to the script editor, and please redeploy the Web Apps as new version. By this, the latest script is reflected to Web Apps. Please be careful this.
When the Web Apps is opened, please input a value to the input box and push the enter key or remove the focus from the input box. By this, addEventListener("change", doThis) is executed and doThis is run.
References:
addEventListener()
openByUrl(url)
Web Apps
I need to load the text file data into a javascript array and define a dynamic form using html.
I tried below code for extracting data from text file and to store in a javascript array and it works as long as it is in .js file
var fs = require('fs');
var textByLine = fs.readFileSync('123.txt').toString().split("\n");
console.log(textByLine);
but when I embed it inside my html file this doesn't work.
below is my html code. for now I am just forming an array with months but i need to replace it with array taken from the text file.
<html>
<head>
<title></title>
<META NAME="DESCRIPTION" CONTENT="">
<META NAME="KEYWORDS" CONTENT="">
<script language="javascript">
var dt=new Date();
var dt_month=dt.getMonth() +1;
//alert(dt_month);
function addOption(selectbox,text,value )
{
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
}
function addOption_list(){
var month = new Array("January","February","March","April","May","June","July","August",
"September","October","November","December");
for (var i=0; i < month.length;++i){
addOption(document.drop_list.Month_list, month[i], month[i]);
document.drop_list.Month_list.options[i].selected=true;
}
}
</script>
</head>
<body onLoad="addOption_list()";>
You can see the view-> Source of this page.
<br><br>
<FORM name="drop_list" action="yourpage.php" method="POST" >
<SELECT NAME="Month_list">
<Option value="" >Month list</option>
</SELECT>
</form>
</body>
</html>
I gave the 3 line code which is working independently as a .js file inside addOption_list function in above code and it doesn't work. Appreciate help on this.
Thanks in advance
The FileSytem (fs) module is for NodeJS applications so needs to be in .js file. If you want to load the file into your html you can use Ajax instead. This may work:
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this.responseText);
}
};
xhttp.open("GET", "123.txt", true);
xhttp.send();
}
function myFunction(data) {
var textByLine = data.split("\n");
console.log(textByLine);
}
loadDoc();
</script>
I'm currently learning JavaScript and I'm struggling to read a txt file and use its contents in the program, what I have so far:
fileBtn.addEventListener("change", function()
{
var content = [];
var file = fileBtn.files[0];
readFile(file, function(data)
{
console.log(JSON.parse(data));
//content.push(JSON.parse(data)) doesn't work, data is undef.
});
});
and a function readFile
function readFile(file, f)
{
var reader = new FileReader();
reader.onload = function(evt)
{
f(evt.target.result);
};
reader.readAsText(file);
}
My txt file is currenty only containing a "1", and it logs this number to the console but I can't work with it, if I try to push it into an array the values is suddenly undefined. My goal is to use the content of the file in the program later on
1 . no need to use JSON.parse if the text file only contain string .
data is containing all the text file content
2 . you need to put var content = [];
globally and not inside the function readFile
follow this snippet of code i think it will solve your problem
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<label for="file-upload" class="custom-file-upload">
Custom Upload
</label>
<input id="file-upload" type="file" />
<input id="log-content" type="button" value="Click Me"/>
</body>
<script>
var content = [];
function readFile(file, f) {
var reader = new FileReader();
reader.onload = function (evt) {
f(evt.target.result);
};
var text = reader.readAsText(file);
}
var fileBtn = document.getElementById("file-upload");
var logContnt = document.getElementById("log-content");
logContnt.addEventListener("click", function () {
alert(content);
})
fileBtn.addEventListener("change", function () {
var file = fileBtn.files[0];
readFile(file, function (data) {
content.push(data);
});
});
</script>
</html>
I am getting data from a file then that data is pushing to array.array data can view in console but that data is not displaying in html page.
If i use any button then i able to see that data in html page.
var app = angular.module('xlsxApp', []);
app.controller('xlsxCtrl', ['$scope', function($scope) {
$scope.finaldata = [];
$scope.UploadFiles = function(files) {
var f = files[0];
var reader = new FileReader();
reader.readAsBinaryString(f);
reader.onload = function(e) {
var data = e.target.result;
/*Converts the excel data in to object*/
var workbook = XLSX.read(data, {
type: 'binary'
});
/*Gets all the sheetnames of excel in to a variable*/
var sheet_name_list = workbook.SheetNames;
/*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*/
var exceljson = XLSX.utils.sheet_to_json(workbook.Sheets[y]);
$scope.finaldata = exceljson;
console.log("finaldata :: ", $scope.finaldata);
});
}
}
$scope.test = function() {
console.log("finaldata :: ", $scope.finaldata);
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.7.7/xlsx.core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xls/0.7.4-a/xls.core.min.js"></script>
</head>
<body ng-app="xlsxApp" ng-controller="xlsxCtrl">
<div class="container">
<div class="form-inline">
<input type="file" class="form-control" name="file" id="excelfile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" onchange="angular.element(this).scope().UploadFiles(this.files)" />
</div>
<button ng-click="test()">preview</button>
{{finaldata[0]}}
</div>
</body>
you get the object in console not an array.so,in html you bind {{finaldata}}/if you want value {{finaldata['C']}}
reader.onload() is evaluated outside the AngularJS environment. You should can $timeout service to update the UI view in next digest cycle
$timeout(function(){
$scope.finaldata = exceljson;
}, 0)
Use $scope.apply() to evaluate changes coming from outside angular.js
The reason why you see result when press a button - you probably have ng-click on the button that implicitly runs through $scope.apply() and applies your changes already sitting in the scope.
I'm new to d3.js so I know this might seem as a silly question to some so please bear with me. I'm trying to parse a csv file which a user uploads and print it's output in the console. I'm able to parse the CSV file when I provide the absolute path of the CSV file but when I try doing the same with file upload functionality I'm not getting any output in the console..
Working Javascript Code..
var dataset = [];
d3.csv("sample.csv", function(data) {
dataset = data.map(function(d) { return [ d["Title"], d["Category"], d["ASIN/ISBN"], d["Item Total"] ]; });
console.log(dataset[0]);
console.log(dataset.length);
});
Console Output...
["Men's Brooks Ghost 8 Running Shoe Black/High Risk Red/Silver Size 11.5 M US", "Shoes", "B00QH1KYV6", "$120.00 "]
8
New HTML code..
<input type="file" id="csvfile" name="uploadCSV"/>
<br/>
<button onclick="howdy()">submit</button>
Modified Javascript Code(not working)..
var myfile = $("#csvfile").prop('files')[0];
var reader = new FileReader();
reader.onload = function(e) {
var text = reader.result;
}
reader.readAsDataURL(myfile);
var dataset = [];
d3.csv(reader.result , function(data) {
dataset = data.map(function(d) { return [ d["Title"], d["Category"], d["ASIN/ISBN"], d["Item Total"] ]; });
console.log(dataset[0]);
console.log(dataset.length);
})
Since there was no official documentation on how to handle user uploaded CSV file I can't figure out where I'm going wrong..Is there a way I can use HTML5 file reader?? Please help..
You are close but you don't need to and can't call d3.csv on a reader.result. d3.csv makes an async AJAX call to retrieve a CSV file from a server. You already have the file contents and just want to parse, so use d3.csv.parse.
Full working example:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3#3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<input type="file" onchange="loadFile()" />
<script>
var reader = new FileReader();
function loadFile() {
var file = document.querySelector('input[type=file]').files[0];
reader.addEventListener("load", parseFile, false);
if (file) {
reader.readAsText(file);
}
}
function parseFile(){
var doesColumnExist = false;
var data = d3.csv.parse(reader.result, function(d){
doesColumnExist = d.hasOwnProperty("someColumn");
return d;
});
console.log(doesColumnExist);
}
</script>
</body>
</html>
This is for d3-csv#3
<!-- https://www.jsdelivr.com/package/npm/d3-dsv -->
<script src="https://cdn.jsdelivr.net/npm/d3-dsv#3.0.1/dist/d3-dsv.min.js" integrity="sha256-IrzYc2a3nTkfvgAyowm/WKmIGdVCMCcccPtz+Y2y6VI=" crossorigin="anonymous"></script>
<input type="file" accept=".csv">
<button>test button</button>
<script>
const testData = `owner,repo,"branch name"
foo,demo,master
boo,"js awesome",sha1123456
`
document.querySelector(`input`).onchange = async e => {
const input = e.target
const file = input.files[0]
const reader = new FileReader()
reader.readAsText(new Blob(
[file],
{"type": file.type}
))
const fileContent = await new Promise(resolve => {
reader.onloadend = (event) => {
resolve(event.target.result)
}
})
const csvData = d3.csvParse(fileContent)
console.log(csvData)
}
document.querySelector(`button`).onclick = e => {
const csvData = d3.csvParse(testData)
console.log(csvData)
}
</script>
The below link may help you know the implementation of csvParse
csv.js : The csv, tsv(tab) are dependent by dsv.js
dsv.js
If you just load the CSV only then do not import the whole JS. (instead of the d3-csv.js)
https://cdn.jsdelivr.net/npm/d3#7.0.1/dist/d3.min.js
https://cdn.jsdelivr.net/npm/d3-dsv#3.0.1/dist/d3-dsv.min.js
This is an old question and I think we have to clarify some points.
How to load a local csv file
How to link the loaded file with D3
1. Load a file is very simple just check this example:
const fileInput = document.getElementById('csv')
const readFile = e => {
const reader = new FileReader()
reader.onload = () => {
document.getElementById('out').textContent = reader.result
}
reader.readAsBinaryString(fileInput.files[0])
}
fileInput.onchange = readFile
<div>
<p>Select local CSV File:</p>
<input id="csv" type="file" accept=".csv">
</div>
<pre id="out"><p>File contents will appear here</p></pre>
Here we have a simple input element with type="file" attribute, this lets us to pick a csv file. Then the readFile() function will be triggered whenever a file is selected and will call the onload function after reading the file as a binary string.
2. I recommend to use readAsDataURL() to integrate it with d3 like this:
const fileInput = document.getElementById('csv')
const previewCSVData = async dataurl => {
const d = await d3.csv(dataurl)
console.log(d)
}
const readFile = e => {
const file = fileInput.files[0]
const reader = new FileReader()
reader.onload = () => {
const dataUrl = reader.result;
previewCSVData(dataUrl)
}
reader.readAsDataURL(file)
}
fileInput.onchange = readFile
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div>
<p>Select local CSV File:</p>
<input id="csv" type="file" accept=".csv">
</div>
<pre id="out"><p>File contents will appear here</p></pre>
To integrate the loaded file we call previewCSVData() and pass the file then we parse it using d3.csv() method. Also lets use await because it is an asynchronous call.
Note:
d3.csv internally uses fetch and works for any type of URL, (httpURL, dataURL, blobURL, etc...)