Export html table to excel using javascript - javascript

I tried to export my html table to excel using the code given in this Gist. But after exporting, when i opened the file, It displays the html code of the demo page in excel. Can anyone please give the correct sample of javascript used to export the html table to excel (Should be opened in office Calc too).
EDIT: Attached the image screenshot.

Here is a function I made.
Add "remove" class on elements you do not want to show in the excel.
function exportExcel(id,name){ //<table> id and filename
var today = new Date();
var date = ('0'+today.getDate()).slice(-2)+"-"+('0'+(today.getMonth()+1)).slice(-2)+"-"+today.getFullYear();
var file_name = name+"_"+date+".xls"; //filename with current date, change if needed
var meta = '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />';
var html = $("#"+id).clone();
html.find('.remove').remove(); //add the 'remove' class on elements you do not want to show in the excel
html.find('a').each(function() { //remove links, leave text only
var txt = $(this).text();
$(this).after(txt).remove();
});
html.find('input, textarea').each(function() { //replace inputs for their respectives texts
var txt = $(this).val().replace(/\r\n|\r|\n/g,"<br>");
$(this).after(txt).remove();
});
html.find('select').each(function() { //replace selects for their selected option text
var txt = $(this).find('option:selected').text();
$(this).after(txt).remove();
});
html.find('br').attr('style', "mso-data-placement:same-cell"); //make line breaks show in single cell
html = "<table>"+html.html()+"</table>";
var uri = 'data:application/vnd.ms-excel,'+encodeURIComponent(meta+html);
var a = $("<a>", {href: uri, download: file_name});
$(a)[0].click();
}
Call it on an event, example:
$("#export_button").click(function(e){
exportExcel("table_id", "filename");
});

Related

Export HTML to Word Doc with continuous line number

I am trying to export HTML content - Table + paragraphs with multiple line breaks.
I want HTML content to export in word doc with Auto line numbers in word document.
I do not want it to generate in code by using loops or any other way. I want it to auto set by word doc.
I have tried below code in PHP :
$objWriter->startElement('w:sectPr');
$objWriter->startElement('w:lnNumType');
$objWriter->writeAttribute('w:countBy', '1');
$objWriter->writeAttribute('w:restart', 'continuous');
$objWriter->endElement();
I have added above code in Document.PHP under function _writeEndSection() after $borders = $_settings->getBorderSize(); in PHPWord Library and its working fine.
Can I do it in JavaScript by using XML code or mso-element tags and attribute?
I have used below code but its not working for me.
function exportHTML(){
var header = '<html xmlns:v="urn:schemas-microsoft-com:vml"'+
'xmlns:o="urn:schemas-microsoft-com:office:office"'+
'xmlns:w="urn:schemas-microsoft-com:office:word"'+
'xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"'+
'xmlns="http://www.w3.org/TR/REC-html40">'+
'<head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><title></title>'+
'<xml>'+
'<w:WordDocument>'+
'<w:View>Print</w:View>'+
'<w:Zoom>75</w:Zoom>'+
'<w:DoNotOptimizeForBrowser/>'+
'</w:WordDocument>'+
'<w:sectPr>'+
'<w:lnNumType w:countBy=1 w:restart=continuous >'+
'</w:sectPr>'+
'</xml>'+
'</head>'+
'<body style="font: Arial">';
var tblNew = 'TableData';
var footer = "</body></html>";
var sourceHTML = header+tblNew+document.getElementById("source-html").innerHTML+footer;
var source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML);
var fileDownload = document.createElement("a");
document.body.appendChild(fileDownload);
fileDownload.href = source;
fileDownload.download = 'testfile.doc';
fileDownload.click();
document.body.removeChild(fileDownload);
}
Can anyone help me on this requirement? Thank You in advance.

Callback function on a url?

