excel return formula with relative cell - excel

I have 2 worksheets in my excel, the first sheet allows me to select a calculation method from a drop down list and input the variable for the calculation (shown in green cell, the column in blue shows some constant number). The result entry will search for the corresponding calculation formula from my second worksheet (database), then paste the formula to the sheet 1, I need the formula to calculate using the cells in sheet 1 instead of cells in my database.
currently I created an user defined function called Eval as below:
Function Eval(ref As String)
Eval = Application.Evaluate(ref)
End Function
by combining the Eval with vlookup :=Eval(VLOOKUP(A3,Database!A2:E10,5,FALSE)) I will get the result that the calculation equation uses the cells from my database, how can I achieve the result which the formula takes cells in sheet 1 during calculation?

One simple way would be to use all formulas within one CHOOSE like this:
=IFERROR(CHOOSE(SUMPRODUCT(MATCH(A2,"Calculation "&ROW($1:$9),0)),B2*C2*D2,B2*C2-D2,B2+C2-D2,B2^2-C2+D2,B2*D2-C2^2,B2+C2*D2,B2*C2-C2*D2,B2-D2-C2*D2,C2-D2*B2),"")
Another would be to use the Application.Caller like:
Public Function eval(ref As String)
eval = Application.Caller.Parent.Evaluate(ref)
End Function
This ensures the use of of the parent of the caller (the sheet with the eval() formula) to be used as main-ref.
EDIT
Keep in mind that your "rows" are static in the formulas. Going for "Calculation 4" will use row 5 (and not the row of your formula from the first sheet). For this you could use something like:
=Eval(SUBSTITUTE(VLOOKUP(A3,Database!A2:E10,5,FALSE),"##",ROW()))
While all row-numbers should be changed to ## (or whatever unique identifier you like). Then "Calculation 1" would look like: =B##*C##*D##
If you still have any questions, just ask :)

Related

Excel - Identify if Worksheet exists between two worksheets?

I have 5 worksheets: (1) Summary (2) 2020 (3) 2019 (4) 2018 (5) 2017
In my "Summary" worksheet, I have Column A with cells each containing the name of each worksheet (A1: 2020, A2: 2019, A3: 2018, A4: 2017) and Column B with the number "1" in each corresponding row.
Let's say I delete the "2019" worksheet so that it is no longer between worksheets "2020" and "2017" - is there any formula that I could use to flag that in row 2? Perhaps through some sort of "if(..,1,0)" formula for Column B? I do not want to use VBA.
There are various error-checking functions available in Excel, and most of them would be appropriate for your situation. The simplest would be to use IFERROR and just refer to a cell on one of the sheets, like this:
=IFERROR('2020'!A1,"Missing")
If the formula receives an error value because it can't find the cell, it will display the text "Missing"; otherwise, it will show the value of the cell.
The disadvantage of doing it this way, hard-coding the sheet name into the function, is that if the sheet is deleted the sheet name will be replaced in the formula with #Ref!, so even if the sheet is restored the formula will need to be changed.
We can enhance the functionality by using an INDIRECT along with the IFERROR. This will take a text string and turn it into a cell reference. So assuming we have worksheet names in column A, we could do this:
=IFERROR(Indirect(A1 & "!A1"),"Missing")
The INDIRECT function takes the value in A1 and combines it with the text string, and reads the whole thing as a cell reference. This has the same result, but is more robust since deleting the sheet and then replacing it will clear the error.
For a slightly more elaborate result, we could next IF and ISERROR instead of using IFERROR. It gives us more control over the result.
=IF(ISERROR(INDIRECT(A1 & "!A1")),"Missing","Found")
ISERROR returns TRUE if the first argument throws an error, an FALSE if it does not. This will return "Found" if the sheet is present, or "Missing" if it isn't.

combine all cells, numbers and symbols to a sum

