Power Appsの使い方

Power AppsとPower Automateの使い方やできることがわかるブログを目指しています。

Power Apps モデル駆動型のよいところ【初級編】

みなさん Power Apps のモデル駆動型、使ってますか?作ってますか?

 

コミュニティ界隈ではキャンバスアプリの情報は目につくのですが、そちらと比べるとモデル駆動型の情報は少なく感じます。理由としては、モデル駆動型を利用するには Power Apps スタンドアロンライセンスが必要だから、うちでは使えないんだよね。という方が多いのかなと思います。

 

それはまぁ仕方ない。でも、モデル駆動型も含めて Power Apps ですから、やはりモデル駆動型も盛り上がってほしい。ということで、今回はモデル駆動型もいいぞという内容を少しお伝えできればと思います。

 

Power Apps モデル駆動型とは?

今回の本筋ではないので本当にざっくり言ってしまうんですが、Dataverse をデータソースとした、データ一覧と入力フォームをメイン要素とした Power Apps のアプリケーション構築方法です。もう一つの方法として、 Power Apps キャンバスアプリがあります。

 

本記事ではモデル駆動型の紹介はしていないので、もし全然わからない方はお調べになってから読まれたほうがいいかもしれません。

 

モデル駆動型を利用する前提条件

モデル駆動型を利用するには、Power Apps スタンドアロンライセンスが必要です。

Power Apps per user

Power Apps per app

・従量課金

などです。

 

ただ、お試しで実験したいということであれば、Power Apps の開発者プランというもので試してみることができますし、試用版ライセンスでもお試しすることができます。

Power Apps 開発者向けプラン | Microsoft Power Apps

 

また、作成するアプリのデータソースは Dataverse である必要があります。

 

こんな人にはモデル駆動型がおすすめ

キャンバスアプリでアプリを作ってみたい方、作ってみた方の中には以下のような悩みをお持ちの方も多いと思います。

 

・アプリを自分で作るなんて不安。

・覚えることが多くて難しい。

・どのようにアプリを構成すればいいのかわからない。

・デザインセンスがなくてUIをどうすればいいかわからない。

・不具合がないか心配。テストもどうすればいいかわからない。

 

こういった方には、モデル駆動型を利用することでのメリットを感じられるはずです。

 

モデル駆動型のメリット(初級編)

基本機能だけでも、以下のようなメリットを享受することができます。本当はほかにも山ほどいいことがありますが、それはまた今度で。

 

メーカー目線のメリット

・入力フォームとデータ一覧の項目の設定するだけで、アプリが自動生成される。

・ノーコードで作成でき、覚えることがキャンバスと比較して少ない。

・コントロールのプロパティや関数を使った数式の実装方法の理解等が不要。

・画面設計、デザインがほぼ不要。

・エラーや不具合なく構築できる。

 

ユーザー目線のメリット

・統一されたUI/UXで使いやすい。

・エラーや不具合がなくスムーズに業務を進められる。

・レスポンシブでPCスマホ対応。

 

モデル駆動型はデータの一覧であるビューと、データの登録及び編集を行うフォームで構成されるアプリを作るのに適しています。逆に、そういった構成にできないアプリは作ることができません。※

 

とはいえ、多くのビジネスアプリケーションはビューとフォームで構成されているはずです。キャンバスでもモデル駆動型でも作成が可能な場合は、モデル駆動型での構築を強くお勧めします。

 

※キャンバスアプリをモデル駆動型に埋め込むことで一応実現可能です。

 

どんなときにモデル駆動型が使える?

以下のようなときには、モデル駆動型アプリが適しています。

・データ一覧と入力フォームで構成できるアプリを作成するとき

・キャンバスかモデル駆動型か迷ったとき

・多数のテーブルを持った大きなソリューションが必要なとき

 

逆に以下のようなときには、キャンバスアプリが適しています。

・自由なUIで作りたいとき

・外部データソースと接続するとき

・データ接続がないとき

・1つか2つのボタン操作のみのシンプルな構成のとき

・入力フォームとデータ一覧以外の要素で構成するとき

・明確にキャンバスアプリを採用する理由があるとき

 

まとめ

どこまでを目指すかにもよりますし、用途は多少限定されてしまいますが、モデル駆動型もキャンバスに負けず劣らず手軽に始めることができます。

もし興味が出てきたら、一度触ってみて、是非その良さを感じてもらえれば幸いです。

 

そのうちさらに高度な利用とメリットについても書いてみる予定です。

