コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。

Power Appsでアプリ起動時に定数を作成したい場合はApp.OnStartよりApp.Formulasを利用しよう!


スポンサードリンク

はじめに

昨日X(旧: Twitter)でも投稿しましたが、Power Appsでは App.OnStart に処理を記載するより App.Formulas に処理を記載したほうがパフォーマンスが良いです。

公式ドキュメントでも言及されていますが、OnStartプロパティは、アプリ読み込み時にパフォーマンスの問題を引き起こすことがあります。

learn.microsoft.com

一番わかりやすいのがアプリの読み込みに掛かる時間ですね。

あとは(最近は発生しないのかもですけど、)私が昔やってたころは、OnStartに処理書きすぎて一部読み込まれずに画面読み込まれて表示されちゃったせいでアプリがうまく動作しない!
なんてことがありましたね。(さすがにこれは改善されてそうな気がしますけど)

Formulasプロパティの使い方はこちらです。

learn.microsoft.com

  終
制作・著作
━━━━━
 ⓀⓇⓃ

とここで終わってもブログにわざわざ書く意味もないので、使い方や比較をこの記事では紹介しようと思います。

比較用アプリ

以下のようなアプリを作成します。

どちらもOnStart、Formulasでユーザ情報、ギャラリー内で表示しているカラーパレットを定義して画面に表示させるようにしています。

あくまでもOnStartとFormulasの比較なので、これらのプロパティ以外は全く同じ構成にしています。

初期変数の定義

ユーザ情報は "UserInfo" に、
カラーパレットの情報は "myRandColors" に、
それぞれ設定したいと思います。

ユーザ情報には、"Office365ユーザー"コネクタの"MyProfileV2"アクション及び、"UserPhotoV2"アクションで取得した情報を設定します。

カラーパレットには、500件のカラー情報と、座標情報、その他GUIDや実行したときの時間を設定します。

座標情報を入れているのは、画面に表示させているギャラリーが"TemplateSize = 0"の手法を用いて設定しているからです。

OnStart

上記の要件をOnStartプロパティで定義すると以下のようになります。

OnStart

Set(
    UserInfo,
    AddColumns(
        Office365ユーザー.MyProfileV2(),
        "Photo",
        Office365ユーザー.UserPhotoV2(ThisRecord.id)
    )
);
ClearCollect(
    myRandColors,
    ForAll(
        Sequence(500) As i,
        With(
            {
                red: RandBetween(0, 255),
                green: RandBetween(0, 255),
                blue: RandBetween(0, 255)
            },
            {
                index: i.Value,
                guid: GUID(),
                now: Now(),
                rgba: RGBA(ThisRecord.red, ThisRecord.green, ThisRecord.blue, 1),
                hex: $"#{Dec2Hex(ThisRecord.red)}{Dec2Hex(ThisRecord.green)}{Dec2Hex(ThisRecord.blue)}",
                x: 52 * Mod(i.Value - 1, 25),
                y: 30 * Int((i.Value - 1) / 25),
                width: 52,
                height: 30
            }
        )
    )
)

Formulas

続いてFormulasプロパティで書き直すと以下のようになります。

Formulas

UserInfo = 
    AddColumns(
        Office365ユーザー.MyProfileV2(),
        "Photo",
        Office365ユーザー.UserPhotoV2(ThisRecord.id)
    );
myRandColors =
    ForAll(
        Sequence(500) As i,
        With(
            {
                red: RandBetween(0, 255),
                green: RandBetween(0, 255),
                blue: RandBetween(0, 255)
            },
            {
                index: i.Value,
                guid: GUID(),
                now: Now(),
                rgba: RGBA(ThisRecord.red, ThisRecord.green, ThisRecord.blue, 1),
                hex: $"#{Dec2Hex(ThisRecord.red)}{Dec2Hex(ThisRecord.green)}{Dec2Hex(ThisRecord.blue)}",
                x: 52 * Mod(i.Value - 1, 25),
                y: 30 * Int((i.Value - 1) / 25),
                width: 52,
                height: 30
            }
        )
    );

Formulasプロパティで式を記載する場合は、

<変数名> = <式>

のようになります。

あとはだいたい同じですね。

アプリ内で変数を利用する

OnStart

まずはOnStartでの利用方法です。
といっても普通のグローバル変数とコレクションの利用なので難しいことはないですね。

