I'm looking to make a bunch of my complicated formulas more readable. For example:
I know about Alt+Enter to add newlines within the formula itself. This makes the formula a little bit more manageable, but it's still not as readable as I'd like it. What else can I do to make big formulas like this one more readable?
I'm going to answer this myself as Excel 2013 doesn't have any truly good ways of doing what I want with formulae.
In my research I have found three ways of making formulae more readable. The first is something I mentioned in my question: Alt + Enter. This will insert a newline into the formula so that you can break up the wall of text. As an example you can change this:
into this:
The second method is to add a sort of comment to your formula. Personally I don't like this solution as it doesn't make formulae more readable to me, but others may like it. The method involves using the function N(). This function will return zero if given a string. For example:
Will give a result of 42 as N() returns zero.
The third method (shoutout to user shawnt00 for suggesting this in the comments) is to use named ranges. This can really help with readability as the user can convert something like A8:C14 to whatever name the user desires. To define a named range go to the Formulas table and click on "Define Name". Give the named range a name (preferably something that makes sense and not just "foo") and select the range of cells. Once done you can change something like this:
into a formula that is much more easily read:
The last method is to create extra columns and hide them (Thank you to user Quintin Balsdon for suggesting this). If, for example, you need the same value multiple times in one formula you can put the formula used to get that value into a separate cell that you hide and reference that cell. Take this formula for example:
On its own this formula isn't too bad, but if you take a close look at the formula in my question you'd see I do a very similar thing. Simply taking the index/match out and putting that into another cell and changing the above formula to
will make a complicated formula much smaller and much easier to quickly check what the value of J1 represents.
Related
I have a table of fruits in Excel 2013.
I'd like to fill the "Category" column by searching from the current row to the top until the first occurrence of "::", which is the keyword for a category in the table.
If there was some way to reverse a range, I could do something like "=Match("::*"; $A6:$A$2)" to find the row. However, this is not possible.
Does anyone know how this might be accomplished using formulas?
Using your provided sample data, and assuming your data is already organized as shown in your sample, you can take advantage of that organization and use this formula in cell C2 and copy down:
=IF(LEFT(A2,2)="::","",IF(LEFT(A1,2)="::",MID(A1,4,LEN(A1)),C1))
Assuming your table is in A1, put this in C3:
=INDEX(A:A, AGGREGATE (14,6,ROW($A$1:A2)/(LEFT($A$1:A2,2)="::"),1))
And copy down.
Here's a kinda different approach. I'm just basically responding to this part of your post to prove this is possible:
If there was some way to reverse a range, I could do something like "=Match("::*"; $A6:$A$2)" to find the row. However, this is not possible.
Reversing a range is possible, it's just tricky.
As you pointed out: $A6:$A$2 won't work since this is equivalent to $A$2:$A6.
However, without getting into the nitty-gritty details, this array formula will reverse this range:
= INDEX($A$2:$A6,N(IF({1},MAX(ROW($A$2:$A6))-ROW($A$2:$A6)+1)))
Note this is an array formula, so you must press Ctrl+Shift+Enter instead of just Enter after typing this formula into a cell.
You could use this in combination with your MATCH formula to get the desired result (which tells you how many rows up the :: row is):
= MATCH("::*",INDEX($A$2:$A6,N(IF({1},MAX(ROW($A$2:$A6))-ROW($A$2:$A6)+1))),0)
(Also haha this is kinda cool: Usually you see MATCH used within INDEX to effectively get a VLOOKUP type of functionality. This is the first time I have ever seen it the opposite way of having INDEX within MATCH.)
Note that I'm not saying this is necessarily the best approach for this specific problem, just proving a point that arrays can be reversed.
I have a big excel formula like-
=CONCATENATE( IF( AND(LEN(A1)>3,LEN(A1)>=5),CONCATENATE( VLOOKUP(NUMBERVALUE(LEFT(RIGHT(A1,5),2)),rng,2)," হাজার "),IF( AND(LEN(A1)>3,LEN(A1)=4),CONCATENATE( VLOOKUP(NUMBERVALUE(LEFT(RIGHT(A1,4),1)),rng,2)," হাজার "),"")),IF(LEN(A1)>2,IF(NUMBERVALUE(LEFT(RIGHT(A1,3),1))>0,CONCATENATE(VLOOKUP(NUMBERVALUE(LEFT(RIGHT(A1,3),1)),rng,2),"শত "),""),""),IF(NUMBERVALUE(IF(LEN(A1)>1, RIGHT(A1,2), RIGHT(A1,1)))>0,VLOOKUP( NUMBERVALUE(IF(LEN(A1)>1, RIGHT(A1,2), RIGHT(A1,1))),rng,2,FALSE),""))
In this formula I had to use 'A1' reference again and again.
I need a function or anything like this-
=DEFVAR(A1,'somevar',CONCATENATE( IF( AND(LEN(somevar)>3,LEN(somevar)>=5),CONCATENATE(....)
So that I can use the formula on 'M9' cell like this-
=DEFVAR(M9,'somevar',CONCATENATE( IF( AND(LEN(somevar)>3,LEN(somevar)>=5),CONCATENATE(....)
Is there any way to achieve this?
No, Excel formulas don't allow you to declare variables within them.
But what you could do in this case is use another cell that holds LEN(A1), and use that in your formula. Excel's very clever calculation cycle will guarantee that LEN(A1) is evaluated before any dependent formulas.
Essentially then you are using one or more other cells to hold "variables".
This also makes your spreadsheet easier to maintain. Avoid VBA if you can; (1) it's difficult to version-control, (2) not all companies permit use of .xlsm due to security issues, (3) VBA runs in a single thread.
Your basic quetion is, "declare variable within formula and use it into the same formula".
Answer is NO.
Any Formula in Excel doesn't allows to declare variable and use it further. This is a common practice while programming and needless to say how, since somewhere you have written that you are using VBA!.
Now let me tell you how indirectly we use variables in Excel formula.
It's a Cell address which works as a variable. Other is Named Range which carries more than one value like an Array. Further more you can also use a formula as variable.
Let me say how, write a formula in cell and just Name it and use that Name in any formula like we call procedure while programming. A simple example I'm showing you here.
Write formula is A2, = if(A5>=1000,Max(B2:B100),0) and just Name it like MYMAX. Then in other formula you can call it like, =if(B2 = "A01",MYMAX,"Nothing").
Hope this help you to realize that, why we need Programming.
It's recommended to use =MATCH() in it's own cell and then use INDEX to refer to that cell. This makes sense, why redo the MATCH() formula over and over when it's the same result?
I want to do the same thing with the OFFSET() formula. I'm working with large tables and I understand that keeping your ranges small is the key to optimization. So, using OFFSET to figure out how big of a range i want to use has been extremely beneficial. However, sometimes I might have an IF statement that checks out several COUNTIFS that require the same range. In these cells I am forced to use the OFFSET to determine the exact same range, over and over... wouldn't it be better to simply do the same thing as INDEX/MATCH?
Unfortunately I don't think excel can output the range itself... I notice in the formula auditor that it will reveal the resulting range--i need that literal range in a cell so A1 might say "$B$2:$B$342".
Probably not possible, but thought I'd ask!
Thanks
You can try to use the 'CELL()' formula. This formula can return the 'address' of a referenced cell. See formula below:
=CELL("address",B1)&":"&CELL("address",B10)
Results should be: $B$1:$B$10
Put the above formula in cell 'A1' and see if this helps you at all. You will probably need to tweak it a bit to get the exact results you're looking for (for example, you may need to 'nest' your offset() formula within the cell() formula).
Best of luck!
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.
I'm trying to tell Excel to change the cell reference for a SUMIF formula based on the last cell that contains a value in each row. Right now, I know I could write a nested if statement to do this for me, but it's far too unwieldy to be a long-term solution.
Example:
On a separate report, every person in this list has multiple lines recording their daily sales. On a small scale, I'd simply write a SUMIF that uses for A2, B3 and C4 as criteria. The scale is much much larger, so my current solution is to write out a logic check with the SUMIF formula folded into it.
In this case, the formula in E2 would be:
=IF(C2="",if(B2="",SUMIF('range',A2,'range'),sumif('range',B2,'range')),sumif('range',C2,'range'))
Is there a different way to tell Excel to run the SUMIF with the last value found in each row?
I was hoping I could use COUNTA for each row, then have the SUMIF formula use the COUNTA value to change the criterion cell reference. I'm missing something here.
=SUMIF('range',INDEX(A2:C2,MATCH("zzzzz",A2:C2)),'range')
seems worth a try.
Edit Too long for a comment:
I don’t really have any idea how =MATCH() works but think of it as traversing left to right while searching. When it fails to find a match it just happens to have been looking at the last entry and (conveniently!) offers that up. So the key is to look for something that won't be found.
For people’s names I chose “zzzzz” as unlikely to be present. For numbers anything up to 9.99999999999999E+307 is theoretically possible and hence some people use that (eg an hour ago Formula to get the first cell with a numerical value from a selection?) but I prefer a googol (1E+100) and that seems quite large enough, is much shorter – and easier to remember, even if a few 9s more or less would make no difference, nor likely what couple of integers are after the +.