Как сгруппировать список в excel?


У меня есть список списков в Excel. В первом столбце есть некоторые характеристики (имя, возраст, страна и т. д.), а во втором-значения. Я не хочу повторять одни и те же спецификации снова и снова. То, что я хочу показать на картинке. Я попробовал =VLOOKUP(), но это не сработало идеально, потому что списки не содержат одинаковых спецификаций. Как я могу этого достичь?

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

2 2

2 ответа:

Макрос VBA может генерировать результаты, а также список параметров для первого столбца результатов.

Чтобы ввести этот макрос (Sub), alt-F11 открывает редактор Visual Basic. Убедитесь, что ваш проект выделен в окне Проводника проектов. Затем в верхнем меню выберите Insert / Module и вставьте приведенный ниже код в открывшееся окно.

Обязательно установите ссылку, как указано в примечании в макросе

Чтобы использовать этот макрос (Sub), alt-F8 открывает диалоговое окно макроса. Выберите макрос по имени и запустите.

Этот макрос генерирует список со списком параметров в первом столбце. Его можно легко переписать, чтобы список параметров был в первой строке, если это предпочтительнее.


Option Explicit
'Set Reference to Microsoft Scripting Runtime

Sub GroupLists()
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
    Dim vSrc As Variant, vRes As Variant
    Dim dictParams As Dictionary
    Dim sParam As String
    Dim I As Long, J As Long, K As Long
    Dim V As Variant

Set wsSrc = Worksheets("sheet1")
Set wsRes = Worksheets("sheet1")
    Set rRes = wsRes.Cells(1, 5)

With wsSrc
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=2)
End With

'Get unique list of Parameters with row number
'Also count the number of entries for number of columns in final result
J = 0
Set dictParams = New Dictionary
K = 0 'row number for parameter
For I = 1 To UBound(vSrc, 1)
    J = J + 1 'column count
    Do
        If Not dictParams.Exists(vSrc(I, 1)) Then
            K = K + 1
            dictParams.Add Key:=vSrc(I, 1), Item:=K
        End If
        I = I + 1
        If I > UBound(vSrc) Then Exit Do
    Loop Until vSrc(I, 1) = ""

    If I > UBound(vSrc) Then Exit For
Next I

'Create results array
ReDim vRes(1 To dictParams.Count, 1 To J + 1)

'Populate Column 1
For Each V In dictParams.Keys
    vRes(dictParams(V), 1) = V
Next V

'Populate the data
J = 1 'column number
For I = 1 To UBound(vSrc, 1)
    J = J + 1
    Do
        sParam = vSrc(I, 1)
        vRes(dictParams(sParam), J) = vSrc(I, 2)
        I = I + 1
        If I > UBound(vSrc) Then Exit Do
    Loop Until vSrc(I, 1) = ""

    If I > UBound(vSrc) Then Exit For
Next I

'Write the results
Set rRes = rRes.Resize(UBound(vRes, 1), UBound(vRes, 2))
rRes.EntireColumn.Clear
rRes = vRes

End Sub

EDIT: макрос изменен для отражения "реальных данных"

Пожалуйста, обратите внимание: вам нужно будет добавить второй лист для результатов. Я назвал его "Лист 2"


Option Explicit
'Set Reference to Microsoft Scripting Runtime

Sub GroupLists()
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
    Dim vSrc As Variant, vRes As Variant
    Dim dictParams As Dictionary
    Dim sParam As String
    Dim I As Long, J As Long, K As Long
    Dim V As Variant
    Dim sDelim As String 'Differentiates each record

Set wsSrc = Worksheets("sheet1")
Set wsRes = Worksheets("sheet2")
    Set rRes = wsRes.Cells(1, 1)

With wsSrc
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=2)
    sDelim = vSrc(1, 1)
End With

