Excel Search returns #Value, but embedded in "Lookup" it works - why? - excel

This links to question 12299700 - I want to understand why SEARCH returns #Value when used alone but works when embedded into LOOKUP, and how I can make it work alone:
In Cell A1 I have a string of text: "This is some sample text"
In Cells D1:D4 I have words: "text, sample1, sample2, string" (all in separate cells)
I want to see if my string contains any of the words in my range - I don't need the matching word/s returned.
Using the Search function in any empty cell in Row 1 =SEARCH($D$1:$D$4,A1), returns 22. Good!
Using this in any other row returns #VALUE. Why?
If I keep my formula in Row 1, but move my range of words down to D2:D5, I get #Value. Why?
How can I make SEARCH work for my cell and ranges, in any cell?
(From the answer to question 12299700 I know I can use this formula to return the matched text, in any cell of the spreadsheet: =LOOKUP(2^15,SEARCH($D$1:$D$4,A1),$D$1:$D$4) - this includes a term that gives #VALUE on its own ... intriguing).
First question asked on Stackoverflow - feedback appreciated.

The function SEARCH returns #VALUE if the searched string was not found within the text. The function SEARCH expect only one searched string. It is not a array function itself. So if it gets a range as searched string, it uses only one of these range values as searched string. Which one it is, depends on the position of the formula.
Within LOOKUP the case is completely different. LOOKUP is an array formula itself. It gets the SEARCH($D$1:$D$4,$A$1) as { SEARCH($D$1,$A$1), SEARCH($D$2,$A$1), SEARCH($D$3,$A$1), SEARCH($D$4,$A$1) } which results in a array like { #VALUE, 21, #VALUE, 21 } depending of if SEARCH finds the string or not. That LOOKUP even works with such an array is strange. Normally it needs a sorted array. But it works and gets the last value which is lower or equal than the searched value.
If you need to use SEARCH like an array formula outside a native array formula, then you have to create this array context by entering the formula with [CTRL]+[SHIFT]+[ENTER] instead of only [ENTER]. The formula gets then curly braces around it.
In my example I have created such a formula in Cell E10.
If you are interested in how formulas work, you should often click fx and look how the single parameters comes through. And you should often use Evaluate Formula on the Formulas tab, in the Formula Auditing group.

What happens is that SEARCH is being used in an array form and is outputting in a linear form (non-array).
So, what happens in row 1 is that you're actually doing:
=SEARCH($D$1,A1)
Because evaluating a linear formula with an array tends to take the value from the array in the same row/column depending on the situation. So that means the above is looking for text in A1 which can be found.
On the second row, you will get:
=SEARCH($D$2,A1)
Which means it is searching for sample1 from A1 and since it cannot be found, you get #VALUE!.
To evaluate an array formula as an array, you will have to use Ctrl+Shift+Enter instead of pushing Enter after typing in the formula. Now the problem is that the formula above will return the same thing if you use only 1 cell...
If you want to see if your string contains any of the words in your range (and it's not important to know what word was found), then you will have to use another function along with SEARCH, for example, SUM and ISNUMBER and evaluating it as an array formula:
=SUM(ISNUMBER(SEARCH($D$1:$D$4,A1)))
And if you get a number above 0, you know there's at least 1 word in the text. Maybe to make the output more explicit:
=IF(SUM(ISNUMBER(SEARCH($D$1:$D$4,A1)))>0, "Word(s) found!", "No words found...")
If you want to know what word was found, you will have to use it as a normal formula and drag it down:
The reason why it works in VLOOKUP is that this function actually expects an array as the second parameter and since SEARCH is returning an array, well, that works out just well.
Also, you can view how functions work by clicking on the cell with the function, then do to 'Formulas' in the menu bar and clicking on 'Evaluate formula':
From there you can see if something is being evaluated as a linear or array formula and see how cell references are being substituted with the actual values.

Related

Same formula, different result

The formula is exactly the same in both yellow cells. both are text.
Why is the result different?
Here is the formula:
=IF(ISNUMBER(SEARCH("b",A1:A4)),"bb",IF(ISNUMBER(SEARCH("d",A1:A4)),"cc","ee"))
With some chages, still same problem. I don't understand.
The function SEARCH returns a result for every cell in the given range (A1:A4). To get only one result, you can wrap it with OR to check whether any cell contains the text you are searching for.
=IF(OR(ISNUMBER(SEARCH("b",A1:A4))),"bb",IF(OR(ISNUMBER(SEARCH("d",A1:A4))),"cc","ee"))
Or just search for one cell at a time:
=IF(ISNUMBER(SEARCH("b",A1)),"bb",IF(ISNUMBER(SEARCH("d",A1)),"cc","ee"))

How to define a range, using an Excel formula

In order to do some calculations on averages and differences of values in columns, I've defined a name, based on a range, but it seems to be completely going berserk:
I have a cell (D13), defined as Header_First _Answer, which contains the title of the column, and I have a value (currently being 69), which contains the number of entries, called Total_Count.
I've defined the entries of that column as another name: "All_First_Answered_Dates", defined as =OFFSET(Header_First_Answer;1;0):OFFSET(Header_First_Answer;Total_Count;0) (start by the first entry under Header_First_Answer, take up to 69 entries, and define a range out of this).
In cell G5, I'm using that name in order to do some calculations (calculating averages), but this seems not to work (there is a #Value error).
After second comment from Rory: G5 formula and first formula evaluation result:
Formula:
=AVERAGE(IF(ISBLANK(All_First_Answered_Dates);TODAY();All_First_Answered_Dates) - All_Start_Dates)
First evaluation result:
=AVERAGE(IF(ISBLANK(#Value!);TODAY();All_First_Answered_Dates) - All_Start_Dates)
Hence, my conclusion:
After some checking I've found out that this is due to the name "All_First_Answered_Dates", which seems to be interpreted one time too many (or how do I explain this):
In different cells, I've entered the formula =OFFSET(Header_First_Answer;1;0):OFFSET(Header_First_Answer;Total_Count;0) (which is exactly the meaning of "All_First_Answered_Dates"), and every time, using the Evaluate Formula feature, I see that the last but one result is correct: $D$14:$D$82. However, after that, another evaluation is done, turning this value into 43283 (in case the formula is entered in "J14"), 43300 (in case the formula is entered in "J15"), ..., and in case I enter this formula in a cell with row number lower than 14, I have the error value #Value (which explains the wrong result in cell G5).
If I simply put the formula =$D$14:$D$82 in any of the mentioned cells, then the content of some cells in column D are shown (which are dates, not values like 43283 or 43300).
It appears that declaring a range as =x:y, where x and y are formula results, is not working.
Does anybody know how I can define a range as a formula, which I can then use in order to define in a name?
I can imagine my explanation being quite complicated without an image, hence the attached screenshot. In there:
In cell J13, there is the formula =OFFSET(Header_First_Answer;1;0):OFFSET(Header_First_Answer;Total_Count;0).
In cell J14, there is the same formula.
In cell K14, there is the formula =$D$14:$D$82.
For completion purposes, hereby a screenshot of the name manager, containing both mentioned names (the ones, selected in the name manager):
Edit after first comment:
The idea behind the range is the following:
1. Take the first row under Header_First_Answer, do not take any other column : OFFSET(Header_First_Answer;1;0)
2. Take the Total_Count's row under Header_First_Answer, do not take any other column : OFFSET(Header_First_Answer;Total_Count;0)
3. Define a range, based on those two cells, by putting a semicolon between them.
I was not aware of the height and width features of the Offset() worksheet function. I've implemented them, which makes the formulas much easier.
Unfortunately the problem still persists.
Thanks in advance
Dominique
I've just found the answer of what was going wrong:
The formula was meant to be an array formula. Something went wrong and while trying to debug, I accidently re-formatted the formula into a normal formula (I must have pressed "ENTER" instead of "Ctrl" + "Shift" + "ENTER") at some point.
I have re-applied array formula (using "Ctrl" + "Shift" + "ENTER"), getting a formula like:
{=AVERAGE(IF(ISBLANK(All_First_Answered_Dates);TODAY();All_First_Answered_Dates) - All_Start_Dates)}
(mind the braces {, })
Now everything is working fine.

COUNTIFS with unique values Excel

I am trying to produce a count of the number of times different strings come up in an Excel table. An example table, currently in SHEET1, would be this:
I have another table in another spreadsheet where I want to indicate, for each letter on the left in Table 1, how many entries for "za", "zc" or "zd" come up on the right. However, I would only like to only consider one entry of each.
The end result, on row B of SHEET2, would have to be something like this:
At the moment I am using a combination of SUM and COUNTIFS to do the job.
More specifically, applied to the example, I am using the following formula:
=SUM(COUNTIFS(Sheet1!A1:A18,Sheet2!$A1,Sheet1!B1:B18,{"za","zc","zd"}))
The formula is doing some of what is intended. However, it is not counting each entry just one time. Instead, its is counting, for each letter on the left, every entry of "za","zc" or "zd". The table that the formula is returning is as follows:
How can I change the formula so that it does what I intend?
Thank you.
My initial thought would be:
=SUM(MIN (1,COUNTIFS(Sheet1!A1:A18,Sheet2!$A1,Sheet1!B1:B18,{"za","zc","zd"}))
but I’m not where I can test if the MIN will apply properly to the COUNTIFS array of results. ;-)
EDITED: The MIN function is taking minimum of 1 or all of the items in the COUNTIFS array, rather than minimum of 1 and each item in the COUNTIFS array, which is what I was afraid of. Using
=MIN(COUNTIFS(Sheet1!A$1:A$18,Sheet2!$A1,Sheet1!B$1:B$18,"za"),1)+MIN(COUNTIFS(Sheet1!A$1:A$18,Sheet2!$A1,Sheet1!B$1:B$18,"zc"),1)+MIN(COUNTIFS(Sheet1!A$1:A$18,Sheet2!$A1,Sheet1!B$1:B$18,"zd"),1)
will gain the desired results. It is a little clunky, but simpler than an array formula. If you want an array formula, you can use:
=SUM(FREQUENCY(IFERROR(MATCH({"za","zc","zd"},(IF(Sheet1!$A$1:$A$18=$A5,Sheet1!$B$1:$B$18)),0),""),IFERROR(MATCH({"za","zc","zd"},(IF(Sheet1!$A$1:$A$18=$A5,Sheet1!$B$1:$B$18)),0),"")))
This uses the FREQUENCY function to take a set of values and see how many items in another set of values fall within each of the data ranges. Since you need text instead of numbers, we use the MATCH function to find out the first time the value occurs in your list, returning "" with the IFERROR function if it doesn't. (We only need the first occurrence since you don't want to know how many occurrences there are). Since it is text, we use the same input for both arguments for FREQUENCY.
Therefore, if you need to change the values you are looking for or the ranges in which you are searching, make sure to change both! Alternately, you could list the values out somewhere, say in F1:F3, and make a named range for this, another one for A1:A18, and another for B1:B18. Your formula would then look something like this:
=SUM(FREQUENCY(IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),""),IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),"")))
Then you need only change your named range definitions and your formulas would update. :-)
NOTE: Since this is an array formula, you must close out of the cell by pressing CTRL+SHIFT+ENTER rather than only ENTER. When you look at the formula bar, you should see
{=SUM(FREQUENCY(IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),""),IFERROR(MATCH(SearchValues,(IF(colA=$A2,colB)),0),"")))}
It does NOT work to enter the curly braces yourself. ;-)
You can use this formula at B1 and fill down:
B1:
=SUMPRODUCT(((Sheet1!$A$1:$A$18=A1)*(Sheet1!$B$1:$B$18= {"za","zc","zd"}))/
COUNTIFS(Sheet1!$A$1:$A$18,Sheet1!$A$1:$A$18,Sheet1!$B$1:$B$18,Sheet1!$B$1:$B$18))

