如何使用VBA循环遍历列表并转换为列?

huangapple go评论70阅读模式
英文:

How to use VBA to loop through list and turn into columns?

问题

I am trying to figure out how I can create a macro to loop through my data that is in 6 rows to a single column with no repeating headers. my data is in the form of:

我正在尝试创建一个宏来循环遍历我的数据,该数据以6行的形式存储在单列中,没有重复的标题。我的数据格式如下:

row1: aaa
row2: bbb
row3: ccc
row4: ddd
row5: eee
row6: fff
row1: 11
row2: 22
row3: 33
row4: 44
row5: 55
row6: 66

and would like to transform it into the form of:

并且希望将其转换为以下形式:

row1:   row2:    row3:     row4:     row5:     row6:
aaa     bbb      ccc       ddd       eee       fff
11      22       33        44        55        66

each entry is in this 6 row format. I have been trying to work with other similar examples without any real luck.

每个条目都是按照这个6行的格式排列的。我一直在尝试处理其他类似的示例,但没有真正的成功。

英文:

如何使用VBA循环遍历列表并转换为列?

I am trying to figure out how I can create a macro to loop through my data that is in 6 rows to a single column with no repeating headers. my data is in the form of:

row1: aaa
row2: bbb
row3: ccc
row4: ddd
row5: eee
row6: fff
row1: 11
row2: 22
row3: 33
row4: 44
row5: 55
row6: 66

and would like to transform it into the form of:

row1:   row2:    row3:     row4:     row5:     row6:
aaa     bbb      ccc       ddd       eee       fff
11      22       33        44        55        66

each entry is in this 6 row format. I have been trying to work with other similar exampled without any real luck.

I have tried some similar examples here, but been able to get it to where the information in the rows do not repeat, since they are the same for each entry in the list

答案1

得分: 3

以下是已翻译的内容:

有很多解决这个问题的方法。

其中一种方法是使用 Power Query,在 Windows Excel 2010+ 和 Excel 365(Windows 或 Mac)中可用。

要使用 Power Query:

  • 选择数据表中的某个单元格
  • 数据 => 获取和转换 => 从表/范围获取从工作表内获取
  • 当 PQ 编辑器打开时:开始 => 高级编辑器
  • 注意第 2 行中的表 名称
  • 将下面的 M 代码粘贴到所见内容的位置
  • 将第 2 行中的表名更改回最初生成的表名。
  • 阅读注释并探索 应用步骤 以理解算法

让我知道如果你需要更多帮助。

英文:

There are many ways of solving this problem.

On way is by using using Power Query, available in Windows Excel 2010+ and Excel 365 (Windows or Mac)

To use Power Query

  • Select some cell in your Data Table
  • Data => Get&Transform => from Table/Range or from within sheet
  • When the PQ Editor opens: Home => Advanced Editor
  • Make note of the Table Name in Line 2
  • Paste the M Code below in place of what you see
  • Change the Table name in line 2 back to what was generated originally.
  • Read the comments and explore the Applied Steps to understand the algorithm
let

//change next line to reflect actual table name
    Source = Excel.CurrentWorkbook(){[Name="Table5"]}[Content],

//set the data types
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}, {"Column2", type text}}),

//Group by column1 = Column headers
//Generates list of column Contents for each column
    #"Grouped Rows" = Table.Group(#"Changed Type", {"Column1"}, {
        {"cols", each [Column2], type list} }),

    #"New Table" = Table.FromColumns(
        #"Grouped Rows"[cols], #"Grouped Rows"[Column1])

in #"New Table"

如何使用VBA循环遍历列表并转换为列?

答案2

得分: 1

