Suppose I have this loop code.
for (var i = 0; i < originList.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
outputDiv.innerHTML += results[j].distance.text + ',';
}
}
I want to export the outputDiv.innerHTML into CSV with this code, but it doesn't work.
function downloadFile(fileName, urlData) {
var aLink = document.createElement('a');
aLink.download = fileName;
aLink.href = urlData;
var event = new MouseEvent('click');
aLink.dispatchEvent(event);
}
downloadFile('output.csv', 'outputDiv.innerHTML/csv;charset=UTF-8,' + encodeURIComponent(outputDiv.innerHTML));
What should I do? I'm new at this. Thank you.
This solution is in JavaScript. I added an event listener to the button so when it is clicked, it will grab the outerHTML of <table>.
outerHTML essentially includes the opening and closing tags of the element as well as the content whereas innerHTML does not include the opening and closing tags.
From MDN Web Docs
The outerHTML attribute of the Element DOM interface gets the serialized HTML fragment describing the element including its descendants. It can also be set to replace the element with nodes parsed from the given string.
When the innerText is extracted from the all rows and columns. download_csv is called.
You can download the data using a Blob object which is a file-like object of immutable, raw data.
document.querySelector("button").addEventListener("click", function () {
let html = document.querySelector("table").outerHTML;
exportToCSV(html, "table.csv");
});
function exportToCSV(html, filename) {
let csv = [];
// grab all rows inside table
let rows = document.querySelectorAll("table tr");
let row, cols;
for (let i = 0; i < rows.length; i++) {
row = []; // will hold innerText of all columns
// retrieve all columns of row
cols = rows[i].querySelectorAll("td, th");
for (let j = 0; j < cols.length; j++){
// push column innerText
row.push(cols[j].innerText);
}
// push all innerText into CSV
csv.push(row.join(","));
}
console.log("Extracted content from html:",csv);
// Download CSV
download_csv(csv.join("\n"), filename);
}
function download_csv(csv, filename) {
let csvFile;
let downloadLink;
// CSV FILE
csvFile = new Blob([csv], {type: "text/csv"});
// create an element and set the file name.
downloadLink = document.createElement("a");
downloadLink.download = filename;
// We have to create a link to the file
downloadLink.href = window.URL.createObjectURL(csvFile);
// prevent link from being shown
downloadLink.style.display = "none";
// Add the link to your DOM
document.body.appendChild(downloadLink);
// start the download
downloadLink.click();
}
<table>
<tr><th>Name</th><th>Age</th><th>Country</th></tr>
<tr><td>Tony</td><td>26</td><td>USA</td></tr>
<tr><td>Levi</td><td>19</td><td>Spain</td></tr>
<tr><td>Calvin</td><td>32</td><td>Russia</td></tr>
</table>
<button>Export HTML table to CSV file</button>
I do not know what are you trying to achieve in your last line, but that does not look like a dataURL, a dataURL looks like:
data:[][;base64],
Now that being said, the idea is to create an object url through a combination of Blob and window.URL.createObjectURL:
function dL(input,fileName){
var blob = new Blob(input,{type:"text/csv"}),
url = window.URL.createObjectURL(blob),
aElem = document.createElement("a"),
fileName = "deogenResults.txt";
aElem.setAttribute("href",url);
aElem.setAttribute("download",fileName);
if (window.navigator.constructor.prototype.hasOwnProperty("msSaveBlob")) {
window.navigator.msSaveBlob(blob,fileName);
} else if ("download" in aElem) {
aElem.click();
} else {
window.open(url,"_blank");
}
setTimeout(function(){window.URL.revokeObjectURL(url)},2000);
}
Use it like this: dL(outputDiv.innerHTML,"someName")
It is important to remind you that some browsers might not allow click to trigger on an element that is NOT in the DOM yet, in that case you might want to append the a element to the body, set it invisible and then remove it inside setTimeout.
I wrote it in plain ES5, you can adapt with const,Promise instead of setTimeout etc declarations accordingly.
A good answer here by dandavis:
It uses a library by http://danml.com/js/download.js you make sure your div contents contains comma seperated content.
var csv = jQuery(".list").map(function(a, i) {
return $.trim($(this).text()).split(/\s*\n\s*/).join(",");
}).toArray().join("\r\n");
alert(csv); // Contents
// Download
// download(csv, "tabledata.csv", "text/csv");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="http://danml.com/js/download.js"></script> <!-- CSV -->
<div class="list">
1, 2, 3
</div>
Related
Following my previous query:
HTML form output as a table
I would like to export my HTML form output to Excel.
I found several examples on the web and tried some of them...
https://www.revisitclass.com/css/how-to-export-download-the-html-table-to-excel-using-javascript/
https://www.codexworld.com/export-html-table-data-to-csv-using-javascript/
https://odoepner.wordpress.com/2012/04/09/export-to-html-table-as-csv-file-using-jquery/
In all cases, I get only the column titles instead of other rows, as you can see below:
There is something wrong with the Element.append() which can't be picked up properly
My code looks as follows:
<table id="opresults" class="outputtable"><p class="outputtablehead">Survey Form - output</p>
<tr class="colname">
<th class="question">Form question</th>
<th colspan="2" class="answer">Answer</th>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
<script>
const resultsList = document.getElementById('opresults')
const matches = document.querySelectorAll("fieldset");
new URLSearchParams(window.location.search).forEach((value, name) => {
resultsList.append(document.createElement('tbody'))
resultsList.append(`${name}`)
resultsList.append(document.createElement('td'))
resultsList.append(`${value}`)
resultsList.append(document.createElement('br'))
})
</script>
and another script, which exports the file to .csv is included here:
https://jsfiddle.net/c0urwa5g/1/
Is there any way to include the append() method in this .csv export?
As per another example:
How to export JavaScript array info to csv (on client side)?
It looks like I have to define the column and row names. Unfortunately, I can't here, because they are input-dependant. Is there a way to solve this issue?
The code with another approach is here:
function downloadCSV(csv, filename) {
var csvFile;
var downloadLink;
// CSV file
csvFile = new Blob([csv], {type: "text/csv"});
// Download link
downloadLink = document.createElement("a");
// File name
downloadLink.download = filename;
// Create a link to the file
downloadLink.href = window.URL.createObjectURL(csvFile);
// Hide download link
downloadLink.style.display = "none";
// Add the link to DOM
document.body.appendChild(downloadLink);
// Click download link
downloadLink.click();
}
function exportTableToCSV(filename) {
var csv = [];
var rows = document.querySelectorAll("table tr");
for (var i = 0; i < rows.length; i++) {
var row = [], cols = rows[i].querySelectorAll("td, th");
for (var j = 0; j < cols.length; j++)
row.push(cols[j].innerText);
csv.push(row.join(","));
}
// Download CSV file
downloadCSV(csv.join("\n"), filename);
}
You aren't creating row elements or inserting cells in those row elements or inserting text into the cells you are creating
You are trying to append everything directly into the table element and that won't work.
You can simplify this using Table.insertRow() and Row.insertCell()
initDemo()
const resultsList = document.getElementById('opresults');
new URLSearchParams(window.location.search).forEach((value, name) => {
const row = resultsList.insertRow();
[name, value].forEach(v => row.insertCell().textContent = v);
})
// for demo only - creates initial url search params
function initDemo() {
const params = new URLSearchParams([
["issue_1", "answer_1"],
["thing_2", "answer_2"]
]);
history.pushState(null, null, '?' + params.toString())
}
<p class="outputtablehead">Survey Form - output</p>
<table id="opresults" class="outputtable" border="1">
<tr class="colname">
<th class="question">Form question</th>
<th colspan="2" class="answer">Answer</th>
</tr>
</table>
my problem is when I select the multiple images it displaying correct, and I am storing this in one array, from that array I need to get the image name. right now it's working but in setOfImages array all image name is same. i need to take the image URL also when i put that setOfImages array in map function that URL are get repeating this are two problems I am facing if not clear put console.log(setOfImages) and console.log(imageUrl),
imagetrigger(e){
var setOfImages =[], imageUrl=[];
for (var i = 0; i < e.target.files.length; i++){
var file = e.target.files[i];
if(!file.type.match('image'))
continue;
var reader = new FileReader();
reader.onload = function(e){
setOfImages.push({
fileName:file.name,
image:e.target.result.split(',')[1]
});
$('.image').remove();
for(var j = 0; j<setOfImages.length; j++) {
$('.placeholder').prepend('<div class="image"><img src="data:image/jpeg;base64,'+ setOfImages[j].image +'" /></div>');
}
setOfImages.map(function(){
imageUrl.push(el.fileName);
})
console.log(imageUrl)
}
reader.readAsDataURL(file);
}
}
Just add parameter el to your map.
setOfImages.map(function(){
imageUrl.push(el.fileName);
})
Change like this.
setOfImages.map(function(el){
imageUrl.push(el.fileName);
})
Target: write&download a csv file starting with a json string, for example data.csv containing
col1,col2,col3
"324","19-08-2014","13000"
"325","19-08-2014","5010"
What I have done until now:
1) iframe and button to call my conversion function
<iframe id="frame" style="display:none"></iframe>
<form><input type="submit" value="Export CSV" onclick="javascript:Download();"></form>
2) my Download() function which would want to download my csv file
<script type="text/javascript">
function Download(){
var csv=ConvertToCSV(<?php echo $json_string ?>);
var url='data:application/csv,'+csv;
var _iframe_dl = $('<iframe />')
.attr('src', url)
.hide()
.appendTo('body');
};
</script>
3) my json to csv conversion function which tries to create a csv string
<script type="text/javascript">
function ConvertToCSV(json) {
var array = typeof json != 'object' ? JSON.parse(json) : json;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
if (line != '') line += ','
line += '"'+array[i][index]+'"';
}
str += line + "\r\n";
}
return str;
}
</script>
Encountered problems :
i) it seems that it doesn't recognize \r\n, infact output is just one line
"324","19-08-2014","13000""325","19-08-2014","5010"
ii) I cannot set the filename and the extension, infact the downloaded file is "download" without extension containing the single line mentioned above
First of all, you will need to ensure your data is in this format, like the example below.
var array = [["col1","col2","col3"],["324","19-08-2014","13000"],["324","19-08-2014","13000"]]
then you need to create csv variable as shown below
var csv = "data:text/csv;charset=utf-8,";
after this you need to loop through your data array and append each line to the csv variable you just set.
array.forEach(function(arrayItem, index){
arrayAsString = arrayItem.join(",");
csv += index < array.length ? arrayAsString+ "\n" : arrayAsString;
});
now to give this file a name and create a download link you must create a hidden anchor node and set its download attribute.
var encUri = encodeURI(csv);
var link = document.createElement("a");
link.setAttribute("href", encUri);
link.setAttribute("download", "file_name.csv");
//add anchor element to body
document.body.appendChild(link);
link.click();
EDIT:
Tested on Chrome and is working, also on Safari. Does not work on Firefox for some reason which i will take a look at now
I found out that if you add the link into the body of the page only then will Firefox initiate the download, you can use a code like so. I have updated my code above
document.body.appendChild(link);
If we were on a nodeJS server, we could write a header, set a mime type, and send it:
res.header("Content-Disposition", "attachment;filename="+name+".csv");
res.type("text/csv");
res.send(200, csvString);
and because of the headers, the browser will create a download for the named csv file.
When useful data is generated in a browser, one solution to getting it in a CSV file is to use ajax, upload it to the server, (perhaps optionally save it there) and get the server to send it back with these headers to become a csv download back at the browser.
However, I would like a 100% browser solution that does not involve ping-pong with the server.
So it occurred to me that one could open a new window and try to set the header with a META tag equivalent.
But this doesn't work for me in recent Chrome.
I do get a new window, and it contains the csvString, but does not act as a download.
I guess I expected to get either a download in a bottom tab or a blank new window with a download in a bottom tab.
I'm wondering if the meta tags are correct or if other tags are also needed.
Is there a way to make this work without punting it to the server?
JsFiddle for Creating a CSV in the Browser (not working - outputs window but no download)
var A = [['n','sqrt(n)']]; // initialize array of rows with header row as 1st item
for(var j=1;j<10;++j){ A.push([j, Math.sqrt(j)]) }
var csvRows = [];
for(var i=0,l=A.length; i<l; ++i){
csvRows.push(A[i].join(',')); // unquoted CSV row
}
var csvString = csvRows.join("\n");
console.log(csvString);
var csvWin = window.open("","","");
csvWin.document.write('<meta name="content-type" content="text/csv">');
csvWin.document.write('<meta name="content-disposition" content="attachment; filename=data.csv"> ');
csvWin.document.write(csvString);
There's always the HTML5 download attribute :
This attribute, if present, indicates that the author intends the
hyperlink to be used for downloading a resource so that when the user
clicks on the link they will be prompted to save it as a local file.
If the attribute has a value, the value will be used as the pre-filled
file name in the Save prompt that opens when the user clicks on the
link.
var A = [['n','sqrt(n)']];
for(var j=1; j<10; ++j){
A.push([j, Math.sqrt(j)]);
}
var csvRows = [];
for(var i=0, l=A.length; i<l; ++i){
csvRows.push(A[i].join(','));
}
var csvString = csvRows.join("%0A");
var a = document.createElement('a');
a.href = 'data:attachment/csv,' + encodeURIComponent(csvString);
a.target = '_blank';
a.download = 'myFile.csv';
document.body.appendChild(a);
a.click();
FIDDLE
Tested in Chrome and Firefox, works fine in the newest versions (as of July 2013).
Works in Opera as well, but does not set the filename (as of July 2013).
Does not seem to work in IE9 (big suprise) (as of July 2013).
An overview over what browsers support the download attribute can be found Here
For non-supporting browsers, one has to set the appropriate headers on the serverside.
Apparently there is a hack for IE10 and IE11, which doesn't support the download attribute (Edge does however).
var A = [['n','sqrt(n)']];
for(var j=1; j<10; ++j){
A.push([j, Math.sqrt(j)]);
}
var csvRows = [];
for(var i=0, l=A.length; i<l; ++i){
csvRows.push(A[i].join(','));
}
var csvString = csvRows.join("%0A");
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([csvString]);
window.navigator.msSaveOrOpenBlob(blob, 'myFile.csv');
} else {
var a = document.createElement('a');
a.href = 'data:attachment/csv,' + encodeURIComponent(csvString);
a.target = '_blank';
a.download = 'myFile.csv';
document.body.appendChild(a);
a.click();
}
#adeneo answer works for Firefox and chrome... For IE the below can be used.
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([decodeURIComponent(encodeURI(result.data))], {
type: "text/csv;charset=utf-8;"
});
navigator.msSaveBlob(blob, 'FileName.csv');
}
See adeneo's answer, but don't forget encodeURIComponent!
a.href = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csvString);
Also, I needed to do "\r\n" not just "\n" for the row delimiter.
var csvString = csvRows.join("\r\n");
Revised fiddle: http://jsfiddle.net/7Q3c6/
Once I packed JS code doing that to a tiny library:
https://github.com/AlexLibs/client-side-csv-generator
The Code, Documentation and Demo/Playground are provided on Github.
Enjoy :)
Pull requests are welcome.
We can easily create and export/download the excel file with any separator (in this answer I am using the comma separator) using javascript. I am not using any external package for creating the excel file.
var Head = [[
'Heading 1',
'Heading 2',
'Heading 3',
'Heading 4'
]];
var row = [
{key1:1,key2:2, key3:3, key4:4},
{key1:2,key2:5, key3:6, key4:7},
{key1:3,key2:2, key3:3, key4:4},
{key1:4,key2:2, key3:3, key4:4},
{key1:5,key2:2, key3:3, key4:4}
];
for (var item = 0; item < row.length; ++item) {
Head.push([
row[item].key1,
row[item].key2,
row[item].key3,
row[item].key4
]);
}
var csvRows = [];
for (var cell = 0; cell < Head.length; ++cell) {
csvRows.push(Head[cell].join(','));
}
var csvString = csvRows.join("\n");
let csvFile = new Blob([csvString], { type: "text/csv" });
let downloadLink = document.createElement("a");
downloadLink.download = 'MYCSVFILE.csv';
downloadLink.href = window.URL.createObjectURL(csvFile);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
See adeneo's answer, but to make this work in Excel in all countries you should add "SEP=," to the first line of the file. This will set the standard separator in Excel and will not show up in the actual document
var csvString = "SEP=, \n" + csvRows.join("\r\n");
I have to display images to the browser and I want to get the image from a JSON response and display it to the browser using Javascript. This is what the JSON response looks like:
[{
"0":"101",
"member_id":"101",
"1":"3k.png",
"image_nm":"3k.png",
"2":"\/images\/phones\/",
"image_path":"\/images\/"
},{
"0":"102",
"member_id":"102",
"1":"mirchi.png",
"image_nm":"mirchi.png",
"2":"images\/phones\/",
"image_path":"images\/phones\/"
},{
"0":"103",
"member_id":"103",
"1":"masti.png",
"image_nm":"masti.png",
"2":"images\/phones\/",
"image_path":"images\/phones\/"
}]
How do I do this (I am a beginner)?
here is the code what i wrote...
var jsonString = '[{"0":"101","member_id":"101","1":"3k.png","image_nm":"3k.png","2":"\/images\/phones\/","image_path":"\/images\/phones\/"},{"0":"102","member_id":"102","1":"mirchi.png","image_nm":"mirchi.png","2":"images\/phones\/","image_path":"images\/phones\/"},{"0":"103","member_id":"103","1":"masti.png","image_nm":"masti.png","2":"images\/phones\/","image_path":"images\/phones\/"}]';
var obj = JSON.parse(jsonString);
for(var i = 0, len = obj.length; i < len; i++){
var img = new Image();
img.setAttribute("src",obj[i][2] + obj[i][1]);
document.body.appendChild(img);
}
Assuming you parsed your json in a variable called json, this would add all images in a container with id yourcontainer:
var images = '';
for( var i=0, max<json.length; ++i ) {
images += '<img src="' + json[i]['image_path'] + json[i]['image_nm'] + '" />';
}
document.getElementById( 'yourcontainer' ).innerHTML = images;
Seems pretty straight forward. If this is json_encoded, then we can use json[key] to get the value, if you aren't familiar with the term 'key', json encodes arrays in the key:value, format, so for this, if we used json[member_id], we would get '101', if we used json[image_nm], we would get '3k.png', putting this all together it seems as if it's pretty well separated, you just have to know what goes where. I have an idea, but not 100%,I would expect you to do something like
var myImages = '';
for(var i = 0; i < json.length; i++){
myImages += '<img src="'+json[i]['image_path']+json[i]['img_nm']+'" />';
}
document.getElementById('myImgHolder').innerHTML = myImages;
Based on your json data, this would evaluate a variable and test it against the length of the json array. The statement also declares that while the variable is less than the total length of the json array, we will iterate to the next object. We would expect output along the format of -
<img src="/images/3k.png" />.
Then it would take the new images and place them in a Div with the id of myImgHolder.
Hope this helps.
EDIT 1
If you don't have a container to place these images inside of it, then you will need to create the container and place it somewhere.
var myImgHolder = document.createElement('div');
myImgHolder.setAttribute("id", "myImgHolder");
document.getElementById('ICanTargetThis').appendChild(myImgHolder);
The above code sets the variable myImgHolder to the creation of a new DIV element. Then, using the variable, we declare the attribute "id" to set as 'myImgHolder'. Now we have the element. But what do we do with it? Well we MUST target an existing element within our page, even if we're just targeting the tag...something. then we use the .appendChild method and use our variable...appendChild(myImgHolder);
You can use jQuery here.
Add following script in the head tag.
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
$(document).ready(function () {
var url = "entries.json";
$.getJSON(url, function (url){
var img= "";
$.each(url, function () {
img += '<li><img src= "' + this.images+ '"></li>';
});
$('body').append(img);
});
});
</script>