#REF error when using INDEX function

I cannot understand why everytime I use INDEX in excel to find a value given the two criteria, I get a #REF error.
INDEX(C2:L1048576,MATCH(O1,A2:A1048576,0),MATCH(O2,B2:B1048576,0))
There were no deleted cells, nor were they shifted at any point in time. They have the same number of rows too. The arrays to search into are correct.
Thanks. I would appreciate if anyone can give me some guidance. I am new to the INDEX formula.
The formula you're using doesn't find a value according to two criteria. The comments you were given explain what you're actually doing.
INDEX returns one cell value from a given range, according to a row and column index - the location within your range, starting with 1. (If your reference has only one row or column, one of them can be omitted).
MATCH finds a value in a range and returns its index.
So finding one value in a one-dimension range is easy using these two functions, using something like this (with a range of one column and multiple rows) =INDEX(range,MATCH(value,range,0),1).
To find two criteria you need to tweak this concept. One way is to use concatenation of strings, using the & operator, and for this you'll also need to use an array formula (entering it using Ctrl+Shift+Enter) like this formula:
=INDEX($C$2:$C$1048576,MATCH(O1&O2,$A$2:$A$1048576&$B$2:$B$1048576,0),1)
It's not clear what you are trying to return, so this formula will return the corresponding value in column C. You can use this concept to return each value from the rest of the columns D:L, one by one, or concatenate them.

