Générer des pdf à partir de HTML dans div en utilisant Javascript

J'ai le code html suivant:

<!DOCTYPE html>
<html>
    <body>
        <p>don't print this to pdf</p>
        <div id="pdf">
            <p><font size="3" color="red">print this to pdf</font></p>
        </div>
    </body>
</html>

Tout ce que je veux faire est d'imprimer au format pdf tout ce qui se trouve dans la div avec un id de "pdf". Cela doit être fait en utilisant JavaScript. Le document" pdf "devrait alors être automatiquement téléchargé avec un nom de fichier de" foobar.pdf "

J'ai utilisé jspdf pour ce faire, mais la seule fonction qu'il a est "text" qui n'accepte que les valeurs de chaîne. Je veux soumettre du HTML à jspdf, pas du texte.

158
demandé sur Lukasz Koziara 2013-08-12 20:18:31

9 réponses

JsPDF est capable d'utiliser des plugins. pour lui permettre d'imprimer du HTML, vous devez inclure certains plugins et donc effectuer les opérations suivantes:

  1. aller à https://github.com/MrRio/jsPDF {[11] } et téléchargez la dernière Version.
  2. incluez les Scripts suivants dans votre projet:
    • jspdf.js
    • jspdf.plugin.from_html.js
    • jspdf.plugin.split_text_to_size.js
    • jspdf.plugin.standard_fonts_metrics.js

Si vous voulez ignorer certains éléments, vous devez les marquer avec un ID, que vous pouvez ensuite ignorer dans un gestionnaire d'éléments spécial de jsPDF. Par conséquent, votre code HTML devrait ressembler à ceci:

<!DOCTYPE html>
<html>
  <body>
    <p id="ignorePDF">don't print this to pdf</p>
    <div>
      <p><font size="3" color="red">print this to pdf</font></p>
    </div>
  </body>
</html>

Ensuite, vous utilisez le code JavaScript suivant pour ouvrir le PDF créé dans une fenêtre contextuelle:

var doc = new jsPDF();          
var elementHandler = {
  '#ignorePDF': function (element, renderer) {
    return true;
  }
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
    source,
    15,
    15,
    {
      'width': 180,'elementHandlers': elementHandler
    });

doc.output("dataurlnewwindow");

Pour moi cela a créé un PDF agréable et bien rangé qui ne comprenait que la ligne "imprimer au format pdf".

Veuillez noter que les gestionnaires d'éléments spéciaux ne traitent que les identifiants dans la version actuelle, ce qui est également indiqué dans un problème GitHub . Il indique:

Parce que la correspondance est faite contre chaque élément de l'arbre des nœuds, mon désir était de le faire aussi vite que possible. Dans ce cas, cela signifiait "seuls les ID d'élément sont appariés" les ID d'élément sont toujours faits dans le style jQuery "# id" , mais il ne signifie pas que tous les sélecteurs jQuery sont pris en charge.

Par conséquent, en remplaçant '# ignorePDF ' par des sélecteurs de classe comme '.ignorePDF ' n'a pas fonctionné pour moi. Au lieu de cela, vous devrez ajouter le même gestionnaire pour chaque élément, que vous voulez ignorer comme:

var elementHandler = {
  '#ignoreElement': function (element, renderer) {
    return true;
  },
  '#anotherIdToBeIgnored': function (element, renderer) {
    return true;
  }
};

De la exemples, il est également indiqué qu'il est possible de sélectionner des étiquettes comme " a " ou "li". Cela pourrait être un peu non restrictif pour la plupart des cas d'utilisation:

Nous soutenons gestionnaires d'éléments spéciaux. Enregistrez-les avec jQuery-style Sélecteur D'ID pour ID ou nom de noeud. ("#iAmID", "div", "durée", etc.) Il n'y a pas de support pour tout autre type de sélecteurs (classe, de composé) à ce moment.

Une chose très importante à ajouter est que vous perdez toutes vos informations de style (CSS). Heureusement, jsPDF est capable de bien formater h1, h2, h3, etc., ce qui était suffisant pour mes besoins. Additionalyl il n'imprimera que du texte dans les nœuds de texte, ce qui signifie qu'il pas imprimer les valeurs de textareas et autres. Exemple:

<body>
  <ul>
    <!-- This is printed as the element contains a textnode -->        
    <li>Print me!</li>
  </ul>
  <div>
    <!-- This is not printed because jsPDF doesn't deal with the value attribute -->
    <input type="textarea" value="Please print me, too!">
  </div>
</body>
156
répondu snrlx 2015-01-06 09:00:12

C'est la solution la plus simple. Cela fonctionne pour moi.Vous pouvez utiliser le concept d'impression javascript et l'enregistrer simplement au format pdf.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript">
        $("#btnPrint").live("click", function () {
            var divContents = $("#dvContainer").html();
            var printWindow = window.open('', '', 'height=400,width=800');
            printWindow.document.write('<html><head><title>DIV Contents</title>');
            printWindow.document.write('</head><body >');
            printWindow.document.write(divContents);
            printWindow.document.write('</body></html>');
            printWindow.document.close();
            printWindow.print();
        });
    </script>
</head>
<body>
    <form id="form1">
    <div id="dvContainer">
        This content needs to be printed.
    </div>
    <input type="button" value="Print Div Contents" id="btnPrint" />
    </form>
</body>
</html>
27
répondu vaibhav kulkarni 2015-11-24 10:04:38

Vous pouvez utiliser autoPrint () et définir output sur 'dataurlnewwindow' comme ceci:

