Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Why am I not just using a Pivot Table / Database?

  • a) I've never ever used either before. And I don't have time to learn how before this project needs to actually be finished.
  • b) The final output is going to be a report for the Company Directors. As such, the flexibility of choosing which bits of data to output in what format in which table on what sheet is highly useful.

I already have my raw data aggregated, validated and consistently formatted in a single table. This part of the Macro takes each line and:

  • Determines which Financial Adviser is involved.
  • Determines what type of business is involved (investments, insurance, premiums, invoives, management fees etc.).
  • Determines which Financial Service provider is involved, if any (e.g. insurance providers, fund managers etc.).
  • Determines which month the business was transacted in.

then aggregates the results into a 4-D array (Advisers, BusinessType, Providers, Month).

I am aware that alongside a pivot table, learning how to use dictionaries and an actual database would be useful. Given that those weren't options here, is there any other feedback you can offer?

N.B. I've tried to make my macro as robust as possible, so there's a lot of Find/Check position of <heading> in <Table/Array>. This report is going to primarily be used by other people, and absolutely has to be 100% accurate, so I feel it's warranted.

Also, some of the basic methods aren't included here. You can safely assume that they do what they say they do.

Module 10: M10_Allocate_Business

Public Sub AllocateBusinessToAdvisersProvidersMonthsAndMetrics()

        PutSheetDataInArray WbAdviserReport, WsAggregatedData, ArrAggregatedData

        FindAllAdvisers

        FindAllProviders

    ReDim ArrAllocatedBusiness(0 To UBound(ArrAdvisers), 0 To ColMetrics.Count, 0 To UBound(ArrProviders), 0 To 13)

        PrepareAllocatedBusinessHeadings

        AllocateAggregatedBusiness

End Sub

Public Sub FindAllAdvisers()

    Dim arrHeadingsRow As Variant

    Dim ixColumnHeading As Long

    Dim arrAdviserColumn As Variant

        arrHeadingsRow = RowFrom2dArray(ArrAggregatedData, 1)
        ixColumnHeading = IndexInArray1d(arrHeadingsRow, "Adviser")
        arrAdviserColumn = ColumnFrom2dArray(ArrAggregatedData, ixColumnHeading)

        ArrAdvisers = ListOfUniqueValues(arrAdviserColumn, True)

End Sub

Public Sub FindAllProviders()

    Dim arrHeadingsRow As Variant

    Dim ixColumnPosition As Long

    Dim arrProviderColumn As Variant

        arrHeadingsRow = RowFrom2dArray(ArrAggregatedData, 1)
        ixColumnPosition = IndexInArray1d(arrHeadingsRow, "Life Co")
        arrProviderColumn = ColumnFrom2dArray(ArrAggregatedData, ixColumnPosition)

        ArrProviders = ListOfUniqueValues(arrProviderColumn, True)

End Sub

Public Sub PrepareAllocatedBusinessHeadings()

    Dim i As Long, j As Long, k As Long, l As Long

    Dim LB1 As Long, UB1 As Long
    Dim LB2 As Long, UB2 As Long
    Dim LB3 As Long, UB3 As Long
    Dim LB4 As Long, UB4 As Long

        AssignArrayBounds ArrAllocatedBusiness, LB1, UB1, LB2, UB2, LB3, UB3, LB4, UB4

        For i = LB1 + 1 To UB1
            ArrAllocatedBusiness(i, 0, 0, 0) = ArrAdvisers(i)
        Next i

        For i = LB1 + 1 To UB1
        For j = LB2 + 1 To UB2
            ArrAllocatedBusiness(0, j, 0, 0) = ColMetrics(j)
            ArrAllocatedBusiness(i, j, 0, 0) = ArrAdvisers(i) & Hyphen & ColMetrics(j)
        Next j
        Next i

        For i = LB1 + 1 To UB1
        For j = LB2 + 1 To UB2
        For k = LB3 + 1 To UB3
            ArrAllocatedBusiness(0, 0, k, 0) = ArrProviders(k)
            ArrAllocatedBusiness(i, j, k, 0) = ArrAdvisers(i) & Hyphen & ColMetrics(j) & Hyphen & ArrProviders(k)
        Next k
        Next j
        Next i

        For l = LB4 + 1 To UB4 - 1
            ArrAllocatedBusiness(0, 0, 0, l) = DateValue("01/" & Right("0" & Month(l), 2) & "/" & Year(Date))
        Next l

        ArrAllocatedBusiness(0, 0, 0, UB4) = "YTD"

