Formsでアップロードできない拡張子のファイルをなんとかして受け取りたい

# はじめに
Power Automate はじめの一歩によく使われるForms ですが、このForms を利用すると、単なるアンケートだけではなく、ファイルを提出してもらうことが出来ます。

しかし、提出できるファイルの種類には、いくらかの制限があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/98585653-b6c7-12e9-bcf1-92a23019a4b2.png)

https://support.microsoft.com/ja-jp/office/ファイルのアップロードを許可するための質問を追加する-6a75a658-c02b-450e-b119-d068f3cba4cf

特に個人的には、CSVファイルなどのテキストファイルや、ZIPファイルの受け取りができないことに不便を感じたので、今回はそれを何とかするフローを考えてみました。

# フローの流れ
基本的な窓口はそのままForms で行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/2aad826a-99d2-5b2e-8043-2e56e45f6251.png)

このフォームには、追加のファイルがある場合のチェックボックスを設けております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/12f67c5f-7407-cfaf-ca05-b39bdb48730d.png)

フォームからの投稿があれば、投稿者にメッセージを返しますが、このチェックが入っている場合のみ、ファイルの**アップロード用のリンク**をつけてメッセージを送ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/63385071-fbe5-0338-1565-31d3f202edd2.png)

このアップロード用のURLは、SharePointの**ファイルの要求機能**を使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/97dce7e6-e97a-fa9a-c388-964baeedb65f.png)

https://support.microsoft.com/ja-jp/office/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E8%A6%81%E6%B1%82%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-f54aa7f8-2589-4421-b351-d415fc3b83af

ある程度時間が経ったら、追加のアップロードが終わったとみなして、どんな回答が来たかを自分に通知します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/cd569f97-59e1-4268-b609-4f244f2e6018.png)


# 事前設定
前述の通り、ファイルの追加アップロードには、SharePointのファイルの要求機能を使用しています。

この機能を使うためには、テナントの設定として、機能が有効になっている必要があります。

通常の操作で、フォルダの右メニュー内に「ファイルを要求する」が表示されていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/e383d2aa-e8e8-1fcc-97a5-fee3a7167d0b.png)

表示されていない場合は、組織の管理者に機能を有効にしてもらいましょう。

https://learn.microsoft.com/ja-jp/sharepoint/enable-file-requests

:::note warn
共有範囲の設定を変更する必要があるため、組織の規定によっては、この機能を使用することが出来ないことがあります。
:::

# フォームの用意
今回は簡単のため、最低限の質問を設定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/892c4591-ed18-b3d5-b764-347c7e86a3ac.png)

1. 所属を示す項目
1. ファイルのアップロード
1. 追加のファイルの有無

追加ファイルの有無は、チェックボックスを設けています。
選択肢形式の質問で、選択肢を一つだけにし、複数回答オプションをオンにすることでチェックボックスが作れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/b16ed770-b04c-072f-c3ad-b58e6e92b4ea.png)

:::note warn
このとき、必須オプションをオンにすると、チェックが外せなくなるので注意してください。
:::


# フローの解説
基本的なFormsを使った部分については割愛して、ファイルの追加アップロードにかかわる部分のみを解説します。

<details><summary>フローの全体像</summary>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/ad0ef7d6-525a-15b8-1b6e-9ecd87ef754c.png)

</details>

## フォルダの作成
ファイルの要求をするために**回答ごとに固有のフォルダ**を作成する必要があります。
Forms の添付ファイルが格納される、質問ごとの固有のフォルダを使う方法もありますが、追加でアップロードされたファイルがどの回答に紐つくものなのかを特定することが困難になってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/15d3256a-534f-689d-2139-a049fa2fd02f.png)

そのため、フォームの回答IDを使って、重複しないような固有のフォルダを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/fcae68d9-1713-9c66-95ee-39c60416dcc4.png)

せっかくフォルダを作るということで、ついでに所属ごとにフォルダ分けしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/a986a7e6-b5d3-d5c2-b9a5-5d22066a7377.png)

フローでのアクションはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/7147a030-3fa3-3c55-14bc-2094908afbb5.png)

ここで作成したフォルダに、追加のファイルをアップロードしてもらうよう依頼します。

## 追加ファイルがあるか？(条件)
この項目にチェックが入っているかどうかで判定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/9820d6d0-7095-96fa-9f52-76611ce8e329.png)

チェックが入っていない場合、この質問の動的なコンテンツが空になりますので、`empty`関数でチェックができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/58178ea8-8b6e-ce03-9bd5-af98467b3fbe.png)

チェックが入っていない場合は空＝`empty`関数の結果がtrueになるので、このように判定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/48b595e4-606c-3761-b781-0e7e1e5322cd.png)



## ファイルのアップロードURLの作成
先の質問で追加のファイルがある場合のみ、アップロード用のリンクを作成して送付します。

SharePointの**ファイルの要求**を行うのですが、Power Automate の標準コネクタではこの機能が用意されておりません。
そのため、`SharePoint に HTTP 要求を送信します`アクションを使用します。

