除了Table.Transpose()与List.Zip()能够完成行列互换,List.TransformMany()也可实现这一动作,不过代码相对没有那么简洁。
如果需要为上表添加行加总与列加总,使之转化为:
需要定义以下fnAddSum()函数:
( input as list ) as list ⇒ let Outcome= List.Transform( input, each List.Combine( { _, { List.Sum( _ ) } } ) ) in Outcome
该函数通过List.Transform()历遍input里的每一个串列(list),并在这些串列的结尾处添加一个元素,这个元素为串列原先所有的元素之和。
为实现行列转换,需要定义以下fnTranspose()函数:
( input as list ) as list ⇒ let Outcome= List.TransformMany( { input }, each List.Numbers( 0, List.Count( _{0} ) ), ( x, y ) ⇒ List.Transform( x, each _{y} ) ) in Outcome
fnTranspose()的轴心骨为List.TransfromMany(),这个函数产生的串列如果代入List.Count(),其产生的结果将会等于该函数的第一个参数和第二个参数分别代入List.Count()的结果之乘积。为了构造出Table.FromRows()或者Table.FromColumns的第一个参数所需要的结构,List.TransformMany()的第一个参数和第二个参数这个两个之中需要有一个满足代入List.Count()的结果为1,而另外一个代入List.Count()的结果为表格的行数或者列数。在fnTranspose()中List.TransformMany()的第一个参数由于在自变量input外面套一个{},第一个参数代入List.Count()的结果为1。第二个参数构造的串列代入List.Count()后的结果刚好为行的总数或者列的总数,为在第三个参数历遍处于同一行或者同一列的元素作准备。值得一提的是,其实fnTranspose()也可以围绕着List.Transform()进行构造:
( input as list ) as list ⇒ let Outcome= List.Transform( List.Numbers( 0, List.Count( input{0} ) ), (y) ⇒ List.Transform( input, (x) ⇒ x{y} ) ) in Outcome
使用List.Transform()构造fnTranspose()其实十分类似VBA的For..Next里再套For..Next,外层的List.Transform()控制的是行数或者列数,而内层的List.Transform()则是控制对应的列数或者行数。
最后,为还原丢失的数据类型需要定义fnDataType()函数:
( input as table, datatype as type ) as table ⇒ let Outcome= Table.TransformColumnTypes( input, List.TransformMany( Table.ColumnNames( input ), each { datatype }, ( x, y ) ⇒ { x, y } ) ) in Outcome
这个函数需要理解了List.TransformMany()里第一个参数调用了Table.ColumnNames的结果(该结果如果代入List.Count()将等于表格的列数),第二个参数由于串列里只有一个元素,所有List.TransformMany()的结果的元素的个数会与列数一样(列数=列数*1)。
以下为从列开始转化的代码:
let ToCols = Table.ToColumns( DB ), SumByCols = fnAddSum( ToCols ), Transpose= fnTranspose( SumByCols ), SumByRows = fnAddSum( Transpose ), ToTable = Table.FromRows( SumByRows ), DataType= fnDataType( ToTable, Number.Type ) in DataType
以下为从行开始转化的代码:
let ToRows = Table.ToRows( DB ), SumByRows = fnAddSum( ToRows ), Transpose= fnTranspose( SumByRows ), SumByCols = fnAddSum( Transpose ), ToTable = Table.FromColumns( SumByCols ), DataType= fnDataType( ToTable, Number.Type ) in DataType
感谢老师的精彩分享!文中“( input as table, datatype as type ) as table ⇒”可改为“( input as table ) as table ⇒”,本人的观点是否妥当,请赐教!
需要datatype生成Table.TransformColumnTypes()的第二个参数
谢谢老师的点评解惑!
List.Sum({[Column1],[Column2],[Column3]})
不就可以得出求和结果吗?