I am reading random row of large Excel file using Javascript. But it is taking some time for example when I am working with 300.000 row data in excel file. I need fast way.
<body>
<input type="file" id="fileUpload" />
<input type="button" id="upload" value="Upload" onclick="Upload()" />
<!-- <input type="button" id="upload" value="Random" onclick="ProcessExcel()" /> -->
<hr />
<h1 id="exc">Hello</h1>
<p id="her"></p>
<p id="limm"></p>
<div id="dvExcel"></div>
<script type="text/javascript">
// var gl_ex = "";
function Upload() {
//Reference the FileUpload element.
var fileUpload = document.getElementById("fileUpload");
//Validate whether File is valid Excel file.
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.xls|.xlsx)$/;
if (regex.test(fileUpload.value.toLowerCase())) {
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
//For Browsers other than IE.
if (reader.readAsBinaryString) {
reader.onload = function (e) {
ProcessExcel(e.target.result);
};
reader.readAsBinaryString(fileUpload.files[0]);
} else {
//For IE Browser.
reader.onload = function (e) {
var data = "";
var bytes = new Uint8Array(e.target.result);
for (var i = 0; i < bytes.byteLength; i++) {
data += String.fromCharCode(bytes[i]);
}
ProcessExcel(data);
// gl_ex = data;
//alert("Uploaded.");
};
reader.readAsArrayBuffer(fileUpload.files[0]);
}
} else {
alert("This browser does not support HTML5.");
}
} else {
alert("Please upload a valid Excel file.");
}
};
function ProcessExcel(data) {
//var data = "";
//data = gl_ex;
//Read the Excel File data.
var workbook = XLSX.read(data, {
type: 'binary'
});
//Fetch the name of First Sheet.
var firstSheet = workbook.SheetNames[0];
//Read all rows from First Sheet into an JSON array.
var excelRows = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[firstSheet]);
var len = excelRows.length;
var rand_num = Math.floor((Math.random() * len) + 1);
document.getElementById("her").innerHTML = rand_num;
document.getElementById("limm").innerHTML = len;
document.getElementById("exc").innerHTML = excelRows[rand_num-1].Name;
};
</script>
</body>
As in example shown I am reading random row from Excel file. I think javascript is reading whole excel file sequentially. Can I read specific row data in faster way?
Related
How to upload zip/rar file to google drive using Google app script? I tried these code below .gs in google app script:
function doPost(e) {
try {
var data = e.parameter.fileContent;
var filename = e.parameter.filename;
var email = e.parameter.email;
var name = e.parameter.name;
var result=uploadFileToGoogleDrive(data,filename,name,email,e);
return redirect();
} catch(error) {
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
var SCRIPT_PROP = PropertiesService.getScriptProperties();
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
function record_data(e,fileUrl) {
try {
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName('datasheet'); // select the responses sheet
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [ new Date() ]; // first element in the row should always be a timestamp
// loop through the header columns
for (var i = 1; i < headers.length; i++) { // start at 1 to avoid Timestamp column
if(headers[i].length > 0 && headers[i] == "Zip-Link") {
row.push(fileUrl); // add data to row
}
else if(headers[i].length > 0) {
row.push(e.parameter[headers[i]]); // add data to row
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
}
catch(error) {
Logger.log(e);
}
finally {
return;
}
}
function uploadFileToGoogleDrive(data, file, name, email,e) {
try {
var dropbox = "dropbox";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy")
var contentType = data.substring(5,data.indexOf(';')),
bytes = Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)),
blob = Utilities.newBlob(bytes, contentType, file);
var file = folder.createFolder([date, email].join("--")).createFile(blob);
var fileUrl=file.getUrl();
record_data(e,fileUrl); //record data into my excel
} catch (f) {
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"file upload failed",
"data": JSON.stringify(f) }))
.setMimeType(ContentService.MimeType.JSON);
}
}
function redirect() {
return HtmlService.createHtmlOutput(
"<script>window.top.location.href=\"" + REDIRECT_URL + "\";</script>"
);
}
I don't know if it is Utilities.base64Decode goes wrong or what, cuz I can upload the file but it gives me an error of broken file or wrong format after I tried to download and open it, could anyone tell me what is my mistake??
For addition to how I get the data URL of the files and zip it together:
function dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
var blob = new Blob([ab], {type: mimeString});
return blob;
}
function getfile() {
var zip = new JSZip();
for(let i = 0; i < testpush.length; i++){
var aFileName = "image"+i+1+".jpg";
var aContent = dataURItoBlob(testpush[i]); //content of file
//put files onto a folder
zip.folder("Image_folder").file(aFileName, aContent)
}
zip.generateAsync({type:"base64"})
.then(function (content) {
fileData = "data:application/zip;base64,"+content;
document.getElementById('fileContent').value = fileData;
});
}
The Script of how I send data to google drive in HTML:
<form id="uploadForm" name="form-uploadForm" data-name="uploadForm" method="post" action="MyGoogleAppScirptLink" class="buyerform">
<textarea placeholder="Example Text"
id="fileContent" name="fileContent" data-name="fileContent" class="input"
spellcheck="false"></textarea>
<label class="img_label" for="placeholder_input">
<div class="plus"></div>
</label>
<input type='file' id="placeholder_input" class="hidden" accept="image/*" onchange='openFiles(event)' multiple>
<input id='sumbit-bill-now' class='submit-display-none' value='check it' type='button' onclick='getfile();' />
</form>
I have used js-xlsx plugin to parse JSON from an excel file. I am parsing JSON from multiple excel files and I want to use the same parsing function to load the result in multiple dropdowns. I have two upload file inputs and two corresponding dropdowns. I am able to get the xlFileName and sheetNames only for the first dropdown. If I want to upload a different excel file using the second file upload input and want to load the xlFileName and sheetNames for the corresponding excel file in the second dropdown how can I use the same JS functions to achieve this. Thanks in advance. (I have tried switch case to get the ids of upload file inputs but didn't know how to get it done right)
HTML:
<input type="file" style="display:none;" name="files" id="inputFile1" />
<span data-bind="text: fileNameXl1"></span>
<select id="dropdown3" required="required" class="form-control select2" data-bind="options:xlnames,value:selectedSheetname1,
selectedOptions: chosenFile,optionsCaption:'Please Select Sheet Name'">
</select>
<input type="file" style="display:none;" name="files" id="inputFile2" />
<span data-bind="text: fileNameXl1"></span>
<h4 class="header-title m-t-0 m-b-30">Select Sheet name(Macro):</h4>
<select id="dropdown4" required="required" class="form-control select2" data-bind="options:xlnames1,value:selectedSheetname2,
selectedOptions: chosenFile,optionsCaption:'Please Select Sheet Name'">
</select>
JS:
self.selectedSheetname1 = ko.observable("");
self.selectedSheetname2 = ko.observable();
self.selectedSheetname3 = ko.observable();
self.chosenFile = ko.observable();
self.xlnames = ko.observableArray([]);
self.xlnames1 = ko.observableArray([]);
self.fileNameXl1 = ko.observable();
self.handleFile = function(e) {
var files = e.target.files;
var f = files[0];
{
var reader = new FileReader();
xlFileName = f.name;
self.fileNameXl1(xlFileName);
console.log(xlFileName);
reader.onload = function(e) {
if(typeof console !== 'undefined') console.log("onload", new Date());
var data = e.target.result;
var wb;
var arr = fixdata(data);
wb = X.read(btoa(arr), {type: 'base64'});
process_wb(wb);
}
}
reader.readAsArrayBuffer(f);
};
self.fixdata = function(data) {
var o = "", l = 0, w = 10240;
for(; l<data.byteLength/w; ++l) o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w)));
o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w)));
return o;
};
self.process_wb = function(wb) {
var output = "";
output = JSON.stringify(to_json(wb), 2, 2);
var parse = JSON.parse(output);
sheetNames = Object.keys(parse);
console.log("this is output");
console.log(sheetNames);
self.xlnames(sheetNames);
if(typeof console !== 'undefined') console.log("output", new Date());
};
self.to_json = function(workbook) {
var result = {};
workbook.SheetNames.forEach(function(sheetName) {
var roa = X.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
if(roa.length > 0){
result[sheetName] = roa;
}
});
return result;
};
self.loadSheetNamesB25 = function(e){
self.xlnames([]);
self.handleFile(e);
};
self.loadSheetNamesB41 = function(e){
self.xlnames1([]);
self.xlnames2([]);
self.handleFile(e);
};
if(xlf1.addEventListener) xlf1.addEventListener('change', self.loadSheetNamesB25, false);
if(xlf2.addEventListener) xlf2.addEventListener('change', self.loadSheetNamesB41, false);
I have an aspx page which already has a code for uploading file using "asp:FileUpload" and webform. On a different section of page, I want to add the functionality for a user to upload file. But i do not want to use webforms or "asp:fileupload".
So, I created an HTML file that i inject as an iframe inside a div tag on the aspx.
<div id="iUploadDoc" style="height:50px;">
<iframe name='FileUpload' id='FileUpload' class='iUploadFrame' width='100%' frameborder='0' border='0'src='DocUpload.htm'></iframe></div>
I set the EnablePageMethods to true.
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
And inside the HTML I made a form and with input type file.
<form method="POST" action="DocDetail.aspx.cs" id="docUpload" enctype="multipart/form-data">
<div>
<label for="fileUpload" class="inputLabel">Upload File</label>
<input type="file" id="fileUpload" name="files"/>
</div>
</form>
<div id="progUpload" style="display: none;">
<p class="uploadBox">Uploading...</p>
</div>
<span id= "selectedFile" style="display: none;"></span><span id="fileName" style="display: none;"></span>
Now, I dont know what to put in the "action" param of form.
First on the iframe, below is the script i wrote:
window.onload = load;
function uploadDocFile() {
var prog = document.getElementById("progUpload");
prog.style.cssText = 'display: block;';
var x = document.getElementById("fileUpload");
var txt = "";
var filePath = "";
var fileName = "";
if (x.value == "") {
txt += "Select a file.";
document.getElementById("selectedFile").innerHTML = txt;
} else {
filePath = x.value;
fileName = filePath.replace(/^.*[\\\/]/, '');
txt += "<br>Selected file: ";
document.getElementById("selectedFile").innerHTML = txt;
document.getElementById("fileName").innerHTML = fileName;
}
var formInfo = document.getElementById("docUpload");
document.getElementById("docUpload").style.display = "none";
window.parent.getFormData(formInfo, x ,x.value, fileName);
}
function load() {
var e = document.getElementById("fileUpload");
//var formInfo = document.getElementById("docUpload");
//fakeClick();
e.onchange = function () {
uploadDocFile();
}
}
Then on the parent page, below is the script i wrote.
DocUpload.prototype.uploadFileDoc= function (formInfo, uploadedFile, fileInfo, lastModifiedDate, name, extension, size, type) {
//blacklitsType is an array of types of file (similarly for blacklistExt) that should not be allowed to upload
if (indexOf.call(blackListType, type) < 0 && indexOf.call(blackListExt, extension) < 0) {
var idParams = { OiD: ordId, pID: pId, QID: qId }
var files = uploadedFile.files;
var fileEntries = [];
for (j = 0, len1 = files.length; j < len1; j++) {
file = files[j];
if (file.getAsEntry) {
entry = file.getAsEntry();
} else if (file.webkitGetAsEntry) {
entry = file.webkitGetAsEntry();
}
if (entry) {
isFyl = entry.isFile;
if (!isFyl) {
alert("You can not upload a folder. Uploading files (if present).");
} else {
fileItem = file.getAsFile();
fileEntries.push(fileItem);
}
} else if (!file.type && file.size % 4096 === 0) {
alert("You can not upload a folder. Uploading files (if present).");
} else {
fileEntries.push(file);
}
}
PageMethods.UploadDocument(fileEntries[0], idParams, function (res) {
if (res == true) {
alert("File uploaded successfully.");
} else {
alert("File upload failed.");
}
}, function (err) {
alert("ERROR: " + err._message);
});
} else {
window.alert('You cannot upload incorrect file types.');
}
return;
};
DocUpload.prototype.getFormData = function (formInfo, uploadedFile, fileInfo, nameInfo) {
var currDate, extension, lastModifiedDate, name, nameArr, size, type;
currDate = new Date();
lastModifiedDate = currDate;
type = '';
size = 512;
name = nameInfo;
nameArr = name.split(".");
extension = nameArr[nameArr.length - 1];
DocUpload.prototype.uploadFileDoc(formInfo, uploadedFile, fileInfo, lastModifiedDate, name, extension, size, type);
};
window.getFormData = DocUpload.prototype.getFormData;
The transfer of attributes of form from iframe to parent page work just fine. But how should i post it as file using PageMethod. Below is the page method in my code behind:
[System.Web.Services.WebMethod()]
[System.Web.Script.Services.ScriptMethod(UseHttpGet = false)]
public static bool UploadDocument(HttpPostedFileBase uploadedFile,IdParams idParams) {
bool err = false;
try{
//code
err= true;}
catch(Exception ex){err = false;}
return err;
}
No matter how much tried, either I keep getting error regarding HTTPPostedFileBase or Serialization of child not allowed.Below are only some of the errors i keep getting (not at the same time):
No parameterless constructor System.Web.HttpPostedFileBase aspx, OR
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter
What should i do?
I am struck in a problem where I am trying to read a csv file using Browse button by the following HTML tag:
<input type="file" name="filename" id="filename">
<div id="csvimporthint"></div>
and my jquery code to read and process the input file is as below:
<script>
$("#filename").change(function(e) {
var ext = $("input#filename").val().split(".").pop().toLowerCase();
if($.inArray(ext, ["csv"]) == -1) {
alert('Upload CSV');
return false;
}
if (e.target.files != undefined) {
var reader = new FileReader();
var csvLines;
var csvValues;
var i;
reader.onload = function(e) {
csvLines = e.target.result.split("\n");
for(i=1; i<csvLines.length; i++){
csvValues = csvLines[i].split(",");
importedLat = csvValues[0];
importedLon = csvValues[1];
markerFunc(importedLat, importedLon);
addLayer();
}
//$("#csvimporthint").html(importedLat + " " + importedLon);
reader.readAsText(e.target.files.item(0));
};
}
return false;
});
</script>
The problem that I am facing is that my reader.onload is never fired, in result of which I cannot process my file data. Kindly help me find a solution to make this code running.
P.S: To write this above code, I followed this link: http://jsfiddle.net/W8fME/1650/
I have found the answer of this question myself. The problem was in jquery code in the script tag, correct jquery code is as below:
<script>
$("#filename").change(function(e) {
var ext = $("input#filename").val().split(".").pop().toLowerCase();
if($.inArray(ext, ["csv"]) == -1) {
alert('Upload CSV');
return false;
}
if (e.target.files != undefined) {
var reader = new FileReader();
var csvLines;
var csvValues;
var i;
reader.onload = function(e) {
csvLines = e.target.result.split("\n");
for(i=1; i<csvLines.length; i++){
csvValues = csvLines[i].split(",");
importedLat = csvValues[0];
importedLon = csvValues[1];
markerFunc(importedLat, importedLon);
addLayer();
}
};
reader.readAsText(e.target.files.item(0));
}
return false;
});
</script>
I try to make form which can upload binary data via octokit.js to the github. For example some pdf or image (binary blob). My problem is that all my attempts ends with damaged data at the github side.
Minimal working example: http://jsfiddle.net/keddie/7r3f4q77/
var _arrayBufferToBase64 = function (buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
};
var go = function () {
var config = {
user: $('#user').val(),
repo: $('#repo').val(),
token: $('#token').val(),
handler: document.getElementById('file').files[0]
};
var reader = new FileReader();
var github = new Octokit({
token: config.token
});
var repo = github.getRepo(config.user, config.repo);
var branch = repo.getBranch();
reader.onloadend = function (evt) {
var files = {};
if (evt.target.readyState == FileReader.DONE) {
/* Anothers attempts:
files[ 'x1.pdf' ] = {
isBase64: true,
content: evt.target.result
};
files[ 'x2.pdf' ] = {
isBase64: true,
content: evt.target.result.substring('data:application/octet-stream;base64,'.length)
};
*/
files['x4.pdf'] = {
isBinary: true,
isBase64: true,
content: _arrayBufferToBase64(evt.target.result)
};
} else {
console.warn(evt.target.error);
}
branch.writeMany(files, "API test commit 1").then(function (res) {
if (res) {
console.log('ok');
$('#result').text('OK');
} else {
console.error(res);
$('#result').text('Error');
}
});
};
var blob = config.handler.slice(0, config.handler.size);
//reader.readAsDataURL(blob);
reader.readAsArrayBuffer(blob);
};
$(document).ready(function () {
$('#submit').click(go);
});
And HTML:
<p>User:
<input type="text" id="user" />
</p>
<p>Repo:
<input type="text" id="repo" />
</p>
<p>Token:
<input type="text" id="token" />
</p>
<p>File:
<input type="file" id="file" />
</p>
<p>
<button id="submit">Submit</button>
</p>
<p id="result"></p>
My second problem is how to find filename in reader.onloadend callback (but this is minor issue).
Relevant is this issue: https://github.com/philschatz/octokit.js/issues/44
Problem was in octokit.js library.
I prepare pull request: https://github.com/philschatz/octokit.js/pull/72