入力が多いリストに対してデータを登録する場合、一つのフォームで入力させるとどうしても長いスクロールが発生したり、あるいは複数列のフォームを用意する必要があります。
よくWebのフォームで見るような「次へ」「戻る」が付いたウィザード形式のフォームをの作成には挑戦してみたのですが、いくつか方法があったので、簡単ではありますが作成する上での考え方やメリット等をご紹介します。
対象とするリスト (のフォーム) はこのようなものを考えます。一部が必須であったり、データ型もバラバラにしてあります。
ウィザード形式ではありますが、画面遷移が必須なわけではありません。今回も基本的には一画面で収まるように設計します。
1. フォームを分割して差分更新
まずはオーソドックスなフォームを分割する方法の1つ目、フォームを分割して各ステップでアイテムを差分更新する方法です。
ここでのポイントは、1ステップ目では新規登録、2ステップ目以降では更新。その際 Form.LastSubmitを利用するところです。
この例では画面には3つのフォームを追加しています (Form1_1~Form1_3)。
「つぎへ」「完了」ボタンはいずれも SubmitForm(Form1_X)
を設定しているので、毎回データソースに対して登録・更新処理が行われます。
1フォーム目とそれ以降で異なるのは、DefaultMode
プロパティです。1フォーム目ではまずアイテムを追加するので FormMode.New
で開始するのに対して、2フォーム目以降では最初に登録したアイテムを更新していくので FormMode.Edit
を使います。
更新する際には、1フォーム目で登録したアイテムを指定する必要があるので、そのために Form1_1.LastSubmit
を利用して、2フォーム目以降の Item
プロパティを指定します。
いいところ
この方法では、毎回データソースに登録・更新を行うので、各ステップで適切なデータバリデーションが行われます。(必須チェックとか文字列長など)
これは他の方法では実現しにくいので大きなメリットと言えます。
むずかしいところ&改善策
問題になるのは「作成途中でユーザーが離脱した場合に中途半端なデータが残ること」です。
最初のフォームで新規登録してしまうので、この問題は回避はできません。緩和策としてはデータの登録状態を管理することです。
最初のフォームでは「下書き」でアイテムを作成し、最後のフォームで「本登録」に更新します。これで途中でユーザーが離脱しても、そのデータが入力完了なのか、途中なのかが区別できます。
ゴミが残ることを避けるなら、夜間にPower Automateを利用して、「下書き」ステータスのアイテムを一括削除することを検討してください。
また、必須の列がある場合、最初のフォームで初期値を与えないとエラーになるので、入力順序には注意が必要です。
もし必須列が複数ステップにわたる場合には、列側に初期値を設定しておくようにするとよいでしょう。
2. 複数フォームを用意して最後に一括登録
1つ目の方法は最初に登録を行い、その後差分更新をしていきましたが、最後のフォームでまとめて登録できれば「下書き残る問題」は回避できそうです。
フォームには入力により更新されたデータを表す Form.Updates
というプロパティがあり、これとPatch()
関数を組み合わせることで、分割された各フォームのデータを纏めて登録できます。
1つ目の方法と異なり、フォームのDefaultMode
はすべてFormMode.New
で統一されています。実際に画面に配置する際には「つぎへ」ボタンでフォームを表示/非表示することで次のフォームにユーザーを誘導します。
利用する式もシンプルですし、ほとんど設定の変更が必要ないので、作りやすさとしては一番簡単かもしれません。(フォームの表示/非表示は変数を利用しますが、それを避けたいのであれば画面遷移させればよい)
いいところ
上でも書いた通り、とにかくシンプルです。設定の手間が一番少ない方法と言えますし、ステップをさかのぼる (「戻るボタン」) 対応も容易です。
むずかしいところ&改善策
通常、データのバリデーションはSubmitForm時に自動で行われますが、この方法はデータ登録にPatch()
関数を使っているので、データバリデーションが自動ではできません。
Patch前に何らか手動でバリデーションを行うことが最も単純な回避策です。フォーム側の設定が容易であることとのトレードオフになっています。
もう一つ、「追加の最終確認画面を入れる」ことでも回避できます。※この場合にはSubmitFormを利用するのでもはや別の方法
4つ目の入力内容確認フォームではすべてのフィールドを表示にします。さらに1~3つ目のフォームの内容を反映させるために、各DataCardValue
コントロールのDefault
プロパティに対して、先ほども利用したForm.Update
を指定します。
これによりまとめて登録で自動でバリデーションも行うことができ、エラーが出ればその画面内で修正も可能になります。
1点、面倒なのは各DataCardValueのDefaultを加工するところです。1~3のフォームが簡単になることとのトレードで4つ目の確認フォームが少し面倒になります。
3. ステップを定義して最後に一括登録
1,2 の方法では、物理的にフォームを分割 (複数フォームコントロールを用意) していましたが、3つ目の方法は 1つのフォームで表示切替 を行うことで疑似的に複数枚のフォームを表現します。
入力段階を表す変数として varStep
を導入してみます。
フォームの各フィールドの Visible
プロパティには varStep=1
のように、どのステップで表示させたいかを設定します。
あとは「つぎへ」ボタンで varStep
を一つずつ上げていくだけです。最後のステップになったら、「登録」ボタンを表示させて、SubmitForm()
してあげましょう。
他の方法に比べてわかりづらいので、以下のツイートで動作を見てみてください。
とりあえず pic.twitter.com/kV8LXM7M9E
— Hiro (@mofumofu_dance) December 24, 2020
いいところ
コントロールが少なくて済むのは良いですね。設定を変えなくてはいけないとき (列追加など) でも、基本的には全フィールド表示させて varStep=XX
を指定するだけなので、それほどアプリ側の対応も多くありません。地味なようですが、コントロールの少なさって結構大事ですよね。
また、一回で登録を完了させるので、ゴミが残る心配もありませんし、SubmitForm()
するのでバリデーションも自動でやってくれます。
むずかしいところ&改善策
最後の入力ですぐにSubmitしてしまうと、バリデーションエラーになったときに非表示のフィールドでエラーが発生、ユーザーがそれを修正できないという事態になりえます。
この点については2.と同様、確認ステップを追加し、そのステップでは全フィールドを表示させることで回避できます。
※その際にはVisible : varStep=1 || varStep=4
のように設定する必要があります。
また、画面を切り替えたいという要望に対してはなかなか素直に対応できないですね。画面の背景を変えるとか、フォーム外の文章を切り替えるといった要望に対しては、それらのコントロールもvarStep
で切替る必要があります。
まとめ
入力項目の多いデータ登録では、複数フォーム・複数ステップでユーザーに入力させること自体は有効な手段だと思います。
Power Appsでフォームコントロールを利用することを前提に、実装方法を考えると、大きくは「フォーム自体をわける」か「表示するフィールドを変数で制御」の2パターン化と思います。
おそらく、共通して言えるのは「確認画面はいずれにせよ必要そう」ということです。(デメリットの回避のためにも)
上で紹介したパターン以外にもいろいろと試してみて最適なものを状況に応じて使い分けできると、さらに活用の幅が広がるのではないでしょうか。