unpivot using nested headers (multiple columns)

oceanBreeze

New Member
Joined
Jul 18, 2019
Messages
2
Hello all,

I have searched for a few days now how to unpivot via VBA. While I have found some helpful information out there, my situation is unique in that the desire is to unpivot nested headers. Horizontal groupings have levels. For example, below is simple example of what I am trying to do. The Current state is nested header data. I want that data in flattened form so we can import into other tools such as a database or visualization tools.

I would prefer to do this via VBA and not power query or power bi. In the details below there are 2 header levels (Quarters and Forecast and yes they are different values), but it could potentially be groupings up to 6 or even 7.

Does ANYONE know how to do this via VBA with an ability to adjust to include more nested headers??? Please please help!


Current State:
QUARTER 1QUARTER 2QUARTER 3QUARTER 4QUARTER 1
4Q17 Forecast4Q17 Forecast4Q17 Forecast4Q17 Forecast1Q18 Forecast
Credit1124332342.00234.67234.2323.600.00
Equity189435.98628.00112374.290.00347.34
RiskAndCredit2548734.34872536.450.0021.96124.64
EstatePlanning0.007893425675.347678254.670.006591.00

<tbody style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline;">
</tbody>




Desired State:
Credit1124332342.00QUARTER 14Q17 Forecast
Equity189435.98QUARTER 14Q17 Forecast
RiskAndCredit2548734.34QUARTER 14Q17 Forecast
EstatePlanning0.00QUARTER 14Q17 Forecast
Credit1234.67QUARTER 24Q17 Forecast
Equity1628.00QUARTER 24Q17 Forecast
RiskAndCredit2872536.45QUARTER 24Q17 Forecast
EstatePlanning7893425675.34QUARTER 24Q17 Forecast
Credit1234.23QUARTER 34Q17 Forecast
Equity1112374.29QUARTER 34Q17 Forecast
RiskAndCredit20.00QUARTER 34Q17 Forecast
EstatePlanning7678254.67QUARTER 34Q17 Forecast
Credit123.60QUARTER 44Q17 Forecast
Equity10.00QUARTER 44Q17 Forecast
RiskAndCredit221.96QUARTER 44Q17 Forecast
EstatePlanning0.00QUARTER 44Q17 Forecast
Credit10.00QUARTER 11Q18 Forecast
Equity1347.34QUARTER 11Q18 Forecast
RiskAndCredit2124.64QUARTER 11Q18 Forecast
EstatePlanning6591.00QUARTER 11Q18 Forecast

<tbody style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; vertical-align: baseline;">
</tbody>

 

Excel Facts

Excel motto
Not everything I do at work revolves around Excel. Only the fun parts.
Hello. The following macro should be placed in the same workbook as your source data.

It will unpivot multiple levels of both column headers and row headers.

Please read the assumptions in the code and make sure you change the indicated line of code.

Best regards.

Code:
' Assumptions:
' 1 - First header row is row 1
' 2 - Can have multiple header rows
' 3 - First header column is column A
' 4 - Can have multiple header columns
' 5 - Block of cells to the left of the header rows
'     and above the header columns are empty (IMPORTANT!)

Public Sub UnpivotAllLevels()
  Const strSHEET_NAME = "Sheet1"   '<--- Set name of sheet with data (IMPORTANT!)
  Dim avntOutputData() As Variant
  Dim wksOutputSheet As Worksheet
  Dim intHeaderCols As Integer
  Dim lngHeaderRows As Long
  Dim lngOutputCols As Long
  Dim lngOutputRows As Long
  Dim lngOutputCol As Long
  Dim lngOutputRow As Long
  Dim intLastCol As Integer
  Dim lngLastRow As Long
  Dim blnError As Boolean
  Dim i As Integer
  Dim j As Long
  Dim k As Long
  
  On Error GoTo ErrorHandler
  Application.DisplayAlerts = False
  
  With ThisWorkbook.Sheets(strSHEET_NAME)
    lngHeaderRows = .Cells(1, "A").End(xlDown).Row - 1
    intHeaderCols = .Cells(1, "A").End(xlToRight).Column - 1
    lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
    intLastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
    lngOutputCols = lngHeaderRows + intHeaderCols + 1
    lngOutputRows = (lngLastRow - lngHeaderRows) * (intLastCol - intHeaderCols)
    ReDim avntOutputData(1 To lngOutputRows, 1 To lngOutputCols)
    
    For i = intHeaderCols + 1 To intLastCol
      For j = lngHeaderRows + 1 To lngLastRow
        lngOutputRow = lngOutputRow + 1
        lngOutputCol = 1
        For k = 1 To intHeaderCols
          avntOutputData(lngOutputRow, lngOutputCol) = .Cells(j, k).Value
          lngOutputCol = lngOutputCol + 1
        Next k
        avntOutputData(lngOutputRow, lngOutputCol) = .Cells(j, i).Value
        For k = 1 To lngHeaderRows
          lngOutputCol = lngOutputCol + 1
          avntOutputData(lngOutputRow, lngOutputCol) = .Cells(k, i).Value
        Next k
      Next j
    Next i
  End With
  
  Set wksOutputSheet = ThisWorkbook.Sheets.Add()
  With wksOutputSheet.Range("A1").Resize(lngOutputRows, lngOutputCols)
    .Value = avntOutputData
    .EntireColumn.AutoFit
  End With
  
ExitHandler:
  On Error Resume Next
  If blnError Then wksOutputSheet.Delete
  Application.DisplayAlerts = True
  Set wksOutputSheet = Nothing
  Exit Sub
  
ErrorHandler:
  MsgBox Err.Description, vbExclamation
  blnError = True
  Resume ExitHandler
End Sub
 
Upvote 0

Forum statistics

Threads
1,214,632
Messages
6,120,649
Members
448,975
Latest member
sweeberry

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