【#PowerApps】PowerAppsを使ってチームのフローをマイフローにコピーして接続先を自分に変える方法

# 本記事の内容

PowerApps ＋Microsoft Flow(以下 Flow) を利用して Flow をマイフローとしてコピーする方法です。

# 概要

社内でチームのフローとして共有されている Flow をマイフローとして PowerApps + Flow を利用してコピーします。

コピーするFlow
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/8916bb80-4e48-10cc-9e3a-3277bcc84112.png)
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/e9a979ba-f9d1-0757-48a9-527174cc8a18.png)

アプリを実行すると...

![メディア1.gif](https://qiita-image-store.s3.amazonaws.com/0/183354/3cc3880c-21c8-d6ff-1a4a-8faf1c36d81b.gif)

コピーされた Flow です。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/94269ba8-87fb-79dd-1464-a611efb9ef16.png)


中身も問題なくコピーできています。

さて、なぜこのような方法を今回行ったかというと、「接続先」を変更するためです。
こちらはチームのフローにある接続先です。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/19b298ed-661c-701e-3023-ef06a4027785.png)


先ほどのマイフローにコピーされた Flow は test_taroユーザーに接続先が設定されていましたが、チームのフローの場合は、変更しない限り、接続先はその Flow の作成者となります。
ここで問題となってくるのは、**誰の予定表**が取得されるかという問題です。
Flow で予定表の取得アクションで取得できる予定表は実行者ではなく**接続先として登録されたのユーザー**の予定表が取得されます。

こういった問題を現時点で回避するには大きく分けて 2 パターン存在します。

## 1.トリガーを PowerApps から実行するようにする。

こうすることで、自動的に接続先が切る変わるので、実行者の予定表が取得できます。
しかし、今回のスケジュールトリガーのように PowerApps 以外のトリガーの場合は？ 

## 2.マイフローとして新たに Flow を作成し、そのFlowの接続先を自分に設定する。

Zipで Flow をエクスポートして、それをインポートすることで、マイフローとしてその Flow を作成できます。その場合、接続先をインポート時に選択できるので、任意のユーザーの予定表を取得できることになります。

ただ、毎回エクスポートとインポートの作業をユーザーごとにするのは面倒ですよね？
しかも、PowerPlatform を利用するユーザーは開発者の想定ではないので、そういった操作はできる限り避けるべきです。
この問題を解決したものが初めに見てもらったアプリとなります。

## 全体のアーキテクチャ

まずは全体のアーキテクチャから。
![図1.png](https://qiita-image-store.s3.amazonaws.com/0/183354/95ad70f6-211d-43fc-d752-0472d9988902.png)

今回作成するシステムは以下の３つです。

1. コピー対象の Flow
2. コピーを作成する Flow
3. コピーを作成する Flow を実行する PowerAppsアプリ


## 1 コピー対象の Flow

何でもいいです。　Flow を用意しましょう。
今回用意した Flow は　スケジュールトリガー + Office 365 Outlook です。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/248e42f2-936a-7530-7317-c8c753a73d95.png)



## 2 コピーを作成する Flow

FlowManagementアクションを利用します。
以下が全体の Flow です。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/9601392e-49fc-1418-60bf-325db71ddf50.png)


![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/c72c587a-dbb9-9d8d-2316-caa66c90e14a.png)

GetFlowアクションを利用し、コピー対象の Flow (今回はtemplateFlow)を選択します。
それぞれの変数に対して、のちに接続先情報として利用する値を PowerApps 上から受け取るようにします。

- FlowName = フローの名前です。わかりやすい名前であれば何でも構いません。名前が同じ場合自動的に後ろに数字が追加されます。エラーにはなりません。
- OutlookConnectionName = これが今回のキーマンです。ユーザーの接続情報によって値が変化します。
- OutlookApiId = OutlookのConnecterIDです。ユーザーによって変化はしません。利用するAPIごとに変化します。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/183354/059b5c25-fbe2-3160-51ef-e2c16d271978.png)

### Create Flow