Dataverse サービス保護のAPI制限について

市民開発者の方へ

今回の内容は主にプロ開発者向けの内容です。市民開発者レベルの利用用途ではまず発生しないと思われますので、ご安心ください。もしそれっぽいことが発生したら、お近くのプロ開発者に相談してみましょう。

 

権利の制限とサービス保護のAPI制限について

よく Power Platform の利用可能な制限について話題に上がるのは、24時間で要求可能な Power Platform 要求の数についてかとおもいます。こちらは、ライセンスごとに付与された権利の制限になります。

 

API 制限の概要 (Microsoft Dataverse) - Power Apps | Microsoft Learn

 

今回話題に挙げているのは権利の制限とは異なるもので、ライセンスを買えば解決!というような類のものではありません。

 

サービス保護のAPI制限と呼ばれるもので、文字通り一部のユーザーによる異常なリクエストを制御し、全体の利用を妨げないようにするための制限となっています。

 

API 制限の概要 (Microsoft Dataverse) - Power Apps | Microsoft Learn

 

制限があることによって不便に感じるかもしれませんが、この制限がないと、例えば1人のユーザーによる異常なリクエストによって、テナントの Dataverse の負荷が過剰に上がってしまい、最終的にテナント全体が停止する、なんてことになってしまうかもしれません。

 

この制限があることによって、多くのユーザーが快適にサービスを利用できるようにしているわけです。ありがたや。

 

サービス保護のAPI制限ってどんな制限があるの?

サービス保護のAPI制限には、以下の3つがあります。

 

・5分間の中で要求しすぎると制限される

・5分間の中で時間のかかる処理を要求しすぎると制限される。

・同時実行の要求をしすぎると制限される。

 

どの程度要求すると制限されるか数値を出したいところですが、この辺りは環境により異なるようです。ただ、普通にしていればそうそう制限にかかることはないと思われます。のちに記載するページに参考値が記載されていますが、許容値の変動要素としては

 

・環境に割り当てられたサーバーの数により許容値が変動する

・サーバーの数は購入したライセンス数や、その他の要因で変動する

・試用版環境は1つのサーバーが割り当てられている

・制限の内容は変更される可能性がある

 

などが記載されています。

 

注意点としては、検証で利用することの多いであろう試用版環境はWebサーバーの割り当ては1つ固定であることです。実際の運用時と制限内容が異なる可能性があるので、留意しておきましょう。

 

参考値として、サーバー1台当たりの制限を記載します。

制限項目

サーバ1台当たりの許容値

要求数の制限

6000 / 5

実行時間の制限

合計20分かかる処理 / 5分

同時実行数の制限

52の処理まで

※環境のサーバーの数やその他の要因により、制限は変動します。最新の情報は下記のページを参照してください。

サービス保護 API の制限 (Microsoft Dataverse) - Power Apps | Microsoft Learn

 

制限されるとどうなる?

しばらくの間、新しい要求ができなくなります。制限解除までの時間は429エラーメッセージに含まれていますが、どの程度制限を超過したかにより異なるようです。一般的な対策ではありますが、その時間分待機を挟んで再度要求を投げるように実装しましょう。

 

また、制限を超過したときに影響を受けるのは、超過したユーザーのみです。他のユーザーには影響しないので、やらかしてしまった場合でもテナント全体への影響は少なそうです。

 

API要求数の制限への対策

バッチを使って一度に複数の処理を要求する

バッチを使うと、最大で1000の操作を1度に要求できます。これにより、API要求数を減らすことが可能です。

※ちなみに、残念ながら権利の制限はバッチで回避できません。

 

毎月から毎日、毎時、リアルタイム実行へ

ため込んで処理を行うと、1度に多くの処理をしなくてはなりません。なるべくリアルタイムで処理できるのであればリアルタイムで処理するようにしましょう。

 

UIを持つアプリで発生する場合には、アプリの作りを改善する

リストの表示数を減らしたり、データをキャッシュするなど要求数をなるべく減らすように作り替えることで、回避できるはずです。

 

実行時間の制限への対策

重いバッチ処理を同時実行しない

そもそも重い処理ということがわかっている場合には、制限を考慮して構築しましょう。

 

プラグインやリアルタイムワークフローを軽量化したり、データ移行のため一時的に無効化する

11つの処理を軽くすることで、処理時間の低減を図りましょう。

 

同時実行数の制限への対策

52を超えて同時実行しないようにする

