Convert table with 6 static columns to list format

iainhogg

New Member
Joined
Sep 7, 2016
Messages
6
Hi, I have a table of data as below with 6 columns of descriptors and year and month/period data extending to the right. I am trying to convert this to a list format, also shown below. I had attempted to amend some VBA code that had a similar table but with three static label columns, I thought this would be quite easy but haven't been able to get it to work. I have included the original VBA code below to avoid any confusion being caused by my meddling.

If someone can advise of a solution to this or if you have a better way to do it then that would be much appreciated!

Original table:
2016
2016
2016
Program
Variant
Deliverables
Supplier
Vendor No.
Package
Jan
Feb
Mar
P1
V1
D1
S1
VN1
PA1
1
2
1
P1
V2
D2
S2
VN2
PA2
3
1
4

<tbody>
</tbody>

Desired List:

Program
Variant
Deliverables
Supplier
Vendor No.
Package
Year
Month/Period
Quantity
P1
V1
D1
S1
VN1
PA1
2016
JAN
1
P1
V1
D1
S1
VN1
PA1
2016
FEB
2
P1
V1
D1
S1
VN1
PA1
2016
MAR
1

<tbody>
</tbody>


Code:
Sub CrossTabToList()
'written by Doctor Moxie

Dim wsCrossTab As Worksheet
Dim wsList As Worksheet
Dim iLastCol As Long
Dim iLastRow As Long
Dim iLastRowList As Long
Dim rngCTab As Range 'Used for range in Sheet1 cross tab sheet
Dim rngList As Range 'Destination range for the list
Dim ROW As Long

Set wsCrossTab = Worksheets("Sheet1") 'AMEND TO SHOW SHEET NUMBER WITH THE CROSS TAB
Set wsList = Worksheets.Add

'Find the last row in Sheet1 with the cross tab
iLastRow = wsCrossTab.Cells(Rows.Count, "A").End(xlUp).ROW

'Set the initial value for the row in the destination worksheet
'I set mine as 2 as I want to put headings in row 1
iLastRowList = 2

'Find the last column in Sheet1 with the cross tab
iLastCol = wsCrossTab.Range("A2").End(xlToRight).Column

'Set the heading titles in the list sheet
'You will need to amend these to something appropriate for your sheet
wsList.Range("A1:F1") = Array("NAME", "PROJECT", "TYPE", "PLAN/ACTUAL", "WEEK", "HOURS")

'Start looping through the cross tab data
For ROW = 3 To iLastRow 'START AT ROW 3 AS THIS IS WHERE DATA BEGINS IN MY CROSS TAB
Set rngCTab = wsCrossTab.Range("A" & ROW, "C" & ROW) 'initial value A3 SETS THE RANGE TO INCLUDE ALL STATIC DATA - IN THIS CASE NAME, PROJECT, TYPE
Set rngList = wsList.Range("A" & iLastRowList) 'initial value A2

'Copy individual names in Col A (A3 initially) into as many rows as there are data columns
'in the cross tab (less 3 for Col A-C).
rngCTab.Copy rngList.Resize(iLastCol - 3)

'SELECT THE HEADING ROW WITH FORECAST/ACTUAL
'Move up ROW (INITIALLY 3) rows less TWO and across 3 columns (using offset function). Copy.
rngCTab.Offset(-(ROW - 2), 3).Resize(, iLastCol - 3).Copy
'Paste transpose to columns in the list sheet alongside the static data
rngList.Offset(0, 3).PasteSpecial Transpose:=True

'SELECT THE ROW WITH THE WEEK NUMBERS
'Move up ROW (INITIALLY 3) rows less ONE and across 3 columns (using offset function). Copy.
rngCTab.Offset(-(ROW - 1), 3).Resize(, iLastCol - 3).Copy

'Paste transpose to columns in the list sheet alongside the static data
rngList.Offset(0, 4).PasteSpecial Transpose:=True

'Staying on same row (3 initially) copy the data from the cross tab
rngCTab.Offset(, 3).Resize(, iLastCol - 3).Copy

'Past transpose as column in list sheet
rngList.Offset(0, 5).PasteSpecial Transpose:=True

'Set the new last row in list sheet to be just below the last name copied
iLastRowList = iLastRowList + (iLastCol - 3)

'increment ROW by 1
Next ROW
End Sub












<tbody>
</tbody>
 

Excel Facts

Which Excel functions can ignore hidden rows?
The SUBTOTAL and AGGREGATE functions ignore hidden rows. AGGREGATE can also exclude error cells and more.
Starting sheet:


Book1
ABCDEFGHI
1201620162016
2ProgramVariantDeliverablesSupplierVendor No.PackageJanFebMar
3P1V1D1S1VN1PA1121
4P1V2D2S2VN2PA2314
Sheet1


Generated sheet:


