Power Appsを使ってOutlookのメールを何とかPDFに変換する方法

# はじめに
Power Automateを使っていると、何気にOutlookのメール本文をPDFにできないという壁に当たります。
本文`HTML`からOneDrive for Businessの`ファイルの変換`アクションで変換を試みるも日本という狭い島国のコトバが混じると**NG**が・・・。

スクリプトによる解決になりそうですが、今回は趣向を変えて、
**Power Appsで無理やり何とかできないか** チャレンジしてみました。

![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b18ed9f7-7bdc-3185-d813-dd5055582be0.gif)

# Power Appsでメールを抽出する
Power Appsでメールの情報を取得するには、
`Office 365 Outlook`コネクタを活用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/c031c3e7-4b4c-08b1-f4dd-c4742cc9ac16.png)



使用方法は、Power Automateと同様です。
メソッドの使い方で戸惑いますが、ざっとこのような内容になります。

```yaml:基本的な式
Office365Outlook.GetEmailsV3({fetchOnlyUnread:false}).value
```

https://learn.microsoft.com/ja-jp/connectors/office365/#%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%A1%E3%83%BC%E3%83%AB%E3%81%AE%E5%8F%96%E5%BE%97-(v3)


基本的な式の部分に`fetchOnlyUnread`を追加した理由は、
このパラメーターがデフォルトでは`true`であり、
**未読のメッセージしか取得できない状態**になっているからです。

また取得できるメールも**最大25件**と大量のメールを
データソースにした処理には向かない印象を受けます。

```plaintext: パラメーター / 内容
{
    "cc":  "セミコロンで区切られた CC の受信者の電子メール アドレス", 
    "toOrCc": "セミコロンで区切られた送信先または CC の受信者の電子メール アドレス", 
    "importance": "重要度", 
    "fetchOnlyWithAttachment": "添付ファイルがある場合のみ", 
    "subjectFilter": "件名フィルター", 
    "folderPath": "電子メールを取得するメール フォルダー", 
    "fetchOnlyUnread": "未読のメッセージのみ取り込む", 
    "includeAttachments": "添付ファイルを含む", 
    "searchQuery": "検索クエリ", 
    "top": "取得するメールの件数 (既定: 10, 最大: 25)。"
}
```

GetEmailsV3では以下の値を取得できます。

```
{
    "id": "メッセージID",
    "receivedDateTime": "受信日時",
    "hasAttachments": "添付ファイルの有無",
    "internetMessageId": "インターネットID",
    "subject": "メールタイトル",
    "bodyPreview": "本文のプレビュー",
    "importance": "重要度",
    "conversationId": "会話ID",
    "isRead": "未読/既読",
    "isHtml": "HTMLかどうか",
    "body": "HTMLのボディ",
    "from": "FROM",
    "toRecipients": "受信者",
    "attachments": ["添付ファイル"]
}
```

## Outlook 365 コネクタで取得できるメールの値の例

今回注目するのは`body`です。
**メール本文**、 **HTMLテキスト** になります。

Power Appsを使って、HTMLテキストを`コンテナー`に格納し、
`コンテナー`を引数にして、PDF化を試みます。

ここで活躍するものが`PDF関数`です。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-pdf

プレビュー機能ですが、アーリーアダプターが沢山いらっしゃいますので、検索すると多くの記事がヒットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/06cd7dfb-6f71-6bb2-fbe4-ce87ccba251c.png)

:::note info
設定から近日公開の機能でPDF関数を有効にしてください。
:::


今回もこちらの方の記事を参考にさせていただきました。

https://mofumofupower.hatenablog.com/entry/gen_pdf_jp

**PDF関数を使うことにより、HTML > PDFの変換が非常に楽になることがメリットです。**

しかし使い方にもクセがあり、引数を`コントロール`や`コンテナー`、
`スクリーン`を対象にする機能であるため、活用するには研究がまだまだ必要です。

### 1. アプリの画面のサイズを変更する
`コンテナー`で見切れている部分は、PDF関数を使っても見切れてしまいます。
邪道ですが、アプリ自体の縦幅を長くし、対応できるメールの幅を広げます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/2bd75c0c-b5c9-03bb-707d-9def4e9f72d7.png)