方法については、コルネさんの解説が詳しかったので、参考にさせてもらいました。

https://koruneko.hatenablog.com/entry/2023/08/03/020827

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/0614e880-e0d3-fe78-292e-b8f69022d645.png)

不要なプロパティを指定していなかったり、ちょこちょこ値を変えているので、変更部分のみ解説します。

- **allowAnonymousAccess**

誰でも回答可能かどうかを指定するプロパティです。

`true`にすると組織外のユーザーからもアップロードできるリンクになりますが、今回は社内ユーザーを想定しているため、`false`にしました。

- **expiration**

リンクの有効期限を指定するプロパティです。

手動でリンクを発行するときには指定できないようですが、APIからは指定できました。
有効期限なしで開放しっぱなしにしてしまうのも管理が面倒なので、回答のあった日だけ有効になるように、以下の関数で**次の日**を期限にしています。
```powerfx:expiration
addDays(
    utcNow(),
    1,
    'yyyy-MM-ddTHH:mm:ssZ'
)
```
分単位・時間単位の指定ができればよかったのですが、日単位での指定のみが可能なようです。

- **description**

リンクを開いたときの説明文を指定するプロパティです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/05156e44-7303-24c8-f01b-68a951cbba28.png)

動的なコンテンツを利用してそれっぽい感じに仕上げています。

## 投稿者への通知
リンクを作成したら、それを投稿者へ送ります。
メッセージにリンクを付けておいて、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/992382e4-a021-1af1-adfc-dcc8d67d2e9e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/8d1dab4d-25c5-08dd-2b45-56a64165a0ea.png)

```html:リンク部分
<a href="@{body('SharePoint_に_HTTP_要求を送信します')?['d']?['ShareLink']?['sharingLinkInfo']?['Url']}">追加ファイルのアップロード用リンク</a>
```

投稿者にTeamsでメッセージを送ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/67363ad4-8a39-272b-e6ce-ee79b4187dd3.png)


## アップロードのための待機時間
有効期限が日単位でしかできなかったので、本当は10分間のみ有効にしたかったのですが、ごまかしてユーザーに対する通知として時間制限を行っています。
（リンクのDELETE方法を誰か教えてください🙏）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/e5760af7-bf66-de55-70f0-639cabb3579d.png)

フローの方でも、10分間の待機を行っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/84cb19c5-b0d9-f756-7c9a-718d13bffcdb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/17763cac-c08b-6e77-c93b-288a84349359.png)

## アップロードされたファイルの取得
10分間の待機ののち、追加のファイルがフォルダに保存された前提でファイルの取得を行います。

もともとFormsで添付されたファイルも、作成したフォルダに移動しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/0c3195e4-35f9-2e03-8942-7c98ea29fa72.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/0059c5a9-8120-de6d-da8f-195faafd9cc3.png)

Forms から直接アップロードしたファイルも、追加でアップロードしたファイルも同じフォルダに格納された状態です。

そのファイルの一覧を`ファイルの取得 (プロパティのみ)`アクションで、フォルダを制限することで取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/c86a29d3-347a-438a-d19d-9bb7f0f13122.png)

取得したファイルの一覧を、データ操作系のアクションを使って、いい感じにリンクに変換します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/89d3ec54-6b47-9ba1-ae05-2264bba3ae1a.png)

選択アクションがちょっとテクいかもしれません。

テキストモードに切り替えて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/56e770de-ef3c-0dee-0c2f-88df15dcb483.png)

全部消して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/bfbd1928-b4c5-74ca-08dc-b5632c058da1.png)

単に値だけを入力すると、値だけの配列が作れるので
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/ee31327f-58ff-9b2d-5ed2-66b69b2f9bd3.png)

こうやってリンクだけの配列を作りたいのですが、有効なJSONじゃないと怒られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/c54f3c7e-d8a3-1192-7d3d-361c3e0b49dc.png)

なので、`concat`関数で文字列結合をしてあげると、同じ結果でも怒られずにリンクのみの配列が作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/edf89451-9b65-7438-8be7-534659bd6d55.png)


```powerfx:選択
concat(
    '<a href="',
    item()?['{Link}'],
    '">',
    item()?['{FilenameWithExtension}'],
    '</a>'
)
```

## 自分への通知
最後に結果を自分に通知して終わりです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/19ae2ee3-5970-577d-0738-b152aeca606a.png)

Formsでは添付できないファイルも、このように受け取ることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/5dcf4364-89de-a7cd-6918-a9d67bbf0536.png)

# おわりに
今回利用したフローを応用して、そもそもファイルの添付を許可できない組織外の人からファイルをもらうフォームを作成することもできそうです。

その場合はメールアドレスの入力欄を設けたり、`allowAnonymousAccess`を`true`にするなどの変更が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/4d7047ae-fb85-ca57-0884-78c63108378f.png)


HTTPリクエストを使わないといけないので、難易度が高いのがネックです。
Forms のカスタマイズ性がもうちょっと良くなればいいんですが・・・今後に期待！
メールアドレス形式のバリデーションチェックも欲しい！