Datatables - uncaught malformed table row a cell is undefined when trying to export to PDF

人盡茶涼 提交于 2021-01-29 13:49:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!