Book1
ABCDEFGHI
1ProgramVariantDeliverablesSupplierVendor No.PackageYearMonth/PeriodQuantity
2P1V1D1S1VN1PA12016JAN1
3P1V1D1S1VN1PA12016FEB2
4P1V1D1S1VN1PA12016MAR1
5P1V2D2S2VN2PA22016JAN3
6P1V2D2S2VN2PA22016FEB1
7P1V2D2S2VN2PA22016MAR4
Sheet2


Macro code:

Code:
Public Sub CrossTabToList()

Const staticHeaderCount = 6

Dim crossTabSheet As Worksheet
Dim listSheet As Worksheet
Dim lastCol As Long
Dim lastRow As Long
Dim nextRow As Long
Dim thisRow As Long
Dim thisCol As Long

' Set up the sheets
Set crossTabSheet = Worksheets("Sheet1")
Set listSheet = Worksheets.Add(After:=crossTabSheet)

' Work out the last row and column and copy the headers
With crossTabSheet
    lastRow = .Cells(.Rows.Count, 1).End(xlUp).ROW
    lastCol = .Cells(2, .Columns.Count).End(xlToLeft).Column
    listSheet.Range(listSheet.Cells(1, 1), listSheet.Cells(1, staticHeaderCount)).Value = .Range(.Cells(2, 1), .Cells(2, staticHeaderCount)).Value
End With

' Set up extra headers in the target sheet and make the headers bold
With listSheet
    .Range(.Cells(1, staticHeaderCount + 1), .Cells(1, staticHeaderCount + 3)).Value = Array("Year", "Month/Period", "Quantity")
    .Range(.Cells(1, 1), .Cells(1, staticHeaderCount + 3)).Font.Bold = True
End With

' Process all the data
nextRow = 1
For thisRow = 3 To lastRow
    For thisCol = staticHeaderCount + 1 To lastCol
        ' New row required on target sheet
        nextRow = nextRow + 1
        
        ' Copy the data
        With crossTabSheet
            listSheet.Range(listSheet.Cells(nextRow, 1), listSheet.Cells(nextRow, staticHeaderCount)).Value = .Range(.Cells(thisRow, 1), .Cells(thisRow, staticHeaderCount)).Value
            listSheet.Cells(nextRow, staticHeaderCount + 1).Value = .Cells(1, thisCol).Value
            listSheet.Cells(nextRow, staticHeaderCount + 2).Value = UCase(.Cells(2, thisCol).Value)
            listSheet.Cells(nextRow, staticHeaderCount + 3).Value = .Cells(thisRow, thisCol).Value
        End With
    Next thisCol
Next thisRow

End Sub

WBD
 
Upvote 0
ProgramVariantDeliverablesSupplierVendor No.PackageJanFebMarAprMayJunJulAugSepOctNovDec
P1V1D1S1VN1PA1121234543454
P1V2D2S2VN2PA2314567876567
Desired List:
ProgramVariantDeliverablesSupplierVendor No.PackageYearMonth/PeriodQuantity
P1V1D1S1VN1PA12016Jan1this macro achieves table to the left
P1V1D1S1VN1PA12016Feb2
P1V1D1S1VN1PA12016Mar1myrow = 7
P1V1D1S1VN1PA12016Apr2 For rrow = 2 To 3
P1V1D1S1VN1PA12016May3 For mmonth = 7 To 18
P1V1D1S1VN1PA12016Jun4 myrow = myrow + 1
P1V1D1S1VN1PA12016Jul5 For z = 1 To 6
P1V1D1S1VN1PA12016Aug4 Cells(myrow, z) = Cells(rrow, z)
P1V1D1S1VN1PA12016Sep3 Next z
P1V1D1S1VN1PA12016Oct4 Cells(myrow, 7) = 2016
P1V1D1S1VN1PA12016Nov5 Cells(myrow, 8) = Cells(1, mmonth)
P1V1D1S1VN1PA12016Dec4 Cells(myrow, 9) = Cells(rrow, mmonth)
P1V2D2S2VN2PA22016Jan3 Next mmonth
P1V2D2S2VN2PA22016Feb1 Next rrow
P1V2D2S2VN2PA22016Mar4End Sub
P1V2D2S2VN2PA22016Apr5
P1V2D2S2VN2PA22016May6
P1V2D2S2VN2PA22016Jun7
P1V2D2S2VN2PA22016Jul8
P1V2D2S2VN2PA22016Aug7
P1V2D2S2VN2PA22016Sep6
P1V2D2S2VN2PA22016Oct5
P1V2D2S2VN2PA22016Nov6
P1V2D2S2VN2PA22016Dec7

<colgroup><col span="6"><col><col><col><col span="10"></colgroup><tbody>
</tbody>
 
Upvote 0
WBD, Thanks very much this has worked, however it is identifying a lot of columns that are actually blank which is significantly slowing down the macro. I assume this is because I have a formula that pulls from a month/period list and there will be a bunch of columns to the right of the actual months with "" to make them appear blank. is there a way to exclude these? I have a count of the number of data columns in addition to the static columns, this is held on the "settings" tab in cell O2 if that could be used?

