請求書のPDFからテキストを抽出して、報告フォーマットに当てはめる。

弊社では請求書のPDFをチャットツールで報告しています。

PDFを貼り付けて、内容を確認して、テンプレートに内容を書き込んで...

めんどくさい！！！！！

:bulb:

そうだ！全て自動化すればいいんだ！

ということで今回は請求書報告自動化に向けてどうすれば実装可能か手を動かしながら考えていきたいと思います。

## マイルストーン
おそらく以下に沿って実装すれば実現できるはず

1. PDF読み込み。テキスト抽出
2. 抽出したテキストから必要な文字列を抜き出す
3. フォーマットに当てはめる

それでは作っていきましょう

## 実装

### 0.　動かす環境を作る
環境を汚したくなかったので...phpが動けばいいのである方は割愛してください。

以下のファイルを作成

```sh:ディレクトリ構造
corp-approval-payment
├── docker-compose.yml
├── Dockerfile
└── index.php
```

```yml:docker-compose.yml
version: "3.9"
services:
  php:
    build: ./
    image: corp-approval-payment
    tty: true
    stdin_open: true
    volumes:
      - .:/var/www/html
    ports:
      - 8010:80
```

```Dockerfile:Dockerfile
# syntax=docker/dockerfile:1
FROM php:8.2.3-apache
ENV ROOT=/var/www/html
WORKDIR ${ROOT}
# composer install
COPY --from=composer /usr/bin/composer /usr/bin/composer
# git install
RUN apt-get update && apt-get install git-all
```

```php:index.php
<?php
    phpinfo();
```

以下を実行
```sh
$ cd corp-approval-payment
$ docker compose up -d
$ docker exec -it {container名} bash
$ php -v #確認
```

念の為アクセスできるかも確認

http://localhost:8010/

### 1.　PDF読み込み。テキスト抽出
今回使うライブラリ。ググったら出てきました。

https://github.com/smalot/pdfparser

```sh:ライブラリをインストール
$ composer require smalot/pdfparser
```

PDFを置くディレクトリを作成。とりあえず変換するPDFをsample.pdfとする
```diff_shell
corp-approval-payment
├── docker-compose.yml
├── Dockerfile
+├── pdf
+└── sample.pdf
└── index.php
```

サンプルはここから取得しました。

https://pdf.wondershare.jp/templates/invoice-template.html

```php:index.php
<?php
require 'vendor/autoload.php';

$parser    = new \Smalot\PdfParser\Parser();
$pdf       = $parser->parseFile('pdf/sample.pdf');
$firstPage = $pdf->getPages()[0];

echo nl2br($firstPage->getText());
```

出力結果
![スクリーンショット 2023-02-16 21.24.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/1a936007-b81c-b5b0-0980-6280b554ae66.png)

取れたね！

### 2.　抽出したテキストから必要な文字列を抜き出す

抽出したいテキストは支払先、金額、計上日、支払期限...etc。今回のサンプルには金額しかないのでこれだけ抽出します。他もロジックは同じなはず。
上記フォーマットの場合は¥32,400-が金額なので

```diff_php:index.php
-echo nl2br($firstPage->getText());
+preg_match_all('/¥(.+)-/', $firstPage->getText(), $match);
+echo $match[1][0];　// 32,400が表示される。
```

正規表現で抽出

### 3.　フォーマットに当てはめる
```diff_php:index.php
-echo $match[1][0];　
+$amount  = $match[1][0];
+
+// TODO: 〇〇のところもテキストを抽出して埋め込む
+$template = <<<EOM
+今月の請求になります。よろしくお願いいたします。
+```
+1)支払先 : 〇〇
+2)金　額 : {$amount}円
+3)予　算 : 通信費
+4)内　容 : 〇〇
+5)備　考 : 計上日 〇〇 / 支払期限 〇〇
+6)決裁者 : 〇〇
+```
+EOM;
+
+echo "<pre>{$template}</pre>";
```
![スクリーンショット 2023-02-16 22.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/311dcd0e-f0f0-3fe5-9158-731fc02a8658.png)

あとは変数を埋め込むだけ。全体のコードはこちら

https://github.com/nero-15/corp-approval-payment

## 感想
PDFからテキストを抽出することは出来ました。フォーマットは請求書によりけりなので、種類によってカスタマイズしないといけなさそう...そこを汎用的にしていければ


## 課題
スキャナーで取り込んだPDFが変換されないだと...
おそらく画像をそのままPDFにされてるため文字列のデータがない。その場合はPDFを画像に変換してからテキストを抽出して同じ処理をかければいけそうな気がする。ImageMagickとか使えばいけそうかな

## あとがき
５分の作業を5秒で終わらせるために2〜3時間かけました。エンジニアしてるね！

## 最後に運動通信社について
運動通信社は「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、一緒に働く仲間を募集しています！
PMやアプリエンジニア、Webエンジニアなど色んな職種を募集しておりカジュアル面談大歓迎なので是非採用フォームよりご連絡ください！
ぜひ一緒に、自分たちも世の中もワクワクするサービスを作りましょう！

https://sportsbull.jp/about/#recruit