我想对其进行转换,使其看起来像这样:
该想法是取消旋转(或转置)表格,以便可以将其输入其他BI工具中,并便于分析。
我大约有20张这样的桌子,上面有100多个列,因此当然几乎不可能手动进行。
如何使用PowerQuery完成此操作?我尝试使用unpivot功能,但由于显示NYC1,NYC2等而卡住了。VBA,宏也无法正常工作。任何其他建议,我们将不胜感激,但我现在不知所措。救命!
答案 0 :(得分:3)
在加载到PowerQuery中之前,请使用定界符(空格)将标题连接到[程序名称]后的空白行。如果使用office365,则可以使用TEXTJOIN函数执行此操作。结果看起来像这样(我没有复制所有数据):
将此范围导入PowerQuery并执行以下步骤(请勿选中my table has headers
复选框)
脚本如下:
let
Source = Excel.CurrentWorkbook(){[Name="table"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}, {"Column2", type any}, {"Column3", type any}, {"Column4", type any}, {"Column5", type any}, {"Column6", type any}, {"Column7", type any}, {"Column8", type any}, {"Column9", type any}}),
#"Removed Top Rows" = Table.Skip(#"Changed Type",2),
#"Promoted Headers" = Table.PromoteHeaders(#"Removed Top Rows", [PromoteAllScalars=true]),
#"Changed Type1" = Table.TransformColumnTypes(#"Promoted Headers",{{"Program Name", type text}, {"NY Budget", Int64.Type}, {"NY Revenue", Int64.Type}, {"NY Cost", Int64.Type}, {"NY Margin", Int64.Type}, {"LA Budget", Int64.Type}, {"LA Revenue", Int64.Type}, {"LA Cost", Int64.Type}, {"LA Margin", Int64.Type}}),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type1", {"Program Name"}, "Attribute", "Value"),
#"Split Column by Delimiter" = Table.SplitColumn(#"Unpivoted Other Columns", "Attribute", Splitter.SplitTextByDelimiter(" ", QuoteStyle.Csv), {"Attribute.1", "Attribute.2"}),
#"Changed Type2" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Attribute.1", type text}, {"Attribute.2", type text}}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type2",{{"Attribute.1", "City"}, {"Attribute.2", "Description"}}),
#"Reordered Columns" = Table.ReorderColumns(#"Renamed Columns",{"City", "Program Name", "Description", "Value"})
in
#"Reordered Columns"
这是结果(在Power Query编辑器中)
答案 1 :(得分:1)
这是一种非常通用的depivot方法,可以处理多个行/列标题。
在运行之前在源表中选择一个单元格(注意-这使用CurrentRegion
,因此如果表中的行或列完全为空白,则会失败。)
Sub UnpivotIt()
Dim numRowHeaders As Long, numColHeaders As Long
Dim numRows As Long, numCols As Long, rng As Range
Dim rngOut As Range, r As Long, c As Long, i As Long, n As Long
Dim arrIn, arrOut, outRow As Long
arrIn = Selection.CurrentRegion.Value
numRowHeaders = Application.InputBox("How many header rows?", Type:=1)
numColHeaders = Application.InputBox("How many header columns?", Type:=1)
Set rngOut = Application.InputBox("Select output (top-left cell)", Type:=8)
Set rngOut = rngOut.Cells(1) 'in case >1 cells selected
numRows = UBound(arrIn, 1)
numCols = UBound(arrIn, 2)
ReDim arrOut(1 To ((numRows - numRowHeaders) * (numCols - numColHeaders)), _
1 To (numRowHeaders + numColHeaders + 1))
outRow = 0
For r = (numRowHeaders + 1) To numRows
For c = (numColHeaders + 1) To numCols
'only copy if there's a value
If Len(arrIn(r, c)) > 0 Then
outRow = outRow + 1
i = 1
For n = 1 To numColHeaders 'copy column headers
arrOut(outRow, i) = arrIn(r, n)
i = i + 1
Next n
For n = 1 To numRowHeaders '...row headers
arrOut(outRow, i) = arrIn(n, c)
i = i + 1
Next n
arrOut(outRow, i) = arrIn(r, c) '...and the value
End If
Next c
Next r
rngOut.Resize(outRow, UBound(arrOut, 2)).Value = arrOut
End Sub