この記事は作成編です。
実際にフローを動かした結果は次の記事をご覧ください。
書類整理って大変…!!
日々、仕事をしているとどうしても書類を整理する場面が出てきますよね?
自部署では、取引先から送られてくる書類を部署メンバーDさん、事務スタッフEさんと一緒に所定の共有フォルダを使用し整理しています。
これが、地味ですが手間と時間がかかり、負担が大きい作業となっていました。
一つの書類を所定のフォルダに保存するだけで、これだけの手順を踏む必要があります。
これが何十枚もあると考えると…考えたくないですね…
さらに手作業で実施することのリスクとして、
- リネーム時の転記ミス
- 格納するフォルダの選択ミス
- 担当者不在による業務ストップ
などが挙げられます。
書類仕分けの自動化をすることで、これらの課題を解決できるのではないかと考えました。
今回は、上記の例をもとに、どうしても人がする必要のある「1.押印済みの注文書をスキャン」より後の項目の自動化フローを作成してみました。
使用したツール
Power Automate Desktop
GPT-5.5
Gemini 3.5 Flash
生成AIはフロー構成の相談として使用しました。
Power Automate Desktopの構成
ここでは、各プロセスごとに説明していきます。
0.事前準備
0-1.Power Automate Desktopを使える状態にする
Power Automate Desktopを起動し、「新しいフロー」をクリックします。

0-2. ブラウザ(GoogleChrome)の拡張機能の設定
これによって、Power Automate Desktopがブラウザを正確にコントロールできるようになります。
フロー作成画面の「ツール」→「ブラウザー拡張機能」→「Google Chrome」の順にクリックします。

↓のポップアップが出ますので、「拡張機能を追加」をクリックします。

ブラウザの拡張機能を確認して、「Microsoft Power Automate」が追加されていればOKです。

1.押印済みの注文書をスキャン
社判が押印された注文書を、社内の複合機を使ってスキャンします。
ここは人の手を使って実施する部分ですので、自動化からは除外します。
2.ダウンロードページにアクセス
ここからPower Automate Desktopを使って自動化していきます。
2-1. スキャンデータを確認するページにアクセス
新しいChromeを起動するアクションを追加します。

スキャンデータをブラウザ経由で見に行くので、「初期URL」にはそのページのURLを入力します。
画面のサイズによって、クリックしたい領域が表示されない可能性を潰すために、「ウインドウの状態」は最大化を選択します。
ここで、開いたブラウザは「Browser」という名前で変数として生成されます。
2-2. 該当のスキャンデータのダウンロードページへの遷移
Webページのリンクをクリックアクションを追加します。

UI要素の右のプルダウンメニューをクリックすると、以下の表示となりますので、「UI要素の追加」をクリックします。

ブラウザ上のクリックしたい場所にカーソルを合わせると、以下のように赤い枠が表示されるので、「Ctrl + クリック」します。

同様にWebページのリンクをクリックアクションを追加し、該当のPDFファイルのダウンロードページまで進みます。

3.PDFでダウンロード
3-1. ダウンロードボタンをクリック
Webページのリンクをクリックアクションを追加します。
直前にスキャンしたファイルの項目内の「PDF」をUI要素追加します。

3-2. 「名前をつけて保存」ウィンドウを表示させる
ウィンドウを待機するアクションを追加します。
「ウィンドウの検索」はウィンドウのUI要素ごとに設定。
「ウィンドウ」はUI要素を追加し、直前に表示された「名前をつけて保存」ウィンドウを指定します。

ウェブページのリンク同様、環境によってウィンドウの表示にタイムラグが発生します。
ウィンドウが表示される前に次のアクションに移ってしまうとエラーが発生するため、それを防ぐためのアクションです。
3-2. 保存先とファイル名を指定して保存する
キーの送信アクションを追加します。
ファイルを保存する際の保存先とファイル名を指定するため、ファイル名欄にファイルパスを入力します。
今回はローカルのダウンロードフォルダに「【注文書】.pdf」という名前で保存することにしました。

続けてキーの送信アクションを追加し、エンターキーを押すことで、ファイルを保存します。

