1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Power Automateでは無理だった SharePoint申請書アーカイブを、Python + Claude Codeで自動化した話

1
Last updated at Posted at 2026-05-12

image.png

はじめに

社内の経費申請システム(SharePointサイト)がリニューアルされることになりました。
それにともない、旧システムに残っている申請データを全件保存しておく必要が生じました。

件数は GE(一般経費)708件・TE(出張経費)470件、合計1,178件

1件ごとに以下作業を行わなくてはなりません。

image.png

これを1,178件分、手作業でやるとしたら……

1件ずつ申請書を開いて、Ctrl+Shift+P でPDF化して、ファイル名を「GE0123_report.pdf」に変えて、添付ファイルも保存して、SharePointの正しいフォルダーに入れて……

気が遠くなるので「自動化しよう!」と動き始めたのが、この話のスタートです。

目次

  1. なぜ Power Automate をやめたのか
  2. Pythonで作った構成
  3. 生成AIをどう使ったか
  4. ハマったポイント2選
  5. 途中で止まっても安全に再開できる設計
  6. Power Automateと比べてどうだったか
  7. 結果

1. なぜ Power Automate をやめたのか

最初からPythonで作ったわけではありません。
まず使い慣れた Power Automate(Microsoftのノーコード自動化ツール)で実装を試みました。

クラウドフローはある程度動いた

クラウドフロー:インターネット上で動くフロー。

SharePointから添付ファイルを取得してOneDriveに保存する部分は、クラウドフローで実現できました。ここまでは順調でした。


デスクトップフローで詰まった

デスクトップフロー
PCの画面を自動操作するフロー。ブラウザの操作なども自動化できる。

申請書をPDF化するには、ブラウザで申請書を開いて印刷する操作が必要です。これをデスクトップフローで実装したのですが、2つの問題にぶつかりました。

① 実行中はPCがまるごと占有される
デスクトップフローが動いている間、マウスやキーボードが自動操作されるため、他の作業が一切できません。1,178件の処理には数時間かかるため、その間ずっとPCを放置するのは現実的ではありませんでした。

② 処理が正しく動いているか確認できない
自動操作の画面を眺めていても「本当に正しいファイルが取れているのか」が見えにくく、全部終わってから初めて問題に気づくということが起きました。ログも限定的で、どこで失敗したかの調査に時間がかかります。

➡「PCを占有せず、バックグラウンドで動きながら、処理状況をリアルタイムで確認できる」構成が必要だと判断し、Pythonで作り直すことにしました。


2. Pythonで作った構成

今回使ったのは主に2つのライブラリです。

ライブラリ 役割
Playwright ブラウザを裏側で自動操作する。ログイン・申請書を開く・PDFに変換する
requests SharePointのAPIを通じてファイルの取得・保存を行う
Python スクリプト
├── Playwright  ── ブラウザをバックグラウンドで操作し、申請書をPDF化
├── requests    ── SharePointへファイルをアップロード・フォルダー一覧を取得
└── ログイン情報(Cookie)を両者で使い回す仕組み

Cookieとは:
「このユーザーはログイン済み」という情報をブラウザが持ち歩く仕組み。
Playwrightでログインした際のCookieをrequestsにも渡すことで、二重ログインなしでAPIも使える。

処理の流れはこうです。

① Playwrightでブラウザを起動・Microsoftアカウントへログイン
② ログイン情報(Cookie)をrequestsにも渡す
③ 申請書リストをSharePoint APIで取得(1,178件)
④ 1件ずつ:申請書を開く → PDFに変換 → SharePointの所定フォルダーへ保存

ログで「今何が起きているか」をリアルタイムに把握できる

Power Automateのデスクトップフローでの一番の問題は「処理が正しく動いているかわからない」ことでした。Pythonに切り替えた際、この問題をログで解決しています。

処理中は以下のようなログがターミナルに流れます。

[1/708] 処理中: GE62
  PDF アップロード完了: GE62_report.pdf
[2/708] 処理中: GE63
  PDF 生成失敗: GE63_report.pdf   ← どこで・何が失敗したか一目瞭然
[3/708] 処理中: GE64
  PDF アップロード完了: GE64_report.pdf
  添付ファイル アップロード完了: GE64_attachment1.xlsx

「708件中の何件目を処理しているか」「どのファイルが失敗したか」がリアルタイムでわかります。処理が終わった後にログファイルを確認すれば、全件の成否も一覧で確認できます。

Power Automateのデスクトップフローでは「全部終わってから問題に気づく」でしたが、Pythonではエラーが出た瞬間に番号とファイル名がわかるので、ピンポイントで再処理できます。


3. 生成AIをどう使ったか

今回のメインツールは Claude Codeです。

① スクリプト全体を30分で完成させた

Power Automateでの実装に約3日かかったのに対し、Claude Codeに構成を伝えたところ約30分でスクリプトが完成しました。

やったことはシンプルで、「何をしたいか」を日本語で伝えただけです。

伝えた内容の例:
「SharePointにPlaywrightでログインし、申請書の一覧をAPIで取得、
 1件ずつページを開いてPDF化してSharePointにアップロードするPythonスクリプトを作って。
 ログイン情報はAPIクライアントとも共有する設計で。」

