聚合、整理行并将行转置为列
Aggregate, Collate and Transpose rows into columns
我有以下table
Id Letter
1001 A
1001 H
1001 H
1001 H
1001 B
1001 H
1001 H
1001 H
1001 H
1001 H
1001 H
1001 A
1001 H
1001 H
1001 H
1001 B
1001 A
1001 H
1001 H
1001 H
1001 B
1001 B
1001 H
1001 H
1001 H
1001 B
1001 H
1001 A
1001 G
1001 H
1001 H
1001 A
1001 B
1002 B
1002 H
1002 H
1002 B
1002 G
1002 H
1002 B
1002 G
1002 G
1002 H
1002 B
1002 G
1002 H
1002 H
1002 G
1002 H
1002 H
1002 H
1002 H
1002 H
1002 M
1002 N
1002 G
1002 H
1002 H
1002 M
1002 M
1002 A
1002 H
1002 H
1002 H
1002 A
1002 B
1002 B
1002 H
1002 H
1002 H
1002 B
1002 H
1002 H
1002 H
1002 A
1002 A
1002 A
1002 H
1002 H
1002 H
1002 H
1002 B
1002 H
1003 G
1003 H
1003 H
1003 N
1003 M
我正在尝试转置它,使第一列中的每个不同的 ID 和第二列中的所有字母都有一个空白 space 原始 table 中的每个空白行:
1001 AHHH BHHH HHH AHHHB AHHHB BHHHB H AGHHAB
1002 BHHB GH BGGH BGHH GHH HHHMN GHHMM AHHHAB BHHH BHHHAA AHHHHB H
1003 GHHNM
我有大约 100 个不同的 ID。我尝试使用 TRANSPOSE 和 TRIM 来处理公式。我也尝试过使用宏,VLOOKUP 似乎是最简单的方法,但找不到方法
您不能在事先不知道范围的情况下使用本机工作表函数连接一系列单元格(又名 字母)。由于您的 collection 字符串分组具有随机数量的元素,因此 VBA 循环方法似乎是解决该问题的最佳(如果不是唯一)方法。循环可以确定工作表函数根本无法执行。
点击 Alt+F11,当 Visual Basic 编辑器(又名 VBE)打开时,立即使用 pull-down 菜单插入 ► 模块 (Alt+I,M)。将以下一项或两项粘贴到标题为 Book1 - Module1 (Code).
的新窗格中
连接由 space 分隔的字符串组:
Sub concatenate_and_transpose_to_delim_string()
Dim rw As Long, lr As Long, pid As Long, str As String
Dim bPutInColumns As Boolean
With ActiveSheet
lr = .Cells(Rows.Count, 1).End(xlUp).row
.Cells(1, 4).Resize(1, 2) = Array("Id", "Letters")
pid = .Cells(2, 1).Value
For rw = 2 To lr
If IsEmpty(.Cells(rw, 1)) Then
str = str & Chr(32)
If pid <> .Cells(rw + 1, 1).Value Then
.Cells(Rows.Count, 4).End(xlUp).Offset(1, 0) = pid
.Cells(Rows.Count, 4).End(xlUp).Offset(0, 1) = str
End If
ElseIf pid <> .Cells(rw, 1).Value Then
pid = .Cells(rw, 1).Value
str = .Cells(rw, 2).Value
Else
str = str & .Cells(rw, 2).Value
End If
Next rw
.Cells(Rows.Count, 4).End(xlUp).Offset(1, 0) = pid
.Cells(Rows.Count, 4).End(xlUp).Offset(0, 1) = str
End With
End Sub
要将字符串组拆分为列:
Sub concatenate_and_transpose_into_columns()
Dim rw As Long, lr As Long, nr As Long, pid As Long, str As String
With ActiveSheet
lr = .Cells(Rows.Count, 1).End(xlUp).row
.Cells(1, 4).Resize(1, 2) = Array("Id", "Letters")
For rw = 2 To lr
If IsEmpty(.Cells(rw, 1)) Then
.Cells(nr, Columns.Count).End(xlToLeft).Offset(0, 1) = str
str = vbNullString
ElseIf pid <> .Cells(rw, 1).Value Then
pid = .Cells(rw, 1).Value
nr = .Cells(Rows.Count, 4).End(xlUp).Offset(1, 0).row
.Cells(nr, 4) = pid
str = .Cells(rw, 2).Value
Else
str = str & .Cells(rw, 2).Value
End If
Next rw
.Cells(nr, Columns.Count).End(xlToLeft).Offset(0, 1) = str
End With
End Sub
点击 Alt+Q 到 return 到您的工作表。使用 A1 中以 Id
开头的活动工作表上的示例数据,点击 Alt+F8 打开 宏对话框和运行宏。
来自concatenate_and_transpose_to_delim_string的结果:
来自 concatenate_and_transpose_into_columns 的结果:
结果将写入从 D2 开始的单元格中。如果事先没有什么重要的东西会被覆盖,那可能是最好的。
附录:
我最初误解了您的请求并将字符串组拆分为单独的列。我已经通过补充例程纠正了这一点,该例程更符合您对要求的描述,但保留了两种变体供其他人参考。
此选项包含数组。从性能的角度来看,与在工作表中逐个单元格地执行程序相比,将工作表中的数据读取到数组后,直接在 VBE 中执行程序并将结果写回工作表要快得多。
Sub transposing()
Const sDestination As String = "D2"
Dim ar1() As Variant
Dim ar2() As Variant
Dim i As Long 'counter
ar1 = ActiveSheet.Range("A2:B" & ActiveSheet.UsedRange.Rows.Count).Value
ReDim ar2(1 To 1, 1 To 2)
ar2(1, 1) = ar1(1, 1): ar2(1, 2) = ar1(1, 2)
For i = 2 To UBound(ar1, 1)
If ar1(i, 1) = ar2(UBound(ar2, 1), 1) Then
ar2(UBound(ar2, 1), 2) = ar2(UBound(ar2, 1), 2) & ar1(i, 2)
ElseIf ar1(i, 1) = vbNullString Then
ar2(UBound(ar2, 1), 2) = ar2(UBound(ar2, 1), 2) & " "
Else
ar2 = Application.Transpose(ar2)
ReDim Preserve ar2(1 To 2, 1 To UBound(ar2, 2) + 1)
ar2 = Application.Transpose(ar2)
ar2(UBound(ar2, 1), 1) = ar1(i, 1)
ar2(UBound(ar2, 1), 2) = ar2(UBound(ar2, 1), 2) & ar1(i, 2)
End If
Next
ActiveSheet.Range(sDestination).Resize(UBound(ar2, 1), UBound(ar2, 2)).Value = ar2
End Sub
结果将如下所示:
第 Const sDestination As String = "D2"
行表示输出的开头。将其更改为您想要的任何单元格。
对于这样的任务,Microsoft 在 "Get&Transform" 到 Excel 2016 中添加了。要在早期版本中使用此功能,您必须使用 Power Query 加载项。
M代码很短:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
FillIdDown = Table.FillDown(Source,{"Id"}),
ReplaceNull = Table.ReplaceValue(FillIdDown,null," ",Replacer.ReplaceValue,{"Letter"}),
Transform = Table.Group(ReplaceNull, {"Id"}, {{"Count", each Text.Combine(_[Letter])}})
in
Transform
您的数据应位于 "Table1"。
https://www.dropbox.com/s/bnvchofmpvd048v/SO_AggregateCollateAndTransposeColsIntoRows.xlsx?dl=0
我有以下table
Id Letter
1001 A
1001 H
1001 H
1001 H
1001 B
1001 H
1001 H
1001 H
1001 H
1001 H
1001 H
1001 A
1001 H
1001 H
1001 H
1001 B
1001 A
1001 H
1001 H
1001 H
1001 B
1001 B
1001 H
1001 H
1001 H
1001 B
1001 H
1001 A
1001 G
1001 H
1001 H
1001 A
1001 B
1002 B
1002 H
1002 H
1002 B
1002 G
1002 H
1002 B
1002 G
1002 G
1002 H
1002 B
1002 G
1002 H
1002 H
1002 G
1002 H
1002 H
1002 H
1002 H
1002 H
1002 M
1002 N
1002 G
1002 H
1002 H
1002 M
1002 M
1002 A
1002 H
1002 H
1002 H
1002 A
1002 B
1002 B
1002 H
1002 H
1002 H
1002 B
1002 H
1002 H
1002 H
1002 A
1002 A
1002 A
1002 H
1002 H
1002 H
1002 H
1002 B
1002 H
1003 G
1003 H
1003 H
1003 N
1003 M
我正在尝试转置它,使第一列中的每个不同的 ID 和第二列中的所有字母都有一个空白 space 原始 table 中的每个空白行:
1001 AHHH BHHH HHH AHHHB AHHHB BHHHB H AGHHAB
1002 BHHB GH BGGH BGHH GHH HHHMN GHHMM AHHHAB BHHH BHHHAA AHHHHB H
1003 GHHNM
我有大约 100 个不同的 ID。我尝试使用 TRANSPOSE 和 TRIM 来处理公式。我也尝试过使用宏,VLOOKUP 似乎是最简单的方法,但找不到方法
您不能在事先不知道范围的情况下使用本机工作表函数连接一系列单元格(又名 字母)。由于您的 collection 字符串分组具有随机数量的元素,因此 VBA 循环方法似乎是解决该问题的最佳(如果不是唯一)方法。循环可以确定工作表函数根本无法执行。
点击 Alt+F11,当 Visual Basic 编辑器(又名 VBE)打开时,立即使用 pull-down 菜单插入 ► 模块 (Alt+I,M)。将以下一项或两项粘贴到标题为 Book1 - Module1 (Code).
的新窗格中连接由 space 分隔的字符串组:
Sub concatenate_and_transpose_to_delim_string()
Dim rw As Long, lr As Long, pid As Long, str As String
Dim bPutInColumns As Boolean
With ActiveSheet
lr = .Cells(Rows.Count, 1).End(xlUp).row
.Cells(1, 4).Resize(1, 2) = Array("Id", "Letters")
pid = .Cells(2, 1).Value
For rw = 2 To lr
If IsEmpty(.Cells(rw, 1)) Then
str = str & Chr(32)
If pid <> .Cells(rw + 1, 1).Value Then
.Cells(Rows.Count, 4).End(xlUp).Offset(1, 0) = pid
.Cells(Rows.Count, 4).End(xlUp).Offset(0, 1) = str
End If
ElseIf pid <> .Cells(rw, 1).Value Then
pid = .Cells(rw, 1).Value
str = .Cells(rw, 2).Value
Else
str = str & .Cells(rw, 2).Value
End If
Next rw
.Cells(Rows.Count, 4).End(xlUp).Offset(1, 0) = pid
.Cells(Rows.Count, 4).End(xlUp).Offset(0, 1) = str
End With
End Sub
要将字符串组拆分为列:
Sub concatenate_and_transpose_into_columns()
Dim rw As Long, lr As Long, nr As Long, pid As Long, str As String
With ActiveSheet
lr = .Cells(Rows.Count, 1).End(xlUp).row
.Cells(1, 4).Resize(1, 2) = Array("Id", "Letters")
For rw = 2 To lr
If IsEmpty(.Cells(rw, 1)) Then
.Cells(nr, Columns.Count).End(xlToLeft).Offset(0, 1) = str
str = vbNullString
ElseIf pid <> .Cells(rw, 1).Value Then
pid = .Cells(rw, 1).Value
nr = .Cells(Rows.Count, 4).End(xlUp).Offset(1, 0).row
.Cells(nr, 4) = pid
str = .Cells(rw, 2).Value
Else
str = str & .Cells(rw, 2).Value
End If
Next rw
.Cells(nr, Columns.Count).End(xlToLeft).Offset(0, 1) = str
End With
End Sub
点击 Alt+Q 到 return 到您的工作表。使用 A1 中以 Id
开头的活动工作表上的示例数据,点击 Alt+F8 打开 宏对话框和运行宏。
来自concatenate_and_transpose_to_delim_string的结果:
来自 concatenate_and_transpose_into_columns 的结果:
结果将写入从 D2 开始的单元格中。如果事先没有什么重要的东西会被覆盖,那可能是最好的。
附录:
我最初误解了您的请求并将字符串组拆分为单独的列。我已经通过补充例程纠正了这一点,该例程更符合您对要求的描述,但保留了两种变体供其他人参考。
此选项包含数组。从性能的角度来看,与在工作表中逐个单元格地执行程序相比,将工作表中的数据读取到数组后,直接在 VBE 中执行程序并将结果写回工作表要快得多。
Sub transposing()
Const sDestination As String = "D2"
Dim ar1() As Variant
Dim ar2() As Variant
Dim i As Long 'counter
ar1 = ActiveSheet.Range("A2:B" & ActiveSheet.UsedRange.Rows.Count).Value
ReDim ar2(1 To 1, 1 To 2)
ar2(1, 1) = ar1(1, 1): ar2(1, 2) = ar1(1, 2)
For i = 2 To UBound(ar1, 1)
If ar1(i, 1) = ar2(UBound(ar2, 1), 1) Then
ar2(UBound(ar2, 1), 2) = ar2(UBound(ar2, 1), 2) & ar1(i, 2)
ElseIf ar1(i, 1) = vbNullString Then
ar2(UBound(ar2, 1), 2) = ar2(UBound(ar2, 1), 2) & " "
Else
ar2 = Application.Transpose(ar2)
ReDim Preserve ar2(1 To 2, 1 To UBound(ar2, 2) + 1)
ar2 = Application.Transpose(ar2)
ar2(UBound(ar2, 1), 1) = ar1(i, 1)
ar2(UBound(ar2, 1), 2) = ar2(UBound(ar2, 1), 2) & ar1(i, 2)
End If
Next
ActiveSheet.Range(sDestination).Resize(UBound(ar2, 1), UBound(ar2, 2)).Value = ar2
End Sub
结果将如下所示:
第 Const sDestination As String = "D2"
行表示输出的开头。将其更改为您想要的任何单元格。
对于这样的任务,Microsoft 在 "Get&Transform" 到 Excel 2016 中添加了。要在早期版本中使用此功能,您必须使用 Power Query 加载项。 M代码很短:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
FillIdDown = Table.FillDown(Source,{"Id"}),
ReplaceNull = Table.ReplaceValue(FillIdDown,null," ",Replacer.ReplaceValue,{"Letter"}),
Transform = Table.Group(ReplaceNull, {"Id"}, {{"Count", each Text.Combine(_[Letter])}})
in
Transform
您的数据应位于 "Table1"。 https://www.dropbox.com/s/bnvchofmpvd048v/SO_AggregateCollateAndTransposeColsIntoRows.xlsx?dl=0