Good day,
I'm at a loss on this problem.
I have a group of cells that contain words, like apple, this word would be the value. It is separated by a symbol for completing the math. They can be changed by the user to make custom calculations.
Cell A1 is "apple", B1 is "+", cell C1 is "apple", cell D1 is "*", cell E1 is "apple", call F1 is "=" and cell G1 is the suggested total, in this case would be "6".
It would be posted as | apple | + | apple | * | apple | = | 6 |
The legend holds the value for the word, so if you enter 2 in the legend, apple would be 2.
The logic would determine that the formula would be 2+2*2= if written in excel, I would like to combine all the cells and calculate this.
I tried using =sum, sumproduct, concate and the like to no avail.
Any head way I did make, I ended up getting BEDMAS wrong as it calculated it as 2+2=4*2=8, instead of the correct 2*2=4+2=6.
Anyone know of a way to combine these cells and properly sum the values to the correct total?
Thank you for your time!
Go to the Name manager and create named range Eval, into Refers to field add formula:
=EVALUATE(CONCATENATE(VLOOKUP(Sheet1!A1,Sheet1!$A$3:$B$5,2,0),Sheet1!B1,VLOOKUP(Sheet1!C1,Sheet1!$A$3:$B$5,2,0),Sheet1!D1,VLOOKUP(Sheet1!E1,Sheet1!$A$3:$B$5,2,0)))
In range A3:B5 I have legend.
Change references as you need. Then in cell G1 write formula =Eval.
Sample:
This is a UDF based solution. Its advantage is that it's more versatile and by far easier to maintain if you learn its elements of code. The disadvantage is in that you do have to learn the elements of code and you have an xlsm macro-enabled workbook which isn't welcome everywhere.
The setup is simple. I created a table with columns Item and Value. I placed it on another sheet than the task. In fact, you could make the sheet with the table VeryHidden so that the user can't look at it without access to the VBA project, which you can password protect. I called the table Legend. The item columns has names like apple, pear, orange. The Value column has the numeric values associated with each name.
Note that, since this is a VBA project, the entire list can be transferred to VBA leaving no trace on the sheet. You could have a function to display the value of each item as the user clicks on it and have it disappear as he clicks elsewhere.
Next I created a data validation drop-down in A1 with the List defined as =INDIRECT("Legend[Item]"). Copy this cell to C1 and E1.
Then I created another Data Validation drop-down in B1 with the list as +,-,*,/. This drop-down must be copied to D1.
Now the code below goes into a standard code module. Find the way to create it because it isn't any of those Excel sets up automatically. It's default name would be Module1. Paste the code there.
Function Evalue(Definition As Range) As Double
Dim Task As String
Dim Fact(2) As Double
Dim C As Long
Dim i As Long
With Definition
For C = 1 To 5 Step 2
On Error Resume Next
Fact(i) = Application.VLookup(.Cells(C).Value, Range("Legend"), 2, False)
i = i + 1
Next C
Task = "(" & Fact(0) & .Cells(2).Value _
& Fact(1) & ")" & .Cells(4).Value _
& Fact(2)
End With
Evalue = Evaluate(Task)
End Function
Now you are ready for testing. Call the function from the worksheet with a call like
=Evalue(A1:E1). You can use it in comparisons like =IF(G6 = Evalue(A1:E1), "Baravo!", "Try again"). As you change any of the components the cell with the function will change.
Remember to use absolute addressing if you copy formulas containing the range. If you need to get a result in VBA while testing, use this sub to call the function.
Private Sub TestEvalue()
Debug.Print Evalue(Range("A1:E1"))
End Sub
My Sheet
Here is what I have.
In cells M - U, i count all the instances of the word from cells E, G and I from the legend.
=SUMPRODUCT((LEN(E3)-LEN(SUBSTITUTE(E3,$B$3,"")))/LEN($B$3))
In cells W - AE, I multiply the instances with the value to give me a total each time the word appears.
=SUM(M3*$C$3)
In cell E8 - I8, i add the three possible values together.
=SUM(W3:Y3) so each worded cell is now a number.
I'd like to take the cells E8 - I8 to make a calculation in k8 and so on.
So, each cell is put together to make an
=SUM(E8:I8)
statement, which all works except E11 - I11 which equates to 26 instead of 43.

Excel Formula - Check if cell has formula

