Home » excel » Excel: define a VBA function to shorten PERCENTRANK

Excel: define a VBA function to shorten PERCENTRANK

Questions:

In Excel formula become often very long and, consequently, unreadable. For example my formula looks like this:

``````=PERCENTRANK([vol];[@vol])-PERCENTRANK([pos];[@pos])
``````

I would like to write just

``````=SCORE("vol", "pos")
``````

How can I create a user defined function from the original worksheet formula?

You can do this relatively easily using VBA’s `WorksheetFunction`. The most difficult part is actually getting the column of the `[@Range]` so you don’t have to enter it – but that’s not too complicated either.

In the VBE, create a new standard module and paste the following UDF:

``````Public Function SCORE(vol As Range, pos As Range) As Double

' We need to get the entire column of the table for each argument
Dim tbl As ListObject, volRng As Range, posRng As Range
Set tbl = vol.ListObject

Rem -> Table columns are relative to the table - not the worksheet
Set volRng = tbl.Range.Columns(vol.Column - tbl.Range.Cells(1).Column + 1)
Set posRng = tbl.Range.Columns(pos.Column - tbl.Range.Cells(1).Column + 1)

With Application.WorksheetFunction
SCORE = .PercentRank(volRng, vol) - .PercentRank(posRng, pos)
End With

End Function
``````

You have to keep in mind that table column numbers are not always the same as the worksheet’s (if your table doesn’t start in column A). So you essentially have to offset by the number of worksheet columns by subtracting the column from your arguments `vol` and `pos` from the column number of the first cell of the entire table `tbl.range.cells(1)`. Then you add one because columns numbers in VBA is “base 1”.

You will still have to send the range of the individual cell – so using string arguments are not going to do well here. With all that being said, your new worksheet formula would look like:

``````=SCORE([@vol],[@pos])
``````

or

``````=SCORE([@vol];[@pos])
``````

depending on if you separate arguments using `,` or `;`.