3

I've read this post (use Cube Functions to get filtered dimensions) and it's quite helpful, but I want to add one more level of filtering.

So let's say my data looks like this in PowerPivot:

Month     Category     Product #     Revenue
January   Trucks       00000001      $50000
January   Trucks       00000002      $75000
January   Cars         00000005      $45000
January   Cars         00000008      $90000
January   Trucks       00000003      $10000
February  Cars         00000005      $10000

So basically I have cars or trucks and I want to return the top selling 2 products in each category for the month of January, February, etc.

I can easily find the top selling products if I only have one dimension filtered. So I can find the top selling products (trucks OR cars) in January. I used the method in the link I provided above. But I want to ADD one layer to that and say, find only the top selling trucks in January.

How do I go about doing this? I was hoping I could use "nonempty" and just add each filtered dimension/condition as I please, but maybe I don't get how the syntax should be.

Sultan of Swing
  • 430
  • 1
  • 6
  • 20
  • Hey, are you okay with a solution using a _[simple]_ custom VBA Function as opposed to multiple _[yucky]_ 4-dimensional cube functions? The function can be much more flexible, for example drawing data from a sheet, table, external file, etc, can provide as many or few results as you like, and could easily be adjusted to return monthly or annual top seller data (even weekly or daily if your data resolution is that fine). It's small and efficient enough for huge datasets. If that's potentially worth the bounty to you, let me know and I'll finish it up and send you a demo. – ashleedawg Nov 19 '17 at 04:23
  • [Image of possible Sample Syntax/Input/Output](https://image.ibb.co/eANfDR/Get_Top_Seller_syntax.jpg) ...Let me know if that could work for you and I can finalize. – ashleedawg Nov 19 '17 at 05:25

1 Answers1

2

I've created a custom function that should satisfy your requirements, therefore avoiding complicated design & maintenance of multiple nested cube functions needed for multi-dimensional reporting of your vehicle sales data.

A further advantage is that using this method, multiple variations can be easily created & edited to provide additional functionality for future reporting needs.

Usage is similar to Excel's built-in Rank function:

  • Call the function from a worksheet, specifying Month and/or Category, as well as the ranked result "rank number" that you need to have returned.

For example, to get the Top (#1) selling Truck for January, you could use formula:

=GetTopSeller ( "January", "Trucks", 1 )

or, to get the 10th best selling car for the month listed in cell A1, you could use formula:

=GetTopSeller ( A$1, "Cars", 10 )

The image below shows Syntax & Usage, as well as the sample dataset used in testing the function, and the example output based on the sample data*.

Syntax & Usage, Sample Data, Sample Output

Option Explicit
'Written by ashleedawg@outlook.com for https://stackoverflow.com/q/47213812

Const returnForNoValue = "" 'could be Null, 0, "(Not Found)", etc

Public cnn As New ADODB.Connection
Public rs As New ADODB.Recordset
Public strSQL As String

'Additional features which can be easily added on request if needed:
' add constants to specify Revenue or Product ID
' allow annual reporting
' allow list of vehicle types, months, etc
' make case insensitive


Public Function GetTopSeller(sMonth As String, sCategory As String, _
    sMonthRank As Integer) As Variant() '1=ProductID  2=Revenue

    Dim retData(1 To 2) As Variant

    strSQL = "Select Month, Category, [Product #], Revenue from [dataTable$] " & _
        "WHERE [Month]='" & sMonth & "' AND [Category]='" & sCategory & "' _
        Order by [Revenue] DESC"

    ' close Excel Table DB _before_ opening
    If rs.State = adStateOpen Then rs.Close
    rs.CursorLocation = adUseClient

    ' open Excel Table as DB
    If cnn.State = adStateOpen Then cnn.Close
    cnn.ConnectionString = "Driver={Microsoft Excel Driver " &
        "(*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=" & _
        ActiveWorkbook.Path & Application.PathSeparator & ActiveWorkbook.Name
    cnn.Open

    ' find appropriate data
    With rs
        .Open strSQL, cnn, adOpenKeyset, adLockOptimistic
        .MoveFirst
        If (.RecordCount <= 0) Or (.RecordCount < sMonthRank) _
            Or (sMonthRank = 0) Then GoTo queryError

        'move the Nth item in list
       .Move (sMonthRank - 1)
        retData(1) = ![Product #]
        retData(2) = !Revenue
    End With

    'return  value to the user or cell
    GetTopSeller = retData
Exit Function

queryError:
    'error trapped, return no values
    retData(1) = returnForNoValue
    retData(2) = returnForNoValue
    GetTopSeller = retData

End Function

Below are instructions for copying the function into your workbook, thus making it accessible as a worksheet function. Alternatively, the sample workbook could be saved as an Add-on, and then accessed from any workbook by creating a reference to the Add-on.


How to add the VBA function to your workbook:

  1. Select the VBA Code below, and hit Ctrl+C to copy.

  2. In your Excel workbook, and hit Alt+F11 to open the VBA Editor (aka VBE).

  3. Click the Insert menu in the VBE, and choose Module.

  4. Hit Ctrl+V to paste the code.

  5. Click the Debug menu in the VBE, and choose **Compile Project*. This checks the code for errors. Ideally "nothing" will happen, meaning it's error-free & good to go.

  6. Close the VBE window by clicking the the " " in the top-right corner of the VBE.

  7. Save the workbook. Your new function is now ready to use!


Usage of the function should be self-explanatory, but do not hesitate to contact me if you need a change, experience a problem, or have any questions.

Good Luck!

ashleedawg
  • 20,365
  • 9
  • 72
  • 105