Assign an Excel function result to a variable within a cell - excel

I'm working on an Excel spreadsheet where I'm using VLOOKUP to get data from another sheet. I have it working, but it's giving me an annoying "0" for blank results. I'd like to incorporate ISBLANK to address it.
My problem is the syntax. I REALLY do NOT want to retype the entire VLOOKUP function for the results if it returns FALSE.
In other words, what I'm trying to avoid doing is this:
=IF(ISNULL(VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2)),"",VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2))
Ideally, what I want to do is something like this:
=IF(ISNULL(VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2)),"",[some variable that stores the result of the VLOOKUP])
Ideas, anyone? Thanks...

Are you open to formatting? You can hide the zeros that way, and therefore keep the formula short.
Highlight the range of the VLOOKUP() results, and go to Formatting, then Custom. Use this format and any 0 will be effectively hidden:
0;-0;;#

It depends whether you're looking up text or numbers.
If you want the result of your expression to be text that you're looking up, it's as simple as wrapping your VLOOKUP with the function T().
So, for text, replace VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2,FALSE) with T(VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2,FALSE))
If the result of your expression is a number, and your VLOOKUP expression is too complicated to repeat, then you can avoid writing it twice by sneakily using IFERROR. The trick is to make it so that when VLOOKUP returns 0, it makes an error, but otherwise it returns what VLOOKUP returned. And you can do this by taking advantage of some maths: Where x<>0, then 1/(1/x) = x. When x=0, Excel returns #DIV/0!. If we use IFERROR, then we can replace that with an empty string ("")
So, for numbers, replace VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2,FALSE) with IFERROR(1/(1/VLOOKUP($A2,Sheet!$B$1:Sheet!$C$200,2,FALSE)),"")

By the looks of it the formula you're asking for is:
=IF(VLOOKUP($A2,Sheet!$B$1:$C$200,2,FALSE)="","",VLOOKUP($A2,Sheet!$B$1:$C$200,2,FALSE))
Edit: The FALSE at the end of the function is so it only finds an exact match. Omitting it, or setting it as True, returns an exact or the next largest value that is less than the lookup value - your list must be sorted in ascending order for that to work.
Note the range reference to the sheet called Sheetis Sheet!$B$1:$C$200 and not Sheet!$B$1:Sheet!$C$200.
Having said that, an easier way is just to hide the 0 returns with number formatting.
Give the cell a custom number format of:
#,##0;-#,##0;;#
The first section #,##0 is the format for positive numbers, the second -#,##0 for negative numbers, the third ;;(no format set) for zeros and the last # for text.

Related

How to highlight a missing value in a specified range with Conditional Formatting from the last used column

