对于未以 Power BI 可以直接使用的格式显示数据源响应的情况,可以使用 Power Query 来执行一系列转换。
静态转换
在大多数情况下,数据源以一致的方式呈现数据:列名、数据类型和分层结构对于给定终结点是一致的。 在这种情况下,应始终应用相同的转换集来获取 Power BI 可接受的格式的数据。
当数据源被视为标准 REST 服务时,可以在 TripPin 第 2 部分 - 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
此示例中的转换如下:
-
Source是从调用TripPin.Feed(...)返回的一条记录。 - 从
Source的某个键值对中提取值。 键的名称是value,结果存储在名为value的变量中。 -
value是一个列表,可转换为表。 每个value元素都会成为表中的一行,你可以将该表称为toTable。 - 每个元素
value本身都是一个 Record。toTable在单个列中具有所有这些项:"Column1"此步骤将具有键"AirlineCode"的所有数据提取到名为"AirlineCode"的列中,并将具有键"Name"的所有数据提取到名为"Name"的列中,针对toTable中的每一行。"Column1"被替换为这两个新列。
在一天结束时,你留下的数据采用简单的表格格式,Power BI 可以使用并轻松呈现:
请务必注意,此特定性的静态转换序列仅适用于 单个 终结点。 在前面的示例中,此转换序列仅在 REST 终结点响应中存在时才"AirlineCode""Name"起作用,因为它们已硬编码为 M 代码。 因此,如果尝试访问/Event该终结点,那么此转换序列可能不起作用。
将数据推送到导航表可能需要这种高度的针对性。 但是,对于更常规的数据访问函数,我们建议你仅执行适合所有终结点的转换。
注释
请务必在各种数据情况下测试转换。 如果用户在终结点上 /airlines 没有任何数据,转换是否会导致具有正确架构的空表? 还是评估期间遇到错误? 有关单元测试的讨论 ,请参阅 TripPin 第 7 部分:具有 M 类型的高级架构 。
动态转换
有时需要更复杂的逻辑,以便将 API 响应转换为适合 Power BI 数据模型的稳定且一致的形式。
API 响应不一致
基本的 M 控制流(如 if 语句、HTTP 状态代码、try...catch 块 等等)通常足以处理 API 响应的几种情况。
动态确定架构
某些 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)
- 首先处理列标题信息。 可以将每个列的
title记录提取到列表中,并在前面添加一个RowNumber列,该列始终作为第一列表示。 - 接下来,可以定义一个函数,该函数允许将行分析为单元格
value列表。 可以再次追加rowNumber信息。 - 将
RowAsList()函数应用于 API响应返回的每个row元素。 - 将列表转换为表,指定列标题。