这是一种我测试过的方法:

    Const NUM_ROWS_PER_GROUP = 6
    Const NUM_ROWS = 12  ' 这也可以在运行时计算,而不是作为一个常量。

    Sub RowsToColumns()
         Dim iRow As Long
         Dim iRow2 As Long
         Dim iRow3 As Long
         Dim iCol As Long
         '
         ' 首先获取列标题
         '
         iRow3 = NUM_ROWS + 2
         For iRow = 1 To NUM_ROWS_PER_GROUP
              iCol = iRow
              Me.Cells(iRow3, iCol) = Me.Cells(iRow, 1)
         Next iRow
         '
         ' 现在处理数据
         '
         iRow3 = iRow3 + 1

         For iRow = 1 To NUM_ROWS Step NUM_ROWS_PER_GROUP
             For iRow2 = 1 To NUM_ROWS_PER_GROUP
                 iCol = iRow2
                 Me.Cells(iRow3, iCol) = Me.Cells(iRow + iRow2 - 1, 2)
             Next iRow2
             iRow3 = iRow3 + 1
         Next iRow
    End Sub

如何使用VBA循环遍历列表并转换为列?

英文:

There's lots of ways to do it. Here's one that I've tested:

Const NUM_ROWS_PER_GROUP = 6
Const NUM_ROWS = 12  ' This is also easy to calculate at runtime rather than a` constant.

Sub RowsToColumns()
     Dim iRow As Long
     Dim iRow2 As Long
     Dim iRow3 As Long
     Dim iCol As Long
     '
     ' Get the column headers first
     '
     iRow3 = NUM_ROWS + 2
     For iRow = 1 To NUM_ROWS_PER_GROUP
          iCol = iRow
          Me.Cells(iRow3, iCol) = Me.Cells(iRow, 1)
     Next iRow
     '
     ' Now the data
     '
     iRow3 = iRow3 + 1

     For iRow = 1 To NUM_ROWS Step NUM_ROWS_PER_GROUP
         For iRow2 = 1 To NUM_ROWS_PER_GROUP
             iCol = iRow2
             Me.Cells(iRow3, iCol) = Me.Cells(iRow + iRow2 - 1, 2)
         Next iRow2
         iRow3 = iRow3 + 1
     Next iRow
End Sub

如何使用VBA循环遍历列表并转换为列?

答案3

得分: 1

以下是您提供的代码的中文翻译:

数据如下所示:<br>
[![在此输入图像描述][1]][1]

期望结果从单元格D1开始:<br>
[![在此输入图像描述][2]][2]

Sub test()
Dim r As Integer, rslt As Range, oData As Range, i As Integer

r = 6
Set rslt = Range("D1") '如果需要更改,请更改
Set oData = Range("B2").Resize(r, 1) '如果需要更改,请更改
rslt.Resize(1, r).Value = Application.Transpose(oData.Offset(0, -1).Value)

For i = 1 To Application.CountIf(Columns(1), oData.Offset(0, -1)(1, 1).Value)
    Set rslt = rslt.Offset(1, 0)
    rslt.Resize(1, r).Value = Application.Transpose(oData.Value)
    Set oData = oData.Offset(r, 0)
Next

End Sub

r变量用于“数据列B中的多少行数据”,在这种情况下为6<br>
rslt变量是结果单元格。<br>
oData变量是列B中前r行数据。<br>
它根据oData.offset(0,-1)创建结果单元格中的“标题”<br>

然后,它循环的次数与存在于第一列中的A2值的计数有关,并通过转置将oData值放入rslt中。<br>

请注意,如果例如在单元格A2中的值为“row 1”,但单元格A8中的值为“row1:”,则代码将失败,因为循环取决于列A中存在的A2值的数量。<br>

如果例如:范围A2:A7的值从“row 1”到“row 6”,但A8:A12中仅存在“row 1”到“row 5” ---》这将失败,因为代码假定数据将始终有r行(在此情况下为6)。

[1]: https://i.stack.imgur.com/SFXYo.png
[2]: https://i.stack.imgur.com/qxQVW.png

只翻译代码部分,不包括注释。

英文:

Data is something like this :<br>
如何使用VBA循环遍历列表并转换为列?

Expected result starting from cell D1:<br>
如何使用VBA循环遍历列表并转换为列?

Sub test()
Dim r As Integer, rslt As Range, oData As Range, i As Integer

r = 6
Set rslt = Range(&quot;D1&quot;) &#39;change if needed
Set oData = Range(&quot;B2&quot;).Resize(r, 1) &#39;change if needed
rslt.Resize(1, r).Value = Application.Transpose(oData.Offset(0, -1).Value)

