IF function - is there a way to avoid repeating formula - excel

Can't believe I don't know this, but is there a way to avoid repeating a formula in an if statement if the logical test is dependent on it?
i.e.
=IF((SUMIFS formula)=0,"",SUMIFs formula)
I want to replace that SUMIFS function in the false scenario with something short that will tell it to just programmatically repeat the formula it originally tested for. Repeating the formula twice has to have detrimental effects on processing speed. Negligible, maybe, but want to go for best-practices here. Thanks.

You can force an error like #DIV/0! and then use IFERROR, e.g.
=IFERROR(1/(1/SUMIFS_formula),"")

You can assign a Name to a formula and use the Name..............See:
Assigning a name to a formula
Relevant excerpt -
For example, let's suppose we frequently use a formula like:
=SUM(A1:A100)-SUM(B1:B100) and this resides in A101 and is copied across many columns on row 101. It would be better in this case to
create a custom formula that does this in each cell on row 101. Here
is how;
1) Select cell A101 (this is vital).
2) Go to Insert>Name>Define and
in the "Names in workbook" box type: SalesLessCosts
3) Now click in
the "Refers to" box and type: =SUM(A1:A100)-SUM(B1:B100) then click
Add.
Now you can replace the formula in cell A101 with: =SalesLessCosts.
You can also copy this across row 101 and it will change its relative
references just as the formula =SUM(A1:A100)-SUM(B1:B100) would. The
reason it does this is all down to the fact we selected A101 before
going to Insert>Name>Define and used relative references in
=SUM(A1:A100)-SUM(B1:B100) when we added it to the "Refers to" box.

If all you need to do is hide zeroes, there is an easy way:
Select all cells where you wish to hide zeroes
Go into Custom Number Formatting
Set format to "General;General;"
The custom formatting has a structure of [positive numbers];[negative numbers];[zeroes]
By making the last part blank you are effectively hiding zeroes, but showing everything else.
The advantage over conditional formatting is that you can use this on any background.
A neat trick which I sometimes use is to hide the cell value completely by using a custom format of ";;;". This way you can put images inside the cells, like the conditional formatting ones, and not see the value at all.

Try using the SUBSTITUTE function like this :
=SUBSTITUTE( VLOOKUP( H4; $D$5:$E$8; 2; 0 ); $H$1; $I$1 )
Here is an example:
Here the formula I don't want to repeat twice is the VLOOKUP function.
The result of VLOOKUP is a string found in another table (ex : "Green").
I want to check if that string matches a specific string value in $H$1 (here, "Yellow").
If it does, SUBSTITUTE replaces it with$I$1 (the error string you want. Here, "FORBIDDEN").
If it doesn't, it displays the VLOOKUP result string (the normal authorized output, like "Green").
This is useful for me because my actual formula is quite long, so I don't want to write it twice.
I also dont want to use two different cells, because I'm already applying this formula on 10 columns, meaning I should add an extra 10 columns to make it work.

In some scenarios, MAX() or MIN() can do a wonderful job.
E.g., something like this:
=IF(SUMIFSformula>0,SUMIFSformula, 0)
Can be shortened to this:
=MAX(0,SUMIFSformula)

The LET formula can be used for this exact scenario. You can define the formula as a variable and then within that same cell you can reference the variable in your formula.
The LET formula format looks like this:
=LET(name,name_value,calculation)
SUMIFS Example
Here's how it would work with your SUMIF example so that you don't have to repeat the formula:
In this screenshot we have an array A1:B7. We want to sum the values (Col B) if the name in ColA is "apple".
For this we have a standard SUMIFS formula of
=SUMIFS(B1:B7,A1:A7,"apple")
The formula is showing in E2. The result is shown in E3.
To put this into the IF statement without having to repeat the formula we can use LET as shown in the screenshot.
We create a variable with the SUMIFS formula as the value of that variable. We then write our IF statement using the variable name instead of rewriting the formula multiple times.
=LET(name,name_value,calculation)
Variable name: sumapples
Variable value: SUMIFS(B1:B7,A1:A7,"apple")
Calculation: IF(sumapples=0,"",sumapples)
Put together in the LET function it looks like this:
=LET(sumapples,SUMIFS(B1:B7,A1:B7,"apple"),IF(sumapples=0,"",sumapples))
This LET function can be used in any Excel formula, and is very useful for shortening long formulas that have repetition.
Optional: Extra complexity
If you want to you can get extra complicated by naming multiple variables.
=LET(name,name_value,name2,name_value2,calculation)

