
Power Apps でダッシュボードを作るとき、KPIカードは画面の顔になります。今月の件数・前月比・直近7日間の3枚を横並びで並べて、アプリを開いた瞬間に現場の状況が把握できるようにする。コンテナを使えばこのレイアウトを崩れなく、メンテナンスしやすい構造で実装できます。
カード1枚の基本構造
KPIカードは2層のコンテナで作ります。外側コンテナがカードの見た目(DropShadow・BorderRadius・Fill)を担当し、内側コンテナがコンテンツのレイアウト(Padding・整列)を担当します。内側はAuto Layout の垂直コンテナにして、タイトルラベル・数値ラベル・補足ラベルを上から順に積み上げます。
cntCard_3rd1(外側コンテナ:DropShadow・BorderRadius・Fill)
└─ cntCard_3rd1_inner(内側垂直コンテナ:Padding・LayoutAlignItems)
├─ lblCard1Title(タイトルラベル)
├─ lblCard1Value(数値ラベル:大きいフォント)
└─ lblCard1Sub(補足ラベル:前月比など)
外側コンテナの Fill には背景色を設定し、内側コンテナは Fill=Color.Transparent にします。DropShadow は外側だけに設定し、内側は必ず DropShadow.None にします。ネストしたコンテナで両方に影をつけると二重影になるので注意してください。
コンテナクラスターの設計思想の全体像はPower Apps コンテナ完全ガイドでまとめています。KPIカードの実装はその集大成の一つです。

3枚均等レイアウトの組み方
3枚のカードを均等に横並びにするには、親の水平AutoLayoutコンテナに3枚のカードを入れて、各カードに FillPortions=1 を設定します。これで親コンテナの幅が変わっても自動的に3等分されます。
ピクセル値で幅を計算する場合は次の式を使います。
// 3枚均等のピクセル計算式(FillPortionsを使わない場合)
(Parent.Width - Parent.LayoutGap * 2) / 3
LayoutGap * 2 は左右のカード間のギャップが2か所あるためです(カード①とカード②の間、カード②とカード③の間)。残った幅を3等分した値が各カードの Width になります。私は基本的に FillPortions を使う派ですが、カードの最小幅を MinimumWidth で保証したい場合はこのピクセル計算式と組み合わせることがあります。

今月件数カードの実装
3層のラベル構成
今月件数カードはタイトルラベル・数値ラベル・前月比ラベルの3層で構成します。数値ラベルは FontSize を大きくして視認性を上げ、タイトルと補足ラベルはそれより小さくして情報の階層を作ります。垂直コンテナに入れているので、LayoutAlignItems を Center にすれば横方向の中央揃えが自動でかかります。
各ラベルの Height は固定値か FillPortions で配分します。タイトルを20%・数値を50%・補足を30%にする場合は FillPortions を 1・2.5・1.5 のような比率で設定します。コンテナの高さが変わっても比率が保たれるので、画面サイズを後から変更する際に修正が楽です。
前月比の表示ロジック
前月比をプラスマイナス付きで表示するには If 式で符号を動的に付与します。varDiff に前月同日比の差分件数が入っている前提で、次のように書きます。
// 前月比ラベルの Text 式
If(varDiff > 0, "+", "") & Text(varDiff, "0") & "件"
varDiff がプラスのときだけ + を付け、マイナスのときは Text 関数が自動でマイナス記号を付けてくれます。ゼロのときは符号なしで 0件 と表示されます。変数の基本についてはPower Apps のグローバル変数とコンテキスト変数の記事で詳しく解説しています。
さらに varDiff の正負で文字色を切り替えると視認性が上がります。
// 補足ラベルの Color 式
If(varDiff >= 0, RGBA(46, 139, 87, 1), RGBA(210, 70, 70, 1))
プラスなら緑、マイナスなら赤にすることで、数字を読まなくても瞬時に良し悪しが判断できます。ダッシュボードはこういった情報設計の積み重ねが大切です。シンプルですが、実際の現場で使うと見やすいと好評でした。
未対応件数カードの実装
未対応件数カードは、総件数から完了件数を引いた差分を表示します。数値ラベルの Text 式はシンプルです。
// 未対応件数の計算
Text(varTotalCount - varCompletedCount, "0") & "件"
未対応件数がゼロかどうかで補足テキストを切り替えると、アラートとして機能するカードになります。
// 補足ラベルの Text 式
If(
varTotalCount - varCompletedCount > 0,
"要対応あり",
"すべて完了"
)
要対応ありのときは文字を赤にして、すべて完了のときは緑にする。私のチームでは毎朝の船舶管理確認にこのカードを使っていて、赤が出ている日は即対応を確認するようにしています。朝のミーティングでこのカードを映した瞬間に全員が状況を把握できるので、言葉で説明する手間が省けます。
直近7日カードの実装
直近7日の件数は、Filter で期間を絞ったコレクションの CountRows を表示します。ClearCollect でデータを取得しているコレクションが colData だとすると、次のように書きます。
// 直近7日の件数
Text(
CountRows(
Filter(colData, UpdatedDate >= DateAdd(Today(), -7, TimeUnit.Days))
),
"0"
) & "件"
DateAdd(Today(), -7, TimeUnit.Days) で7日前の日付を計算し、それ以降のレコードだけを Filter で絞り込んで CountRows で件数を取得します。コレクションはすでにメモリ上にあるので委任の問題が起きません。データソースに直接 Filter をかけると委任の警告が出ることがありますが、ClearCollect で手元に落としてから Filter すれば全件カウントできます。コレクションの基本と使いどころも合わせて確認しておくと理解が深まります。
データ取得とスピナー制御
KPIカードのデータは画面を開いたときと更新ボタンを押したときに取得します。更新ボタンの OnSelect に ClearCollect を書いて、取得中はスピナーを表示する設計が使いやすいです。
// 更新ボタンの OnSelect
Set(varSpinner, true);
ClearCollect(colData, DataSource);
Set(varSpinner, false);
varSpinner が true のあいだはローディング表示のコンテナを Visible にして、false になったらカードを表示する切り替えです。データ件数が多いと取得に数秒かかることがあるので、スピナーがないとアプリが固まったように見えます。私も最初はスピナーなしで作っていましたが、現場から「ボタンを押しても何も起きない」と言われてから必ず入れるようにしました。

まとめ
KPIカードはコンテナの構造・変数管理・Filter の組み合わせで作ります。カード1枚の構造を覚えてしまえば、3枚目でも5枚目でも同じパターンで作れます。前月比の符号表示や色の切り替えなど、細かい仕掛けを一つ入れるだけで現場での使い勝手がぐっと上がります。ダッシュボードは地道な積み重ねで育てていくものです。