In my web app, I want to be able to click on a href link within a datatable that loads a second table on a new page, which in turn filters out rows so that the table only displays rows with the same id as the id of the row I clicked on in the previous table/page.
The code below does not work. I believe this is because before it has had time to save the row data from the first table, a new web page is already being opened and it is too late to save the data as it is no longer there. Is there a way to create a callback so that my javascript function is executed before the href link is opened?
Or maybe I am doing this completely wrong?
Any help would be appreciated.
Datatable.Column() code: (the user clicks on an image/url link within the table):
"data": "ErrorCount",
"render": function (data, type, row) {
if (type === 'display') {
return (data === 0)
? data = '<span data-search="0"></span>'
: data = '<a id="errors" href="http://localhost/WTM/LogError/Index" type="hidden" class="fas fa-exclamation-triangle" style="color:red"></a>';
}
return data;
},
Javascript filter function:
var clickError = document.getElementById("errors")
var xTable = $('#TABLE_ONE').DataTable();
var yTable = $('#TABLE_TWO').DataTable();
$('clickError').click(function () {
var rowData = xTable.row(this).data();
yTable.columns(0).search(rowData.TaskSchedulerLogUid).draw();
});
Multiple issues here:
ID's can't be repeated in a page, use class instead
$('clickError') is invalid selector
The elements in question are dynamically rendered and thus won't all exist when the code is run. Use event delegation
The row is not the <a>
Fixes:
HTML
'<a ̶i̶d̶=̶"̶e̶r̶r̶o̶r̶s̶"̶ class="errors"...
JS
$('#tableID').on('click', 'a.errors', function(e){
e.preventDefault();
var row = $(this).closest('tr')[0];
var rowData = xTable.row(row).data();
yTable.columns(0).search(rowData.TaskSchedulerLogUid).draw();
})
For anyone interested. I found a different way of doing this.
First I added the search query/row ID to the url of the new page I wanted to open like this:
'
then I extracted the search query/ID from the url, and searched the table on the new page using the newly extracted search query/ID, like this:
var queryString = window.location.search;
queryString = queryString.substring(4);
if (queryString == null) {
throw "Error: id is null"
} else {
WtmDetails.vars.secondaryTable.columns(0).search(queryString).draw();
}

Button function does not work when in subpage

