ヘッドレスブラウザが搭載されたGoogle Chromeを使って、A4のラベルレイアウトに対応したPDFを作成してみました。

今回はChromeを操作できるNode.jsライブラリPuppeteerでPDFデータを作成していきます。A4などの用紙サイズに、ミリ単位で位置決めしたテンプレートを作成する際の参考になりましたら幸いです。

また過去に、PDF生成を活用した事例を書いていますので、興味がありましたらそちらもご覧ください。

目次

作成されるPDFデータの例

まず最初に結論を書きたいと思います。今回は、以下のような12個の印刷領域を持つPDFデータを作成してみたいと思います。

後半で解説する内容を実行すると、次のようなPDFが作られます。

生成されたPDFデータ
生成されたPDFデータ ©

領域を分かり易くするために、あえて背景を着色しています。

ラベルシールを例に取りましたが、レイアウトはミリ単位で作成可能です。自由度が高いので、応用次第ではExcelファイルを読み取って年賀状ハガキの住所印刷なども出来ます。

Excelを読み取る方法については以下をご覧ください。

ヘッドレスブラウザってなに?

ヘッドレスブラウザとはGUIを持たないインターネット閲覧ソフトのことです。UIを持たないため、コマンドラインや別のソフトから遠隔で操作する目的で使用します。

過去のヘッドレスブラウザには、PhantomJSや派生ソフトウェアとしてCasperJS、NightmareJSなどがありました。最近では、ブラウザの代表格とも言えるChrome59以降にヘッドレス機能が新たに搭載されたため、ヘッドレスChromeと呼んでいます。

ヘッドレスChromeで出来ること

ヘッドレスブラウザでは主に以下の用途で使用されます。

  • 作成したWebページの自動テスト
  • クローリングやスクレイピングなどの情報処理
  • Webページの画像化(キャプチャー)
  • WebページのPDF化

特にテストとスクレイピングと呼ばれるWebサイトの情報を処理する用途が多いです。私の場合はWebデータをPDF化する用途で使っています。

Puppeteerを使ってヘッドレスChromeからPDF生成

それでは、Puppeteerを使ってPDFを作成していきたいと思います。まずは、puppeteerとその他のプラグインをnpmインストールします。

bash
1
npm install --save puppeteer html-minifier
コマンドラインとnode.jsの環境の作り方

npmやコマンドラインについては別の解説記事をご覧ください。

続いてsample.jsを作成して、Node.jsのコードを記述します。まずは余白無しの単純なPDFを作成してみましょう。

sample.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const puppeteer = require('puppeteer')
const minify = require('html-minifier').minify // htmlを圧縮するライブラリ
const pdf = './sample.pdf' // 生成するPDFのファイル名
const html = `<html>
<body style="padding:0; margin:0; width:21cm;">
<div style="padding:0; margin:0; width:21cm; background:#FFF;">
印刷したい中身のデータはここに記述する
</div>
</body>
</html>`

(async() => {
// htmlの圧縮。PDF化するHTMLは圧縮しておくのがオススメ
const minified_html = minify(html , {
"removeComments" : true,
"caseSensitive" : false,
"collapseBooleanAttributes" : true ,
"collapseInlineTagWhitespace" : false,
"collapseWhitespace" : true ,
"conservativeCollapse" : false
})

// puppeteerでPDF生成
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.setContent(minified_html)
await page.pdf({
path: pdf ,
format: 'A4',
printBackground: 'true',
margin: {
top: '0mm',
right: '0mm',
left: '0mm',
botom: '0mm'
}
})

browser.close()
})()

印刷したい中身のデータについてはCSSでmarginWidthなどを使ってmm単位やcm単位でレイアウトしていく事ができます。印刷するHTMLデータに外部ファイルがあると、PDFのレンダリングが上手くいかない時があります。可能であればHTMLにCSSを直接記述する方法が確実です。

余白無しのA4サイズPDFを生成する時のポイント

ラベルや専用用紙を印刷する際には、余白が無いレイアウトを作成します。例えば、A4用紙で余白を持たないPDFデータを作成するにはpage.pdf()に次のオプションを指定します。

オプション名 値の指定例 オプションの説明
path '/sample.pdf' 生成するPDFの場所
format 'A4' 用紙サイズ
printBackground true CSSで指定された背景色を印刷するか否か
margin {top: '0mm', right: '0mm', left: '0mm', botom: '0mm'} 印刷領域の余白

こちらのオプションは、前述のサンプルコードで実際に指定していますので、ご覧ください。

印刷内容をミリ単位でHTMLレイアウトする

前述しましたが、PDF化するHTMLのデータはミリ単位やセンチメートル単位でレイアウトが可能です。

sample.jsの抜粋
1
2
3
4
5
6
7
const html = `<html>
<body style="padding:0; margin:0; width:21cm;">
<div style="padding:0; margin:0; width:21cm; background:#888;">
${labelData}
</div>
</body>
</html>`

例えば、こちらの12個のラベルシールのようなレイアウトを作成するには、次のような記述で生成できます。

label12.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const labelData = `
<div style="padding:20.3mm 14.5mm 22.9mm 20.3mm; margin:0;">
<div style="margin:0;">

<!-- (ラベルの数だけ記述する。※最大12個まで) -->
<div style="display:inline-block; width:83.8mm; height:42.3mm; margin: 0 3.8mm 0 0; background:#DFD; position:relative;">
<div style="position:absolute; width:83.8mm; height:42.3mm;">

ラベルに印刷したい文字列などをここに記述する

</div>
</div>

</div>
</div>`

上記のようなHTMLをPDF化すると、次のような結果となります。

生成されたPDFデータ
生成されたPDFデータ ©

冒頭でも触れましたが、ラベルシールの12個の印刷領域が確かに作られていますよね。

参考にさせて頂いた記事

ヘッドレス chromeでpdfを生成 - Chrome

ヘッドレスブラウザの Puppeteer を利用して WEB ページを PDF 出力してみる - Qiita