自社の設定上、保存するボタンを押すと以下のように表示されます。

カーソルを「保存」に合わせるため、キーの送信アクションを追加し、Tabキーを4回押下するよう設定します。

{Ctrl}のように{}で囲われているキーは、実際にその通りに入力されるわけではなく、そのキーを押下するときに使われます。
保存するボタンをクリックした後は、データの書き込みに時間がかかる可能性があるので、待機時間を入れたほうが安全です。
3-3. 不要なウィンドウを閉じる
今後のフローを動かすために、不要なウィンドウを閉じておきます。
ダウンロード時に表示されたウィンドウを閉じるため、ウィンドウを閉じるアクションを追加します。

さらに、ダウンロードページを表示していたブラウザも閉じます。
Webブラウザーを閉じるアクションを追加し、ブラウザを閉じます。

最初に生成された「Browser」というブラウザを閉じるというアクションになります。
4.ファイルを開く
4-1. ダウンロードしたファイルをPDFビューアで開く
中身の情報を読み取るために、まずは該当のファイルを画面上に表示させます。
アプリケーションの実行アクションを追加し、開きたいファイルのパスを入力します。
前述の理由でウィンドウスタイルは最大化しておきます。

さらに、ファイル内の文字以外を誤って読み込まないよう、PDFビューアをフルスクリーンモードに変更します。
キーの送信アクションを追加し、フルスクリーンモードのショートカットキーである「Ctrl + L」を入力します。

さらに文字を読み込みやすいよう表示を拡大します。
キーの送信アクションを追加し、拡大のショートカットキーである「Ctrl + +」を入力します。

{Add}は「+」と同義です。5回繰り返すことで、拡大ボタンを5回押すことになります。
今回のPDFファイルは画像としてスキャンされているもので、テキスト化されていません。
この後のフローで画像からテキストを抽出するために、画面上にできるだけ大きく表示しておくと、正しく文字を読み取りやすくなります。
5. 「内容」と「日付」を確認
5-1. 「内容」をテキストとして読み込む
5-1-1. 画面上に表示された文字を抽出する
今の画面上には、PDFビューアで大きく注文書が表示されています。
この画像データから文字データを抽出するツールとしてOCRという技術があります。
Power Automate Desktopでは、OCR機能をアクションとして使用することができます。
OCRを使ってテキストを抽出アクションを追加します。

今回は日本語を読み取る精度が比較的高いとされる「WindowsOCRエンジン」を使用していきます。
読み取る画面は「フォアグラウンドウィンドウ」(アクティブなウィンドウのこと)とし、言語を「日本語」に合わせておきます。
ここで読み取ったテキストデータは「OcrText」という変数に入ることになります。
5-1-2. 抽出したテキストデータをリストに変換する
今回抽出したいのは、注文書の中の「○○店様○○機器設置」という文言です。ここに記載されている文言は、この注文書のタイトルにあたるものですので、注文書ごとに変化します。
逆にその上段にある「ご提案システム」という文言は、この取引先の全ての注文書に当てはまるものですので、「ご提案システム」という文言が含まれる行の次の行を抽出すると、「○○店様○○機器設置」が切り抜けることになります。
OCRで抽出した文字列をリスト化することで、読み取ったテキストデータを行で認識することができるようになります。
テキストの分割アクションを追加し、読み取った「OcrText」を分割し、リスト化します。
リスト化したデータは、「TextList」という変数に入ります。

5-1-3. リスト化したファイルから特定の行を抽出する準備
このあと、該当行の抽出を行うために必要な変数(値の入れ物)を準備します。
変数の設定アクションを追加し、「GetNext」という変数に「False」という値を入れておきます。

同じように、変数の設定アクションを追加し、「NerVar」という変数に「''」という値を入れておきます。

本来「NewVar」には何も入れず空欄でいいのですが、設定上何か入力しないとエラーになってしまうので、空欄を意味する「''」を入力しました。
5-1-4. リスト化したファイルから特定の行を抽出する
ここでは、リスト化したテキストデータを1行1行チェックし、「ご提案システム」という文言が入っている行を探し当てます。
For eachアクションを追加し、反復処理を行う値を「TextList」に設定することで、このアクションを行うたびに変数「CurrentItem」に「TextList」が1行ずつ書き換わることになります。

