【Power Apps】数値入力を楽にする|前回記録の自動参照の作り方

Power Apps「Torelog」の記録画面。種目選択時に前回記録のRepsとTotalSetsが自動入力され、±ボタンで数値を調整できる画面イメージ Power Apps

この記事でできること

最近、Power Appsで自重トレーニング用のアプリを作っています。トレーニング記録を入力するのですが、おおよそ前回と同じくらいの回数を入力することが多く、Defaultの値から離れていると少し手間に感じます。
この記事では、Power AppsのEditFormに以下の3つの機能を追加した実装を紹介します。

  • 種目を選ぶだけで前回の回数・セット数が自動で入る
  • ボタンで前回値から微調整できる
  • 新規入力と編集モードを背景色で見分けられる

今回のサンプルは自作筋トレ記録アプリ「Torelog」での実装ですが、他のEditFormにも応用できる内容です。

完成イメージ

種目を選ぶと前回記録のReps・TotalSetsが自動表示されているフォーム画面

種目を選んだ瞬間に前回の回数とセット数が自動で入り、「<<,<, >, >>」ボタンで数値を微調整できます。また新規入力時は薄緑、編集時は薄青色で背景色が切り替わります。

全体の実装構成

今回の実装で使う変数とコントロールを整理しておきます。

変数名種類用途
gLastRecordグローバル変数選択した種目の前回記録を保持
locRepsローカル変数Reps入力欄の値を管理
(ボタン連動)
locTotalSetsローカル変数TotalSets入力欄の値を管理(ボタン連動)

locRepsとlocTotalSetsは、ローカル変数(UpdateContext)として使用するので、App.OnStart ではなく MainScreen.OnVisible で初期化します。

// MainScreen.OnVisible
UpdateContext({locReps: 20, locTotalSets: 3})

実装① 種目を選ぶと前回記録が自動で入る仕組み

OnChangeで最新記録を取得してgLastRecordに保存する。

種目ドロップダウン(ExerciseNameDataCardValue)の OnChange プロパティに以下を設定します。

// ExerciseNameDataCardValue の OnChange
Set(
    gLastRecord,
    First(
        SortByColumns(
            Filter(
                WorkoutLog,
                ExerciseName = ExerciseNameDataCardValue.Selected.タイトル
            ),
            "RecordedAt",
            SortOrder.Descending
        )
    )
);

UpdateContext({
    locReps: If(
        IsBlank(gLastRecord),
        20,
        gLastRecord.Reps
    ),
    locTotalSets: If(
        IsBlank(gLastRecord),
        3,
        gLastRecord.TotalSets
    )
})

やっていることは2段階です。

まず Filter で選んだ種目の記録だけに絞り、SortByColumns で RecordedAt(記録日時)の降順に並び替えます。その先頭1件を First で取り出して gLastRecord に保存します。

次に UpdateContext で locReps と locTotalSets を更新します。前回記録があればその値、なければデフォルト値(Reps 20・TotalSets 3)をセットします。

ExerciseNameDataCardValueを選択している画面とツリービュー
ExerciseNameDataCardValueのOnChangeプロパティにgLastRecordを取得するFilter・SortByColumnsの式が入力されている画面

locReps・locTotalSetsで入力欄の値を制御する

RepsDataCardValueとTotalSetsDataCardValueの Default プロパティをローカル変数に統一します。

// RepsDataCardValue の Default
Text(locReps)

// TotalSetsDataCardValue の Default
Text(locTotalSets)

ここで Text() で包んでいるのは、EditFormのDataCardValueが Text型を要求するためです。数値をそのまま渡すとエラーになります。

また、編集モードでギャラリーの行をタップした時は、既存レコードの値をローカル変数にロードします。

// WorkoutLogGallery の OnSelect
Set(gSelectedRecord, ThisItem);
UpdateContext({
    locReps: ThisItem.Reps,
    locTotalSets: ThisItem.TotalSets
})
WorkoutLogGalleryのOnSelectプロパティにgSelectedRecordのセットとUpdateContextの式が入力されている画面

これで新規モードは「前回記録またはデフォルト値」、編集モードは「既存レコードの値」が入力欄に自動で表示されます。

実装② ボタンで回数・セット数を調整する

ボタンはDataCard直下にXY座標で配置する

DataCard内にボタンを置く際、コンテナでまとめようとするとエラーが起きます。DataCard内にコンテナを挟むと Parent.Default がそのコンテナを参照してしまい、DataCardValueが正しく動かなくなります。

ボタンはDataCard直下にXY座標で直接配置して設置します。

