我对 VBA 完全陌生,正在尝试实现 Raystafarian 提供的出色解决方案如何在 Excel 中将多行的值合并为一行?(重新审视的版本)。但是,由于我真的不理解解决方案,我很难在列号等不同的情况下运行它。有人能向我解释一下变量指的是什么吗,以便我可以将它应用于不同的示例?我的问题完全一样 - 单个数据点有多行,并希望获得一个表,其中 name/data1/data2/data3 都在同一行中,以进行 Spotfire 数据分析。
答案1
这是一个相当粗糙的宏,但是
Option Explicit
Sub CombineRowsRevisited()
'c is a CELL or a range
Dim c As Range
'i is a number
Dim i As Integer
'for each CELL in this range
For Each c In Range("A2", Cells(Cells.SpecialCells(xlCellTypeLastCell).Row, 1))
'if the CELL is the same as the cell to the right AND
'if the cell 4 to the right is the same as the cell below that one
If c = c.Offset(1) And c.Offset(, 4) = c.Offset(1, 4) Then
'then make the cell 3 to the right the same as the cell below it
c.Offset(, 3) = c.Offset(1, 3)
'and delete the row below the CELL
c.Offset(1).EntireRow.Delete
End If
Next
End Sub
鉴于上述情况,这将更容易理解
Sub CombineRowsRevisitedAgain()
Dim myCell As Range
Dim lastRow As Long
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
For Each myCell In Range(Cells("A2"), Cells(lastRow, 1))
If (myCell = myCell.Offset(1)) And (myCell.Offset(0, 4) = myCell.Offset(1, 4)) Then
myCell.Offset(0, 3) = myCell.Offset(1, 3)
myCell.Offset(1).EntireRow.Delete
End If
Next
End Sub
但是,根据问题的不同,最好step -1
使用行号,这样就不会跳过任何内容。
Sub CombineRowsRevisitedStep()
Dim currentRow As Long
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For currentRow = lastRow To 2 Step -1
If Cells(currentRow, 1) = Cells(currentRow - 1, 1) And _
Cells(currentRow, 4) = Cells(currentRow - 1, 4) Then
Cells(currentRow - 1, 3) = Cells(currentRow, 3)
Rows(currentRow).EntireRow.Delete
End If
Next
End Sub
答案2
我建议采用 VBA 等不同的方法来处理这个转换步骤。
您可以尝试免费的 Microsoft 插件Power Query(来自 Excel 2010)。加载和转换数据非常直观。基本上,您将数据导入 Power Query,然后取消透视并重新透视它们。
首先在 Excel 中将您的数据定义为表格。
| Customer | Value A | Value B | Year |
|------------|---------|---------|------|
| Customer 1 | 134 | | 2009 |
| Customer 1 | | 3 | 2009 |
| Customer 1 | 175 | | 2010 |
| Customer 1 | | 5 | 2010 |
| Customer 1 | 7784 | | 2011 |
| Customer 2 | 515 | | 2009 |
| Customer 2 | 1943 | | 2010 |
| Customer 2 | | 1 | 2010 |
| Customer 2 | 9745 | | 2011 |
| Customer 2 | | 154 | 2011 |
将光标放在表格中的某处
转到 Power Query 选项卡并单击From Table
。它将打开 Power Query 编辑器。
选择值 A/B 列(使用 Ctrl)。右键单击您选择的列标题之一以调出选项菜单。单击“取消透视列”菜单。
下一步:选择Attribute
和Value
列,然后Pivot Column
从Transform
菜单中选择。Value
从下拉列表中选择要透视的列,然后单击“确定”。
输出将如下所示:
| Customer | Year | Value A | Value B |
|------------|------|---------|---------|
| Customer 1 | 2009 | 134 | 3 |
| Customer 1 | 2010 | 175 | 5 |
| Customer 1 | 2011 | 7784 | |
| Customer 2 | 2009 | 515 | |
| Customer 2 | 2010 | 1943 | 1 |
| Customer 2 | 2011 | 9745 | 154 |
这三个步骤的 Power Query 脚本是
let
Source= Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Columns" = Table.UnpivotOtherColumns(Source, {"Customer", "Year"}, "Attribut", "Value"),
#"Pivot Column" = Table.Pivot(#"Unpivoted Columns", List.Distinct(#"Unpivoted Columns"[Attribut]), "Attribut", "Value", List.Sum)
in
#"Pivot Column"
您还可以找到有关逆透视的分步教程这里
答案3
以下是对剧本中最重要的几行的解释:
For each c In Range("A2", Cells(Cells.SpecialCells(xlCellTypeLastCell).Row, 1))
遍历从 A 列A2
到最后使用的单元格的所有列,并将值分配给变量c
。
就像c
单元格一样,它具有行和列值,因此它充当我们可以使用它进行移动的参考点Offset
。
If c = c.Offset(1) And c.Offset(,4) = c.Offset(1,4) Then
将单元格c
与下一行的单元格进行比较c.Offset(1)
和位于同一行但第 4 列的单元格c.Offset(,4)
与位于第 4 列下一行的单元格c.Offset(1,4)
。
c.Offset(,3) = c.Offset(1,3)
c.Offset(,3)
将下一行第 3 列的单元格的值分配给该行第 3 列的单元格c.Offset(1,3)
。
c.Offset(1).EntireRow.Delete
删除下一行