Avoiding duplicate long expressions in Excel - excel

I often find myself writing Excel formulas that have something like this in the formula:
= IF(<long expression>=<some condition>,<long expression>,0)
Is there any way to accomplish this without needing to type out <long expression> twice (and also without using helper cells)?
Ideally, something that works similar to IFERROR, i.e.
= IFERROR(<some expression>,0)
This checks if <some expression> would return any type of error, and if it doesn't, it automatically returns <some expression> (without needing to again explicitly type it out a second time).
Is there an Excel function (or combination of Excel functions) similar to IFERROR but instead of checking an error condition, it checks a general (user-defined) condition based on the formula?

When it comes to formula efficiency and calculation speed, using helper cells can be of great value, even if they may initially muck up the spreadsheet design.
Put calculations into a helper cell and refer to the helper cell in the IF statement. That way the calculation will only happen once.
This method is preferred by spreadsheet auditors over the alternative of packing everything into one formula, because it is also much easier to follow and pick apart.
With careful spreadsheet planning you can house helper cells in a different (hidden) sheet or in columns that you hide to tidy up the design.

This answer applies to Excel 365 as of March 2020. A new function is now available in Insider builds of Excel. It is called LET() and is used to define, and assign a value to, a variable that can then be used multiple times inside the braces of the LET() function.
Example:
=LET(MyResult,XLOOKUP(C1,A1:A3,B1:B3),IF(MyResult=0,"",MyResult))
The first parameter is the name of a new variable, MyResult. The variable is assigned a value with the second parameter. This can be a constant, like a number or a text, or like in this case, a formula.
The third parameter is a calculation that can use the variable value.
In the following screenshot, the Xlookup returns a 0 because the found cell is empty.
In the next formula down, the Xlookup is wrapped in an IF statement, evaluated, and then repeated. This is the approach where the calculation is duplicated, as described in the question.
The third formula shows the LET() function and its result.

Related

ADDRESS TO RANGE

I have this formula:
=MATCH(""&"W"&C2&"",'Raw Data'!$5:$5,0) --> Which extract the column number, then
=SUBSTITUTE(ADDRESS(1,E3,4),"1","") --> I convert to letter
It returns: DH
Finally, I want to use that value of "DH" into the following formula
=INDEX('Raw Data'!A:A,MATCH(E26,'Raw Data'!DH:DH,0))
I tried many times and ways without success.
Data is dynamic, so the first value I'm looking for W2 (for example) will not always be in the same column.
Depending on the variable which you get on the column number, I want the spreadsheet to select that column.
Here is a simplified demonstration of what I think you are trying to do here:
Formula in A3:
=INDEX(A11:A20,MATCH(A2,INDEX(A11:E20,,MATCH("W"&A1,5:5,0)),0))
As you see, this can be done without transformation of a column number into a letter reference. It's simply a matter of nested INDEX/MATCH functions as per #BigBen in the comments.
Please adapt the above to suit your ranges.
Few more remarks just for future reference:
ADDRESS - This is a so-called volatile function. Though maybe not obvious these type of functions recalculate on any save, open, edit on your worksheet. The more of these, the slower your workbook gets.
""&"W"&C2&"" - There is no need to concatenate empty strings in front of other string values leaving you with the exact same results but formulas that are simply harder to read.

Excel Formula with OFFSET Fails When Copied to Different Sheet