変数「GetNext」にtrueが入っていた時だけ、以下のアクションを実行します。
①変数「NewVar」に変数「CurrentItem」を入れる
②変数「GetNext」にFalseを入れる

直前の変数の設定で、「GetNext」にはFalseを入れているので、1週目はこのIFアクションはスルーされます。
次に、テキストを置換するアクションを使って、変数「CurrentItem」内のテキストの不要なスペースを削除します。
実はOCR機能で抽出したテキストデータには、文字と文字の間に余計なスペースが入っていることが多々あります。
今回、「ご提案システム」という文字列が含まれている行を探すため、余計なスペースが入っているとヒットしません。
確実にヒットさせるためには、スペース削除が必須です。
最終的に「CurrentItem」に入っていたテキストデータからスペースが削除されたものが、変数「Replaced」に入ります。

検索するテキストの「\s+」は正規表現でいう「1個以上の空白文字」を指します。
置き換え先のテキストの%''%は前述したように空欄を指します。
スペースを空欄に置換、つまりスペースを削除することになります。
次に再度IFアクションを追加します。
直前のアクションで保存された「Replaced」に「ご提案システム」が入っていた場合のみ、以下のアクションを実行します。
ここでFor eachの反復が1周します。
「GetNext」にtrueが入っていた場合、反復の最初のIFアクションで「NewVar」に「CurrentItem」が入ります。
流れとしては以下のようになります。
- 「ご提案システム」という行が見つかる
↓ - 反復で「CurrentItem」に次の行が入る
↓ - その行が「NewVar」に入る
つまり、「ご提案システム」が含まれる行の次の行が「NewVar」に入ることになります。
5-1-5. 抽出したテキストデータから不要なスペースを削除
前述のようにOCRで抽出したテキストデータには余計なスペースが含まれているので、それを削除します。
テキストを置換するアクションを追加し、以下のように設定します。

解析するテキストと生成された変数を同じにすることで、スペースを削除した形で上書きすることができます。
5-2. 「日付」をテキストとして読み込む
5-2-1. 日付が記載されている部分を画面に表示させる
ここでは注文書の中で、納入予定日を読み込みたいのですが、今のままでは注文書の上半分が拡大されていることで、画面の中に表示されていません。
キーの送信アクションを追加し、ページダウンを行うことで注文書の下半分を表示させます。

RPAツール全般に言えることかと思いますが、UI要素をクリックするより、キー入力で処理をした方が動作は安定します。
5-2-2. 「内容」抽出と同様に日付を抽出する
細かい変数名や、トリガーとなる文字列は違いますが、やっていることは「内容」抽出のときと全く同じです。

5-2-3. 日付を含んだ行の中から必要な部分のみを切り出す
最終的に欲しい部分は、納入予定日の年月であり「yyyyMM」という形を使いたいです。
現在抽出できているのは、日付を含んだ行であり、「12株式会社○○2026年09月19日」となっています。
ここから、「yyyyMM」という形の202609切り出すために、以下のようなテキストを置換するアクションを追加します。
検索するテキストは「○○○○年○○月」という文字列の前後も全て含めて検索し、置き換え先のテキスト$1$2は、カッコの中身の1番目(今回は2026)と2番目(04)に置換するという意味になります。

5-3. テキストを抽出したPDFファイルは閉じておく
このあと、ファイル名を変えることになるため、開いたままだとエラーになってしまいます。
このタイミングでPDFビューアを必ず閉じておくことが必要です。
キーの送信アクションで、Escapeキーを押すことでフルスクリーンモードを解除します。

さらにキーの送信アクションで、アプリ閉じるキーである「Alt + F4」を入力します。

