Excel UDF Tutorial
Microsoft Excel supports macros but it also supports library functions, known as User Defined Functions (UDF). Library functions are less risky than macros because they must return a value to a cell. This is a quick tutorial, mostly for my students, but as usual for anybody who’s interested.
Microsoft Excel User Defined Functions (UDFs) are different than standard VBA macros. They’re behavior is restricted. You can’t access other cells in a workbook, and may only return a value (also known as an expression) to the cell that uses the formula. That having been said, they can dramatically hide the complexity of mega-formulas and remove them from the editing control of users.
Here are the steps to configure your Excel 2007 environment to work with Visual Basic for Applications (VBA) and UDFs. They show you how to display the developer ribbon, open a module for editing, save VBA code into a library (*.xlam
file), and add the library file as an “Add-in” library to your Excel 2007 installation. The name of the library will be the same as the Workbook where you created it.
- Displaying Excel’s Developer Tab
There are four steps to make this visible. They are:
- Choose the Office Button. You’ll see the following:
- Click the Excel Options button.
- Click the Popular tab if not highlighted (it’s the default). Inside the right side pane, click the Show Developer tab in the Ribbon check box to enable it, and click the OK button to set it.
- Click the Developer ribbon tab. Click the left most icon to launch the Visual Basic Editor screen.
- Open a Module in the Visual Basic Editor by clicking the Insert menu item and choosing the Module element.
- Copy the following function definition into the open Module. The name of the UDF will be the case-sensistive name of the function in the VBA module. That means you’ll now have a newSerialDate function in your list of functions when you click the insert function button.
I struggled to come up with a simple function to illustrate this and how you debug UDFs. A word to the wise, you can’t use a numeric variable inside a MsgBox
by itself. If you attempt it, Excel will return a #Value!
error in the cell where you call the UDF. You must include a numeric variable as an argument (also known as a call parameter) to the CStr()
function. An example is: Cstr(myVariable)
. You call this sample function by entering:
=monthEnd(cell_reference) |
When you pass a date (actually an integer in the spreadsheet), the function handles it as a string. While no data type is assigned the dateIn
variable in the example, variables without an explicit data type are always of the Variant
data type. The Variant
data type is a master data type and can hold any other type, which makes it like the Object
data type in Java.
This program parses the string, then uses the DateSerial()
function to return it as a number. It’s critical to note that the last line returns the value in the newSerialDate
variable, and that variable must always be the function name. Place a single quote mark before all MsgBox()
function calls after verifying that the function works.
Public Function newSerialDate(dateIn) ' Define local variables. Dim day As String Dim month As String Dim year As String Dim startPosition As Integer Dim endPosition As Integer Dim length As Integer ' Initialize local variables and parse the month from the left. startPosition = 1 endPosition = InStr(startPosition, dateIn, "/") month = Left(dateIn, endPosition - 1) ' This is a debugging tool to track variables during execution. MsgBox ("Month [" + month + "]") ' Shift the start position and parse the day from the middle. startPosition = endPosition + 1 endPosition = InStr(startPosition, dateIn, "/") day = Mid(dateIn, startPosition, endPosition - startPosition) ' This is a debugging tool to track variables during execution. MsgBox ("Day [" + day + "]") ' Get the remainder of the string. startPosition = endPosition length = Len(dateIn) - startPosition year = Right(dateIn, length) ' This is a debugging tool to track variables during execution. MsgBox ("Year [" + year + "]") ' Return a value from a User Defined Function (UDF) by using ' the function name as the return variable. newSerialDate = DateSerial(year, month, day) End Function |
Aside from the fact that all this parsing isn’t really necessary because the problem is much simpler and cleaner. At least, it becomes so when you understand the breadth of built-in functions in VBA. You can solve the problem by designating the formal parameter as a Double
like the example below.
Function newSerialDate(dateIn As Double) newSerialDate = dateIn End Function |
Alternatively, you can accept a Variant
, which maps to a String
. Then, you convert it to a Date
like this:
Function newSerialDate(dateIn) newSerialDate = DateValue(dateIn) End Function |
- Create the following spreadsheet, the formula values are noted below the screen shot. You should be able to copy and past them into the spreadsheet. After you’ve created the spreadsheet, entering a new date in cell
A1
causes the UDF to run. When the UDF runs “as-is”, you’ll see message dialog boxes that show values set during runtime.
Spreadsheet Functions | |
---|---|
Cell | Formula |
A2 | =newSerialDate(A1) |
C1 | =VLOOKUP(TYPE(A1),$E$3:$F$7,MATCH("Meaning",$E$2:$F$2,FALSE)) |
C2 | =VLOOKUP(TYPE(A2),$E$3:$F$7,MATCH("Meaning",$E$2:$F$2,FALSE)) |
- You can now save this as an Add In library but comment out those debug
MsgBox()
function calls. Click the Office Button and click SaveAs in the menu, then accept Excel Workbook initially. When you get to the SaveAs dialog, choose Excel Add-In as the file type. Below is a screen capture of the drop down selection box.
- Open a new Excel Workbook. Click the Excel Options button. Click the Add-Ins tab. Inside the right side pane, make sure the Manage drop down says Excel Add-ins before you click the Go button.
- Check the Samplefunction check box as shown below. Samplefunction is the name of the Workbook that contains the module, and it is saved as an
*.xlam
file. Click the OK button to add the library. You’ve now created, and added an Add-In library to your new spreadsheet. It will create aSampleFunction.xlam
file in the users directory.
The file is found by default in:
C:\Users\UserName\AppData\Roaming\Microsoft\AddIns |
Ranjit asked how you could call a UDF from inside a module. In the answer noted below, I show how to do it with the Unary
function:
Function Unary(number As Integer) Unary = number + 1 End Function |
Then, enter the following ordinary Increment
macro:
Sub Increment() ActiveCell.FormulaR1C1 = Unary(ActiveCell.Value()) End Sub |
Enter a number in a cell, then navigate to Tools -> Macro -> Macros… and choose the increment
macro, which increments the value previously in the cell by calling the Unary
function.
As always, I hope this is helpful to a few folks.