简体   繁体   English

excel vba 中多列堆叠为一列

[英]Stack Multiple columns into one columns in excel vba

I have multiple columns (15 to 16) of data ( see Image ).我有多列(15 到 16)数据(参见图片)。

It has One number that is split into 3 columns Eg.它有一个数字,分为 3 列,例如。 147 is split into three columns 1, 4, 7 and 268 is split into 2,6,8. 147 分为三列 1、4、7,268 分为 2、6、8。 Now i want to stack the data in a way as presented in this image现在我想以此图像所示的方式堆叠数据

For this I tried to concatenate the three columns to make a single digit such as 1,4,7 are combined to form 147 and 2,6,8 are combined to form 268. The code i have written has given output 148 and 268 but it has two empty columns in between them shown as this .为此,我尝试将三列连接成一个数字,例如 1、4、7 组合成 147,2、6、8 组合成 268。我写的代码给出了 output 148 和 268 但是它们之间有两个空列,如图所示

I am not able to stack these columns to get desired output. Please suggest any method to stack from input to desired output directly Or any amendment in my current code so that i get the concatenated data in sequential columns.我无法堆叠这些列以获得所需的 output。请建议任何方法直接从输入堆叠到所需的 output 或者我当前代码中的任何修改,以便我在顺序列中获得连接的数据。

Note:- The number of rows and columns are variable not static.注意:- 行数和列数是可变的,不是 static。

Sub JoinAndCut()
Dim n As Long
Dim p, col As Long
Dim lastrow As Long
For p = 1 To 25 Step 3

lastrow = ThisWorkbook.Worksheets(2).Cells(Rows.count, p).End(xlUp).Row   '<== To Count number of rows in each column

For n = 2 To lastrow

Cells(n, p).Offset(, 25).Value = Cells(n, p).Value & Cells(n, p + 1).Value & Cells(n, p + 2).Value ' <=== Offset by 25 values so as they dont overlap the input

Next n
Next p

End Sub


Sub JoinAndCut()
Dim n As Long
Dim p, col As Long
Dim lastrow As Long
For p = 1 To 25 Step 3

lastrow = ThisWorkbook.Worksheets(2).Cells(Rows.count, p).End(xlUp).Row   '<== To Count number of rows in each column

For n = 2 To lastrow

Cells(n, p).Offset(, 25).Value = Cells(n, p).Value & Cells(n, p + 1).Value & Cells(n, p + 2).Value ' <=== Offset by 25 values so as they dont overlap the input

Next n
Next p

End Sub

You could try this:你可以试试这个:

Sub JoinAndCut()
    Dim n As Long
    Dim p, col As Long
    Dim lastrow As Long, lastrowstack As Long
    For p = 1 To 25 Step 3

        lastrow = ThisWorkbook.Worksheets(2).Cells(Rows.Count, p).End(xlUp).Row   '<== To get row number in each column
        lastrowstack = ThisWorkbook.Worksheets(2).Cells(Rows.Count, 26).End(xlUp).Row   '<== To get row number in in the stacked column

        For n = 2 To lastrow
            
            Cells(n + lastrowstack - 1, 26).Value = Cells(n, p).Value & Cells(n, p + 1).Value & Cells(n, p + 2).Value ' <=== Starting in column 26 so as they dont overlap the input

        Next n
    Next p

End Sub

Let's say you had something like this:假设你有这样的事情:

在此处输入图像描述 Data in html format html格式的数据

You would then have them combined and stacked in column Z (aka. column 26) and the first 36 rows would look like this .然后,您可以将它们合并并堆叠在 Z 列(又名第 26 列)中,前 36 行看起来像这样

If I understand what you want correctly, which is a three column table with a single value in each column, the following should help.如果我理解你想要的是正确的,这是一个三列表,每列有一个值,那么以下内容应该有所帮助。

I chose to use Power Query (available in Excel 2010+)我选择使用Power Query (Excel 2010+可用)

Algorithm:算法:

  • Unpivot all the columns:取消透视所有列:
    • Results in 2 columns consisting of the column header and value 2 列中的结果由列 header 和值组成
  • Add an index column and then add an Integer/Divide column where we divide the Index column by 3.添加一个索引列,然后添加一个整数/除法列,我们将索引列除以 3。
    • This returns a column of 0,0,0,1,1,1,2,2,2, ...这将返回一列0,0,0,1,1,1,2,2,2, ...
  • Group by the Integer/Divide columnInteger/Divide列分组
  • Extract the values from the resultant table into a delimiter separated list.将结果表中的值提取到分隔符分隔的列表中。
  • Split the list into columns.将列表拆分为列。
  • Delete the unneeded columns and we're done.删除不需要的列,我们就完成了。
  • If you add or remove columns/rows and Refresh , the output table will reflect that.如果您添加或删除列/行和Refresh , output 表将反映出来。

