Unpivoting data - tricky VBA

jgs224466

New Member
Joined
Dec 9, 2014
Messages
8
Hi Guys,

I am trying to do something that is far beyond my skill set.

I have attached a link to an excel file. The file has the following sheets:

original: One row of data for every opportunity, this is my source data
desired: This is what I am trying to achieve, each opportunity repeated for every month between Onhire and Offhire dates with the month and year values added in columns H and I
fiscal calendar: This is the company fiscal calendar I use to calculate hire days

Note: All columns from J-N are just formulas and won't cause me any issues, the issue I need solved is columns A-I and the repeated data.

Link to my excel file :) Opportunity Analysis.xlsx
 

Excel Facts

Does the VLOOKUP table have to be sorted?
No! when you are using an exact match, the VLOOKUP table can be in any order. Best-selling items at the top is actually the best.
Hello,

I suggest to save your file as .xlsm (so that it can contain macros), to insert a sheet "result" and to enter below formula, and to insert a general VBA module into which you insert below VBA code.

Then you should get:
MrExcel_Opportunity Analysis.xlsm
ABCDEFGHIJKLM
1RegionSectorOpportunityOnhire DateOffhire DateHire Duration)Value USDYearMonthHire Days in MonthDistributed ValueFirst Date of MonthLast Date of Month
2AustraliaEventsO656755701.06.202112.09.202110422500020216265625030.05.202126.06.2021
3AustraliaEventsO656755701.06.202112.09.2021104225000202174495192,3127.06.202109.08.2021
4AustraliaEventsO656755701.06.202112.09.2021104225000202181941105,7710.08.202128.08.2021
5AustraliaEventsO656755701.06.202112.09.2021104225000202191532451,9229.08.202102.10.2021
6AustraliaEventsO565445820.10.202126.10.202171624020211071624003.10.202130.10.2021
7AustraliaManufacturingO321765004.07.202116.08.20214484765202173771279,6627.06.202109.08.2021
8AustraliaManufacturingO321765004.07.202116.08.2021448476520218713485,3410.08.202128.08.2021
9AustraliaOil & GasO655822212.11.202114.02.20229512400202111162088,4231.10.202127.11.2021
10AustraliaOil & GasO655822212.11.202114.02.20229512400202112354568,4228.11.202101.01.2022
11AustraliaOil & GasO655822212.11.202114.02.2022951240020221283654,7402.01.202229.01.2022
12AustraliaOil & GasO655822212.11.202114.02.2022951240020222162088,4230.01.202226.02.2022
result
Cell Formulas
RangeFormula
A1:M12A1=opportunity_analysis(original!A1:G5,'fiscal calendar'!A1:F25)
Dynamic array formulas.


VBA Code:
Option Explicit

Enum input_columns
    in_LBound = 0
    in_Region
    in_Sector
    in_Opportunity
    in_Onhire_Date
    in_Offhire_Date
    in_Hire_Duration
    in_Value_USD
    in_UBound
End Enum

Enum fiscal_calendar_columns
    fc_LBound = 0
    fc_month_key
    fc_financial_year
    fc_financial_period
    fc_first_date
    fc_last_date
    fc_days_in_month
    fc_UBound
End Enum

Enum output_columns
    out_LBound = 0
    out_Region
    out_Sector
    out_Opportunity
    out_Onhire_Date
    out_Offhire_Date
    out_Hire_Duration
    out_Value_USD
    out_Year
    out_Month
    out_Hire_Days_in_Month
    out_Distributed_Value
    out_First_Date_of_Month
    out_Last_Date_of_Month
    out_UBound
End Enum

Function opportunity_analysis(vInput As Variant, _
    vFiscalYear As Variant) As Variant
Dim i                                  As Long
Dim j                                  As Long
Dim lvdim                              As Long
Dim k                                  As Long
Dim m                                  As Long
Dim oFC_Start                          As Object
Dim oFC_End                            As Object