ユーザの画像を表示

Image.Image

UserInfo.Photo

ユーザの名前を表示

Label.Text

UserInfo.displayName

コレクション内で最も大きい時間最も小さい時間の差を表示

Labl.Text

$"DateDiff: {DateDiff(Max(myRandColors, now), Min(myRandColors, now))}"

カラーパレットの表示

Gallery.Items

myRandColors

Label.Text

ThisItem.hex

Label.X

ThisItem.x

Label.Y

ThisItem.y - (ThisItem.index - 1)

Label.Width

ThisItem.width

Label.Height

ThisItem.height

Formulas

続いてFormulasで宣言した変数の利用方法です。

ユーザの画像を表示

Image.Image

UserInfo.Photo

ユーザの名前を表示

Label.Text

UserInfo.displayName

コレクション内で最も大きい時間最も小さい時間の差を表示

Labl.Text

$"DateDiff: {DateDiff(Max(myRandColors, now), Min(myRandColors, now))}"

カラーパレットの表示

Gallery.Items

myRandColors

Label.Text

ThisItem.hex

Label.X

ThisItem.x

Label.Y

ThisItem.y - (ThisItem.index - 1)

Label.Width

ThisItem.width

Label.Height

ThisItem.height

なんと同じ式で利用できるのですね!

OnStartからFormulasへの移行もスムーズに行えることがわかってもらえたかと思います。

実行速度の比較

モニター機能でそれぞれの実行時間をみてみましょう!

OnStart

Formulas

Formulasの方が圧倒的に処理速度が速いですね!

より多くの処理や複雑な処理、時間の掛かる処理を実行する場合などはより顕著に差が表れると思います。

Formulasプロパティを利用するにあたって理解しておくこと

ドキュメントで利点として記載されていること、および制限事項を理解しておくといいですかね。

名前付き計算式を使用する利点は次のとおりです。

  • 数式の値は常に利用可能です。 タイミング依存関係も、値が設定される前に最初に実行する必要のある OnStart もなく、式の値が不正確になる時間もありません。 名前付き計算式は、循環参照を作成しない限り、任意の順序で相互に参照できます。 それらは並行して計算できます。
  • 数式の値は常に最新です。 数式は、コントロール プロパティまたはデータベース レコードに依存する計算を実行でき、それらが変更されると、数式の値が自動的に更新されます。 変数の場合のように値を手動で更新する必要はありません。 また、数式は必要な場合にのみ再計算されます。
  • 式の定義は不変です。 数式の定義は信頼できる唯一の情報源であり、アプリ内の他の場所で値を変更することはできません。 変数を使用すると、一部のコードが予期せず値を変更する可能性がありますが、名前付きの数式ではこれは不可能です。
  • 数式の計算は延期できます。 値は不変であるため、必要なときにいつでも計算できます。つまり、必要になるまで計算する必要はありません。 アプリのスクリーン 2 まで使用されない数式の値はスクリーン 2 が表示されるまで計算する必要はないと表示されます。 これにより、アプリの読み込み時間を改善できます。 名前付き計算式は宣言型であり、システムが計算方法とタイミングを最適化する機会を提供します。
  • 名前付き計算式は Excel の概念です。 非常に多くの人が Excel をよく知っているので Power Fx は可能な限り Excel の概念を使用します。 名前付き計算式は、名前マネージャーで管理される Excel の名前付きセルおよび名前付き計算式と同等です。 コントロール プロパティと同じように、スプレッドシートのように自動的に再計算されます。

名前付き計算式のいくつかの制限:

  • 動作関数を使用したり、アプリ内で副作用を引き起こしたりすることはできません。
  • 循環参照を作成することはできません。 a = b; と b = a; を同じアプリ内で持つことは許可されていません。

利点として述べられている、値が不変な点と動作関数やアプリ内で副作用を起こすことができない。
という点が特に注意ですかね。

つまり現状OnStartプロパティに記載されていた内容すべてをFormulasプロパティに移植できるわけではありません。

じゃあどうすればいいか?というと、個人的には初回起動画面のOnVisibleに記載することをおすすめします。

要件によっては、初回ロード画面なんてものを作るのもありじゃないですかね?

おわりに

皆さんもOnStartプロパティは卒業して、Formulasプロパティの利用にシフトしましょう!


スポンサードリンク