I suggest you我建议你

  • Select a cell in your data.table Select data.table 中的一个单元格
  • Enter Power Query输入电源查询
    • In Excel 2016+, Data-->Get&Transform-->From Table/Range Excel 2016+, Data-->Get&Transform-->From Table/Range
      • In other versions, you install a free add-in from MS and follow those directions在其他版本中,您可以从 MS 安装一个免费的插件并按照这些说明进行操作
  • In the PQ UI, go to Home/Advanced Editor在 PQ UI 中,go 到Home/Advanced Editor
    • Note the Table name in Line 2注意第 2 行中的Table
    • Delete the contents of the editor, and paste the M Code below into its place删除编辑器的内容,将下面的M代码粘贴到它的位置
      • Change the Table name in line 2 to match your real table name.更改第 2 行中的表名以匹配您的真实表名。
    • Examine the Applied Steps window to see better what is done at each step.检查应用步骤 window 以更好地了解每个步骤的执行情况。
      • double click the steps with a settings gear icon to show the options双击带有settings gear icon的步骤以显示选项

M Code M代码

let
    Source = Excel.CurrentWorkbook(){[Name="Table5"]}[Content],
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {}, "Attribute", "Value"),
    #"Added Index1" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 0, 1),
    #"Inserted Integer-Division" = Table.AddColumn(#"Added Index1", "Integer-Division", each Number.IntegerDivide([Index], 3), Int64.Type),
    #"Removed Columns1" = Table.RemoveColumns(#"Inserted Integer-Division",{"Index", "Attribute"}),
    #"Grouped Rows" = Table.Group(#"Removed Columns1", {"Integer-Division"}, {{"Grouped", each _, type table [Value=number, #"Integer-Division"=number]}}),
    #"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"Integer-Division"}),
    #"Added Custom" = Table.AddColumn(#"Removed Columns", "Column", each Table.Column([Grouped],"Value")),
    #"Extracted Values" = Table.TransformColumns(#"Added Custom", {"Column", each Text.Combine(List.Transform(_, Text.From), ";"), type text}),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Extracted Values", "Column", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Column.1", "Column.2", "Column.3"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Column.1", Int64.Type}, {"Column.2", Int64.Type}, {"Column.3", Int64.Type}}),
    #"Removed Columns2" = Table.RemoveColumns(#"Changed Type",{"Grouped"})
in
    #"Removed Columns2"

Original Data原始数据

在此处输入图像描述

Results结果

在此处输入图像描述

If doing it in VBA is an absolute requirement, you can try this code: but read through it so you can change the range and worksheet references appropriately:如果在 VBA 中执行此操作是绝对必要的,您可以尝试此代码:但通读它以便您可以适当地更改范围和工作表引用:

Option Explicit
Sub JoinAndCut()
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range, col As Collection, vSrc, vRes
    Const firstRow As Long = 31
    Const firstCol As Long = 1
    Dim I As Long, J As Long, K As Long, arr(0 To 2), v
    
'read the data into VBA array
Set wsSrc = ThisWorkbook.Worksheets("sheet9")
With wsSrc
    vSrc = .Cells(firstRow, firstCol).CurrentRegion
End With

'collect output array
Set col = New Collection
For I = 2 To UBound(vSrc, 1) 'skip the header row
    For J = 1 To UBound(vSrc, 2) Step 3
        For K = 0 To 2
            arr(K) = vSrc(I, J + K)
        Next K
        If arr(0) <> "" Then col.Add arr 'skip the blanks
    Next J
Next I

'Create results array
ReDim vRes(0 To col.Count, 1 To 3)

'Headers
vRes(0, 1) = "Column.1"
vRes(0, 2) = "Column.2"
vRes(0, 3) = "Column.3"

'Populate
I = 0
For Each v In col
    I = I + 1
    For J = 1 To 3
        vRes(I, J) = v(J - 1)
    Next J
Next v

'Set output range
Set wsRes = wsSrc
    Set rRes = wsRes.Cells(50, 1)
    Set rRes = rRes.Resize(UBound(vRes, 1) + 1, UBound(vRes, 2))
    
    With rRes
        .ClearContents
        .Value = vRes
      'could add formatting commands
    End With
End Sub

Either one of the above can be easily modified to output the results as triplets, instead of in three separate columns, should I have misunderstood you.以上任何一项都可以很容易地修改为 output 结果作为三元组,而不是在三个单独的列中,我应该误解你了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM