VBA to Transpose Data

jrock8859

New Member
Joined
Oct 11, 2022
Messages
5
Office Version
  1. 365
Platform
  1. Windows
Hi,

I would like a VBA that will transpose the data set like this below. I am at a loss of where to start. I am good with VBA for the basic excel functions but I learn by reverse engineering things.

Columns A,B,C is how I am starting, I want to finish with it looking like Columns F and beyond

Tank you

Data.png
 

Excel Facts

How to fill five years of quarters?
Type 1Q-2023 in a cell. Grab the fill handle and drag down or right. After 4Q-2023, Excel will jump to 1Q-2024. Dash can be any character.
This will work for your example:

VBA Code:
Sub transpose()
    Dim lRow As Integer
    Dim c As Integer
    Dim r As Integer
    c = 6
    r = 1

    lRow = Cells(Rows.Count, 1).End(xlUp).Row
    For i = 2 To lRow
        If Cells(i, 1).Value = Cells(i - 1, 1).Value Then
            For ii = 0 To 1
                Cells(r, c).Value = Cells(i, 2 + ii).Value
                c = c + 1
            Next
        Else
            c = 6
            r = r + 1
            For ii = 0 To 2
                Cells(r, c).Value = Cells(i, 1 + ii).Value
                c = c + 1
            Next
        End If
    Next
End Sub
 
Upvote 0
Hi and welcome to MrExcel!

Here is another macro for you to consider:

VBA Code:
Sub TransposeData()
  Dim dic As Object
  Dim a As Variant, b As Variant
  Dim i As Long, n As Long, lr As Long, y As Long
  Dim nrow As Long, ncol As Long
 
  lr = Range("A" & Rows.Count).End(3).Row
  a = Range("A1:C" & lr).Value
  n = Evaluate("=MAX(COUNTIF(A2:A" & lr & ",A2:A" & lr & "))")
  ReDim b(1 To UBound(a, 1), 1 To (n * 2) + 1)
 
  Set dic = CreateObject("Scripting.Dictionary")
 
  y = 1
  b(1, 1) = a(1, 1)
  For i = 2 To UBound(a, 1)
    If Not dic.exists(a(i, 1)) Then
      y = y + 1
      dic(a(i, 1)) = y & "|" & 2
      b(y, 1) = a(i, 1)
    End If
   
    nrow = Split(dic(a(i, 1)), "|")(0)
    ncol = Split(dic(a(i, 1)), "|")(1)
   
    b(1, ncol) = a(1, 2)
    b(1, ncol + 1) = a(1, 3)
    b(nrow, ncol) = a(i, 2)
    b(nrow, ncol + 1) = a(i, 3)
   
    ncol = ncol + 2
    dic(a(i, 1)) = nrow & "|" & ncol
   
  Next
 
  Range("F1").Resize(y, UBound(b, 2)).Value = b
End Sub
 
Upvote 0
If it's not a lot of data, try this macro:

VBA Code:
Sub TransposeData2()
  Dim c As Range, f As Range
  
  For Each c In Range("A2", Range("A" & Rows.Count).End(3))
    Set f = Range("F:F").Find(c.Value, , xlValues, xlWhole)
    If f Is Nothing Then
      Range("F" & Rows.Count).End(3)(2).Resize(1, 3).Value = c.Resize(1, 3).Value
    Else
      Cells(f.Row, Columns.Count).End(1)(1, 2).Resize(1, 2).Value = c.Offset(0, 1).Resize(1, 2).Value
    End If
  Next
End Sub
 
Upvote 0
This will work for your example:

VBA Code:
Sub transpose()
    Dim lRow As Integer
    Dim c As Integer
    Dim r As Integer
    c = 6
    r = 1

    lRow = Cells(Rows.Count, 1).End(xlUp).Row
    For i = 2 To lRow
        If Cells(i, 1).Value = Cells(i - 1, 1).Value Then
            For ii = 0 To 1
                Cells(r, c).Value = Cells(i, 2 + ii).Value
                c = c + 1
            Next
        Else
            c = 6
            r = r + 1
            For ii = 0 To 2
                Cells(r, c).Value = Cells(i, 1 + ii).Value
                c = c + 1
            Next
        End If
    Next