End Sub

Public Sub AllocateAggregatedBusiness()

    Dim i As Long, j As Long, k As Long

    Dim row As Long

    Dim lngFirstRow As Long, lngFinalRow As Long '/ Of the AggregatedData

    Dim strTypeOfBusiness As String

    Dim ixAdviserColumn     As Long
    Dim ixProviderColumn    As Long

    Dim ixDateSubmittedColumn       As Long
    Dim ixInvestmentAmountColumn    As Long
    Dim ixDateMoneyReceivedColumn   As Long
    Dim ixMonthlyPremiumColumn      As Long
    Dim ixSinglePremiumColumn       As Long
    Dim ixCommissionDueColumn       As Long
    Dim ixCommissionPaidColumn      As Long
    Dim ixDateCommissionPaidColumn  As Long
    Dim ixFirstMonthColumn          As Long

    Dim ixAdviser   As Long
    Dim ixMetric    As Long
    Dim ixProvider  As Long
    Dim ixMonth     As Long

    Dim varSearchValue As Variant

    Dim strErrorMessage As String

        DetermineColumnPositions ixAdviserColumn, ixProviderColumn, ixDateSubmittedColumn, ixInvestmentAmountColumn, ixDateMoneyReceivedColumn, ixMonthlyPremiumColumn, _
                                    ixSinglePremiumColumn, ixCommissionDueColumn, ixCommissionPaidColumn, ixDateCommissionPaidColumn, ixFirstMonthColumn

            AssignArrayBounds ArrAggregatedData, lngFirstRow, lngFinalRow
            lngFirstRow = lngFirstRow + 2

            For row = lngFirstRow To lngFinalRow

                strTypeOfBusiness = TypeOfBusiness(row, ixDateSubmittedColumn, ixInvestmentAmountColumn, ixDateMoneyReceivedColumn, ixMonthlyPremiumColumn, ixSinglePremiumColumn, _
                                ixCommissionDueColumn, ixCommissionPaidColumn, ixDateCommissionPaidColumn, ixFirstMonthColumn)

                Select Case strTypeOfBusiness

                    Case Is = ColMetrics.Item("Investment Amount")
                        DetermineAllocatedBusinessIndexes row, ixAdviser, ixAdviserColumn, ixMetric, ixInvestmentAmountColumn, ixProvider, ixProviderColumn, ixMonth, ixDateSubmittedColumn, strTypeOfBusiness
                        AllocateBusiness ixInvestmentAmountColumn, ixAdviser, ixMetric, ixProvider, ixMonth, row

                    Case Is = ColMetrics.Item("Single Premium")
                        DetermineAllocatedBusinessIndexes row, ixAdviser, ixAdviserColumn, ixMetric, ixSinglePremiumColumn, ixProvider, ixProviderColumn, ixMonth, ixDateSubmittedColumn, strTypeOfBusiness
                        AllocateBusiness ixSinglePremiumColumn, ixAdviser, ixMetric, ixProvider, ixMonth, row

                    Case Is = ColMetrics.Item("Monthly Premium")
                        DetermineAllocatedBusinessIndexes row, ixAdviser, ixAdviserColumn, ixMetric, ixMonthlyPremiumColumn, ixProvider, ixProviderColumn, ixMonth, ixDateSubmittedColumn, strTypeOfBusiness
                        AllocateBusiness ixMonthlyPremiumColumn, ixAdviser, ixMetric, ixProvider, ixMonth, row

                    Case Is = ColMetrics.Item("Invoice")
                        DetermineAllocatedBusinessIndexes row, ixAdviser, ixAdviserColumn, ixMetric, ixCommissionDueColumn, ixProvider, ixProviderColumn, ixMonth, ixDateSubmittedColumn, strTypeOfBusiness
                        AllocateBusiness ixCommissionDueColumn, ixAdviser, ixMetric, ixProvider, ixMonth, row

                    Case Is = ColMetrics.Item("Recurring")
                        For i = 1 To 12
                            ixMonth = i
                            DetermineAllocatedBusinessIndexes row, ixAdviser, ixAdviserColumn, ixMetric, ixFirstMonthColumn, ixProvider, ixProviderColumn, ixMonth, ixDateSubmittedColumn, strTypeOfBusiness
                            AllocateBusiness ixFirstMonthColumn, ixAdviser, ixMetric, ixProvider, ixMonth, row
                        Next i

                End Select

            Next row