With Application.WorksheetFunction
'Initialize
lvdim = 1
ReDim v(1 To out_UBound - 1, 1 To lvdim) As Variant
On Error GoTo ErrHdl
Set oFC_Start = CreateObject("Scripting.Dictionary")
Set oFC_End = CreateObject("Scripting.Dictionary")
i = 2
Do While vFiscalYear(i, fc_financial_year) <> ""
    oFC_Start(vFiscalYear(i, fc_financial_year) & "|" & _
        vFiscalYear(i, fc_financial_period)) = _
        vFiscalYear(i, fc_first_date)
    oFC_End(vFiscalYear(i, fc_financial_year) & "|" & _
        vFiscalYear(i, fc_financial_period)) = _
        vFiscalYear(i, fc_last_date)
    i = i + 1
Loop

i = 2
v(out_Region, 1) = "Region"
v(out_Sector, 1) = "Sector"
v(out_Opportunity, 1) = "Opportunity"
v(out_Onhire_Date, 1) = "Onhire Date"
v(out_Offhire_Date, 1) = "Offhire Date"
v(out_Hire_Duration, 1) = "Hire Duration)"
v(out_Value_USD, 1) = "Value USD"
v(out_Year, 1) = "Year"
v(out_Month, 1) = "Month"
v(out_Hire_Days_in_Month, 1) = "Hire Days in Month"
v(out_Distributed_Value, 1) = "Distributed Value"
v(out_First_Date_of_Month, 1) = "First Date of Month"
v(out_Last_Date_of_Month, 1) = "Last Date of Month"
j = 2
Do While vInput(i, in_Value_USD) <> ""
    k = 12 * (Year(vInput(i, in_Offhire_Date)) - Year(vInput(i, in_Onhire_Date))) + _
        Month(vInput(i, in_Offhire_Date)) - Month(vInput(i, in_Onhire_Date)) + 1
    For m = 1 To k
        v(out_Region, j) = vInput(i, in_Region)
        v(out_Sector, j) = vInput(i, in_Sector)
        v(out_Opportunity, j) = vInput(i, in_Opportunity)
        v(out_Onhire_Date, j) = vInput(i, in_Onhire_Date)
        v(out_Offhire_Date, j) = vInput(i, in_Offhire_Date)
        v(out_Hire_Duration, j) = vInput(i, in_Hire_Duration)
        v(out_Value_USD, j) = vInput(i, in_Value_USD)
        v(out_Year, j) = Year(DateSerial(Year(vInput(i, in_Onhire_Date)), _
            Month(vInput(i, in_Onhire_Date)) + m - 1, Day(vInput(i, in_Onhire_Date))))
        v(out_Month, j) = Month(DateSerial(Year(vInput(i, in_Onhire_Date)), _
            Month(vInput(i, in_Onhire_Date)) + m - 1, Day(vInput(i, in_Onhire_Date))))
        v(out_Hire_Days_in_Month, j) = .Min(v(out_Offhire_Date, j), oFC_End(v(out_Year, j) & "|" & v(out_Month, j))) - _
            .Max(v(out_Onhire_Date, j), oFC_Start(v(out_Year, j) & "|" & v(out_Month, j))) + 1
        v(out_Distributed_Value, j) = Round(v(out_Hire_Days_in_Month, j) * v(out_Value_USD, j) / _
            v(out_Hire_Duration, j), 2)
        v(out_First_Date_of_Month, j) = oFC_Start(v(out_Year, j) & "|" & v(out_Month, j))
        v(out_Last_Date_of_Month, j) = oFC_End(v(out_Year, j) & "|" & v(out_Month, j))
        j = j + 1
    Next m
    i = i + 1
Loop
ReDim Preserve v(1 To out_UBound - 1, 1 To j - 1) As Variant
opportunity_analysis = .Transpose(v)
End With
Exit Function
ErrHdl:
If Err.Number = 9 Then
   If j > lvdim Then
       'We need to increase last dimension
       lvdim = 10 * lvdim
       ReDim Preserve v(1 To out_UBound - 1, 1 To lvdim) As Variant
       Resume 'Back to statement which caused error
   End If
End If
'Other error - terminate
On Error GoTo 0
Resume
End Function

Regards,
Bernd
 
Upvote 0

Forum statistics

Threads
1,214,839
Messages
6,121,887
Members
449,057
Latest member
Moo4247

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