[Python]画像を連番付きでラベルシートに印刷するためのPDFを作成するスクリプト

## はじめに

QR画像を連番付きで大量印刷する必要があったので、Pythonの[reportlab](https://www.reportlab.com/)というライブラリを活用して作成しました。

ローカル環境でのその作成方法とスクリプトをまとめておきます。

※本記事ではスクリプトの全体を載せていますが、解説については長くなってしまうので省略しています。別記事で整理したいと思います。

## やりたいこと

印刷する用紙としては、こちらの**「[エーワン ラベルシール 品番72312](https://item.rakuten.co.jp/bungle/72210/)」**を使いました。
名刺サイズの１０枚組のもの。

![image-20211124234520642.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499640/d4159432-6e47-e843-6f85-eb0fcb76dc65.png)

このラベルに合わせて、QRを連番付きで印刷するためのpdfファイルを作成します。
以下が完成形のpdfです（QRはダミー）。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499640/b0255115-5a08-fa3c-9e8b-73b469d05b94.png" width="50%">


今回の記事では、このような1枚だけのpdfを作成する流れをまとめています。

いくらか汎用性のあるスクリプトにしているので、数値を変えれば違う様式のラベルシートにも対応しているハズです。
また、複数ページにまたがるpdfを作成することもできますが、今回のスクリプトをもう少し応用する必要があります。

## 今回使用するPythonライブラリについて

Pythonの標準ライブラリとしては、パスを扱う`Pathlib`を使用します。

サードパーティーライブラリとして、`ReportLab`と`Pillow`の二つを使用します。

### 1. ReportLab

- [公式サイト](https://www.reportlab.com/)
- [ドキュメント](https://www.reportlab.com/docs/reportlab-userguide.pdf)

Pythonで様々なpdf生成ができるライブラリです。
ReportLab PLUSという有料プランがあるようですが、今回は無料版を利用して、簡単なテキスト、図形、画像を配置したpdfを生成します。

### 2. Pillow

- [ドキュメント](https://pillow.readthedocs.io/en/stable/)

Pythonで画像を扱うためのライブラリです。こちらもちらっと使用します。



## 準備

### 1. プロジェクトディレクトリの構成

まず、今回のプロジェクト用のディレクトリを準備しておきます。

適当なプロジェクト名をつけたディレクトリ（ここでは`pdfMaker`）を作成し、その中にQR画像用のディレクトリ（`img`）を用意しておきます。

Pythonのスクリプトファイル（`.py`や`.ipynb`）もこのディレクトリの中に作成します。

こんな感じのディレクトリ構造になっていればOKです。

> pdfMaker/
> ​	├  img/			* 画像を格納するためのディレクトリ
> ​	└ code.py		* Pythonスクリプトファイル

### 2. QR画像の準備

先ほど作成した`img`ディレクトリの中に、使用するQRの画像を用意しておきましょう。

ファイル名は`番号.pdf`という名前で連番を振っておきます。

このファイル名をそのままpdfにテキスト出力させていくので、余計な文字列は入れないようにします。

番号ではなく出力させたい文字列をファイル名にしても良いですが、Reportlabで日本語フォントを指定する必要があるのでやや注意が必要です。

英数字のみだと表示させやすいですね。

今回はダミーデータを10枚用意しておきました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499640/a622e146-cc61-5a05-fef3-4c30ac125b87.png" width="50%">

### 2. ライブラリのインストール

環境に応じて、必要なライブラリ（reportlab, Pillow）をインストールしておきます。

`pip list`で確認して既にインストールされているなら不要です。



ライブラリのインストールは通常、`pip install ライブラリ名`もしくは`pip3 install ライブラリ名`で行います。

anaconda使用時の場合は`conda install` ライブラリ名で行います。

この辺りは環境によって違うので注意が必要です。

例）
`pip install Pillow`
`pip install reportlab`

## 実装

### 全体のスクリプト

以下が全体のスクリプトになります。

```python
from pathlib import Path
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4

# 画像ファイルのパスとファイル名（=連番）をタプルで用意する
_images = tuple(Path('./img').glob('*.png'))
images = tuple(sorted(_images))
images_name = tuple(map(lambda im: im.stem , images))

# （※１）ラベルシートの設定
cards_num= (2, 5)  # カードをA4に何枚配置するか（横の枚数, 縦の枚数）
A4_mm = (210, 297)  # A4用紙のサイズをmmで指定(横、縦)
card_mm = (86.4, 50.8)  # 1枚のラベルのサイズをmmで指定(横、縦)
margin_mm = (18.6, 21.2) # 余白をmmで指定(左右、上下)

to_px = A4[0] / A4_mm[0] # mmをpxに変換
card = tuple(( x * to_px for  x in card_mm )) # カードのサイズpx
margin = tuple(( x * to_px for  x in margin_mm )) # 余白のサイズpx

# （※２）A4のpdfを作成する
file_name = 'sample.pdf'
page = canvas.Canvas(file_name, pagesize=A4)

page.setLineWidth(3)  # 線の太さを指定
page.setFont('Helvetica', 80)  # ページのフォントを指定

pos = [margin[0], margin[1]] # 描画の初期地点
i = 0

# A4のpdfに必要なものを描画する
while  (i < cards_num[0] * cards_num[1]):
        for y in range(cards_num[1]):
            for x in range(cards_num[0]):

                # （※３）図形（長方形、直線）とテキストの描画
                page.rect(pos[0], pos[1], card[0], card[1]) 
                page.line(pos[0] + card[0]/12, pos[1] + card[1]/4, pos[0] + card[0]/2 - 5, pos[1] + card[1]/4)
                page.drawString(pos[0] + card[0]/12, pos[1] + card[1]/4 + 5, images_name[i])

                # （※４）画像の挿入
                image = Image.open(images[i])
                page.drawInlineImage(image, pos[0] + card[0]/2 - 5, pos[1] + card[1]/12, width=card[0]/2, height= card[0]/2)

                i += 1
                pos[0] += card[0]

            pos[0] = margin[0]
            pos[1] += card[1]

# PDFファイルを保存
page.save()
```

### スクリプトのカスタマイズ方法

（※１）部分の4つの変数は、ラベルシートの規格に対応しています。
別の規格のラベルシートに印刷したい場合は、この4つの変数を変更することで可能になります。
`card_num`に何枚×何枚でラベルが配置されているのかをタプル`(横の枚数, 縦の枚数)`で指定し、
`A4_mm`、`card_mm`、`margin_mm`にそれぞれA4サイズ、１枚のラベルのサイズ、余白をそれぞれmm値のタプル`(横, 縦)`で入力してあげます。

（※２）以下が、reportlabを使ってpdfを作成していく具体的な処理になっています。
変数`file_name`で保存するpdfのファイル名を変更したり、描画する図形の線の太さやフォントの変更など必要に応じて変更することができます。

（※３）（※４）の部分で、図形描画やテキスト、画像の配置を行なっています。
`reportlab`では配置位置をpx単位で指定できるので、それらをここで指定して調整することができます。
（本記事ではあまり解説できないので、[ドキュメント](https://www.reportlab.com/docs/reportlab-userguide.pdf)と照らし合わせてご覧いただけたらと思います。）
変数`card`には先ほどmmで指定したラベルサイズがpx値のタプルに変換されて入っているので、配置位置の指定や画像のサイズ指定にはこの値を利用しています。
直接px値で指定もできるので、手持ちの画像に応じてちょうど良い配置を探してみてください。


## おわりに

１枚のラベルシートに印刷するためのPDFファイルの作成方法とスクリプト全体を紹介しました。

スクリプトの解説が足りないので、これだけだとカスタマイズのやり方が難しいかと思います。詳細につきましては別で解説記事を書きたいなと思っています。