軽い処理であっても、同時実行数を増やしすぎないようにしましょう。10程度から始めて、ほかの要素を加味しながら制限を超えない値を探っていく方法が推奨されています。

 

まとめ

以上、サービス保護のためのAPI制限についてでした。あまりこの制限に引っかかることはないかもしれませんが、存在だけでも知っておくと何かあった時に気が付きやすいかと思います。

プロ開発者の方は、処理の重いバッチやデータ処理が無造作に実行されないよう気を付けましょう。

 

今回は実際にエラーを出すとこまで書けなかったので、そのうち実験してみたものを記事にしようと思います。

 

参考リンク

サービス保護 API の制限 (Microsoft Dataverse) - Power Apps | Microsoft Learn

API 制限の概要 (Microsoft Dataverse) - Power Apps | Microsoft Learn

Web APIを使用したバッチ処理の実行 (Microsoft Dataverse) - Power Apps | Microsoft Learn

 

 

この記事は Microsoft Power Automateのカレンダー | Advent Calendar 2022 - Qiita に参加しています。

【ハンズオン】そうだ、Power Apps でブロック崩しを作ろう。

かなり前にブロック崩し Power Apps で作ってみたんですが、それの作成方法をまとめてみようと思います。(今度コミュニティの方でハンズオンでも出来たらなーとかも思ってたり。)

 

アプリはゲーム的ですが、楽しみながらPower Apps アプリ作成に役に立つTIPSが学べると思いますので、是非トライしてみてください。

 

どんなアプリを作るの?

こんな感じのアプリを作ります。

Power Apps でブロック崩し

何の変哲もないブロック崩しですね。

 

ざっくり作成の流れ

  • ボールを動かす
  • ボールが壁に反射するようにする
  • ボールをバーで跳ね返せるようにする
  • ブロックを設置する
  • ブロックに当たった時の処理を実装する

以下、作成手順です。

 

ボールを動かす

まずはボールを設置して、動くようにしてみましょう。

 

変数初期化用のボタンを設置

ボタンコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

ButtonInitBall

Text

InitBall

OnSelect

UpdateContext(

    {

        locBallPoint: {

            X: App.Width/2,

            Y: App.Height/2

        },

        locAcceleration:{

            X: 30,

            Y: -30

            }

    }

)

 

OnePoint

locBallPoint:ボールのXY座標の情報を保持しておくための変数です。のちの手順でボール用コントロールXYプロパティに入れ込んでいきます。

 

locAcceleration:加速度情報の変数です。壁やブロックに当たって反射する際には、-1をかけて反転させています。描画更新のたびに locBallPoint に加算して、ボールを動いているように見せています。

ボタンの配置は適当でいいです。私はこんな感じにしました。

