Search code examples
groupingjspdfcalculated-columnsformattertabulator

Preserve formatting of ColumnCalculations while downloading pdf from tabulator


Issue: While downloading through tabulator all the column formatting is removed. I am aware of using accessors to reformat the data before downloading. This way I can define formatting for individual columns. However, for column calculations, I am unable to define formatting for calculation results at the time of downloading in pdf format. In addition, I want row groups headers to have proper indentation as its available in tabulator.

Implemented code:

var tabledata = [
              {
                  "Department": "Dept1",
                  "Promo Name": "$2 Off",
                  "Menu": "BURGER",
                  "Check #": "111",
                  "Settled By": "aaaaa",
                  "Discount By": "aaaaa",
                  "Price": "12.50",
                  "Discount": "2.00",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "$2 Off",
                  "Menu": "soda",
                  "Check #": "1112",
                  "Settled By": "emp2",
                  "Discount By": "emp2",
                  "Price": "11.95",
                  "Discount": "2.00",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "10% Off",
                  "Menu": "BURGER",
                  "Check #": "112",
                  "Settled By": "aaaaa",
                  "Discount By": "aaaaa",
                  "Price": "12.50",
                  "Discount": "0.00",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "10% Off",
                  "Menu": "Water",
                  "Check #": "1122",
                  "Settled By": "aaaaa",
                  "Discount By": "aaaaa",
                  "Price": "1.85",
                  "Discount": "0.00",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "222",
                  "Menu": "menu2",
                  "Check #": "1134",
                  "Settled By": "emp3",
                  "Discount By": "emp3",
                  "Price": "10.25",
                  "Discount": "2.00",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "meal",
                  "Menu": "pizza",
                  "Check #": "1156",
                  "Settled By": "emp3",
                  "Discount By": "emp3",
                  "Price": "12.95",
                  "Discount": "6.48",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "meal",
                  "Menu": "BURGER",
                  "Check #": "11562",
                  "Settled By": "aaaaa",
                  "Discount By": "aaaaa",
                  "Price": "12.50",
                  "Discount": "3.13",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "meal",
                  "Menu": "sandwich",
                  "Check #": "157",
                  "Settled By": "emp2",
                  "Discount By": "emp2",
                  "Price": "56.25",
                  "Discount": "28.13",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "meal",
                  "Menu": "coke",
                  "Check #": "27818",
                  "Settled By": "aaaaa",
                  "Discount By": "aaaaa",
                  "Price": "3.00",
                  "Discount": "1.50",
                  "Count of PromoID": "1"
              },
              {
                  "Department": "Dept1",
                  "Promo Name": "meal",
                  "Menu": "juice",
                  "Check #": "13346",
                  "Settled By": "aaaaa",
                  "Discount By": "aaaaa",
                  "Price": "3.00",
                  "Discount": "1.50",
                  "Count of PromoID": "1"
              }
          ];


          const formatter = new Intl.NumberFormat('en-US', {
              style: 'currency',
              currency: 'USD',
              minimumFractionDigits: 2
          })

          var colMoneyFormatter = function (value, data, type, params, column) {
              return formatter.format(value);
          }

          //create Tabulator on DOM element with id "example-table"
          var table = new Tabulator("#example-table",
              {
                  //height: 205, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
                  data: tabledata //assign data to table
                  ,
                  layout: "fitData" //fit columns to width of table (optional)
                  ,
                  groupClosedShowCalcs: [true, true],
                  columnCalcs: "both",
                  groupBy: ["Department", "Promo Name"],
                  groupStartOpen: [true, true],
                  groupHeader: function(value, count, data, group) {
                      return value + "<span style='color:#d00; margin-left:10px;'>(" + count + " item)</span>";
                  },
                  groupToggleElement: ["arrow", "arrow"],
                  columns: [
                      { title: "Department", field: "Department", formatter: "plaintext" },
                      { title: "Promo Name", field: "Promo Name", formatter: "plaintext" },
                      { title: "Description", field: "Menu", formatter: "plaintext" }, {
                          title: "Price",
                          field: "Price",
                          accessorDownload: colMoneyFormatter,
                          formatter: "money",
                          bottomCalc: "sum",
                          bottomCalcParams: { precision: 2 },
                          bottomCalcFormatter: "money",
                          bottomCalcFormatterParams: {
                              decimal: ".",
                              thousand: ",",
                              symbol: "$"
                          },
                          formatterParams: {
                              decimal: ".",
                              thousand: ",",
                              symbol: "$"
                          }
                      }, {
                          title: "Discount",
                          field: "Discount",
                          accessorDownload: colMoneyFormatter,
                          formatter: "money",
                          bottomCalc: "sum",
                          bottomCalcParams: { precision: 2 },
                          bottomCalcFormatter: "money",
                          bottomCalcFormatterParams: {
                              decimal: ".",
                              thousand: ",",
                              symbol: "$"
                          },
                          formatterParams: {
                              decimal: ".",
                              thousand: ",",
                              symbol: "$"
                          }
                      }, { title: "Check #", field: "Check #", formatter: "plaintext" },
                      { title: "Settled By", field: "Settled By", formatter: "plaintext" },
                      { title: "Discount By", field: "Discount By", formatter: "plaintext" }
                  ]
              });

          //trigger download of data.pdf file
          $("#download-pdf").click(function () {
              table.download("pdf",
                  "data.pdf",
                  {
                      orientation: "landscape" //set page orientation to portrait
                      ,
                      title: "Detailed Promo Report" //add title to report
                      ,
                      autoTable: {
                          margin: {
                              top: 60
                          }
                      }
                  });
          });

