Power BI基于Usage details表调用Azure REST API生成3年预留单价列
Power BI获取Azure 3年预留实例单价解决方案
问题背景
使用Power BI Desktop的Azure Cost Management连接器拉取成本管理数据,需要生成包含3年预留实例单价的列用于支出预测,数据需来自官方Azure Retail Prices API。此前尝试在DAX计算列中调用Web.Contents函数时,出现错误:Failed to resolve name "Web.Contents"。期望基于Usage details表的meterCategory(对应API的serviceName)、meterName(对应API的skuName)、location参数调用API,也可接受生成新表的方案。
错误原因
Web.Contents是Power Query(M语言)专属函数,无法在DAX计算列的环境中使用,因此直接在DAX中调用会触发名称解析错误。
解决方案
方案一:批量获取预留价格数据后关联(推荐)
通过Power Query一次性拉取所有3年预留的虚拟机价格数据,再与Usage details表关联,大幅减少API调用次数,避免限流风险。
- 在Power BI Desktop中点击数据转换,新建空白查询
- 粘贴以下M语言代码并执行:
let // 调用Azure零售价格API,筛选3年预留的虚拟机价格 Source = Json.Document(Web.Contents("https://prices.azure.com/api/retail/prices?$filter=serviceName eq 'Virtual Machines' and reservationTerm eq '3 Years'")), // 提取返回结果中的价格数组 PricesList = Source[value], // 将数组转换为表结构 PricesTable = Table.FromList(PricesList, Splitter.SplitByNothing(), null, null, ExtraValues.Error), // 扩展记录字段,保留所需列 ExpandedTable = Table.ExpandRecordColumn(PricesTable, "Column1", {"serviceName", "skuName", "location", "unitPrice"}, {"serviceName", "skuName", "location", "3YearReservedUnitPrice"}), // 清理无效数据行 CleanedTable = Table.SelectRows(ExpandedTable, each not List.Contains({null, ""}, [3YearReservedUnitPrice])) in CleanedTable
- 将生成的价格表与Usage details表建立关系:关联字段为
meterCategory = serviceName、meterName = skuName、location = location - 在Usage details表中可直接使用价格表的
3YearReservedUnitPrice字段进行分析
方案二:Power Query中逐行调用API(不推荐)
若仅需针对特定行获取价格,可在Power Query中对Usage details表添加自定义列,但需注意API限流风险,建议先对数据去重。
- 进入Usage details表的Power Query编辑界面
- 粘贴以下M语言代码添加自定义列:
let Source = <替换为你的Usage details表源>, // 添加自定义列获取3年预留单价 AddReservedPrice = Table.AddColumn(Source, "3YearReservedUnitPrice", each let // 转义字段中的单引号,避免API筛选语法错误 ServiceName = Text.Replace([meterCategory], "'", "''"), SkuName = Text.Replace([meterName], "'", "''"), Location = Text.Replace([location], "'", "''"), // 构造API请求URL ApiUrl = "https://prices.azure.com/api/retail/prices?$filter=serviceName eq '" & ServiceName & "' and skuName eq '" & SkuName & "' and location eq '" & Location & "' and reservationTerm eq '3 Years'", // 调用API并解析结果 ApiResponse = Json.Document(Web.Contents(ApiUrl)), // 提取单价,无结果则返回空值 UnitPrice = if List.Count(ApiResponse[value]) > 0 then ApiResponse[value]{0}[unitPrice] else null in UnitPrice ) in AddReservedPrice
- 替换代码中的
<替换为你的Usage details表源>为实际的表源名称,执行后即可得到包含预留单价的列
注意事项
- 方案二需注意API调用频率,Azure Retail Prices API有限流限制,建议先对Usage details表按
meterCategory、meterName、location分组去重,获取唯一组合的价格后再关联原表 - 确保Power BI Desktop具备访问
https://prices.azure.com的网络权限 - API返回的价格货币需与成本数据的货币一致,必要时需添加货币转换逻辑
内容的提问来源于stack exchange,提问作者Francesco Mantovani
相关产品推荐
相关产品推荐