最後に Create Flow です。
図のようにそれぞれに値を入力していきます。

#### Flow Definition
Flow の定義が書かれているオブジェクト型の JSON です。いわば Flow の本体です。
ただし、Flow Definition はオブジェクト型を要求しているのですが、なぜか入力時にオブジェクト型の変数が選択できません。かといって文字列の JSON を入力すると、400 エラーが返されるので、ここの値を変数などに変えたい場合は、選択するのではなく式 variables() を利用して、入力するようにしましょう。

#### Flow State 
Flow State は任意で構いません。今回はいちいち動かれると面倒だったので、Stopped（停止）でコピーするようにしています。

## 3 PowerApps を実装する

とはいっても簡単で、PowerAppsにも FlowManagementコネクタがあるのでその中の 2 つの関数を利用します。

以下の関数を利用します。

```
Flow.ListUserEnvironments().value
```

こちらの関数は自分が属している環境が配列で取得できます。
式にすると例えばこんな感じですね。

```
ClearCollect(EnviromentCollection,Flow.ListUserEnvironments().value)
```

もう１つはこちらです。

```
Flow.ListConnections("環境ID").value
```

こちらの関数は指定した環境の中で自分が接続として設定しているコネクタと Flow が取得できます。
こちらも式にしてみると、

```
ClearCollect(EnviromentConnectionCollection,Flow.ListConnections("環境ID").value)
```


### point
この状態だと、接続としてコネクタを設定していないので表示されず、結局コネクタをユーザーに作らせてしまうことになるので、**データソースで今回利用するOutlookをあらかじめ設定しておきます**。（データソースとして追加するだけで実際には利用しません。）
こうしておくことで、アプリを実行したときに、コネクタがない場合、**自動的にコネクタを作成してくれます**。

Flow.ListConnectionsから値が取得出来たらその中の

```
name
```

と

```
properties.apiId
```

を利用します。
これらの値がそれぞれ以下のようになります。

| FlowName  |      PowerApps property |  
|:-----------------|------------------:|
| OutlookConnectionName              |              name|    
| OutlookApiId |           properties.apiId |  

最後にこれらの値を先ほど工程２で作成したFlowに対して渡すようにして Run() すると完成です。


```
POSTTemplateCopyFlow.Run("Flowの名前",name,apiId)
```


# まとめと今後の展開

## 注意点

- コピーする Flow は必ず共有されていることが条件です。(JSONファイルに分けておけば実は共有する必要すらありませんがこれは次の機会に...)。毎回ユーザーに対して共有するのがめんどくさい場合は、共有先にグループが設定できますので、 Microsoft Teams で全社員を自動的に追加するグループが作れますので、そのグループを指定するといいと思います。
- PowerApps から Flow を利用すると接続先が切り変わるよ！
- Flow Definition は事前に作られているオブジェクト型を指定しないとだめだよ！中で json(stringvalue)をやってもエラーになるよ！だけど、選択肢にオブジェクト型の変数は出てこないから注意してね！

## 感想
　いかがだったでしょうか？この仕組みを利用することで、Flow を共有するのに、Zipでダウンロードなどの必要がなく、ユーザーは簡単に利用したい 共有されている Flow を自分用の接続に変更してマイフローにコピーすることができます。

　PowerPlatform は確かにユーザー自身で簡単にアプリを作成でき便利ですが、保守運用まで考えた構成を作るには少しコツが必要です。アプリケーションに関しての情報がきちんと共有されない場合は、よくあるExcelのVBAのように作った人しかわからないといったことが容易に起こりえます。ましてや、そういった操作をするのは開発者ではないので、PowerApps や Flow を使ったシステムの構築できる人は、次のステップとして保守運用まで自動化するシステムの構築を考えてみてはいかがでしょうか？

## まだ試せてないこと

1. 同じような形で PowerApps アプリケーションの自動作成（理論上はできるはず。ただ delete はあっても create がない...）
2. 別テナントの Flow をコピー（環境招待されていることが前提）

これらの情報をお持ちの方コメントを頂けると助かります。