I've been struggling with this longer than I care to admit, but I have a fairly simple OFFSET function call which works on one sheet, but if I copy it to a different sheet it gives a #VALUE error.
On a sheet named "Deliverable" I have this formula in a cell:
=OFFSET(Deliverable!$B$72,1,0,,3)
and it works fine.
If I go to any other sheet and use the same exact formula, or use it in the Name Manager, it gives a #VALUE error.
If I leave off the final parameter indicated the number of columns I want, it does work:
=OFFSET(Deliverable!$B$72,1,0)
but of course isn't giving me the range I need.
Any idea what's going on with this?
I'm using Excel 2016 on Windows 7.
-- Updated Info --
In a nutshell, my spreadsheet has two cells which I'm using as dropdown lists, where the 2nd cell's list feeds off the selection in the first. The data they are based on has this format:
OptionA A B C D
OptionB A B
OptionC D E F
So the first dropdown uses a simple Data Validation source pointing to the column with OptionA, OptionB, etc. Once that's chosen, the second dropdown list should contain the appropriate options for the one selected. So if OptionB is selected, then the 2nd dropdown list should show A and B.
When I initially wrote this, the data validation source was just a simple VLOOKUP entry, but the lists often had blanks since the number of options varies for each entry. Wanting to fix it up a bit, I ended up with this formula:
=OFFSET(Deliverable!B72,Deliverable!B87,0,1,COUNTA(OFFSET(Deliverable!B72,Deliverable!B87,0,1,5)))
There won't be any more than 5 options, and there are no empty cells in the middle of the data to filter out.
In one spreadsheet I have I used this as a named range definition, then specified the named range for the cells data validation source and it worked. In this other spreadsheet however, it gave me the error described earlier.
However, it looks like when I enter the statement directly into the data validation source field and not in the name manager, it works as expected.
Am I taking the totally wrong approach?
What is it that you want this formula to do? As written, it is returning a block of three horizontal cells. The #VALUE error is Excel's way of telling you "Hey, you're trying to return three cells, but I can't fit them all in the one cell that you are calling this formula from".
The reason you see a result in some places and not others is because of something called Implicit Intersection. Give it a spin on Google. But basically, it just returns whichever one of those three results corresponds to the column that the formula is entered into. If you copy that exact same formula to say row F you will see that it returns a #VALUE error there, because it doesn't know what cell it should return given the column you're calling it from doesn't match any of the cells it is returning. The fact that you don't know this indicates that the formula you're using doesn't in fact do what you think it does.
--UPDATE --
Okay, following your further clarificaiton it seems that you're talking about Cascading Dropdowns aka Dynamic Dropdowns. Lots of info on Google about how to set these up, but you may be interested in an approach I blogged about sometime back that not only provides this functionality, but also ensures that someone can't later on go and change the 'upstream' dropdown without first clearing the 'downstream' one should they want to make a change.
Note that those links talk about a slightly complicated method compared to others, but the method has it's advantages in that it also handles more levels than two, and your DV lists are easily maintained as they live in an Excel Table.
This sounds like an array equation. Try hitting Ctrl+Shift+Enter in the other sheets to validate it as an array equation.
Whenever you need to reference ranges instead of single cells, Excel needs to know that you are working with arrays.

Use INDEX/MATCH to select formula written as string, and enable it?

