Copy a HTML table to a Word file - overwrite error - javascript

I'm trying to copy a HTML table to a Word file.
In the first all the first column copied just fine to the word table.
When the code starts to copy the second column it is overwrite the first one.
I change the index of the column --> Cell(i,0)/Cell(i,1).
Any idea why it happen?
<script>
function tab()
{
var NUMBER_OF_ROWS = 22;
var NUMBER_OF_COLUMNS = 2;
var objWord = new ActiveXObject("Word.Application");
objWord.Visible = True
Set objDoc = objWord.Documents.Add();
var objRange = objDoc.Range();
objDoc.Tables.Add (objRange, NUMBER_OF_ROWS, NUMBER_OF_COLUMNS);
var objTable = objDoc.Tables(1);
var thisTable = $(' .ms-table');
for (var i=0;i<thisTable.rows.length;i++)
{
var oCell = thisTable.rows.item(i).cells;
objTable.Cell(i,0).Range.Text = oCell.item(0).innerText;
}
for (var i=0;i<thisTable.rows.length;i++)
{
var oCell = thisTable.rows.item(i).cells;
objTable.Cell(i,1).Range.Text = oCell.item(1).innerText;
}
objTable.AutoFormat(9)
}
</script>

Please see if the below JavaScript code is helpful:
JavaScript :
if (typeof jQuery !== "undefined" && typeof saveAs !== "undefined") {
(function($) {
$.fn.wordExport = function(fileName) {
fileName = typeof fileName !== 'undefined' ? fileName : "jQuery-Word-Export";
var static = {
mhtml: {
top: "Mime-Version: 1.0\nContent-Base: " + location.href + "\nContent-Type: Multipart/related; boundary=\"NEXT.ITEM-BOUNDARY\";type=\"text/html\"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset=\"utf-8\"\nContent-Location: " + location.href + "\n\n<!DOCTYPE html>\n<html>\n_html_</html>",
head: "<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<style>\n_styles_\n</style>\n</head>\n",
body: "<body>_body_</body>"
}
};
var options = {
maxWidth: 624
};
// Clone selected element before manipulating it
var markup = $(this).clone();
// Remove hidden elements from the output
markup.each(function() {
var self = $(this);
if (self.is(':hidden'))
self.remove();
});
// Embed all images using Data URLs
var images = Array();
var img = markup.find('img');
for (var i = 0; i < img.length; i++) {
// Calculate dimensions of output image
var w = Math.min(img[i].width, options.maxWidth);
var h = img[i].height * (w / img[i].width);
// Create canvas for converting image to data URL
var canvas = document.createElement("CANVAS");
canvas.width = w;
canvas.height = h;
// Draw image to canvas
var context = canvas.getContext('2d');
context.drawImage(img[i], 0, 0, w, h);
// Get data URL encoding of image
var uri = canvas.toDataURL("image/png");
$(img[i]).attr("src", img[i].src);
img[i].width = w;
img[i].height = h;
// Save encoded image to array
images[i] = {
type: uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")),
encoding: uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")),
location: $(img[i]).attr("src"),
data: uri.substring(uri.indexOf(",") + 1)
};
}
// Prepare bottom of mhtml file with image data
var mhtmlBottom = "\n";
for (var i = 0; i < images.length; i++) {
mhtmlBottom += "--NEXT.ITEM-BOUNDARY\n";
mhtmlBottom += "Content-Location: " + images[i].location + "\n";
mhtmlBottom += "Content-Type: " + images[i].type + "\n";
mhtmlBottom += "Content-Transfer-Encoding: " + images[i].encoding + "\n\n";
mhtmlBottom += images[i].data + "\n\n";
}
mhtmlBottom += "--NEXT.ITEM-BOUNDARY--";
//TODO: load css from included stylesheet
var styles = "";
// Aggregate parts of the file together
var fileContent = static.mhtml.top.replace("_html_", static.mhtml.head.replace("_styles_", styles) + static.mhtml.body.replace("_body_", markup.html())) + mhtmlBottom;
// Create a Blob with the file contents
var blob = new Blob([fileContent], {
type: "application/msword;charset=utf-8"
});
saveAs(blob, fileName + ".doc");
};
})(jQuery);
} else {
if (typeof jQuery === "undefined") {
console.error("jQuery Word Export: missing dependency (jQuery)");
}
if (typeof saveAs === "undefined") {
console.error("jQuery Word Export: missing dependency (FileSaver.js)");
}
}
$("a.jquery-word-export").click(function(event) {
$("#page-content").wordExport();
});
Html:
<table class="ms-table">
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td>Italy</td>
</tr>
</table>
<button>tab</button>
<div class="col-xs-5">
<a class="btn jquery-word-export" href="javascript:void(0)">
<span class="word-icon">W</span>
Export as .doc
</a>
</div>
Supporting Js files:
https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js