設定 > 表示からアプリケーションのサイズを設定します。
16:10でも十分な領域がもてますが、少し足りない。

:::note warn
**邪道 OF 邪道**です。
調べれば、マシな解決策が出ると思いますので、調査してみてください
※私もします
:::


### 2. Power Automate フローを構築する
Power Automateは至って簡単です。
ファイルとしてPower Automateに値を渡し、
目的の場所に`ファイルの作成`で対処するだけでPDFが生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b82bbd97-6fb8-1408-b14f-984a9b51bedb.png)


https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/how-to/pdf-function


メールで参照できていた画像は、PDF化する中で参照できなくなります。
実際にOutlookで見ていたものと乖離がでるのは仕方がないと思うところです。

## Advance - 一括処理をする
ここまででは、単なるPDF関数の説明に過ぎないので、
**Outlook 365 コネクタ** で取得したメールを全てPDF化するという、
ゴリゴリの力業を残しておきます。

課題有りの方法ですので、`こういう方法で一応何とか繰り返しができるのね`
くらいで考えてください。

### 流れ
1. **ギャラリーコントロールのデータソースを、変数を使って動的にする**
    - PDF化するメールだけ表示する
1. **繰り返し処理のために下記を設ける**
    - 変数を初期化するためのボタン or アイコン
    - 繰り返しを制御するための`スライダー`コントロール
    - 遅延処理を用いるための`タイマー`コントロール
1. **繰り返し処理を実装する**
    1. ボタンを押して変数を初期化する
    1. ギャラリーコントロールでN番目のメールを表示する
        1. 付随してコンテナー内のHTMLテキストも変更される
    1. `スライダー`コントロールの`OnChange`で
        1. Power Automateを起動
        1. タイマーを初期化
    1. `タイマー`コントロールで遅延処理
        - HTMLテキストの表示とPower Automateの起動が同期的ではないため
        - インクリメントをして`スライダー`コントロールの`OnChange`を再発火

確実にビジネス向けではないですね。
 - 同期・非同期の問題も解決していません。
 - カイゼンの余地が大ありです。

### 変数
必要なのは`タイマー`コントロールをリセットする変数と、
インクリメント用の数値だけです。

```plaintext:タイマーコントロールリセット用　スライダーのOnChangeに設定する
UpdateContext({_start:false});
UpdateContext({_start:true});
```

```plaintext:インクリメント用　繰り返し処理実行ボタンに設定する
UpdateContext({num:1});
```

### コントロール
**動的にメールの表示を変更させるためのギャラリー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/137a1db7-8453-40f2-c0a8-e0924424605d.png)

```plaintext:Items
First(LastN(Office365Outlook.GetEmailsV3({fetchOnlyUnread:false}).value, num))
```

**ボタンであるPDFアイコン**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/91785f23-5add-d332-a9db-24a408be5c0e.png)

```plaintext:OnStart
UpdateContext({num:1});
```

**繰り返し処理を無理やり実行するためのスライダー**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/4a54fa70-2ee1-ba61-6b91-641e3ff3ee84.png)

```plaintext:Default
num
```

```plaintext:OnChange
'Power Automateのフロー'.Run({file:{name:galMails.Selected.subject & "_" & num & "_.pdf", contentBytes: PDF(印刷するコンテナ)}});
Reset(タイマーコントロール);
UpdateContext({_start:false});
UpdateContext({_start:true});
```

**タイマー コントロール**
非表示にしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b3a17c9d-93c6-4074-9865-918c25423931.png)

```plaintext:Duration
3000
```
※3秒遅延処理

```plaintext:Duration
3000
```

```plaintext:OnTimerEnd
If(num < 11,UpdateContext({num:num + 1}));
```
10回繰り返す用

```plaintext:AutoStart
_start
```

```plaintext:Start
_start
```
リセットしてタイマーを起動する用

## 最後に
ネタとして載せていますが、こんな業務・・・ない方がいいよね！
それでは良いPower Lifeを！