如何通过C#从Power BI公开URL获取数据到DataTable中?
从Power BI公开URL获取数据到C# DataTable
可以实现,但Power BI的公开查看URL本身没有提供直接返回结构化数据的API接口,需要通过以下两种可行方式处理:
方式一:使用Power BI嵌入API(推荐)
如果该报表的所有者已将其发布为可嵌入的Web内容,你可以通过Power BI REST API获取数据集数据:
- 步骤1:确认报表对应的数据集ID(可通过Power BI服务后台获取)
- 步骤2:在C#中调用Power BI REST API的
GetRows接口获取结构化数据 - 步骤3:将返回的JSON数据解析并映射到DataTable
示例代码:
using System.Data; using System.Net.Http; using System.Text.Json; public async Task<DataTable> GetPowerBiDataToDataTable(string datasetId, string tableName, string accessToken) { var dataTable = new DataTable(); using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); // 调用Power BI REST API获取数据 var response = await client.GetAsync($"https://api.powerbi.com/v1.0/myorg/datasets/{datasetId}/tables/{tableName}/rows"); response.EnsureSuccessStatusCode(); var jsonString = await response.Content.ReadAsStringAsync(); var jsonDoc = JsonDocument.Parse(jsonString); // 解析JSON结构并填充DataTable var rows = jsonDoc.RootElement.GetProperty("value"); if (rows.GetArrayLength() > 0) { // 添加列 var firstRow = rows[0]; foreach (var prop in firstRow.EnumerateObject()) { dataTable.Columns.Add(prop.Name, GetTypeFromJsonElement(prop.Value)); } // 添加行数据 foreach (var row in rows.EnumerateArray()) { var dataRow = dataTable.NewRow(); foreach (var prop in row.EnumerateObject()) { dataRow[prop.Name] = prop.Value.ValueKind switch { JsonValueKind.String => prop.Value.GetString(), JsonValueKind.Number => prop.Value.GetDouble(), JsonValueKind.Boolean => prop.Value.GetBoolean(), _ => DBNull.Value }; } dataTable.Rows.Add(dataRow); } } return dataTable; } private Type GetTypeFromJsonElement(JsonElement element) { return element.ValueKind switch { JsonValueKind.String => typeof(string), JsonValueKind.Number => element.TryGetInt64(out _) ? typeof(long) : typeof(double), JsonValueKind.Boolean => typeof(bool), _ => typeof(object) }; }
注意:需要先通过Azure AD应用注册获取有效的Power BI访问令牌,并确保应用拥有对应数据集的读取权限。
方式二:网页抓取(不推荐,易失效)
如果无法使用API,可模拟浏览器请求抓取页面中的可视化表格数据,但Power BI的前端数据是动态渲染的,需要处理JavaScript加载后的内容:
- 使用
Selenium或PuppeteerSharp等工具模拟浏览器加载页面 - 定位页面中的表格元素并提取数据
- 将提取的文本数据转换为DataTable
示例代码(使用PuppeteerSharp):
using System.Data; using PuppeteerSharp; public async Task<DataTable> ScrapePowerBiTable(string url) { var dataTable = new DataTable(); await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision); using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }); using var page = await browser.NewPageAsync(); await page.GoToAsync(url, new NavigationOptions { WaitUntil = WaitUntilNavigation.Networkidle2 }); // 等待表格加载完成(需根据实际页面的DOM结构调整选择器) await page.WaitForSelectorAsync("table"); // 提取表格数据 var rows = await page.QuerySelectorAllAsync("table tr"); if (rows.Count > 0) { // 提取表头 var headerCells = await rows[0].QuerySelectorAllAsync("th"); foreach (var cell in headerCells) { var text = await cell.EvaluateFunctionAsync<string>("e => e.textContent.trim()"); dataTable.Columns.Add(text); } // 提取行数据 for (int i = 1; i < rows.Count; i++) { var cells = await rows[i].QuerySelectorAllAsync("td"); var dataRow = dataTable.NewRow(); for (int j = 0; j < cells.Count; j++) { var text = await cells[j].EvaluateFunctionAsync<string>("e => e.textContent.trim()"); dataRow[j] = text; } dataTable.Rows.Add(dataRow); } } return dataTable; }
注意:这种方式完全依赖Power BI前端的DOM结构,一旦平台更新页面布局,代码会直接失效,且可能违反Power BI的服务条款,仅作为临时方案使用。
内容的提问来源于stack exchange,提问作者Alessandro Sanfilippo
相关产品推荐
相关产品推荐

