Param関数で外部から値を受け取り、アプリを制御する

この記事は[PowerApps Advent Calendar 2019](https://qiita.com/advent-calendar/2019/powerapps)に参加しています。
12/4のAdvent Calendarが空いてたので、別の日に出す予定だった内容の一部を先出し。
#Param関数
今回は**Param関数でアプリ起動時の挙動を制御する**お話です。
細かい仕様がMicrosoft Docsに書かれていないので、そこも含めて書いていきます。
[キャンバスアプリでの Download、Launch、および Param 関数](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-param)
##Param関数の仕様
Param関数は**アプリを起動した際にパラメータを受け取ります。**
###パラメータの設定
パラメータはアプリのWebリンク(URL)の後ろに`?パラメータ名=値`を付け足して設定します。

構文は以下の通りです。

```html:パラメータ付きURL
https://apps.powerapps.com/play/アプリID?tenantId=テナントID&パラメータ名=値
```
これをParam関数で`Param("パラメータ名")`として受け取る事で、**アプリ内でパラメータの値を利用できます。**
###複数パラメータの設定
複数のパラメータを設定する場合は、`?パラメータ1=値&パラメータ2=値`のように`&`を間に挟みます。
なお、make.powerapps.comから取得できるアプリのWebリンクは、tenantIdが既にパラメータとして設定されているので`&パラメータ名=値`でも構いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/1d20bf2b-7cb5-4c0a-d986-f5b2793cf3b9.png)
###戻り値
Param関数は引数に設定したパラメータを元に、データ型が自動でテキスト型か数値型になります。
**引数のパラメータが存在しない場合、Blankをテキスト型で返します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/fa83bd72-7f4e-4fef-0ae6-f9f52c6aefa4.png)

なお、create.powerapps.com/studio上でのParam関数は必ずBlankです。

このような特徴から、アプリ作成中に数値型のデータとParam関数を比較演算子で繋いだ場合、データ型の不一致で「互換性が無い型」の警告が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/61001fd8-18d1-d781-69b9-9ec05cda90ca.png)
**パラメータの値が数値であれば、警告を無視しても問題なく動きます。**
以下のように、データ型は入力されたパラメータの値を元に設定されるからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/27178674-7af5-f2ae-1155-e8996b124391.png)
警告が気になる場合は、`Value(Param("spoid"))`とValue関数でラッピングすれば消えます。

###使用上の注意点
**Param関数は同時に複数のパラメータを受け取れません。**
**受け取るパラメータの数だけParam関数が必要です。**

```html:複数パラメータ付きURL
https://apps.powerapps.com/play/アプリID?tenantId=テナントID&パラメータ1=値&パラメータ2=値
```
このような場合はパラメータを以下のように別々に取得します。

1. パラメータ1を取得
    - `Param("パラメータ1")`
2. パラメータ2を取得
    - `Param("パラメータ2")`

##番外編 : Launch関数でパラメータを設定
**Launch関数を使えばアプリ上から他のアプリを起動し、パラメータを渡せます。**
[キャンバスアプリでの Download、Launch、および Param 関数](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-param)

使い方はの第一引数にアプリのURLを設定し、それ以降にパラメータを設定します。
`Launch("URL","パラメータ1",パラメータ1の値,"パラメータ2",パラメータ2の値, ...)`

パラメータの値におけるデータ型は、数値、もしくは`""`で囲んだテキスト型のどちらかです。

```C#:Launch関数パターン
Launch("https://apps.powerapps.com/play/アプリID","spoid",2) ///数値型
Launch("https://apps.powerapps.com/play/アプリID","spoid","2") ///テキスト型
```

#Param関数でアプリを制御する
では実際にアプリを制御してみましょう。
##アプリを開くと指定の画面へ移動し、特定のアイテムを表示する
以下のような事が出来たら便利な場面は多いと思います。

- 特定アイテムの詳細画面が開いた状態でアプリが起動
- 特定のフィルターがかかった状態でアプリが起動

