公開日:2022.10.18 最終更新日:2024.03.28
この 記事では、 PAD で 請求書PDFを テキスト化する 方法と、 JavaScriptを 実行する 時の ハマり ポイントを 紹介します!
請求書って、 毎月、 毎月処理が あるので 大変ですよね。 自分の 話で いいますと、 AWSの 請求書から、 各アカウント(各事業部)が それぞれいくら 使ったのかを 集計しなくちゃ いけない のですが、 その 請求書PDFが、 1ファイル数十ページ、 数十ファイルとか あるので、 自動化するまでは、 かなり 大変でした。
例えば、 AWSの 請求書PDFを PAD で テキスト化して、 さらに 正規表現を 使って、 ちょっとした 加工を 行うと、 こんな 感じのtsvファイルが 一発で 出力できちゃいます。
AWSアカウント
利用料
消費税
hogehoge-AmiVoice00 (012345678900)
$1,234,567.89
$123,456.78
hogehoge-AmiVoice01 (012345678901)
$123,456.78
$12,345.67
…
…
…
hogehoge-AmiVoice99 (012345678999)
$0.12
$0.01
正規表現は、 請求書の 種類ごとに 作る 必要が ありますが、 1度作ってしまえば、 毎月の 手間が なくなります!
目次
はじめに
1. 全体フローの解説
2. 各アクションの解説とハマりどころ
おわりに
はじめに
PAD(Power Automate Desktop)について
PADとは、 Power Automate Desktopの 略称で、 RPA(Robotic Process Automation) ツールの ひとつです。 Microsoft社が 2021年3月から 無償で 提供しています。 PADを 使えば、 プログラミングの 知識を 持っていない 方でも、 ノーコード・ローコード開発で 自動化アプリが 簡単に 作れます。PADは、ここからダウンロード できます。
実践するとできるようになること
・PDFを テキスト化 (※今回の記事では 手書きPDFは 想定外です)
・PADでJavaScriptを 実行 (ハマりどころを 公開してます)
・ 日常業務を 自動化(他の 重要な 仕事に 専念できる 時間が 増えます)
実践するために必要なものリスト
・PADを 実行できる 環境 (執筆時の バージョン:2.23.114.22217)
・テキスト化したいPDF
1. 全体フローの解説
全体フローの完成形はこんな感じ
最初に 処理開始~処理終了までのざっくりとした 流れを 解説します。
請求書PDFテキスト化の全体フロー
アクション①:フォルダー内の ファイルを 取得
⇒指定フォルダー内に あるPDFを 探します。
アクション②:For each(ループ)
⇒各PDFごとに ループ内の アクションを 繰り返します。
アクション③:PDFから テキストを 抽出
⇒PDFを テキスト化します。
アクション④:テキストを 置換する
⇒JavaScriptを 実行する 際に 不都合な 文字を 置き換えます。
アクション⑤:正規表現の エスケープテキスト
⇒JavaScriptを 実行する 際に 不都合な 特殊文字を 置き換えます。
アクション⑥:JavaScriptの 実行
⇒JavaScriptを 実行します。 (ここに 正規表現を 記述します)
アクション⑦:テキストを ファイルに 書き込む
⇒JavaScriptの 実行結果を ファイルに 保存します。
アクション⑧:ファイルの 移動
⇒テキスト化済みのPDFを 指定フォルダー内に 移動します。
アクション⑨:End(ループ)
⇒PDFが 他にも あれば②に 戻ります。 なければ ループ終了。
簡単に まとめますと、 指定フォルダー内に ある、全てのPDFを テキスト化 (JavaScriptの 実行結果を 保存)し、 処理が 終わったPDFを 別の フォルダーに 移動させる。 です。
2. 各アクションの解説とハマりどころ
アクション①:フォルダー内のファイルを取得
まずは、 テキスト化したいPDFの 一覧を 取得しましょう。
■アクション『フォルダー』 ⇒『フォルダー内のファイルを取得』
フォルダー:フォルダー内のファイルを取得
「フォルダー」:
テキスト化したいPDFのPath(保存場所)を 指定します。 例は、 AWS請求書の 中のAWS Incを 指定しています。
「ファイルフィルター」:
この 欄に *.pdf と 入力すると、 拡張子が .pdfである 全ての ファイルの Path一覧を 取得できます。
「フロー変数 Files 」:
この 変数に 検索で ヒットした ファイルの Path一覧が 入ります。
これで テキスト化したいPDFのPath一覧が 取得できます。
アクション②:For each(ループ)
次に、 テキスト化したいPDFが 複数あった 場合に 備えて、 各PDFごとに 処理を 繰り返すための ループを 設定しましょう。
■アクション『ループ』 ⇒『For each』
ループ:For each
「反復処理を 行う 値」:
PDFのPath一覧を 指定します。 この 欄に フロー変数 %Files% と 入力します。 PADの アクションの 中で 変数を 指定する 時は、 両端を % で 挟んだ 変数名を 入力する 必要が あります。
「フロー変数 CurrentItem 」:
この 変数に 1つのPDFのPathが 入ります。 処理が 繰り返されるたびに、 次のPDFのPathに 入れ替わります。
これで 各PDFごとに 処理を 行う 用意が できました。
アクション③:PDFからテキストを抽出
では 本題に 入って、 PDFを テキスト化してみましょう。
■アクション『PDF』 ⇒『PDFからテキストを抽出』
PDF:PDFからテキストを抽出
「PDFファイル」:
PDFのPathを 指定します。 この 欄に フロー変数 %CurrentItem% と 入力します。
「フロー変数 ExtractedPDFText 」:
この 変数に PDFから 抽出した テキスト情報が 入ります。 実は、 これだけでPDFの テキスト化が 完了します。
単に請求書PDFを テキスト化 したいだけ の場合は、【アクション⑦:テキストを ファイルに 書き込む】 に 移動可能です。 あとは、 フロー変数 %ExtractedPDFText% を 「書き込む テキスト」に 入力し、 保存場所を 決めるだけです。
テキスト化後に、 CSV形式や TSV 形式に 整えたい 場合には、 スクリプト (今回はJavaScript)で 正規表現を 使うと 便利です。
アクション④:テキストを置換する
PADでJavaScript等の スクリプトを 実行する 時には、ハマりポイント が いくつか 存在しています。 その 落とし穴を 回避する ために、 ちょっとした 工夫が 必要です。 このアクションでは、 JavaScriptを 実行する際に 不都合な文字を 置き換えます。 この例では、 フロー変数 %ExtractedPDFText% に 含まれる ” を 削除しています。
■アクション『テキスト』 ⇒『テキストを置換する』
テキスト:テキストを置換する
「解析する テキスト」:
テキスト情報が 入っている 変数を 指定します。 この 欄に フロー変数 %ExtractedPDFText% と 入力します。
「検索する テキスト」:
置き 換えられる テキストを 指定します。 この 欄に ” と 入力します。 (ダブルクォーテーション1つです。)テキスト情報に ” と ‘ の 両方が 含まれている 場合、どちらか 片方を 削除しないと スクリプトに その 変数が 渡せません。 理由は、 【アクション⑥:JavaScriptの 実行】 で 紹介します。 今回は ” の 方を 削除する ために 入力しています。
「置き 換え 先の テキスト」:
置き 換える テキストを 指定します。 この 欄に %”% と 入力します。 (シングルクォーテーション2つです。) これは、 削除したい (何も ない 状態に 置換したい) 場合に 使います。この 欄に 何も 入力しなかった 時は、 下記の エラーに なります。 (パラメーター’置き換え先のテキスト’: 空にできません。)
「フロー変数 Replaced 」:
この 変数に 削除処理が 完了した テキスト情報が 入ります。
これで テキスト情報に 含まれる ” を 削除できます。
アクション⑤:正規表現のエスケープテキスト
ハマりポイント は、 まだあります。 もうひと工夫が 必要です。 このアクションでは、 JavaScriptを 実行する際に 不都合な特殊文字を 置き換えます。
■アクション『テキスト』 ⇒『正規表現のエスケープテキスト』
テキスト:正規表現のエスケープテキスト
「エスケープする テキスト」:
エスケープする テキストを 指定します。 この 欄に フロー変数 %Replaced% と 入力します。テキスト情報に 文字に なっていない 改行が 含まれている 場合、スクリプトに その 変数が 渡せません。 ここで 改行を 文字の 改行 \n に 置換(エスケープ) します。【アクション:テキストを 置換する】では、 \n に 置換できません。
「フロー変数 EscapedText 」:
この 変数に 置換処理が 完了した テキスト情報が 入ります。
これで テキスト情報に 含まれる 改行を 文字の 改行に 置換できます。
アクション⑥:JavaScriptの実行
JavaScript等の スクリプトを 実行する 前処理が やっと 完了したので、 気を 取り直してJavaScriptを 実行しましょう。
■アクション『スクリプト』 ⇒『JavaScriptの実行』
スクリプト:JavaScriptの実行
「実行するJavaScript」:
JavaScriptの ソースコードを 指定します。 この 欄に JavaScriptの ソースコードと 入力します。 ソースコードは、 請求書の 仕様に 応じて 正規表現を 作ってください。
PADで 定義した 数値型の 変数を JavaScriptに 渡す 時は、 %hogehoge% で 渡すことができるのですが、テキスト型の 変数を 渡す時は、 両端を ” 又は ‘ で 挟んだ 変数名、”%hogehoge%” 又は ‘%hogehoge%’ で 渡す 必要が あります。 これらのように 記述しなかった 時は、 下記の エラーに なります。 (Microsoft JScript コンパイル エラー: 文字が 正しく ありません。)テキスト情報に ” が 含まれていなければ、 “%hogehoge%” で、 ‘ が 含まれていなければ、 ‘%hogehoge%’ で 渡せます。
【 アクション④:テキストを 置換する】 で 回避した、 テキスト情報に ” と ‘ の 両方が 含まれている 場合、 どちらか 片方を 削除しないと エラーに なる 理由ですが、両端を ” 又は ‘ で 挟んだ 変数名で 渡す 必要が あるので、 両方が 含まれていた 時は、 下記の エラーに なります。 (Microsoft JScript コンパイル エラー: ‘;’ が ありません。等)
JavaScriptの 中で 変数の 宣言を 行う 時は、 var 、 let 、 const が 使えません。 これらを 記述した 時は、 下記の エラーに なります。(Microsoft JScript コンパイル エラー: ‘;’ が ありません。 等)
JavaScriptの 実行結果を 出力する ために、 WScript.Echo() や WScript.StdOut.Write() が 利用できます。 WScript.Echo() は、 改行ありの 出力で、 WScript.StdOut.Write() は、 改行なしの 出力です。
「フロー変数 JavascriptOutput 」:
この 変数に JavaScriptの 実行結果 (正常時)が 入ります。
「フロー変数 ScriptError 」:
この 変数に JavaScriptの エラー内容 (異常時)が 入ります。
これでPADでJavaScriptを 実行する ことができます。
アクション⑦:テキストをファイルに書き込む
では、 JavaScriptの 実行結果を ファイルに 保存しましょう。
■アクション『テキスト』 ⇒『テキストをファイルに書き込む』
テキスト:テキストをファイルに書き込む
「ファイルパス」:
保存場所の Path(ファイル名も)を 指定します。 例は、 AWS請求書の 中のAWS Inc.tsvを 指定しています。 ※tsv形式でもcsv形式でも 正規表現を 使うと 簡単に 作れます。
「書き込む テキスト」:
保存したい テキスト情報を 指定します。 この 欄に フロー変数 %JavascriptOutput% と 入力します。 ※JavaScript(正規表現)を 使わずに 済んだ 場合には、 この 欄に フロー変数 %ExtractedPDFText% と 入力します。
「新しい 行を 追加する」:
テキスト情報を 書き 込んだ 後に 改行を 入れるかを 指定します。 オンでも オフでも お好きなように。
「ファイルが 存在する 場合」:
既存の 内容を 上書きするか、 末尾に 追記するかを 指定します。 今回は ループの 中で 書き込む 仕様なので、 内容を 追加するを 選択します。
これで 保存したい テキスト情報を ファイルに 保存できます。
アクション⑧:ファイルの移動
テキスト化済みのPDFを 別の フォルダー内に 移動させて管理したい 場合には、 これを 使います。
■アクション『ファイル』 ⇒『ファイルの移動』
ファイル:ファイルの移動
「移動する ファイル」:
PDFのPathを 指定します。 この 欄に フロー変数 %CurrentItem% と 入力します。
「宛先フォルダー」:
移動させる ファイルの Path(保存場所)を 指定します。 例は、 AWS請求書の 中のAWS Inc_処理済を 指定しています。
「ファイルが 存在する 場合」:
既存の 内容を 上書きするか、 なにもしないかを 指定します。 基本的には、 上書きを 選択します。 (お好きなように)
これで テキスト化済みのPDFを 別の フォルダーに 移動できます。
アクション⑨:End(ループ)
『アクション②:For each』を 設定すると、 自動的に 追加されます。 テキスト化してないPDFが 他にも あれば②に 戻って ループします。 全てのPDFの 処理完了で、 ループ(フロー全体)が 終了です。
おわりに
いかがでしたか? テキスト化できましたでしょうか? 初回の 設定は、 ちょっと 大変だったかもしれませんが、 これらを 業務フローに 応じて カスタマイズしていけば、 毎月の 請求書処理が ワンクリックでできると 思います。
あの手先
ポチポチするだけで大半の仕事を遂行できるように、
業務自動化・RPA・MAの領域で、日々試行錯誤しています。