I have a function where i can download my table data into csv. But the button function only works when i place it in my index.html page, while my table's on the subpage.html page. But somehow, my button in the index page is able to download my table data in that subpage.html when i navigate to there.
Index.html : The button here works
<body>
<header ng-include="'views/header.html'"></header>
<main ng-view></main>
<button type="button" id="btnDownload"> Download as CSV</button>
</body>
Subpage.html : If i place the button here it doesn't work
<div>
<table id="tabletodownload" ng-show="auditoriums === 'none'" style="border:1px solid #000;">
<tr> <th> Customer Name </th> <th> Order Value </th> <th> Ordered On </th> </tr>
<tr ng-repeat="audit in auditoriums| limitTo: 1 - auditoriums.length">
<td>{{audit.NAME}}</td>
<td>{{audit.ADDRESSBLOCKHOUSENUMBER}}</td>
<td>{{audit.ADDRESSPOSTALCODE}}</td>
<td>{{audit.ADDRESSSTREETNAME}}</td>
</tr>
</table>
<br />
</div>
<button type="button" id="btnDownload"> Download as CSV</button>
Javascript code to DL to csv :
$(function() {
$('#btnDownload').click(function() {
$("#tabletodownload").tableToCSV({
filename: 'CustomerList'
});
});
});
jQuery.fn.tableToCSV = function (options) {
var settings = $.extend({
filename: ""
}, options);
var clean_text = function (text) {
text = $.trim(text.replace(/"/g, '""'));
return '"' + text + '"';
};
$(this).each(function () {
var table = $(this);
var caption = settings.filename;
var title = [];
var rows = [];
$(this).find('tr').each(function () {
var data = [];
$(this).find('th').each(function () {
var text = clean_text($(this).text());
title.push(text);
});
$(this).find('td').each(function () {
var text = clean_text($(this).text());
data.push(text);
});
data = data.join(",");
rows.push(data);
});
title = title.join(",");
rows = rows.join("\n");
var csv = title + rows;
var uri = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv);
var download_link = document.createElement('a');
download_link.href = uri;
var ts = new Date().getTime();
if (caption == "") {
download_link.download = ts + ".csv";
} else {
download_link.download = caption + "-" + ts + ".csv";
}
document.body.appendChild(download_link);
download_link.click();
document.body.removeChild(download_link);
});
};
If the index.html and subpage.html are 2 different pages (and not an angularjs template or something like that) then it's probably because the code that is handling the button click and the rest of your function doesn't exist in the subpage.html.
quick and dirty
I assume you're not using any build tools. The simplest way is to move the button function to a script tag inside subpage.html
the angularjs way
I see you're using angularjs in the project. Manually attaching evenlisterens like a button click isn't the angularjs way of doing thing. You could easily move the functionality to your angular controller that control's that page and add a ng-click attribute to the button that calls that function. This way you're letting the framework decide when and hpw to attach the click event listener instead of managing that yourself.
Btw...
Using a framework like angular/react/vue most of the times makes jQuery unnecessary. In this case you could also use a library that made for amgularjs to make a csv from a table. jQuery is very DOM way of thinking while angular is more of a DATA way of thinking. In my opinion is that why it's better to not mix these things.
This might help you:
https://github.com/kollavarsham/ng-table-to-csv

How to get complete data from (html) bootstrap table when pagination is turned on

I am using bootstrap table in my web page and want to get complete textual data from all table cells, when pagination is on. I have tried the following method and it returns all the data:
var data = $('#' + tableID).bootstrapTable('getData')
Now when i traverse data object to get value for every cell it works fine but, for those cells which have some nested html , for example:
<td class="danger">cell 4</td>
<td>
google
</td>
Now, in this case, i want to get value for second cell as google but it returns me whole html as
google
Any idea, how i can get only textual value.
I can't do any server side operation, I have to achieve this using javascript/jquery. I have also tried using jquery:
function getColData(tableID,colIndex) {
var colArray = $('#' + tableID + ' td:nth-child'+'('+colIndex+')').map(function(){
return $(this).text();
}).get();
return colArray
}
it returns data correctly but only which is visible on active page and i want all the data.
Based on your file on JSFiddle I have modified the JS part as follows, this will get you the text on every td(i.e. text or text content) and not the values of their attributes. Basically this traverses through the DOM searching for tags embedded in ones - except for those on the table header - then obtains the text value.
var table = $('#table'), button = $('#button');
button.click(function() {
var data = [];
table.find('tr:not(:first)').each(function(i, row) {
var cols = [];
$(this).find('td').each(function(i, col) {
cols.push($(this).text());
});
data.push(cols);
});
alert(data);
});
You can see it in action here
UPDATE:
This will get you all data regardless of pagination, also it will strip tags and nested tags.
var table = $('#table'), button = $('#button');
button.click(function() {
var messedData = table.bootstrapTable('getData');
var data = [];
$.each(messedData, function(i, row) {
var rowData = {
'name': row['0'],
'star': row['1'],
'forks': row['2'],
'desc': row['3'],
}
for (prop in rowData) {
var tmp = document.createElement("div");
tmp.innerHTML = rowData[prop];
rowData[prop] = tmp.textContent || tmp.innerText || "";
}
data.push(rowData);
});
console.log(data);
});
You can see it here
Since the actual data is coming in as a string, I don't think bootstrap-table can't differentiate it from the other data. The simple solution I can think of is to use substring() to extract the data from the cells that contain custom html.
http://jsfiddle.net/vwg5Lefz/
The alternative is to go through the generated table <td> and use text() to get the text data from the cells.
http://jsfiddle.net/n0djy60v/

Export HTML table from an iframe to CSV

I'm trying to look for a script (with no progess) that could export an HTML table that I am able to get from an iframe. The table is inside the iframe and I can get and display its contents on my parent document.
<script type="text/javascript">
function myFunction() {
var myIFrame = document.getElementById("myIframe");
var content = myIFrame.contentWindow.document.getElementById("table").innerHTML;
alert(content);
// suggestions here to export the table to CSV
}
</script>
I am not asking you to write the code for me. I would appreciate if someone could point me to the right direction.
I made a simple jsfiddle to illustrate the idea. https://jsfiddle.net/anjvsqt7/9/
The code snippet from the example I made is below:
var csvStr = '';
var table = $('#table');
var rows = table.children('tbody').children('tr');
var len = rows.length;
for(var i=0;i<len;i++) {
var row = $(rows[i]);
var cols = row.children('td');
for(var j=0;j<cols.length;j++) {
col = cols[j];
csvStr += col.innerText + ',';
}
csvStr += '\n';
}
//console.log(csvStr);
I have used datatables to do this in the past.
It gives you options to display buttons that can be used to export to CSV, Excel and PDF as well as exporting to your clipboard.
Example page

Categories