VBA to transpose blocks (arrays) of data

Antonf

New Member
Joined
Sep 16, 2009
Messages
21
I have to transform literally hundreds of blocks of data exported from financial software into a different format for my manager.
The source data is on the left in the image and the required output is on the right.
Doing it manually is not that difficult but i will drive me to drink!
Any help will be highly appreciated!
Transpose.xlsx
ABCDEFGHIJKLMNO
1CodeDescriptionMar 2023Apr 2023May 2023Jun 2023400190459150
2NR0001Name1NR0001Name1
340017.917.917.917.91Mar 20237.91177.12178.73
49045177.12177.12177.12177.12Apr 20237.91177.12182.54
59150178.73182.54229.54191.93May 20237.91177.12229.54
6NR0004Name2Jun 20237.91177.12191.93
740017.917.917.917.91NR0004Name2
89045177.12177.12177.12177.12Mar 20237.91177.12551.67
99150551.67514.18664.42636.36Apr 20237.91177.12514.18
10May 20237.91177.12664.42
11Jun 20237.91177.12636.36
Sheet1
 

Attachments

  • Transpose.jpeg
    Transpose.jpeg
    68.5 KB · Views: 12
Book3
ABCDEF
1NRDescriptionAttribute800190459150
2AM002Name1Jul-232018.47177.12191.93
3AM004Mr Robin Shawn Van BiljonJul-2313760.3177.12567.7
Table1


Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Code", type any}, {"Description", type text}, {"Jul-23", type number}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "NR", each if [Code]= Text.Select([Code], {"0".."9"} ) then null else [Code]),
    #"Replaced Errors" = Table.ReplaceErrorValues(#"Added Custom", {{"NR", null}}),
    #"Filled Down" = Table.FillDown(#"Replaced Errors",{"NR"}),
    #"Reordered Columns" = Table.ReorderColumns(#"Filled Down",{"Code", "NR", "Description", "Jul-23"}),
    #"Filled Down1" = Table.FillDown(#"Reordered Columns",{"Description"}),
    #"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Filled Down1", {"Code", "NR", "Description"}, "Attribute", "Value"),
    #"Pivoted Column" = Table.Pivot(Table.TransformColumnTypes(#"Unpivoted Columns", {{"Code", type text}}, "en-IE"), List.Distinct(Table.TransformColumnTypes(#"Unpivoted Columns", {{"Code", type text}}, "en-IE")[Code]), "Code", "Value", List.Sum)
in
    #"Pivoted Column"
 
Upvote 0

Excel Facts

Format cells as time
Select range and press Ctrl+Shift+2 to format cells as time. (Shift 2 is the @ sign).
When you copied you seem to have missed this piece, highlighted in red below
1691049535487.png
 
Upvote 1
Another option through VBA, For your reference:

工作簿1.xlsb
ABCDEFG
1CodeDescriptionMar-23Apr-23May-23Jun-23Jul-23
2NR0001Name1
340017.917.917.917.912
49045177.12177.12177.12177.123
59150178.73182.54229.54191.933
6NR0004Name2
740017.917.917.917.915
89045177.12177.12177.126
99150551.67514.18636.367
Sheet1


Need to put code in sheet2 column G & H ( Code and column number)
1691125916925.png


工作簿1.xlsb
ABCDEFGH
140019045915040013
2NR0001Name190454
33/1/237.91177.12178.7391505
44/1/237.91177.12182.54
55/1/237.91177.12229.54
66/1/237.91177.12191.93
77/1/23233
8NR0004Name2
93/1/237.91177.12551.67
104/1/237.91177.12514.18
115/1/237.91177.12
126/1/237.91636.36
137/1/23567
Sheet2


VBA Code:
Option Explicit
Sub test()
Dim a As Variant, T As Variant
Dim ws2 As Worksheet
Set ws2 = Sheets("sheet2") ' output
Dim ws As Worksheet
Set ws = Sheets("sheet1") ' data
ReDim b(1 To 100000, 1 To 6)
Dim dict As Object
'Dim dict As New Dictionary
Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim month%, i%, lastcol%, lrow%, k%, j%

a = ws2.Range("g1:h" & ws2.Cells(Rows.Count, "g").End(xlUp).Row).Value 'Add Code to Array

For i = 1 To UBound(a, 1)
    dict.Add a(i, 1), a(i, 2) 'Add code to dictionary
Next i

With ws
    lastcol = .UsedRange.Columns(ActiveSheet.UsedRange.Columns.Count).Column
    lrow = .Cells(Rows.Count, "A").End(xlUp).Row
    a = .Range(.Cells(1, 1), .Cells(lrow, lastcol)).Value  'Redefine array from a1 to G last row
    month = lastcol - 2
End With

For i = 2 To UBound(a, 1) 'Loop through data
    If Len(a(i, 2)) >= 5 Then 'desc
         k = IIf(k > 0, k + month, k + 1)
         b(k, 1) = a(i, 1) 'Name
         b(k, 2) = a(i, 2) 'Desc
    End If
   
    If dict.Exists(a(i, 1)) Then
            For j = 1 To month 'loop through month
                b(k + j, 2) = a(1, j + 2)
                b(k + j, dict(a(i, 1))) = a(i, j + 2) '
            Next j
    End If

Next i

T = dict.Keys
With ws2
    .Range("c1").Resize(, UBound(T, 1) + 1).Value = T
    .[a2].Resize(UBound(b, 1), UBound(b, 2)).Value = b
End With

End Sub
 
Upvote 0

Forum statistics

Threads
1,223,236
Messages
6,170,906
Members
452,366
Latest member
TePunaBloke

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