Excel 2007 Power Programming with VBA (Mr. Spreadsheets Bookshelf)

Emulating Excel's SUM Function

In this section, I present a custom function called MySum . Unlike the SimpleSum function listed in the previous section, the MySum function emulates Excel's SUM function (almost) perfectly .

Before you look at the code for MySum , take a minute to think about the Excel SUM function. It is, in fact, very versatile. It can have as many as 255 arguments (even "missing" arguments), and the arguments can be numerical values, cells , ranges, text representations of numbers , logical values, and even embedded functions. For example, consider the following formula:

=SUM(B1,5,"6",,TRUE,SQRT(4),A1:A5,D:D,C2*C3)

This perfectly valid formula contains all the following types of arguments, listed here in the order of their presentation:

The MySum function (see Listing 10-1) handles all these argument types.

CD-ROM  

A workbook containing the MySum function is available on the companion CD-ROM. The file is named  mysum function.xlsm .

Listing 10-1: MySum Function

Function MySum(ParamArray args() As Variant) As Variant ' Emulates Excel's SUM function ' Variable declarations Dim i As Variant Dim TempRange As Range, cell As Range Dim ECode As String Dim m, n MySum = 0 ' Process each argument For i = 0 To UBound(args) ' Skip missing arguments If Not IsMissing(args(i)) Then ' What type of argument is it? Select Case TypeName(args(i)) Case "Range" ' Create temp range to handle full row or column ranges Set TempRange = Intersect(args(i).Parent.UsedRange, _ args(i)) For Each cell In TempRange If IsError(cell) Then MySum = cell ' return the error Exit Function End If If cell = True Or cell = False Then MySum = MySum + 0 Else If IsNumeric(cell) Or IsDate(cell) Then _ MySum = MySum + cell End If Next cell Case "Variant()" n = args(i) For m = LBound(n) To UBound(n) MySum = MySum(MySum, n(m)) 'recursive call Next m Case "Null" 'ignore it Case "Error" 'return the error MySum = args(i) Exit Function Case "Boolean" ' Check for literal TRUE and compensate If args(i) = "True" Then MySum = MySum + 1 Case "Date" MySum = MySum + args(i) Case Else MySum = MySum + args(i) End Select End If Next i End Function

 

Figure 10-6 shows a workbook with various formulas that use SUM and MySum . As you can see, the functions return identical results.

Figure 10-6: Comparing SUM with MySum.

If you're interested in learning how this function works, create a formula that uses the function. Then, set a breakpoint in the code and step through the statements line by line. (See "Debugging Functions," later in this chapter.) Try this for several different argument types, and you'll soon have a good feel for how this function works. As you study the code for MySum , keep the following points in mind:

You might be curious about the relative speeds of SUM and MySum . MySum , of course, is much slower, but just how much slower depends on the speed of your system and the formulas themselves . On my system, a worksheet with 1,000 SUM formulas recalculates instantly. After I replace the SUM functions with MySum functions, it takes about eight seconds. MySum may be improved a bit, but it can never come close to SUM's speed.

By the way, I hope you understand that the point of this example is not to create a new SUM function. Rather, it demonstrates how to create custom worksheet functions that look and work like those built into Excel.

Категории