We use this format in our casino to know where we have to send our employees to certain tables or games. We recently changed the way we do this and we now need to have some checks to make sure we didn't forget certain tables.
Every hour/half hour/20mins we assign a table to a person, everyone else moves one up. We know exactly which tables are open at which times. We fill this in at the top. When we fill in the upcoming timeslot we would like to have some check so we don't forget a table and maybe miss out a employee.
Example:
In the example supplied you can see that we accidentally have two number 6's but no 7 I highlighted the number 7 in the top row but it would be nice if this is doable automatically
I used VLOOKUP and INDEX/MATCH in the formula for Conditional formatting but that does not seem to create the correct outcome.
Here is an example of how it can be done:
The formula used has the array {1;2;3;4;5;6;7} hard written into it, assuming that the number of tables does not vary. The output is 0 when no table is missing, otherwise it returns a list of missing tables separated by commas.
Note: That of course means, the comma separated list is not a numeric value but a string value and cannot be used for further calculations. If further calculations on this output are required, the 'solution' has to be changed accordingly.
Formula
=IFERROR(CONCAT(FILTER({1;2;3;4;5;6;7},ISERROR(MATCH({1;2;3;4;5;6;7},H5:H24,0)))&", "),0)
Explanation
The MATCH() function checks which of the numbers 1 to 7 are present in the given range (here H5:H24) and returns the cell index of where it is found. When a number does not appear in the range, the MATCH() function will generate an #N/A error for that number.
Then, the ISERROR() function will output a FALSE value for all numbers found by MATCH() and a TRUE value for those numbers where the MATCH() function lead to an error.
The FILTER() function filters and thereby reduces the number array {1;2;3;4;5;6;7} to only those numbers where the ISERROR() function is TRUE.
The CONCAT() function concatenates the resulting array from the FILTER() function (in case more than 1 number is missing) to a single string of numbers separated by commas.
However, when there are no open tables, i.e. the MATCH() function finds all numbers 1 to 7 in the given range, then the ISERROR() function will only return FALSE values and the thus the FILTER() function returns an 'empty' array, which is not allowed in excel and leads to an #CALC error in excel. This case is captured by the IFERROR() function encapsulating the whole calculation, and instead of showing the error, returning 0.
What about this formula:
=AND(COUNTIF(A$2:A$10,1)=1,COUNTIF(A$2:A$10,2)=1,COUNTIF(A$2:A$10,3)=1,COUNTIF(A$2:A$10,4)=1,COUNTIF(A$2:A$10,5)=1,COUNTIF(A$2:A$10,6)=1,COUNTIF(A$2:A$10,7)=1)
A bit clearer:
=AND(COUNTIF(A$2:A$10,1)=1,
COUNTIF(A$2:A$10,2)=1,
COUNTIF(A$2:A$10,3)=1,
COUNTIF(A$2:A$10,4)=1,
COUNTIF(A$2:A$10,5)=1,
COUNTIF(A$2:A$10,6)=1,
COUNTIF(A$2:A$10,7)=1)
... which means that the number of ones need to be 1, the number of twos need to be 1, ..., up to the number of sevens.
Hereby a screenshot of an Excel sheet, which contains that formula:
In order to understand how this works, you might work with formula auditing, more especially formula evaluating, hereby an extra screenshot, showing formula evaluating after some steps:
Have fun :-)

Index Match Works on some cells, not others

I was using this Index Match formula with no issues:
=INDEX('Rain Data For 9 Stations'!A:S,MATCH(RainWICSProximity!J100,'Rain Data For 9 Stations'!A:A,0),INDEX($N$4:$N$12,MATCH(H100,$M$4:$M$12,0)))
I added more data, and it now only returns some values, while returning #N/A for others, even though there is a value to return.
Index returns the value in a range.
What you are doing is =INDEX(MATCH(),INDEX(MATCH())). It works due to some luck, because sometimes the second Index() returns cell with value as well. However, if the second index returns cell with an empty value, then the first index has to return something like =Index(4,0), which is #N/A.
In general, try =Index(Match(),Match()).
To see where exactly the error is, select the cell with the formula, go to the Excel ribbon >Formulas>Evaluate Formula.
Then press a few times Evaluate Formula and see what happens:
See this answer for step-by-step formula evaluation.
#Vityata was correct, Index, Match, Match works wonderfully, also, my original formula does work.
The issue was, I had calculate set to Manual, not auto, in excel settings.
I believe you need to expand your range. I am not real familiar with Index Match but trying to learn to use it more, but I believe it is kind of like VLOOKUP. Your ranges $N$4:$N$12 and $M$4:$M$12 is where it is looking right? If so, those ranges are not expanding even though you added more data. So you need to expand it to like $M$4:$M$100 or whatever. Or expand it to find the last row which is what I usually do. like mine would be "$M$4:$M" & LastRow & "" or something like that.

Excel: order effects in arrays

