TripPin パート 3 - ナビゲーション テーブル
このマルチパート チュートリアルでは、Power Query 用の新しいデータ ソース拡張機能の作成について説明します。 このチュートリアルは、順次実行することを意図したものです。各レッスンでは、それまでのレッスンで作成したコネクタを基にして、コネクタに新しい機能を段階的に追加していきます。
このレッスンの内容:
- 固定クエリ セットのためにナビゲーション テーブルを作成する
- Power BI Desktop でナビゲーション テーブルをテストする
このレッスンでは、前のレッスンで作成した TripPin コネクタにナビゲーション テーブルを追加します。 コネクタに OData.Feed 関数を使っていた場合 (パート 1) は、OData サービスの $metadata ドキュメントから派生したナビゲーション テーブルを "無料で" 受け取りました。 Web.Contents 関数 (パート 2) に進むと、組み込みのナビゲーション テーブルを失いました。 このレッスンでは、Power BI Desktop で作成した固定クエリ セットを使い、Power Query に適切なメタデータを追加して、データ ソース関数の [ナビゲーター] ダイアログをポップアップ表示します。
ナビゲーション テーブルの使用については、ナビゲーション テーブルのドキュメントを参照してください。
コネクタでの固定クエリの定義
REST API のシンプルなコネクタは、それぞれからテーブルが返される固定クエリ セットと考えることができます。 これらのテーブルは、コネクタのナビゲーション テーブルを使って検出できるようになります。 基本的に、ナビゲーターの各項目は、特定の URL と一連の変換に関連付けられています。
まず、(前のレッスンで) Power BI Desktop で作成したクエリをコネクタ ファイルにコピーすることから始めます。 TripPin Visual Studio プロジェクトを開き、Airlines および Airports クエリを TripPin.pq ファイルに貼り付けます。 次に、これらのクエリを 1 つのテキスト パラメーターを受け取る関数に変えることができます。
GetAirlinesTable = (url as text) as table =>
let
source = TripPin.Feed(url & "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;
GetAirportsTable = (url as text) as table =>
let
source = TripPin.Feed(url & "Airports"),
value = source[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"Name", "IcaoCode", "IataCode", "Location"}, {"Name", "IcaoCode", "IataCode", "Location"}),
#"Expanded Location" = Table.ExpandRecordColumn(#"Expanded Column1", "Location", {"Address", "Loc", "City"}, {"Address", "Loc", "City"}),
#"Expanded City" = Table.ExpandRecordColumn(#"Expanded Location", "City", {"Name", "CountryRegion", "Region"}, {"Name.1", "CountryRegion", "Region"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded City",{{"Name.1", "City"}}),
#"Expanded Loc" = Table.ExpandRecordColumn(#"Renamed Columns", "Loc", {"coordinates"}, {"coordinates"}),
#"Added Custom" = Table.AddColumn(#"Expanded Loc", "Latitude", each [coordinates]{1}),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Longitude", each [coordinates]{0}),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"coordinates"}),
#"Changed Type" = Table.TransformColumnTypes(#"Removed Columns",{{"Name", type text}, {"IcaoCode", type text}, {"IataCode", type text}, {"Address", type text}, {"City", type text}, {"CountryRegion", type text}, {"Region", type text}, {"Latitude", type number}, {"Longitude", type number}})
in
#"Changed Type";
次に、これらのデータ セット クエリにリンクする固定テーブルを作成するモック ナビゲーション テーブル クエリを記述してインポートします。 これを TripPinNavTable と呼びます。
TripPinNavTable = (url as text) as table =>
let
source = #table({"Name", "Data"}, {
{ "Airlines", GetAirlinesTable(url) },
{ "Airports", GetAirportsTable(url) }
})
in
source;
最後に、メインのデータ ソース関数として使う新しい共有関数 TripPin.Contents を宣言します。 また、 [データの取得] ダイアログに表示されないように TripPin.Feed から Publish の値を削除します。
[DataSource.Kind="TripPin"]
shared TripPin.Feed = Value.ReplaceType(TripPinImpl, type function (url as Uri.Type) as any);
[DataSource.Kind="TripPin", Publish="TripPin.Publish"]
shared TripPin.Contents = Value.ReplaceType(TripPinNavTable, type function (url as Uri.Type) as any);
注意
DataSource.Kind との関連付けの有無にかかわらず、拡張機能で複数の関数に shared とマークすることができます。 ただし、関数を特定の DataSource.Kind と関連付ける場合、各関数には名前と種類が同じ 必須の パラメーター セットを指定する 必要があります。 これは、データ ソース関数のパラメーターを組み合わせて、キャッシュされた資格情報を検索するときに使う 'キー' を作成するためです。
TripPin.query.pq ファイルを使って TripPin.Contents 関数をテストすることができます。 次のテスト クエリを実行すると、資格情報のプロンプトとシンプルなテーブル出力が表示されます。
TripPin.Contents("https://services.odata.org/v4/TripPinService/")

ナビゲーション テーブルの作成
便利な Table.ToNavigationTable 関数を使って、静的テーブルを Power Query がナビゲーション テーブルとして認識できる形式に変更します。
Table.ToNavigationTable = (
table as table,
keyColumns as list,
nameColumn as text,
dataColumn as text,
itemKindColumn as text,
itemNameColumn as text,
isLeafColumn as text
) as table =>
let
tableType = Value.Type(table),
newTableType = Type.AddTableKey(tableType, keyColumns, true) meta
[
NavigationTable.NameColumn = nameColumn,
NavigationTable.DataColumn = dataColumn,
NavigationTable.ItemKindColumn = itemKindColumn,
Preview.DelayColumn = itemNameColumn,
NavigationTable.IsLeafColumn = isLeafColumn
],
navigationTable = Value.ReplaceType(table, newTableType)
in
navigationTable;
これを拡張機能ファイルにコピーした後、TripPinNavTable 関数を更新してナビゲーション テーブルのフィールドを追加します。
TripPinNavTable = (url as text) as table =>
let
source = #table({"Name", "Data", "ItemKind", "ItemName", "IsLeaf"}, {
{ "Airlines", GetAirlinesTable(url), "Table", "Table", true },
{ "Airports", GetAirportsTable(url), "Table", "Table", true }
}),
navTable = Table.ToNavigationTable(source, {"Name"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
in
navTable;
テスト クエリを再度実行すると、前回と同様の結果が得られます。ただし、いくつかの列が追加されています。

注意
Visual Studio では [ナビゲーター] ウィンドウは表示されません。 [M Query Output](M クエリ出力) ウィンドウには、常に基となるテーブルが表示されます。
拡張機能を Power BI Desktop カスタム コネクタにコピーし、 [データの取得] ダイアログから新しい関数を呼び出すと、ナビゲーターが表示されます。

ナビゲーション ツリーのルートを右クリックして [編集] を選ぶと、Visual Studio 内で実行したものと同じテーブルが表示されます。

まとめ
このチュートリアルでは、拡張機能にナビゲーション テーブルを追加しました。 ナビゲーション テーブルは、コネクタを使いやすくするための重要な機能です。 この例のナビゲーション テーブルには 1 つのレベルしかありませんが、Power Query UI は、(不規則であっても) 複数のディメンションを持つナビゲーション テーブルの表示をサポートしています。