View Single Post
  #7   Report Post  
Posted to microsoft.public.excel.worksheet.functions
Harlan Grove[_2_] Harlan Grove[_2_] is offline
external usenet poster
 
Posts: 1,231
Default Lotus 123 @nsum function equivalent in excel(?)

"Rick Rothstein" wrote...
If you want something more "friendly" looking that the other solutions

....

And A LOT SLOWER if used frequently!

Function NSUM(Offset As Long, SkipAmount As Long, Rng As Range) As Double
* Dim X As Long
* With Rng
* * If .Rows.Count 1 And .Columns.Count 1 Then
* * * MsgBox "This function only works with single rows or single " & _
* * * * * * *"columns!", vbCritical, "Improper Range Specified"
* * End If

....

A classic and stupendous design MISTAKE!

NEVER have udfs display @#$% error dialogs! The problem is filling or
pasting formulas calling a udf into perhaps thousands of cells, but
for one reason or another, the filled or pasted formulas trigger the
error. Rather than Excel's recalc engine QUICKLY returning error
values, Excel would instead display the same STUPID error dialog for
EVERY cell that triggers the error.

For someone who supposedly knows something about VB, you don't seem to
have much practical experience with VBA udfs.

Then there's the question why this should be an error. It's useful to
know the particulars of the OP's question, which in this case means
having a 123 help file handy if not an actual installed 123 version. I
have both, and 123's @NSUM handles 3D(!!) ranges as 3rd argument. For
example, the 123 formula

@NSUM(0,3,A:C3..D:F11)

returns a numeric result, not an error. 123 iterates through its 3rd
argument in the same order as it would iterate through 3D arguments to
@NPV, which defaults to by row then by column then by sheet. Simple
enough to come up with a 2D equivalent udf, even extend it to handle
multiple area ranges. Note that 123 iterates through ranges by row
then by column, so For Each iteration through Excel ranges would
usually produce different results.


Function nsum(ByVal offs As Long, n As Long, a As Variant) As Variant
Dim x As Variant, k As Long, i As Long, j As Long, m As Long

k = -offs - 1

If offs < 0 Or n < 1 Then 'trap 123 error conditions and return
error values QUICKLY!
nsum = CVErr(xlErrNum)

ElseIf TypeOf a Is Range Then
For m = 1 To a.Areas.Count
For j = 1 To a.Areas(m).Columns.Count
For i = 1 To a.Areas(m).Rows.Count
k = k + 1
If k = 0 And k Mod n = 0 _
And VarType(a.Areas(m).Cells(i, j).Value2) = vbDouble Then
_
nsum = nsum + a.Areas(m).Cells(i, j).Value2
Next i
Next j
Next m

ElseIf IsArray(a) Then
For Each x In a
k = k + 1
If k = 0 And k Mod n = 0 And VarType(x) = vbDouble Then _
nsum = nsum + x
Next x

ElseIf offs = 0 And n = 1 Then 'return the same result as 123 for
degenerate ranges
nsum = a

End If

End Function


This still leaves support for variable number of arguments. You wanna
try that?