+ Reply to Thread
Results 1 to 6 of 6

Query-Style Custom Function needs speed boost!

Hybrid View

  1. #1
    Registered User
    Join Date
    10-24-2007
    Posts
    5

    Query-Style Custom Function needs speed boost!

    I have created a custom function (GetData) that I use to pull data from a "database" (which I update in the Fin_Data tab). It works well, however the report I need requires that I use requires that I call this function in 10,000+ cells, and as a result the report takes over 4 hours to recalculate. I would really appreciate any help/advice/code-tweaks/changes that could be offered to cut down on this run-time, thanks in advance!



    I've included the function below and attached a sample spreadsheet with report to facilitate/encourage tinkering. The data source is normally ~11,000 rows and the report itself is 1,000 rows and has an additional 50 columns but has been reduced to accommodate the file size limitations to upload.



    Function GetData(IInum As String, Scenario As String, Version As String, FinCat As String, _
        FinType As String, Yr As String, Func As String, Acct As String, Region As String, OngComp As String, _
        RunInc As String, Vw As String, Mnth As String) As Double
    ' This is some help on this function!
    
        Application.Volatile (True)
    
        Dim FinalDataRow As Double, DataColumn As Double
        Dim IIidCol As Double, ScenarioCol As Double, VersionCol As Double, FinTypeACol As Double
        Dim FinTypeBCol As Double, YearCol As Double, FunctionCol As Double, AcctCol As Double
        Dim RegionCol As Double, OngCompCol As Double, RunIncCol As Double
        Dim PLViewCol As Double, CashViewCol As Double, CapViewCol As Double, BusUnitCol As Double
        Dim i As Integer, MnthNum As Integer
        
        With ThisWorkbook.Worksheets("Fin_Data")
            'Define Columns
            IIidCol = .Range("1:1").Find(What:="ITM_ID", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            ScenarioCol = .Range("1:1").Find(What:="SCENARIO_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            VersionCol = .Range("1:1").Find(What:="VERSION_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            FinCatCol = .Range("1:1").Find(What:="FIN_CAT_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            FinTypeCol = .Range("1:1").Find(What:="FIN_TYPE_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            YearCol = .Range("1:1").Find(What:="YR_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            FunctionCol = .Range("1:1").Find(What:="FXNL_AREA_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            AcctCol = .Range("1:1").Find(What:="ACCT_TYPE_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            RegionCol = .Range("1:1").Find(What:="RGN_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            OngCompCol = .Range("1:1").Find(What:="CPLT_ONG_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            RunIncCol = .Range("1:1").Find(What:="FIN_SUB_TYPE_NM", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            PLViewCol = .Range("1:1").Find(What:="PL_VW", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            CashViewCol = .Range("1:1").Find(What:="CASH_VW", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            CapViewCol = .Range("1:1").Find(What:="CAP_VW", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            BusUnitCol = .Range("1:1").Find(What:="Bus Unit", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            
            If Mnth = "Q1" Then
                DataColumn = .Range("1:1").Find(What:="Q1 Total", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            ElseIf Mnth = "Q2" Then
                DataColumn = .Range("1:1").Find(What:="Q2 Total", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            ElseIf Mnth = "Q3" Then
                DataColumn = .Range("1:1").Find(What:="Q3 Total", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            ElseIf Mnth = "Q4" Then
                DataColumn = .Range("1:1").Find(What:="Q4 Total", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            ElseIf Mnth > 0 And Mnth < 13 Then
                MnthNum = CInt(Mnth)
                DataColumn = MnthNum - 1 + .Range("1:1").Find(What:="JAN", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            Else 'Month # is invalid, give FY number
                DataColumn = .Range("1:1").Find(What:="FY Total", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, MatchByte:=False).Column
            End If
            FinalDataRow = .Cells(Application.Rows.Count, 1).End(xlUp).Row
            GetData = 0
            
            For i = 2 To FinalDataRow
                If .Cells(i, IIidCol).Value = IInum Or IInum = "ALL" Or .Cells(i, BusUnitCol).Value = IInum Then  'Check II Number
                    If .Cells(i, ScenarioCol).Value = Scenario Or Scenario = "ALL" Then  'Check Scenario
                        If .Cells(i, VersionCol).Value = Version Or Version = "ALL" Then  'Check Version
                            If .Cells(i, FinCatCol).Value = FinCat Or FinCat = "ALL" Then  'Check Financial Category (Dir, Indr, Res)
                                If .Cells(i, FinTypeCol).Value = FinType Or FinType = "ALL" Then  'Check Fin Type (Revenue, Save, Spend)
                                    If .Cells(i, YearCol).Value = Yr Or Yr = "ALL" Then  'Check Year
                                        If .Cells(i, FunctionCol).Value = Func Or Func = "ALL" Then  'Check Functional Area
                                            If .Cells(i, AcctCol).Value = Acct Or Acct = "ALL" Then  'Check Account
                                                If .Cells(i, RegionCol).Value = Region Or Region = "ALL" Then  'Check Region
                                                    If .Cells(i, OngCompCol).Value = OngComp Or OngComp = "ALL" Then  'Check Ongoing/Completion
                                                        If .Cells(i, RunIncCol).Value = RunInc Or RunInc = "ALL" Then  'Check Run-Rate/Incremental
                                                            If (Vw = "PL" And .Cells(i, PLViewCol).Value = 1) Or (Vw = "Cash" And .Cells(i, CashViewCol).Value = 1) Or (Vw = "Cap" And .Cells(i, CapViewCol).Value = 1) Then  'Check View to be shown
                                                                If (Vw = "Cap" And .Cells(i, AcctCol).Value Like "*Credit*") Then
                                                                    GetData = GetData - .Cells(i, DataColumn).Value
                                                                Else
                                                                    GetData = GetData + .Cells(i, DataColumn).Value
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next i
        End With
        
    End Function
    Attached Files Attached Files
    Last edited by cyber553; 08-12-2009 at 02:09 PM. Reason: Bad code formatting...

  2. #2
    Registered User
    Join Date
    08-20-2003
    Location
    Luton, England
    Posts
    63

    Re: Query-Style Custom Function needs speed boost!

    Your method is too complicated to check through in detail. I am very simple minded, you see

    Looking at your final worksheet, it is very similar in layout to many of the reports I had to produce. I usually used pivot tables (sometimes more than one) with VLOOKUP() to transfer data to the final sheet.

    This often needed extra calculated columns in the data to analyse the data to fit a PT.

    Not knowing your organisation setup etc. ........... I usually handled monthly reporting - doing the calculations once and distributing just the final reports.
    Regards
    BrianB
    Most problems are caused by starting from the wrong place.
    Use a cup of coffee to speed up all Windows processes.
    It's easy until you know how.
    -----------------------------------------

  3. #3
    Registered User
    Join Date
    10-24-2007
    Posts
    5

    Re: Query-Style Custom Function needs speed boost!

    Thanks Brian - I recognize that the data is very Pivot Table friendly, unfortunately my boss doesn't like how they look. While I also realize I could do SUMIFs based on a pivot, I'm still curious to know if anyone can think of a way to speed up my function (I was an engineer in college and still enjoy programming, so maybe now I'm just curious...).

  4. #4
    Registered User
    Join Date
    08-20-2003
    Location
    Luton, England
    Posts
    63

    Re: Query-Style Custom Function needs speed boost!

    Your boss does not need to see a pivot table.
    As stated, it is just used as a link to the properly formatted report.

  5. #5
    Registered User
    Join Date
    07-14-2009
    Location
    Brighton, England
    MS-Off Ver
    Excel 97
    Posts
    49

    Re: Query-Style Custom Function needs speed boost!

    I'm pondering that perhaps there is a workaround by reducing the number of cells you calculate from rather than changing the way you are doing so, however I'm not sure if its viable. I think this depends on whether or not you are normally modifying data or adding data.

    If you are adding data my thinking is perhaps that you can have the code only calculate the newly entered data. This could possibly be done by having a line at the end of the code which writes the number of rows which contained data when you ran that code to a cell and then calling on that cell's value at the start of your code to say which row to start calculating from.

    Then instead of summing/calulating all the data again e.g. A2+A3+A4+A5+A6 you add only the values from new data to the previously calculated values from the last time you ran the code e.g. (A2+A3+A4)+A5+A6.

    I am not sure how much data you add each time but this could reduce times needed to calculate drasticly provided you are not for example writing all the data calculated from in one or two big sessions.

    I'm a little better at understanding what I want to do and seeing novel workarounds than actually coding for them so I'm of little help there but hopefully there is some concept that can be drawn from this.

    Tom

  6. #6
    Registered User
    Join Date
    10-24-2007
    Posts
    5

    Re: Query-Style Custom Function needs speed boost!

    Brian - I appreciate your idea, I've written some other macros and used your strategy of utilizing VLOOKUPs (I use SUMIFs as they provide a bit more flexibility) to re-work my report(s). This has helped a ton - reporting can now be accomplished in about 15 minutes (a 94% improvement in the time required) - and this method seems to scale very well!

    To all those with a mind for code and who might be looking for a challenge, I'm still very curious if there might be ways to improve my GetData() function without introducing any new assumptions about how the data is sorted. I'm open to suggestions!

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1