Related

Datatables ExcelHTMl5 export add Page-Header and Page-Footer

How can I add page_header and page_footer sections in the exported excel file from datatables so that the header and footer will be in each page while printing the document?
Current Printing view of the exported excel without page_header, page_footer:
Printing view I want with page_header, page_footer:
Here is my sample code:
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.23/css/jquery.dataTables.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.6.5/css/buttons.dataTables.css"/>
</head>
<body>
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start<br />date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger<br />Nixon</td>
<td>System<br />Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>Garrett<br />Winters</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>63</td>
<td>2011/07/25</td>
<td>$170,750</td>
</tr>
<tr>
<td>Ashton<br />Cox</td>
<td>Junior<br />Technical<br />Author</td>
<td>San<br />Francisco</td>
<td>66</td>
<td>2009/01/12</td>
<td>$86,000</td>
</tr>
<tr>
<td>Cedric<br />Kelly</td>
<td>Senior<br />Javascript<br />Developer</td>
<td>Edinburgh</td>
<td>22</td>
<td>2012/03/29</td>
<td>$433,060</td>
</tr>
<tr>
<td>Airi<br />Satou</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>33</td>
<td>2008/11/28</td>
<td>$162,700</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start<br />date</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/2.5.0/jszip.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.6.5/js/dataTables.buttons.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.6.5/js/buttons.html5.js"></script>
<script>
$(document).ready(function() {
$('#example').DataTable({
dom: "Bftrip",
buttons: [
{
extend: 'excelHtml5',
messageTop : 'Employee List',
footer: true,
exportOptions: {
format: {
header: function ( data, row, column, node ) {
return data.replace(/<br\s*\/?>/ig, "\r\n");
},
body: function ( data, row, column, node ) {
return data.replace(/<br\s*\/?>/ig, "\r\n");
},
footer: function ( data, row, column, node ) {
return data.replace(/<br\s*\/?>/ig, "\r\n");
}
},
},
customize: function(xlsx) {
var sheet = xlsx.xl.worksheets['sheet1.xml'];
var sSh = xlsx.xl['styles.xml'];
var lastXfIndex = $('cellXfs xf', sSh).length - 1;
var newStyleNumber = lastXfIndex + 1;
var newStyleNumber2 = lastXfIndex + 2;
var currentDoc = "";
var currentStyle;
var s1 = '<xf numFmtId="0" fontId="0" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1"><alignment vertical="center" horizontal="center" wrapText="1"/></xf>';
var s2 = '<xf numFmtId="0" fontId="2" fillId="0" borderId="0" applyFont="1" applyFill="1" applyBorder="1" xfId="0" applyAlignment="1"><alignment vertical="center" horizontal="center" wrapText="1"/></xf>';
sSh.childNodes[0].childNodes[5].innerHTML += s1+ s2;
var rowCount = document.getElementById("example").rows.length + 1;
for(var i=0; i<3; i++) {
$('row:eq(' + i + ') c*', sheet).attr('s', newStyleNumber2);
}
for(var i=3; i<rowCount; i++) {
$('row:eq(' + i + ') c*', sheet).attr('s', newStyleNumber);
}
$('row:eq(' + i + ') c*', sheet).attr('s', newStyleNumber2);
var col = $('col', sheet);
$(col[0]).attr('width', 15);
$(col[1]).attr('width', 15);
$(col[2]).attr('width', 10);
$(col[3]).attr('width', 5);
$(col[4]).attr('width', 12);
$(col[5]).attr('width', 12);
}
}
]
});
});
</script>
</body>
</html>
With this code, you can create a header and footer page.
"buttons": [
{
extend: 'excelHtml5',
text: 'Excel',
customize: function( xlsx ) {
var sheet = xlsx.xl.worksheets['sheet1.xml'];
// Get reference to the worksheet and parse it to xml nodes
// Has to be done this way to avoid creation of namespace atributes.
var afSerializer = new XMLSerializer();
var xmlString = afSerializer.serializeToString(sheet);
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlString,'text/xml');
//Create header and add it to the worksheet
var headerFooter = xmlDoc.createElementNS('http://schemas.openxmlformats.org/spreadsheetml/2006/main','headerFooter');
sheet.getElementsByTagName('worksheet')[0].appendChild(headerFooter);
var nodeHeaderFooter = sheet.getElementsByTagName("headerFooter");
//Creation of the header
var oddHeader = xmlDoc.createElementNS('http://schemas.openxmlformats.org/spreadsheetml/2006/main','oddHeader');
nodeHeaderFooter[0].appendChild(oddHeader);
var nodeOddHeader = sheet.getElementsByTagName("oddHeader");
//The header/footer column definitions
// If unwanted, you can skip a column
//&L = Left column
//&F = Filename
//&A = sheetname
//&C = Center column
//&D = Date
//&T = Time
//&R = Right Column
//&P = Pagenumber
//&N = Total number of pages
var txtHeader = "&L"+"&F - &A"+"&R"+"&D - &T";
var nodeHeader = xmlDoc.createTextNode(txtHeader);
nodeOddHeader[0].appendChild(nodeHeader);
//Creation of the footer
var oddFooter = xmlDoc.createElementNS('http://schemas.openxmlformats.org/spreadsheetml/2006/main','oddFooter');
nodeHeaderFooter[0].appendChild(oddFooter);
var nodeOddFooter = sheet.getElementsByTagName("oddFooter");
var txtFooter = "&R"+"Page &P of &N";
var nodeFooter = xmlDoc.createTextNode(txtFooter);
nodeOddFooter[0].appendChild(nodeFooter);
//Add header and footer to the worksheet
sheet.getElementsByTagName('worksheet')[0].appendChild(headerFooter);
}
}
]
I found the solution at this link https://codepen.io/RedJokingInn/pen/yMqezX

