変換の処理

Power BI で直接使用できる形式でデータ ソースの応答が表示されていない場合は、Power Query を使用して一連の変換を実行できます。

静的変換

ほとんどの場合、データはデータ ソースによって一貫した方法で表示されます。列名、データ型、階層構造は、特定のエンドポイントに対して一貫しています。 このような状況では、常に同じ一連の変換を適用して、Power BI で受け入れ可能な形式でデータを取得することが適切です。

静的変換の例は、「TripPin パート 2 - REST サービスのデータ コネクタ」チュートリアルの、データ ソースが標準の REST サービスとして扱われる部分で確認できます。

let
    Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines"),
    value = Source[value],
    toTable = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    expand = Table.ExpandRecordColumn(toTable, "Column1", {"AirlineCode", "Name"}, {"AirlineCode", "Name"})
in
    expand

この例における変換は次のとおりです。

  1. Source は、TripPin.Feed(...) への呼び出しから返されるレコードです。
  2. Source のキーと値のペアの 1 つから値をプルします。 キーの名前は value であり、結果は value という変数に格納します。
  3. value は、テーブルに変換するリストです。 value の各要素はテーブル内の行になり、toTable を呼び出すことができます。
  4. value の各要素自体はレコードです。 toTable には、それらすべてが 1 つの列 ("Column1") で示されます。 このステップでは、toTable の各行につき、キー "AirlineCode" のすべてのデータを "AirlineCode" という列にプルし、キー "Name" のすべてのデータを "Name" という列にプルします。 "Column1" はそれら 2 つの新しい列に置換されます。

1 日の終わりには、Power BI で使用して簡単にレンダリングできるる単純な表形式のデータが残ります。

表形式のデータ。

この特定性の一連の静的変換は、単一の エンドポイントにのみ適用可能であることに注意してください。 上の例では、この一連の変換は、M コードにハードコードされているため、"AirlineCode""Name" がREST エンドポイント応答に存在する場合にのみ機能します。 したがって、この一連の変換は、/Event エンドポイントへのヒットを試行する場合は機能しないことがあります。

この高いレベルでの特定性は、ナビゲーション テーブルにデータをプッシュするために必要な場合がありますが、より一般的なデータ アクセス関数の場合は、すべてのエンドポイントに適した変換のみを実行することをお勧めします。

注意

さまざまなデータ状況下で変換をテストしてください。 /airlines エンドポイントにデータがないユーザーの場合、変換の結果は正しいスキーマを持つ空のテーブルになりますか? または、評価中にエラーが発生しますか? 単体テストについて詳しくは、「TripPin パート 7 - M 式の高度なスキーマ」をご覧ください。

動的変換

API 応答を Power BI のデータ モデルに適した安定した一貫性のある形式に変換するには、より複雑なロジックが必要になる場合があります。

一貫性のない API 応答

通常、API の応答手段がいくつかある状況では、基本的な M 制御フロー (if ステートメント、HTTP 状態コード、try...catch ブロックなど) で十分に処理できます。

オンザフライでのスキーマの判定

一部の API は、正しい表形式を取得するために、複数の情報を組み合わせることが求められるよう設計されています。 Smartsheet の /sheets エンドポイント応答について考えてみると、これには列名の配列とデータ行の配列が含まれています。 Smartsheet コネクタでは、次の方法でこの応答を解析できます。

raw = Web.Contents(...),
columns = raw[columns],
columnTitles = List.Transform(columns, each [title]),
columnTitlesWithRowNumber = List.InsertRange(columnTitles, 0, {"RowNumber"}),
                
RowAsList = (row) =>
    let
        listOfCells = row[cells],
        cellValuesList = List.Transform(listOfCells, each if Record.HasFields(_, "value") then [value]
                else null),
        rowNumberFirst = List.InsertRange(cellValuesList, 0, {row[rowNumber]})
    in
        rowNumberFirst,

listOfRows = List.Transform(raw[rows], each RowAsList(_)),
result = Table.FromRows(listOfRows, columnTitlesWithRowNumber)
  1. 最初に、列ヘッダー情報を処理します。 各列の title レコードを List にプルできます。RowNumber 列を先頭に追加することで、常にこの最初の列として表されることがわかります。
  2. 次に、行をセル value の List に対して解析できるようにする関数を定義できます。 再度 rowNumber 情報を先頭に追加できます。
  3. API 応答で返される各 rowRowAsList() 関数を適用します。
  4. 列ヘッダーを指定して、List をテーブルに変換します。