Сценарий VBA для объединения значения ячейки на основе двух столбцов

#excel #vba

Вопрос:

Я очень новичок в VBA и только сейчас начал автоматизировать работу в excel. У меня есть требование объединить значение ячейки на основе двух столбцов. Например

введите описание изображения здесь

В приведенном выше excel в столбце A, если Doc2 существует трижды, но имеет уровни 3,4 и 3 (в строке с номером 3,4 и 6 соответственно). Я хочу объединить значения идентификатора в один столбец, как показано ниже

введите описание изображения здесь

На основе уровня и имени документа, если оба они одинаковы, то объединять идентификатор иначе не нужно.

 Sub ConcatenateCellsIfSameValueExists()
DestRowRef = 2
CheckedCell = Cells(2, "A").Value
For i = 2 To Range("A" amp; 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 amp; " " amp; Cells(i, "B").Value
    CheckedCell = Cells(i, "A").Value
Next
End Sub
 

Я попробовал приведенный выше код, он объединяется только на основе одной ячейки, а также повторное имя документа после объединения не удаляется. Кто-нибудь может здесь помочь, пожалуйста?

Ответ №1:

В VBA я бы использовал словарь для организации данных. Для ключа объедините то, что вы хотите сгруппировать (имя документа и уровень), а для содержимого-объединенные идентификаторы.

 '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) amp; "|" amp; vSrc(I, 3)
    If Not D.Exists(sKey) Then
        D.Add Key:=sKey, Item:=vSrc(I, 2)
    Else
        D(sKey) = D(sKey) amp; vbLf amp; 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

 

введите описание изображения здесь

Вы также можете получить желаемый результат с помощью Power Query , доступных в Windows Excel 2010 и Office 365 Excel

  • Выберите какую-нибудь ячейку в исходной таблице
  • Data => Getamp;Transform => From Table/Range
  • Когда откроется пользовательский интерфейс PQ, перейдите к Home => Advanced Editor
  • Обратите внимание на название таблицы в строке 2 кода.
  • Замените существующий код на приведенный ниже M-код
  • Измените имя таблицы в строке 2 вставленного кода на ваше «настоящее» имя таблицы
  • Изучите любые комментарии, а также Applied Steps окно, чтобы лучше понять алгоритм и шаги
  • После закрытия/загрузки отформатируйте полученную таблицу для переноса слов и центрирования.
    • Это форматирование должно сохраняться при последующих обновлениях.

Код 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 amp; "#(lf)" amp; current), Text.Type}
        }),

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

введите описание изображения здесь

Комментарии:

1. спасибо за ваш ответ, и это работает как шарм. Мне нужно внести еще несколько изменений, но я хочу попробовать самостоятельно, прежде чем задавать запрос, большое спасибо за это решение