0

Similar to a question by Stephen Roy April 26, 2013, answered by Barry Houdini. I have a named range per this generic formula

{=IFERROR(INDEX(Range,SMALL(IF( MATCH(Range,Range,0)=ROW(INDIRECT("1:"&ROWS(Range))), MATCH(Range,Range,0)),ROW(INDIRECT("1:"&ROWS(Range))))),"")}

[obviously in 2003 I don't use IFERROR()]

"Range" itself is a named array formula.

The formula is used to pull unique entries from a range and arrange them at the 'top' of another 'range'. However, INDEX() appears to 'store' only a single value, not the array expected. Barry talked about wrapping the ROW() in another function to lose the {array}. It looks as though the first ROW() returns multiple values and works fine, it's the last ROW() which seems to be reduced to the first array entry only, thereby causing INDEX() to return only a single value. However, instead of trying to store this in memory, I select a multi-cell range for output, and use CSE, it works perfectly well. But I don't want to have to do that.

I've tried messing around with INDIRECT(), but can't get that to work at all.

Grateful for your thoughts folks, ian taylor

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138

2 Answers2

1

This might work for you. To return a list of unique values given your range x for example:

=LOOKUP(SMALL(IF(MATCH(x,x,0)=ROW(INDIRECT("1:"&ROWS(x))),MATCH(x,x,0)), ROW(INDIRECT("1:"&SUM(IF(FREQUENCY(MATCH(x,x,0),MATCH(x,x,0)),1))))), ROW(INDIRECT("1:"&ROWS(x))),x)

You could define this as a name called Unique and use it in other formulas eg =COUNTIF(x,Unique) returns an array of frequencies.

Addendum

Regarding INDIRECT/INDEX/ROW etc. here's my 2c (see also here). Function inputs and outputs can essentially be divided into three cases: single values, arrays or references. If a function input argument takes single values by default and an array is specified, then the result depends on the type of output of the function. If the output type of the function is:

A) a single value - an array of values is returned, one for each input value. This is the case for most functions eg =LOOKUP({1;2},{1;2;3},{"a";"b";"c"}) returns {"a";"b"}.

B) a reference - an array of references is returned. This is the case for INDIRECT/OFFSET. eg =INDIRECT("A1:A"&ROW()) returns a single element array containing a reference but this can raise errors in many functions as the references are not converted to values by default.

C) an array - a value or array is returned based on the first input of the function if evaluated normally and entered into a single cell. Or else an array is returned based on the first result for each input if entered into multiple cells. This is the case for INDEX which may return an array if one of the arguments is zero. For example =INDEX({1,2;3,4},0,{1;2}) returns {1;3} when evaluated in the formula bar, but {1;2} when array-entered into cells.

In fact Excel uses a variant data type that can take on any of these types so the details are a little more complex than this. Also there is the ability to modify arguments in place which may be why for example VLOOKUP behave like case C with arrays in the first argument but case A with the third argument.

Community
  • 1
  • 1
lori_m
  • 5,487
  • 1
  • 18
  • 29
-1

i tried this as a defined name say, "Unique_List" so that i can use it as a Data validation list, but when i add this defined name to the data validation list, it gives an error.

=LOOKUP(SMALL(IF(MATCH(x,x,0)=ROW(INDIRECT("1:"&ROWS(x))),MATCH(x,x,0)), ROW(INDIRECT("1:"&SUM(IF(FREQUENCY(MATCH(x,x,0),MATCH(x,x,0)),1))))), ROW(INDIRECT("1:"&ROWS(x))),x)

where x is my range.

i tried transposing this formula to get the values comma-separated rather than semicolon-separated, but data validation list doesnt seem to work.

=TRANSPOSE(LOOKUP(SMALL(IF(MATCH(x,x,0)=ROW(INDIRECT("1:"&ROWS(x))),MATCH(x,x,0)), ROW(INDIRECT("1:"&SUM(IF(FREQUENCY(MATCH(x,x,0),MATCH(x,x,0)),1))))), ROW(INDIRECT("1:"&ROWS(x))),x))

Kindly advice.

sifar
  • 1,086
  • 1
  • 17
  • 43