エラーが発生しないように記述する方がいいのですが、エラーの発生がどううしようもない場合、わざと発生させる場合などあります。エラーの発生の仕方と、対応方法を検討します。
1.エラーの発生のさせ方
errorを使ってエラーを発生させます。
let
Output = error "エラーメッセージ"
in
Output
エラーメッセージだけでなく、詳細を付けることもできます。
let
Output =
error Error.Record(
"ファイル読み込みエラー",
"ファイル名my.txtが見つかりません",
"my.txt"
)
in
Output
以下の書き方もできます。
let
Output =
error [
Reason = "ファイル読み込みエラー",
Message = "ファイル名my.txtが見つかりません",
Detail = "my.txt"
]
in
Output
2.tryとotherwiseによってエラーをつかまえる
tryの後の処理でエラーが発生した場合、処理を中断せずにotherwiseの処理に移ります。以下の例では、"foo"という文字列に1を加算しようとしているので、エラーとなります。
try "foo"+1
otherwiseをつかって、このエラーを処理します。
try
"foo"+1
otherwise
"エラー発生"
tryで返される値は、2-1でやったように、[HasError]にエラーが発生したかどうかのブーリアン型の値が入ります。
エラーが発生していた場合は[Error]の中にReason、Message、Detailがレコードとして入っています。
let
Result = try "foo"+1,
Output =
if Result[HasError] then
"エラーメッセージ:" & Result[Error][Message]
else
Result[Value]
in
Output
3.エラー抑制(Error Containment)
エラーが発生すると、エラーの発生した値にアクセスする部分にのみ影響し、影響しない部分は最後まで実行されます。
let
Source = NotDefine(),
Result = [
Value1 = 25,
Value2 = Source,
Value3 = Value1 + Value2
]
in
Result
Sourceの値はエラーとなりますが、最後まで実行されて、Result[Value1]の値は25と表示されます。
また、エラーが発生していても、その式が評価されなければ、何の影響も発生しません。下の例では、行の数を計算するのに項目の値は関係ないため、正常に値を返します。
let
Data = #table({"Col1"}, {{"SomeValue"}, { error "bad" }})
in
Table.RowCount(Data)
4.スコープ
下の例では、テーブルの中の値の1つでエラーが発生しており、このコードは0を返すことを期待していますが、結果的にエラーを含むテーブルとして値が返されます。
テーブル内のセルで発生したエラーは、テーブルの式レベルには影響を与えません。
let
Data = #table({"Amount"}, {{10}, {error "help!"}, {error "save me!"}})
in
try Data otherwise 0
一方、次の式では、最後にList.Sumでテーブル内のセルの値を評価しているため、エラーが発生し、0が返されます。
let
Data = #table({"Amount"}, {{10}, {error "help!"}, {error "save me!"}})
in
try List.Sum(Data[Amount]) otherwise 0
参考に、エラーを0に置き換えて集計するには、以下のようにやります。
let
Data =
#table(
{"Amount"},
{
{10},
{error "help!"},
{error "save me!"}
}
),
// 項目NewAmountを追加し、Amountの値を入れる。ただし、エラーの場合は0にする。
ErrorsReplacedWithZero =
Table.AddColumn(
Data,
"NewAmount",
(row) => try row[Amount] otherwise 0
),
// 項目Amountを削除
RemoveOldAmount =
Table.RemoveColumns(
ErrorsReplacedWithZero,
{"Amount"}
),
// 項目名をNewAmountからAmountに変更
RenameNewAmount =
Table.RenameColumns(
RemoveOldAmount,
{
"NewAmount",
"Amount"
}
)
in
List.Sum(RenameNewAmount[Amount]) // returns 10
5.Webコンテンツのレスポンスコードを取得する
Web,Contentsで404(Not Found)を発生させます。
let
response = try Web.Contents(url)
in
response
Web.Contentsではエラーが帰ってきません。Valueの中にステータスコードが入っているようです。以下のように、ManualStatusHandling、Metadataを使ってレスポンスコードを取り出します。
let
Source = Web.Contents(url, [ManualStatusHandling={400,404,500}]),
// 400 Bad Request, 404 Not Found, 500 Internal Server Error
Response = Value.Metadata(Source)
in
Response
レスポンスコードは、 Response.Statusにあることがわかります。
let
response = Web.Contents(url, [ManualStatusHandling={400,404, 500}]),
// 400 Bad Request, 404 Not Found, 500 Internal Server Error
responseCode = Value.Metadata(response)[Response.Status]
in
responseCode
レスポンスコードを取り出すには、以下のようにします。
let
Source = Web.Contents(#"url", [ManualStatusHandling={400,404,500}]),
ResponseCode = Value.Metadata(Source)[Response.Status]
in
ResponseCode
Try & Catch