I'm currently using this expression to check if a cell contains at least one of a set of strings:
A B
1 abcd =ISNUMBER(SEARCH({"a","x"},A1))
B1 will return true here. However if I change the order of the array as follows it returns false:
A B
1 abcd =ISNUMBER(SEARCH({"x","a"},A1))
Why is that? Is there a better way to do this that's more elegant than using a bunch of OR()'s?
Say we have text in A1 and we also have a list of sub-strings in column C. These can be either single or multiple character substrings. We assign the Name - KeyStrings to the list of cells in column C
We want to know if any of the substrings is present in A1.
Enter the following in B1:
=NOT(LEN(TRIM(SUBSTITUTE(A1,INDEX(KeyStrings,SUMPRODUCT(ROW(KeyStrings)*ISNUMBER(SEARCH(KeyStrings,A1)))),"")))=LEN(A1))
The formula will report True if any of the substrings in column C can be found in A1
Just for completeness, the answer to the original question "Why is that?" i.e. why does the result seem to be sensitive to the order of the strings in curly brackets is that the formula
=ISNUMBER(SEARCH({"a","x"},A1))
only looks at at the first string "a" because there is nothing to make it operate like an array formula and step through all the values "a","x" etc.
The usual procedure is to wrap the function in an aggregate function like SUM. If you do this you also have to add minus signs to make the TRUE/FALSE values from ISNUMBER behave as ones and zeroes and further wrap in SUMPRODUCT or enter it as an array formula to make it work:-
=SUMPRODUCT(SUM(--ISNUMBER(SEARCH({"a","x"},A1))))
Even then it gives a numeric result which is not what you actually want.
# Dirk Reichel's idea is therefore much better giving you:-
=OR(ISNUMBER(SEARCH({"a","x"},A1)))
which works very nicely and incidentally doesn't need to be entered as an array formula.
I think since you have put a curly bracket there, it indicates an array search. (I am not an expert with arrays, so following is an educated guess).
What Excel is doing is in the first example, it is finding "a" in position no 1, so it is returning the no 1 to ISNUMBER function, which is TRUE. (Basically, compares "a" to a in abcd which is position 1, and doesn't find/look for[?] "x". Returns 1 for the "a", which is TRUE for ISNUMBER function)
In the 2nd code, "x" is compared to a from abcd, which returns a non-numeric value (and doesn't find/look for[?] "a"), hence it is FALSE.
PS:
what I mean by Excel doesn't find/look for[?] the second or any element there on, seems to be based on how arrays and formulae are coded in. In the curly brackets, commas separate "columns" and semi-colons separate "rows". So you are entering a 2 column/1row array inside a search function. While there is nothing wrong with that, the SEARCH function itself may not be coded to look for any element in the array apart from the one in position [1,1]. Someone better informed with the inner workings of SEARCH function should confirm this answer. (If it is a completely wrong educated guess, I wouldn't mind taking it off)

Is there a function, that would return "" when input ref is empty, and its contents if it is not?

IMO Excel has weird treatment of empty Cells.
I am building a complex array formula. One of the referenced ranges contain cells, that may, or may not be empty, and if not empty, they can contain both numeric values and strings.
What function can I use, to get the value of the cell if the cell is not empty, and "" (or anything other non-numeric, e.g. #N/A) if the cell is empty?
I want to get something like this working:
=MIN(OFFSET(<column vector that contains text, numbers and empty cells>;<row vector of indices>-1;0))
This form of formula returns an #ARG error, as was explained in the answer to Why this array formula doesn't work?.
But when I prefix the OFFSET with N, it transforms any empty cell into 0, so the net result is 0 (unless there are negative numbers in the column vector).
=MIN(L(OFFSET(<column vector>;<row vector of indices>-1;0)))
Is there any formula, that only dereferences the reference returned by OFFSET preserving the "emptyness" of the empty cell? Or maybe there is an alternate way of solving the problem, like
=MIN(IF(OFFSET(<column vector>;<row vector of indices>-1;0)="",L(OFFSET(<column vector>;<row vector of indices>-1;0)),""))
(This example also fails with #ARG, because, as I understand, I need to dereference the array reference for the = test as well).
If it is at all possible, I prefer to keep with Excel 2007 set of built-in functions. And no VBA.
I would accept any solution, that uses constant number of cells irregardless of the size of each input array.
EDIT:
As a side remark I wonder what is wrong with the arrays returned by OFFSET anyway? This simple example works perfectly:
...while the array returned by OFFSET somehow wants to be alone in the formula.
There may be another option but I don't see it at the moment.....
You can filter out zeroes by using an IF like this
=MIN(IF(N(OFFSET(INDIRECT($A$2),$C4:$G4-1,0))<>0,N(OFFSET(INDIRECT($A$2),$C4:$G4-1,0))))
but that won't distinguish between any actual zeroes in your range and those produced when the N function encounters blanks or text
Edit
This version should work
=MIN(IF(COUNTBLANK(OFFSET(INDIRECT($A$2),$C4:$G4-1,0,1))+LEN(T(OFFSET(INDIRECT($A$2),$C4:$G4-1,0,1))),"",N(OFFSET(INDIRECT($A$2),$C4:$G4-1,0,1))))
Perhaps not completely relevant here but the problem is finding functions that can deal with the "array of references" returned by OFFSET with this type of setup - N and T work as shown here and also COUNTBLANK. Other functions that can be used on the OFFSET output are SUBTOTAL and COUNTIF. Note that COUNTBLANK (along with SUBTOTAL and COUNTIF) can work on ranges while T and N will only work with single values - if the latter functions are applied to ranges they simply look at the first value in the range - because of that I was able to use OFFSET without the "height" parameter but you need that with COUNTBLANK (and it's a good habit to get in to so OFFSET should have the final 1 as here
=OFFSET(INDIRECT($A$2),$C4:$G4-1,0,1)
Consider in B1:
=IF(ISBLANK(A1),"nothing there",A1)
So if A1 contains the formula:
=""
Then B1 will also display the null.
Another possibility:
=MIN(CELL("contents",OFFSET(INDIRECT($A$2),N(INDEX($C4:$G4-1,)),0)))
Note: The N(INDEX(...)) part is a trick used to enforce array evaluation.

Excel 2010: Inserting AND operator into function that returns true if referenced cell has value

As best I can tell, IF([cell],TRUE,FALSE) is always returning TRUE if [cell] contains a value, but I can't find any documentation on this sort of truth-value test in Excel 2010. I don't know what it's called, and all the documentation I can find seems to require some conditional operator in the first field of the IF function. Is this shorthand, a bug, or am I using some other feature in a way that is unintended?
Here's my mess:
=IF([#[LL Billed]],NETWORKDAYS([#Closed],[#Paid]),NETWORKDAYS([#Closed],TODAY()))
All referenced cells either contain a date or are blank. Currently, if #[LL Billed] is blank and #Paid is blank (#closed always contains a date), I get an integer returned (which is how it should work).
What I need to do is change this formula so the logic test checks whether there is a value in both #[LL Billed] AND in #Paid; if both contain value it should return TRUE, and if either one contains no value then it should return FALSE.
I'd like to avoid completely restructuring this IF function because it has symmetry with other functions in the workbook. Is there another "shorthand" test I can employ as part of the logic test? I've tried nesting NOT-ISBLANK-AND functions, but to no avail, plus it's messy.
Any suggestions?
Try using COUNT (which counts numbers, including dates), i.e.
=IF(COUNT([#[LL Billed]],[#Paid])=2,NETWORKDAYS([#Closed],[#Paid]),NETWORKDAYS([#Closed],TODAY()))
If COUNT = 2 then both cells have dates
btw if you use an IF function with a number as the test, it always returns TRUE.....unless the number is zero, in which case it returns FALSE
Note: if you want you can shorten the formula by embedding the IF function within NETWORKDAYS, i.e.
=NETWORKDAYS([#Closed],IF(COUNT([#[LL Billed]],[#Paid])=2,[#Paid],TODAY()))
Consider the formula =IF(A1,True,False)
This will be False if A1 contains the number zero
It will be True if A1 contains a number not equal to zero
It will be False if A1 is a blank cell
All other cases it will be #VALUE
If you want to suppress #VALUE then write =IFERROR(IF(A1,True,False),"Hello") to print "Hello" instead of #VALUE.
Hope that helps a bit.
See if this works.
=IF(AND([#[LL Billed]],[#Paid]),NETWORKDAYS([#Closed],[#Paid]),NETWORKDAYS([#Closed],TODAY()))
A lot of issues come into play on what you consider a value. Not blank, Greater then 0, a number vs text. Errors. a lot of variables come into play and without more information on your data this is the best I feel I can provide you with

Resources