Since Excel 2007, the IFERROR statement does what the OP asked. From the help file:
Description:
Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula. [italics mine]
Syntax:
IFERROR(value, value_if_error)
I've since realised that this was already answered by #barry houdini above.

Here is a hack - depending on whether you are just interested in the displayed value, or whether you need to use the value in another formula:
Put your SUMIF formula in the cell (without the IF part)
Create a conditional formatting rule which sets the font color to the background color when the cell value is 0
And hey presto, you get the desired result.
As I said - it's a hack, but it does prevent the double evaluation.
There is no "clean" solution that I am aware of.

Related

Excel conditional formatting row if cell starts with

I'm trying to format a row based off a cell within it.
My table runs from A6 to K207 and I want to highlight the row in bold if the cell in B6 starts with SA.
I tested my formula
=IF(LEFT(TRIM(B26),2)="SA","YES","NO")
in another cell and that works ok - but I can't get the formatting to work for some reason...
I removed the yes/no and placed into a conditional formatting rule applying to my whole table and it doesn't work. Even if I apply it to just a row it doesn't work.
Am I using if statements within conditional formatting right? I've looked on Google and here and have found similar issues but not the same one, they've all used set values/ranges but not a 'starts with' condition.
The conditional formatting is an IF statement by default, and formats depending on whether the formula is TRUE or FALSE therefore an additional IF statement is not needed:
=LEFT($A6,2)="SA"
This will do the trick, apply this to the entire range as needed.
It will test whether all cells in column a start with "SA" and highlight that cell. If it is applied to a range including more columns, the $ sign fixes the column as A so tests that cell and highlights every cell based on that, effectively highlighting the entire row.
You can also use an OR statement to pass multiple arguments like so:
=OR(LEFT($A6,2)="SA",LEFT($A6,2)="BO")
Welcome to SO. When doing conditional formating (CF) in a formula, you need to apply references.
Switch between relative, absolute, and mixed references
Right now your formula is =IF(LEFT(TRIM(B26),2)="SA","YES","NO"). You are using relative references, so the CF rule will check according to their position. In A6 it will check the value of A6, and I guess you would like the rule to check the value always in column B.
So the first fix you need in yor formula will be (it needs more, hold on)
=IF(LEFT(TRIM($B26),2)="SA","YES","NO")
Now, it will check always the value in column B. But we need to fix something else. To make the CF based on a formula, you need to formulate something that returns a boolean value, True or False. Your values Yes or NO are strings (text), not boolean, so they don't work.
So try this formula and let's see if it works:
=IF(LEFT(TRIM($B26),2)="SA",TRUE,FALSE)
An IF Functions allows you to make a question where the answer must be yes/no (true/false) and, depending of the answer, Excel will do an option or another.
With CF rule based on a formula, you just need the question itself, you don't need to choose an option. So the short version of this formula, as #Plutian states in his answer, is just doing:
=LEFT(TRIM($B26),2)="SA"
Try to adapt this to your needs.

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))

Excel - How to use the value of a cell as the row value of another cell?