End Sub

Public Function TypeOfBusiness(ByVal row As Long, ByRef ixDateSubmittedColumn As Long, ByRef ixInvestmentAmountColumn As Long, ByRef ixDateMoneyReceivedColumn As Long, _
                                    ByRef ixMonthlyPremiumColumn As Long, ByRef ixSinglePremiumColumn As Long, ByRef ixCommissionDueColumn As Long, _
                                    ByRef ixCommissionPaidColumn As Long, ByRef ixDateCommissionPaidColumn As Long, ByRef ixFirstMonthColumn As Long) As String

    Dim strBusiness     As String
        strBusiness = ""

    Dim bDateSubmittedIsPresent As Boolean
    Dim bSubmittedAmountIsPresent As Boolean
    Dim bMultipleBusinessTypesArePresent As Boolean
    Dim bRecurringBusinessIsPresent As Boolean
    Dim bCommissionIsPresent As Boolean

    Dim bValuePresent As Boolean

    Dim varElement As Variant

    Dim i As Long

    Dim arrAmountColumns As Variant
        arrAmountColumns = Array()
    ReDim arrAmountColumns(1 To 3, 1 To 2)
        arrAmountColumns(1, 1) = ixInvestmentAmountColumn
        arrAmountColumns(1, 2) = ColMetrics.Item("Investment Amount")

        arrAmountColumns(2, 1) = ixSinglePremiumColumn 
        arrAmountColumns(2, 2) = ColMetrics.Item("Single Premium")

        arrAmountColumns(3, 1) = ixMonthlyPremiumColumn
        arrAmountColumns(3, 2) = ColMetrics.Item("Monthly Premium")

    Dim LB1 As Long, UB1 As Long
        AssignArrayBounds arrAmountColumns, LB1, UB1


        varElement = ArrAggregatedData(row, ixDateSubmittedColumn)
        bDateSubmittedIsPresent = (IsDate(varElement) And Not IsEmpty(varElement))


        bSubmittedAmountIsPresent = False
        For i = LB1 To UB1

            varElement = ArrAggregatedData(row, arrAmountColumns(i, 1))
            bValuePresent = (IsNumeric(varElement) And Not IsEmpty(varElement) And varElement <> 0)
            If bValuePresent And bSubmittedAmountIsPresent Then bMultipleBusinessTypesArePresent = True
            If bValuePresent And Not bSubmittedAmountIsPresent Then bSubmittedAmountIsPresent = True

            If bValuePresent Then strBusiness = arrAmountColumns(i, 2)

        Next i


        For i = ixFirstMonthColumn To ixFirstMonthColumn + 11

            varElement = ArrAggregatedData(row, i)
            If (IsNumeric(varElement) And Not IsEmpty(varElement) And varElement <> 0) Then bRecurringBusinessIsPresent = True

        Next i
        If bRecurringBusinessIsPresent Then strBusiness = ColMetrics.Item("Recurring")


        varElement = ArrAggregatedData(row, ixCommissionDueColumn)
        bCommissionIsPresent = (IsNumeric(varElement) And Not IsEmpty(varElement) And varElement <> 0)
        If Not (bSubmittedAmountIsPresent Or bRecurringBusinessIsPresent) And bCommissionIsPresent Then strBusiness = ColMetrics.Item("Invoice")

        CheckErrorConditionsBusinessType row, bDateSubmittedIsPresent, bSubmittedAmountIsPresent, bMultipleBusinessTypesArePresent, bRecurringBusinessIsPresent, bCommissionIsPresent

        TypeOfBusiness = strBusiness

End Function

