There is a form that a user will use to upload an excel file to. From there, in JavaScript, I am able to pull the data (this includes if excel file has multiple sheets) and store it in arrays (columnA, columnB, etc.). However, I am not sure how to write to an existing excel file that is on the server with the data stored in the arrays. Any help would be appreciated.
The following is what I have so far:
let selectedFile, fileName;
document.getElementById('input-excel').addEventListener("change", (event) => {
selectedFile = event.target.files[0];
fileName = event.target.files[0].name;
})
let data=[{
"name":"jayanth",
"data":"scd",
"abc":"sdef"
}]
document.getElementById('button').addEventListener("click", () => {
XLSX.utils.json_to_sheet(data, selectedFile);
if(fileName.includes("Excel FileName")){
let fileReader = new FileReader();
fileReader.readAsBinaryString(selectedFile);
fileReader.onload = (event)=>{
let data = event.target.result;
let workbookInputted = XLSX.read(data,{type:"binary"}); //excel file
let residential_worksheet = workbookInputted.Sheets[workbookInputted.SheetNames[0]]; //test1 sheet
let non_residential_worksheet = workbookInputted.Sheets[workbookInputted.SheetNames[1]]; //test2 sheet
let peh_worksheet = workbookInputted.Sheets[workbookInputted.SheetNames[2]]; //test3 sheet
let educational_worksheet = workbookInputted.Sheets[workbookInputted.SheetNames[3]]; //test4 setting sheet
let correct_worksheet = workbookInputted.Sheets[workbookInputted.SheetNames[4]]; //test5 setting sheet
const sheetList = workbookInputted.SheetNames;
const res = WhichSheet(residential_worksheet,sheetList[0]);
const nonRes = WhichSheet(non_residential_worksheet,sheetList[1]);
const peh = WhichSheet(peh_worksheet,sheetList[2]);
const ed = WhichSheet(educational_worksheet,sheetList[3]);
const correct = WhichSheet(correct_worksheet,sheetList[4]);
//console.log(sheetList[3]);
}
}
});
function WhichSheet(worksheet, fileNme){
if(fileName.localeCompare("test")){
ReadColumntoJSData(worksheet, fileNme);
} else if(fileName.includes("test2")){
ReadColumntoJSData(worksheet, fileNme);
} else if(fileName.includes("test3")){
ReadColumntoJSData(worksheet, fileNme);
} else if(fileName.includes("test4")){
ReadColumntoJSData(worksheet, fileNme);
} else if(fileName.includes("test5")){
ReadColumntoJSData(worksheet, fileNme);
}
}
/*==
====== Following method reads each column per sheet. ======
===*/
function ReadColumntoJSData(worksheet, fileNme){
var colA = [];
var colB = [];
var colC = [];
var colD = [];
var colE = [];
var colF = [];
for(let col in worksheet){
if(col.toString()[0] === 'A'){
if(col === "A1" || col === "A2" || col === "A3"){
//do nothing
} else {
colA.push(worksheet[col].v);
}
}
if(col.toString()[0] === 'B'){
if(col === "B1" || col === "B2" || col === "B3"){
//do nothing
} else {
colB.push(worksheet[col].v);
}
}
if(col.toString()[0] === 'C'){
if(col === "C1" || col === "C2" || col === "C3"){
//do nothing
} else {
colC.push(worksheet[col].v);
}
}
if(col.toString()[0] === 'D'){
if(col === "D1" || col === "D2" || col === "D3"){
//do nothing
} else {
colD.push(worksheet[col].v);
}
}
if(col.toString()[0] === 'E'){
if(col === "E1" || col === "E2" || col === "E3"){
//do nothing
} else {
colE.push(worksheet[col].v);
}
}
if(fileNme == "test2" || fileNme == "test5"){
//do nothing
} else{
if(col.toString()[0] === 'F'){
if(col === "F1" || col === "F2" || col === "F3"){
//do nothing
} else {
colF.push(worksheet[col].v);
}
}
}
}
ExportToExcel(colA,colB,colC,colD,colE,colF);
}
function ExportToExcel(colA,colB,colC,colD,colE,colF,fileName){
console.log(colA)
}
UPDATE: I tried the following to write to the existing excel sheet. However, I am getting the following error: Uncaught TypeError: Cannot read properties of undefined (reading 'A3').
var req = new XMLHttpRequest();
req.open("GET", fileURL2, true);
req.responseType = "arraybuffer";
req.onload = function(e) {
var data = new Uint8Array(req.response);
const writeWorkBook = XLSX.read(data, {type:"array"});
const writeWorkSheet = writeWorkBook.Sheets["TEST123"]
console.log("Worksheet: " + JSON.stringify(writeWorkSheet));
writeWorkSheet['A3'].v = colA[0];
}
req.send();
Related
In checkData method I am checking 2 API's status as fulfilled or rejected and based on that I am sending API Data and FailFlag. How can i optimize it as I have used if else statements.
const checkData = (data, allData, failFlag) => {
if (data && data[0].status === 'fulfilled' && data[1].status === 'fulfilled') {
if (data[0].value && data[1].value) {
allData.push(...data[0].value, ...data[1].value);
failFlag = 'NONE';
}
} else if (data[0].status === 'rejected' && data[1].status === 'fulfilled') {
allData.push(...data[1].value);
failFlag = 'INTERNAL';
} else if (data[0].status === 'fulfilled' && data[1].status === 'rejected') {
allData.push(...data[0].value);
failFlag = 'EXTERNAL';
console.log('All data with fail flag', allData, failFlag);
} else {
Promise.reject('Both are rejected');
failFlag = 'ALL';
}
return { errorFlag: failFlag, accounts: allData };
};
I'm not sure why you are passing in failFlag, because you're never using that variable. I'm also not sure why you have written Promise.reject('Both are rejected');. However, the code can be simplified as follows:
const checkData = ([{status:s0, value:v0}, {status:s1, value:v1}]=[{},{}], allData) => {
let errorFlag = 'NONE';
let f0 = s0 === 'fulfilled';
let f1 = s1 === 'fulfilled';
if(f0) allData.push(...v0);
if(f1) allData.push(...v1);
if(!f0 && !f1) errorFlag = 'ALL';
if(!f0 && f1) errorFlag = 'INTERNAL';
if( f0 && !f1) errorFlag = 'EXTERNAL';
return { errorFlag, accounts: allData };
};
My goal is from an xlsx file that loads the client, represent the variables using Leaflet.
When I give the absolute path of the example that I have on my server everything is fine, the problem comes when I try to give the file from <input type = "file">.
From what I have been able to read in other questions, a "fakepath" is created for security reasons, but this means that I can not access the file that the client leaves in the input.
I'm new to programming and I'm pretty lost in terms of security and this stuff. If someone had a solution, I would be very grateful.
HTML
<input type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
JS
/* DATA --- Read xlsx file (foreign code - PLUGIN xlsx.full.min.js ) */
function readXlsxFile(url, sheet, cb) {
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onerror = function() {
cb(new Error("Could not load file " + url));
}
oReq.onload = function() {
var arraybuffer = oReq.response;
// Convertir datos a binario
var data = new Uint8Array(arraybuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
var workbook = XLSX.read(bstr, { type: "binary" });
var sheetName = workbook.SheetNames[sheet];
var worksheet = workbook.Sheets[sheetName];
var result = XLSX.utils.sheet_to_json(worksheet, { raw: true });
cb(null, result);
}
oReq.send();
};
function readXlsxFileSheet(url, cb) {
const rateFile = serializeMapFormValues().rate
if (rateFile === "travelers" || rateFile === "travelersPoblation" || rateFile === "travelersForeignPercent" || rateFile === "travelersNatPercent") {
readXlsxFile(url, 0, cb);
} else if (rateFile === "ruralTravelers" || rateFile === "ruralForeignPercent" || rateFile === "ruralPercent" || rateFile === "ruralNatPercent") {
readXlsxFile(url, 1, cb);
} else if (rateFile === "apartTravelers" || rateFile === "apartPoblation" || rateFile === "apartForeignPercent" || rateFile === "apartNatPercent") {
readXlsxFile(url, 2, cb);
} else if (rateFile === "hotelTravelers" || rateFile === "hotelForeignPercent" || rateFile === "hotelNatPercent") {
readXlsxFile(url, 3, cb);
} else {
console.log("Lost variable for sheet");
}
};
const submitButton = document.querySelector("input[type=submit]");
submitButton.addEventListener("click", function(ev) {
ev.preventDefault();
//Catch path and variable from the HTML form
let fileUrl = serializeMapFormValues().url;
let fileRow = serializeMapFormValues().rate;
// Update map data
readXlsxFileSheet(fileUrl, function(error, data) {
// code
});
});
If I change fileUrl ("C:\fakepath\turismo_ejemplo_resuelto.xlsx") for "files/turismo_ejemplo_resuelto.xlsx" everything is fine.
I'm trying to setup a file upload through rest for large files. The function below is taking care of chunking but I need to be able to recognize the last chunk because my rest call changes to /finishUpload() in order to commit the save.
Right now I'm only able to figure out when the blob is empty but I can't figure out how to determine the last iteration before the blob is empty.
This is the script I'm using below to parse my files.
export default function parseFile(file, options) {
var opts = typeof options === 'undefined' ? {} : options;
var fileSize = file.size;
var chunkSize = typeof opts['chunk_size'] === 'undefined' ? 64 * 1024 : parseInt(opts['chunk_size']);
var binary = typeof opts['binary'] === 'undefined' ? false : opts['binary'] == true;
var offset = 0;
var self = this; // we need a reference to the current object
var readBlock = null;
var chunkReadCallback = typeof opts['chunk_read_callback'] === 'function' ? opts['chunk_read_callback'] : function() {};
var chunkErrorCallback = typeof opts['error_callback'] === 'function' ? opts['error_callback'] : function() {};
var success = typeof opts['success'] === 'function' ? opts['success'] : function() {};
var onLoadHandler = function(evt) {
if (evt.target.result == "") {
console.log('Chunk empty, call finish');
success(file);
return;
}
if (evt.target.error == null) {
chunkReadCallback(evt.target.result, offset).then(function() {
offset += evt.target.result.length;
readBlock(offset, chunkSize, file);
});
} else {
chunkErrorCallback(evt.target.error);
return;
}
if (offset >= fileSize) {
success(file);
return;
}
}
readBlock = function(_offset, _chunkSize, _file) {
var r = new FileReader();
var blob = _file.slice(_offset, _chunkSize + _offset);
console.log("blob size:", blob.size, "offset:", _offset, "C+S:",_chunkSize + _offset)
r.onload = onLoadHandler;
if (binary) {
r.readAsArrayBuffer(blob);
} else {
r.readAsText(blob);
}
}
readBlock(offset, chunkSize, file);
}
Codepen
Why not rely on the filesize, i.e. check the condition _chunkSize + _offset >= fileSize?
You can use progress, loadend events to process File object one byte at a time; define a variable where processing should be paused or stopped at nth byte, every nth byte, or any byte during processing of file.
var str = "abcdefghijklmnopqrstuvwxyz";
var type = "application/octet-stream";
var data = new Blob([], {
type: type
});
var filename = "file.txt";
var reader = new FileReader();
var complete = false;
var beforeEnd = false;
var stopAt = str.length - 1;
function handleFile(e) {
data = new File([data.slice()
, str.slice(data.size, data.size + 1)]
, filename, {
type: type,
lastModifiedDate: new Date()
});
}
function handleRead(e) {
if (data.size <= str.length && !complete) {
if (data.size === stopAt && !beforeEnd) {
beforeEnd = true;
var r = new FileReader();
r.onloadend = function() {
alert(`stopAt: ${stopAt}\n`
+`data.size: ${data.size}\n`
+`result at stopAt: ${r.result[stopAt -1]}`);
reader.readAsArrayBuffer(data);
}
r.readAsText(data);
} else {
reader.readAsArrayBuffer(data)
}
} else {
console.log("complete")
}
}
function handleProgress(e) {
if (data.size <= str.length && !complete) {
var read = new FileReader();
read.onload = function() {
if (!complete) {
console.log(read.result);
if (read.result.length === str.length) {
complete = true;
console.log(data);
}
}
}
read.readAsText(data);
}
}
reader.addEventListener("load", handleFile);
reader.addEventListener("loadend", handleRead);
reader.addEventListener("progress", handleProgress);
reader.readAsArrayBuffer(data);
The hierarchy can be very deep, So how to check if the a property exists somewhere within the root object ? If not then create it.
I have the following html
<div id="container">
<div id="level-1">
<input id="value-1" group="a.b" name="c" value="some-value-1">
</div>
</div>
Now i would like to put the value of this input into a javascript object based on the parent attribute.
Desired output is
{
"a" : {
"b" : {
"c" : "some-value-1"
}
}
}
My Effort :
function traverse(id, obj) {
var methodName = "traverse";
var elementToTraverse = document.getElementById(id);
var currentElementLength = elementToTraverse.childNodes.length;
if (currentElementLength > 0) {
var children = getChildNodes(elementToTraverse);
for (var ch in children) {
var currentChild = children[ch];
//ignore the text nodes
if (currentChild.nodeType == 3) {
continue;
}
if (currentChild.nodeType == 1 && currentChild.childNodes.length > 0 && currentChild.id != "") {
//call without the object argument as it has already been constructed.
traverse(currentChild.id, obj);
}
else if (currentChild.nodeType == 1 && currentChild.id != "" && currentChild.getAttribute('name') != null) {
if (DEBUG) {
logOnConsole(methodName, currentChild.getAttribute('name') + "--" + currentChild.id, logLevel.INFO);
}
var group = currentChild.getAttribute('group') || null;
var name = currentChild.getAttribute('name');
var value = getValue(currentChild);
if (value == "" || value == undefined) {
if(group){
if(isNull(obj[group])){
obj[group] = new Object();
}
obj[group][name] = "";
}
else{
obj[name] = "";
}
}
else if(group){
if(isNull(obj[group])){
obj[group] = new Object();
}
obj[group][name] = value;
}
else {
obj[name] = value;
}
}
else {
if (DEBUG) {
logOnConsole(methodName, "Element not useful. \n" + currentChild.nodeName, logLevel.INFO);
}
}
}
}
return obj;
}
I call it via traverse('container-id', new Object()) but this will work for a single value in the group rather than a nested structure.
Try this
function isExist(obj, path) {
patharray = path.split(".");
for(var i=0;i < patharray.length; i++) {
obj = obj[patharray[i]];
if(obj === undefined) return false
}
return true;
}
document.body.innerHTML = isExist({subobject:{subsubobject:{test: 34}}}, 'subobject.subsubobject');
I am developping an hybrid app (JQM 1.4 + Phonegap 3.6.3).
I have a function populateImagesUrlsLocalAndServer that checks if an image file exists on my server, but I can't use this function because it makes my app crash on Phonegap...
I can't find why.
Can you help me fix this issue so I can use this feature in my app again ?
Thank
function populateImagesUrlsLocalAndServer(str, baseUrl, type) {
if (connectionStatus == "online") {
if (UrlExists('./'+baseUrl+str)) { //local file
imagesUrls[str] = './'+baseUrl+str;
} else if (isPhoneGap && UrlExists('http://boardlineapp.com/app/'+baseUrl+str)) { //server file....we exclude this for desktop browser because of cross domain error
console.log('retrieving '+'http://boardlineapp.com/app/'+baseUrl+str+' on server')
imagesUrls[str] = 'http://boardlineapp.com/app/'+baseUrl+str;
} else {
imagesUrls[str] = './'+baseUrl+'default.png';
}
} else { //offline
if (UrlExists('./'+baseUrl+str)) { //local file
imagesUrls[str] = './'+baseUrl+str;
} else {
imagesUrls[str] = './'+baseUrl+'default.png';
}
}
imagesUrls[str+'type'] = type;
}
instead, for now I am using :
function populateImagesUrls(str, baseUrl, type) {
if ( str == 'byrne-ow-fender.png'
|| str == 'ci-tacogrinder.png'
|| str == 'noamizuno.png'
|| str == 'brendanmargieson.png'
|| str == 'kaihing.png'
|| str == 'dustinhollick.png'
|| str == 'dhd-thetwin.png'
) {
//console.log(str);
//console.log(baseUrl);
imagesUrls[str] = './'+baseUrl+'default.png';
} else {
imagesUrls[str] = './'+baseUrl+str;
}
imagesUrls[str+'type'] = type;
}
the function that calls it is the following:
function checkIfImagesExistAllAtOnce() {
var prodataTemp = [];
prodataTemp = prodata.slice();
prodataTemp.shift();
prodataTemp.sort(sort_by('brand', 'name', 'model'));
var strBrandDone;
var strNameDone;
var strModelDone;
for (i = 1; i < prodataTemp.length; ++i) {
//check brand
var str = prodataTemp[i]['brand'].replace(/\s+/g, '').toLowerCase();
str = str+'.png';
if (str != strBrandDone) {
var baseUrl = "images/brands/";
strBrandDone = str;
var type = "brand";
populateImagesUrls(str, baseUrl, type);
//populateImagesUrlsLocalAndServer(str, baseUrl, type);
}
//check pro image
var str = prodataTemp[i]['name'].replace(/\s+/g, '').toLowerCase();
str = str+'.png';
if (str != strNameDone) {
var baseUrl = "images/pros/";
strNameDone = str;
var type = "pro";
populateImagesUrls(str, baseUrl, type);
//populateImagesUrlsLocalAndServer(str, baseUrl, type);
}
//check board image
var str = prodataTemp[i]['imageName'];
if (str != strModelDone) {
var baseUrl = "images/boards/";
strModelDone = str;
var type = "board";
populateImagesUrls(str, baseUrl, type);
//populateImagesUrlsLocalAndServer(str, baseUrl, type);
}
}
prodataTemp = null;
}