Power AppsでのCopilot連携がプレビューとなったタイミングでボタンの自己呼出しが可能になりました。
これにより、今までタイマーでしか実現できなかった疑似ループがボタンでも実現可能になりました。
今回は、ボタンを疑似ループ化する際のサンプルコード並びにメリット・デメリットを紹介します。
ターゲットユーザー:開発者
ボタンによる疑似ループの基本形
以前のボタンは自身を選択する動作はエラーとなっていました。
現在は自身を選択することが可能になりましたので、OnSelectプロパティに以下を記述することでループ可能となります。
Select(Self)
上記コードにより自身が選択された瞬間に再度自身を選択します。
選択されるたび自身を再選択するわけですので、この1行のみでは無限ループとなりますし、実際には何もしません。
通常、どのループ処理においても終了条件を設定することが必須ですのでScreen.OnVisibleにもコードを追加し、Button.OnSelectを修正してみます。
/*
Screen.OnVisible
*/
Set(_Limit, 10); // ループの終了値
Set(_Step, 1); // ループごとの増減値
Set(_SEQ, 0); // 現在のループ回数
Set(_Result, 0); // 処理結果
/*
Button.OnSelect
_Limitまでの総和を求める
*/
If(
_SEQ < _Limit,
Set(_SEQ, _SEQ + _Step);
Set(_Result, _Result + _SEQ);
Select(Self);
)
/*
画面にTextCanvasを設置し以下を設定
*/
Text =_Result
この段階では多くの課題が残ります、重大な課題として以下が挙げられます。
- ボタンを際限なくクリック・タップできてしまうため何度でも実行される。
- 内部に変数の初期化を行う処理を条件なしに記述すると毎回初期化されてしまう。
- 画面を移動しない限り各変数の値がリセットされない。
- 2回目以降の実行結果が保証されない。(実際には追加され続けます)
完全なボタンループの基本形(パターン①)
ボタンコントロール=押すことのできるコントロールということでボタン単体でのループを構築しがちですが、実はそこが落とし穴となっています。
起動用のボタン(または数式) + ループ処理を行うボタンという構成で構築してみます。
コントロール | 担う処理 | 名前 | Visible |
---|---|---|---|
TEXTINPUT | ループ回数の入力 | Limit1 | true |
ボタン | 変数の初期化とループの開始 | BtnStartLoop | true |
ボタン | ループ処理 | BtnLoop1 | false |
TextCanvas | 結果の表示 | Result1 | true |
/*
App
*/
Formulas =_Step = 1; // 定数として定義
/*
Screen(任意の画面)
*/
OnVisible =Set(_IsCalc, false); // ループの実行中
/*
BtnStartLoop
*/
OnSelect |
=Set(_Limit, Limit1.Value);
Set(_SEQ, 0);
Set(_Result, 0);
Select(BtnLoop1);
Set(_IsCalc, true);
DisplayMode =If(_IsCalc, DisplayMode.Disabled, DisplayMode.Edit) // ループ中は無効
/*
BtnLoop1
*/
If(
_SEQ < _Limit,
Set(_SEQ, _SEQ + _Step);
Set(_Result, _Result + _SEQ);
Select(Self);,
Set(_IsCalc, false); // 起動ボタンの有効化
)
/*
Result1
*/
Text =_Result
- ループの制御用に起動ボタンを設置しました。起動時にすべての変数が初期化されます。
- ループ回数を指定できるようTextInputを設置しました。
- ループ中を示す変数を設けて起動ボタンの動作を制限しています。
完全なボタンループの基本形(パターン②)
アプリデザイン上の理由でボタンを表示できない場合のループ起動例
コントロール | 担う処理 | 名前 | Visible |
---|---|---|---|
TEXTINPUT | ループ回数の入力と変数の初期化、ループの起動 | Limit2 | true |
ボタン | ループ処理 | BtnLoop2 | false |
TextCanvas | 計算結果の表示 | Result2 | true |
/*
App
*/
Formulas =_Step = 1; // 定数として定義
/*
Limit2
入力後0.5秒待つ
*/
OnChange |
=Set(_Limit, Self.Value);
Set(_SEQ, 0);
Set(_Result, 0);
Select(BtnLoop2);
TriggerOutput = 'TextInputCanvas.TriggerOutput'.Delayed
/*
BtnLoop2
*/
If(
_SEQ < _Limit,
Set(_SEQ, _SEQ + _Step);
Set(_Result, _Result + _SEQ);
Select(Self);
)
/*
Result2
*/
Text =_Result
まとめ
今回はボタンでのループ処理について紹介しました。
タイマーを使った場合と大きく違う点は「遅延を設定することが出来ない」ということです、遅延しないためタイマーを使うよりパフォーマンスが向上します。
今回紹介したボタンループや以前の記事で紹介したStartプロパティでのタイマーループ、Repeatプロパティでのタイマーループでは自身を再呼出しする方法で疑似ループを実現してます。
つまり再帰関数のような動作を実現可能です、関数の定義が出来ないPower Appsでハノイの塔や8クイーン巡回などの再起プログラムの実現が出来ます。
手間とパフォーマンスを無視すればアニメーション化して教育プログラムとして利用するなど可能性が広がります。