Power Automateで予定表から業務報告を自動作成する

お仕事の一日の終わりに、チャットで簡単な業務報告をしています。会議や定型作業はあらかじめスケジュールに入っていますが、なるべく細かくその日やったこともOutlookのカレンダーに書き込んでいるので、それを転記するだけですが、Power Automateを使えばその下書きを用意することができます。
例えば下記はとある一日のカレンダーです。

作業が2つ。会議が2つ入っています。これをチャットにはこんな感じで報告しています。
ダディー 〇〇時退勤します。お疲れ様でした。
Teamsの業務報告チャネル
【業務報告】
・会議:戦略会議、定例会
・作業:プログラム修正作業、定期作業
今回はこれをPower Automateのクラウドフローを使って、自分宛にチャットで投げてみようと思います。それならコピーしてちょこっと修正して投稿できます。
JSONで予定単位の情報が簡単にとってこれる
まずはカレンダーの内容を取得します。Outlookのイベント取得系はいくつか並んでいますが、最新の「イベント取得(v4)でよいでしょう。

素直にメインのカレンダーを選択してテスト実行してみます。

すると、Outlookのカレンダーに登録していた自分の予定がずらりとJSONで取得できます。

ちなみに中身はこんな感じ。ちょっと長いですが載せますね。
なんとなく見てもわかるとおり、{}の中が1つの予定です。{}で区切られた予定がカンマで区切られて[]の中で配列になっているのがわかります。
subjectが予定表のタイトルですね。startが予定の開始日時ですが、この値はUTC時刻なので日本時間より9時間前であることに注意が必要です。あと、locationの値に「Microsoft Teams 会議」と入っているのがTeamsで設定された会議なのがわかります。場所として定義されているのが面白いですね。そのほかにもいろいろ使えそうな値がありますが、今回のスクリプトでは上記の3点を使うことにします。
[
{
"subject": "定期作業",
"start": "2023-10-09T06:00:00.0000000",
"end": "2023-10-09T06:30:00.0000000",
"startWithTimeZone": "2023-10-09T06:00:00+00:00",
"endWithTimeZone": "2023-10-09T06:30:00+00:00",
"body": "",
"isHtml": true,
"responseType": "organizer",
"responseTime": "0001-01-01T00:00:00+00:00",
"id": "hogehoge",
"createdDateTime": "2023-10-08T12:31:58.5063102+00:00",
"lastModifiedDateTime": "2023-10-08T23:19:46.3008863+00:00",
"organizer": "daddy@example.com",
"timeZone": "UTC",
"iCalUId": "hogehoge",
"categories": [],
"webLink": "https://outlook.office365.com/owa/?itemid=hogehoge",
"requiredAttendees": "",
"optionalAttendees": "",
"resourceAttendees": "",
"location": "",
"importance": "normal",
"isAllDay": false,
"recurrence": "none",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"showAs": "busy",
"responseRequested": true,
"sensitivity": "normal"
},
{
"subject": "定例会",
"start": "2023-10-09T04:00:00.0000000",
"end": "2023-10-09T04:30:00.0000000",
"startWithTimeZone": "2023-10-09T04:00:00+00:00",
"endWithTimeZone": "2023-10-09T04:30:00+00:00",
"body": "会議への招待メールの内容",
"isHtml": true,
"responseType": "organizer",
"responseTime": "0001-01-01T00:00:00+00:00",
"id": "hugahuga",
"createdDateTime": "2023-10-08T12:31:26.1288937+00:00",
"lastModifiedDateTime": "2023-10-08T23:19:49.1920508+00:00",
"organizer": "daddy@example.com",
"timeZone": "UTC",
"iCalUId": "hugahuga",
"categories": [],
"webLink": "https://outlook.office365.com/owa/?itemid=hugahuga",
"requiredAttendees": "",
"optionalAttendees": "",
"resourceAttendees": "",
"location": "Microsoft Teams 会議",
"importance": "normal",
"isAllDay": false,
"recurrence": "none",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"showAs": "busy",
"responseRequested": true,
"sensitivity": "normal"
},
3つ目の予定
{
4つ目の予定
},
{
5つめの予定
}
]
日付範囲を限定したイベントを取得したい
自分の予定を取得してみるとわかるのですが、何も指定せずにイベントを取得すると、今日だけでなく過去や未来の予定までたくさん取得してきてしまします。ですから取得する範囲を今日の予定に絞る必要があります。
これにはイベント取得の「フィルタークエリ」を用います。記述にはODATAクエリの書式で書かないといけません。とりあえず以下のように記述して再度テスト実行してみます。
start/dateTime ge '2023-10-09'

