Analyzing a formula-tree to consolidate formula - excel

Excel formulas are often linked with each other.
Example:
As you can see, there is data labelled α-ε.
The final result is some function that is depending on α-ε.
f(α,β,γ,δ,ε) = g(α,β,γ,δ,ε) / h(α,β,γ,δ,ε)
Now I'd like to see how changing α (or β) impacts the final result. To do this, I could use the scenario manager, but I'd like to do a do it with VBA.
The problem is, I don't know the final function! I know that the function is something like =SUM(.....)/PRODUCT(PRODUCT(SUM(...))..), but to produce the output I'd need to have the full function in some VBA-comprehensive form.
To do this, one could see it as a tree. Root being my total, every sub-calculation is a root-child. Every sub-calculation in these childs is yet another child. And by somehow putting all the leafs of the tree together, you could find out the final enormous function.
Does anyone have an idea on how to tackle this problem?
EDIT: Some more info on what I meant:
Say E3 as my output has the function =SUM(E4;E5).
It is the root of our tree. Now we take a look at all of its components: E4 and E5. Let us do that:
Say E4 as has the function =PRODUCT(2;2).
Say E5 as has the function =SQRT(3).
My question: How do I get a formula that instead of saying
=SUM(E4;E5)
it says
=SUM(PRODUCT(2;2);SQRT(3))

Related

Excel's LAMBDA with a "kind of" composite function