これで、アプリは閉じられましたが、変数「NewVar」には注文書の内容が、「Replaced2」には日付が入っている状態となりました。
6. 「内容」をもとにファイル名を変更
今切り抜いてきた「Replaced」を使って、ファイル名を変更します。
今回は、「【注文書】押印済み_○○店様○○機器設置」というファイル名になるように設定します。
ファイルの名前を変更するアクションを追加します。
名前を変更するファイルは先ほどダウンロードして保存したファイルのパスを入力します。
新しいファイル名として、「【注文書】押印済み_NewVar」とすることで、NewVarに格納されていた「○○店様○○機器設置」が反映されることになります。
ここで、リネームしたファイルは変数「RenamedFiles」に格納されます。

7. 「日付」をもとに指定フォルダに保存
7-1. 指定のフォルダがない場合は作成する
直前にリネームしたファイルは、所定のフォルダ直下の「202609」というフォルダに保存したいです。
そのフォルダが既に存在しているのであれば、そのままそのフォルダ内に保存できますが、保存すべきフォルダがない場合、エラーとなってしまいます。
そこで、フォルダーが存在する場合アクションを使用し、フォルダがない場合は作成するという手順を加えます。
フォルダーの作成アクションを追加し、新しいフォルダ名を「Replaced2」にすることで、「202609」というフォルダが作成できます。

7-2. 該当ファイルを指定のフォルダへ移動する
最後に、ここまで大事に育ててきたファイルを指定のフォルダへ移動します。
ファイルの移動アクションを追加し、以下のように設定します。
移動先のフォルダに同じ名前のファイルが存在していたとしても、最新のファイルが保存されるように「上書き」としています。

