[multipage] jsPDF multi page PDF with HTML renderer

I am using jsPDF in my site to generate PDFs. But now I have multiple DIVs to print in a single PDF. which may take 2 to 3 pages.

For example:

<div id="part1">
  content
</div>

<div id="part2">
  content
</div>

<div id="part2">
   content
</div>

my JS code

  • This works but not as I expected, It add a part of the content(which cannot be included in more than one page).
  • It removes html tags like br, h1 etc.
    function formtoPDF() {
      jsPDF.API.mymethod = function() {
        // 'this' will be ref to internal API object. see jsPDF source
        // , so you can refer to built-in methods like so:
        //   this.line(....)
        //   this.text(....)
      };
      var doc = new jsPDF();
      doc.mymethod();
      var pdfPart1 = jQuery('#genPDFpart1');
      var pdfPart2 = jQuery(".ltinerary");
      var pdfPart3 = jQuery("#domElementHTML");
      var specialElementHandlers = {
        '#loadVar': function(element, renderer) {
          return true;
        }
      };
      doc.fromHTML(pdfPart1.html() + pdfPart3.html() + pdfPart3.html(), 15, 15, {
        'width': 170,
        'elementHandlers': specialElementHandlers
      });
      doc.output('save', 'Download.pdf');
    }

Can I have a solution for this. Thanks in advance pals .

This question is related to multipage jspdf

The answer is


Below is my code but the problem is that the document doesn't split to display the other part of the document in a new page.

Please improve this code.

<script type='text/javascript'>
$(document).on("click", "#btnExportToPDF", function () {
    var table1 =
    tableToJson($('#table1')[0]),
    cellWidth =42,
    rowCount = 0,
    cellContents,
    leftMargin = 2,
    topMargin = 12,
    topMarginTable =5,
    headerRowHeight = 13,
    rowHeight = 12,
    l = {
        orientation: 'p',
        unit: 'mm',
        format: 'a3',
        compress: true,
        fontSize: 11,
        lineHeight: 1,
        autoSize: false,
        printHeaders: true
    };

    var doc = new jsPDF(l,'pt', 'letter');

    doc.setProperties({
        title: 'Test PDF Document',
        subject: 'This is the subject',
        author: 'author',
        keywords: 'generated, javascript, web 2.0, ajax',
        creator: 'author'
    });
    doc.cellInitialize();

    $.each(table1, function (i, row)
    {
        rowCount++;

        $.each(row, function (j, cellContent) {

            if (rowCount == 1) {
                doc.margins = 1;
                doc.setFont("Times New Roman");
                doc.setFontType("bold");
                doc.setFontSize(11);

                doc.cell(leftMargin, topMargin, cellWidth, headerRowHeight, cellContent, i)
            }
            else if (rowCount == 2) {

                doc.margins = 1;
                doc.setFont("Times ");
                doc.setFontType("normal");
                // or for normal font type use ------ doc.setFontType("normal");

                doc.setFontSize(11);

                doc.cell(leftMargin, topMargin, cellWidth, rowHeight, cellContent, i);
            }
            else {

                doc.margins = 1;
                doc.setFont("Times  ");
                doc.setFontType("normal ");
                doc.setFontSize(11);
                doc.cell(leftMargin, topMargin, cellWidth, rowHeight, cellContent, i);
                // 1st=left margin    2nd parameter=top margin,     3rd=row cell width      4th=Row height
            }
        })
    })
    doc.save('sample Report.pdf');
});

function tableToJson(table) {

    var data = [];

    // first row needs to be headers
    var headers = [];

    for (var i=0; i<table.rows[0].cells.length; i++) {
        headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
    }

    // go through cells
    for (var i=1; i<table.rows.length; i++) {

        var tableRow = table.rows[i];

        var rowData = {};

        for (var j=0; j<tableRow.cells.length; j++) {
            rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
        }

        data.push(rowData);
    }

    return data;
}
</script>

here's an example using html2canvas & jspdf, although how you generate the canvas doesn't matter--we're just going to use the height of that as the breakpoint on a for loop, in which a new page is created and content added to it.

after the for loop, the pdf is saved.

function makePDF() {

       var quotes = document.getElementById('container-fluid');
       html2canvas(quotes)
      .then((canvas) => {
            //! MAKE YOUR PDF
            var pdf = new jsPDF('p', 'pt', 'letter');

            for (var i = 0; i <= quotes.clientHeight/980; i++) {
                //! This is all just html2canvas stuff
                var srcImg  = canvas;
                var sX      = 0;
                var sY      = 980*i; // start 980 pixels down for every new page
                var sWidth  = 900;
                var sHeight = 980;
                var dX      = 0;
                var dY      = 0;
                var dWidth  = 900;
                var dHeight = 980;

                window.onePageCanvas = document.createElement("canvas");
                onePageCanvas.setAttribute('width', 900);
                onePageCanvas.setAttribute('height', 980);
                var ctx = onePageCanvas.getContext('2d');
                // details on this usage of this function: 
                // https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
                ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);

                // document.body.appendChild(canvas);
                var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);

                var width         = onePageCanvas.width;
                var height        = onePageCanvas.clientHeight;

                //! If we're on anything other than the first page,
                // add another page
                if (i > 0) {
                    pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
                }
                //! now we declare that we're working on that page
                pdf.setPage(i+1);
                //! now we add content to that page!
                pdf.addImage(canvasDataURL, 'PNG', 20, 40, (width*.62), (height*.62));

            }
            //! after the for loop is finished running, we save the pdf.
            pdf.save('Test.pdf');
        }
      });
    }

Automatically not split data to multi pages. You may split manually.

