Excel 将重复列重新构造为行VBA
我有一个广泛的数据集,由标识符和一系列20组重复列组成,每组中有相同的8列。我想将这些数据重新组织成行,这样每个重复的标识符和每个8序列代表一个唯一的行 我有一些代码可以让我大部分时间都在那里,如果我只在标识符和前两列上运行它,它就会工作。它不会通过每组的第3-8列。下面是在每个组的前两列上成功运行的代码Excel 将重复列重新构造为行VBA,excel,vba,Excel,Vba,我有一个广泛的数据集,由标识符和一系列20组重复列组成,每组中有相同的8列。我想将这些数据重新组织成行,这样每个重复的标识符和每个8序列代表一个唯一的行 我有一些代码可以让我大部分时间都在那里,如果我只在标识符和前两列上运行它,它就会工作。它不会通过每组的第3-8列。下面是在每个组的前两列上成功运行的代码 Sub StackData() Dim Key, Dic As Object, cl As Range, Data As Range, i&, n& Set
Sub StackData()
Dim Key, Dic As Object, cl As Range, Data As Range, i&, n&
Set Dic = CreateObject("Scripting.Dictionary")
Dic.CompareMode = vbTextCompare
i = Cells(Rows.Count, "A").End(xlUp).Row
n = 1
Set Data = Range("F2:F" & i & "," & "N2:N" & i & "," & "V2:V" & i & "," & "AD2:AD" & i & "," & "AL2:AL" & i & "," & "AT2:AT" & i & "," & "BB2:BB" & i & "," & "BJ2:BJ" & i & "," & "BR2:BR" & i & "," & "BZ2:BZ" & i & "," & "CH2:CH" & i & "," & "CP2:CP" & i & "," & "CX2:CX" & i & "," & "DF2:DF" & i & "," & "DN2:DN" & i & "," & "DV2:DV" & i & "," & "ED2:ED" & i & "," & "EL2:EL" & i & "," & "ET2:ET" & i & "," & "FB2:FB" & i)
Dic.Add "|Name", "Var1|Var2|Var3|Var4|Var5|Var6|Var7|Var8"
For Each cl In Data
If Cells(cl.Row, "A") <> "" Then
Dic.Add n & "|" & Cells(cl.Row, "A"), cl.Text & "|" & cl.Offset(, 1).Text
n = n + 1
End If
Next cl
n = 1
For Each Key In Dic
Worksheets("Worksheet").Cells(n, "A") = Split(Key, "|")(1)
Worksheets("Worksheet").Cells(n, "B") = Split(Dic(Key), "|")(0)
Worksheets("Worksheet").Cells(n, "C") = Split(Dic(Key), "|")(1)
n = n + 1
Next Key
End Sub
子堆栈数据()
尺寸键,Dic作为对象,cl作为范围,数据作为范围,i&,n&
设置Dic=CreateObject(“Scripting.Dictionary”)
Dic.CompareMode=vbTextCompare
i=单元格(Rows.Count,“A”)。结束(xlUp)。行
n=1
“2.2:V”和“i&”,以及“2.2:V”和“我和我”和“2.2:V”和“我和,”以及“AD2:AD和i&”,以及“2:AL和2:AL和i&,”和“2:F和i&”和“2:F”和“F-2:F”和“F-2:F”和数据范围范围的范围,包括包括范围范围,包括:F-2:AD和我和我和我的范围范围范围,以及各种各种数据,以及“F-2:F和我和我和我和我和我的范围,以及“F”和“F-2:F”和我和我和我和我和我和我,以及我,以及“2:F”和我和我,以及我,以及“2:A:F和我和我,以及我,以及“2:A:A.2:L和我和我和我和我,以及我,以及我,以及我,以及我,以及我,以及DN“&i&“,”和“DV2:DV”&i&“,”和“ED2:ED”&i&“,”和“EL2:EL”&i&“,”和“ET2:ET”&i&“,”和“FB2:FB”&i)
Dic.添加“|名称”、“Var1 | Var2 | Var3 | Var4 | Var5 | Var6 | Var7 | Var8”
对于数据中的每个cl
如果单元格(第1行,“A”)“则
Dic.添加n&“|”和单元格(第1行,“A”)、第1行文本和第1行偏移(,1).Text
n=n+1
如果结束
下一个cl
n=1
对于Dic中的每个键
工作表(“工作表”)。单元格(n,“A”)=拆分(键“|”)(1)
工作表(“工作表”)。单元格(n,“B”)=拆分(Dic(键),“|”)(0)
工作表(“工作表”)。单元格(n,“C”)=拆分(Dic(键),“|”)(1)
n=n+1
下一键
端接头
当我添加到“For each Key in Dic”时,我得到一个错误。任何关于我做错了什么的输入?也可以使用不同的方法来解决这个问题,这可能比这个笨拙的方法更简洁。您也可以使用Excel 2010中提供的Power Query来解决这个问题+ 在下面的代码中,我使用了您提供的示例。 您需要进行一些更改以使其适应您的实际数据 例如:
- 在代码中,我选择了前两列,取消了其他列;在实际数据中,您必须选择前三列
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Name", "ID"}, "Attribute", "Value"),
#"Added Index" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 0, 1),
#"Inserted Integer-Division" = Table.AddColumn(#"Added Index", "Integer-Division", each Number.IntegerDivide([Index], 3), Int64.Type),
#"Removed Columns" = Table.RemoveColumns(#"Inserted Integer-Division",{"Attribute", "Index"}),
#"Grouped Rows" = Table.Group(#"Removed Columns", {"Integer-Division"}, {{"Grouped", each _, type table [Name=text, ID=number, Value=text, #"Integer-Division"=number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Name", each List.First(Table.Column([Grouped],"Name"))),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "ID", each List.First(Table.Column([Grouped],"ID"))),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Custom", each Table.Column([Grouped],"Value")),
#"Extracted Values" = Table.TransformColumns(#"Added Custom2", {"Custom", each Text.Combine(List.Transform(_, Text.From), ";"), type text}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Extracted Values", "Custom", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Custom.1", "Custom.2", "Custom.3"}),
#"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Custom.1", type text}, {"Custom.2", type text}, {"Custom.3", type text}}),
#"Removed Columns1" = Table.RemoveColumns(#"Changed Type",{"Integer-Division", "Grouped"}),
//Rename last columns
origColNames =List.Buffer(List.Range(Table.ColumnNames(#"Removed Columns1"),2)),
newNameNum = List.Generate(() => 1 , each _ <=List.Count(origColNames), each _ + 1),
//There has to be a better way to convert the numbers to strings
#"Converted to Table" = Table.FromList(newNameNum, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Changed Type1" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type text}}),
newNames = Table.Column(#"Changed Type1","Column1"),
renameCols = Table.RenameColumns(#"Removed Columns1",List.Zip({origColNames,newNames}))
in
renameCols
Sub stackData()
' Error Handler
Const Proc As String = "stackData"
On Error GoTo cleanError
' Source
Const srcName As String = "Sheet1" ' Worksheet Name
Const srcFirst As String = "A2" ' First Cell Address
Const LRCol As Long = 1 ' Last Row Column Number
Const IdentCols As Long = 3 ' Number of Identifier Columns
Const GroupCols As Long = 8 ' Number of Group Columns
Const GroupsCount As Long = 20 ' Number of Groups
' Target
Const tgtName As String = "Sheet2" ' Worksheet Name
Const tgtFirst As String = "A2" ' First Cell Address
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values of Source Range to Source Array.
Dim ws As Worksheet: Set ws = wb.Worksheets(srcName)
Dim rng As Range
Set rng = ws.Columns(LRCol).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.row < ws.Range(srcFirst).row Then Exit Sub
Dim LastRow As Long: LastRow = rng.row
Set rng = Nothing
Dim LastCol As Long: LastCol = IdentCols + GroupCols * GroupsCount
Dim Source As Variant
Source = ws.Range(ws.Range(srcFirst), ws.Cells(LastRow, LastCol))
Set ws = Nothing
Dim ubS As Long: ubS = UBound(Source)
' Write values of Source Array to Target Array.
Dim Target As Variant
ReDim Target(1 To ubS * GroupsCount, 1 To IdentCols + GroupCols)
Dim i As Long, j As Long, k As Long, m As Long
GoSub writeIdentifiers
GoSub writeGroups
' Write values of Target Array to Target Range.
Set ws = wb.Worksheets(tgtName)
ws.Range(tgtFirst).Resize(UBound(Target), UBound(Target, 2)).Value = Target
' Inform user.
MsgBox "Data stacked.", vbInformation, "Success"
Exit Sub
' Subroutines
writeIdentifiers:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To IdentCols
Target(m, k) = Source(i, k)
Next k
m = m + 1
Next j
Next i
Return
writeGroups:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To GroupCols
Target(m, k + IdentCols) = _
Source(i, k + IdentCols + (j - 1) * GroupCols)
Next k
m = m + 1
Next j
Next i
Return
' Error Handler
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
End Sub
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Name", "ID"}, "Attribute", "Value"),
#"Added Index" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 0, 1),
#"Inserted Integer-Division" = Table.AddColumn(#"Added Index", "Integer-Division", each Number.IntegerDivide([Index], 3), Int64.Type),
#"Removed Columns" = Table.RemoveColumns(#"Inserted Integer-Division",{"Attribute", "Index"}),
#"Grouped Rows" = Table.Group(#"Removed Columns", {"Integer-Division"}, {{"Grouped", each _, type table [Name=text, ID=number, Value=text, #"Integer-Division"=number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Name", each List.First(Table.Column([Grouped],"Name"))),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "ID", each List.First(Table.Column([Grouped],"ID"))),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Custom", each Table.Column([Grouped],"Value")),
#"Extracted Values" = Table.TransformColumns(#"Added Custom2", {"Custom", each Text.Combine(List.Transform(_, Text.From), ";"), type text}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Extracted Values", "Custom", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Custom.1", "Custom.2", "Custom.3"}),
#"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Custom.1", type text}, {"Custom.2", type text}, {"Custom.3", type text}}),
#"Removed Columns1" = Table.RemoveColumns(#"Changed Type",{"Integer-Division", "Grouped"}),
//Rename last columns
origColNames =List.Buffer(List.Range(Table.ColumnNames(#"Removed Columns1"),2)),
newNameNum = List.Generate(() => 1 , each _ <=List.Count(origColNames), each _ + 1),
//There has to be a better way to convert the numbers to strings
#"Converted to Table" = Table.FromList(newNameNum, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Changed Type1" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type text}}),
newNames = Table.Column(#"Changed Type1","Column1"),
renameCols = Table.RenameColumns(#"Removed Columns1",List.Zip({origColNames,newNames}))
in
renameCols
Sub stackData()
' Error Handler
Const Proc As String = "stackData"
On Error GoTo cleanError
' Source
Const srcName As String = "Sheet1" ' Worksheet Name
Const srcFirst As String = "A2" ' First Cell Address
Const LRCol As Long = 1 ' Last Row Column Number
Const IdentCols As Long = 3 ' Number of Identifier Columns
Const GroupCols As Long = 8 ' Number of Group Columns
Const GroupsCount As Long = 20 ' Number of Groups
' Target
Const tgtName As String = "Sheet2" ' Worksheet Name
Const tgtFirst As String = "A2" ' First Cell Address
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values of Source Range to Source Array.
Dim ws As Worksheet: Set ws = wb.Worksheets(srcName)
Dim rng As Range
Set rng = ws.Columns(LRCol).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.row < ws.Range(srcFirst).row Then Exit Sub
Dim LastRow As Long: LastRow = rng.row
Set rng = Nothing
Dim LastCol As Long: LastCol = IdentCols + GroupCols * GroupsCount
Dim Source As Variant
Source = ws.Range(ws.Range(srcFirst), ws.Cells(LastRow, LastCol))
Set ws = Nothing
Dim ubS As Long: ubS = UBound(Source)
' Write values of Source Array to Target Array.
Dim Target As Variant
ReDim Target(1 To ubS * GroupsCount, 1 To IdentCols + GroupCols)
Dim i As Long, j As Long, k As Long, m As Long
GoSub writeIdentifiers
GoSub writeGroups
' Write values of Target Array to Target Range.
Set ws = wb.Worksheets(tgtName)
ws.Range(tgtFirst).Resize(UBound(Target), UBound(Target, 2)).Value = Target
' Inform user.
MsgBox "Data stacked.", vbInformation, "Success"
Exit Sub
' Subroutines
writeIdentifiers:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To IdentCols
Target(m, k) = Source(i, k)
Next k
m = m + 1
Next j
Next i
Return
writeGroups:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To GroupCols
Target(m, k + IdentCols) = _
Source(i, k + IdentCols + (j - 1) * GroupCols)
Next k
m = m + 1
Next j
Next i
Return
' Error Handler
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
End Sub
let
Source=Excel.CurrentWorkbook(){[Name=“Table1”]}[Content],
#“unpivottothercolumns”=表.UnpivotOtherColumns(源,{“名称”,“ID”},“属性”,“值”),
#“添加的索引”=表的AddIndexColumn(#“取消插入其他列”,“索引”,0,1),
#“插入的整数除法”=Table.AddColumn(#“添加的索引”、“整数除法”、每个数字.IntegerDivide([Index],3)、Int64.Type),
#“删除的列”=Table.RemoveColumns(#“插入的整数除法”、{“属性”、“索引”}),
#“分组行”=Table.Group(#“已删除列”、{“整型分割”}、{{“分组”,每个#,键入Table[Name=text,ID=number,Value=text,#“整型分割”=number]}),
#“添加的自定义”=Table.AddColumn(#“分组行”、“名称”,每个列表)。首先(Table.Column([分组],“名称”)),
#“Added Custom1”=Table.AddColumn(#“Added Custom”,“ID”,每个列表。首先(Table.Column([分组],“ID”)),
#“添加的Custom2”=Table.AddColumn(#“添加的Custom1”、“Custom”、每个Table.Column([分组]、“值”)),
#“提取的值”=Table.TransformColumns(#“Added Custom2”,{“Custom”,每个Text.Combine(List.Transform(#,Text.From),“;”),键入Text}),
#“按分隔符拆分列”=表.SplitColumn(#“提取值”、“自定义”、拆分器.SplitTextByDelimiter(“;”,QuoteStyle.Csv)、{“自定义.1”、“自定义.2”、“自定义.3”}),
#“更改的类型”=表.TransformColumnTypes(#“按分隔符拆分列”、{{“Custom.1”、类型text}、{“Custom.2”、类型text}、{“Custom.3”、类型text}),
#“Removed Columns1”=Table.RemoveColumns(#“Changed Type”、{“Integer Division”、“Grouped”}),
//重命名最后一列
origColNames=List.Buffer(List.Range(Table.ColumnNames(#“Removed Columns1”),2)),
newNameNum=List.Generate(()=>1,每个p>您也可以使用Excel 2010中提供的Power Query执行此操作+
在下面的代码中,我使用了您提供的示例。
您需要进行一些更改以使其适应您的实际数据
例如:
- 在代码中,我选择了前两列,取消了其他列;在实际数据中,您必须选择前三列
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Name", "ID"}, "Attribute", "Value"),
#"Added Index" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 0, 1),
#"Inserted Integer-Division" = Table.AddColumn(#"Added Index", "Integer-Division", each Number.IntegerDivide([Index], 3), Int64.Type),
#"Removed Columns" = Table.RemoveColumns(#"Inserted Integer-Division",{"Attribute", "Index"}),
#"Grouped Rows" = Table.Group(#"Removed Columns", {"Integer-Division"}, {{"Grouped", each _, type table [Name=text, ID=number, Value=text, #"Integer-Division"=number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Name", each List.First(Table.Column([Grouped],"Name"))),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "ID", each List.First(Table.Column([Grouped],"ID"))),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Custom", each Table.Column([Grouped],"Value")),
#"Extracted Values" = Table.TransformColumns(#"Added Custom2", {"Custom", each Text.Combine(List.Transform(_, Text.From), ";"), type text}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Extracted Values", "Custom", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Custom.1", "Custom.2", "Custom.3"}),
#"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Custom.1", type text}, {"Custom.2", type text}, {"Custom.3", type text}}),
#"Removed Columns1" = Table.RemoveColumns(#"Changed Type",{"Integer-Division", "Grouped"}),
//Rename last columns
origColNames =List.Buffer(List.Range(Table.ColumnNames(#"Removed Columns1"),2)),
newNameNum = List.Generate(() => 1 , each _ <=List.Count(origColNames), each _ + 1),
//There has to be a better way to convert the numbers to strings
#"Converted to Table" = Table.FromList(newNameNum, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Changed Type1" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type text}}),
newNames = Table.Column(#"Changed Type1","Column1"),
renameCols = Table.RenameColumns(#"Removed Columns1",List.Zip({origColNames,newNames}))
in
renameCols
Sub stackData()
' Error Handler
Const Proc As String = "stackData"
On Error GoTo cleanError
' Source
Const srcName As String = "Sheet1" ' Worksheet Name
Const srcFirst As String = "A2" ' First Cell Address
Const LRCol As Long = 1 ' Last Row Column Number
Const IdentCols As Long = 3 ' Number of Identifier Columns
Const GroupCols As Long = 8 ' Number of Group Columns
Const GroupsCount As Long = 20 ' Number of Groups
' Target
Const tgtName As String = "Sheet2" ' Worksheet Name
Const tgtFirst As String = "A2" ' First Cell Address
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values of Source Range to Source Array.
Dim ws As Worksheet: Set ws = wb.Worksheets(srcName)
Dim rng As Range
Set rng = ws.Columns(LRCol).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.row < ws.Range(srcFirst).row Then Exit Sub
Dim LastRow As Long: LastRow = rng.row
Set rng = Nothing
Dim LastCol As Long: LastCol = IdentCols + GroupCols * GroupsCount
Dim Source As Variant
Source = ws.Range(ws.Range(srcFirst), ws.Cells(LastRow, LastCol))
Set ws = Nothing
Dim ubS As Long: ubS = UBound(Source)
' Write values of Source Array to Target Array.
Dim Target As Variant
ReDim Target(1 To ubS * GroupsCount, 1 To IdentCols + GroupCols)
Dim i As Long, j As Long, k As Long, m As Long
GoSub writeIdentifiers
GoSub writeGroups
' Write values of Target Array to Target Range.
Set ws = wb.Worksheets(tgtName)
ws.Range(tgtFirst).Resize(UBound(Target), UBound(Target, 2)).Value = Target
' Inform user.
MsgBox "Data stacked.", vbInformation, "Success"
Exit Sub
' Subroutines
writeIdentifiers:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To IdentCols
Target(m, k) = Source(i, k)
Next k
m = m + 1
Next j
Next i
Return
writeGroups:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To GroupCols
Target(m, k + IdentCols) = _
Source(i, k + IdentCols + (j - 1) * GroupCols)
Next k
m = m + 1
Next j
Next i
Return
' Error Handler
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
End Sub
对于整数/除法列,我除以3;您可能需要除以8
在代码中,我添加了三个自定义列(每个标识符列一个,其余一个)。您需要添加四个自定义列
无论如何:
MCode
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Name", "ID"}, "Attribute", "Value"),
#"Added Index" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 0, 1),
#"Inserted Integer-Division" = Table.AddColumn(#"Added Index", "Integer-Division", each Number.IntegerDivide([Index], 3), Int64.Type),
#"Removed Columns" = Table.RemoveColumns(#"Inserted Integer-Division",{"Attribute", "Index"}),
#"Grouped Rows" = Table.Group(#"Removed Columns", {"Integer-Division"}, {{"Grouped", each _, type table [Name=text, ID=number, Value=text, #"Integer-Division"=number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Name", each List.First(Table.Column([Grouped],"Name"))),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "ID", each List.First(Table.Column([Grouped],"ID"))),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Custom", each Table.Column([Grouped],"Value")),
#"Extracted Values" = Table.TransformColumns(#"Added Custom2", {"Custom", each Text.Combine(List.Transform(_, Text.From), ";"), type text}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Extracted Values", "Custom", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Custom.1", "Custom.2", "Custom.3"}),
#"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Custom.1", type text}, {"Custom.2", type text}, {"Custom.3", type text}}),
#"Removed Columns1" = Table.RemoveColumns(#"Changed Type",{"Integer-Division", "Grouped"}),
//Rename last columns
origColNames =List.Buffer(List.Range(Table.ColumnNames(#"Removed Columns1"),2)),
newNameNum = List.Generate(() => 1 , each _ <=List.Count(origColNames), each _ + 1),
//There has to be a better way to convert the numbers to strings
#"Converted to Table" = Table.FromList(newNameNum, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Changed Type1" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type text}}),
newNames = Table.Column(#"Changed Type1","Column1"),
renameCols = Table.RenameColumns(#"Removed Columns1",List.Zip({origColNames,newNames}))
in
renameCols
Sub stackData()
' Error Handler
Const Proc As String = "stackData"
On Error GoTo cleanError
' Source
Const srcName As String = "Sheet1" ' Worksheet Name
Const srcFirst As String = "A2" ' First Cell Address
Const LRCol As Long = 1 ' Last Row Column Number
Const IdentCols As Long = 3 ' Number of Identifier Columns
Const GroupCols As Long = 8 ' Number of Group Columns
Const GroupsCount As Long = 20 ' Number of Groups
' Target
Const tgtName As String = "Sheet2" ' Worksheet Name
Const tgtFirst As String = "A2" ' First Cell Address
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values of Source Range to Source Array.
Dim ws As Worksheet: Set ws = wb.Worksheets(srcName)
Dim rng As Range
Set rng = ws.Columns(LRCol).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.row < ws.Range(srcFirst).row Then Exit Sub
Dim LastRow As Long: LastRow = rng.row
Set rng = Nothing
Dim LastCol As Long: LastCol = IdentCols + GroupCols * GroupsCount
Dim Source As Variant
Source = ws.Range(ws.Range(srcFirst), ws.Cells(LastRow, LastCol))
Set ws = Nothing
Dim ubS As Long: ubS = UBound(Source)
' Write values of Source Array to Target Array.
Dim Target As Variant
ReDim Target(1 To ubS * GroupsCount, 1 To IdentCols + GroupCols)
Dim i As Long, j As Long, k As Long, m As Long
GoSub writeIdentifiers
GoSub writeGroups
' Write values of Target Array to Target Range.
Set ws = wb.Worksheets(tgtName)
ws.Range(tgtFirst).Resize(UBound(Target), UBound(Target, 2)).Value = Target
' Inform user.
MsgBox "Data stacked.", vbInformation, "Success"
Exit Sub
' Subroutines
writeIdentifiers:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To IdentCols
Target(m, k) = Source(i, k)
Next k
m = m + 1
Next j
Next i
Return
writeGroups:
m = 1
For i = 1 To ubS
For j = 1 To GroupsCount
For k = 1 To GroupCols
Target(m, k + IdentCols) = _
Source(i, k + IdentCols + (j - 1) * GroupCols)
Next k
m = m + 1
Next j
Next i
Return
' Error Handler
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
End Sub
let
Source=Excel.CurrentWorkbook(){[Name=“Table1”]}[Content],
#“unpivottothercolumns”=表.UnpivotOtherColumns(源,{“名称”,“ID”},“属性”,“值”),
#“添加的索引”=表的AddIndexColumn(#“取消插入其他列”,“索引”,0,1),
#“插入的整数除法”=Table.AddColumn(#“添加的索引”、“整数除法”、每个数字.IntegerDivide([Index],3)、Int64.Type),
#“删除的列”=Table.RemoveColumns(#“插入的整数除法”、{“属性”、“索引”}),
#“分组行”=Table.Group(#“已删除列”,{“整型除法”},{{“分组”,每个#,键入Table[Name=text,ID=number,Value=text,#“整型除法”