フローのソースコード
Power Automate Desktopにそのまま貼り付けられるソースコードはこちら
WebAutomation.LaunchChrome.LaunchChrome Url: $'''スキャンデータを見るページのURL''' WindowState: WebAutomation.BrowserWindowState.Maximized ClearCache: False ClearCookies: False WaitForPageToLoadTimeout: 60 Timeout: 60 PiPUserDataFolderMode: WebAutomation.PiPUserDataFolderModeEnum.AutomaticProfile TargetDesktop: $'''{\"DisplayName\":\"ローカル コンピューター\",\"Route\":{\"ServerType\":\"Local\",\"ServerAddress\":\"\"},\"DesktopType\":\"local\"}''' BrowserInstance=> Browser
WebAutomation.Click.Click BrowserInstance: Browser Control: appmask['Web Page \'スキャンデータを見るページのURL\'']['Span \'文書操作\''] ClickType: WebAutomation.ClickType.LeftClick MouseClick: True WaitForPageToLoadTimeout: 60 MousePositionRelativeToElement: WebAutomation.RectangleEdgePoint.MiddleCenter OffsetX: 0 OffsetY: 0
WebAutomation.Click.Click BrowserInstance: Browser Control: appmask['Web Page \'スキャンデータを見るページのURL\'']['Anchor \'ドキュメントボックス\''] ClickType: WebAutomation.ClickType.LeftClick MouseClick: True WaitForPageToLoadTimeout: 60 MousePositionRelativeToElement: WebAutomation.RectangleEdgePoint.MiddleCenter OffsetX: 0 OffsetY: 0
WebAutomation.Click.Click BrowserInstance: Browser Control: appmask['Web Page \'スキャンデータを見るページのURL\'']['Anchor \'PDF\''] ClickType: WebAutomation.ClickType.LeftClick MouseClick: True WaitForPageToLoadTimeout: 60 MousePositionRelativeToElement: WebAutomation.RectangleEdgePoint.MiddleCenter OffsetX: 0 OffsetY: 0
WAIT (UIAutomation.WaitForWindow.ToOpen Window: appmask['Window \'about:blank - Google Chrome\'']['Window \'名前を付けて保存\''] FocusWindow: False)
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''C:\\ローカル\\Downloads\\【注文書】.pdf''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Enter}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
WAIT 2
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Tab}{Tab}{Tab}{Tab}{Enter}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
WAIT 2
UIAutomation.CloseWindow.Close Window: appmask['Window \'about:blank - Google Chrome\'']['Button \'閉じる\'']
WebAutomation.CloseWebBrowser BrowserInstance: Browser
System.RunApplication.RunApplication ApplicationPath: $'''C:\\ローカル\\Downloads\\【注文書】.pdf''' WindowStyle: System.ProcessWindowStyle.Maximized ProcessId=> AppProcessId
WAIT 5
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Control}{L}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Control}{Add}{Add}{Add}{Add}{Add}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
WAIT 10
OCR.ExtractTextWithOCR.ExtractTextFromForegroundWindowWithWindowsOcr WindowsOcrLanguage: OCR.WindowsOcrLanguage.Japanese ImageWidthMultiplier: 1 ImageHeightMultiplier: 1 OcrText=> OcrText
Text.SplitText.Split Text: OcrText StandardDelimiter: Text.StandardDelimiter.NewLine DelimiterTimes: 0 Result=> TextList
SET GetNext TO False
SET NewVar TO $'''%''%'''
LOOP FOREACH CurrentItem IN TextList
IF GetNext = True THEN
SET NewVar TO CurrentItem
SET GetNext TO False
END
Text.Replace.ReplaceTextWithRegex Text: CurrentItem TextToFind: $'''\\s+''' IgnoreCase: False ReplaceWith: $'''%''%''' ActivateEscapeSequences: False Result=> Replaced
IF Contains(Replaced, $'''ご提案システム名''', False) THEN
SET GetNext TO True
END
END
Text.Replace.ReplaceTextWithRegex Text: NewVar TextToFind: $'''\\s+''' IgnoreCase: False ReplaceWith: $'''%''%''' ActivateEscapeSequences: False Result=> NewVar
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{PageDown}{PageDown}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
OCR.ExtractTextWithOCR.ExtractTextFromForegroundWindowWithWindowsOcr WindowsOcrLanguage: OCR.WindowsOcrLanguage.Japanese ImageWidthMultiplier: 1 ImageHeightMultiplier: 1 OcrText=> OcrText
Text.SplitText.Split Text: OcrText StandardDelimiter: Text.StandardDelimiter.NewLine DelimiterTimes: 0 Result=> TextList
SET NewVar2 TO $'''%''%'''
LOOP FOREACH CurrentItem IN TextList
IF GetNext = True THEN
SET NewVar2 TO CurrentItem
SET GetNext TO False
END
Text.Replace.ReplaceTextWithRegex Text: CurrentItem TextToFind: $'''\\s+''' IgnoreCase: False ReplaceWith: $'''%''%''' ActivateEscapeSequences: False Result=> Replaced
IF Contains(Replaced, $'''納入予定日''', False) THEN
SET GetNext TO True
END
END
Text.Replace.ReplaceTextWithRegex Text: NewVar2 TextToFind: $'''\\s+''' IgnoreCase: False ReplaceWith: $'''%''%''' ActivateEscapeSequences: False Result=> NewVar2
Text.Replace.ReplaceTextWithRegex Text: NewVar2 TextToFind: $'''.*(\\d{4})年(\\d{2})月.*''' IgnoreCase: True ReplaceWith: $'''$1$2''' ActivateEscapeSequences: False Result=> Replaced2
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Escape}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
WAIT 5
MouseAndKeyboard.SendKeys.FocusAndSendKeys TextToSend: $'''{Alt}{F4}''' DelayBetweenKeystrokes: 10 SendTextAsHardwareKeys: False
WAIT 5
File.RenameFiles.Rename Files: $'''C:\\ローカル\\Downloads\\【注文書】.pdf''' NewName: $'''【注文書】押印済み_%NewVar%''' KeepExtension: True IfFileExists: File.IfExists.Overwrite RenamedFiles=> RenamedFiles
IF (Folder.IfFolderExists.DoesNotExist Path: $'''\\共有フォルダ\\契約書PDF または 注文書PDF\\%Replaced2%''') THEN
Folder.Create FolderPath: $'''\\共有フォルダ\\契約書PDF または 注文書PDF''' FolderName: Replaced2 Folder=> NewFolder
END
File.Move Files: RenamedFiles Destination: $'''\\共有フォルダ\\契約書PDF または 注文書PDF\\%Replaced2%''' IfFileExists: File.IfExists.Overwrite MovedFiles=> MovedFiles
作成編はここまで
記事が長くなってしまったので、実際に動かした結果や部署のメンバーに使ってもらってのフィードバック、今後の課題などは、次の記事に投稿します。
ぜひ見てください!!
バージョンアップ(2026/7/20追記)
フィードバックをいただいた部分について、改良を行いました。
1. 複数件のスキャンファイル取り込み
今回作成したフローだと、「1つの案件のスキャンを行ってフロー実行」という内容を繰り返すことしかできず、複数案件があった場合に不便でした。
実際、フィードバックでもこの部分が改良できればもっと時間短縮につながるという意見が多く出てきました。
なので、スキャンファイルをダウンロードする部分を複数フローに組み込むことで実現しようと考えました。
1-1. 何個のファイルをスキャンしたかをPADに読み込ませる
PAD側は、スキャンしたファイルを見るためのページを閲覧しに行っているだけなので、そこに何件のスキャンファイルがあるかは認識できません。
つまり、人間が行うこととしては
①案件ごとに連続してファイルをスキャンする
②PADに何件スキャンしたか認識させる
という作業が必要です。
実際にPADに数値を読み込ませるために、入力ダイアログを表示アクションを追加します。

