この記事で説明する動作は、 数式レベルのエラー管理機能 が有効になっている場合にのみ使用できます。
Power Fx では、数式レベルのエラー処理がサポートされています。 この機能は、すべての新しいアプリで既定で有効になっています。 ただし、一部の古いアプリでは、アプリ の設定で無効になっている可能性があります。 この機能はオンのままにします。
- キャンバス アプリを編集モードで開きます。
- 設定>のアップデート>、リタイア済みタブに移動します。
- [ 数式レベルの管理を無効にする ] がオフになっていることを確認します。
詳細については、「 有効にする機能の制御」を参照してください。
エラーは発生するものです。 ネットワークはダウンするものであり、ストレージがいっぱいになることも、予期しない値が入力されることもあります。 潜在的な問題に直面した場合でも、ロジックが適切に機能し続けることが重要です。
既定では、エラーはアプリの数式を通過し、アプリのエンド ユーザーに報告されます。 この方法では、エンド ユーザーは予期しない問題が発生したことを認識します。 別の入力で問題自体を修正したり、アプリの所有者に問題を報告したりする可能性があります。
アプリ作成者は、アプリ内のエラーを制御します。
- エラーを検出して処理します。 エラーが発生する可能性がある場合は、アプリの数式を記述してエラー状態を検出し、操作を再試行します。 エンド ユーザーはエラーが発生したことを心配する必要はありません。作成者がその可能性を考慮しているからです。 数式内で IfError、IsError、IsErrorOrBlank 関数を使用してエラーをキャプチャします。
- エラーを報告します。 発生した数式でエラーが処理されない場合、エラーは App.OnError ハンドラーにバブルアップされます。 エラーは既に発生しており、数式の計算の一部であるため、置き換えることはできません。 しかし、App.OnError を使用して、エラー報告を一斉に抑制するなど、エラーがエンド ユーザーに報告される方法を制御できます。 App.OnError は、アプリ全体でエラーを報告するための共通のチョーク ポイントも提供します。
- エラーを作成して再スローします。 最後に、独自のロジック (アプリに固有の条件) を使用してエラー条件を検出できます。 カスタム エラーを作成するには、Error 関数を使用します。 Error 関数を使用して、IfError や App.OnError で処理された後にエラーを再スローします。
スタートガイド
簡単な例から始めましょう。
- Power Apps キャンバス アプリで新しい画面を作成します。
- TextInput コントロールを挿入します。 既定では TextInput1 という名前になります。
- Label コントロールを挿入します。
- Label コントロールの Text プロパティを以下の数式に設定します
1/Value( TextInput1.Text )
TextInput コントロールの既定のテキストが"Text input"されており、数値に変換できないため、エラーが発生します。 既定では、これは良いことです。エンド ユーザーは、アプリで想定どおりに動作していないという通知を受け取ります。
明らかに、ユーザーがこのアプリを開くたびにエラーが表示されると困ります。 おそらく、"Text input" はテキスト入力ボックスに対して正しい既定値ではありません。 この問題を解決するには、TextInput コントロールの Default プロパティを次の値に変更します。
Blank()
今度は別のエラーが発生していることに気づきました。 除算などの 空白の算術演算では、空白の値を 0 に強制します。 この値を指定すると、0 除算エラーが発生します。 この問題を解決するには、このアプリでこの状況に対する適切な動作を決定する必要があります。 答えは、テキスト入力が 空白 のときに 空白と表示されることがあります。 この目標を達成するには、 数式を IfError 関数でラップします。
IfError( 1/Value( TextInput1.Text ), Blank() )
エラーは有効な値に置き換えられ、エラー バナーは消えます。 ただし、オーバーショットが発生した可能性があります。使用した IfError では、などの不適切な値の入力を含め、"hello"エラーがカバーされます。 この問題に対処するには、IfError を調整して、ゼロによる除算の場合にのみ対応し、他のすべてのエラーを再びスローするようにします。
IfError( 1/Value( TextInput1.Text ),
If( FirstError.Kind = ErrorKind.Div0, Blank(), Error( FirstError ) ) )
そのため、アプリを実行し、いくつかの異なる値を試してください。
アプリの起動時など、値がない場合は、既定値が空白であるため回答は表示されませんが、IfError によって 0 による除算エラーが置き換えられるため、エラーは表示されません。
4 を入力すると、予想される結果は 0.25 になります。
helloなど、何か無効なものを入力すると、エラー バナーが表示されます。
これは簡単な紹介例です。 アプリのニーズに応じて、さまざまな方法でエラーを処理できます。
- エラー バナーの代わりに、ラベル コントロールに数式を 含む "#Error" を 表示できます。 最初の引数と互換性のある置換の型を IfError に保持するには、 Text 関数を使用して数値の結果をテキスト文字列に明示的に変換する必要があります。
IfError( Text( 1/Value( TextInput1.Text ) ), If( FirstError.Kind = ErrorKind.Div0, Blank(), "#Error" )
- この特定のインスタンスを IfError でラップする代わりに、一元化された App.OnError ハンドラーを記述できます。 エラーが既に発生し、 App.OnError はレポートを制御するためにのみ提供されているため、表示される文字列を "#Error" に置き換えることはできません。
If( FirstError.Kind <> ErrorKind.Div0, Error( FirstError ) )
エラーの伝播
エラーは、Excel の場合と同じように数式を通過します。 たとえば、Excel では、セル A1 に数式が =1/0されている場合、A1 はエラー値 #DIV0!表示します。
セルA2がA1などの数式で=A1*2を参照している場合、エラーはその数式にも反映されます。
このエラーは、本来数式が計算するはずの値を置き換えてしまいます。 ゼル A2 の乗算の結果はなく、A1 の除算によるエラーのみがあります。
Power Fx は同じように動作します。 一般に、関数または演算子に引数としてエラーを指定した場合、操作は行われません。 入力エラーは、操作の結果に影響を与えます。 たとえば、最も内側のエラーが Mid( Text( 1/0 ), 1, 1 ) 関数と Mid 関数を通過すると、は 0 除算エラーを返します。
一般的に、エラーはPower Appsの制御プロパティを通過しません。 前の例を、最初のラベルの Text プロパティがエラー状態であるかどうかを表示する別のコントロールで拡張してみましょう。
すべてのコントロール プロパティへの入力に関するエラーがシステムによって観察されるため、エラーがコントロールを介して伝達されないのは問題ありません。 エラーは失われません。
ほとんどの関数と演算子は "エラー イン、エラー アウト" の規則に従いますが、いくつかの例外があります。 IsError、IsErrorOrBlank、および IfError 関数はエラーを処理するために設計されているため、エラーが渡された場合でもエラーが返されない可能性があります。
エラーの確認
Power Fx では、数式でエラー値が使用されるまでエラーは観察されません。
その結果、 If 関数と Select 関数は、渡された場合にエラーを返さない可能性があります。 数式 If( false, 1/0, 3 ) を考えてみましょう。 この数式には 0 除算エラーが存在しますが、If 関数が false 条件のためにその分岐を受け取っていないため、Power Fx と Power Appsはエラーを報告しません。
Set 関数をエラーと共に使用しても、エラーが変数に配置された時点でエラーは報告されません。 たとえば、Power Appsでは、App.OnStart の数式で、変数xに 0 除算エラーを発生させます。
x が参照されていないため、エラーは報告されません。 ただし、ラベル コントロールを追加し、その Text プロパティを x に設定すると、エラーが表示されます。
IfError、IsError、IsErrorOrBlank 関数を使用して、数式内のエラーを確認できます。 これらの関数を使用すると、別の値を返したり、別のアクションを実行したり、エラーを観察して報告する前に変更したりできます。
エラーの報告
Power Fx でエラーが観察された後、次の手順は、エンド ユーザーにエラーを報告することです。
Excel とは異なり、数式の結果によって、テキストを表示するのに便利な場所がないコントロールの X 座標や Y 座標などのプロパティが駆動される可能性があるため、エラー結果を表示するのに便利な場所が常に存在するとは限りません。 各 Power Fx ホストは、エラーが最終的にエンド ユーザーにどのように表示されるかと、作成者がこのプロセスをどの程度制御できるかを制御します。 Power Appsでは、エラー バナーが表示され、エラーの報告方法を制御するために App.OnError が使用されます。
App.OnError は、IfError でできるのと同じ方法ではエラーを置換できないことに注意してください。 App.OnError が実行された時点で、エラーは既に発生しており、結果は他の数式を介して伝達されます。 App.OnError は、エンド ユーザーにエラーを報告する方法のみを制御し、必要に応じて作成者がエラーをログに記録するためのフックを提供します。
スコープ変数 FirstError と AllErrors は、1 つまたは複数のエラーに関するコンテキスト情報を提供します。 このコンテキストは、エラーの種類、エラーが発生した場所、および発生した場所に関する情報を提供します。
エラー後の停止
動作の数式では、アクションの実行、データベースの変更、状態の変更がサポートされます。 これらの数式を使用すると、 ; チェーン演算子 (またはロケールに応じて ;; ) を使用して、シーケンス内で複数のアクションを実行できます。
この場合、たとえば、グリッド コントロールには、 T テーブル内の内容が表示されます。 ボタンを選択するたびに、2 つの Patch 呼び出しによってこのテーブルの状態が変更されます。
連鎖した動作の数式では、アクションは最初のエラーの後も停止しません。 最初の Patch 呼び出しで無効なインデックス番号を渡すように例を変更してみましょう。 2 番目の Patch は、この前のエラーにもかかわらず続行されます。 最初のエラーはエンド ユーザーに報告され、Studio のコントロールにエラーとして表示されます。
エラーの後に実行を停止するには 、IfError を使用します。 If 関数と同様に、この関数の 3 番目の引数は、エラーがない場合にのみ実行するアクションの配置場所を指定します。
ForAll のイテレーションの 1 つでエラーが発生した場合、残りのイテレーションは停止しません。 ForAll は、各反復を個別に実行するように設計されており、並列実行を可能にします。 ForAll が完了すると、エラーが返されます。エラーには、発生したすべてのエラーが含まれます (IfError または App.OnError で AllErrors を調べることによって)。
たとえば、次の数式では ForAll が 2 つのエラーを返します(Value が 0 の場合に 0 での除算のためです)。Collection には、Value が 0 でない場合に 3 つのレコードが含まれています: [1, 2, 3]。
Clear( Collection );
ForAll( [1,0,2,0,3], If( 1/Value > 0, Collect( Collection, Value ) ) );
複数のエラーへの対応
動作の数式では複数のアクションを実行できるので、複数のエラーが発生する可能性もあります。
既定では、アプリは最初のエラーをエンド ユーザーに報告します。 この例では、両方の Patch 呼び出しが失敗しますが、2 番目の呼び出しは 0 除算エラーで失敗します。 ユーザーには、インデックスに関する最初のエラーのみが表示されます。
IfError 関数と App.OnError は、AllErrors スコープ変数を使用して発生したすべてのエラーにアクセスできます。 この場合、この変数をグローバル変数に設定し、発生した両方のエラーを確認できます。 それらは、検出されたのと同じ順序でテーブルに表示されます。
動作に関連しない数式は、複数のエラーを返すこともあります。 たとえば、更新するレコードのバッチで Patch 関数を使用すると、複数のエラー (失敗したレコードごとに 1 つずつ) が返される場合があります。
テーブルのエラー
前に説明したように、変数にエラーを格納できます。 テーブルなどのデータ構造にエラーを含めることもできます。 この方法は、1 つのレコードに対するエラーがテーブル全体を無効にできないことを保証するため、重要です。
たとえば、Power Appsの次のデータ テーブル コントロールについて考えてみます。
AddColumns の計算で、いずれかの値に対して 0 除算エラーが発生しました。 その 1 つのレコードでは、Reciprocal 列にエラー値 (0 による除算) がありますが、他のレコードにはエラー値がなく、問題ありません。
IsError( Index( output, 2 ) ) は false を返し、IsError( Index( output, 2 ).Value ) は true を返します。
テーブルをフィルター処理するときにエラーが発生した場合、レコード全体がエラーになります。 この操作では、結果のレコードが返されるため、エンド ユーザーは何かが存在し、問題が発生したことを認識します。
この例を見てみましょう。 ここで、元のテーブルにはエラーがありませんが、Value が 0 に等しい場合は常に、フィルター処理によってエラーが発生します。
値 -5 と -3 は適切にフィルターで除外されます。値が 0 の場合、フィルターの処理でエラーになるため、レコードを結果に含める必要があるかどうかは不明です。 エンド ユーザーとヘルプ 作成者のデバッグの透明性を最大化するために、操作には元のエラー レコードの代わりにエラー レコードが含まれます。 この場合、IsError( Index( output, 2 ) ) は true を返します。
データ ソース エラー
Patch、Collect、Remove、RemoveIf、Update、UpdateIf、SubmitForm など、データ ソース内のデータを変更する関数は、2 つの方法でエラーを報告します。
- これらの各関数は、操作の結果としてエラー値を返します。 IsError を使用してエラーを検出し、通常どおり IfError と App.OnError を使用してエラーを置換または抑制できます。
- 操作の後、 Errors 関数は前の操作のエラーも返します。 この動作は、状態変数でエラーをキャプチャしなくても、フォーム画面にエラー メッセージを表示する場合に役立ちます。
たとえば、次の数式は Collect からのエラーをチェックし、カスタム エラー メッセージを表示します。
IfError( Collect( Names, { Name: "duplicate" } ),
Notify( $"OOPS: { FirstError.Message }", NotificationType.Warning ) )
Errors 関数は、ランタイム操作中の過去のエラーに関する情報も返します。 状態変数でエラーをキャプチャする必要なしに、フォーム画面にエラーを表示するのに役立つ可能性があります。
エラーの再スロー
エラーが発生する可能性があり、無視しても問題ありません。
IfError と App.OnError 内で、次の上位のハンドラーに渡す必要があるエラーが検出された場合は、Error( AllErrors )を使用して再スローします。
独自のエラーの作成
Error 関数を使用して独自のエラーを作成することもできます。
独自のエラーを作成する場合は、1,000 より大きい値を使用して、将来のシステム エラー値との競合の可能性を回避します。
ErrorKind 列挙値
| ErrorKind 列挙型 | 値 | 説明 |
|---|---|---|
| 解析エラー | 18 | システム エラー。 コンパイラ分析に問題があります。 |
| 無効な言語コード | 14 | 無効または認識されていない言語コードが使用されました。 |
| BadRegex | 15 | 正規表現が無効です。 IsMatch、Match、または MatchAll 関数で使用される構文を確認してください。 |
| 競合 | 6 | 更新中のレコードはソースで既に変更されているため、競合を解決する必要があります。 一般的な解決策は、ローカルの変更を保存し、レコードを更新して、変更を再適用することです。 |
| 制約違反 | 8 | レコードはサーバーでの制約チェックに合格しませんでした。 |
| 権限作成 | 3 | データソースのレコードを作成する権限がありません。 たとえば、Collect 関数が呼び出されました。 |
| 権限削除 | 5 | データ ソースのレコードを削除する権限がありません。 たとえば、Remove 関数が呼び出されました。 |
| Div0 | 13 | 0 による除算。 |
| 編集権限 | 4 | データソースのレコードを作成する権限がありません。 たとえば、Patch 関数が呼び出されました。 |
| GeneratedValue | 9 | サーバーが自動的に計算するフィールドの値が誤ってサーバーに渡されました。 |
| 無効な関数使用 (InvalidFunctionUsage) | 16 | 関数の使用法が間違っています。 多くの場合、関数への引数の 1 つ以上が正しくないか、無効な方法で使用されています。 |
| ファイルが見つかりません | 17 | SaveData ストレージが見つかりませんでした。 |
| メモリ不足 | 21 | 操作に十分なメモリまたはストレージがデバイスにありません。 |
| 無効な引数 | 25 | 関数に無効な引数が渡されました。 |
| 内部 | 26 | システム エラー。 関数の 1 つに内部的な問題があります。 |
| 必須項目が欠けています | 2 | レコードの必須フィールドがありません。 |
| ネットワーク | 23 | ネットワーク通信に問題があります。 |
| None | 0 | システム エラー。 エラーはありません。 |
| 該当なし | 27 | 使用できる値はありません。 このエラーは、数値計算でゼロとして扱うことができる 空白 値と、値を使用する場合に潜在的な問題としてフラグを設定する必要がある空白値を区別するのに役立ちます。 |
| 見つかりません | 7 | レコードが見つかりませんでした。 たとえば、Patch 関数で変更されるレコードなどです。 |
| サポートされていません | 20 | このプレーヤーまたはデバイスでは操作がサポートされていません。 |
| 数値 | 24 | 数値関数が不適切な方法で使用されました。 たとえば、-1 が指定された Sqrt などです。 |
| 限度超過 | 22 | ストレージ クォータを超えています。 |
| 読み取り専用値 | 10 | 列は読み取り専用であり、変更できません。 |
| 読み取り権限 | 19 | データソースのレコードを読む権限がありません。 |
| 同期 | 1 | データ ソースからエラーが報告されました。 詳細については、Message 列を確認してください。 |
| 不明 | 12 | エラーが発生しましたが、種類が不明です。 |
| 検証 | 11 | レコードは検証チェックに合格しませんでした。 |