これで2023年10月9日以降のデータが取得できます。クエリの中の 「ge」は「次の値以上」を意味する比較演算子です。たぶんGreater Equal の略かな?慣れないとぱっと見わかりにくいですが、以下の公式ドキュメントにまとめられています。ODATAクエリはSharePointのアイテムをフィルタリングして取得する際にも使えるので、こういうのがあると覚えておくだけでできることの幅が広がります。
これだけだと、未来日のイベントもとってきてしまうので、本日の23時59分までの情報を取得できるようにします。(そんなに働かなくても・・・)
start/dateTime ge '2023-10-09' and start/dateTime le '2023-10-09T23:59:59.0000000'
「以下」を意味する比較演算子は「le」です。日付と時刻の間にはTを入れます。このフォーマットは先ほどテストでイベントを取得したときに出力されたJSONのstart項目を参考にするとよいでしょう。
日付と時刻を自動取得する
取得したいのは日本時間の本日の朝0時から夜の0時までです。このスタートとエンドをもっと簡単に取れる方法があったら教えてほしいのですが、とりあえずこんな感じにしました。
タイムゾーンの変換でutcNow()で取得した日時を「yyyy-MM-dd」の形式で取得します。年月日だけが取れるので、これは実行した日本の日付だけが取れます。UTCだと0時。日本時間だと朝9時を表します。
1つめの「時間からの減算」では日本の0時、つまりUTCの前日15時を取得するために9時間減します。
2つめの「時間からの減算」では、その24時間後を取得するために「-24」を減算しています。つまり24時間足しています。

これをイベントのフィルタークエリの時刻部分に、動的な値として組み込みます。シングルクォーテーションを忘れないように注意します。

会議と作業を分ける
業務報告は、会議と作業を分けているので、ここでもイベントのなかからこれらを振り分けたいと思います。イベントは配列になっているので、「アレイのフィルター処理」が使えます。
差出人には「イベントの取得(v4)」を指定し、左辺には動的なコンテンツから「場所」を選択します。
先ほど、JSONの中身を見たときに、Teams会議の場合はlocationの項目が以下のようになっている特徴がありました。今回は「会議」というキーワードを含むイベントを絞り込むことにします。
"location": "Microsoft Teams 会議"

取得したいのは、各イベントのタイトル部分「subject」の項目だけです。この後の処理で取得したタイトルを文字としてつなげて表現したいので、こういう時には「選択」アクションを使います。
まず、アレイのフィルター処理の結果「本文」を選択の開始にセットします。
次に、マップの右側にある「T」のようなボタンをクリックしてテキストモードに変更します。

モードを切り替えられたら、ここに動的なコンテンツから「件名」を選択します。

テスト実行してみると、いい感じに各イベントのsubject部分だけが配列化されて取得できたのがわかります。

今度は、この配列から「、」でつないだ文字にします。これには、「作成」アクションを用意して式でjoin関数を使います。このあたりの配列を文字列にする処理については、こちらの記事で試行錯誤していますので参考にしてください。
join(body('選択'),'、')

テスト結果を見ると、文字列として会議だけを集めて書くことができました。

会議と同じように作業も振り分ける
会議だけを抽出することができたので、今度は会議以外の作業を抽出します。アレイのフィルタを使うのですが、一連の処理を使いまわすために「スコープ」にまとめます。まとめられたらそのスコープごとコピーします。

イベントの取得の下に分岐を作って、クリップボードからスコープをコピーできます。

作業のスコープの中のフィルタでは、条件を「次の値を含まない」に変えるだけですね。

ここまでできていれば、あとは「作成」として用意した文字列を、適当なフォーマットをチャット投稿すればOKです。

ばっちりです!

ディスカッション
コメント一覧
まだ、コメントがありません