Ever since I learnt that Excel is now Turing-complete, I understood that I can now "program" Excel using exclusively formulas, therefore excluding any use of VBA whatsoever.
I do not know if my conclusion is right or wrong. In reality, I do not mind.
However, to my satisfaction, I have been able to "program" the two most basic structures of program flow inside formulas: 1- branching the control flow (using an IF function has no secrets in excel) and 2- loops (FOR, WHILE, UNTIL loops).
Let me explain a little more in detail my findings. (Remark: because I am using a Spanish version of Excel 365, the field separator in formulas is the semicolon (";") instead of the comma (",").
A- Acumulator in a FOR loop
B- Factorial (using product)
C- WHILE loop
D-UNTIL loop
E- The notion of INTERNAL/EXTERNAL SCOPE
And now, the time of my question has arrived:
I want to use a formula that is really an array of formulas
I want to use an accumulator for the first number in the "tuple" whereas I want a factorial for the second number in the tuple. And all this using a single excel formula. I think I am not very far away from succeeding.
The REDUCE function accepts a LET function that contains 2 LAMBDAS instead of a single LAMBDA function. Until here, everything is perfect. However, the LET function seems to return only a "single" function instead of a tuple of functions
I can return (in the picture) function "x" or function "y" but not the tuple (x,y).
I have tried to use HSTACK(x,y), but it does not seem to work.
I am aware that this is a complex question, but I've done my best to make myself understood.
Can anybody give me any clues as to how I could solve my problem?
Very nice question.
I noticed that in your attempts you have given REDUCE() a single constant value in the 1st parameter. Funny enough, the documentation nowhere states you can't give values in array-format. Hence you could use the 1st parameter to give all the constants in (your case; horizontal) array-format, and while you loop through the array of the 2nd parameter you can apply the different types of logic using CHOOSE():
=REDUCE({0,1},SEQUENCE(5),LAMBDA(a,b,CHOOSE({1,2},a+b,a*b)))
This way you have a single REDUCE() function which internal processes will update the given constants from the 1st parameter in array-form. You can now start stacking multiple functions horizontally and input an array of constants, for example:
=REDUCE({0,1,100},SEQUENCE(5),LAMBDA(a,b,CHOOSE({1,2,3},a+b,a*b,a/b)))
I suppose you'd have to use {0\1} and {1\2} like I'd have to in my Dutch version of Excel.
Given your accumulator:
Formula in A1:
=REDUCE(F1:G1,SEQUENCE(F3),LAMBDA(a,b,CHOOSE({1,2},a+b,a*b)))

EXCEL - Circular Reference Error when Entering Data

I've got another one that is really kicking my butt.
I know why the error is occurring. I just don't know how to fix it. There are a lot of IF statements so I'm thinking maybe they are arranged in a way that is causing the error. I'm sure there is a much cleaner way to write them.
Whenever I try to input data into D7 or E7 I get the circular reference error.
These are my current formulas for all relevant cells:
F7: =IF(C7<0,"FAIL",IF(OR(ISBLANK(B7),ISBLANK(C7))," ",IF(ABS(F8)<=30,"PASS","FAIL")))
G7: =IF(D7<0,"FAIL",IF(OR(ISBLANK(B7),ISBLANK(D7))," ",IF(ABS(G8)<=30,"PASS","FAIL")))
H7: =IF(E7<0,"FAIL",IF(OR(ISBLANK(B7),ISBLANK(E7))," ",IF(ABS(H8)<=30,"PASS","FAIL")))
F8: =IF(B7<0,"",IF(C7<0,"",IF(D7<0,"",IF(E7<0,"",IF(G7="FAIL","",IF(H7="FAIL","",IF(ISBLANK(B7),IF(ISBLANK(C7),"","input Lw_Lw"),IF(ISBLANK(C7),"input Lw_Up",SUM(C7-B7)))))))))
G8: =IF(B7<0,"",IF(C7<0,"",IF(D7<0,"",IF(E7<0,"",IF(F7="FAIL","",IF(H7="FAIL","",IF(ISBLANK(B7),IF(ISBLANK(D7),"","input Lw_Lw"),IF(ISBLANK(D7),"input Up_Lw",SUM(D7-B7)))))))))
H8: =IF(B7<0,"",IF(C7<0,"",IF(D7<0,"",IF(E7<0,"",IF(G7="FAIL","",IF(F7="FAIL","",IF(ISBLANK(B7),IF(ISBLANK(E7),"","input Lw_Lw"),IF(ISBLANK(E7),"input Up_Up",SUM(E7-B7)))))))))
Snip of Excel table
Any help would be much appreciated!
I worked out the following two formulas for you. Please try them.
[F7] =IF(IFERROR(ABS(F8)<=30,FALSE),"PASS","FAIL")
[F8] ==IF(ISBLANK(C7),"input "&F$3,IF(OR(COUNT($B7:$E7)<4,COUNTIF($B7:$E7,"<0")>0),"",SUM(C7-$B7)))
Copy them from F7:F8 to G7:H8.
The basic principle I applied in order to avoid a circular reference is to do all testing in row 8 with the outcome that F8 will either hold a blank or a number. Therefore "Pass" or "Fail" in row 7 can be decided based on the number: If the number is within range it's a PASS, else it's failed. Note that Abs("") will cause an error. Therefore IFERROR(ABS(F8)<=30,FALSE) will return False in case F8 = "". Effectively, this is the reverse of what I wrote in my comment above.
I looked for shorter expressions for other tests as well. Count() will only count cells with numbers in them. Therefore I use this function instead of a series of ISBLANK() queries. Similarly for COUNTIF($B7:$E7,"<0").
I used mixed absolute and relative addressing to enable copying formulas to other columns and referred to the column captions in place of repeating the same texts in the formulas.
I didn't fully test my solution. However, with my above explanation as a guide you should be able to take possession and eliminate any errors I might have left behind.

Return the value in the first non-empty cell in the column directly to the left and going upward

I'm all new to VBA and have mostly been trying to modify code after recording macros, so it's all pretty basic and the approach might not be as elegant as some of the stuff I've seen on here. So here we go.
I have coded (by brute force) my data to be arranged like a CAD design tree view with parent products/assemblies and constituent sub-assemblies/parts.
Column E contains Level 0 top assembly Part Number
Column F contains Level 1 items Part Number
... etc all the way to ...
Column M containing Level 8 items Part Number
As an example, cell G112 contains ASSY1; cells H113 to H134 contain its constituent items.
I would like to display in a new column (i.e. Column O) the value of cell G112 (ASSY1) for each of its constituents. So O113 to O134 would show the value of G112. That would need to be applied to every single level of the assembly.
I'm not sure I'm making much sense do please have a look at the picture linked below, it speaks a thousand words. I've highlighted and colour-coded the result I would like in column O.
ADDENDUM - To clarify things:
I don't know how else to explain my request but to post a simplified version of my original picture.
SIMPLIFIED EXCEL TABLE
.CSV available here WeTransfer
A very useful tool to retrieve VBA code for determined action is the macro recorder, in the ribbon, Developer -> RecordMacro, perform you action and stop recording and then you can check the code generated for the actions you recorded. Its not the cleanest code but you can find there the lines of code for the specific actions you want. Once you step into a one concrete problem with the code you tried, you can then ask for help regarding something more concrete, more than expecting that someone will code that for you.
Anyhow if you want someone to try to solve your problem, you need to post the table with the accessible data instead of the image, for the person whoever tries to approach your problem to have the data available.
Hope that helps
Here's the answer I got from somewhere else if anyone is interested:
Formula in Cell O3:
=IF(C3=0,"N/A , ALREADY TOP LEVEL",INDEX(D$2:D2,AGGREGATE(14,6,(ROW(D$2:D2)-ROW(D$2)+1)/(C$2:C2=C3-1),1)))
Copy/Paste down in every cell in column O

Renaming CUBEVALUE function to something shorter?

I've been using a rather long embedded CUBEVALUE() function, which is a pain to work with. It looks something like:
=IFERROR(VALUE(CUBEVALUE(arg1;arg2;arg3));CUBEVALUE(arg1;arg2;arg3))
Due to the CUBEVALUE function and its arguments, it's becoming a REALLY long function and thus not easy to work with. Since there are only 3 arguments, which are written in different cells, I'd like to create something like
=MyFunction(A1,A2,A3)
and use A1, A2 and A3 as "arg1, arg2, arg3" in the function mentioned first. This way its possible to "pull" the function so it would calculate using the input in B1:B3 and C1:C3 etc. as well.
The function works fine and can be pulled through and such, but my question is how to rename this loooong function into something more user-friendly, as it requires only 3 cells as an input and the rest of the text in the function just makes it hard to use for end-users.
Using UDF is not an option because CUBEVALUE can't be called through VBA... and any attempt to stich strings together and using the final result with INDIRECT also seems to fail..
In a similar question on this site, someone refers to using "asynchronous UDF's", but no further information was given (and what I could find seemed irrelevant).
You shouldn't really have several long cube functions. Allocate some space in hidden rows/columns or in header rows/columns to add your cubemember functions. Then throughout most of your report, you should just have cubevalue functions that reference other cells with error handling around them. Proper use of absolute and relative references are your friend.
Peter Meyers has some great tips for this here, slides 20 - 24. I have an example Excel file with cube functions on my blog here.

Excel Named Function Parameters or UDF without Macros

It seems like a bit of an omission that there's no easy way to create a user-defined declarative function in Excel without defining a macro. I can't use XSLM with the uphill battle that will entail in the Enterprise, but I want to be able to define a function with intent thus.
I want to do this;
=BreakEven(C1:C20)
But I can't use a macro, although I can use a "named formula". The trouble is how to pass parameters to that? I've seen a couple of tricks (kludgy workarounds) but not for xslx.
I'd like to be able to define a Breakeven() function in another tab and reference it here passing in MORE THAN one parameter, two ranges in fact. I'm sure there's some way using string parsing but I can't see it.
I don't mind if the function doesn't look exactly like that, as long as it evaluates within the cell and I can parse it for 'intent'. For instance, this example (http://www.jkp-ads.com/articles/ExcelNames09.asp) which I was unable to get to work in xlsx uses this syntax;
=IF(ROW(D3),CellColor)
Where "cellcolor" is the name of the function and D3 is the range parameter. The other solution I'm toying with is to define a function in column format with a variable argument list (this is two rows of an excel spreadsheet);
[Value][function][parameter1][parameter2][parameter3]
24050 BreakEven C1:C20 A1:A20
It's not pretty, but the benefit of the latter is that it describes the function to an external reader. We know it's a breakeven function, whereas if we put the actual formula "OFFSET,INDIRECT,SUM()()()()etc" it would not be readable/parseable. Of course, in that case, I'd have to construct the value field by parsing the cells to the right in Excel, which would make the Value formula messy but at least it would be a self-describing row.
Can anyone suggest a better method?
Poor-man's UDF
So I think what we're going to have to do is this;
A B C D E
1 [Value][function][parameter1][parameter2][parameter3]
2 24050 BreakEven C1:C20 A1:A20
3 111 mySum 1 10 100
Where "BreakEven" is a "named function". Here's the formula for "mySum";
=sum(C1:E1)
To evaluate functions listed in B, we just put this in column A (transposing the same value for all rows in column A;
=value(B)
This works because A2 and A3 both evaluate column B as a value, which causes BreakEven and Sum to run (as poor-man's UDFs) in the context of A2 and A3. The range (C1:E1) is relative of course.
So in effect, we can write any function name in column B (as long as there's a corresponding named function defined in the workbook which can be as complex as you like). Columns C, D and E act as the parameters for the function on the same row.
I would have loved to just be able to write the following in column A instead;
=mySum(1,10,100)
But in the absence of that support, the mechanism above serves to provide a readable parameterised function that would be understandable by a user, that's also machine readable (works in CSV too) and allows us to offload our re-usable functions to a library sheet somewhere in the workbook for maintenance.
Not perfect, but an acceptable compromise, unless anyone has a clever way of doing this in a single cell?
Not really an answer, but easier to illustrate here than in a comment. Although you can't rename formulas in a simplistic way - I like your suggestion actually I've never thought about that before; but then I've never worked in a non-macro environment so this has never occurred- you can add notes into the actual formula explaining what it does. For example:
=N("This is a really complex BreakEven Formula")+SUM(3,4,5)
Is a perfectly valid formula. As I said, not really an answer, but could potentially add clarity to a complex formula
You can do this with a small trick
For example to create effectively a cuberoot UDF that emulates =cuberoot(x) then name a variable as cuberoot with a 'value' like this.
=(RC[-1])^(1/3)
Now you can either do this using a temporary switch to RC mode, or put the cursor in say cell E5 and type the name value as =(D5)^(1/3)
Now whenever you need a cuberoot you can put the argument in any cell and put =cuberoot in the cell to its right. It really works and follows true Excel rules.
I use it for multiparameter models that have the single 'argument' Time as a dependent variable. I then define the term Model as the model equation eg =a+bTime+cTime^2
where a,b,c are already named locations holding unique parameter values -
and then define Time as =RC[-1]
My sheets are filled with cells simply saying =Model and have the required time value to the left (ie their argument). It is simple to extend to multi arg functions using multiple cells. It usually fits in well with spreadsheet layouts. Change the definition of your model once in the define name box and all places change simultaneously.
I have a function called ToDMS which takes the decimal degree value in the preceding cell and converts it to a deg Min and Sec string - very tidy.
You need the degrees to be in a single cell but want it in the alt. form in another cell
elegant, simple and it works
Bob Jordan

Resources