Arrays 将行聚合、整理并转换为列
我有下表Arrays 将行聚合、整理并转换为列,arrays,excel,transpose,vba,Arrays,Excel,Transpose,Vba,我有下表 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
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和第二列中的所有字母在原始表中的每一空白行都有一个空格:
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。我试着用转置和修剪来做一个公式。我还尝试过使用宏,VLOOKUP似乎是最简单的方法,但无法找到如何在事先不知道范围的情况下使用本机工作表函数连接一系列单元格(也称为字母)。由于分组中的字符串集合具有随机数目的元素,因此VBA循环方法似乎是解决此问题的最佳(如果不是唯一)方法。循环可以在工作表函数无法执行的过程中进行确定 点击Alt+F11,当Visual Basic编辑器(也称为VBE)打开时,立即使用下拉菜单插入► 模块(Alt+I,M)。将以下一项或两项粘贴到名为Book1-Module1(代码)的新窗格中 连接由空格分隔的字符串组:
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
Sub-concatenate_和_-transpose_到_-delim_字符串()
尺寸rw为长,lr为长,pid为长,str为字符串
将列设置为布尔值
使用ActiveSheet
lr=.Cells(Rows.Count,1).End(xlUp).row
.单元格(1,4).调整大小(1,2)=数组(“Id”,“字母”)
pid=.Cells(2,1).Value
对于rw=2至lr
如果为空(.Cells(rw,1)),则
str=str&Chr(32)
如果pid.单元格(rw+1,1).值,则
.Cells(Rows.Count,4)。End(xlUp)。Offset(1,0)=pid
.Cells(Rows.Count,4)。End(xlUp)。Offset(0,1)=str
如果结束
ElseIf pid.Cells(rw,1)值,然后
pid=.Cells(rw,1).Value
str=.Cells(rw,2).Value
其他的
str=str和.Cells(rw,2).Value
如果结束
下一个rw
.Cells(Rows.Count,4)。End(xlUp)。Offset(1,0)=pid
.Cells(Rows.Count,4)。End(xlUp)。Offset(0,1)=str
以
端接头
将字符串组拆分为列:
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
Sub-concatenate_和_-transpose_到_列()
尺寸rw为长,lr为长,nr为长,pid为长,str为字符串
使用ActiveSheet
lr=.Cells(Rows.Count,1).End(xlUp).row
.单元格(1,4).调整大小(1,2)=数组(“Id”,“字母”)
对于rw=2至lr
如果为空(.Cells(rw,1)),则
.Cells(nr,Columns.Count).End(xlToLeft).Offset(0,1)=str
str=vbNullString
ElseIf pid.Cells(rw,1)值,然后
pid=.Cells(rw,1).Value
nr=.Cells(Rows.Count,4)。End(xlUp)。Offset(1,0)。row
.单元格(nr,4)=pid
str=.Cells(rw,2).Value
其他的
str=str和.Cells(rw,2).Value
如果结束
下一个rw
.Cells(nr,Columns.Count).End(xlToLeft).Offset(0,1)=str
以
端接头
点击Alt+Q返回工作表。使用活动工作表上的示例数据,从A1中的Id
开始,点击Alt+F8打开宏对话框,然后运行宏
连接字符串和将字符串转置到字符串的结果:
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
连接\u和将\u转置到\u列的结果:
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
结果将从D2开始写入单元格。如果事先没有什么重要的东西会被覆盖,那可能是最好的
附录:
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
我误解了您的请求,将字符串组拆分为单独的列。我已经用一个补充例程纠正了这一点,它更接近您对需求的描述,但保留了这两个变体供其他人参考。此选项包含阵列。从性能角度来看,将工作表中的数据一次读取到数组、直接在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 sdestinion As String=“D2”
表示输出的开始。将其更改为所需的任何单元格。对于此类任务,Microsoft在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
您的数据应该放在“表1”中。
将随机长度的值组串联起来几乎是不可能的,当然也是不可行的。我认为VBA是寻求解决方案的唯一现实途径。非常感谢!!两个答案都非常完美。我应该勾选两个,因为它们都很有用,并且给它们更多的分数,但不知道如何给它们打分数。谢谢:)只是为了通知您以后使用-直接在VBE中执行过程比在工作表中循环单元格快得多。用户发布了一个新问题,询问为什么宏会给出错误13。当连接的单元格长度为733个字符时,它将失败。我的理解是,如果元素的长度为255个字符,则
工作表function.Transpose
不起作用。当然,我可以通过将长度减少到255来清除错误。请注意,WorksheetFunction.Transpose
是一个缓慢的函数,ReDim Preserve
的速度越来越慢,因此我认为如果直接输出到工作表,您将获得一个不会失败的更快的例程。@ZygD-我尝试克服报告的错误,但想看看您对我发布修改您的sub。不幸的是,除了发布它之外,无法真正向您展示我的努力,因为我知道没有“沙箱”。@ZygD专家们总是说工作表。函数比相同的函数快