For i = 1 To Application.CountIf(Columns(1), oData.Offset(0, -1)(1, 1).Value)
    Set rslt = rslt.Offset(1, 0)
    rslt.Resize(1, r).Value = Application.Transpose(oData.Value)
    Set oData = oData.Offset(r, 0)
Next

End Sub

r variable is for "how many rows of data" in column B to be tranposed, 6 in this case<br>
rslt variable is the result cell.<br>
oData variable is the first r rows of data in column B.<br>
It create the "header" in the result cell based on the oData.offset(0,-1) <br>

Then it loop as much as the count of "row 1" which reside in column 1, and put the oData value to rslt via transpose.

Please note, the code will fail if for example in cell A2 value is "row 1", but cell A8 value is "row1:", because the loop depends on how many A2 value exists in column A.

It will also fail if for example : range A2:A7 value is from "row 1" to "row 6", but there is only "row 1" to "row 5" in A8:A12 ---> this will fail because the code assumed the data will always has r rows (6 in this case).

答案4

得分: 1

以下是代码的中文翻译部分:

在第2行和B列中的示例列表,从D2开始转置

子 TransposeValues()
    Dim lastRow As Long,j As Long
    Dim dict As Object,key As Variant
    Dim rng As Range,nxt As Long,foundcell As Range
    Set dict = CreateObject(“Scripting.Dictionary”)
    Dim firstAddress

    nxt = 3
    lastRow = ActiveSheet.Cells(Rows.Count,1)。End(xlUp)。Row
    Set rng = ActiveSheet.Range(“A2:A”&lastRow)

    '循环遍历A列并将唯一值添加到字典中
    For i = 2 To lastRow
        If Not dict.Exists(ActiveSheet.Cells(i,1)。Value) Then
            dict.Add Cells(i,1)。Value,1
        End If
    Next i

    '循环遍历字典键并查找B列中对应的值
    For Each key In dict.Keys
        nxt = nxt + 1
        ActiveSheet.Cells(2,nxt)。Value = key
        j = 2
        Set foundcell = rng.Find(What:=key,LookIn:=xlValues)
        If Not foundcell Is Nothing Then
            firstAddress = foundcell.Address
            Do
                ActiveSheet.Cells(j + 1,nxt)。Value = foundcell.Offset(0,1)。Value
                j = j + 1
                Set foundcell = rng.FindNext(foundcell)
            Loop While Not foundcell Is Nothing And foundcell.Address <> firstAddress
        End If
    Next key

End Sub

这是您要求的代码的翻译。如果您需要任何进一步的帮助,请随时告诉我。

英文:

example your list in column A and B starting at row 2, transpose starting at D2

Sub TransposeValues()
    Dim lastRow As Long, j As Long
    Dim dict As Object, key As Variant
    Dim rng As Range, nxt As Long, foundcell As Range
    Set dict = CreateObject(&quot;Scripting.Dictionary&quot;)
    Dim firstAddress
    
    nxt = 3
    lastRow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
    Set rng = ActiveSheet.Range(&quot;A2:A&quot; &amp; lastRow)
    
    &#39;Loop through column A and add unique values to dictionary
    For i = 2 To lastRow
        If Not dict.Exists(ActiveSheet.Cells(i, 1).Value) Then
            dict.Add Cells(i, 1).Value, 1
        End If
    Next i
    
    &#39;Loop through dictionary keys and find corresponding values in column B
    For Each key In dict.Keys
        nxt = nxt + 1
        ActiveSheet.Cells(2, nxt).Value = key
        j = 2
        Set foundcell = rng.Find(What:=key, LookIn:=xlValues)
        If Not foundcell Is Nothing Then
            firstAddress = foundcell.Address
            Do
                ActiveSheet.Cells(j + 1, nxt).Value = foundcell.Offset(0, 1).Value
                j = j + 1
                Set foundcell = rng.FindNext(foundcell)
            Loop While Not foundcell Is Nothing And foundcell.Address &lt;&gt; firstAddress
        End If
    Next key
    
End Sub

huangapple
  • 本文由 发表于 2023年4月17日 07:36:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76030835.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定