PythonでPDFに文字や画像を記入

トラストバンクといったら「ふるさとチョイス」が代名詞ではあるのですが、「ふるさとチョイス」以外にもいくつか事業を展開しております。
その1つに自治体専用ツール（LoGoチャット、LoGoフォーム）の開発・提供をしている事業部があります。

自治体専用ビジネスチャットツール「LoGoチャット」
https://publitech.fun/service_logochat
自治体専用WEBフォーム作成ツール「LoGoフォーム」
https://publitech.fun/service_logoform

今回は、このLoGoフォームで使われている「PDF作成機能」についてご紹介させていただきます

# 準備
とりあえず試したい方向けのDockerfile。これでPythonの環境ができあがり

```
FROM python:3.8.12-bullseye

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

RUN pip install -y pdfrw reportlab

WORKDIR /opt
```

# PDFに文字を書き出す

## 文字の書き出し
元のPDFファイルとなる「sample.pdf(A4縦)」を用意してください

```.py
from pdfrw import PdfReader
from pdfrw.buildxobj import pagexobj
from pdfrw.toreportlab import makerl
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import portrait, landscape, A3, A4, A5, A6, B3, B4, B5, B6

def make_pdf():
    file_in  = './sample.pdf'
    file_out = './sample_out.pdf'

    # 元のPDFを読み込み
    pages = PdfReader(file_in, decompress=False).pages

    # キャンバスのセット
    cc = canvas.Canvas(file_out, pagesize=portrait(A4))

    # ページ取得
    pp = pagexobj(pages[0])
    cc.doForm(makerl(cc, pp))

    # 文字書き出し
    cc.drawString(x=20, y=10, text='aaa')

    cc.showPage()
    cc.save()
```
これでPDFに文字が書き足されます！（左下にコッソリとｗ）
というのもこの「pdfrw」を使ったときの起点は **左下** になります
ですので表示したい位置を左下から計る必要があります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/246752c1-c2ae-2c33-13c2-076d012ddbf7.png) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/314d1111-2029-674d-4552-0429e6c020e9.png)

:::note warn
pdfrw で書き出すときの起点は左下
:::

## 指定位置への書き出し
書き出せたところで次は指定の位置に書き出してみたい
適当にx,yの引数を試して目的の場所に当たりをつけていくのでもいいですが、おおまかな位置だけでも測ってから微調整としたいところ

### 位置の測り方
今回は無料の[Acrobat Reader DC](https://get.adobe.com/jp/reader/) でのやり方

ツールの物差しを使って、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/1853215e-9eec-775d-6fd6-757818a9f044.png)

左下からの大まかな位置を確認します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/f5bbafe9-fe8c-9d8d-3b14-eecafc39e81e.png)

### 指定位置への書き出し
さきほどのソースの書き出し部分をこちらに変更

```.py
from reportlab.lib.units import mm

cc.drawString(x=19.97*mm, y=21.55*mm, text='aaa')
```

`drawString` のx,yは`px`での指定になるため「ものさし」で出てくる`mm`では単位があわない
そんなときは、`reportlab` に用意されている `mm` を使用
上記のように ミリメートルの値に `mm` を乗算することでの指定が可能になる
出力結果はこちら

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/cdb8771f-1a7c-047b-debd-7bbdb512cc89.png)

:::note warn
drawString の引数(位置指定)は px（ピクセル）
:::

指定の位置に文字が書けたらあとはこんなこともできるよという紹介を

## 文字の中央揃え、右揃え

中央揃え、右揃えで書き出すことが可能です

```.py
# 通常の左揃え(指定した位置から右に文字が記載される)
cc.drawString(x=40.00*mm, y=24.55*mm, text='aaa')
# 中央揃え(指定した位置を中心に左右に文字が記載される)
cc.drawCentredString(x=40.00*mm, y=24.55*mm, text='bbb')
# 右揃え(指定した位置から左に文字が記載される)
cc.drawRightString(x=40.00*mm, y=24.55*mm, text='ccc')
```

同じ引数でもそれぞれこんな出力になる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/efdd145b-0e44-104a-5cfd-7bb7122e919a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/17c174bd-5b7e-b5bc-74ca-b478aa8471cc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/1526a0d0-800a-28b7-5437-54e5c7efa3bc.png)

## 文字の色を変える

出力する文字の色をかえることも可能です

```.py
from reportlab.lib.colors import HexColor

cc.setFillColor(HexColor('#FF0000')) # RRGGBB で指定
cc.drawString(x=40.00*mm, y=24.55*mm, text='aaa')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/33b898db-761a-13ae-a829-27e720e3e219.png)

# PDFに画像を出力
画像の書き出しも可能で、このように書きます

```.py
image_path = './logo.png'
cc.drawImage(image=image_path, x=23.00*mm, y=245.00*mm, width=50*mm, height=50*mm, mask='auto')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92773/4c075b37-8d1d-550b-a96c-b82a77bb6b52.png)

ぜひいろいろと試してみてください