问题
I have the below table,
<table id="dtBasicExample" class="table table-bordered" style="border : none;">
<thead class="text-info" style="border : none;">
<tr>
<th colspan="16" style="border : none;"></th>
</tr>
<tr>
<th colspan="2" class="text-right" style="border : none;">Date</th>
<th colspan="14" style="border : none;">: <%=dstart%> - <%=dend%></th>
</tr>
<tr>
<th colspan="2" class="text-right" style="border:none;">Personel</th>
<th colspan="14" style="border : none;">: <%=pers%></th>
</tr>
<tr>
<th colspan="2" class="text-right" style="border:none;">Grade</th>
<th colspan="14" style="border : none;">: <%=grade%></th>
</tr>
<tr>
<th colspan="2" class="text-right" style="border:none;">Date Generated</th>
<th colspan="14" style="border : none;">: <%=nowdate %></th>
</tr>
<tr>
<th colspan="16" style="border-left : none; border-right: none;"/>
</tr>
<tr class="text-center">
<th rowspan="3">Date</th>
<th colspan="14">Number of Students</th>
<th rowspan="3">Grand Total</th>
</tr>
<tr class="text-center">
<th colspan="7">Class A</th>
<th colspan="7">Class B</th>
</tr>
<tr class="text-center">
<th style="width:6.2%;">Eng</th>
<th style="width:6.2%;">BM</th>
<th style="width:6.2%;">Man</th>
<th style="width:6.2%;">SC</th>
<th style="width:6.2%;">PHY</th>
<th style="width:6.2%;">CHE</th>
<th style="width:6.2%;">Sum</th>
<th style="width:6.2%;">Eng</th>
<th style="width:6.2%;">BM</th>
<th style="width:6.2%;">Man</th>
<th style="width:6.2%;">SC</th>
<th style="width:6.2%;">PHY</th>
<th style="width:6.2%;">CHE</th>
<th style="width:6.2%;">Sum</th>
</tr>
</thead>
...
Below is my js for my PDF exporting.
{
action: function (e, dt, button, config) {
showNotification('top', 'right', 'PDF exported sucessfully!');
$.fn.dataTable.ext.buttons.pdfHtml5.action.call(this, e, dt, button, config);
},
extend: 'pdf',
className: 'btn-info btnspaces',
text: 'Export to PDF',
filename: 'Students',
orientation: 'landscape',
pageSize: 'LEGAL',
customize: function (pdf) {
var firstHeaderRow = [];
var secondHeaderRow = [];
//11
$('#dtBasicExample').find("thead>tr:nth-child(7)>th").each(
function (index, element) {
var colSpan = element.getAttribute("colspan");
var rowSpan = element.getAttribute("rowspan");
firstHeaderRow.push({
text: element.innerHTML,
style: "tableHeader",
colSpan: colSpan,
rowSpan: rowSpan
});
for (var i = 0; i < colSpan - 1; i++) {
firstHeaderRow.push({});
}
});
//10
$('#dtBasicExample').find("thead>tr:nth-child(8)>th").each(
function (index, element) {
var colSpan = element.getAttribute("colspan");
var rowSpan = element.getAttribute("rowspan");
secondHeaderRow.push({
text: element.innerHTML,
style: "tableHeader",
colSpan: colSpan,
rowSpan: rowSpan
});
for (var i = 0; i < colSpan - 1; i++) {
secondHeaderRow.push({});
}
});
pdf.content[1].table.headerRows = 3;
var objLayout = {};
objLayout['hLineWidth'] = function (i) {
return .5;
};
objLayout['vLineWidth'] = function (i) {
return .5;
};
objLayout['hLineColor'] = function (i) {
return 'black';
};
objLayout['vLineColor'] = function (i) {
return 'black';
};
objLayout['paddingTop'] = function (i) {
return 5;
};
objLayout['paddingBottom'] = function (i) {
return 5;
};
objLayout['paddingLeft'] = function (i) {
return 9;
};
objLayout['paddingRight'] = function (i) {
return 9;
};
pdf.content[1].table.body.unshift(secondHeaderRow);
pdf.content[1].table.body.unshift(firstHeaderRow);
pdf.content[1].layout = objLayout;
}
I have no issue exporting this to excel, but when I try to export it to PDF, it is giving the error
uncaught malformed table row a cell is undefined
I tried to remove the colspan and manually add in <td></td>
into the tables up to 16 cols, it works fine, but the date and grand total are in the last column instead of spanning throughout the 3 columns.
回答1:
To export the pdf header with colSpan
, and rowSpan
, empty cell should be padded for cell covered by span. The following code snippet will pad empty cell base on the colSpan
and rowSpan
of the head row(<th>).
Due to Download in Sandboxed Iframes (removed), the button in the code snippet will not work, you may copy the following code to an html file, and open the file with a browser to see the effect.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/jszip-2.5.0/dt-1.10.21/b-1.6.2/b-flash-1.6.2/b-html5-1.6.2/b-print-1.6.2/datatables.min.css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/jszip-2.5.0/dt-1.10.21/b-1.6.2/b-flash-1.6.2/b-html5-1.6.2/b-print-1.6.2/datatables.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#dataTable').DataTable({
dom: 'Bfrtip',
buttons: [{
extend: 'pdf',
download: 'download',
text: 'Export to PDF',
filename: 'Students',
orientation: 'landscape',
pageSize: 'LEGAL',
customize: function(pdfDocument) {
let headerRows = [];
let noOfColumn = 16;
let rowSpansOfColumns = [];
for (let i = 0; i < noOfColumn; i++) {
rowSpansOfColumns.push([]);
}
let noOfExtraHeaderRow = 3;
pdfDocument.content[1].table.headerRows = noOfExtraHeaderRow + 1;
for (let i = 1; i <= noOfExtraHeaderRow; i++) {
let headerRow = [];
let colIdx = 0;
while (colIdx < rowSpansOfColumns.length && rowSpansOfColumns[colIdx].includes(i)) {
headerRow.push({});
colIdx++
}
$('#dataTable').find("thead>tr:nth-child(" + i + ")>th").each(
function(index, element) {
let colSpan = parseInt(element.getAttribute("colSpan"));
let rowSpan = parseInt(element.getAttribute("rowSpan"));
if (rowSpan > 1) {
for (let col = colIdx; col < colIdx + colSpan; col++) {
for (let row = i + 1; row < i + rowSpan; row++) {
rowSpansOfColumns[col].push(row);
}
}
}
headerRow.push({
text: element.innerHTML,
style: "tableHeader",
colSpan: colSpan,
rowSpan: rowSpan
});
colIdx++
for (let j = 0; j < colSpan - 1; j++) {
headerRow.push({});
colIdx++
}
while (colIdx < rowSpansOfColumns.length && rowSpansOfColumns[colIdx].includes(i)) {
headerRow.push({});
colIdx++
}
});
headerRows.push(headerRow);
}
for (let i = 0; i < headerRows.length; i++) {
pdfDocument.content[1].table.body.unshift(headerRows[headerRows.length - 1 - i]);
}
}
}]
});
});
</script>
<table id="dataTable" cellspacing="0" width="auto">
<thead>
<tr>
<th colspan="16" style="border-left : none; border-right: none;"></th>
</tr>
<tr class="text-center">
<th rowspan="3">Date</th>
<th colspan="14">Number of Students</th>
<th rowspan="3">Grand Total</th>
</tr>
<tr class="text-center">
<th colspan="7">Class A</th>
<th colspan="7">Class B</th>
</tr>
<tr class="text-center">
<th style="width:6.2%;">Eng</th>
<th style="width:6.2%;">BM</th>
<th style="width:6.2%;">Man</th>
<th style="width:6.2%;">SC</th>
<th style="width:6.2%;">PHY</th>
<th style="width:6.2%;">CHE</th>
<th style="width:6.2%;">Sum</th>
<th style="width:6.2%;">Eng</th>
<th style="width:6.2%;">BM</th>
<th style="width:6.2%;">Man</th>
<th style="width:6.2%;">SC</th>
<th style="width:6.2%;">PHY</th>
<th style="width:6.2%;">CHE</th>
<th style="width:6.2%;">Sum</th>
</tr>
</thead>
<tbody>
<tr>
<td>2020/10/11</td>
<td>50</td>
<td>60</td>
<td>70</td>
<td>80</td>
<td>90</td>
<td>85</td>
<td>25</td>
<td>50</td>
<td>60</td>
<td>70</td>
<td>80</td>
<td>90</td>
<td>85</td>
<td>25</td>
<td>100</td>
</tr>
<tr>
<td>2020/11/11</td>
<td>53</td>
<td>63</td>
<td>73</td>
<td>83</td>
<td>93</td>
<td>83</td>
<td>23</td>
<td>53</td>
<td>63</td>
<td>73</td>
<td>83</td>
<td>93</td>
<td>83</td>
<td>26</td>
<td>100</td>
</tr>
</tbody>
</table>
Image of exported report
References:
pdfmake documentation
pdfmake playground
来源:https://stackoverflow.com/questions/64762639/datatables-uncaught-malformed-table-row-a-cell-is-undefined-when-trying-to-exp