Public Sub CheckErrorConditionsBusinessType(ByVal row As Long, ByVal bDateSubmittedIsPresent As Boolean, ByVal bSubmittedAmountIsPresent As Boolean, _
                                            ByVal bMultipleBusinessTypesArePresent As Boolean, ByVal bRecurringBusinessIsPresent As Boolean, ByVal bCommissionIsPresent As Boolean)
    Dim bError As Boolean

    Dim strErrorMessage As String

    '/ Check for: Multiple types of submitted business, submitted and recurring, submitted without date, no business at all

        bError = False

        If bMultipleBusinessTypesArePresent _
            Then
                bError = True
                strErrorMessage = strErrorMessage & "Found Multiple Types of Submitted Business on line: " & row
        End If

        If bSubmittedAmountIsPresent And bRecurringBusinessIsPresent _
            Then
                bError = True
                strErrorMessage = strErrorMessage & "Found Submitted and Recurring Business on line: " & row
        End If

        If Not (bSubmittedAmountIsPresent Or bRecurringBusinessIsPresent Or bCommissionIsPresent) _
            Then
                bError = True
                strErrorMessage = strErrorMessage & "Could not find any submitted or recurring business on line: " & row
        End If

        If bSubmittedAmountIsPresent And Not bDateSubmittedIsPresent _
            Then
                bError = True
                strErrorMessage = strErrorMessage & "No Date Submitted for business on line: " & row
        End If

        If bError = True Then ErrorMessage strErrorMessage

End Sub

Public Sub DetermineAllocatedBusinessIndexes(ByVal row As Long, ByRef ixAdviser As Long, ByRef ixAdviserColumn As Long, ByRef ixMetric As Long, ByRef ixMetricColumn As Long, _
                                                ByRef ixProvider As Long, ByRef ixProviderColumn As Long, ByRef ixMonth As Long, ByRef ixDateColumn As Long, ByRef strTypeOfBusiness As String)
    Dim i As Long

    Dim varSearchValue As Variant

    Dim strErrorMessage As String

    Dim lngDimension As Long

    Dim arrMetrics As Variant
        arrMetrics = Array()
    ReDim arrMetrics(1 To ColMetrics.Count)
        For i = 1 To ColMetrics.Count
            arrMetrics(i) = ColMetrics(i)
        Next i

        varSearchValue = ArrAggregatedData(row, ixAdviserColumn)
        ixAdviser = IndexInArray1d(ArrAdvisers, varSearchValue)

        varSearchValue = ColMetrics.Item(strTypeOfBusiness)
        ixMetric = IndexInArray1d(arrMetrics, varSearchValue)

        varSearchValue = ArrAggregatedData(row, ixProviderColumn)
        ixProvider = IndexInArray1d(ArrProviders, varSearchValue)


        Select Case strTypeOfBusiness

            Case Is <> ColMetrics.Item("Recurring")
                ixMonth = 0
                varSearchValue = ArrAggregatedData(row, ixDateColumn)
                ixMonth = Month(varSearchValue)
                If ixMonth = 0 _
                    Then
                        strErrorMessage = "Could not determine month of " & varSearchValue & " on row: " & row
                        ErrorMessage strErrorMessage
                End If

            Case Is = ColMetrics.Item("Recurring")
                '/ do nothing

        End Select

End Sub

Public Sub AllocateBusiness(ByRef ixBusinessColumn As Long, ByRef ixAdviser As Long, ByRef ixMetric As Long, ByRef ixProvider As Long, ByRef ixMonth As Long, ByVal row As Long)

    Dim i As Long, j As Long, k As Long

    Dim strErrorMessage As String

    Dim dblCurrentValue As Double
    Dim dblAdditionalValue As Double
    Dim dblNewValue As Double

        dblCurrentValue = ArrAllocatedBusiness(ixAdviser, ixMetric, ixProvider, ixMonth)

        dblAdditionalValue = ArrAggregatedData(row, ixBusinessColumn)

        dblNewValue = dblCurrentValue + dblAdditionalValue

        ArrAllocatedBusiness(ixAdviser, ixMetric, ixProvider, ixMonth) = dblNewValue

End Sub
share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.