これらはParam関数を使う事で実現できます。
###この話の前提条件
データソースはSharePoint Online カスタムリストです。
**リスト名は`TestList`とします。
TestListはアプリ上のギャラリー`galSpoList`のデータソースです。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/a0c1d3c5-b51d-39f3-7524-9fbcb76cf39f.png)

###下準備
まず、**アプリに表示させたいリストアイテムを識別する一意の値を取得する必要があります。**
幸いSPOリストには既定で一意となるID列があるのでそれを使います。

設定するパラメータ名は`spoid`。
取得したいリストアイテムのIDは`2`です。

###パラメータの用意
まず、spoidを2を設定したURLを用意します。
`https://apps.powerapps.com/play/アプリID?tenantId=テナントID&spoid=2`

###パラメータの有無で、アプリ起動時に表示されるスクリーンを切り替える
**Power Appsアプリは、起動時にツリービューで一番上のScreenが表示される仕様です。**
以下の場合、アプリを起動するとScreen1が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/fa6d7462-0c56-1365-808b-8ebb7b8cc73e.png)
これを起動時にパラメータを受け取ったら、Screen2を表示するように設定します。

####アプリ起動時の制御
**AppのOnStartは、アプリ起動時に自動的に実行される動作を設定できます。**
事前にデータを読み込んだり、アプリで使うプルダウン用Collection作成などの用途で使われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/63097f2d-47d8-74fb-be52-b29e4f7224d9.png)
**このOnStartにParam関数を仕込むことで、起動後の画面を変更します。**

####パラメータが設定されているか判断する
まず、パラメータの値が設定されているかを調べます。
Param関数`Param("パラメータ名")`は**パラメータが無ければBlankを返します。**
よって`IsBlank(Param("spoid"))`でパラメータの有無を確認できます。

####起動画面を変更条件を設定する
パラメータの有無を条件にScreen2へNavigateします。
![Param関数画面移動.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/5cc4defe-5d84-b6b8-c963-545c88d083b9.gif)

#####構文

```C#:App.OnStart
If(
    !IsBlank(Param("spoid")),
    Navigate(
        Screen2,
        ScreenTransition.None
    )
)
```
###パラメータの有無で、表示するアイテムを切り替える
次はパラメータをアプリ内で利用する一例です。
Screen2にはTestListをデータソースにしたギャラリー(galSpoList)があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/870e3373-3884-e426-c18f-0053f548fba4.png)
これをパラメータがある時だけ、パラメータのアイテムのみを表示するように設定します。
####パラメータが設定されているか判断する
ここでも`IsBlank(Param("spoid"))`を使います。
####表示アイテム切り替え条件の設定
`Param("spoid")`がBlankなら`TestList`を、そうでなければIDをパラメータでフィルターした`TestList`を返します。
![Param関数フィルター制御.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313502/4e6a1cf2-5658-1e2b-295a-1165d65ddce8.gif)

ギャラリーgalSpoListに設定したItemsの構文は以下の通りです。
#####構文
```C#:galSpoList.Items
If(
    IsBlank(Param("spoid")),
    TestList,
    Filter(
        TestList,
        ID = Value(Param("spoid"))
    )
)
```
#まとめ

- **Param関数を使えばアプリ起動時に外部から値を渡せる**
    - この記事みたいにギャラリーのフィルターに使ったり、Power AutomateでURLを自動生成してパーソナライズされたアプリ表示にしたりと夢が広がります。
- **Param関数を使えばアプリ起動時の挙動をパラメータで制御できる**
    - パラメータはアプリが起動する前に値を定義できるので、起動時の制御と相性抜群です。
- **パラメータが無ければParam関数はBlankを返す**
    - これさえ覚えておけばIsBlank関数と組み合わせて幅広くアプリを制御できます。
- **複数のパラメータを読み込むには、パラメータの数だけParam関数が必要**
    - 面倒ですが仕様です。

Param関数は外部との連携や、アプリから他のアプリを起動するシナリオで必ず使います。
是非覚えてアプリをブラッシュアップして下さい。