![]() |
![]() |
|
|||||||
| Excel Questions All Excel/VBA questions - formulas, macros, pivot tables, general help, etc. Please post to this forum in English only. |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Join Date: Feb 2002
Posts: 76
|
I would like to know if it is possible to get user written functions to work with array formulas.
As an example, here is a Average function I wrote to illustrate the question: ---- Function MyAverage(DRange As Range) As Double Dim R As Object Dim Sum As Double Dim Count As Integer Count = 0: Sum = 0 For Each R In DRange Sum = Sum + R.Value Count = Count + 1 Next R MyAverage = Sum / Count End Function ---- Now, this works fine if I just use it in normal formulas, but it returns "#VALUE!" if I try to use it in an array formula. So, if column A = {1;1;2;2;1} and B = {1;4;2;9;10} I get the following results: As Array Formulas {=myaverage(IF(A1:A5=1,B1:B5))} = #VALUE! {=AVERAGE(IF(A1:A5=1,B1:B5))} = 3 As Normal Formulas =myaverage(B1:B5) = 5.2 =AVERAGE(B1:B5) = 5.2 How can I a user written function to work in an array formula? Or is it even possible? Thanks for any help John |
|
|
|
|
|
#2 |
|
MrExcel MVP
Join Date: Feb 2002
Location: Austin, Texas USA
Posts: 11,653
|
Take a look at the data types that you're passing as arguments to MyAverage...
{1;4;FALSE;FALSE;10} ...One of the causes of the #VALUE! error are incompatible data types (see the last entry in the Help Topic for "What does the error #VALUE! mean?"). The AVERAGE worksheet function ignores boolean values -- that's the "trick" behind {=AVERAGE(IF(A1:A5=1,B1:B5))}. How does your UDF handle boolean values? Sorry, I can't answer this question for you. I'm not a VBA guru. BTW, {=AVERAGE(IF(A1:A5=1,B1:B5))} is 5 instead of 3. Perhaps, you were using a different data set. [ This Message was edited by: Mark W. on 2002-03-08 15:11 ] |
|
|
|
|
|
#3 |
|
MrExcel MVP
Join Date: Feb 2002
Location: Bogota, Colombia
Posts: 11,771
|
Yes, it's possible. The "trick" is that you need to declare your function as a Variant.
Then, handle the info in a temporary array. But, if you need to do an AVERAGEIF function, I would go with Excel's built in way. Or you could just create an UDF that would "appear" as a SUMIF, but, really work as told. |
|
|
|
|
|
#4 |
|
Join Date: Feb 2002
Posts: 76
|
I tried the variant approach, and it still doesnt work. I simplified the code greatly to JUST focus on getting a function to work with an array formula:
---- Function MyAverage(DRange as Range)As Variant MyAverage = DRange.Range("A1").Value End Function ---- In this attempt, I am only trying to assign the function with the value of the 1st cell in the range. It works if I dont enter the function in an array formula, but as an array formula, I still get "#VALUE!" I'm totally stumped. (I am pressing CTRL-SHIFT-ENTER) |
|
|
|
|
|
#5 |
|
MrExcel MVP
Join Date: Feb 2002
Location: Portland, OR USA
Posts: 1,369
|
I was able to get it to work using the following code. Hope this helps!
[ This Message was edited by: Russell Hauf on 2002-03-09 15:23 ] |
|
|
|
|
|
#6 | |
|
MrExcel MVP
Join Date: Feb 2002
Location: Bogota, Colombia
Posts: 11,771
|
Quote:
But, i feel you need this:
Which works EXACTLY like SUMIF, no need to array enter. |
|
|
|
|
|
|
#7 |
|
Join Date: Feb 2002
Posts: 76
|
Thanks Russell!
I guess I am clueless as to how excel passes the array to the function. You are manipulating it as a 2 dimensional array, but to me it seems like it is 1 dimensional. In fact, with experimenting with your code I noticed that I could omit the "intj" inner loop and get the same result. (I replaced "DRange(intI,intJ)" with "DRange(IntI,1)") This tells me that the second dimension of the array only includes 1 field. But thats virtually a 1-dimensional array, right? As Mark W. mentioned, what is being passed to my function is {1;4;FALSE;FALSE;10}, or a 1d array. Why must it be manipulated as a 2d array? Anyways, your help was great. Thanks again! |
|
|
|
|
|
#8 | |
|
Join Date: Feb 2002
Posts: 76
|
Quote:
I changed ".Range("A1").Value" to simply ".Range("A1")" as you have above, and I still get the "#VALUE!" error when entered with CSE. Thanks for your help anyways! John |
|
|
|
|
|
|
#9 |
|
Banned
Join Date: Mar 2002
Posts: 1,582
|
Hi
You are asking for calculation slow down by using arrays (try Excels Database functions instead) but combining these with UDF's is not advised at all. You see an array formula must loop through all cells referenced and see if the criteria matches (its a bit like uisng a loop in VBA to find a value when the Find Method would get there 100+ times quicker). When you also combine a loop with an array formula it could be doing the same thing twice. I would strongly advise using the DAVERAGE function for your needs. These functions are at least 100 times faster then array formulas, agian because they are not restricted to having to loop. If however you do use a UDF just add a condition to check, like: Function MyAverage(DRangeComp As Range, vExclude, dAveRange As Range) As Double Dim R As Range Dim vVal Dim iAveCount As Integer For Each R In DRangeComp If R <> vExclude Then vVal = WorksheetFunction.Sum(dAveRange.Cells(R.Row, 1), vVal) iAveCount = iAveCount + 1 End If Next R MyAverage = vVal / iAveCount End Function _________________ Kind Regards Dave Hawley OzGrid Business Applications Microsoft Excel/VBA Training If it's Excel, then it's us! [ This Message was edited by: Dave Hawley on 2002-03-09 20:26 ] |
|
|
|
|
|
#10 | |
|
MrExcel MVP
Join Date: Feb 2002
Location: Portland, OR USA
Posts: 1,369
|
Quote:
Regards, Russell |
|
|
|
|
![]() |
| Bookmarks |
| Thread Tools | |
| Display Modes | |
|
|