Power Automate DesktopでPDFのページ数を取得するのは難しい
Power Automate DesktopでPDFのページ数を取得するのは容易ではないという話です。
PDFをページごとに処理するにはページ数が必要
銀行のサイトから計算書を取得しました。1ページ1件で複数ページあります。このファイルから1件ごとにデータを取得したいと思います。
「PDFからテキストを抽出」アクションを使ってループ内で1ページごとデータを取得して処理しようと思いました。
ループを使うにはファイルのページ数が必要です。簡単にPower Automate Desktopで取れるのだろうと思ったらなんとそのような方法が見つかりませんでした。
ありえないページ数を最大値に指定して、見つからなかったらエラー処理という方法も考えられますが好きではありません。
ExtractedPDFTables.Countを使用
丁度今月リリースされたPower Automate Desktop 2.17 には「PDFからテーブルを抽出する」というアクションが追加されています。
このアクションで取得されたデータの Count プロパティを使うとファイルに含まれるテーブル数を取得できます。
今回のPDFファイルは1ページに1つテーブルが含まれていたため、これを使って取得することができました。
例:ExtractedPDFTables.Count
アクションの実行に時間はかかるものの、今回の件では確実にページ数を取得でき、正しく処理できました。
PDFから直接ページ数を取得するのは容易ではない
PDFファイルを直接読み込んでページ数を取得できるのではと思いました。
しかし、実際にはバージョン違い等があって、容易ではないようです。
EXCEL VBA AcrobatReaderやAdobeを使わずにPDFのページ数を取得する方法
自社で作ったPDFならバージョンやフォーマットがある程度特定できるのでこういった方法も一つだと思います。
しかし、いろんなところからくる請求書を処理するような場合、いつどんなデータがくるのかわかりません。
Power Automate DesktopでPDFのプロパティを取得できるアクションが欲しいと思いました。
試してみると
次のページにVBAでページ数を取得する方法が紹介されていました。
ExcelVBAのみでPDFファイルのページ数を取得する Qiita
PDFファイルの構造上、「/Count 」はソーステキストに1回しか出現しないこと、通常表示される文字列はStreamオブジェクト内に圧縮されているため正規表現にマッチしないことからページ数の抜き出しが可能となっています。
と書かれています。
そこでPower Automate Desktopに移植してみました。
コピーしたコードは次の通りです。Power Automate Desktopの編集画面に貼付すれば復元できます。
Display.SelectFileDialog.SelectFile FileFilter: $'''*.pdf''' IsTopMost: True CheckIfFileExists: False SelectedFile=> SelectedFile ButtonPressed=> ButtonPressedページ数はSubtext変数に入ります。
実行してみたところExcelから出力したファイルは取得できました。
しかし、家電製品等の取説などは軒並みだめでした。
まずソニーの取説はCountが見つかりませんでした。Encryptという文字があったので暗号化されているようです。もしかしたらそのせいかもしれません。
Chromeで保存したと思われるPDFは次のように複数のカウントがありました。
223 0 objこれは、ページカウントオブジェクトが階層化されているようです。
この場合 /Parentがないオブジェクトを探し出して処理する必要があります。
少しトライしてみましたが容易ではありませんでした。
/Type /Pagesと/Countの順番が入れ替わっている場合もあるようです。
各キーワードのデリミターもスペースの場合と改行の場合もあります。改行はCRなのかLFなのか、CRLFなのかも考える必要があります。
存在しないページを指定してもエラーが発生しない
好きではないけれど、エラーが発生したらおしまいという方法も試してみようと思いました。
ところが、ループで「PDFからテキストを抽出」アクションを繰り返して、存在しないページに達してもエラーは発生しませんでした。
そしてExtractedPDFTextには最終ページのテキストが入るようです。直前でExtractedPDFTextをクリアしても挙動は一緒でした。
これは困りました。
ファイル分割ではエラーが発生
仕方がないのでファイル分割を試したところ、さすがにこちらはエラーが発生しました。そのため、「ページが範囲外です」エラーが発生したらループを抜けるというフローを書いてみました。
ループ中で、「新しいPDFファイルへのPDFファイルページの抽出」アクションにページ数(LoopIndex)を指定しながら実行します。存在しないページを指定するとエラーが発生するので、LoopIndexから1引いた数がページ数です。
コードは次の通りです。
デスクトップフローとして部品化してもよいかもしれません。
実際に使うとなると、分割ファイルのパスについて考慮が必要です。固定ファイルにするのか、一時ファイルとして処理するのか。分割ファイルの最後は削除するのかどうかも考慮する必要があります。他のエラーが発生したときのTry Catchも必要でしょう。
ページ数が最大値に達したときの処理も必要かもしれません。ありえないページ数にしておけば現実的には問題ありませんが。
コメント
コメントを投稿
間違いがあればコメントを頂けるとありがたいです。