What formula do you use to check if another cell has formula? For example, I have 2 columns, A has cells which contains either a formula or a value.
(Column A usually contains Formulas but other users try to change their values by directly typing and replacing the formula that was previously there)
In Column B I want to add a formula that will say "HasFormula" if the cell on Column A has formula and say "PlainValue" if it contains a value.
I'm thinking maybe using =ISNUMBER() but that may not be accurate.
I am using Excel 2010.
Excel actually has a builtin ISFORMULA() function.
Say A1 has a formula and you want to check that. In say B1, you can use:
=If(ISFORMULA(A1),"HasFormula","PlainValue")
Edit: Per your comment, you don't have ISFORMULA(). An alternative is to create a quick UDF, and use the custom function in the worksheet.
In a workbook module, put this code:
Function isFormula(ByVal target As Range) As Boolean
isFormula = target.hasFormula
End Function
Then you can call it like this: =isFormula(A1) and it will return TRUE if A1 has a formula.
If you can't use VBA, then you can use this formula:
=IF(ISERROR(FORMULATEXT(A1)),"PlainText","HasFormula")
The MrExcel website (link below) has this method which uses old code from Excel 4 (which is still present for backward compatibility)...
Define a NAME such as "CellToLeftHasFormula" and in the "refers to" box put
=GET.CELL(48,OFFSET(INDIRECT("RC",FALSE),0,-1))
Then in column B use the formula =CellToLeftHasFormula which will return TRUE if it has.
Be aware that this will mean your Excel will now contain a macro and so will need to be saved as such (xlsm). I use this in Excel 2010.
For full explanation (and other .CELL options, besides 48) see MrExcel link: https://www.mrexcel.com/forum/excel-questions/20611-info-only-get-cell-arguments.html
You can use the Range.HasFormula property.
https://learn.microsoft.com/en-us/office/vba/api/excel.range.hasformula
EDIT:
Text and code from the above link:
"True if all cells in the range contain formulas; False if none of the cells in the range contains a formula; null otherwise. Read-only Variant. ..."
Worksheets("Sheet1").Activate
Set rr = Application.InputBox( _
prompt:="Select a range on this worksheet", _
Type:=8)
If rr.HasFormula = True Then
MsgBox "Every cell in the selection contains a formula"
End If
You can restrict the user by protecting the column A.
You can directly check if a cell contains a formula by using a shortcut Ctrl + `.
You can use vba and write a user defined function :
1. Press alt + F11
2. Insert module in workbook
3. Paste this code
Function IsFormula(cell_ref As Range)
IsFormula = cell_ref.HasFormula
End Function
4. Now, use Isformula in the cell wherever you want.

referencing sheets by number instead of name in cells

Lets say
sheet3.name = "d"
Is there a way I could put in a cell on sheet2 the formula =sum(sheet3!b:b) where sheet3 is being substituted with the actual sheet3 name?
I can only get =sum('d'!b:b) to work so far.
I could use VBA for this probably but I'm curious how to do this in a cell so I don't have to run a macro each time.
If you can use a UDF User Defined Function that will return the sheet name
Function SHEETNAME(number As Long) As String
SHEETNAME = Sheets(number).Name
End Function
then a formula like
=SUM(INDIRECT(SHEETNAME(3) &"!B:B"))
will return the sum from column B on sheet 3.
SHEETNAME(number) returns the sheet name of the number which is index.
So Sheet(1) returns Sheet1, etc
Use below formula anywhere in the sheet to get the sheet name - the sheet must have a filename for this to work:
=REPLACE(CELL("filename"),1,FIND("]",CELL("filename")),"")
You can either reference that cell using Indirect:
=SUM(Indirect("'"&A1&"'!B:B"))
or, if you don't want to have a second cell, you can combine the two formulas into one:
=SUM(INDIRECT("'"&REPLACE(CELL("filename"),1,FIND("]",CELL("filename")),"")&"'!B:B"))
For anyone not concerned with the order of the sheets, the post by Biff here on mrexcel.com works well.
In Excel 2013, go to the Formulas tab in the ribbon and make a defined name:
Name: SheetNames
Refers to: =GET.WORKBOOK(1)&T(NOW())
Then use a formula like this example:
=INDIRECT("'"&INDEX(MID(SheetNames,FIND("]",SheetNames)+1,255),A3)&"'!A1")
where A3 refers to the index number in a cell in the current sheet, and A1 refers to the location of the value to be retrieved from the other sheet. I.e., in the current sheet, if A3 = 2, then the formula will point to cell A1 in the second sheet of the workbook. I just use a column of index numbers in my current sheet, then drag this formula down and it fills in values from all of my other sheets.
You will need to save as a macro-enabled file (.xlsm).
I'm not sure if this is a good idea but it's the first one I could think of.
I would add additional function to your VBA project which will return actual name of your Sheet3:
Function Sheet3Name()
Sheet3Name = Sheet3.Name
End Function
Next, when you create sum formula of column B:B in Excel cell you need to do it in this way:
=SUM(INDIRECT(Sheet3Name()&"!A:A"))

Excel - Selecting from cell A1 to AX, where X is read in cell B1

I have an Excel with 2 worksheets, first will be dinamically filled with data, having a row with a combo box feeding from row A on the second worksheet.
The second worksheet will also be filled dinamically, where will be:
Row A:
some values of variable number
B1 - Number of values on Row A to considerate.
My question is - Im using Data Validation > List to define the values on the ws1rowA combo box, is it possible to range from A1 to A(value in B1) ?
So far tried this on Data Validation "source" field:
=Sheet2!$A$1:offset(Sheet2!$A$1,=Sheet2!$B$1,0,1,1)
but an error is returned
You can also use INDIRECT function for this.
=INDIRECT("Sheet2!$A$1:$A"&Sheet2!$B$1)
In my version of Excel "You cannot use references to other worksheets or workbooks for Data Validation criteria" but you can use named ranges that have a Workbook Scope, so name a range (eg DataValid) to apply to say the range as #Maxim Korneev and then for Data Validation in Sheet1 use a list whose Source: is =DataValid.
Sure, just use
=OFFSET(Sheet2!$A$1,0,0,Sheet2!$B$1,1)

Resources