Excel VBA脚本,用于基于两列连接单元格值

Excel VBA脚本,用于基于两列连接单元格值,excel,vba,Excel,Vba,我是VBA新手,刚刚开始在excel中实现自动化。我需要基于两列连接单元格值。比如说 在上面的excel中,如果Doc2存在三次,但其级别为3、4和3(行号分别为3、4和6),则在A列中。我想将id的值连接到一个列中,如下所示 基于级别和文档名称,如果两者相同,则连接id,否则不连接id Sub ConcatenateCellsIfSameValueExists() DestRowRef = 2 CheckedCell = Cells(2, "A").Value For

我是VBA新手,刚刚开始在excel中实现自动化。我需要基于两列连接单元格值。比如说

在上面的excel中,如果Doc2存在三次,但其级别为3、4和3(行号分别为3、4和6),则在A列中。我想将id的值连接到一个列中,如下所示

基于级别和文档名称,如果两者相同,则连接id,否则不连接id

Sub ConcatenateCellsIfSameValueExists()
DestRowRef = 2
CheckedCell = Cells(2, "A").Value
For i = 2 To Range("A" & Rows.Count).End(xlUp).Row + 1
    If Cells(i, "A").Value <> CheckedCell Then
        tempConValues = tempConValues
        Cells(DestRowRef, "C").Value = tempConValues
        tempConValues = ""
        DestRowRef = DestRowRef + 1
    End If
    tempConValues = tempConValues & " " & Cells(i, "B").Value
    CheckedCell = Cells(i, "A").Value
Next
End Sub
子级联CellSifsSameValueExists()
DestRowRef=2
CheckedCell=单元格(2,“A”)。值
对于i=2到范围(“A”&行数)。结束(xlUp)。行数+1
如果单元格(i,“A”)。值选中单元格,则
tempConValues=tempConValues
单元格(DestRowRef,“C”)。值=临时值
tempConValues=“”
DestRowRef=DestRowRef+1
如果结束
tempConValues=tempConValues&&Cells(i,“B”)。值
CheckedCell=单元格(i,“A”)。值
下一个
端接头

我尝试了上面的代码,它只基于单个单元格进行连接,而且,连接后的重复文档名不会被删除。有人能帮忙吗?

在VBA中,我会使用字典来组织数据。 对于键,连接要分组的内容(DocumentName和Level)以及连接的ID的内容

'Set Reference to Microsoft Scripting Runtime
Option Explicit
Sub jugate()
'Declare variables
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
    Dim vSrc As Variant, vRes As Variant
    Dim D As Dictionary
    Dim I As Long, V As Variant
    Dim sKey As String
    
'set Source and Result worksheets and ranges
Set wsSrc = ThisWorkbook.Worksheets("sheet4") 'edit to real worksheet
Set wsRes = ThisWorkbook.Worksheets("sheet4") 'could put this on different sheet
    Set rRes = wsRes.Cells(1, 6)
    
'read table into array for fastest processing
With wsSrc
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=3)
End With

'read into dictionary, combining like doc/level
Set D = New Dictionary
    D.CompareMode = TextCompare
    
For I = 2 To UBound(vSrc) 'skip header row
    sKey = vSrc(I, 1) & "|" & vSrc(I, 3)
    If Not D.Exists(sKey) Then
        D.Add Key:=sKey, Item:=vSrc(I, 2)
    Else
        D(sKey) = D(sKey) & vbLf & vSrc(I, 2)
    End If
Next I

'create results array
ReDim vRes(0 To D.Count, 1 To 3)

'header row
For I = 1 To 3
    vRes(0, I) = vSrc(1, I)
Next I

'populate data
I = 0
For Each V In D.Keys
    I = I + 1
    vRes(I, 1) = Split(V, "|")(0) 'doc name
    vRes(I, 2) = D(V) 'concatenated ID
    vRes(I, 3) = Split(V, "|")(1) 'level
Next V

'write results to worksheet
Set rRes = rRes.Resize(rowsize:=UBound(vRes, 1) + 1, columnsize:=UBound(vRes, 2))
With rRes
    .EntireColumn.Clear
    .Value = vRes

'Next lines are just for formatting
'not really necessary and not internationally aware
    .Style = "output"
    .EntireColumn.AutoFit
    .VerticalAlignment = xlCenter
End With

End Sub

您还可以使用Windows Excel 2010+和Office 365 Excel中提供的
电源查询
,获得所需的输出

  • 在原始表格中选择一些单元格
  • Data=>Get&Transform=>fromtable/Range
  • 当PQ UI打开时,导航到
    Home=>Advanced Editor
  • 记下代码第2行中的表名
  • 将现有代码替换为下面的M代码
  • 将粘贴代码第2行中的表名更改为“真实”表名
  • 检查所有注释,以及
    应用步骤
    窗口,以便更好地理解算法和步骤
  • 关闭/加载后,设置结果表格的换行和定心格式。
    • 此格式应在后续刷新过程中保持不变