Here is my problem:
I have a cell (V4) containing the value 444. I want to use this value in the formula of another cell (M12) in the following way. I want the formula to be equivalent to =MIN(L12:L444) but instead of 444 I want to refer to cell V4 which contains the value 444. But when I type in =MIN(L12:L(V4)) it obviously doesnt work so how do I do it? Sorry if I didn't explain it very well. :S
Would this work for you:
=MIN(L12:INDIRECT("L"&$V$4))
From: Excel - INDIRECT and Using the value in a cell as a cell reference in a formula?
INDIRECT will work and is closest to the solution you described, but I prefer OFFSET, which uses proper references. (For example, if you insert a column in the sheet before L, INDIRECT will break while OFFSET will just update its reference as expected.
Two ways to go with OFFSET:
1 - Start at L$1 and go down $V$4-1 rows. (This will work with $V$4 as you've defined it now.)
=MIN(L12:OFFSET(L$1,$V$4-1,0))
2 - In $V$4, provide the height of the range you want.
=MIN(OFFSET(L12,0,0,$V$4,0))
It's hard to make suggestions without more context, but I'm sure you can tweak one of these patterns to meet your needs.
I am not sure if you are trying to include all of the values in 1 column and then on non-contiguous cell. If so, it should look like = Min(L12:L444,V4) . The L12:L444 looks at the value in every cell in the L column from 12 - 444.
So you can check individual cell (A3, D15, Q54) with commas, or a range of cells (A3:Z54) with a colon. Or a range and a specific cell like above =Min(L12:L444, V4).

Create a custom function in Excel

This seems like such an obvious thing that excel must have this feature, I just can't find it.
How can I create a custom function without using VBA? (VBA is too big of a hammer and causes security warnings, etc).
For example, I have a spreadsheet with several very complex formulas. Each of these formulas are replicated in several columns. Each column has hundreds of entries, so each one is replicated hundreds of times. If I tweak something then I have to manually fill-down or copy my change from one column to another.
A simple one looks like this:
=(Payment1 - F$12)*12 + ($D21-H21)
But what I'd like to do is:
=MyFunction(f$12,$D21,H21)
And have the actual formula for "MyFunction" written just once someplace.
I've found a few things that come close to giving me what I want. For example, in tables Excel will automatically replicate changes in a formula down the rest of the column saving you the step of manually selecting the range and doing a "Fill Down".
It will also allow relative references off of named cells, which seems equivalent of a user-defined parameter-less functions.
if you can use text to create the formula, then you can define a name to evaluate the function.
In cell A2, create a name EvalAbove, and in Refers To, enter =evaluate(A1)
This way, you can construct a formula
e.g. B1 contains SUM, B2 contains =("="&B1&"(A2:A5)")
and in B3, you can then put =EvalAbove
This means that if you change the formula name in B1, then B2 will change to show the changed formula, and B3 will change to show the result.
Note that this still counts as a macro enabled workbook, but there's no VBA code, just named ranges
You can do this for the example you show if I interpret it correctly.
If not you may be able to rearrange things slightly to conform
your function has three parameters:
The first comes from row 12 of the current column
The second from column D of the current row
The third comes from the column two to the right of the current row
I assume Payment1 is a named variable already?
Set the cursor in say F21 and then define this name
MyFunction =(Payment1 - F$12)*12 + ($D21-H21)
This will set the parameters to come from the places shown
To understand this better switch to RC mode and type the formula as:
=(Payment1 - R12C)*12 + (RC4-RC[+2])
You can now propagate down the formula through the F coloumn
=MyFunction
and it will always use the values in the corresponding F12 column Dxx and column Hxx
If you drag the formula to the next column it will use G12, Dxx and Ixx
If you want to change the formula edit it in the define name space
This is a general exception to the rule that you cannot have non-vba UDFs in Excel. Often in Excel the things you want as 'arguments' to the function are actually in fixed places (rows or columns) that can be addressed relatively.
For example you often want to perform a udf on the cell to the left
So a udf giving the cuberoot of the cell to the left would be a named formula like this:
Cuberoot =(RC[-1])^(1/3)
Or in a1 form set the cursor in B1 and type =(A1)^(1/3)
And Excel will convert it internally to the RC form
For three args - use three columns
It works and does not suffer the volatility issue mentioned about evaluate()
Yes I know this is an old posting but it may help someone with the same issue.
Bob J.

Resources