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.
Related
Instead of writing the formula multiple times at multiple instances, I'd like excel to detect the formula based on a defined reference.
Column F should be calculated based on the Operation defined in column E. In this example, I can use IF() as I only have 4 Operations but this question is linked to another scenario where I have over 20 Operations.
I have all the formula's ready but I'd love to understand if there is way to use the appropriate formula based on "Operation" Column.
I would approach your situation by labeling your Column A, B, C, or X, Y, Z or something similar for consistent readability with your formulas.
Second thing I would do is build your formula table similar to what you have except that I would change your formula from being sheet and cell references to being you variable references:
A+B+C+D
A-B-C-D
A/B/C/D
A*B*C*D
Make sure the formulas are written with operators the same way you would if you were using a cell reference.
Then based on your lay out on sheet 3 I would use a VLOOKUP:
=VLOOKUP(E2,SHEET4!$A$2:$B$5,2,0)
Place that in F2 and copy down. That will tell you if you are pulling the right formula or not.
In G2 use the following:
=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(F2,"A",A2),"B",B2),"C",C2),"D",D2)
Check this to see that your substitution of your values for your variables is correct.
Then select cell H2 to make it the active cell. Then go Formula Ribbon and select Define Name from the Definied Names section.
Give a name for your formula such as ANSWER.
For your formula use
=evaluate(G2)
once you have added the defined formula to the list of formulas go to cell H2 and enter the following:
=ANSWER
now if you want to avoid all those helper columns, you can substitute one formula into the other.
I'm going around in circles with this and have tried as many different options as I can think of - VLOOKUP, INDEX/MATCH, IF etc... but I'm failing everytime.
I need to create a drop down list in sheet 3 (column A) that gets populated with values in column B of sheet 2, only where the value in column G of sheet 2 is "Yes". The values in sheet 2 look as follows:
This is what is shown at present:
I am using the following formula within Name Manager to get to this point:
=OFFSET(Units!$B$11,0,0,COUNTIF(Units!$B$11:$B$202,">"""),1)
and although this works, it's not quite as I need it to be. I've tried using Index/Match, small, VLOOKUP etc... but Excel reports that either I've too few arguments or can't reference a worksheet.
I've literally been though as many excel websites as I can find but no one seems to cover creating drop down lists where the drop down is dependent on a specific selection.
The values within sheet 2, column B are obtained from a hidden sheet and collected using the following query:
=IF(ISERROR(INDEX(All_Units!$D$2:$D$660542,MATCH(Units!A11,All_Units!$C$2:$C$660540,0))),"",INDEX(All_Units!$D$2:$D$660542,MATCH(Units!A11,All_Units!$C$2:$C$660540,0)))
I wondered whether I could take this query and use it to generate the drop down list, something along the lines of:
=INDEX(Units!$B$11:$B$202,MATCH(Units!$G$11:$G$202="Yes",Units!$G$11:$G$202,0)))
but this returns an error. The closest I got was using the OFFSET formula above but performing a COUNTIF, however; this unsurprisingly wouldn't tie Column B to the corresponding 'Yes' in column G.
Does anyone have any ideas as to how I can get this working?
You will need to create another sheet into which you will place an array formula. This formula will return all the desired output.
so create a sheet and name it something like DataVal
In A2 put the following array formula:
=IFERROR(INDEX(Units!$B$11:$B$202,MATCH(1,(Units!$G$11:$G$202="Yes")*(COUNTIF($A$1:A1,Units!$B$11:$B$202)=0),0)),"")
Being an array formula it needs to be confirmed with Ctrl-Shift-Enter. If done correctly then Excel will put {} around the formula.
Then copy/drag down far enough to ensure capturing every possible return.
Then use another INDEX/MATCH to create the named range (OFFSET() is volatile and should be avoided when possible). The formula would be something like:
=DataVal!$A$2:INDEX(DataVal!$A:$A,MATCH("ZZZ",DataVal$A:$A))
This will dynamically set the named range to the extent of the dynamic list created by the array formula above.
I have the names of the tabs/worksheets (M-61,M-62,M-63W) at the top row (A1, B1, C1...etc)
I am trying to get a sum of several cells within the different sheets:
=SUM('M-60'!H21,'M-60'!H43,'M-60'!H86,'M-60'!H87,'M-60'!H97,'M-60'!H98)
However, right now I’m referring to the sheet itself, and have to apply the same formula to all the other sheets. This will require me to manually go and change all the sheet titles accordingly.
I was wondering if there is any way to reference the top row with the sheet titles within the formula so it automatically refers to the row text instead of me having to manually change the sheet title.
Edit
Now i got the reference to work, just wondering how would I do a sum of several cells in that tab
=INDIRECT("'"&$F1&"'!H87",TRUE)
Maybe:
=SUM(INDIRECT("'"&C1&"'!H21"),INDIRECT("'"&C1&"'!H43"),INDIRECT("'"&C1&"'!H86:H87"),INDIRECT("'"&C1&"'!H97:H98"))
(though there may well be a much smarter way).
You can use the INDIRECT function, which uses a string as an argument and converts it to a range. So
=M-60'!H21
is the same as
=INDIRECT("M-60'!H21")
or, if Sheet name is stored in, say, cell C1:
=INDIRECT(C1&"'!H21")
Your example has a SUM, though, which requires some adaptations. This your example:
=SUM('M-60'!H21,'M-60'!H43,'M-60'!H86,'M-60'!H87,'M-60'!H97,'M-60'!H98)
Since you are not using a range, you can convert that SUM into simple addition. Assuming Sheet name in cell C1
=INDIRECT("'"&C1&"'!H21")+INDIRECT("'"&C1&"'!H43")+INDIRECT("'"&C1&"'!H86")+INDIRECT("'"&C1&"'!H87")+INDIRECT("'"&C1&"'!H97")+INDIRECT("'"&C1&"'!H98")
This should solve your problem. More info here
By the way, if you were using a range, the OFFSET function with INDIRECT as an argument would work. But that's not necessary here.
I know there's several posts about this, here and other places, but I seem to get errors no matter which method I try.
I'm trying to fill an adjacent cell with a value based on the corresponding value from a list of values. For example, there's a list of Test -> Action pairs, defined in two columns. In another cell, I want to type in a value which exists in column B, and then fill the adjacent cell with the corresponding value in column A.
Here's my Sheet.
The columns "Actions" and "Tests (test groups)" define the corresponding values.
I'm using VLOOKUP in the "Test (test grop)" column (below the first two columns, from row 10 and down), to fill the cells when I'm entering a value in the "Action" value. Simple enough.
However, now I need this exact functionality in another sheet. I need to move the "Action" and "Test (test group)" columns - row 10 and down - to another sheet, and still reference the values in this sheet (row 2 - 6).
I've tried INDIRECT and a couple of other alternatives, and all give me either "#REF" or "#VALUE" in the cell where I use VLOOKUP.
Anyone able to explain how to do this, related to this example?
You need to add the worksheet name to your formula. Use single quotes if you have spaces or special characters in the name. Like this:
=VLOOKUP(A1,'sheet-name-with-dash'!$A$1:$B$9,2,FALSE)
may seem out of place, but whenever I see this kind of problems (in defining and using ranges) I think of the Excel option to define those ranges (like in Ctrl+F3, Name Manager).Showcase:
select your area: in your case A2:B6,
hit: Ctrl+F3,
name the range: i.e. LookupRange
use that range in Vlookup formula like: Vlookup($A12,LookupRange,2,0)
I do not use this on regular basis,but might get handy in a workbook with many sheets, ranges, formulas. Try this for fun at least.
Hope it helps.
How does one cell obtain the formula of another cell as text without using VBA? I can see this question has already been asked many times and the answer is always to write a custom function in VBA.
However, I found a post made in 2006 which claimed to have found the non-VBA solution but the link provided in that post is already broken.
=FormulaText(Reference) will do the trick Documentation
There is nice way of doing this without VBA. It uses XL4 macros (these are macros, but it is not VBA, as asked).
With reference to the figure 1, cells A2:A4 contain usual formulas.
Going to Formulas -> Define Name, I defined two named ranges (see fig. 2), with the information shown in cells A6:B8.
Enter in cell B2 =FormulaAsText. This will retrieve the formula in cell A2 as text.
Explanation:
The named range FormulaAsText uses =GET.CELL(info_type,reference). In this case, ìnfo_type = 6 retrieves the formula, and reference = OFFSET(INDIRECT("RC",FALSE),0,-1) uses the cell with 0 rows and -1 columns offset from the one the formula is used in.
Copy B2 and paste into B3:B4. This will show formulas in A3:A4. Cell A4 shows that the worksheet function CELL only retrieves values, not formulas (as opposed to GET.CELL).
Since FormulaAsText gets the formula from a cell at fixed offset (0,-1) from the current, I defined another range FormulaAsText2, which uses an offset (rows,cols) read from the worksheet itself. Cells D2:D4 contain =FormulaAsText2. Thus, cell D2 shows the contents of cell B3 (=OffSET(D2,1,-2)), which is FormulaAsText. cells D3:D4 show the contents of themselves. This adds some flexibility. YMMV.
PS1: The essence was taken from
http://www.mrexcel.com/forum/excel-questions/20611-info-only-get-cell-arguments.html
PS2: Tim Williams mentioned in a comment "the old XLM GET.FORMULA()". This answer is possibly related (not the same, since this one uses GET.CELL()).
PS3: A simple VBA solution is given, e.g., in
http://dmcritchie.mvps.org/excel/formula.htm
EDIT: Complementing this nice answer, the worksheet function FormulaText is available for Excel 2013 and later.
This suggestion may be helpful for those who after retrieving a block of formulas and transporting them to a new spreadsheet want to put them to work again. Excels FORMULATEXT function is great for picking up formulas but it leaves them as unusable text strings. If you want to get them back as fully functioning formulas you have to edit each one individually to remove the string character, but here is a shortcut for larger blocks.
Get to the position where you have the required formulas as text (in other words after using FORMULATEXT - you have done a copy and (value only) paste). The next step involves highlighting all the cells you want to convert and then navigating to the [Text-To-Columns] menu option ({Data} bar on Excel 2016). You can select 'Delimited' but on the next screen just make sure you de-select any marks that do appear in your formulas. Then 'Finish'. Excel should automatically analyse the cells as containing formulas and you should now have them working again.
There is a way to do this. In my example I had a table that showed a date. The date comes from Sheet!G91. In my table I also had a column that showed the sheet name. I added two more columns to my table. The first column had column(Sheet!g91), which returns the number 7, because G is the seventh letter in the alphabet. I then converted the number to a letter (G) using another table in my workbook. In the second column that I added, I made a formula row(Sheet!G91), which returns the number 91. Note: Row and Column may appear as volatile formulas, which recalculate with every calculation of the workbook.
I wanted another column to show the formula contents of the date cell mentioned at the beginning of this post. I included the following string function (you can also use CONCATENATE).
"=" & AJ9 & "!" & AM9 & AN9
The items separated by ampersands get strung together (that is, concatenated). AJ9 in my example contains the sheet name, AM9 contains the column letter, and AN9 contains the row number.
I now have a column that dynamically updates its contents to reflect the sheet name and cell reference. The results in my workbook cell are
=Sheet!G91.
You can't. This is most likely a design choice to eliminate an average Excel user from accidentally getting something they did not want.
What you are reading is correct - writing a UDF is the solution you want.