web-dev-qa-db-ja.com

Javascriptを使ってdivからHTMLからpdfを生成する

以下のHTMLコードがあります。

<!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>

私がしたいのは、 "pdf"というIDを持つdivにあるものが何であれpdfに出力することです。これはJavaScriptを使用して行わなければなりません。 「pdf」ドキュメントは自動的に「foobar.pdf」というファイル名でダウンロードされます。

私はこれを行うためにjspdfを使ってきましたが、それが持っている唯一の関数は文字列値だけを受け付ける "text"です。テキストではなくjspdfにHTMLを送信したいです。

181
John Crawford

jsPDFはプラグインを使用できます。 HTMLを印刷できるようにするには、特定のプラグインを含めなければならず、したがって次のことを行う必要があります。

  1. https://github.com/MrRio/jsPDF にアクセスして、最新バージョンをダウンロードしてください。
  2. プロジェクトに次のスクリプトを含めます。
    • jspdf.js
    • jspdf.plugin.from_html.js
    • jspdf.plugin.split_text_to_size.js
    • jspdf.plugin.standard_fonts_metrics.js

特定の要素を無視したい場合は、それらをIDでマークする必要があります。これをjsPDFの特別な要素ハンドラで無視することができます。したがって、HTMLはこのようになります。

<!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>

次に、次のJavaScriptコードを使用して、作成したPDFをPopUpで開きます。

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");

私にとってはこれで 'print this to pdf'という行だけが含まれているすてきなPDFが作成されました。

特別な要素ハンドラは現在のバージョンのIDのみを扱うことに注意してください。これは GitHub Issue にも書かれています。それは述べています:

マッチングはノードツリーのすべての要素に対して行われるので、できるだけ速くすることが私の望みでした。その場合は、「要素IDのみが一致する」という意味です。要素IDは依然としてjQueryスタイル「#id」で処理されますが、すべてのjQueryセレクタがサポートされているわけではありません。

そのため、 '#ignorePDF'を '.ignorePDF'のようなクラスセレクタに置き換えても私にはうまくいきませんでした。代わりに、すべての要素に対して同じハンドラを追加する必要があります。これは無視したいものです。

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

の例 からも、 'a'や 'li'のようなタグを選択することが可能であると述べられています。ただし、ほとんどのユースケースでは、これは少し制限的ではないかもしれません。

特別な要素ハンドラをサポートします。 IDまたはノード名のいずれかをjQueryスタイルのIDセレクタで登録します。 ( "#iAmID"、 "div"、 "span"など)現時点では、他の種類のセレクター(クラス、複合)はサポートされていません。

付け加えるべき1つの非常に重要なことはあなたがあなたのスタイル情報(CSS)をすべて失うということです。幸いなことにjsPDFはうまく私の目的のために十分だったh1、h2、h3などをフォーマットすることができます。さらに、テキストノード内のテキストのみを印刷します。つまり、テキストエリアなどの値は印刷されません。例:

<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>
178
snrlx

これが簡単な解決策です。これは私のために動作します。JavaScriptの印刷概念を使用して、単純にこれを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>
36

AutoPrint()を使用して、出力を次のように 'dataurlnewwindow'に設定できます。

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
}
13
Marco

前述のように、 jsPDF および html2canvas を使用する必要があります。私はまたあなたのpdfを自動的に複数のページに分割するjsPDFの問題の中に関数を見つけました( 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');
    }
  });
}
8
BaptWaels

あなたが特定のページのダウンロード可能なpdfを必要とするならば、ちょうどこのようなボタンを加える

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

divだけでなくあなたの全ページを印刷するにはwindow.print()を使ってください

4
Wael Mahmoud

テーブルをエクスポートしたい場合は、 このエクスポートサンプル を参照してください。/ Shield UIグリッドウィジェットによって提供されます。

これは、このように設定を拡張することによって行われます。

...
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
  • これは何年も私に役立ちました:

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; }

1
Lukas

動的に作成されたテーブルをdivからjsPDFに印刷させることができました。

$(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");
    });
    });
});

ChromeとFirefoxに最適です。フォーマットはすべてIEで行われます。

私もこれらを含めました:

<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>
1
Wasskinny

DivをPDFとしてキャプチャするには、 https://grabz.it solutionを使用します。それは簡単で柔軟なJavaScript APIを持っていて、divやspanのような単一のHTML要素のコンテンツを取得することを可能にします。

それを実装するためには、最初に appキーとシークレットdownload (無料)SDKを入手する必要があります。

そして今、例です。

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>

機能IDの下にあるものをキャプチャするには、次のことが必要になります。

//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>