I want my pdf to look exactly like tabulator table with some additional rows, headers, and footers.

Any help will be greatly appreciated.


Solution

  • <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <link href="https://unpkg.com/[email protected]/dist/css/tabulator.min.css" rel="stylesheet">
      <script src="https://unpkg.com/[email protected]/dist/js/tabulator.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
    
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.0.5/jspdf.plugin.autotable.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    </head>
    <body>
    <button id="download-pdf">Download PDF</button>
    <div id="example-table"></div>
    </body>
    </html>
    
    <script>
      var tabledata = [{
        "Department": "Dept1",
        "Promo Name": "$2 Off",
        "Menu": "BURGER",
        "Check #": "111",
        "Settled By": "aaaaa",
        "Discount By": "aaaaa",
        "Price": "12.50",
        "Discount": "2.00",
        "Count of PromoID": "1"
      },
        {
          "Department": "Dept1",
          "Promo Name": "$2 Off",
          "Menu": "soda",
          "Check #": "1112",
          "Settled By": "emp2",
          "Discount By": "emp2",
          "Price": "11.95",
          "Discount": "2.00",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "10% Off",
          "Menu": "BURGER",
          "Check #": "112",
          "Settled By": "aaaaa",
          "Discount By": "aaaaa",
          "Price": "12.50",
          "Discount": "0.00",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "10% Off",
          "Menu": "Water",
          "Check #": "1122",
          "Settled By": "aaaaa",
          "Discount By": "aaaaa",
          "Price": "1.85",
          "Discount": "0.00",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "222",
          "Menu": "menu2",
          "Check #": "1134",
          "Settled By": "emp3",
          "Discount By": "emp3",
          "Price": "10.25",
          "Discount": "2.00",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "meal",
          "Menu": "pizza",
          "Check #": "1156",
          "Settled By": "emp3",
          "Discount By": "emp3",
          "Price": "12.95",
          "Discount": "6.48",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "meal",
          "Menu": "BURGER",
          "Check #": "11562",
          "Settled By": "aaaaa",
          "Discount By": "aaaaa",
          "Price": "12.50",
          "Discount": "3.13",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "meal",
          "Menu": "sandwich",
          "Check #": "157",
          "Settled By": "emp2",
          "Discount By": "emp2",
          "Price": "56.25",
          "Discount": "28.13",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "meal",
          "Menu": "coke",
          "Check #": "27818",
          "Settled By": "aaaaa",
          "Discount By": "aaaaa",
          "Price": "3.00",
          "Discount": "1.50",
          "Count of PromoID": "1"
        },
        {
          "Department": "Dept1",
          "Promo Name": "meal",
          "Menu": "juice",
          "Check #": "13346",
          "Settled By": "aaaaa",
          "Discount By": "aaaaa",
          "Price": "3.00",
          "Discount": "1.50",
          "Count of PromoID": "1"
        }
      ];
    
    
      const formatter = new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 2
      })
    
      var colMoneyFormatter = function(value, data, type, params, column) {
        return formatter.format(value);
      }
    
    
      const table = new Tabulator("#example-table", {
        data: tabledata,
        layout: "fitData",
        groupClosedShowCalcs: [true, true],
        columnCalcs: "both",
        groupBy: ["Department", "Promo Name"],
        groupStartOpen: [true, true],
        groupHeader: function(value, count, data, group) {
          return value + "<span style='color:#d00; margin-left:10px;'>(" + count + " item)</span>";
        },
        groupToggleElement: ["arrow", "arrow"],
        columns: [{
          title: "Department",
          field: "Department",
          formatter: "plaintext"
        },
          {
            title: "Promo Name",
            field: "Promo Name",
            formatter: "plaintext"
          },
          {
            title: "Description",
            field: "Menu",
            formatter: "plaintext"
          }, {
            title: "Price",
            field: "Price",
            accessorDownload: colMoneyFormatter,
            formatter: "money",
            bottomCalc: "sum",
            bottomCalcParams: {
              precision: 2
            },
            bottomCalcFormatter: "money",
            bottomCalcFormatterParams: {
              decimal: ".",
              thousand: ",",
              symbol: "$"
            },
            formatterParams: {
              decimal: ".",
              thousand: ",",
              symbol: "$"
            }
          }, {
            title: "Discount",
            field: "Discount",
            accessorDownload: colMoneyFormatter,
            formatter: "money",
            bottomCalc: "sum",
            bottomCalcParams: {
              precision: 2
            },
            bottomCalcFormatter: "money",
            bottomCalcFormatterParams: {
              decimal: ".",
              thousand: ",",
              symbol: "$"
            },
            formatterParams: {
              decimal: ".",
              thousand: ",",
              symbol: "$"
            }
          }, {
            title: "Check #",
            field: "Check #",
            formatter: "plaintext"
          },
          {
            title: "Settled By",
            field: "Settled By",
            formatter: "plaintext"
          },
          {
            title: "Discount By",
            field: "Discount By",
            formatter: "plaintext"
          }
        ]
      });
    
      //trigger download of data.pdf file
      $("#download-pdf").click(function(){
        table.download("pdf", "data.pdf", {
          orientation:"portrait", //set page orientation to portrait
          title:"Example Report" //add title to report
        });
      });
    </script>