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
Related
I am calling a BUS ETA api which it will return a json with ETA and route information. Example as below. I manage to get the first array to show in HTML but without success for the second [1] and third[2]. I manage to see all three ETA with console.log but won't show in HTML.
Any idea?
UPDATE : Created a jsFiddle example.
https://jsfiddle.net/21tk38b9/
BUS ETA API SAMPLE DATA
{
"type": "ETA",
"version": "1.0",
"generated_timestamp": "2021-06-29T16:02:53+08:00",
"data": [
{
"co": "KMB",
"route": "978",
"dir": "I",
"service_type": 1,
"seq": 7,
"dest_tc": "粉嶺(華明)",
"dest_sc": "粉岭(华明)",
"dest_en": "FANLING (WAH MING)",
"eta_seq": 1,
"eta": "2021-06-29T16:11:24+08:00",
"rmk_tc": "",
"rmk_sc": "",
"rmk_en": "",
"data_timestamp": "2021-06-29T16:02:41+08:00"
},
{
"co": "KMB",
"route": "978",
"dir": "I",
"service_type": 1,
"seq": 7,
"dest_tc": "粉嶺(華明)",
"dest_sc": "粉岭(华明)",
"dest_en": "FANLING (WAH MING)",
"eta_seq": 2,
"eta": "2021-06-29T16:28:15+08:00",
"rmk_tc": "原定班次",
"rmk_sc": "原定班次",
"rmk_en": "Scheduled Bus",
"data_timestamp": "2021-06-29T16:02:41+08:00"
},
{
"co": "KMB",
"route": "978",
"dir": "I",
"service_type": 1,
"seq": 7,
"dest_tc": "粉嶺(華明)",
"dest_sc": "粉岭(华明)",
"dest_en": "FANLING (WAH MING)",
"eta_seq": 3,
"eta": "2021-06-29T16:43:15+08:00",
"rmk_tc": "原定班次",
"rmk_sc": "原定班次",
"rmk_en": "Scheduled Bus",
"data_timestamp": "2021-06-29T16:02:41+08:00"
}
]
}
HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mining Status</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="/src/js/Untitled-4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="/src/css/main.css">
<link rel="stylesheet" href="/src/css/15.css">
<style type="text/css">
.fullscreen {
position: fixed;
overflow-y:fixed;
width: 100%;
}
</style>
</head>
<div id="wrap">
<body>
<div style="
font-size: 100px;
text-align: center;">
<div id="rmk"></div>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Route</th>
<th scope="col">ETA</th>
<th scope="col">Remark</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td><div id="route"></div></td>
<td><div id="but"></div>
</td>
<td></td>
</tr>
<tr>
<th scope="row">2</th>
<td></td>
<td><div id="but"></div>
<td></td>
</tr>
<tr>
<th scope="row">3</th>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</body>
</div>
</html>
Javascript
function repeat57() {
$(function() {
$.ajax({
type: "GET",
url: "https://data.etabus.gov.hk/v1/transport/kmb/eta/83B717529F9794BC/978/1",
dataType: "json",
success: function (data) {
console.log(typeof data); // -- Object
var json = data;
for (var i = 0; i < json.data.length; i++) {
var str = json.data[i].eta
if (str !== null ) {
str = str.split("T").pop();
str2 = str.split("+",1).pop();
str3 = str2.replace(/:/g,'');
d = new Date();
datetext = d.toTimeString();
datetext = datetext.split(' ')[0];
datetext = datetext.replace(/:/g,'');
console.log(datetext)
var eta = str3 - datetext;
console.log(eta)
var eta2 = "[ " + eta.toString().slice(0, -2) +" mins,]";
} else {
var remark = json.data[i].rmk_tc
eta2 = remark;
}
console.log(typeof str)
$('#but').html(eta2);
$('#rmk').html(remark);
}
}
});
});
setTimeout(repeat57, 19000);
}
repeat57();
function repeat58() {
$(function() {
$.ajax({
type: "GET",
url: "https://data.etabus.gov.hk/v1/transport/kmb/eta/83B717529F9794BC/978/1",
dataType: "json",
success: function (data) {
var json = data;
console.log(typeof .json)
for (var i = 0; i < json.data.length; i++) {
var str = JSON.parse(json.data[i].route)
if (str !== null ) {
} else {
var remark = json.data[i].rmk_tc
str = remark;
}
console.log(typeof str)
$('#route').html(str);
}
}
});
});
setTimeout(repeat58, 19000);
}
repeat58();
Do you want to be dynamic or are there always only 3 entries?
If there are three entries you could do:
HTML Code:
<head>
<meta charset="utf-8">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div id="rmk"></div>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Route</th>
<th scope="col">ETA</th>
<th scope="col">Remark</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>
<div class="route"></div>
</td>
<td>
<div class="but"></div>
</td>
<td></td>
</tr>
<tr>
<th scope="row">2</th>
<td>
<div class="route"></div>
</td>
<td>
<div class="but"></div>
</td>
<td></td>
</tr>
<tr>
<th scope="row">3</th>
<td>
<div class="route"></div>
</td>
<td>
<div class="but"></div>
</td>
<td></td>
</tr>
</tbody>
</table>
</body>
JavaScript:
function repeat57() {
$(function() {
$.ajax({
type: "GET",
url: "https://data.etabus.gov.hk/v1/transport/kmb/eta/83B717529F9794BC/978/1",
dataType: "json",
success: function(data) {
console.log(data); // -- Object
var json = data;
const buts = $('.but');
for (var i = 0; i < json.data.length; i++) {
var str = json.data[i].eta
if (str !== null) {
str = str.split("T").pop();
str2 = str.split("+", 1).pop();
str3 = str2.replace(/:/g, '');
d = new Date();
datetext = d.toTimeString();
datetext = datetext.split(' ')[0];
datetext = datetext.replace(/:/g, '');
console.log(datetext)
var eta = str3 - datetext;
var eta2 = eta.toString().slice(0, -2) + " mins";
} else {
var remark = json.data[i].rmk_tc
eta2 = remark;
}
$(buts[i]).html(eta2);
}
}
});
});
setTimeout(repeat57, 19000);
}
repeat57();
function repeat58() {
$(function() {
$.ajax({
type: "GET",
url: "https://data.etabus.gov.hk/v1/transport/kmb/eta/83B717529F9794BC/978/1",
dataType: "json",
success: function(data) {
var json = data;
console.log(json)
const routeElements = $('.route');
for (var i = 0; i < json.data.length; i++) {
var str = JSON.parse(json.data[i].route)
if (str !== null) {
} else {
var remark = json.data[i].rmk_tc
str = remark;
}
$(routeElements[i]).html(str);
}
}
});
});
setTimeout(repeat58, 19000);
}
repeat58();
Make sure to change the ids to classes (but, route, etc) and add it to all the rows where it is needed.
And when iterating through the result you pick the correct element via the index.
See the updated jsFiddle: https://jsfiddle.net/sgjx05qf/
This would be a solution if you always know the count of the result.
I am trying to put an array in a HTML table with javascript function but i dont khont how to insert this array? The idea is when i click on button Insert, it'll add one person's information into row.
This's my table
<script>
//Array
var a = [
{name:"Micheal", age:20, hometown:"New York"},
{name:"Santino", age:25, hometown:"Los Angeles"},
{name:"Fredo", age:29, hometown:"California"},
{name:"Hagen", age:28, hometown:"Long Beach"},
]
//Insert data function
function Insert_Data() {
var table = document.getElementById("myTable");
//Help......
}
</script>
<!--Button Insert-->
<input type="button" onclick="Insert_Data" value="Insert" />
<!--Table-->
<table id="myTable">
<tr>
<th>Full Name</th>
<th>Age</th>
<th>Country</th>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
You declare both thead and tbody and in function in loop fill the table
var a = [
{name:"Micheal", age:20, hometown:"New York"},
{name:"Santino", age:25, hometown:"Los Angeles"},
{name:"Fredo", age:29, hometown:"California"},
{name:"Hagen", age:28, hometown:"Long Beach"},
]
//Insert data function
function Insert_Data() {
var table = document.getElementById("datas");
table.innerHTML="";
var tr="";
a.forEach(x=>{
tr+='<tr>';
tr+='<td>'+x.name+'</td>'+'<td>'+x.age+'</td>'+'<td>'+x.hometown+'</td>'
tr+='</tr>'
})
table.innerHTML+=tr;
//Help......
}
<input type="button" onclick="Insert_Data()" value="Insert" />
<!--Table-->
<table id="myTable">
<thead>
<tr>
<th>Full Name</th>
<th>Age</th>
<th>Country</th>
</tr>
</thead>
<tbody id="datas">
</tbody>
</table>
Demo proof: https://jsfiddle.net/psw41g6k/
function Insert_Data() {
var table = document.getElementById("myTable");
var rows = table.querySelectorAll('tr');
console.log(rows)
for (let i = 1; i < rows.length; i++) {
rows[i].children[0].textContent = a[i-1].name
rows[i].children[1].textContent = a[i-1].age
rows[i].children[2].textContent = a[i-1].hometown
}
}
For dynamic tables if you gonna change your array frequently
let tableBody = a.reduce((rows, nextRow) =>{
return rows +=
'<tr>' +
Object.keys(nextRow).reduce((cols, nextCol) => {
return cols += '<th>' + nextRow[nextCol] + '</th>'
}, '') +
'</tr>'
}, '')
Create a dynamic element tr and td at the click of the button and append it to the table element in the document.
Use https://www.w3schools.com/jsref/met_node_appendchild.asp as a reference to understand how to create a dynamic element.
Here is a completely generic method, you can add a new key and it adds a new column to the data, no problem:
//Array
var myData = [
{name:"Micheal", age:20, hometown:"New York", example: "extra"},
{name:"Santino", age:25, hometown:"Los Angeles", example: "extra"},
{name:"Fredo", age:29, hometown:"California", example: "extra"},
{name:"Hagen", age:28, hometown:"Long Beach", example: "extra"},
]
//get references to the table and the head and body:
const myTable = document.getElementById('myTable');
const myTable_header = myTable.querySelector('thead')
const myTable_body = myTable.querySelector('tbody')
//Insert data function
function Insert_Data() {
//Help...... :
myTable_header.innerHTML = '';
var tr = document.createElement('tr');
const headers_data = Object.keys(myData[0]);
headers_data.forEach((key) => {
var th = document.createElement('th')
th.innerHTML = key
tr.appendChild(th);
})
myTable_header.appendChild(tr);
myTable_body.innerHTML = '';
for (let i = 0; i < myData.length; i++){
var tr = document.createElement('tr');
headers_data.forEach((key) => {
var td = document.createElement('td');
td.innerHTML = myData[i][key]
tr.appendChild(td);
});
myTable_body.appendChild(tr);
}
}
<!--Button Insert-->
<input type="button" onclick="Insert_Data()" value="Insert" />
<!--Table-->
<table id="myTable">
<thead>
<!-- Data is injected here -->
</thead>
<tbody>
<!-- Data is injected here -->
</tbody>
</table>
TableThis is my cshtml and js codes. I tried tablesorter plugin on other tables (justnormal tables with thead and tbody) and it was working. I think the problem is that there is no body inside of tbody tags because I add the body with JS and webapi , do you have any idea how can I fix it and sort this table? I am a beginner, so would appreciate any help or advice.
<head>
<script src="lib/jquery/dist/jquery.js" asp-append-version="true"></script>
<script src="js/jquery.tablesorter.min.js"></script>
<link rel="stylesheet" type="text/css" href="~/css/theme.default.css">
</head>
<h3>Branch Index</h3>
<div id="branchIndex">
<table class="table tablesorter mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp customTable" id="branchIndexTablee">
<thead>
<tr>
<th>Branch Name</th>
<th>Open Now</th>
<th>Number Of Assets</th>
<th>Number Of Patrons</th>
</tr>
</thead>
<tbody id="branchess">
</tbody>
</table>
</div>
<script>
$(document).ready(function () {
$('table').tablesorter({ sortList: [[0, 0]] });
});
</script>
js
const uri = 'api/BranchApi';
let branchess = [];
function getItems() {
fetch(uri)
.then(response => response.json())
.then(data => _displayItems(data))
.catch(error => console.error('Unable to get items.', error));
}
function _displayItems(data) {
var table = jQuery(".tablesorter");
table.tablesorter();
const tBody = document.getElementById('branchess');
tBody.innerHTML = '';
data.forEach(item => {
let tr = tBody.insertRow();
let td1 = tr.insertCell(0);
var a = document.createElement('a');
var name = document.createTextNode(item.branchName);
a.appendChild(name);
a.title = item.name;
a.href = "Branch/Detail/" + item.id;
td1.appendChild(a);
let td2 = tr.insertCell(1);
let time = document.createTextNode(item.isOpen);
td2.append(time);
let td3 = tr.insertCell(2);
let telephoneN = document.createTextNode(item.numberOfAssets);
td3.appendChild(telephoneN);
let td4 = tr.insertCell(3);
let address = document.createTextNode(item.numberOfPatrons);
td4.appendChild(address);
});
branchess = data;
}
Typo: id has been assign to wrong place:
NOW:
<tbody >
<tr>
<td id="branchess"></td>
</tr>
</tbody>
Expected:
<tbody id="branchess">
<tr>
<td ></td>
</tr>
</tbody>
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.31.3/js/jquery.tablesorter.min.js"></script>
<link rel="stylesheet" type="text/css" href="~/css/theme.default.css">
</head>
<h3>Branch Index</h3>
<div id="branchIndex">
<table
class="table tablesorter mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp customTable"
id="branchIndexTablee">
<thead>
<tr>
<th>Branch Name</th>
<th>Open Now</th>
<th>Number Of Assets</th>
<th>Number Of Patrons</th>
</tr>
</thead>
<tbody id="branchess">
<tr>
<td></td>
</tr>
</tbody>
</table>
</div>
<script>
$(document).ready(function () {
_displayItems([{
id: 1,
branchName: "Random",
isOpen: true,
numberOfAssets: 10,
numberOfPatrons: 11
},
{
id: 2,
branchName: "Lost",
isOpen: true,
numberOfAssets: 10,
numberOfPatrons: 11
},
{
id: 3,
branchName: "Found",
isOpen: false,
numberOfAssets: 10,
numberOfPatrons: 11
},
{
id: 4,
branchName: "OK",
isOpen: true,
numberOfAssets: 10,
numberOfPatrons: 11
},
])
$('table').tablesorter({
sortList: [
[0, 0]
]
});
});
function _displayItems(data) {
const tBody = document.getElementById('branchess');
tBody.innerHTML = '';
data.forEach(item => {
let tr = tBody.insertRow();
let td1 = tr.insertCell(0);
var a = document.createElement('a');
var name = document.createTextNode(item.branchName);
a.appendChild(name);
a.title = item.name;
a.href = "Branch/Detail/" + item.id;
td1.appendChild(a);
let td2 = tr.insertCell(1);
let time = document.createTextNode(item.isOpen ? 'OPEN' : 'CLOSED');
td2.append(time);
let td3 = tr.insertCell(2);
let telephoneN = document.createTextNode(item.numberOfAssets);
td3.appendChild(telephoneN);
let td4 = tr.insertCell(3);
let address = document.createTextNode(item.numberOfPatrons);
td4.appendChild(address);
});
// branchess = data;
var table = jQuery(".tablesorter");
table.tablesorter();
}
</script>
</html>
I have a JS function that writes the contents of a table on the page to a CSV file.
However, whenever I come across a table cell that has a hyperlink (e.g., <td><a href="https://www.example.com>Cell Value 1</a></td>), I need to write the href value (https://www.example.com in this case) and not the html text (Cell Value 1 in this case)
The code below shows a function that loops over rows and then columns. I have no problems creating a CSV this way, but am struggling to implement the "check" for <a href=""> values.
<script>
function downloadCSV() {
var table = document.getElementById("table-example");
// Array of rowData arrays
var results = [];
// holds data from each table row
var rowData;
//iterate through rows, skipping header
for (var i = 1, row; row = table.rows[i]; i++) {
rowData = [];
//iterate through columns
for (var j = 0, col; col = row.cells[j]; j++) {
// Checking for href and extracing link
let link = $(this).find('a').attr('href');
console.log(link);
if () {
....
}
else {
rowData.push(col.textContent);
}
}
results.push(rowData);
}
If needed, a sample table is:
<button onClick="downloadCSV()">Download CSV</button>
<table id="table-example">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
</tbody>
</table>
My goal was to implement an if-else where I would add the value of the href to the array is the table cell had one, or add the html text if not. However, the link variable is always undefined, even while iterating on a column that I know has an <a href="">.
Edit:
Following Taplar's suggestion that using $(this) in the for-loop was misguided, I came up with the following solution:
for (var j = 0, col; col = row.cells[j]; j++) {
// Checking for href and extracing link
var links = col.getElementsByTagName('a');
if (links.length > 0) {
var cellData = links[0].getAttribute('href');
} else {
var cellData = col.textContent;
}
rowData.push(cellData);
I aggree with Taplar about this.
Bellow i think is what you are looking for.
function downloadCSV() {
var table = document.getElementById("table-example");
// Array of rowData arrays
var results = [];
// holds data from each table row
var rowData;
for (var i = 1; row = table.rows[i]; i++) {
rowData = [];
//iterate through columns
for (var j = 0, col; col = row.cells[j]; j++) {
var cell = $(row.cells[j]);
var hashref = cell.find('a');
// Cause it get a collection
if (hashref.length > 0 && hashref.length === 1) {
rowData.push(hashref.attr('href'));
} else {
rowData.push(col.textContent);
}
} // end for cell
results.push(rowData);
} // end row
console.log(results);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onClick="downloadCSV()">Download CSV</button>
<table id="table-example">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
</tbody>
</table>
My solution was the following:
for (var j = 0, col; col = row.cells[j]; j++) {
// Checking for href and extracing link
var links = col.getElementsByTagName('a');
if (links.length > 0) {
var cellData = links[0].getAttribute('href');
} else {
var cellData = col.textContent;
}
rowData.push(cellData);
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