Exporting to Excel with Color, Style

I have two scripts, one successfully exports to xlsx with color and style for the rows and columns with both class and in line css. I have a more sophisticated script that exports multiple sheets, that I want to apply style to. This second one is not working though. I have a feeling the issue lies in the javascript, particularly the template portions, I cant see what would be the difference otherwise. Here is the one that works:
<script src="https://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script type="text/javascript">
var tableToExcel = (function () {
// Define your style class template.
var style = "<style>.green { background-color: green; }</style>";
var uri = 'data:application/vnd.ms-excel;base64,'
, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->' + style + '</head><body><table>{table}</table></body></html>'
, base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)))
}
, format = function (s, c) {
return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; })
}
return function (table, name) {
if (!table.nodeType) table = document.getElementById(table)
var ctx = { worksheet: name || 'Worksheet', table: table.innerHTML }
window.location.href = uri + base64(format(template, ctx))
}
})()
</script>
<style type="text/css">
.green
{
background-color: green;
}
</style>
<input type="button" onclick="tableToExcel('testTable', 'W3C Example Table', 'testTable2', 'This is a test')" value="Export to Excel" />
<table id="testTable" summary="Code page support in different versions of MS Windows."
rules="groups" frame="hsides" border="2">
<caption>
CODE-PAGE SUPPORT IN MICROSOFT WINDOWS
</caption>
<colgroup align="center"></colgroup>
<colgroup align="left"></colgroup>
<colgroup span="2" align="center"></colgroup>
<colgroup span="3" align="center"></colgroup>
<thead valign="top">
<tr>
<th>Code-Page<br />ID</th>
<th>Name</th>
<th>ACP</th>
<th>OEMCP</th>
<th>Windows<br />NT 3.1</th>
<th>Windows<br />NT 3.51</th>
<th>Windows<br />95</th>
</tr>
</thead>
<tbody>
<tr>
<td>1200</td>
<td style="background-color: #00f; color: #fff">Unicode (BMP of ISO/IEC-10646)</td>
<td></td>
<td></td>
<td>X</td>
<td>X</td>
<td>*</td>
</tr>
Here is the script for the one that doesnt, no errors, just wont publish the styles on the same html elements:
Head:
<script>
var tablesToExcel = (function() {
var style = "<style>.green { background-color: green; }</style>";
var uri = 'data:application/vnd.ms-excel;base64,'
, tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Seecuring</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }
return function(tables, wsnames, wbname, appname) {
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
for (var i = 0; i < tables.length; i++) {
if (!tables[i].nodeType) tables[i] = document.getElementById(tables[i]);
for (var j = 0; j < tables[i].rows.length; j++) {
rowsXML += '<Row>'
for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
dataValue = (dataValue)?dataValue:tables[i].rows[j].cells[k].innerHTML;
var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
dataFormula = (dataFormula)?dataFormula:(appname=='Calc' && dataType=='DateTime')?dataValue:null;
ctx = { attributeStyleID: (dataStyle=='Currency' || dataStyle=='Date')?' ss:StyleID="'+dataStyle+'"':''
, nameType: (dataType=='Number' || dataType=='DateTime' || dataType=='Boolean' || dataType=='Error')?dataType:'String'
, data: (dataFormula)?'':dataValue
, attributeFormula: (dataFormula)?' ss:Formula="'+dataFormula+'"':''
};
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>'
}
ctx = {rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i};
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
}
ctx = {created: (new Date()).getTime(), worksheets: worksheetsXML};
workbookXML = format(tmplWorkbookXML, ctx);
console.log(workbookXML);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = wbname || 'Oracle Cloud Snapshot Management.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})();
</script>
<style type="text/css">
.green
{
background-color: #0F51F6;
}
</style>
</head>
The html:
<table id="intro" class="table2excel" rules="groups" frame="hsides" border="2">
<tr>
<td><!--<img src='<?php //echo $environment; ?>/access/images/erpra.png' width='100px' height='100px'> --></td>
</tr>
<tr>
<td class="green">KPMG - Oracle Cloud ERP/HCM Configuration Management Assessment
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td style="background-color: #00f; color: #fff">A review of key Configuration elements within the Oracle Cloud Applications/Fusion suite. <?php if(!isset($_POST['no_date'])&& $_POST['no_date']== "Y"){
$CREATION_DATE_POST_DISPLAY_RAW = $_POST['creation_from'];
$CREATION_DATE_DISPLAY=date("m/d/Y",strtotime($CREATION_DATE_POST_DISPLAY_RAW));
$LAST_UPDATE_DATE_POST_DISPLAY_RAW = $_POST['update_from'];
$LAST_UPDATE_DATE_DISPLAY=date("m/d/Y",strtotime($LAST_UPDATE_DATE_POST_DISPLAY_RAW));
echo "Creation Date from : $CREATION_DATE_DISPLAY, Last Updated Date from: $LAST_UPDATE_DATE_DISPLAY";
}
?></td>
Thanks for reading!
<div>
<style>
#media all {
.page-break {
display: none;
}
}
#media print {
.page-break {
display: block;
page-break-inside: auto;
}
}
</style>
</div>

