Power Query 系列 (12) - Power Query 结构化列应用案例
本篇数据处理来自一个实际处理数据的简化。下图中,假设左边是一个直观的 BOM 结构展示,数据在 Excel 中存储格式如中间部分所示:第一列为物料编码的级别,第二列为物料编码。数据处理任务:需要在 Excel 中增加一列输出物料编码上一级的物料编码(目标为黄色部分)。
Excel 处理这种没有明显规律的数据,借助 VBA 比较方便。我的方法是这样的:从第二行开始循环,如果 Level = 1,初始化一个数组 BomMaterials
, 如果不等于 1,则根据 level 刷新该级别的物料编码,并且将上级物料的编码写入到 Parent 列。下面的 VBA 代码显示了处理过程。
Public Sub populate_parent()Dim currSheet As WorksheetSet currSheet = Sheet3Dim i As LongDim BomMaterials() As StringDim level As IntegerFor i = 2 To 367 ' 数据开始和结束行level = Range("B" & i).ValueIf Range("B" & i).Value = 1 ThenReDim BomMaterials(1 To 8)BomMaterials(level) = Range("C" & i).ValueElseBomMaterials(level) = Range("C" & i).ValueRange("D" & i).Value = BomMaterials(level - 1)End IfNext
End Sub
现在需要在 Power Query (PQ) 中做相同的处理。将 Excel 工作表的 BOM 数据通过 Ctrl + T 变成 Excel 的 Table,加载到 Power Query 查询编辑器(操作过程可以参考我之前的博客),此时界面如下。为了处理方便,步骤名称我改为了英文。
对 BOM查询,添加一个新的条件列,找出每一行物料编码所属的第一级物料编码:
点击确定按钮,回到查询编辑器,此时界面如下。除了第 1 级,其他级别物料编码为 null。
选中 Level1 列,切换到【转换】选项卡,打开【填充】下拉框,选择向下填充。或者在选中这一列后,右键菜单,也有【填充】菜单项。向下填充后,所有 null 值都被自动填充为上一行的值,直到遇到非空值。
选中左边 BOM 查询,右键菜单【复制】,将 BOM 复制为一个新的查询,将新查询名改为 BOMGrouped。目前 BOMGrouped 查询和 BOM 查询完全相同。
选择 BOMGrouped 查询,选中 Level1 这一列,通过【主页】或者右键菜单中的【分组依据】,打开下面的对话框:
注意这里选择:所有行(要点)。
通过这种分组的方式,除第一级物料编码之外的所有数据,全部变成一列。Grouped 这一列中的每个单元格,不是一个单值数据,而是 Table 类型的数据,所以将其称为结构化列。我们后面可以对结构化列进行展开 (expand),获得我们想要的数据,这种数据处理方法跟 Excel 有着天壤之别,后面我们还将通过其它示例,领会和掌握结构化列的使用方法。结构化列不仅仅是 Table 类型,如果某一列是 Table、Record 或者 List,则都是结构化列。
完成本步骤,BOMGrouped 查询的 M语言脚本如下:
let Source = Excel.CurrentWorkbook(){[Name="BOM"]}[Content],ChangedTypes = Table.TransformColumnTypes(Source,{{"IDX", Int64.Type}, {"Level", Int64.Type}, {"MaterialCode", type text}}),AddedLevel1 = Table.AddColumn(ChangedTypes, "Level1", each if [Level] = 1 then [MaterialCode] else null),FilledDown = Table.FillDown(AddedLevel1,{"Level1"}),GroupedByLevel1 = Table.Group(FilledDown, {"Level1"}, {{"Grouped", each _, type table [IDX=number, Level=number, MaterialCode=text, Level1=text]}})
inGroupedByLevel1
接下来,选中 BOM 查询,与刚才加工好的 BOMGrouped 查询做一个合并查询 (操作方法可以参考本系列第 9 和第 10 篇 ):
完成本步骤后界面如下:
需要对 BOMGrouped 列进行展开操作,展开时只保留 Grouped 字段:
完成操作后,点击 Grouped 字段,下面已经可以看到 BOM 信息,是 Table 类型的结构化数据:
目前这个子表 (sub-table) 包含所有数据,我们需要对其进行筛选。为了方便处理,我们添加一列,值与 Grouped 一样:
完成刚才的步骤,高级编辑器中的 M 代码为:
let Source = Excel.CurrentWorkbook(){[Name="BOM"]}[Content],ChangedTypes = Table.TransformColumnTypes(Source,{{"IDX", Int64.Type}, {"Level", Int64.Type}, {"MaterialCode", type text}}),AddedLevel1 = Table.AddColumn(ChangedTypes, "Level1", each if [Level] = 1 then [MaterialCode] else null),FilledDown = Table.FillDown(AddedLevel1,{"Level1"}),MergedWithBOMGrouped = Table.NestedJoin(FilledDown, {"Level1"}, BOMGrouped, {"Level1"}, "BOMGrouped", JoinKind.LeftOuter),ExpandedBOMGrouped = Table.ExpandTableColumn(MergedWithBOMGrouped, "BOMGrouped", {"Grouped"}, {"Grouped"}),AddedSelectedMaterialCol = Table.AddColumn(ExpandedBOMGrouped, "SelectedMaterial", each [Grouped])
inAddedSelectedMaterialCol
为了对 Grouped 列包含的字表数据进行筛选,需要用到两个标准款函数:Table.SelectRows
和 Table.Last
。
Table.SelectRows(table as table, condition as function) as table
Table.SelectRows
函数根据条件筛选出表中符合条件的记录,返回值是 table
Table.Last(table as table, optional default as any) as any
Table.Last
函数获取 table 中的最后一行,返回值一般是 record。
使用上面两个函数,对最后一个步骤的代码进行变更,变更之前:
AddedSelectedMaterialCol = Table.AddColumn(ExpandedBOMGrouped, "SelectedMaterial", each [Grouped])
首先对 subtable 进行筛选,筛选出 IDX 比主表 IDX 小,物料的 Level 比本 Level 小 1 的所有记录:
AddedSelectedMaterialCol = Table.AddColumn(ExpandedBOMGrouped, "SelectedMaterial", each Table.SelectRows([Grouped], (x) => x[IDX] <= [IDX] and x[Level] = [Level]-1))
回到查询编辑器界面,子表的筛选条件已经起作用了:
然后再对最后一个步骤的代码用 Table.Last
函数,将符合条件的记录从 Table 变成 Record,经这一处理,字表只剩下最后一行符合条件的记录,单元格的数据类型是 Record:
AddedSelectedMaterialCol = Table.AddColumn(ExpandedBOMGrouped, "SelectedMaterial", each Table.Last(Table.SelectRows([Grouped], (x) => x[IDX] <= [IDX] and x[Level] = [Level]-1)))
完成这一个步骤,界面如下:
M 语言脚本如下:
let Source = Excel.CurrentWorkbook(){[Name="BOM"]}[Content],ChangedTypes = Table.TransformColumnTypes(Source,{{"IDX", Int64.Type}, {"Level", Int64.Type}, {"MaterialCode", type text}}),AddedLevel1 = Table.AddColumn(ChangedTypes, "Level1", each if [Level] = 1 then [MaterialCode] else null),FilledDown = Table.FillDown(AddedLevel1,{"Level1"}),MergedWithBOMGrouped = Table.NestedJoin(FilledDown, {"Level1"}, BOMGrouped, {"Level1"}, "BOMGrouped", JoinKind.LeftOuter),ExpandedBOMGrouped = Table.ExpandTableColumn(MergedWithBOMGrouped, "BOMGrouped", {"Grouped"}, {"Grouped"}),AddedSelectedMaterialCol = Table.AddColumn(ExpandedBOMGrouped, "SelectedMaterial", each Table.Last(Table.SelectRows([Grouped], (x) => x[IDX] <= [IDX] and x[Level] = [Level]-1)))
inAddedSelectedMaterialCol
读者也可将 M 语言的脚本拷贝到高级编辑器,直接看效果,并且可以进入每一步骤查看数据的变化过程。最后,对 SelectedMaterial 结构化列展开,只保留 MaterialCode 这一列。
将列名改为 Parent,并删除不需要的辅助列。完成后的 M 语言脚本:
let Source = Excel.CurrentWorkbook(){[Name="BOM"]}[Content],ChangedTypes = Table.TransformColumnTypes(Source,{{"IDX", Int64.Type}, {"Level", Int64.Type}, {"MaterialCode", type text}}),AddedLevel1 = Table.AddColumn(ChangedTypes, "Level1", each if [Level] = 1 then [MaterialCode] else null),FilledDown = Table.FillDown(AddedLevel1,{"Level1"}),MergedWithBOMGrouped = Table.NestedJoin(FilledDown, {"Level1"}, BOMGrouped, {"Level1"}, "BOMGrouped", JoinKind.LeftOuter),ExpandedBOMGrouped = Table.ExpandTableColumn(MergedWithBOMGrouped, "BOMGrouped", {"Grouped"}, {"Grouped"}),AddedSelectedMaterialCol = Table.AddColumn(ExpandedBOMGrouped, "SelectedMaterial", each Table.Last(Table.SelectRows([Grouped], (x) => x[IDX] <= [IDX] and x[Level] = [Level]-1))),ExpandedMaterialCol = Table.ExpandRecordColumn(AddedSelectedMaterialCol, "SelectedMaterial", {"MaterialCode"}, {"Parent"}),DeletedCols = Table.RemoveColumns(ExpandedMaterialCol,{"Level1", "Grouped"})
inDeletedCols
通过【主页】上关闭并上载,将结果数据加载到 Excel 工作表:
示例数据已经放到 github - BOMSample.xlsx,方便大家学习。
Power Query 系列 (12) - Power Query 结构化列应用案例相关推荐
- power query 向下填充_Power Query 系列 (12) - Power Query 结构化列应用案例
本篇数据处理来自一个实际处理数据的简化.下图中,假设左边是一个直观的 BOM 结构展示,数据在 Excel 中存储格式如中间部分所示:第一列为物料编码的级别,第二列为物料编码.数据处理任务:需要在 E ...
- Power Query 系列 (01) - Power Query 介绍
Power Query 介绍 Power Query 是微软提供的工具,Excel 2013 版作为插件加载使用,从 Office 2016 版开始,Power Query 的功能集成到 Excel ...
- Power Query 系列 (13) - 自定义函数
本篇博客介绍 Power Query 自定义函数的技巧,在 PQ 中计算个税. 以工资类所得应交个税为例,最新的个税起征点为 5000 并按下表的级次进行缴税(假设没有其它扣除项). 对照税率表,我们 ...
- access“idno”字段改为文本型_结构化文本计算示例(一)
结构化文本是很常见的文件格式,对结构化文本的计算也是很常见的需求.在实现这种计算时,一种很容易想到的办法是将文件导入数据库后再计算,但这会消耗大量时间以及昂贵的数据库资源,而且有的场合下并没有合适的数 ...
- 关于结构化伪类的案例
结构化伪类的案例 开发工具与关键技术:DW html和css 作者:沈金凤 年级:18级(4)班 撰写日期:2019年2月21日 伪类分很多种例如:UI伪类,结构化伪类,伪元素,CSS3新增伪类选择器 ...
- Google结构化数据
为什么要向网页添加结构化数据? 添加结构化数据可让您获得对用户更有吸引力的搜索结果,并可能会鼓励用户与您的网站进行更多互动,这就是富媒体搜索结果. 以下是一些为网站实现了结构化数据的案例研究: Rot ...
- 结构化文本计算示例(一)
结构化文本是很常见的文件格式,对结构化文本的计算也是很常见的需求.在实现这种计算时,一种很容易想到的办法是将文件导入数据库后再计算,但这会消耗大量时间以及昂贵的数据库资源,而且有的场合下并没有合适的数 ...
- 结构化查询语言(Structured Query Language)
2019独角兽企业重金招聘Python工程师标准>>> 结构化查询语言(Structured Query Language)简称SQL(发音:/ˈɛs kjuː ˈɛl/ " ...
- Oracle结构化查询语言(Structured Query Language)
SQL是结构化查询语言(Structured Query Language) 专门用于数据存取.数据更新及数据库管理等操作. 此文后积累学习用SQL语句对数据库的表进行增删改查的操作. 在Oracle ...
最新文章
- Ubuntu 系统 查看代码的方法在那些地方使用
- 天涯htmlcss基础框架
- 学长毕业日记 :本科毕业论文写成博士论文的神操作20170413
- Abbirb120型工业机器人_ABB工业机器人-ABBIRB120结构介绍
- HTML与CSS布局技巧总结
- 如何添加自动更新Play Framework 2.X项目的版本号
- bzoj千题计划227:bzoj1486: [HNOI2009]最小圈
- 详细的 Python 安装教程(windows)
- 敏捷开发相关概念——学习笔记
- 浅学一下XMind思维导图
- python期权定价公式_一揽子欧洲期权蒙特卡洛定价(python)(一)
- 5-lighttpd安装
- 腾讯QQ就“读取浏览器历史记录”道歉!
- DrawerLayoutMenu使用详解
- Spring Cloud Alibaba学习记录
- Android无线调试 Wifi连接ADB不用数据线
- STL之容器stack
- java的 %3c%3c 运算符_scanf(%3c%3c, a, b)
- python炒股学习软件_要炒股,学Python-LSTM学习
- RH10M漏电故障保护继电器
热门文章
- 电脑蓝屏c语言代码大全,Win10电脑卡机遇到蓝屏代码0xc000014c应该怎么办?
- 华为服务器gpu芯片怎么样,GPU服务器怎么样
- 计算机word求差函数,【2人回答】如何在Word表格中插入公式求差?-3D溜溜网
- Debian7升级glibc至2.15
- Windows服务简介(转)
- 泰勒公式求极限c语言switch,C语言利用泰勒公式构造求SIN(X),求大触帮看我的代码哪里有问题...
- html表格与CSS控制表格样式
- FICO入门系列2:FICO中的组织架构
- vue mounted遇到的问题
- java实现html页面转pdf解决方案_[Java教程]纯js实现html转pdf