M代码

let

//Change table name in next line to your actual table name
    Source = Excel.CurrentWorkbook(){[Name="Table11"]}[Content],

//set data types
    #"Changed Type" = Table.TransformColumnTypes(Source,{
        {"DocumentName", type text}, {"ID", type text}, {"Level", Int64.Type}}),

//group by doc name and Level
//then aggregate the text strings
    #"Grouped Rows" = Table.Group(#"Changed Type", {"DocumentName", "Level"}, {
        {"ID", each List.Accumulate([ID],"",
            (state,current)=> if state = "" then current else state & "#(lf)" & current), Text.Type}
        }),

//Place columns in desired order
    #"Reordered Columns" = Table.ReorderColumns(#"Grouped Rows",{"DocumentName", "ID", "Level"})
in
    #"Reordered Columns"

在VBA中,我会使用字典来组织数据。 对于键,连接要分组的内容(DocumentName和Level)以及连接的ID的内容

'Set Reference to Microsoft Scripting Runtime
Option Explicit
Sub jugate()
'Declare variables
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
    Dim vSrc As Variant, vRes As Variant
    Dim D As Dictionary
    Dim I As Long, V As Variant
    Dim sKey As String
    
'set Source and Result worksheets and ranges
Set wsSrc = ThisWorkbook.Worksheets("sheet4") 'edit to real worksheet
Set wsRes = ThisWorkbook.Worksheets("sheet4") 'could put this on different sheet
    Set rRes = wsRes.Cells(1, 6)
    
'read table into array for fastest processing
With wsSrc
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=3)
End With

'read into dictionary, combining like doc/level
Set D = New Dictionary
    D.CompareMode = TextCompare
    
For I = 2 To UBound(vSrc) 'skip header row
    sKey = vSrc(I, 1) & "|" & vSrc(I, 3)
    If Not D.Exists(sKey) Then
        D.Add Key:=sKey, Item:=vSrc(I, 2)
    Else
        D(sKey) = D(sKey) & vbLf & vSrc(I, 2)
    End If
Next I

'create results array
ReDim vRes(0 To D.Count, 1 To 3)

'header row
For I = 1 To 3
    vRes(0, I) = vSrc(1, I)
Next I

'populate data
I = 0
For Each V In D.Keys
    I = I + 1
    vRes(I, 1) = Split(V, "|")(0) 'doc name
    vRes(I, 2) = D(V) 'concatenated ID
    vRes(I, 3) = Split(V, "|")(1) 'level
Next V

'write results to worksheet
Set rRes = rRes.Resize(rowsize:=UBound(vRes, 1) + 1, columnsize:=UBound(vRes, 2))
With rRes
    .EntireColumn.Clear
    .Value = vRes

'Next lines are just for formatting
'not really necessary and not internationally aware
    .Style = "output"
    .EntireColumn.AutoFit
    .VerticalAlignment = xlCenter
End With

End Sub

您还可以使用Windows Excel 2010+和Office 365 Excel中提供的
电源查询
,获得所需的输出

  • 在原始表格中选择一些单元格
  • Data=>Get&Transform=>fromtable/Range
  • 当PQ UI打开时,导航到
    Home=>Advanced Editor
  • 记下代码第2行中的表名
  • 将现有代码替换为下面的M代码
  • 将粘贴代码第2行中的表名更改为“真实”表名
  • 检查所有注释,以及
    应用步骤
    窗口,以便更好地理解算法和步骤
  • 关闭/加载后,设置结果表格的换行和定心格式。
    • 此格式应在后续刷新过程中保持不变
M代码

let

//Change table name in next line to your actual table name
    Source = Excel.CurrentWorkbook(){[Name="Table11"]}[Content],

//set data types
    #"Changed Type" = Table.TransformColumnTypes(Source,{
        {"DocumentName", type text}, {"ID", type text}, {"Level", Int64.Type}}),

//group by doc name and Level
//then aggregate the text strings
    #"Grouped Rows" = Table.Group(#"Changed Type", {"DocumentName", "Level"}, {
        {"ID", each List.Accumulate([ID],"",
            (state,current)=> if state = "" then current else state & "#(lf)" & current), Text.Type}
        }),

//Place columns in desired order
    #"Reordered Columns" = Table.ReorderColumns(#"Grouped Rows",{"DocumentName", "ID", "Level"})
in
    #"Reordered Columns"

谢谢你的回答,效果很好。我还有一些修改要做,但我想在提出问题之前自己尝试一下,非常感谢这个解决方案谢谢你的回答,它很有魅力。我还有一些更改要做,但我想在询问问题之前自己尝试一下,非常感谢这个解决方案