[Solved] Transpose Column into Row with VBA [closed]


This is not so straightforward a problem because of having to consolidate the information by date.

You also do not indicate what you want to happen should there be more than one identical code associated with a particular date. I chose to ignore it, and only list the unique codes, but you can modify the code below to do something else, if you need.

Simplified algorithm:

  • Read the data into a VBA array (for speed of processing)
  • Create User Defined Objects (class) with properties of:
    • the relevant date
    • a collection (dictionary) of all the codes associated with that date
  • Collect these objects into another dictionary with the Key being the relevant date
  • Reorder the information into a “Results” array
  • output to the worksheet and format.

Read the notes in the code, as they are quite important

Class Module

'**Rename this Module:  cByDates**

Option Explicit

Private pDt As Date
Private pCode As String
Private pCodes As Dictionary

Public Property Get Dt() As Date
    Dt = pDt
End Property
Public Property Let Dt(Value As Date)
    pDt = Value
End Property

Public Property Get Code() As String
    Code = pCode
End Property
Public Property Let Code(Value As String)
    pCode = Value
End Property

Public Property Get Codes() As Dictionary
    Set Codes = pCodes
End Property
Public Function addCodesItem(Value)
    'bypass any duplicates
    If Not Codes.Exists(Value) Then _
    Codes.Add Value, Value
End Function

Private Sub Class_Initialize()
    Set pCodes = New Dictionary
        pCodes.CompareMode = TextCompare
End Sub

Regular Module

'Set Reference to Microsoft Scripting Runtime

Option Explicit

Sub ConsolidateByDate()
    Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
    Dim vSrc As Variant, vRes As Variant
    Dim cBD As cByDates, dBD As Dictionary
    Dim I As Long, J As Long
    Dim lRC() As Long 'last row-col
    Dim V As Variant, W As Variant

'Setup worksheets and results range
Set wsSrc = Worksheets("sheet1")
Set wsRes = Worksheets("sheet2")
    Set rRes = wsRes.Cells(1, 1)

'read original data into VBA array for speed of processing
'if there is or will be other information on Sheet1, then you will need a
'   different routine to find the last row and column
With wsSrc
    lRC = LastRowCol(.Name)
    vSrc = .Range(.Cells(1, 1), .Cells(lRC(0), lRC(1)))
End With

'Collect and organize the data
Set dBD = New Dictionary
For I = 1 To UBound(vSrc, 1)
    For J = 2 To UBound(vSrc, 2)
        Set cBD = New cByDates
        With cBD
            .Dt = vSrc(I, 1)
            .Code = vSrc(I, J)
            .addCodesItem .Code

            If Not dBD.Exists(.Dt) Then
                dBD.Add Key:=.Dt, Item:=cBD
            Else
                dBD(.Dt).addCodesItem .Code
            End If
        End With
    Next J
Next I

'Create results array
'number of columns = number of dBD items
lRC(0) = 0
lRC(1) = dBD.Count

'number of rows = max codes count
For Each V In dBD.Keys
    lRC(0) = IIf(lRC(0) > dBD(V).Codes.Count, lRC(0), dBD(V).Codes.Count)
Next V

ReDim vRes(0 To lRC(0), 1 To lRC(1))

'Populate each column
J = 1
For Each V In dBD.Keys
    I = 0
    vRes(I, J) = V
    For Each W In dBD(V).Codes.Keys
        I = I + 1
        vRes(I, J) = W
    Next W
    J = J + 1
Next V

Set rRes = rRes.Resize(UBound(vRes, 1) + 1, UBound(vRes, 2))
With rRes
    .EntireColumn.Clear
    .Value = vRes
    With .Rows(1)
        .Font.Bold = True
        .HorizontalAlignment = xlCenter
    End With
    .EntireColumn.AutoFit
End With

End Sub

'------------------------------------------------------
Function LastRowCol(Worksht As String) As Long()
    Dim WS As Worksheet, R As Range
    Dim LastRow As Long, LastCol As Long
    Dim L(1) As Long
Set WS = Worksheets(Worksht)
With WS
    Set R = .Cells.Find(what:="*", after:=.Cells(1, 1), _
                    LookIn:=xlValues, searchorder:=xlByRows, _
                    searchdirection:=xlPrevious)

    If Not R Is Nothing Then
        LastRow = R.Row
        LastCol = .Cells.Find(what:="*", after:=.Cells(1, 1), _
                    LookIn:=xlValues, searchorder:=xlByColumns, _
                    searchdirection:=xlPrevious).Column
    Else
        LastRow = 1
        LastCol = 1
    End If
End With

L(0) = LastRow
L(1) = LastCol
LastRowCol = L
End Function

Original Data

enter image description here

Results

enter image description here

I try to avoid references to non-SO information, but I will make an exception here. For a basic discussion of Classes, see Chip Pearson’s Introduction to Classes

4

solved Transpose Column into Row with VBA [closed]