function printPDF() {
    var printDoc = new jsPDF();
    printDoc.fromHTML($('#pdf').get(0), 10, 10, {'width': 180});
    printDoc.autoPrint();
    printDoc.output("dataurlnewwindow"); // this opens a new popup,  after this the PDF opens the print window view but there are browser inconsistencies with how this is handled
}
11
répondu Marco 2015-08-24 14:47:03

Comme mentionné précédemment, vous devez utiliser jsPDF et html2canvas. J'ai également trouvé une fonction dans les problèmes de jsPDF qui divise automatiquement votre pdf en plusieurs pages (sources )

function makePDF() {

    var quotes = document.getElementById('container-fluid');

    html2canvas(quotes, {
        onrendered: function(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');
    }
  });
}
7
répondu BaptWaels 2017-02-17 14:07:00

Si vous souhaitez exporter une table, vous pouvez jeter un oeil à cet exemple d'exportation fourni par le widget Shield UI Grid.

Cela se fait en étendant la configuration comme ceci:

...
exportOptions: {
    proxy: "/filesaver/save",
    pdf: {
        fileName: "shieldui-export",
        author: "John Smith",
        dataSource: {
            data: gridData
        },
        readDataSource: true,
        header: {
            cells: [
                { field: "id", title: "ID", width: 50 },
                { field: "name", title: "Person Name", width: 100 },
                { field: "company", title: "Company Name", width: 100 },
                { field: "email", title: "Email Address" }
            ]
        }
    }
}
...
2
répondu Vladimir Georgiev 2016-10-18 13:07:46

Si vous avez besoin de télécharger le pdf d'une page spécifique, ajoutez simplement un bouton comme celui-ci

<h4 onclick="window.print();"> Print </h4>

Utiliser la fenêtre.print() pour imprimer toute votre page pas seulement une div

1
répondu Wael Mahmoud 2018-03-09 17:48:32

J'ai pu obtenir jsPDF pour imprimer des tables créées dynamiquement à partir d'un div.

$(document).ready(function() {

        $("#pdfDiv").click(function() {

    var pdf = new jsPDF('p','pt','letter');
    var specialElementHandlers = {
    '#rentalListCan': function (element, renderer) {
        return true;
        }
    };

    pdf.addHTML($('#rentalListCan').first(), function() {
        pdf.save("caravan.pdf");
    });
    });
});

Fonctionne très bien avec Chrome et Firefox... le formatage est tout explosé dans IE.

J'ai également inclus ceux-ci:

<script src="js/jspdf.js"></script>
    <script src="js/jspdf.plugin.from_html.js"></script>
    <script src="js/jspdf.plugin.addhtml.js"></script>
    <script src="//mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>
    <script src="http://html2canvas.hertzen.com/build/html2canvas.js"></script>
    <script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
    <script type="text/javascript" src="./libs/Blob.js/Blob.js"></script>
    <script type="text/javascript" src="./libs/deflate.js"></script>
    <script type="text/javascript" src="./libs/adler32cs.js/adler32cs.js"></script>

    <script type="text/javascript" src="js/jspdf.plugin.addimage.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.sillysvgrenderer.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.split_text_to_size.js"></script>
    <script type="text/javascript" src="js/jspdf.plugin.standard_fonts_metrics.js"></script>
0
répondu Wasskinny 2015-03-12 11:52:07

Pour capturer div au format PDF, vous pouvez utiliser https://grabz.it solution. Il a une API JavaScript qui est facile et flexible et vous permettra de capturer le contenu d'un seul élément HTML tel qu'un div ou un span

Pour l'implémenter, vous devrez d'abord obtenir une clé d'application et un secret etTélécharger le SDK (gratuit).

Et maintenant un exemple.

Disons que vous avez le code HTML:

<div id="features">
    <h4>Acme Camera</h4>
    <label>Price</label>$399<br />
    <label>Rating</label>4.5 out of 5
</div>
<p>Cras ut velit sed purus porttitor aliquam. Nulla tristique magna ac libero tempor, ac vestibulum felisvulput ate. Nam ut velit eget
risus porttitor tristique at ac diam. Sed nisi risus, rutrum a metus suscipit, euismod tristique nulla. Etiam venenatis rutrum risus at
blandit. In hac habitasse platea dictumst. Suspendisse potenti. Phasellus eget vehicula felis.</p>

Pour capturer ce qui se trouve sous l'id des fonctionnalités, vous besoin de:

//add the sdk
<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
//login with your key and secret. 
GrabzIt("KEY", "SECRET").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "format": "pdf"}).Create();
</script>

Veuillez noter le target: #feature. #feature est votre sélecteur CSS, comme dans l'exemple précédent. Maintenant, lorsque la page est chargée, une capture d'écran d'image sera maintenant créée au même endroit que la balise de script, qui contiendra tout le contenu des fonctionnalités div et rien d'autre.

Sont d'autres configurations et personnalisations que vous pouvez faire au mécanisme de capture d'écran div, veuillez les vérifier ici

0
répondu Stas 2017-07-01 17:40:23
  • aucune dépendance, js pur

Cela m'a servi pendant des années:

export default function printDiv({divId, title}) {
  let mywindow = window.open('', 'PRINT', 'height=650,width=900,top=100,left=150');

  mywindow.document.write(`<html><head><title>${title}</title>`);
  mywindow.document.write('</head><body >');
  mywindow.document.write(document.getElementById(divId).innerHTML);
  mywindow.document.write('</body></html>');

  mywindow.document.close(); // necessary for IE >= 10
  mywindow.focus(); // necessary for IE >= 10*/

  mywindow.print();
  mywindow.close();

  return true;
}
0
répondu Lukas 2018-05-06 13:45:58