如何将多个数据表导出为 PDF,导出到单个压缩文件夹中

问题描述 投票:0回答:1

我在一个小组报告系统中有一个解决方案,我在视图中呈现了选定数量的数据表,并且我提供了每个表的下载链接,即:

let singlePDFdownload = function (table_id) {
    $(`.toolbar${table_id} .custom-pdf`).trigger('click')
}

这适用于单个下载,但我还想启用一个快速按钮,以便一次生成所有下载。我目前使用

.custom_pdf
类执行此操作,因此我可以对执行所述表的数据表导出的按钮进行分组。这是我目前使用的方式的一个问题,因为它会在浏览器中启动多次下载并弹出多个窗口(偶尔会显示警告)。

如何将这些“点击”合并为一次下载?

我能否捕获由于

trigger('click;)
而发生的下载,然后以某种方式将 PDF 合并到一个压缩文件夹中,或者如何实现?

这里是触发多次下载的代码:

const $massPDFExport = $('#massPDFExport')
$massPDFExport.on('click', () => {
    // remember all tables shown have this class
    $(`.custom-pdf`).trigger('click')
})

这是一个完全可重现的例子:

<link rel="stylesheet" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css">

<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script>


<script>
    $(document).ready(function () {
        $('#example_1').DataTable({
            dom: 'Bfrtip',
            buttons: [
                'copy', 'csv', 'excel', 'pdf', 'print'
            ]
        });
        $('#example_2').DataTable({
            dom: 'Bfrtip',
            buttons: [
                'copy', 'csv', 'excel', 'pdf', 'print'
            ]
        });
        $('#export_all').on('click', () => {
            $('.buttons-pdf').each(function (a) {
                console.log(9888)
                $(this).trigger("click");
            });
        });
    });
</script>

<a id='export_all' class=''> Export All As PDF</a>

<table id="example_1" class="display nowrap" style="width:100%">
    <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>
    <tr>
        <td>Garrett Winters</td>
        <td>Accountant</td>
        <td>Tokyo</td>
        <td>63</td>
        <td>2011-07-25</td>
        <td>$170,750</td>
    </tr>
    </tbody>
</table>

<table id="example_2" class="display nowrap" style="width:100%">
    <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>
    <tr>
        <td>Garrett Winters</td>
        <td>Accountant</td>
        <td>Tokyo</td>
        <td>63</td>
        <td>2011-07-25</td>
        <td>$170,750</td>
    </tr>
    </tbody>
</table>

javascript datatables jquery-events export-to-pdf
1个回答
0
投票

我想出了一个解决方案,并想我会发布一个答案,展示一个简单的例子,说明如何使用数据表、JSZip 和 PDfMake 组合和压缩多个 PDF 文件,因为我找不到很多真实的例子。

总的来说,它归结为按钮定义的

customize
选项。

buttons.pdf.js

function customPdfButtonAction (e, dt, button, config) {
  this.processing(true);

  var that = this;
  var data = dt.buttons.exportData(config.exportOptions);
  var info = dt.buttons.exportInfo(config);
  var rows = [];

  if (config.header) {
    rows.push(
      $.map(data.header, function (d) {
        return {
          text: typeof d === "string" ? d : d + "",
          style: "tableHeader"
        };
      })
    );
  }

  for (var i = 0, ien = data.body.length; i < ien; i++) {
    rows.push(
      $.map(data.body[i], function (d) {
        if (d === null || d === undefined) {
          d = "";
        }
        return {
          text: typeof d === "string" ? d : d + "",
          style: i % 2 ? "tableBodyEven" : "tableBodyOdd"
        };
      })
    );
  }

  if (config.footer && data.footer) {
    rows.push(
      $.map(data.footer, function (d) {
        return {
          text: typeof d === "string" ? d : d + "",
          style: "tableFooter"
        };
      })
    );
  }

  var doc = {
    pageSize: config.pageSize,
    pageOrientation: config.orientation,
    content: [
      {
        table: {
          headerRows: 1,
          body: rows
        },
        layout: "noBorders"
      }
    ],
    styles: {
      tableHeader: {
        bold: true,
        fontSize: 11,
        color: "white",
        fillColor: "#2d4154",
        alignment: "center"
      },
      tableBodyEven: {},
      tableBodyOdd: {
        fillColor: "#f3f3f3"
      },
      tableFooter: {
        bold: true,
        fontSize: 11,
        color: "white",
        fillColor: "#2d4154"
      },
      title: {
        alignment: "center",
        fontSize: 15
      },
      message: {}
    },
    defaultStyle: {
      fontSize: 10
    }
  };

  if (info.messageTop) {
    doc.content.unshift({
      text: info.messageTop,
      style: "message",
      margin: [0, 0, 0, 12]
    });
  }

  if (info.messageBottom) {
    doc.content.push({
      text: info.messageBottom,
      style: "message",
      margin: [0, 0, 0, 12]
    });
  }

  if (info.title) {
    doc.content.unshift({
      text: info.title,
      style: "title",
      margin: [0, 0, 0, 12]
    });
  }

  if (config.customize) {
    config.customize(doc, config, dt);
  }

  var pdf = window.pdfMake.createPdf(doc);

  if (config.download === "open" && !_isDuffSafari()) {
    pdf.open();
  } else {
    // In case of silent mode — exit without downloading
    if (e.detail.silent) return this.processing(false);

    pdf.download(info.filename);
  }

  this.processing(false);
}

window.customPdfButtonAction = customPdfButtonAction

main_functionality.js

(function ($) {
  let PDF_BLOB_PROMISES = [];
  const buttons = [
    "copy",
    "csv",
    "excel",
    "print",
    {
      extend: "pdf",
      text: "PDF",
      customize: customPDFButtonCustomize,    // here is the key
      action: customPdfButtonAction          // here is the key
    }
  ]

  // Push Blob to array of Promises
    
  async function customPDFButtonCustomize(doc) {
    try {
      PDF_BLOB_PROMISES.push(
        new Promise((resolve, reject) => {
          window.pdfMake.createPdf(doc).getBlob(resolve);
        })
      );
    } catch (e) {
      console.error("Push PDF to Blob failed", e);
    }
  }

  // Init Data tables

  function initDT() {
    $('[data-type="dt"]').each(function (i) {
      const table = $(this).DataTable({
        buttons
      });

      table
        .buttons()
        .container()
        .appendTo(`#DataTables_Table_${i}_wrapper .col-md-6:eq(0)`);
    });
  }

  // Export All button handler

  async function exportAllPDF() {
    try {
      const zip = new window.JSZip();
      const folder = zip.folder("pdf");

      PDF_BLOB_PROMISES = [];

      $(".buttons-pdf").each(function (a) {
        const event = new CustomEvent("click", {
          detail: {
            silent: true
          }
        });
        this.dispatchEvent(event);
      });

      const blobs = await Promise.all(PDF_BLOB_PROMISES);

      if (!blobs.length) return;

      for (let i = 0; i < blobs.length; i++) {
        folder.file(`pdf-${i + 1}.pdf`, blobs[i]);
      }

      const zipped = await zip.generateAsync({ type: "blob" });

      window.saveAs(zipped, "pdfs.zip");
    } catch (e) {
      console.error("Eport All PDF failed", e);
    }
  }

  $(document).ready(function () {
    // Init Data Tables
    initDT();

    // Export All button event listener
    $("#export_all").on("click", exportAllPDF);
  })
})(window.jQuery)

HTML 页面

<!DOCTYPE html>
<html>
  <head>
    <title>Show Me Some Magic</title>
    <meta charset="UTF-8" />
    <!-- CSS -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.css"
    />
    <link
      rel="stylesheet"
      href="https://cdn.datatables.net/1.13.4/css/dataTables.bootstrap4.min.css"
    />
    <link
      rel="stylesheet"
      href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.bootstrap4.min.css"
    />
    <style>
        body {
          padding: 2rem;
        }

        .dataTables_wrapper {
          margin-bottom: 3rem;
        }

        .btn-export-all {
          background: #afddff;
          border-radius: 10px;
          border: none;
          padding: 10px 20px;
          cursor: pointer;
        }

    </style>

    <!-- VENDOR JS -->
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
    <script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.13.4/js/dataTables.bootstrap4.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.bootstrap4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.colVis.min.js"></script>

    <!-- Local JS -->
    <script src="./js/buttons.pdf.js"></script>
    <script src="./js/main_functionality.js"></script>
  </head>

  <body>
    <div style="padding: 20px 0;">
      <button id="export_all" class="btn-export-all">Export All As PDF</button>
    </div>

    <table data-type="dt" class="table table-striped table-bordered compact">
      <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 1</td>
          <td>System Architect</td>
          <td>Edinburgh</td>
          <td>61</td>
          <td>2011-04-25</td>
          <td>$320,800</td>
        </tr>
        <tr>
          <td>Garrett Winters 1</td>
          <td>Accountant</td>
          <td>Tokyo</td>
          <td>63</td>
          <td>2011-07-25</td>
          <td>$170,750</td>
        </tr>
      </tbody>
    </table>

    <table data-type="dt" class="table table-striped table-bordered compact">
      <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 2</td>
          <td>System Architect</td>
          <td>Edinburgh</td>
          <td>61</td>
          <td>2011-04-25</td>
          <td>$280,800</td>
        </tr>
        <tr>
          <td>Garrett Winters 2</td>
          <td>Accountant</td>
          <td>Tokyo</td>
          <td>63</td>
          <td>2011-07-25</td>
          <td>$590,750</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.