入力ダイアログに表示させる内容を「タイトル」「メッセージ」に記載します。
実際の入力ダイアログは以下のように表示されます。

ここでユーザーが何件のファイルをスキャンしたかを入力することで、PAD側に件数を認識させることができるようになります。
入力された値は変数「UserInput」に格納されます。
次に、入力された値はテキストファイルとして認識されるため、これを数値に変換する必要があります。
テキストを数値に変換アクションを追加して、今格納された「UserInput」を数値に変換し、変数「TextAsNumber」に格納します。

1-2. 読み込ませたファイル数分のスキャンファイルをダウンロードする
次に、入力ダイアログで入力した数の分、スキャンファイルをダウンロードするフローを作成します。
1つ目のファイルをダウンロード後、ダウンロードページが表示されているところで以下のフローを挿入します。

「TextAsNumber」つまり入力した件数が2以上だった場合のIFアクションを追加します。
IFの中身は1つ目のダウンロードとほぼ変わりませんが、Webページのリンクをクリックアクションでは、ダウンロードページの2つ目のファイルのダウンロードボタンをUI要素クリックとして追加しています。

保存するファイル名が重複してしまうと最初にダウンロードしたファイルが上書きされてしまうため、ファイル名を【注文書】2.pdfとしています。
このIFアクションをさらに追加することで、3件以上のファイルでも対応できるようになります。

件数がそれぞれのIFアクションで設定している件数を下回った場合に、次のフローに進むようになります。
これで、複数ファイルを1回の実行でダウンロードできるようになりました。
忘れてはいけないのは、ダウンロード部分だけでなくリネームと指定フォルダへの保存についても、複数ファイル分の実行が必要ということです。
今回のIFアクションのように、1つ目のファイルのフローを繰り返すことで可能となります。
2. 保存したファイルをメールに添付
次に、保存したファイルを指定の宛先に向けたメールに添付して保存するという、保存した後の工程についても自動化に組み込んでいきます。
今回組んだフローの続きに、Outlookを起動しますアクションを追加します。

続いてOutlookからのメール メッセージの送信アクションを追加し、それぞれ設定していきます。

「アカウント」には、送信元となるアカウントを入力、「件名」「本文」には、その都度変わることになる注文書のタイトルを変数「NewVar」を利用して入力することで、自動的にどの案件についてのメールなのかがわかるようになります。
「添付ファイル」には、保存後のファイルを格納していた「MovedFiles」を設定することで、パスをいちいち入力することなく指定することができます。
今回は、送信までは行わず「下書きとして保存」までを自動化として組み込みました。
特に取引先に送るメールについては、間違いがあっては信用問題に関わりますので、自動化はメールを送る直前までにしておき、最後に人間のチェックをした上で送信ボタンを押すという安全設計としました。



