Check if Cells contain value exactly one time

I have five cells in Excel filled with ones and zeros and now I want to check if in those five cells there is zero exactly one time?
Example:
(11110) true
(11100) false
I need a regular Excel function without VB please.
Assuming the value is in cell A1, use this formula:
This is an array formula and must be confirmed with Ctrl+Shift+Enter.
=1=SUM(--(MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1)="0"))
Now copy the formula to point at the four other cells.
That's it.
Here is how it works...
Let's say that the value of cell A1 is 11101111
So, that's a total of eight characters. We can see that seven of them are 1s and one is a 0.
But how do we get Excel to see the same thing?
At the heart of the formula is the MID() function. We use it to break apart the value into eight separate characters.
Under normal usage, the MID() function just returns one substring of text from a larger string. You provide it the start position within the larger text and how long of a substring you want and it returns that substring.
For example: =MID(A1,3,3) would return 101 when referencing our A1.
And if we changed that to: =MID(A1,4,1) we would get 0.
But how can we have the MID() function completely decompose the value in A1 into discreet, single-character substrings. Remember that MID() normally just returns one substring. But in our case we want it to return eight substrings.
This is where the array-formula comes in. Remember that the 2nd parameter for MID() is the start position of the substring we want back. If we pass to that 2nd parameter an array of numbers instead of one single number, then MID() will perform its function once for each value in the array.
One way of specifying arrays in Excel is to use and array constant. So we could change our MID() example to this:
=MID(A1,{1;2;3;4;5;6;7;8},1)
And the result would look like this: {"1";"1";"1";"0";"1";"1";"1";"1"}.
Now if you just enter the above formula in a single cell, you will only see the first element, which is a one. But if you selected a range of eight vertical cells and then clicked on the Formula Bar at the top of the worksheet and entered the formula and then confirmed the array-way with Ctrl+Shift+Enter
... you would see these eight different values appear in the selected range.
Another way to see the full results, even from one cell, is to select the full formula inside the Formula Bar and then press the F9 key on the keyboard. The formula will be replaced with the results in the Formula Bar. You can use this technique to evaluate the formula or discreet parts of a larger formula. If you press Enter the results will stay in the Formula Bar. If you want the formula instead, press Esc.
The problem with using the array constant is that it only works correctly when the text in cell A1 is exactly eight characters long or less. If we want to handle longer text, then we need an array constant with more values. One way to side-step this issue is to use a formula to create an array on the fly that when evaluated would look like our array constant. We would design this formula to have precisely the same number of incrementing elements as there are characters in the text in cell A1.
That is precisely what this construct in the middle of our formula does:
ROW(OFFSET($A$1,,,LEN(A1))
Recall that when the MID() function is finished we are left with this array of results: {"1";"1";"1";"0";"1";"1";"1";"1"}
Now we apply a logical test to each element, asking is each of these equal to 0?
Here is how that would look:
{"1";"1";"1";"0";"1";"1";"1";"1"}=0
A new array result is returned that looks like this:
{FALSE;FALSE;FALSE;TRUE;FALSE;FALSE;FALSE;FALSE}
Notice that only the 4th element is TRUE, which of course is exactly right.
So that's progress.
Now we want to count how many elements are TRUE. We know the answer is one. But how can Excel figure this out?
It would be nice if our array were of numbers rather than these Boolean TRUE and FALSE values. An easy way to convert the array of Booleans to numbers is to use two minus signs in front of the array. When a TRUE value is turned negative it becomes a number; it becomes -1. When we hit it with the 2nd minus sign, that -1 becomes +1. And of course FALSE becomes 0.
So doing that would look like this:
--({FALSE;FALSE;FALSE;TRUE;FALSE;FALSE;FALSE;FALSE}=0)
And the result would look like this:
{0;0;0;1;0;0;0;0}
Notice that the array is now composed of numbers. When we first looked at the results from the MID() function, it looked like this: {"1";"1";"1";"0";"1";"1";"1";"1"} and those are not numbers; they are text. Notice all the quotation marks.
If you are following closely you may be wondering why we could not have used the two minus signs directly on the output from the MID() function to convert those text numbers into real numbers. Well, in truth we could have. But we want an array where the 1s represent the source zeroes and the 0s represent the source 1s. In other words, we want the inverse. Taking these extra steps gives us that.
We can now use SUM() on the array.
=SUM{0;0;0;1;0;0;0;0})
Since it is only summing 1s and 0s and the 1s represent the original source zeros, the result is the count of the source zeroes.
We perform one final test to see if the result is equal to one, because you want to know if the value in cell A1 has one and only one zero in it:
=1=SUM{0;0;0;1;0;0;0;0})
The result is TRUE.

Resources