RepsDataCardの直下にコンテナを使わずボタン4つとDataCardValueが配置されているツリービューの画面
RepsDataCardに配置されているボタンの画面

DataCardValueのDefaultはText(locReps)に統一する

各ボタンの OnSelect には UpdateContext で加減算を書きます。

// RepsMinus10Button の OnSelect
UpdateContext({locReps: Max(1, Value(RepsDataCardValue.Text) - 10)})

// RepsMinus1Button の OnSelect
UpdateContext({locReps: Max(1, Value(RepsDataCardValue.Text) - 1)})

// RepsPlus1Button の OnSelect
UpdateContext({locReps: Value(RepsDataCardValue.Text) + 1})

// RepsPlus10Button の OnSelect
UpdateContext({locReps: Value(RepsDataCardValue.Text) + 10})

Max(1, …) を入れることで、0以下にならないようにしています。

RepsMinus10ButtonのOnSelectプロパティにUpdateContextでlocRepsを減算する式が入力されている画面

実装③ 新規・編集モードを見た目で区別する

新規と編集のどちらで操作しているかをひと目でわかるようにします。

RecordButtonのTextでボタンラベルを切り替えます。

// RecordButton の Text
If(RecordForm.Mode = FormMode.Edit, "✏️ 更新する", "✅ セットを記録")

FormContainerのFillで背景色を切り替えます。

// FormContainer の Fill
If(RecordForm.Mode = FormMode.Edit, gTheme.MainLight, gTheme.NewRecord)
薄緑背景の新規入力モードになっているフォーム画面
薄青色背景の編集モードになっているフォーム画面
App.OnStartのカラーテーマ設定画像

ハマりポイントまとめ

実装中に引っかかったポイントを整理します。

① DataCardValueはText型を要求する

locReps は数値型のローカル変数ですが、DataCardValueの Default に数値をそのまま渡すとエラーになります。Text(locReps) のように Text() で包みます。

② コンテナを挟むとParent.Defaultが壊れる

DataCard内にコンテナを追加してDataCardValueを中に入れると、Parent.Default がコンテナを参照してしまいエラーになります。ボタンはコンテナを使わず、DataCard直下にXY座標で直置きします。

③ SubmitForm後にFormModeがViewに変わる

SubmitFormが成功するとフォームは自動的に FormMode.View に切り替わります。If(RecordForm.Mode = FormMode.New, Patch(…)) のように記録後に判定しようとしても、すでにNewではなくなっています。SubmitFormを呼ぶ前に Set(gIsNew, RecordForm.Mode = FormMode.New) で変数に保存しておく必要があります。

RecordButtonのOnSelectプロパティに、SubmitForm前にモードを変数に保存している関数が記載されている画面

④ キャンセル・記録完了時のlocRepsリセット忘れ

ローカル変数はリセット操作を明示的に書かないと前の値が残ります。CancelIcon・RecordButtonのOnSelectにはそれぞれリセット処理を追加してください。

// CancelIcon の OnSelect
Set(gSelectedRecord, Blank());
ResetForm(RecordForm);
UpdateContext({locReps: 20, locTotalSets: 3})

// RecordButton の OnSelect(末尾に追加)
Set(gSelectedRecord, Blank());
ResetForm(RecordForm);
UpdateContext({locReps: 20, locTotalSets: 3})

まとめ

今回の実装のポイントをまとめます。

  • OnChange で前回記録を gLastRecord に保存し、UpdateContext でローカル変数に展開する
  • DataCardValueの Default はすべて Text(locReps) 形式で統一する
  • 加算減算ボタンはDataCard直下にXY座標で配置する(コンテナ不使用)
  • ローカル変数のリセットは記録完了・キャンセルの両方で明示的に書く
  • 編集モードとの区別は FormMode.Edit を使ってボタンラベルと背景色で表現する

今回は「前回値の自動参照」と「ボタン」という地味な改善ですが、毎日使うアプリほどこういった入力の手間がじわじわ効いてくるのでおすすめです。

Power Platformを触り始めたばかりの方に向けて、こういった詰まりポイントをこれからも発信していきます。よかったらブログをブックマークして、またのぞきに来てください!

あわせて読みたい

この記事の前に読むとスムーズです。後から直しやすいアプリの設計はこちら。

【Power Apps】後から直しやすいアプリの設計|命名規則・カラーテーマ管理・バリデーション
Power Appsで後から直しやすいアプリを作るための設計のコツを4つ紹介。コントロールの命名・gThemeによるカラー管理・ボタンの状態別色設定・バリデーションの実装まで、コピペできるコードつきで解説します。

コメント

タイトルとURLをコピーしました