'Get unique list of Parameters with row number
'Also count the number of entries for number of columns in final result
J = 0
Set dictParams = New Dictionary
K = 0 'row number for parameter
For I = 1 To UBound(vSrc, 1)
    J = J + 1 'column count
    Do
        If Not dictParams.Exists(vSrc(I, 1)) Then
            K = K + 1
            dictParams.Add Key:=vSrc(I, 1), Item:=K
        End If
        I = I + 1
        If I > UBound(vSrc) Then Exit Do
    Loop Until vSrc(I, 1) = sDelim

    If I > UBound(vSrc) Then
        Exit For
    Else
        I = I - 1
    End If
Next I

'Create results array
ReDim vRes(1 To dictParams.Count, 1 To J + 1)

'Populate Column 1
For Each V In dictParams.Keys
    vRes(dictParams(V), 1) = V
Next V

'Populate the data
J = 1 'column number
For I = 1 To UBound(vSrc, 1)
    J = J + 1
    Do
        sParam = vSrc(I, 1)
        vRes(dictParams(sParam), J) = vSrc(I, 2)
        I = I + 1
        If I > UBound(vSrc) Then Exit Do
    Loop Until vSrc(I, 1) = sDelim

    If I > UBound(vSrc) Then
        Exit For
    Else
        I = I - 1
    End If
Next I

'Write the results
Set rRes = rRes.Resize(UBound(vRes, 1), UBound(vRes, 2))
rRes.EntireColumn.Clear
rRes = vRes

End Sub

EDIT2: этот макрос является модификацией вышеприведенного, в котором перечислены результаты в противоположной ориентации. Это может оказаться более полезным.


Option Explicit
'Set Reference to Microsoft Scripting Runtime

Sub GroupListsVertical()
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
    Dim vSrc As Variant, vRes As Variant
    Dim dictParams As Dictionary
    Dim sParam As String
    Dim I As Long, J As Long, K As Long
    Dim V As Variant
    Dim sDelim As String 'Differentiates each record

Set wsSrc = Worksheets("sheet1")
Set wsRes = Worksheets("sheet3")
    Set rRes = wsRes.Cells(1, 1)

With wsSrc
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=2)
    sDelim = vSrc(1, 1)
End With

'Get unique list of Parameters with row number
'Also count the number of entries for number of columns in final result
J = 0
Set dictParams = New Dictionary
K = 0 'column number for parameter
For I = 1 To UBound(vSrc, 1)
    J = J + 1 'row count
    Do
        If Not dictParams.Exists(vSrc(I, 1)) Then
            K = K + 1
            dictParams.Add Key:=vSrc(I, 1), Item:=K
        End If
        I = I + 1
        If I > UBound(vSrc) Then Exit Do
    Loop Until vSrc(I, 1) = sDelim

    If I > UBound(vSrc) Then
        Exit For
    Else
        I = I - 1
    End If
Next I

'Create results array
ReDim vRes(1 To J + 1, 1 To dictParams.Count)

'Populate row 1
For Each V In dictParams.Keys
    vRes(1, dictParams(V)) = V
Next V

'Populate the data
J = 1 'row number
For I = 1 To UBound(vSrc, 1)
    J = J + 1
    Do
        sParam = vSrc(I, 1)
        vRes(J, dictParams(sParam)) = vSrc(I, 2)
        I = I + 1
        If I > UBound(vSrc) Then Exit Do
    Loop Until vSrc(I, 1) = sDelim

    If I > UBound(vSrc) Then
        Exit For
    Else
        I = I - 1
    End If
Next I

'Write the results
Set rRes = rRes.Resize(UBound(vRes, 1), UBound(vRes, 2))
rRes.EntireColumn.Clear
rRes = vRes
rRes.EntireColumn.AutoFit


End Sub

Используйте следующие Формулы ARRAY.

Формула ячейки F2

=IFERROR(INDEX($B$1:$B$20,SMALL(IF($A$1:$A$20=$E2,ROW($B$1:$B$20),""),COLUMN(A:A))),"")

формула ячейки Е19

=IFERROR(INDEX($B$1:$B$20,SMALL(IF($A$1:$A$20=$E2,ROW($B$1:$B$20),""),COLUMN(A:A))),"")

Нажмите CTRL+сдвиг+введите , чтобы оценить формулу, поскольку она является формулой массива.

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