问题
Is there a quick way to "unpivot" an Excel matrix/pivot-table (in Excel or elsewhere), without writing macros or other code ?
Again, I can write code (C# or VBA or whatever) that does that myselfs.
I want to know if it is possible to do it without code, quickly ?
E.g. I need to convert this permission matrix (given as Excel-table/matrix)
into this half-normalized table (so I can insert it into a SQL database):
e.g. in SQL I could do it like this:
CREATE TABLE dbo.T_DocumentMatrix
(
[Function] [varchar](255) NULL,
[GROUP-Admin] [varchar](255) NULL,
[GROUP-SuperUser] [varchar](255) NULL,
[GROUP-Manager] [varchar](255) NULL,
[GROUP-OLAP] [varchar](255) NULL,
[GROUP-1] [varchar](255) NULL,
[GROUP-2] [varchar](255) NULL,
[GROUP-3] [varchar](255) NULL,
[GROUP-4] [varchar](255) NULL,
[GROUP-5] [varchar](255) NULL,
[GROUP-6] [varchar](255) NULL,
[GROUP-7] [varchar](255) NULL,
[GROUP-8] [varchar](255) NULL,
[Externals] [varchar](255) NULL
);
copy-paste the data from excel, and then
SELECT *
FROM
(
SELECT
[Function]
,[GROUP-Admin]
,[GROUP-SuperUser]
,[GROUP-Manager]
,[GROUP-OLAP]
,[GROUP-1]
,[GROUP-2]
,[GROUP-3]
,[GROUP-4]
,[GROUP-5]
,[GROUP-6]
,[GROUP-7]
,[GROUP-8]
,[Externals]
FROM T_DocumentMatrix
) AS p
UNPIVOT
(
Rights FOR GroupName IN
(
[GROUP-Admin]
,[GROUP-SuperUser]
,[GROUP-Manager]
,[GROUP-OLAP]
,[GROUP-1]
,[GROUP-2]
,[GROUP-3]
,[GROUP-4]
,[GROUP-5]
,[GROUP-6]
,[GROUP-7]
,[GROUP-8]
,[Externals]
)
) AS unpvt
;
However, that requires I change the table-create script and the unpivot-script for every change in groups...
回答1:
Oh, well, it's a little complicated. One of the problems is, the wizard-callup shortcuts don't work in non-english versions of excels (damn, at home I would have the English version, but here at work...)
Here's a good video: https://www.youtube.com/watch?v=pUXJLzqlEPk
But youtube videos can be deleted, so to make it a solid SO answer:
First, you need to go to "Options", and add the menuband-item "Pivot table and PivotChart Wizard".
Create a multiple consolidation pivot table
and use the custom variant
and select the range, and in new work sheet
then delete rows and columns fields
Double click on the NUMBER (54 in the picture)
and excel will give you the halfway normalized data.
回答2:
There's another way now through Power Query:
- select your cells
- menu
Data
>From a table or a range
screenshot - in the Power Query editor, chose all columns save the first one and then
Transform
>Unpivot
screenshot - the table is unpivoted. go to
Home
>Close and load
screenshot - your unpivoted table is here. right-click it and choose
Refresh
if your original table is updated screenshot
回答3:
I am using this VBA code
Sub Unpivot()
'
Dim Rowlabel As Range
Dim Columnlabel As Range
Dim Pap As Range
Dim Tabl As Range
Dim i As Integer
Dim j As Integer
Dim a As Integer
Dim b As Integer
Dim Data As Range
Dim k As Integer
Dim Label As Range
Dim pvtCache As PivotCache
Dim pvt As PivotTable
Dim SrcData As String
'
ActiveSheet.Copy Before:=Worksheets(1)
Set Tabl = Selection
For Each Pap In Tabl
If Pap.MergeCells Then
With Pap.MergeArea
.UnMerge
.Value = Pap.Value
End With
End If
Next
i = Application.InputBox("Number of row contain label:", "Excel", i, Type:=2)
j = Application.InputBox("Number of column contain label:", "Excel", j, Type:=2)
On Error Resume Next
Sheets("Unpivot_Table").Delete
Sheets.Add.Name = "Unpivot_Table"
Set Pap = Range("Unpivot_Table!B2")
b = Tabl.Rows.Count
a = Tabl.Columns.Count
Set Data = Range(Tabl.Cells(i + 1, j + 1), Tabl.Cells(b, a))
Set Columnlabel = Range(Tabl.Cells(i + 1, 1), Tabl.Cells(b, j))
Set Rowlabel = Range(Tabl.Cells(1, j + 1), Tabl.Cells(i, a))
Pap.Select
For Each Column In Data.Columns
Column.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Columnlabel.Copy
Selection.Offset(0, 1).PasteSpecial Paste:=xlPasteValues
Column.Copy
Selection.Offset(b - i, -1).Select
Next Column
Pap.Offset(0, j + 1).Select
For Each Column In Rowlabel.Columns
Column.Copy
Range(Selection, Selection.Offset(b - i - 1, 0)).PasteSpecial Paste:=xlPasteValues, Transpose:=True
Selection.End(xlDown).Offset(1, 0).Select
Next Column
Set Label = Range(Pap.Offset(-1, 0), Pap.Offset(0, i + j + 1))
For k = 1 To i + j + 1
Label.Cells(1, k).Value = Application.InputBox(Label.Cells(2, k).Value & " is belong to Fieldname", "Hoang", k, Type:=2)
Next
Range(Pap.End(xlUp), Pap.End(xlDown).End(xlToRight)).Select
SrcData = ActiveSheet.Name & "!" & Selection.Address
On Error Resume Next
Sheets("Pivot").Delete
Sheets.Add.Name = "Pivot"
Set pvtCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=SrcData)
Set pvt = pvtCache.CreatePivotTable( _
TableDestination:="Pivot!" & Sheets("Pivot").Range("A3").Address(ReferenceStyle:=xlR1C1), _
TableName:="PivotTable1")
End Sub
来源:https://stackoverflow.com/questions/32115219/unpivot-an-excel-matrix-pivot-table