SharePointのリスト登録画面をPowerAppsでフォームカスタマイズ

#はじめに
MicroSoftのSharePointとPowerApps＆PowerAutomateを使って、とあるフォームカスタマイズとリスト管理をする機会があるので、勉強がてらにどのように作るのかを備忘録がわりに残す。
今回の記事はPowerAppsのカスタマイズをメインとする。

プライベートで勉強するようにこちらの記事を参考しにして、開発者用プログラムに登録して各サービスを利用できるようにした。
・[PowerAppsを個人で無料で始める](https://www.powerplatform.work/blog/2020/08/04/PowerApps%E3%82%92%E5%80%8B%E4%BA%BA%E3%81%A7%E7%84%A1%E6%96%99%E3%81%A7%E5%A7%8B%E3%82%81%E3%82%8B/)

#作るもの
ファームの画面イメージや仕様
##完成イメージ
作成済みリストの[新規]ボタンをクリックして表示される申請フォームのイメージ
![スクリーンショット 2021-05-02 1.11.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955833/dee10884-6608-96c3-f094-88a7eead355b.png)

なお、PowerAppsでのツリービューはこのように作成し、
AppliciateFormにフィールドを追加する。
![スクリーンショット 2021-05-04 18.01.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955833/4fb76631-9733-4e5f-0eac-d6bbf281f19f.png)


##仕様
前提は下記のようになる。

+ 画面イメージは新規フォーム
+ 空白列は新規の際、空白にする
+ 既に入力されている値は自動入力となる
+ 必須項目は値が入力されていないと黄色背景になる
+ ドロップダウンやラジオボタンは合わせる

|列|仕様|
|---|---|
|作成者|編集不可能。画面表示と共にサインインしているアカウント名を表示|
|申請者|入力必須。画面表示と共にサインインしているアカウントを自動入力|
|申請者：連絡先|画面表示と共にサインインしているアカウントの会社連絡先を自動入力|
|部門|入力必須。部門リストから選択する|
|申請種別|選択肢をラジオボタンで表示。値は選択肢の値をそのまま入力|
|顧客名|入力必須|
|プロジェクト名|入力必須|
|リージョン|入力必須。リージョンリストから選択する|
|使用数|入力必須|
|START|入力必須。ヒントテキストを表示|
|END|ヒントテキストを表示|
|〜必ずチェック|リージョンが「東リージョン」か「北リージョン」が選ばれたら表示。選択肢をラジオボタンで表示|
|連絡事項|★下記詳細|
|利用番号|編集不可能|
|利用箇所番号|編集不可能|
|申請ボタン|保存と同義|

※リージョンリストや部門リストなどについては下記別途記載

###連絡事項について
左側に入力するボックス、右側に連絡事項の履歴を表示するようにする。
例えば、新規作成のとき連絡事項に「こんにちは」と入力して保存した後、編集画面でのイメージはこちら
![スクリーンショット 2021-05-02 1.35.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955833/4025164b-2dca-8e3e-e372-2acefde71af2.png)
コメントした人＆時間＆内容が履歴的に閲覧できる。再度この状態で、編集すると履歴に追加される。履歴（右）は編集できない仕様で、入力（左）はリセットされて、ヒントテキストが表示される。

#準備
PowerAppsの具体的な設定の前に、SharePointの事前設定をする
##メインリスト
Sharepointでカスタマイズフォームの元となるリストを下記の列に合わせて作成する。
なお、今回の申請フォーム（PowerAppsカスタマイズ）で触れない列もあるが、管理フォーム（PowerAppsのカスタマイズ）やPowerAutomateで利用する列となるため、このタイミングで作成する。

|列|種類|必須|
|---|---|---|
|顧客名|1行テキスト|●|
|更新日|日付と時刻||
|作成日|日付と時刻||
|プロジェクト名|1行テキスト|●|
|リージョン|1行テキスト|●|
|ゾーン|1行テキスト||
|使用数|数値|●|
|申請種別|選択肢|●|
|申請者|ユーザーまたはグループ|●|
|申請者：連絡先|1行テキスト||
|部門|1行テキスト|●|
|CC先|ユーザーまたはグループ||
|START|日付と時刻|●|
|END|日付と時刻||
|利用番号|1行テキスト||
|利用箇所番号|1行テキスト||
|連絡事項|複数行テキスト||
|ステータス|1行テキスト||
|処理選択|1行テキスト||
|バックオフィス通知有無|はい/いいえ||
|東用チェック|選択肢||
|リージョンエリア|1行テキスト||
|課金開始月|数値||
|オーダ|1行テキスト||
|予約課金回答|選択肢||
|回答期日|日付と時刻||
|予約課金フェーズ|1行テキスト||
|取消理由|複数行テキスト||
|最終依頼日|日付と時刻||
|割当回答日|日付と時刻||
|作成者|ユーザーまたはグループ||
|更新者|ユーザーまたはグループ||

##選択肢と選択肢リスト
フォームの中、ドロップダウンやラジオボタンで複数選択の中から選択する項目がある。下記観点で選択肢とするか、１行テキストでリスト制御にするかを分けた。

+ 選択肢｜今後変わることがないと思われる選択肢
+ リスト制御｜定期的に変化する選択肢

選択肢の場合は、SharePointリストの選択肢で、値を直接入力した。
リスト制御の場合は、選択肢リストを作成し、対象列を選択肢リストで制御する設定をPowerAppsで行う。

|列|制御|備考|
|---|---|---|
|リージョン|リスト制御|リージョンリストを作成|
|ゾーン|リスト制御|リージョンリストに合わせたゾーンリストを作成|
|申請種別|選択肢|リスト設定の選択肢で値設定|
|部門|リスト制御|部門リストを作成|
|ステータス|リスト制御|ステータスリストを作成|
|処理選択|リスト制御|ステータスリストを作成|

一旦、この状態でリストフォームのカスタマイズを行う。
PowerAppsの立ち上げ基礎はググったりこちらを参考にして欲しい
[PowerAppsでSharePointのフォームをいじってみる](https://tech.la-fra.com/2018/08/11/post-256/)

#PowerApp設定
##下準備
立ち上げができたら、まずは下記を行う

+ スクリーンやフォームの名前をリネームする
+ フォームの規定モードを新規にする
+ フォームのグリッド列を12にする

その後に、必要な列（フォールド）を追加する。
フォームのプロパティにある[フィールドの編集]で追加できる。
グリッドを使った位置調整などはめんどくさいが、Width/Height、X/Yの値を駆使してうまくやる。

##グローバル変数
アプリが立ち上がったら（画面がでたら）、このアプリで何度か使う値を変数化して格納させる。
★ツリービューの[App]で、OnStart関数に値をセット

```:グローバル変数
Set(_userName,Office365ユーザー.MyProfileV2().displayName);
```

※[参考サイト](https://news.mynavi.jp/article/powerapps-9/)

もし、苗字と名前が逆転していれば、こちらを参考にする

```:姓名の逆転
Concatenate(Last(Split(User().FullName," ").Result).Result," ",
First(Split(User().FullName," ").Result).Result)
```

##必須項目の背景
共有項目として、必須項目は値が入力されていないと黄色背景になるようにする。値が入力されると白色背景にする。
カーソルが当たっている時（ホバー）とそうでない時に背景色が分岐するので、項目によっては２箇所値を変更する。

###1行テキスト
```:ValueカードのFill＆HoverFill
If(
    IsBlank(〇〇〇Value.Text),
    RGBA(255, 255, 0, 1),
    RGBA(255, 255, 255, 1)
)
```

###リスト選択肢
```:ValueカードのFill＆HoverFill
If(
  IsBlank(〇〇〇Value.SelectedText),
  RGBA(255, 255, 0, 1),
  RGBA(255, 255, 255, 1)
)
```

###ユーザ選択肢
```:ValueカードのFill＆HoverFill
If(
    IsBlank(〇〇〇Value.Selected),
    RGBA(255, 255, 0, 1),
    RGBA(255, 255, 255, 1)
)
```

###日付
```:ValueカードのFill
If(
    IsBlank(〇〇〇Value.SelectedDate),
    RGBA(255, 255, 0, 1),
    RGBA(255, 255, 255, 1)
)
```

##選択肢のドロップダウンからラジオボタンに変更
ドロップダウンをそのまま、ラジオボタンに変更することはできなさそうだったので、下記で対応。

1. 変更したいDataCardにラジオボタンを追加
２. 元々あったValueカードを削除
3. ラジオボタンを削除したValueカードと同じ名前にリネーム

##作成者（ユーザ名）の初期値表示
作成者はSharePointのデフォ機能で、新規保存されたと同時に自動的に値が補完される項目のため、ユーザ側で値を指定することができないようだった。
そのため新規画面と編集・ビュー画面で可視化されるコンポーネントを切り替えることで対応した。

+ 新規画面｜Valueカードを非表示、自動入力されたLabelカードを表示
+ 編集画面｜値保存済みのValueカードを表示、Labelカードを非表示

Valueカードと同じサイズ・位置にLabelカードを配置する。
その後、下記のように値をセットいていく

```:作成者ValueカードのVisible関数
If(
    AppliciateForm.Mode = FormMode.New,
    false,
    true
)
```

```:作成者LabelカードのVisible関数
If(
    AppliciateForm.Mode = FormMode.New,
    true,
    false
)
```

```:作成者LabelカードのText関数
_userName
```

##申請者（ユーザ名・ユーザ情報）の初期値表示
新規申請しようとしているユーザ情報をデフォルトで入力されているようにする。２パターン記載したが、どちらか都合の良い方を使う。
今回は、②で作成した。
※[参考サイト１](https://trivia365.hatenablog.com/entry/2020/02/10/212653)
※[参考サイト2](https://ippu-biz.com/development/powerplatform/powerapps/control-combobox/)

```:ValueカードのDefaultSelectedItems関数
①
{
　　Claims: "i:0#.f|membership|" & Lower(User().Email),
　　Department: "",
　　Email: User().Email,
　　DisplayName: _userName,
　　JobTitle: "",
　　Picture: ""
}

②
LookUp(Office365ユーザー.SearchUserV2().value, Mail = User().Email)
```

なお、Office365ユーザ対応はこちらの記事を参考にして、修正が必要があるかもしれない。
※[参考サイト](https://news.mynavi.jp/article/powerapps-9/)

また、異なるユーザで確認したとき申請者がサインインユーザに変わってしまう。ここは別途修正方法を検討する。

##連絡先の初期値表示
新規登録しようとしているユーザの職場の電話（連絡先）を自動取得させる。

```:ValueカードのDefault関数
If(
    AppliciateForm.Mode = FormMode.New,
    First(Office365ユーザー.MyProfileV2().businessPhones).Value,
    ThisItem.'申請者：連絡先'
)
```

##部門のドロップダウン（選択肢は部門リスト）
まずコントロールの種類を「テキストの編集」から「許可値」へと変更。また、データソースの新規追加で部門リストも接続する。
※[参考サイト](https://ippu-biz.com/development/powerplatform/powerapps/link-dropdown/)

```:DataCardのUpdate関数
DepartmentCategoryValue.Selected.Result
```

```:Valueのitem関数
Distinct(部門リスト,Title)
```

この状態だと、ドロップダウンの初期値が勝手に表示されるので、初期値を空白にする設定もする。

```:ValueのAllowEmptySelection関数
true
```

※[参考サイト](https://qiita.com/yamad365/items/18d50ab976d4ede96d13)

リージョンのドロップダウンも同じ設定を行う。

##申請種別の編集時リセットされる問題
編集画面時、新規申請で選んだ値が表示されない。値は選ばれた状態にしたいので、下記を設定

```:ValueのDefault関数
If(
    ApplicantForm.Mode = FormMode.New,
    "",
    ThisItem.申請種別.Value
)
```

東・北リージョンのチェック欄も同じ設定を行う。

##日付のヒント表示(2001年）を変更する
初期状態ではヒントテキストのような形で、2001年〜の日付が入力されているように見えるので、文字列に変更する。

```:ValueのInputTextPlaceholder関数
If(IsBlank(Self.SelectedDate), Text("〇〇日を入力", Self.Format, Self.Language))
```

##東・北リージョンのチェック欄
東・北リージョンのチェック欄は、リージョンが東リージョンか北リージョンが選択されたら表示するようにする。言い換えれば、西リージョンが選択されたら非表示にする。

```:DataCardのVisible関数
If(
   Or(RegionValue.SelectedText.Value = "東リージョン",
      RegionValue.SelectedText.Value = "北リージョン"),
   false,
   true
)
```

##利用番号と利用箇所番号は編集させない
```:DataCardのDisplayMode
View
```

##申請ボタンのクリックで保存
```:onClick関数
SubmitForm(ApplicantForm)
```

##連絡事項の履歴表示
仕様に記載した通り、複雑な処理が必要になる。まずは、こちらを行う。

1. 連絡事項DataCardにラベルを追加する。今回はValue_historyを命名。
2. 元々のValueカードを左に、追加したラベルカードを右に配置
3. 追加したラベルカードの表示モードはビュー
4. 左のValueカード内容を開くたびに値をリセットさせる
 
```:ValueのReset関数
true
```

5. 左のValueカードにヒントテキストを表示させる

```:ValueのHintText関数
"連絡事項や質問はこちらに記載"
```

6. 保存されるたびに、右のhistoryに内容を追記させる。

```:DataCardのUpdate関数
If(
    IsBlank(ContactValue.Text)||IsEmpty(ContactValue.Text),
    ContactValue_history.Text & " ",
    "■" & _userName & "｜" & Now() & "■" & Char(10) &
    ContactValue.Text & Char(10) &
    "---------------------" & Char(10) &
    Char(10) &
    ContactValue_history.Text & Char(10)
)
```

編集時の連絡事項を空白の場合の条件について、ContactValue_history.Textだけだと何故か値がリセットされてしまうので、イレギュラー対応として、ContactValue_history.Text & " "の形とした。

#今後の課題
##各DataCardの枠線を表示
編集モードでも表示モードでも枠線を表示させたいが、設定ではどうしようもなさそう。
https://zezeze.hateblo.jp/entry/2020/03/30/152634

##ビューと編集モードの細かい見た目修正
今回記載していないが、見た目やユーザビリティを考慮して修正は必要

##IsBlankとIsEmpty
空判定している箇所について、IsBlankを使うべきかIsEmptyを使うべきかわかっていないため、その辺りは別途検討が必要。

#最後に
まずは申請フォームを作成したので、次は管理画面フォームを作成する。
（ただ、ワークフローも作成するので、どっちが先か迷いどころ）