② ハマったときの壁打ち相手

うまく動かないとき、エラーメッセージとコードをそのまま貼って相談しました。

相談例:
「パスワードを自動入力するとMicrosoftにログイン画面へ戻されてしまう。
 このコードとエラーを見て、原因と解決策を教えて」

AIが「人間らしいタイピング速度で入力すると検知されにくい」という方向性を教えてくれたので、そこから自分で試して調整しました。

注意点:AIの提案をそのままコピペしても動かないことはある。 「この方向が正しそう」という仮説をもらって、自分で検証する、という使い方が現実的です。


③ コードを整理・読みやすくしてもらう

動いたコードを「関数に分割して、コメントもつけて整理して」と依頼すると、きれいに返してくれます。後から見直すときの負担が大幅に減りました。


4. ハマったポイント2選

① 全件処理後の検証で「500件しか確認できていない」ことが発覚

全件処理が終わった後、「本当に1,178件すべてアップロードできているか」を確認するための検証スクリプトを走らせました。SharePointのフォルダー一覧を取得して件数を数えるだけのスクリプトです。

ところが、1,178件あるはずのフォルダーが500件しか返ってこないという結果になりました。

原因: SharePointのAPIは、1回のリクエスト(問い合わせ)で返せる件数が最大500件に制限されています。処理そのものは正しく動いていたのですが、確認スクリプト側がこの制限を考慮していませんでした。

# 問題のある取得方法(500件で打ち切られる)
/Folders?$top=500

解決策: 「GEで始まるフォルダーだけ取得する」という条件(フィルタ)を加えました。GEとTEでスクリプトを分けて実行する構成だったため、これで1回500件以内に収まりました。

# 解決後(GEで始まるフォルダーだけ、最大1000件取得)
/Folders?$filter=startswith(Name,'GE')&$top=1000

② 長時間動かすとログアウトされる

1,178件の処理には数時間かかります。その間にログイン状態が切れると、「ログイン画面のスクリーンショット」がPDFとして大量保存されるという最悪の事態になります。

ログイン状態(Cookie)は一定時間で失効します。ブラウザは自動で更新しますが、APIクライアント側は古い情報を持ち続けます。

解決策: 1件処理するごとに、ブラウザの最新ログイン情報をAPIクライアントにも渡し直す仕組みを入れました。

# 1件処理する前に、ブラウザの最新ログイン情報をAPIクライアントへ同期
sp.set_cookies(await ctx.cookies())

これにより、ブラウザが自動更新したログイン情報がAPIクライアントにも常に反映されます。


5. 途中で止まっても安全に再開できる設計

1,178件の処理が途中でエラー終了した場合、最初からやり直しでは時間の無駄です。そこで2つの仕組みを入れました。

処理済みはスキップ: SharePointにすでにフォルダーが存在する件は自動的に飛ばします。

SKIP_EXISTING = True  # 処理済みの件をスキップする

特定の件だけ再処理: 失敗した件番号だけを指定して再実行できます。

RETRY_IDS = ["GE-0312", "GE-0487"]  # この2件だけ再処理する

「500件処理して501件目でクラッシュしたとき、501件目から再開できる」というのは、大量処理の自動化では地味に重要な設計です。


6. Power Automate と比べてどうだったか

今回の要件では、Power Automate よりも Python + Playwright の方が相性が良い結果になりました。

Power Automate Python + Playwright
向いているケース 少量処理・簡単な業務自動化 大量処理・複雑な操作
実行中 ❌ PCが占有される ✅ バックグラウンド実行
進捗確認 ❌ 完了後に問題が見つかりやすい ✅ ログでリアルタイム確認
PDF化 ❌ レイアウト崩れが発生しやすい ✅ 画面そのまま出力
エラー時 △ 再実行が少し面倒 ✅ 続きから再開可能
導入ハードル ✅ GUI中心で始めやすい △ Python環境が必要
生成AIとの相性 △ フロー相談が難しい ✅ コードをそのまま相談可能

結論:
件数が少なく、PDF化が不要な業務なら Power Automate は今でも十分強力です。
一方で、「大量処理 × PDF化 × 再実行性」 が必要な今回のケースでは、Pythonの方が相性が良いと感じました。


7. 結果

  • GE 708件・TE 470件、合計1,178件のPDFと添付ファイルをSharePointへ格納完了
  • スクリプト完成までの時間:約30分(Claude Codeで実装)
  • 実行時間:約3時間(GEとTEを並列実行)
  • Power Automateでの実装:GE・TE合わせてクラウドフロー・デスクトップフロー計4本を約3日かけて構築 → それでも限界に
Power Automate Python + Claude Code
実装にかかった時間 約3日(フロー4本) 約30分
全件処理の実行時間 未完(断念) 約3時間

おわりに

「ローコードツールで無理なら、コードで書く」という選択は、思ったよりハードルが下がっています。
生成AIに「何をしたいか」を伝えると土台を作ってくれるので、Pythonの経験が少なくても取り組みやすくなっています。「全部自分で書く」ではなく「AIと一緒に作る」という感覚です。

同じような課題を抱えている方の参考になれば幸いです。
最後まで読んでいただきありがとうございました!


参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?