Documentos de Académico
Documentos de Profesional
Documentos de Cultura
#NAME?
#NAME?
This formula works fine until somone comes along and says, "Hey, I've got a column of
500 values and I need to return an average of the smallest 200 and I might want to
change it to look at a variable number of smallest amounts."
2. It could potentially be an array of any amount from 1 to 500! So I'd have to create
500 different variations of the formula to handle them all (and that's just assuming only
the upper bound is changing and the lower bound is always 1).
3. Finally, even if I did attempt to create a b'zillion different formulas with all the different
possible arrays, I would still well exceed the 256 character limit for a cell formula once
the arrays started getting large.
At right you'll notice a column of 500 values and a cool array formula (in the yellow cell)
that will allow you to enter the lower and upper bound of an array to feed to the Small
function to be used in an Average calculation.
So how do we accomplish it?
At right you'll notice a column of 500 values and a cool array formula (in the yellow cell)
that will allow you to enter the lower and upper bound of an array to feed to the Small
function to be used in an Average calculation.
{=AVERAGE(SMALL(mybigrange,TRANSPOSE(ROW(OFFSET($A$1,Lbound-1,,Ubound-Lbound+1)))))}
In the yellow textbox above you can see the actual array formula that I used. Notice how
it allows me to change the lower and upper bound limits for the Small function "k" array.
If I wanted to, I could use 3 and 10 for my lower and upper bounds and it would return
the array {3,4,5,6,7,8,9,10} to use in the Small function to return just the 3 thru 10 largest
items for the average calculation.
Am I an array formula genius? Not hardly! If you want to learn something about
designing array formula logic read on...
Now let's disect this array formula to see how it's really working.
First of all let's keep in mind the original simple non-array formula:
=AVERAGE(SMALL(myrange,{1,2,3,4,5}))
We are quickly faced with the following dilema when trying to convert to the more
advanced function.
How can I make a formula generate a variable sized array to replace my hardcoded
array of: {1,2,3,4,5} ?
It would require that an array is built within the formula given variables for the upper and
lower bounds of the array. That is, assuming we want to stick with the SMALL function
since it so nicely avoids the duplication problem that a "<=" solution would run up against
if attempting to use a SUMIF function.
Ranges are good proxies for 1d and 2d arrays. Although generally, people are unaware
of the link between a 2d range and a 2d array. For instance in VBA I can create a 2d
array and set the values of a range equal to it in a single line of code. People often think
they have to step thru values of an array to assign the values to a range; not so.
So, if I wanted to create a variable sized array in a cell formula I could use the OFFSET
function to mimic the size of the array that I need.
Just entering this formula in a cell would return the single value of 1 (the first value of the
array). To see=COLUMN(OFFSET($A$1,,Lbound-1,,Ubound-Lbound+1))
the actual array of values, in the formula editor highlight everything to the
right of the = sign and press F9. You'll see the evaluation of the formula returns the array
{1,2,3,4,5}. Which is what we were feeding to the SMALL function by hardcode in the
simpler examples. You can test with the formula in the the blue cell at right. Remember,
at this point I'm just trying to build an array to feed to the SMALL function.
To create the array, I'm simply returning all the row numbers of a variable sized range (or
array). Although, using columns is limited in that it cannot exceed an array size of 256
due to the number of columns in Excel. If you don't need more than 256 array elements
then of course this will suffice. If you want the option to do more than 256 it's just a little
Just entering this formula in a cell would return the single value of 1 (the first value of the
array). To see the actual array of values, in the formula editor highlight everything to the
right of the = sign and press F9. You'll see the evaluation of the formula returns the array
{1,2,3,4,5}. Which is what we were feeding to the SMALL function by hardcode in the
simpler examples. You can test with the formula in the the blue cell at right. Remember,
at this point I'm just trying to build an array to feed to the SMALL function.
To create the array, I'm simply returning all the row numbers of a variable sized range (or
array). Although, using columns is limited in that it cannot exceed an array size of 256
due to the number of columns in Excel. If you don't need more than 256 array elements
then of course this will suffice. If you want the option to do more than 256 it's just a little
trickier.
At this point, you might suggest using rows instead. That's a good idea; only a vertical
range equates to a 2d array that we would need to transpose.
For instance:
To convert the=ROW(OFFSET($A$1,Lbound-1,,Ubound-Lbound+1))
2d array, we could use the TRANSPOSE function on the array to convert
it for use in our formula:
You'll notice with the transpose, this now returns {1,2,3,4,5} and we can use it in our
formula! So now I guess we have the ability to create a variable sized array without the
256 limitation. I s'pose (theorhetically speaking) in this example, the array could be as
large as 65536 elements. (Although, I haven't tested it for the 5,461element limitation
that MS speaks of in the knowledge base related to the TRANSPOSE function.)
So, if =TRANSPOSE(ROW(OFFSET($A$1,Lbound-1,,Ubound-Lbound+1)))
I replace the hard-coded array in my formula with the variable array logic I'd get
something like this:
If you enter this formula as it is, it won't return the correct result. In this case you do
actually have to use Ctrl-Shift-Enter and make it a true array formula. If you enter it
properly you'll see the array brackets { } appear around the formula and it will work. See
the difference between the non-array entered result and the array entered result at right?
This is an interesting exercise in array formula logic. Hopefully during the course of the
explanation it became clear that I am no genius with regard to array formulas, I have to
build them piece-by-piece. There's no way I would have been able to just sit down and
type out that array formula answer without building it piecemeal. Hopefully you will have
=AVERAGE(SMALL(mybigrange,TRANSPOSE(ROW(OFFSET($A$1,Lbound-1,,Ubound-Lbound+1)))))
learned that you can evaluate portions of formulas with the F9 key as you work to see
what the array logic is returning. This is a very helpful (to me, invaluable) tool when
trying to build array formula logic.
XL-Logic.com
Beware!
In this example I used the anchor cell $A$1 in much of my discussion above as the basis
for building a variable sized array. If I happen to insert a new top row, all the formulas
using the $A$1 reference will change to $A$2 which would actually damage the formula
result. Notice what happens to the blue cell formulas above if I insert a new row 1.
Yikes!
In this case, to be safe, it would probably be best to use an indirect reference to the
range A1. This way inserting rows at the top will not damage the formula results in any
way. I modified my formula in cells P39 and P40 to accomodate the INDIRECT
reference so inserting rows at row 1 won't damage my formula results.
This is one of the reasons why only truly advanced Excel users should mess around with
such formulas. Imagine if you picked up someone elses work and accidentally changed
all the formula results because you wanted to insert a few rows or columns. If you don't
know what to watch out for when you create these things the results could be
disasterous! But then again, the same could be said for VLOOKUP and HLOOKUP
functions and people use those things all the time.
Perhaps as a challenge you should think of a way to modify a VLOOKUP and HLOOKUP
function so they don't get destroyed when someone accidentally inserts a row or column
in the data table. I'd tell you how, but that's a whole other discussion...
5 things you should learn from this example:
From the Excel Help Topic for the "Small Worksheet Function"
SMALL(array,k)
Array is an array or range of numerical data for which you want to determine the k-th smallest value.
K is the position (from the smallest) in the array or range of data to return.
Remarks
If array is empty, SMALL returns the #NUM! error value.
If k ≤ 0 or if k exceeds the number of data points, SMALL returns the #NUM! error value.
If n is the number of data points in array, SMALL(array,1) equals the smallest value, and SMALL(array,n)
equals the largest value.
ay,n)
nge the
nds to
mall and
n my
.