动态展开JSON响应中所有列表与记录的Power Query实现求助
动态展开Power Query中所有记录列的解决方案
你已经搞定列表的动态展开了,接下来的记录全动态展开思路其实和列表展开一脉相承——核心就是用List.Accumulate迭代处理每个记录类型的列,同时动态获取每个记录列的字段名来完成展开。下面直接给你可复用的函数和完整流程:
第一步:编写获取所有记录类型列的函数
和你之前写的Cn.GetAllColumnsWithType逻辑一致,只是把目标类型换成type record,还特意兼容了列中存在null的情况:
Cn.GetAllRecordColumns = (table as table) as list => let ColumnNames = Table.ColumnNames(table), // 筛选出所有列值为记录类型或null的列 RecordColumns = List.Select(ColumnNames, (name) => List.AllTrue(List.Transform(Table.Column(table, name), (cell) => cell = null or Type.Is(Value.Type(cell), type record) )) ) in RecordColumns;
第二步:编写动态展开所有记录列的函数
这个函数会遍历所有记录列,自动提取每个列的记录字段名,然后完成展开,还处理了边界情况:
Cn.ExpandAllRecordsFromTable = (table as table) as table => let // 获取所有记录类型的列 RecordColumns = Cn.GetAllRecordColumns(table), // 迭代展开每一个记录列 ExpandedTable = List.Accumulate(RecordColumns, table, (currentTable, colName) => let // 取该列第一个非空记录,用来提取字段名(避免全null的情况) SampleRecord = List.First(List.RemoveNulls(Table.Column(currentTable, colName))), // 全null则跳过,否则获取所有字段名 FieldNames = if SampleRecord = null then {} else Record.FieldNames(SampleRecord), // 执行展开,给新列加上原列名前缀(比如`User.Name`)避免字段名冲突 Expanded = if List.IsEmpty(FieldNames) then currentTable else Table.ExpandRecordColumn(currentTable, colName, FieldNames, List.Transform(FieldNames, (field) => colName & "." & field) ) in Expanded ) in ExpandedTable;
第三步:整合列表+记录的完整展开流程
把你之前的列表展开函数和新的记录展开函数结合,就能一键完成所有嵌套结构的展开:
Cn.FullyExpandAllListsAndRecords = (table as table) as table => let // 先展开所有列表(你已经实现的逻辑) ListColumns = Cn.GetAllColumnsWithType(table, type list), AfterListExpansion = Cn.ExpandAllListsFromTable(table, ListColumns), // 再展开所有记录 AfterRecordExpansion = Cn.ExpandAllRecordsFromTable(AfterListExpansion) in AfterRecordExpansion;
调用Cn.FullyExpandAllListsAndRecords(你的数据源表)就能自动完成所有列表和记录的动态展开了。
额外提示
如果你的数据存在多层嵌套(比如记录里还有列表/记录),可以给函数加个递归逻辑:每次展开后检查是否还有新的列表/记录列,直到没有可展开的列为止。
内容的提问来源于stack exchange,提问作者Cramble
相关产品推荐
相关产品推荐