PowerApps ー プ ロ ッ ク 崩 し 2 
← 戻 る ラ | 
0 「 ご 
十 挿 入 
X 
Open Sans 
InitBall 
[ コ 5 ( 肥 enl 
中 太 字 
false 
nit8a118utton 
A 
色 
背 昌 色 
設 定 
誠 有 田 s Environment 
ホ タ ン ② 
Init8a118utton 
ロ ) ト , 
9 
十 
ツ リ - ヒ ュ - 
画 面 コ ン ホ - ネ ン ト 
刄 検 索 
十 新 し い 亘 直 
、 ・ Screenl 
匚 Init3a118utton 
ア イ デ ア 
i ~ Ⅱ 
A 
三 コ 第 匚 ] [ - 
Open Sans 
B キ 太 早 
冊 キ 
80 
プ ロ バ テ ィ 諱 設 定 
バ デ ィ ン グ 
フ ォ ン ト 
フ ォ ン ト サ イ ス 
フ ォ ン ト の 太 さ 
フ ォ ン ト ス タ イ ル 
テ キ ス ト の ア ラ イ ン メ ン ト 
垂 直 方 向 の 言 
新 時 の ま 化 
効 時 の 色

ボール用の円アイコンを設置

続いてボールを設置します。

円アイコンコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

Ball

X

locBallPoint.X-(Ball.Width/2)

Y

locBallPoint.Y-(Ball.Height/2)

Width

20

Height

20

こんな感じになっていれば、OKです。

PowerApps ー プ ロ ッ ク 崩 し 2 
← 戻 る ラ | 
十 挿 入 
X 
田 罫 線 、 、 / 背 昌 色 、 、 / 設 定 
、 ′ 10 [ 日 allPoint . X 
InitBall 
誠 有 田 s Environment 
プ ロ バ テ ィ 
効 時 の 色 
ロ ) ト , 
9 
十 
ツ リ - ヒ ュ - 
画 面 コ ン ホ - ネ ン ト 
刄 検 索 
十 新 し い 亘 直 
、 ・ Screenl 
& Ball 
匚 auttonInitBaII 
諱 設 定 
ホ イ ン ト 蓍 の 色 
さ れ た 状 態 の 色 
タ ブ 順 
ア イ デ ア 
値 な し 
[ コ 5 ( 肥 enl 
& Ball 
80 %

描画更新用のタイマーを設置

さらに、ボールを動かすためにlocBallPoint変数の更新が必要です。なので、短いタイマーを使って描画を更新させようと思います。

タイマーコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

Timer

Duration

20

Repeat

true

AutoStart

true

Visible

false

OnTimerStart

//加速度に従いボールが移動する

UpdateContext(

    {

        locBallPoint:{

            X:locBallPoint.X+locAcceleration.X,

            Y:locBallPoint.Y+locAcceleration.Y

        }

    }

);

これでボールが動くようになりました!ただ、ボールが突き抜けてどこかへ行ってしまいます。

※タイマーを動かすには再生モードにします。編集モードではタイマーが動きませんので注意!

 

OnePoint

ここではボールの位置情報を持っているlocBallPointに加速度情報のlocAccelerationを加算しています。もっと早くしたい場合や遅くしたい場合は、locAccelerationを初期化している箇所の数値をいじってみましょう。

ちなみに、処理速度を上回るほどDurationを短くしても早くはならないようです。

再生モードにして、ボールが動くのを確認出来たら次に進みましょう!

 

ボールが壁に反射するようにする

天井と左右の壁に当たったら跳ね返す

続いて、ボールが突き抜けていかないように、天井や壁で跳ね返るようにしてみましょう。

先ほど設定した Timer コントロール OnTimerStart に下記の処理を追加しましょう。

 

OnTimerStart

//壁当たり判定 天井にあたったら跳ね返る

If(locBallPoint.Y<0,UpdateContext({locAcceleration:{X:locAcceleration.X, Y:locAcceleration.Y*-1}}));

//壁当たり判定 左の壁にあたったら跳ね返る

If(locBallPoint.X<0,UpdateContext({locAcceleration:{X:locAcceleration.X*-1, Y:locAcceleration.Y}}));

//壁当たり判定 右の壁にあたったら跳ね返る

If(locBallPoint.X>App.Width,UpdateContext({locAcceleration:{X:locAcceleration.X*-1, Y:locAcceleration.Y}}));

これでボールが跳ね返ってくれるようになりました。ただし、画面下に行ってしまうと相変わらずどこかへ行ってしまいます。このままではなすすべがありません。

ボールが壁と天井に反射するのを確認出来たら、次に進みます。

 

ボールをバーで跳ね返せるようにする

バーと連動させる用のスライダーを設置する

続いて、バーを使ってボールを跳ね返せるようにしましょう。まずは後の手順でバーと連動させるためのスライダーを準備します。

スライダーコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

SliderForHitBar

X

0

Y

500

Width

App.Width

Height

200

HandleSize

200

RailThickness

0

ShowValue

False

ValueFill

RGBA(0, 0, 0, 0)

HandleFill

RGBA(0, 0, 0, 0)

BorderStyle

BorderStyle.None

Max

App.Width

Default

App.Width/2

 

OnePoint

Widthには、横幅いっぱいにするためApp.Widthを指定しています。

HandleSizeはつかみやすくするため、200を指定しています。

見えないようにしたいので、5つの項目を設定しています。のちの手順で何をしているかわかりにくいので、後で理解してから設定してもいいかもしれません。

Maxはのちの手順でValueをバーと連動させるため、App.Widthにしています。

上にも書いていますが、非表示にする項目は後で設定してもかまいません。

設定出来たら、次に進みましょう。(スケスケなのでスクショは割愛します。)

 

跳ね返すバー用の四角形アイコンを設置する

続いて、実際に跳ね返すバーを追加します。先ほどのスライドと連動させていきます。

四角形アイコンコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

HitBar

X

SliderForHitBar.Value - (HitBar.Width/2)

Y

650

Width

200

Height

20

 

OnePoint

Xプロパティがキーです。ここで先ほどのスライダーの値と連動させています。

スライダーを動かせば横の位置が連動して動くのが確認できるはずです。

バーにかぶっているとスライダーがつかめないので、スライダーを前面に持ってくるようにしましょう。ツリービューから設定できます。

← 戻 る ラ | 
Def 三 し に 
PowerApps ー プ ロ ッ ク 崩 し 2 
- マ 
& Ball 
十 挿 入 
X 
宅 
ニ 
丁 - タ の 追 加 
新 し い 画 面 
尹 
、 ′ App. Width/2 
設 定 
9 
十 
ツ リ - ヒ ュ - 
画 面 コ ン ホ - ネ ン ト 
刄 検 索 
十 新 し い 亘 直 
、 ・ Screenl 
HitBar 
・ : ー SliderForHit3ar 
auttonInitBaII 
衂 う 取 う 
鱸 う イ 1 け 
誠 有 田 s Environment 
ス プ イ タ - ② 
SliderForHit3ar 
プ ロ バ テ ィ 諱 設 定 
レ イ ア ウ ト 
値 の を テ 
ハ ン ド ル の サ イ ズ 
値 の り つ ふ し 
ハ ン ド ル の リ つ ふ し 
効 時 の 色 
ホ イ ン ト 蓍 の 色 
値 の ホ イ ン ト 蓍 の リ つ 。 
レ - ル の ホ イ ン ト 時 の … 
ハ ン ド ル の ホ イ ン ト 時 の … 
ア イ デ ア 
1 ヨ 65 
1 ヨ 65 
亘 ] 名 前 の 変 
与 配 列 
ロ 最 前 直 へ 移 動 
ロ 前 直 へ 移 勧 
曜 耆 直 へ 移 動 
ロ 最 当 直 へ 移 動 
新 し い コ メ ン ト 
InitBall 
[ コ 5 ( 肥 enl 
・ : ー SliderForHit8a 「 
80

これでバーを動かすことができるようになりましたね。ただ、これだけではまだボールを跳ね返すことはできません。

 

バーで跳ね返す処理を追加する

続いて、ボールを跳ね返せるようにしていきましょう。

ボールを跳ね返すようにするには、Timer.OnTimerStartに下記の処理を追加しましょう。

 

コントロール

Timer

OnTimerStart

//バーの当たり判定

If(

    And(

        // ボールのY座標がヒットバーの内側かつ

        locBallPoint.Y+(Ball.Height/2)>HitBar.Y && locBallPoint.Y < HitBar.Y+HitBar.Height,

        // ボールのX座標がヒットバーの内側のとき

        locBallPoint.X>HitBar.X&&locBallPoint.X<HitBar.X+HitBar.Width

    ),

    // Y加速度を反転してボールを上方へ跳ね返す

    UpdateContext({locAcceleration:{X:locAcceleration.X, Y:locAcceleration.Y*-1}})

);

※既存の処理に追加します。既にあった数式を消さないように注意してください。

 

OnePoint

内容としては、ボールがバーにかぶったら(当たったら)、Y方向の変数に-1をかけて跳ね返すようにしています。

これでバーでボールを跳ね返せるようになります。やっとゲームっぽくなってきた気がしますね。

あとはブロックを設置して、ボールに当たったらブロックが消える処理を実装していけば完成です。

 

ブロックを設置する

ブロックの情報を準備する用のボタンを設置する

ブロックを設置していきますが、ブロックの情報はコレクションに保持しておこうと思います。

ということで、準備としてコレクションを初期化するためのボタンを作っていきます。

 

ボタンコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

ButtonInitBlocks

Text

InitBlocks

OnSelect

Clear(colBlocks);

ForAll(

    Sequence(6,0,1) As Y,

    ForAll(

        Sequence(10,0,1) As X,

        Collect(colBlocks,

        {

            XIndex:X.Value,

            YIndex:Y.Value,

            Hit:false

        })

    )

);

 

OnePoint

Sequence()で生成したテーブルにAsで名前を付けています。こうすると、改装になっていても参照できますし、明示的に指定できるのでわかりやすくなりますので個人的におすすめです。

これで、次の手順で使用するコレクションの準備ができました。

作成出来たら、一度ボタンを押してコレクションを生成しておいてくださいね。

 

ブロック用ギャラリーを設置する

続けて、表示用のギャラリーとその中に四角アイコンを設置していきましょう。

空の垂直ギャラリーコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

GalleryBlocks

Items

colBlocks

X

0

Y

0

Width

App.Width

Height

300

WrapCount

10

TemplateSize

44

 

OnePoint

ギャラリーは空にしておいてください。

垂直方向のギャラリーを追加することに注意。

Itemsには先ほど作成したコレクションを指定します。ボタンを一度押してコレクションが生成されていることを確認しておきましょう。

この時点ではまだ何も出てなくてOKです。気にせず次に進みます。

 

ギャラリーに四角形アイコンを追加

ギャラリーのセルにコントロールを追加してブロックを表せるようにします。

四角形アイコンコントロールを追加し、各プロパティを以下の通りに設定しましょう。

 

コントロール

Block

X

0

Y

0

Width

Parent.TemplateWidth

Height

Parent.TemplateHeight

Visible

!ThisItem.Hit

 

OnePoint

Visible!ThisItem.Hitを指定して、コレクションの情報と連動させています。[ ! ]が付くことに注意。

これでブロックを配置することができましたね。

0 0 
小 ャ 旧 甼 ャ く 口 C 
△ n 
叫 回 (J 呱 削 
側 い (J 叱 回 
q C 町 
一 u 出 」 い S 
贋 〉 囈 国 呱 謳 
> レ ー 旧 > 国 3 「 一 に e 〕 > 冐 聖 い — 小 睥 > Y* 十 一 > - 
'O 一 8 に u 一 
= 28 に u 一 
【 と い S 〔 凵 
X 
Z 阜 ロ 一 sddVEM0d 
′ 一 ハ ー 長 ハ 冂 目 国 
」 2 〒 」 0 亠 」 22 新 — 
5 0 一 8 、 = 29 ■ ロ 
—Za ー コ う 
> - い 一 ↓ 
岡 回 コ 「 靃 十 
LUaa-DS 〔 凵 > 
IleE 「 ツ 
贐 0 、 十 
0 、

ブロックに当たった時の処理を実装する

ボールに当たったらボールが消えるようにする

続いて、ボールに当たったらブロックが消えるようにしてみましょう。

既存のTimerコントロールのプロパティに追記していきます。

 

コントロール

Timer

OnTimerStart

// ブロック当たり判定処理 ブロック

// 未HitならHit処理をする

With(

    {

        _BallIndexX:RoundDown( locBallPoint.X/(App.Width/10),0),

        _BallIndexY:RoundDown( locBallPoint.Y/(GalleryBlocks.TemplateHeight+(GalleryBlocks.TemplatePadding*2)),0)

    },

    With(

        {

            // ボールがある位置のセル情報を取得

            _TargetBlock:LookUp(colBlocks,XIndex = _BallIndexX && YIndex = _BallIndexY)

        },

        If(

            _TargetBlock.Hit = false,

            // ブロックのHit処理

            Patch(colBlocks,_TargetBlock,{Hit:true});

        );

    );

);

 

OnePoint

_BallIndexXYはボールの位置がインデックスで表すとどこにあるか?を取得しています。これを利用して、コレクションから該当する場所のブロック情報を取得し、更新しています。

Patch()Hitフィールドを更新していますが、これはブロックのVisibleと連動しているので、更新することでブロックが非表示になるわけです。

これで、ブロック崩しの貫通モードみたいになったかと思います。再生モードで試してみてください。

確認出来たら、先に進みます。

 

ブロックに当たったら跳ね返るようにする

仕上げに、ブロックに当たったら跳ね返るするようにしていきましょう。

先ほどの Timer.OnTimerStart に実装した部分を以下のように書き換えて、跳ね返るようにしていきます。

 

コントロール

Timer

OnTimerStart

// ブロック当たり判定処理 ブロック

// 未HitならHit処理をする

With(

    {

        _BallIndexX:RoundDown( locBallPoint.X/(App.Width/10),0),

        _BallIndexY:RoundDown( locBallPoint.Y/(GalleryBlocks.TemplateHeight+(GalleryBlocks.TemplatePadding*2)),0)

    },

    With(

        {

            // ボールがある位置のセル情報を取得

            _TargetBlock:LookUp(colBlocks,XIndex = _BallIndexX && YIndex = _BallIndexY)

        },

        If(

            _TargetBlock.Hit = false,

            // ブロックのHit処理

            Patch(colBlocks,_TargetBlock,{Hit:true});

            // 反射の処理 横から来てたらX方向に跳ね返す。

            If(locLastIndex.X <> _BallIndexX,UpdateContext({locAcceleration:{X:locAcceleration.X*-1, Y:locAcceleration.Y}}));

            // 反射の処理 上下から来てたらY方向に跳ね返す。

            If(locLastIndex.Y <> _BallIndexY,UpdateContext({locAcceleration:{X:locAcceleration.X, Y:locAcceleration.Y*-1}}));

        );

        //今回の値を次回の比較のために保持しておく。

        UpdateContext({locLastIndex:{X:_BallIndexX,Y:_BallIndexY}});

    );

);

 

OnePoint

ボールが横から来たらX方向に跳ね返す。上下から来たらY方向に跳ね返すようになっています。インデックス単位での判定なので、多少判定がガバガバなのはご愛敬。

また、どこから来たか判定したかったので、前の情報を保持するようにしています。

上記のように書き換えると、ボールに当たったブロックは消えつつ、ボールが跳ね返るようになるはずです。

Power Apps でブロック崩し

完成!

以上でブロック崩し完成です!お疲れさまでした!

 

さらに余裕がある方は、点数加算のギミックを追加したり、残機を実装してゲームオーバーになるようにしたり、ブロックの背景に面白い画像などを置いてみても面白いかもしれません!

 

以上、ブロック崩しの作り方でした!

皆様が楽しく感じながら、ついでに少しでも学びにつながってましたら幸いです!

 

 

この記事はMicrosoft Power Appsのカレンダー | Advent Calendar 2022 - に参加しています。

Power Apps キャンバスアプリで Dataverse 選択肢フィールドでソートするには

キャンバスアプリで Dataverse を使用しているときに、選択肢フィールドでソートしたい場合について。

 

普通に試すと、ソートができない

キャンバスアプリで選択肢フィールドを対象にSort()関数などでソートしようとすると、どうにもうまくいきません。通常のフィールドのように指定しても、エラーが出てしまいます。

 

現状私が確認した限りでは、Sort()SortByColumns()でソートをする方法はなさそうです。

 

ビューでソートする

では詰みかと思いきや、そうでもありません。

Dataverse ビュー の機能を使用すると、ビューで設定したフィルタ条件とソート順でキャンバスアプリにデータをもってくることができます。これを利用することで実現可能です。

 

手順

細かい手順は省きますが、ざっくり2ステップでソート済みデータをキャンバスアプリに持ってくることができます。

 

・ソート順を指定したビューを作成

並 へ 替 え 臺 準 . 
↓ OptionSetField 
三 自 加 の 並 べ 替 え 墓 準 
X

 

・作成したビューをキャンバスアプリから参照

プ ロ バ テ ィ 
デ - タ ソ - ス 
諱 設 を 
5 し 厄 mp 
SortayOptionset 
、 ノ

 

上記の手順で選択肢によるソートが実装できます。

 

動的にフィルタもしたいんだけど・・・

ユーザーからの入力値によって動的にしたい場合、ビューでは少し弱いです。できないわけではないんですが・・・。

全てのパターンをビューで網羅するのは厳しいので、その中から実際にユーザーが利用するパターンを洗い出して限定的にビューで実装する方向で一度検討してみてはいかがでしょうか。

 

蛇足:ソート用フィールドを追加するのは?

ソート用にフィールドを用意して保持しておく方法もあると言えばありますが、あまりおすすめできません。選択肢の中身を変えたときに対応させるのが面倒になりますし、メンテを忘れそうです。

 

蛇足:委任非対応でよければなんでもあり

コレクション化しているものを対象にする場合など、委任に対応できないことが問題でない場合は以下のようにするとソートができます。

 

Sort(

    colItems,

    Text( OptionSetField ),

    Ascending

)

 

ただ、上記の例だとテキストに変換してソートしてしまうため、本来の並びと異なる可能性があります。

ソート順を変えたくない場合は、ソート順参照用のコレクションを作成しておき、

 

ForAll(

    Sequence(CountRows(Choices( ABC_Set)),1,1) As Index,

    Collect(

        colOptionSets,

        {

            Value:Last(FirstN(Choices( ABC_Set),Index.Value)).Value,

            Text:Text(Last(FirstN(Choices( ABC_Set),Index.Value)).Value),

            Index:Index.Value

        }

    )

)

 

ItemsではAddColumns()を使用してソート用インデックスフィールドを追加したテーブルを用いてソートすることで、ソートが可能です。が、ちょっと面倒。

 

SortByColumns(

    AddColumns( 

        Test_Temp As Source,

        "OptionsetIndex",

        LookUp(colOptionSets,Value = Source.OptionSetField).Index

    ),

    "OptionsetIndex",

    Ascending

)

 

そもそも委任に対応できていないので、使い所も限られてきます。一応ご紹介まで。

 

まとめ

・ひとまず、ビューを試してみるのがおすすめ。

・動的なフィルタには弱い。利用パターンを洗い出してみては。

・委任非対応でよければ、キャンバス側での実装はいくつか方法がある。が、やや面倒。

 

PR

アプリ作成支援や導入支援サービスを提供しています。

Power Apps / Power Automate 技術支援サービス | ZEE CitizenDevSupport

https://powerapps.zee-citizendevsupport.com/

Dataverse for Teams のフローを複製するには

Dataverse for Teams でのフローの複製について整理してみます。

 

Dataverse for Teams のフローは複製できない?

まず、前提として普通に Dataverse for Teams フローを複製しようとすると、うまくいきません。

 

フローを選択して[ 名前をつけて保存 ] から保存、複製しても、Dataverse for Teams 上に表示されません。

どこかに複製されたのか、されていないのか。よくわからない状態になってしまいます。

 

 

複製したフローはどこにいった?

実はフローの複製自体はされています。

 

どこに保存されているかというと、環境内の[マイフロー]に保存されています。

これは、通常の Power Automate ポータルから確認できます。

 

 

どうすれば Dataverse for Teams に表示できる?

Dataverse for Teams に表示されるフローと表示されないフローの違いはなにか?

答えは、特定のソリューションに含まれるか否か、です。

 

Dataverse for Teams に表示されるアプリ、チャットボット、フローはすべて [ Common Data Services Default Solution ] という名前のソリューションに含まれています。

 

逆に言えば、このソリューションに含めることができれば、Dataverse for Teams 上に表示させることができます。

 

Common Data Services Default Solution に追加するには

クラウドフロー一覧から、[ Power Apps で開く ] からソリューション画面に移動します。

 

 

移動先は Common Data Services Default Solution の管理画面です。ここからソリューションに含めることができます。

 

画面上部の [ 追加 ] から、望みのフローをソリューションに追加することができます。

 

 

 

フローを追加すると、一覧に表示されるようになります。

 

フローがソリューション外部の一覧にないことも・・・

残念ながら、全てのフローがこの方式で複製できるわけではありません。

一部のフローはソリューションへの追加に対応しておらず、一覧に出てこないことがあります。

 

たとえば、

Power Automate ボタントリガーを使用しているフロー

 

Power Apps トリガーを使用しているフロー

 

などはソリューションに含めることができないため、複製できないということになります。

(意外にもPower Apps V2トリガーは対応しています。

 

子フローの複製には対応できない

Power Apps V2 トリガーはソリューションに含めることができるので、子フローも複製できるかと思いきや、フローを作成して保存するときにエラーが発生してしまいます。

ソリューションで新規作成したもののみ、子フローとして使用することができます。

 

結局、この方法で複製したフローはどうやっても子フローとして利用することはできません。

 

複製できないときの回避策 トリガーを一時的に変更する

トリガー次第で外部からソリューションに含められるかどうかが決まります。

なので、複製時だけトリガーを変更し、力技で複製する方法が取れるかもしれません。

 

こういうこともあるので、日頃からトリガー変更に強い作り方をしておくといいかもしれませんね。

 

複製できないときの回避策 アクションのコピーでコピーする

子フローとして利用したいフローを複製したい場合は、今回の方法ではどうやっても対応できないと思われます。

どうしてもDataverse for Teams からの新規フロー作成が必要になります。

 

代案として、スコープとアクションのコピーが使えるかもしれません。

予めフロー作成時に全てのアクションをスコープに含めておけば、アクションのコピーで簡単に全体をコピーすることができます。

 

苦肉の策ですが、これらで対応しましょう。

 

まとめ

・普通のやり方では、Dataverse for Teams のフローを複製することができない。

・実はマイフローに複製されている。

・表示させるには、Common Data Services Default Solution に含める必要がある。

・ソリューションに追加できないフローもあるので、注意。

・最後は力技で解決。

 

ということで、Dataverse for Team のフローの複製についてでした。ご参考になれば幸いです。

 

PR

アプリ作成支援や導入支援サービスを提供しています。

Power Apps / Power Automate 技術支援サービス | ZEE CitizenDevSupport

https://powerapps.zee-citizendevsupport.com/

Power Apps や Power Automate に関する仕事のご依頼は下記ページからお問い合わせください。
ZEE CitizenDevSupport