Multiple countdown timers comparing a given time and current time?

Really struggling with this part for some reason.
I'm creating a timer I can use to keep track of bids. I want to be able to compare two times and have the difference (in minutes and seconds) shown in the countdown column. It should be comparing the bid start time and the time right now.
Perhaps when it reaches bid start it could also change to show how long until bid ends. Eventually I want to add background changes once it's getting close to the time, and perhaps the ablility to set alarms with a prompt window.
Here's the code I have so far:
HTML
<table>
<tr>
<td>Item Name</td>
<td><input id="itemNameField" placeholder="" type="text"></td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>Time of Notice</td>
<td><input id="noticeField" type="time"></td>
</tr>
</table>
<input id="addButton" onclick="insRow()" type="button" value="Add Timer">
<div id="errorMessage"></div>
<hr>
<div id="marketTimerTableDiv">
<table border="1" id="marketTimerTable">
<tr>
<td></td>
<td>Item Name</td>
<td>Time of Notice</td>
<td>Bid Start</td>
<td>Bid End</td>
<td>Countdown</td>
<td></td>
</tr>
<tr>
<td></td>
<td>
<div id="itembox"></div>Example Item
</td>
<td>
<div id="noticebox"></div>12:52
</td>
<td>
<div id="bidstartbox"></div>13:02
</td>
<td>
<div id="bidendbox"></div>13:07
</td>
<td>
<div id="countdownbox"></div>
</td>
<td><input id="delbutton" onclick="deleteRow(this)" type="button" value="X"></td>
</tr>
</table>
</div>
JAVASCRIPT
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex;
if (i == 1) {
console.log = "hi";
} else {
document.getElementById('marketTimerTable').deleteRow(i);
}
}
function insRow() {
if (itemNameField.value == "" || noticeField.value == "") {
var div = document.getElementById('errorMessage');
div.innerHTML = "*Please fill in the fields*";
div.style.color = 'red';
document.body.appendChild(div);
} else {
var div = document.getElementById('errorMessage');
div.innerHTML = "";
var x = document.getElementById('marketTimerTable');
var new_row = x.rows[1].cloneNode(true);
var len = x.rows.length;
var inp1 = new_row.cells[1].getElementsByTagName('div')[0];
inp1.id += len;
inp1.innerHTML = itemNameField.value;
itemNameField.value = "";
var inp2 = new_row.cells[2].getElementsByTagName('div')[0];
inp2.id += len;
inp2.innerHTML = noticeField.value;
noticeField.stepUp(10);
var inp3 = new_row.cells[3].getElementsByTagName('div')[0];
inp3.id += len;
inp3.innerHTML = noticeField.value;
noticeField.stepUp(5);
var inp4 = new_row.cells[4].getElementsByTagName('div')[0];
inp4.id += len;
inp4.innerHTML = noticeField.value;
var inp5 = new_row.cells[5].getElementsByTagName('div')[0];
inp5.id += len;
inp5.innerHTML = "";
noticeField.value = "";
x.appendChild(new_row);
}
}
I apologize in advance because my code is probably really messy and badly formatted. Here's a JSFIDDLE as well! Thanks :)
To calculate the difference between the current and given time, you can use setInterval
Example :
var noticeTime = noticeField.value.split(":");
const interval = setInterval(function(){
var currentDate = (new Date());
var diffInHours = currentDate.getHours() - noticeTime[0];
var diffInMinutes = currentDate.getMinutes() - noticeTime[1];
inp5.innerHTML = diffInHours + ":" + diffInMinutes;
if(diffInHours === 0 && diffInMinutes === 0) {
clearInterval(interval);
}
},1000)
I managed to do it with the help of the code from ProgXx.
I added the following code:
var noticeTime = noticeField.value.split(":");
var originalTime = noticeField.value.split(":");
const interval = setInterval(function(){
var currentDate = (new Date());
noticeTime[1] = originalTime[1] - currentDate.getMinutes() + 10;
noticeTime[1] = noticeTime[1] + (originalTime[0] * 60) - (currentDate.getHours() * 60);
Here's a JSFIDDLE of the finihsed code: http://jsfiddle.net/joefj8wb/

How to export data from table to csv file using jquery

I'm trying to export from a data table into a CSV file. Here is my whole function. It downloads a file, but it shows the whole code for the table and not separating any of the data out. When I say whole code I mean everything within 'table /table'
function displayDataTable(index){
$("#pageOverlay").empty();
html = "<div id='volumeChartDiv'><h4>Data Table</h4><table id='dataTable' class='table table-bordered table-striped dataTable' role='grid'><thead><tr role='row'><th>header1</th><th>header2</th><th>header3</th></tr></thead><tbody><tr><td>cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr><tr><td>bell2-1</td><td>bell2-2</td><td>bell2-3</td></tr><tr><td>fell3-1</td><td>fell3-2</td><td>fell3-3</td></tr></tbody></table><input type='button' value='Close' onclick='closeOverlay()'> <input type='button' id='exportDataTable' value='Export Table'></div>";
$("#pageOverlay").html(html);
// export data function
$("#exportDataTable").click(function (e) {
window.open('data:application/vnd.ms-excel,' + $('.dataTable').html());
e.preventDefault();
});
openOverlay();
}
CSV format cannot accept $('.dataTable').html() as .html() is not a structured data, it's not even data, just a silly hmtl.
You have to get data from your table, make a string representing CSV format, and download it, As you don't show your table data structure here's working demo below
$('#export').click(function() {
var titles = [];
var data = [];
/*
* Get the table headers, this will be CSV headers
* The count of headers will be CSV string separator
*/
$('.dataTable th').each(function() {
titles.push($(this).text());
});
/*
* Get the actual data, this will contain all the data, in 1 array
*/
$('.dataTable td').each(function() {
data.push($(this).text());
});
/*
* Convert our data to CSV string
*/
var CSVString = prepCSVRow(titles, titles.length, '');
CSVString = prepCSVRow(data, titles.length, CSVString);
/*
* Make CSV downloadable
*/
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", CSVString]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "data.csv";
/*
* Actually download CSV
*/
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
});
/*
* Convert data array to CSV string
* #param arr {Array} - the actual data
* #param columnCount {Number} - the amount to split the data into columns
* #param initial {String} - initial string to append to CSV string
* return {String} - ready CSV string
*/
function prepCSVRow(arr, columnCount, initial) {
var row = ''; // this will hold data
var delimeter = ','; // data slice separator, in excel it's `;`, in usual CSv it's `,`
var newLine = '\r\n'; // newline separator for CSV row
/*
* Convert [1,2,3,4] into [[1,2], [3,4]] while count is 2
* #param _arr {Array} - the actual array to split
* #param _count {Number} - the amount to split
* return {Array} - splitted array
*/
function splitArray(_arr, _count) {
var splitted = [];
var result = [];
_arr.forEach(function(item, idx) {
if ((idx + 1) % _count === 0) {
splitted.push(item);
result.push(splitted);
splitted = [];
} else {
splitted.push(item);
}
});
return result;
}
var plainArr = splitArray(arr, columnCount);
// don't know how to explain this
// you just have to like follow the code
// and you understand, it's pretty simple
// it converts `['a', 'b', 'c']` to `a,b,c` string
plainArr.forEach(function(arrItem) {
arrItem.forEach(function(item, idx) {
row += item + ((idx + 1) === arrItem.length ? '' : delimeter);
});
row += newLine;
});
return initial + row;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="export">export</button>
<table class="dataTable">
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td>Italy</td>
</tr>
</table>
If you find any bugs, comment below, i'll fix them
An small improvement over Medet answer, assuming that you headers are in tr, all this code does is get all the columns and rows push that in plain array and exports to csv.
$('#export').click(function() {
var titles = [];
var data = [];
$('.table tr').each(function() {
data.push($(this));
});
csv_data = []
data.forEach(function(item,index){
td = item[0].children
for(i=0;i<td.length;i++){
csv_data.push(td[i].innerText)
}
csv_data.push('\r\n')
})
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", csv_data]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "minicrawl.csv";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
})
If the data's not too complicated, then you can get by without jQuery:
const csvContents = [].map.call(document.getElementById('dataTable').rows,
tr => [].map.call(tr.cells, td => td.textContent).join(',')
).join('\n'))
and then download the file as with the other answers.
This won't work if the data's a bit more complicated (eg, has commas in the data), but in that case you should probably use a csv library in the first place.

Iterate over table cells, re-using rowspan values

I have a simple HTML table, which uses rowspans in some random columns. An example might look like
A | B |
---|---| C
D | |
---| E |---
F | | G
I'd like to iterate over the rows such that I see rows as A,B,C, D,E,C, then F,E,G.
I think I can probably cobble together something very convoluted using cell.index() to check for "missed" columns in later rows, but I'd like something a little more elegant...
without jquery:
function tableToMatrix(table) {
var M = [];
for (var i = 0; i < table.rows.length; i++) {
var tr = table.rows[i];
M[i] = [];
for (var j = 0, k = 0; j < M[0].length || k < tr.cells.length;) {
var c = (M[i-1]||[])[j];
// first check if there's a continuing cell above with rowSpan
if (c && c.parentNode.rowIndex + c.rowSpan > i) {
M[i].push(...Array.from({length: c.colSpan}, () => c))
j += c.colSpan;
} else if (tr.cells[k]) {
var td = tr.cells[k++];
M[i].push(...Array.from({length: td.colSpan}, () => td));
j += td.colSpan;
}
}
}
return M;
}
var M = tableToMatrix(document.querySelector('table'));
console.table(M.map(r => r.map(c => c.innerText)));
var pre = document.createElement('pre');
pre.innerText = M.map(row => row.map(c => c.innerText).join('\t')).join('\n');
document.body.append(pre);
td {
border: 1px solid rgba(0,0,0,.3);
}
<table>
<tr>
<td colspan=2>A</td>
<td rowspan=2>B</td>
</tr>
<tr>
<td>C</td>
<td rowspan=3>D</td>
</tr>
<tr>
<td rowspan=2>E</td>
<td rowspan=4>F</td>
</tr>
<tr></tr>
<tr>
<td rowspan=2 colspan=2>G</td>
</tr>
<tr></tr>
<tr>
<td rowspan=3 colspan=3>H</td>
</tr>
<tr></tr>
<tr></tr>
<tr>
<td colspan=3>I</td>
</tr>
</table>
Try this:
<table id="tbl">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="2" rowspan="2">A</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
Script:
var finalResult = '';
var totalTds = $('#tbl TR')[0].length;
var trArray = [];
var trArrayValue = [];
var trIndex = 1;
$('#tbl TR').each(function(){
var currentTr = $(this);
var tdIndex = 1;
trArray[trIndex] = [];
trArrayValue[trIndex] = [];
var tdActuallyTraversed = 0;
var colspanCount = 1;
$('#tbl TR').first().children().each(function(){
if(trIndex > 1 && trArray[trIndex - 1][tdIndex] > 1)
{
trArray[trIndex][tdIndex] = trArray[trIndex - 1][tdIndex] - 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex - 1][tdIndex];
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
else
{
if(colspanCount <= 1)
{
colspanCount = currentTr.children().eq(tdActuallyTraversed).attr('colspan') != undefined ? currentTr.children().eq(tdActuallyTraversed).attr('colspan') : 1;
}
if(colspanCount > 1 && tdIndex > 1)
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed + colspanCount).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = trArrayValue[trIndex][tdIndex - 1];
colspanCount--;
}
else
{
trArray[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).attr('rowspan') != undefined ?currentTr.children().eq(tdActuallyTraversed).attr('rowspan') : 1;
trArrayValue[trIndex][tdIndex] = currentTr.children().eq(tdActuallyTraversed).html();
tdActuallyTraversed++;
}
finalResult = finalResult + trArrayValue[trIndex][tdIndex];
}
tdIndex++;
});
trIndex++;
});
alert(finalResult);
Fiddle
i am not sure about the performance, but it works well.
what I understood with your question is: You want to split the merged cell with same value and then iterate the table simply by row.
I've created a JSFiddle that will split the merged cells with the same value. Then you'll have a table that can be iterated simply by rows to get the desired output that you specified.
See it running here http://jsfiddle.net/9PZQj/3/
Here's the complete code:
<table id="tbl" border = "1">
<tr>
<td>A</td>
<td>B</td>
<td rowspan="2">C</td>
</tr>
<tr>
<td>D</td>
<td rowspan="2">E</td>
</tr>
<tr>
<td>F</td>
<td>G</td>
</tr>
</table>
<br>
<div id="test"> </div>
Here's the jquery that is used to manipulate the table's data.
var tempTable = $('#tbl').clone(true);
var tableBody = $(tempTable).children();
$(tableBody).children().each(function(index , item){
var currentRow = item;
$(currentRow).children().each(function(index1, item1){
if($(item1).attr("rowspan"))
{
// copy the cell
var item2 = $(item1).clone(true);
// Remove rowspan
$(item1).removeAttr("rowspan");
$(item2).removeAttr("rowspan");
// last item's index in next row
var indexOfLastElement = $(currentRow).next().last().index();
if(indexOfLastElement <= index1)
{
$(currentRow).next().append(item2)
}
else
{
// intermediate cell insertion at right position
$(item2).insertBefore($(currentRow).next().children().eq(index1))
}
}
});
console.log(currentRow)
});
$('#test').append(tempTable);
You can use this Gist. It supports all the requirements by W3C, even "rowspan=0" (which seems to be only supported by Firefox).

Categories

Resources