target: #featureに注意してください。前の例のように、#featureはあなたのCSSセレクタです。これで、ページが読み込まれると、スクリーンショットがscriptタグと同じ場所に作成されるようになります。これには、div要素のすべての内容が含まれ、それ以外は含まれません。

Div-screenshotメカニズムにできる他の設定とカスタマイズがあります、それらをチェックしてください ここ

0
Stas

pdfMake.js および this Gist を使用します。

(Gist here パッケージへのリンクと一緒に html-to-pdfmake を見つけました。これは今のところ使用していません。)

npm install pdfmakeの後、htmlToPdf.jsにGistを保存すると、次のように使用します。

const pdfMakeX = require('pdfmake/build/pdfmake.js');
const pdfFontsX = require('pdfmake-unicode/dist/pdfmake-unicode.js');
pdfMakeX.vfs = pdfFontsX.pdfMake.vfs;
import * as pdfMake from 'pdfmake/build/pdfmake';
import htmlToPdf from './htmlToPdf.js';

var docDef = htmlToPdf(`<b>Sample</b>`);
pdfMake.createPdf({content:docDef}).download('sample.pdf');

備考:

  • 私の使用例は、マークダウンドキュメントから関連するhtmlを作成し( markdown-it を使用)、その後PDFを生成し、そのバイナリコンテンツをアップロードすることです(pdfMake 's getBuffer() function)、すべてブラウザから。生成されたpdfは、私が試した他のソリューションよりもこの種のhtmlの方が優れていることがわかりました。
  • 解決策は、HTMLの特殊文字によって混乱しやすく、明らかにマークアップの一種として解釈され、結果のPDFを完全に混乱させるため、受け入れられた回答で提案されたjsPDF.fromHTML()から得た結果に不満です。
  • キャンバスベースのソリューション(推奨されないjsPDF.from_html()関数など、受け入れられた回答の関数と混同しないようにする)を使用することは、生成されたPDFのテキストをキャンバスベースのソリューションはビットマップベースのPDFを生成しますが、貼り付け可能です。
  • md-to-pdf のようなpdfコンバーターへの直接マークダウンはサーバー側のみであり、私にとっては機能しません。
  • 生成されたPDFを表示したくないが、そのバイナリコンテンツをアップロードするため、ブラウザの印刷機能を使用しても機能しません。
0
ilmiacs

私はCSSレンダリングのためにjspdfとhtml2canvaseを使用し、これは私のコードですので私は特定のdivのコンテンツをエクスポートします

$(document).ready(function () {
    let btn=$('#c-oreder-preview');
    btn.text('download');
    btn.on('click',()=> {

        $('#c-invoice').modal('show');
        setTimeout(function () {
            html2canvas(document.querySelector("#c-print")).then(canvas => {
                //$("#previewBeforeDownload").html(canvas);
                var imgData = canvas.toDataURL("image/jpeg",1);
                var pdf = new jsPDF("p", "mm", "a4");
                var pageWidth = pdf.internal.pageSize.getWidth();
                var pageHeight = pdf.internal.pageSize.getHeight();
                var imageWidth = canvas.width;
                var imageHeight = canvas.height;

                var ratio = imageWidth/imageHeight >= pageWidth/pageHeight ? pageWidth/imageWidth : pageHeight/imageHeight;
                //pdf = new jsPDF(this.state.orientation, undefined, format);
                pdf.addImage(imgData, 'JPEG', 0, 0, imageWidth * ratio, imageHeight * ratio);
                pdf.save("invoice.pdf");
                //$("#previewBeforeDownload").hide();
                $('#c-invoice').modal('hide');
            });
        },500);

        });

;));

0

一つの方法はwindow.print()関数を使うことです。どのライブラリも必要としません

長所

1.外部ライブラリは必要ありません。

2.体の一部だけを印刷することもできます。

3. CSSの競合やjsの問題はありません。

4.Html/js機能をコアにする

---以下のコードを追加するだけです

_ css _ /

@media print {
        body * {
            visibility: hidden; // part to hide at the time of print
            -webkit-print-color-adjust: exact !important; // not necessary use         
               if colors not visible
        }

        #printBtn {
            visibility: hidden !important; // To hide 
        }

        #page-wrapper * {
            visibility: visible; // Print only required part
            text-align: left;
            -webkit-print-color-adjust: exact !important;
        }
    }

JSコード - / btnクリックでbewlow関数を呼び出す

$scope.printWindow = function () {
  window.print()
}

注:すべてのCSSオブジェクトで!importantを使用してください

例 -

.legend  {
  background: #9DD2E2 !important;
}
0
Rohit Parte