Home > database >  Get items of the dictionary object
Get items of the dictionary object

Time:11-11

In sheet1, I have data in 6 columns like that

enter image description here

And this is my try with the code

    Sub Test()
    Dim a, dic As Object, i As Long, ii As Long
    With Sheet1
    a = .Range("A1").CurrentRegion.Value
    Set dic = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(a, 1)
        If Not dic.Exists(a(i, 2)) Then
        dic(a(i, 2)) = Array(a(i, 3), a(i, 4), a(i, 5), a(i, 6))
        Else
        For ii = 0 To 3
            If dic(a(i, 2))(ii) = Empty Then
                dic(a(i, 2))(ii) = a(i, ii   3)
            End If
        Next ii
        End If
    Next i
    .Range("J1").Resize(dic.Count, 1).Value = Application.Transpose(dic.Keys)
    .Range("K1").Resize(dic.Count, 4).Value = dic.Items
End With
End Sub

I could get the keys with no problem but how to return the items. The items should be the names in C2:F11

For example:

Name1 Ahmed Khaled Empty Amany

Another Example:

Name2 Ahmed Khaled Reda Amany

The target in simple words to join the data for each unique name only if there is no data inside the array items.

** I think I can solve it with the help of comments and please tell me if there are any notes

Sub Test()
    Dim a, w, dic As Object, i As Long, ii As Long
    With Sheet1
    a = .Range("A1").CurrentRegion.Value
    Set dic = CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(a, 1)
        If Not dic.Exists(a(i, 2)) Then
        dic(a(i, 2)) = Array(a(i, 3), a(i, 4), a(i, 5), a(i, 6))
        Else
        w = dic(a(i, 2))
        For ii = 0 To 3
            If w(ii) = Empty Then
                w(ii) = a(i, ii   3)
            End If
        Next ii
        dic(a(i, 2)) = w
        End If
    Next i
    .Range("J1").Resize(dic.Count, 1).Value = Application.Transpose(dic.Keys)
    .Range("K1").Resize(dic.Count, 4).Value = Application.Transpose(Application.Transpose(dic.Items))
End With
End Sub

CodePudding user response:

Transpose Data

  • This is using the items of the dictionary as columns in the 'Redim Preserve' Items Array.
Option Explicit

Sub Test()
    
    Dim ws As Worksheet: Set ws = Sheet1
    Dim srg As Range: Set srg = ws.Range("A1").CurrentRegion
    Dim sData As Variant: sData = srg.Value
    
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    dict.CompareMode = vbTextCompare
    
    Dim iData() As Variant
    Dim Key As Variant
    Dim n As Long
    Dim sr As Long
    Dim ir As Long
    Dim ic As Long
    
    For sr = 1 To UBound(sData, 1)
        Key = sData(sr, 2)
        If Not dict.Exists(Key) Then
            n = n   1
            dict(Key) = n
            ReDim Preserve iData(1 To 4, 1 To n) ' add another column
            For ir = 1 To 4
                iData(ir, n) = sData(sr, ir   2)
            Next ir
        Else
            ic = dict(Key) ' write the column of the current Key to a variable
            For ir = 1 To 4
                If IsEmpty(iData(ir, ic)) Then
                    iData(ir, ic) = sData(sr, ir   2)
                End If
            Next ir
        End If
    Next sr
    
    ws.Range("J1").Resize(dict.Count).Value = Application.Transpose(dict.Keys)
    ws.Range("K1").Resize(n, 4).Value = Application.Transpose(iData)

End Sub

CodePudding user response:

You have to walk through each entry in the array in order to get those names back out to the worksheet. Here is an example:

Option Explicit

Sub Test()
    Dim a, dic As Object, i As Long, ii As Long
    With Sheet1
        a = .Range("A1").CurrentRegion.Value
        Set dic = CreateObject("Scripting.Dictionary")
        For i = 1 To UBound(a, 1)
            If Not dic.Exists(a(i, 2)) Then
            dic(a(i, 2)) = Array(a(i, 3), a(i, 4), a(i, 5), a(i, 6))
            Else
            For ii = 0 To 3
                If dic(a(i, 2))(ii) = Empty Then
                    dic(a(i, 2))(ii) = a(i, ii   3)
                End If
            Next ii
            End If
        Next i
        
        Dim dest As Range
        Set dest = .Range("J1")
        Dim entry As Variant
        For Each entry In dic.keys
            Dim names As Variant
            names = dic(entry)
            
            dest.Offset(0, 0).Value = entry
            For i = LBound(names) To UBound(names)
                dest.Offset(0, i   1).Value = names(i)
            Next i
            Set dest = dest.Offset(1, 0)
        Next entry
    End With
End Sub

CodePudding user response:

I think the dictionary assignment code, whatever that is, just doesn't support arrays I think.

Sub test()
    
    Dim vaValues As Variant
    Dim i As Long, j As Long
    Dim dc As Scripting.Dictionary
    Dim wf As WorksheetFunction
    Dim x As Variant
    
    vaValues = Sheet1.Cells(1, 1).CurrentRegion.Value
    Set dc = New Scripting.Dictionary
    Set wf = Application.WorksheetFunction
    
    For i = LBound(vaValues, 1)   1 To UBound(vaValues, 1)
        If Not dc.Exists(vaValues(i, 2)) Then
            dc.Add vaValues(i, 2), wf.Index(vaValues, i, Array(3, 4, 5, 6))
        Else
            For j = 1 To 4
                If Len(dc(vaValues(i, 2))(j)) = 0 Then
                    x = dc(vaValues(i, 2))
                    x(j) = vaValues(i, j   2)
                    dc(vaValues(i, 2)) = x
                End If
            Next j
        End If
    Next i
    
    For i = 0 To 6
        Debug.Print Join(dc.Items(i), " ")
    Next i
    
End Sub
  • Related