5

I'm trying to convert an HTML table to a PDF without success.

I've used jsPDF to do that but the result is really poor and I'm trying to understand why.

Considering I have a tablet, what I want is to have this table printed on A4 pages in landscape mode (using all the pages that are needed). My problem is that the PDF is composed by images (and I prefer text) and that images are in a really low quality.

What I've tryed is this:

const html = document.getElementById('resultTable');
const pdf = new jsPDF('landscape', 'px', 'a4');

pdf.addHTML(html, 0, 0, {
    'width': html.clientWidth,
    'height': html.clientHeight
}, () => { pdf.save('web.pdf'); });

I've already tried to use, as width and height, the size of the pdf page (with pdf.internal.pageSize) without success. And I've already tried to use 'pt' and 'mm' instead of 'px'.

Any ideas?

DeooK
  • 535
  • 3
  • 8
  • 23

4 Answers4

2

This is not so trivial task. On the server I tried using wkhtmltopdf but end up looking for a better solution, because with it I can't use all the power of CSS for printing. I think it is the same problem with client-side tools like jsPDF, you will not get an expected and consistent result.

Headless chrome in Google Cloud is my choice right now.

Here is a good overview of available tools and technologies Modern HTML to PDF conversion

UPDATE:

If you need to create a PDF and can't install anything on your server, you can do so by using Headless Chrome and Google Cloud Function.

using-puppeteer-in-google-cloud-functions

puppeteering-in-firebase-google-cloud-functions

UPDATE 2:

And by the way, you always have an option to Print to PDF in browser. However, I'm not sure how it works on Android tablets, Safari for iOS can export to PDF.

DeC
  • 2,226
  • 22
  • 42
Vladimir Prudnikov
  • 6,974
  • 4
  • 48
  • 57
  • All of these solutions aren't applicable to my application. I can't assume that the user will use Chrome and surerly I can't install any other application like wkhtmltopdf (or even Chrome). – DeooK Feb 11 '19 at 11:37
  • Conversion must be done on the server. You use headless chrome on the server https://cloud.google.com/blog/products/gcp/introducing-headless-chrome-support-in-cloud-functions-and-app-engine – Vladimir Prudnikov Feb 11 '19 at 20:40
  • There is no point to do that on the server in my case: what I have to convert to PDF is the resulted view obtained by an user after a search. By the way, I cannot install anything even on the server. If I do not find any client solution probably I will realize the convertion with Java and iText directly on the back end. – DeooK Feb 12 '19 at 08:49
  • @DeooK you are so lean that you can't even read and learn things that I suggested to you, nobody will do your job. I spent a lot of time trying to solve this task. Doing so on the client-side you will have a lot of pain and inconsistent results. TIP: By using headless chrome in you can POST your HTML or URL to search results (same results that user is viewing) to the Cloud Function that will create PDF for you. https://medium.com/@ebidel/puppeteering-in-firebase-google-cloud-functions-76145c7662bd and https://medium.com/@ebidel/puppeteering-in-firebase-google-cloud-functions-76145c7662bd – Vladimir Prudnikov Feb 14 '19 at 11:01
  • 1
    Yeah, wonderful, but... I DO NOT CONTROL THE SERVER INSTALLATION. I can't use cloud functionality and I can't install anything on the server marchine. I have to put all I need on the Java application or on the Angular application. – DeooK Feb 14 '19 at 15:01
2

Use this way stackblitz working example

In yout typescript file

import {jsPDF} from 'jspdf';

@ViewChild('content', {static: false}) content: ElementRef;


public downloadPDF() {
   const doc = new jsPDF();

   const specialElementHandlers = {
      '#editor': function (element, renderer) {
       return true;
       }
   };

   const content = this.content.nativeElement;

   doc.fromHTML(content.innerHTML, 15, 15, {
      width: 190,
     'elementHandlers': specialElementHandlers
   });

   doc.save('test.pdf');
}

In your html file

<div id="content" #content>
    <!-- Put your content here -->
</div>

<button (click)="downloadPDF()">Export To PDF</button>
dasunse
  • 2,839
  • 1
  • 14
  • 32
  • Not Working..Getting some error "ERROR TypeError: jspdf__WEBPACK_IMPORTED_MODULE_9__.jsPDF is not a constructor" – afsarkhan10182 Jan 02 '20 at 13:08
  • @afsarkhan10182 please see the stackblitx example. It is working. see https://stackblitz.com/edit/angular-html-to-pdf-example – dasunse Jan 03 '20 at 07:33
  • @dasunse Have you imported html2canvas or any script? Because check the answer https://stackoverflow.com/questions/51518819/how-to-use-addhtml-in-angular-4 – afsarkhan10182 Jan 03 '20 at 13:44
0

Try .html() instead.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.debug.js" 
        integrity="sha384-NaWTHo/8YCBYJ59830LTz/P4aQZK1sS0SneOgAvhsIl3zBu8r9RevNg5lHCHAuQ/"
        crossorigin="anonymous"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
<script>
    function convert() {
        let pdf = new jsPDF('l', 'pt', [tblWidth, tblHeight]);
        pdf.html(document.getElementById('resultTable'), {
            callback: function () {
                // pdf.save('web.pdf');
                window.open(pdf.output('bloburl')); // use this to debug
            }
        });
    }
</script>
0
public downloadPdf() {
let doc = new jsPDF('p', 'pt', 'a4');
h2c(document.getElementById('printpdf')).then(function (canvas) {
  let width = doc.internal.pageSize.getWidth();
  let height = doc.internal.pageSize.getHeight();
  let dataURL = canvas.toDataURL('image/jpeg', 1.0);
  doc.addImage(dataURL, 'jpg', 0, 0, width, height, 'none');
  doc.save('mypdf.pdf');
  });
}
Bansi29
  • 1,053
  • 6
  • 24