End Sub

Thank you for this, I have a better understanding on how this functions now. Is there a way to have it run faster if the data set is rather large, say a couple hundred rows?
 
Upvote 0
Using arrays may help. Also consider to turn off and on screen update.

VBA Code:
Sub transpose()
  Application.ScreenUpdating = False
  // Code here
  Application.ScreenUpdating = True
End Sub
@DanteAmor 's dictionary solution might be faster.
 
Upvote 0
Hi and welcome to MrExcel!

Here is another macro for you to consider:

VBA Code:
Sub TransposeData()
  Dim dic As Object
  Dim a As Variant, b As Variant
  Dim i As Long, n As Long, lr As Long, y As Long
  Dim nrow As Long, ncol As Long
 
  lr = Range("A" & Rows.Count).End(3).Row
  a = Range("A1:C" & lr).Value
  n = Evaluate("=MAX(COUNTIF(A2:A" & lr & ",A2:A" & lr & "))")
  ReDim b(1 To UBound(a, 1), 1 To (n * 2) + 1)
 
  Set dic = CreateObject("Scripting.Dictionary")
 
  y = 1
  b(1, 1) = a(1, 1)
  For i = 2 To UBound(a, 1)
    If Not dic.exists(a(i, 1)) Then
      y = y + 1
      dic(a(i, 1)) = y & "|" & 2
      b(y, 1) = a(i, 1)
    End If
  
    nrow = Split(dic(a(i, 1)), "|")(0)
    ncol = Split(dic(a(i, 1)), "|")(1)
  
    b(1, ncol) = a(1, 2)
    b(1, ncol + 1) = a(1, 3)
    b(nrow, ncol) = a(i, 2)
    b(nrow, ncol + 1) = a(i, 3)
  
    ncol = ncol + 2
    dic(a(i, 1)) = nrow & "|" & ncol
  
  Next
 
  Range("F1").Resize(y, UBound(b, 2)).Value = b
End Sub

Hi Dante,

Thank you for your solution. If you wouldn't mind, for my learning purposes. Let's say I only have 2 columns now instead of 3, how would this effect the vba?
 
Upvote 0
for my learning purposes. Let's say I only have 2 columns now instead of 3

I added a * to the changed lines in the macro. By the way, jrock8859's macro is quite fast.

VBA Code:
Sub TransposeData_1col()
  Dim dic As Object
  Dim a As Variant, b As Variant
  Dim i As Long, n As Long, lr As Long, y As Long
  Dim nrow As Long, ncol As Long
  
  lr = Range("A" & Rows.Count).End(3).Row
  a = Range("A1:B" & lr).Value              '*
  n = Evaluate("=MAX(COUNTIF(A2:A" & lr & ",A2:A" & lr & "))")
  ReDim b(1 To UBound(a, 1), 1 To n + 1)    '*
  
  Set dic = CreateObject("Scripting.Dictionary")
  
  y = 1
  b(1, 1) = a(1, 1)
  For i = 2 To UBound(a, 1)
    If Not dic.exists(a(i, 1)) Then
      y = y + 1
      dic(a(i, 1)) = y & "|" & 2
      b(y, 1) = a(i, 1)
    End If
    
    nrow = Split(dic(a(i, 1)), "|")(0)
    ncol = Split(dic(a(i, 1)), "|")(1)
    
    b(1, ncol) = a(1, 2)
    'b(1, ncol + 1) = a(1, 3)         '*
    b(nrow, ncol) = a(i, 2)
    'b(nrow, ncol + 1) = a(i, 3)      '*
    
    ncol = ncol + 1                   '*
    dic(a(i, 1)) = nrow & "|" & ncol
    
  Next
  
  Range("F1").Resize(y, UBound(b, 2)).Value = b
End Sub
 
Upvote 0

Forum statistics

Threads
1,223,881
Messages
6,175,161
Members
452,615
Latest member
bogeys2birdies

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top