If your ( rowCount * rowHeight ) > 420mm ( A3 Height in mm ) add new page function. ( Sorry I can't edit your code without run ) After add new page leftMargin, topMargin = 0; ( start over ) I added sample code with yours. I hope it's right.

else {
    doc.margins = 1;
    doc.setFont("Times  ");
    doc.setFontType("normal ");
    doc.setFontSize(11);
    if ( rowCount * rowHeight > 420 ) {
        doc.addPage();
        rowCount = 3; // skip 1 and 2 above
    } else {
        // now rowcount = 3 ( top of new page for 3 )
        // j is your x axis cell index ( j start from 0 on $.each function ) or you can add cellCount like rowCount and replace with
        // rowcount is your y axis cell index
        left = ( ( j ) * ( cellWidth + leftMargin );
        top = ( ( rowcount - 3 ) * ( rowHeight + topMargin );
        doc.cell( leftMargin, top, cellWidth, rowHeight, cellContent, i);
        // 1st=left margin    2nd parameter=top margin,     3rd=row cell width      4th=Row height
    }
}

You can convert html directly to pdf lossless. Youtube video for html => pdf example


This is my first post which support only a single page http://www.techumber.com/html-to-pdf-conversion-using-javascript/

Now, the second one will support the multiple pages. http://www.techumber.com/how-to-convert-html-to-pdf-using-javascript-multipage/


 var doc = new jsPDF('p', 'mm');

 var imgData = canvas.toDataURL('image/png');
 var pageHeight= doc.internal.pageSize.getHeight();
 var pageWidth= doc.internal.pageSize.getWidth();

 var imgheight = $('divName').height() * 25.4 / 96; //px to mm
 var pagecount = Math.ceil(imgheight / pageHeight);

 /* add initial page */
 doc.addPage('l','mm','a4');
 doc.addImage(imgData, 'PNG', 2, 0, pageWidth-4, 0);

 /* add extra pages if the div size is larger than a a4 size */
 if (pagecount > 0) {
     var j = 1;
     while (j != pagecount) {
         doc.addPage('l','mm','a4');
         doc.addImage(imgData, 'PNG', 2, -(j * pageHeight), pageWidth-4, 0);
         j++;
     }
 }

$( document ).ready(function() {    
$('#cmd').click(function() {
      var options = {
              pagesplit: true //include this in your code
      };
      var pdf = new jsPDF('p', 'pt', 'a4');
      pdf.addHTML($("#pdfContent"), 15, 15, options, function() {
        pdf.save('Menu.pdf');
      });
    });
});

var a = 0;
var d;
var increment;

for(n in array){
    d = a++;        

    if(n % 6 === 0 && n != 0){
        doc.addPage();
        a = 1;
        d = 0;
    }

    increment = d == 0 ? 10 : 50;
    size = (d * increment) <= 0 ? 10 : d * increment;

    doc.text(array[n], 10, size);
}

         html2canvas(element[0], {
                    onrendered: function (canvas) {
                        pages = Math.ceil(element[0].clientHeight / 1450);
                        for (i = 0; i <= pages; i += 1) {
                            if (i > 0) {
                                pdf.addPage();
                            }
                            srcImg = canvas;
                            sX = 0;
                            sY = 1450 * i;
                            sWidth = 1100;
                            sHeight = 1450;
                            dX = 0;
                            dY = 0;
                            dWidth = 1100;
                            dHeight = 1450;
                            window.onePageCanvas = document.createElement("canvas");
                            onePageCanvas.setAttribute('width', 1100);
                            onePageCanvas.setAttribute('height', 1450);
                            ctx = onePageCanvas.getContext('2d');
                            ctx.drawImage(srcImg, sX, sY, sWidth, sHeight, dX, dY, dWidth, dHeight);
                            canvasDataURL = onePageCanvas.toDataURL("image/png");
                            width = onePageCanvas.width;
                            height = onePageCanvas.clientHeight;
                            pdf.setPage(i + 1);
                            pdf.addImage(canvasDataURL, 'PNG', 35, 30, (width * 0.5), (height * 0.5));
                        }
                        pdf.save('testfilename.pdf');
                    }
                });

You can use html2canvas plugin and jsPDF both. Process order: html to png & png to pdf

Example code:

jQuery('#part1').html2canvas({
    onrendered: function( canvas ) {
        var img1 = canvas.toDataURL('image/png');
    }
});
jQuery('#part2').html2canvas({
    onrendered: function( canvas ) {
        var img2 = canvas.toDataURL('image/png');
    }
});
jQuery('#part3').html2canvas({
    onrendered: function( canvas ) {
        var img3 = canvas.toDataURL('image/png');
    }
});
var doc = new jsPDF('p', 'mm');
doc.addImage( img1, 'PNG', 0, 0, 210, 297); // A4 sizes
doc.addImage( img2, 'PNG', 0, 90, 210, 297); // img1 and img2 on first page

doc.addPage();
doc.addImage( img3, 'PNG', 0, 0, 210, 297); // img3 on second page
doc.save("file.pdf");

I found the solution on this page: https://github.com/MrRio/jsPDF/issues/434 From the user: wangzhixuan

I copy the solution here: // suppose your picture is already in a canvas

      var imgData = canvas.toDataURL('image/png');

      /*
      Here are the numbers (paper width and height) that I found to work. 
      It still creates a little overlap part between the pages, but good enough for me.
      if you can find an official number from jsPDF, use them.
      */
      var imgWidth = 210; 
      var pageHeight = 295;  
      var imgHeight = canvas.height * imgWidth / canvas.width;
      var heightLeft = imgHeight;

      var doc = new jsPDF('p', 'mm');
      var position = 0;

      doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
      heightLeft -= pageHeight;

      while (heightLeft >= 0) {
        position = heightLeft - imgHeight;
        doc.addPage();
        doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
        heightLeft -= pageHeight;
      }
      doc.save( 'file.pdf');?