I have a pricelist, with currently 5 different categories of products. Each product will have to have two different prices. Depedning of the product and the type of price, the calculation will be different. Therefor I've used INDEX/MATCH to find the formula needed, from a table I created.
Below a screendump, and I wanted to attach the Excel fil, but canøt seem to work out how.
Question: HOW do I then "run" the formula I fetched? -I've tried different suggestions on using EVALUATION, but it doesn't seem to cut it? Also I've tried "Indirect' on the whole formula, without success.
I would like to avoid any VBA for this case.
Can anybody provide some insight?
You could but if I understand properly, the only thing changing in the formulas is the "muliplier" number, then it's better to lookup that number instead of the whole formula. The other method (which would use Evaluate etc) is not be considered "good practice" for a number of reasons.
EDIT:
I didn't see the 2nd varying value (since I was on the SO mobile app) but it's still not an issue since it would a target column. You could be thinking of the opposite: sometimes lookups based on multiple criteria can get complicated, but this a matter of more data, as opposed to adding criteria for the lookup.
VLookup would have been the simplest method, like G2 could have been:
=VLOOKUP(E2, $J$4:$L$8, 2, False)
...to return the second column of range J4:L8 where the first column equals E2. (Then for the next required column, same formula except with 3 instead of 2.)
Since I wasn't sure more columns could be added one day, I allowed for that by, instead of specifying "Column 2 or 3" etc, it finds the column dynamically by name. (So the multiplier/factor used in G2 will change if you change the title in G1 to the name of a different column existing in the target data chart.
For the sake of neatness as well as potential of additional columns like G & H, I moved the lookup table to a separate sheet. It can stay out of the way since you won't need to see or change it very often. (If the same chart was going to be referenced by many workbooks, you could even move it to a separate workbook and point all formulas at that, since it's always best to have one copy of identical data instead of many in different workbooks.
Also to assist with potential future changes (and just to be tidier), instead of referring to the target table range addresses (like "J4:L8" etc) I named two ranges:
the table of multiplier/factor data can be referred to by it's address, or by myMultipliers
the titles of the same table is also called myMultiplierTitles (used to match to the titles of column G & H on the original sheet.
Formula
After those changes, the lookup formula in G2 is:
=INDIRECT(VLOOKUP($E2,myMultipliers,MATCH(G$1,myMultiplierTitles,0),FALSE)&ROW())*VLOOKUP($E2,myMultipliers,MATCH(G$1,myMultiplierTitles,0)+1,FALSE)
INDIRECT returns the value of a cell that you refer to by name (text/string) as opposed to directly (as a range). For example:
=INDIRECT("A1")
returns the same as
=A1
...but with INDIRECT we can get the name from elsewhere (a cell, function or formula). So if x="A1" then =INDIRECT(x) returns the same as the 2 above examples.
Your original plan of storing the entire formula in a table as text would have worked with the help of INDIRECT and/or EVALUATE but I think this way is considered better practice partly because it facilitates easier future expansion.
The formula is longer than it would have been, but that's mostly because it's dynamically reading the field names. And size doesn't matter. :-)

How to change the GETPIVOTDATA() dynamically

I have two formulas like below:
=GETPIVOTDATA("Sum of Values",'Input Data'!$A$4,"State",Q42,"Route",$S$1,"STAT_COMB",$G$37,"SHA",$G$35)
=GETPIVOTDATA("Sum of Values",'Input Data'!$A$4,"State",Q42,"Route",$S$1,"STAT_COMB",$G$37)
The main difference in the second formula is, I'm not considering the "SHA" parameter. To consider this or not depends on another cell value. I can write an if condition to pick the formula accordingly. But the problem is I have another situation like this:
=GETPIVOTDATA("Sum of Values",'Input Data'!$A$4,"Route",Q42,"STAT_COMB",$G$37)
Here, I'm not considering the "State" and "SHA" parameter which depends on a respective different cells whether to consider or not.
Similarly each [Field],[Item] Pair in the formula depends on respecitve different cells to include them or not.
Writing too many if conditions will make the formula cumbersome. So, I'm wondering if there is any way to dynamically omit the [Field],[Item] pairs in the formula.
I could've used INDIRECT inside the getpivotdata() but INDIRECT fetches only a single value but I need a pair of values for each parameter.
This is the best I could figure out...but it isn't necessarily pretty...
The challenge here is that you can't (to my knowledge and without VBA) dynamically change which overloaded GETPIVOTDATA function you are using in a cell. So we need to pick 1 function. In this example, here's my function:
=GETPIVOTDATA("Sum of hello",INDIRECT(K2),M1,O1,M2,O2,M3,O3,M4,O4)
I've picked an overload that specifies 4 [field,item] pairs.
Now I set up my worksheet like this...
You see -- for this example, I only want to use 2 [field,item] pairs -- so I just copy the parameters to fill in the remaining 2 pairs in the overloaded function. Excel still calculates the GETPIVOTDATA function correctly since I really have only specified 2 unique [field,item] pairs.
Does this get you far enough towards your goal?

Run a text formula in an adjacent cell

I'm having trouble trying to figure out a way to have two columns, one to show the entire formula that can be editable and the second to actually perform the formula.
Ideally, I would like my sheet to be set up like this:
Formula | Value
=5+2 | 7
=3-2 | 1
I would like to be able to change the Formula column and have it automatically update the Value column.
I've tried using the GetFormula() function but I don't think that's what I want to do as I would end up in a circular reference based on what I want to do. The closest I've got is using a Right() function and Text in the formula column or a space and removing the space. However, I end up with the text and not the solved formula instead.
Using =RIGHT(A2, LEN(A2)-1)
Formula | Value
=5+2 | =5+2
I have also tried using =RIGHT(A2,LEN(A2)-1) but without the "=" and can't figure out how to convert the "5+2" into text that I can use to solve. I'm hoping to do this with a formula and without a macro/VBA.
Here is how to do it.
1
Open the Name Manager. Control-F3 from the worksheet, and then click the New button.
2
For the Name field in the dialog, enter EVALA. I just picked this name; it stands for "Evaluate A". But you can pick whatever name you like.
3
For the Refers to field, enter this
=EVALUATE($A1)
4
Click OK and then Close.
5
In B1 enter this formula:
=EVALA
That's it.
You can now use this formula on any row in the worksheet and it will evaluate whatever is in the column A cell of the row where you enter the formula.
You can make a user defined function easily enough with VBA, but if you don't regularly use VBA then an alternative method is to create a Name object. Name objects can access certain functions not typically available in a cell's formula. One of these functions is "Evaluate" which will evaluate a string as a mathematical expression. Here's a demonstration how to do this.
NOTE: Pay special attention to the use of $. Chances are you don't want any $ in your name definition since that will prevent it from behaving in a relative manner. Also, Sheet1! means that this will not work on another sheet.
Update I just want to give credit for this method to the following sources. This is pretty neat stuff, so for anyone interested give it a read. The last link in particular gives a neat example of creating a chart with no data points.
MSDN Evaluating Defined Names
The power of evaluate (ozgrid)
XL4 Macro Functions in Names - JKP
Evaluate and Indirect
More unique functionality of Defined Names
This is probably the best solution for the OP, since it asks to avoid using VBA; however, this method is somewhat limited. It requires manual set-up on every sheet to be used. Much preferable I think is to create a very simple UDF like this...
Function Eval(Expr As String)
Eval = Application.Evaluate(Expr)
End Function
This can be added to any accessible add-in, making it available to any instance of Excel. A little more set-up, but less maintenance.
Just put a single ' before the formula in your A column:
'=5+2 will show in your cell as "=5+2". Then in the B column, just do the formula as normal, =5+2.

Resources