I also have rows formatted down to 500 as a contingency will these be getting picked up as well and slowing things down? Any data I want to include will always have a value in column A and the contingent rows are completely blank just formatted.

Thanks,

Iain
 
Upvote 0
ProgramVariantDeliverablesSupplierVendor No.PackageJanFebMarAprMayJunJulAugSepOctNovDechow many months
P1V1D1S1VN1PA11212345439
P1V2D2S2VN2PA2314567876
Desired List:
ProgramVariantDeliverablesSupplierVendor No.PackageYearMonth/PeriodQuantity
P1V1D1S1VN1PA12016Jan1this macro achieves table to the left
P1V1D1S1VN1PA12016Feb2
P1V1D1S1VN1PA12016Mar1myrow = 7
P1V1D1S1VN1PA12016Apr2 For rrow = 2 To 3
P1V1D1S1VN1PA12016May3 For mmonth = 7 To 7 + Cells(2, 20) - 1
P1V1D1S1VN1PA12016Jun4 myrow = myrow + 1
P1V1D1S1VN1PA12016Jul5 For z = 1 To 6
P1V1D1S1VN1PA12016Aug4 Cells(myrow, z) = Cells(rrow, z)
P1V1D1S1VN1PA12016Sep3 Next z
P1V2D2S2VN2PA22016Jan3 Cells(myrow, 7) = 2016
P1V2D2S2VN2PA22016Feb1 Cells(myrow, 8) = Cells(1, mmonth)
P1V2D2S2VN2PA22016Mar4 Cells(myrow, 9) = Cells(rrow, mmonth)
P1V2D2S2VN2PA22016Apr5 Next mmonth
P1V2D2S2VN2PA22016May6 Next rrow
P1V2D2S2VN2PA22016Jun7End Sub
P1V2D2S2VN2PA22016Jul8
P1V2D2S2VN2PA22016Aug7
P1V2D2S2VN2PA22016Sep6
oct nov dec now blank
and macro could be altered to ignore them
but in Nov there will be some oct figures so you need to run the macro again
T2 is now how many months
so third line becomes
for mmonth=7 to 7+cells(2,20)-1
note we now only print out jan to sept

<colgroup><col span="6"><col><col><col><col><col><col><col><col><col><col><col><col><col span="5"></colgroup><tbody>
</tbody>
 
Upvote 0
ProgramVariantDeliverablesSupplierVendor No.PackageJanFebMarAprMayJunJulAugSepOctNovDechow many months
P1V1D1S1VN1PA11212345439
P1V2D2S2VN2PA2314567876
how many rows to process
2
ProgramVariantDeliverablesSupplierVendor No.PackageYearMonth/PeriodQuantity=sumproduct((a2:a5<>"")*1)
P1V1D1S1VN1PA12016Jan1this macro achieves table to the left
P1V1D1S1VN1PA12016Feb2
P1V1D1S1VN1PA12016Mar1myrow = 7
P1V1D1S1VN1PA12016Apr2 For rrow = 2 To 2 + Cells(5, 20) - 1< < < < < <
P1V1D1S1VN1PA12016May3 For mmonth = 7 To 7 + Cells(2, 20) - 1< < < < < <
P1V1D1S1VN1PA12016Jun4 myrow = myrow + 1
P1V1D1S1VN1PA12016Jul5 For z = 1 To 6
P1V1D1S1VN1PA12016Aug4 Cells(myrow, z) = Cells(rrow, z)
P1V1D1S1VN1PA12016Sep3 Next z
P1V2D2S2VN2PA22016Jan3 Cells(myrow, 7) = 2016
P1V2D2S2VN2PA22016Feb1 Cells(myrow, 8) = Cells(1, mmonth)
P1V2D2S2VN2PA22016Mar4 Cells(myrow, 9) = Cells(rrow, mmonth)
P1V2D2S2VN2PA22016Apr5 Next mmonth
P1V2D2S2VN2PA22016May6 Next rrow
P1V2D2S2VN2PA22016Jun7End Sub
P1V2D2S2VN2PA22016Jul8
P1V2D2S2VN2PA22016Aug7
P1V2D2S2VN2PA22016Sep6
oct nov dec now blank
and macro could be altered to ignore them
but in Nov there will be some oct figures so you need to run the macro again
T2 is now how many months
so third line becomes
for mmonth=7 to 7+cells(2,20)-1
note we now only print out jan to sept
NOW WE CAN LIMIT THE ROWS PROCESSED TO THE VALUE IN T5

<colgroup><col span="6"><col><col><col><col><col><col><col><col><col><col><col><col><col span="5"></colgroup><tbody>
</tbody>
 
Upvote 0
Thanks very much to both for your quick responses. WBD I've now got it working perfectly, turns out it was getting stuck because of one hidden bloated sheet killing the calcs. Thanks again, Iain
 
Upvote 0

Forum statistics

Threads
1,215,453
Messages
6,124,930
Members
449,195
Latest member
Stevenciu

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