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 中编写的查询(在上一节课中)复制到连接器文件中。 在 Visual Studio Code 中打开 TripPin 项目,并将航空公司和机场查询粘贴到 TripPin.pq 文件中。 然后,可以将这些查询转换为采用单个文本参数的函数:

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该函数用作主数据源函数。 此外,还可以从Publish中删除TripPin.Feed该值,使其不再显示在“获取数据”对话框中。

[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);

注释

扩展可以将多个函数标记为shared,可选择将它们与DataSource.Kind关联或不关联。 但是,将函数与特定DataSource.Kind函数相关联时,每个函数必须具有相同的名称和类型所需的参数集。 之所以存在此要求,是因为将数据源函数参数组合在一起,以生成用于查找缓存凭据的“密钥”。

在完成所有更改后,生成连接器,并使用 TripPin.query.pq 文件测试 TripPin.Contents 函数。 可以继续使用以前创建的凭据,也可以设置一个新凭据,然后评估当前的 Power Query 文件。

TripPin.Contents("https://services.odata.org/v4/TripPinService/")

PQTest 结果的屏幕截图,其中包含修改后的连接器的输出。

创建导航表

使用方便的 Table.ToNavigationTable 函数将静态表格式化为 Power Query 识别为导航表的内容。 由于此函数不是 Power Query 标准库的一部分,因此需要将其源代码复制到 .pq 文件中。

确保此帮助函数到位后,接下来更新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;

再次运行测试查询,在再次生成连接器后,可提供与上次类似的结果,同时添加了一些列。

PQTest 结果的屏幕截图,输出包含多个新行。

注释

看不到 导航器 窗口显示在 Visual Studio Code 的 PQTest 结果窗口中。 M 查询输出窗口始终显示基础表。

如果将扩展复制到 Power BI Desktop 自定义连接器并从 “获取数据 ”对话框中调用新函数,则将显示导航器。

导航器对话框的屏幕截图,其中显示了新函数的结果。

如果右键单击导航树的根,然后选择 “编辑”,则会显示 Visual Studio 中显示的同一个表。

Power Query 编辑器的屏幕截图,其中显示了与上一个 PQTest 结果中相同的表。

结论

在本教程中,你向扩展添加了 导航表 。 导航表是一项关键功能,使连接器更易于使用。 在此示例中,导航表只有一个级别,但 Power Query UI 支持显示具有多个维度的导航表(即使它们不规则)。

后续步骤

TripPin 第 4 部分 - 数据源路径