I am trying to build a formula that simulates a "loop" in excel. The spreadsheet pulls data from a database into four spreadsheets. The formula needs to iterate through the sheets, moving onto the next sheet if the value found is #N/A. The current set up uses index(match()) to find the value in the table on the sheet. To move between sheets, I am using choose() to drive an indirect() to change to the next sheet, but I'm not sure how to simulate the loop... the problem seems to be that I would need to refer the function back to itself and then break out of the loop.
I'm imagining the solution would be something like
=IFNA(CHOOSE( [the next number], INDEX(Sheet[the next number]!A1:Z500, MATCH(G1, Sheet[the next number]!A1:Z1), MATCH(A250, Sheet[the next number]!A1:A500)
The sheet cannot use VBA.
Further to my comment:
Iterative calculations could be used, similar to this setup -
A1: =INDEX(B1:B4,A2)*1
A2: IF(ISERR(A1),A2+1,A2)
B1:B4: lookup values
When Index in A1 encounters a letter in B1:B4 it throws an error (from *1)
When A2 sees an error in A1, it increments
Since A2 is the row value that A1 is indexing, A1 looks at the next row, which may or may not cause an error
When A1 is not an error, A2 stops incrementing. See the below image
A similar setup could be used to iterate through the sheets looking for an error in the index formula using ISNA, I would have used that as the example, but I'm not 100% sure what your formula is doing (it has too many open brackets!)
Notes
To access the iterative formulae option, go File->Options->Formulas->Check Enable iterative calculation. Set the value of maximum iterations to 1 if you want to hit F9 and increment through the sheets one at a time manually, otherwise set it to the number of sheets you are looking at (4?). That way you will loop your helper cell 4 times, and it will stop incrementing on whatever occasion it does not detect an error.
Also, I like to wrap my circular reference formula, A2, in an extra IF(A3 = "rst",1,...) so that I can reset the value without retyping the formula
Iterative calculations are great as they allow you effectively to save data in Excel mid calculation, but they must be used with caution to avoid infinite loops and huge calculation times - I use VBA because it's safer for that
It would be simpler to split the formula in to 5 different formulas: the first 4 do the lookups on the 4 sheets then the 5th formula uses nested If (or IFS if you are on Office 365 Excel 2016) to select the lookup with a valid result from the 4 formulas.
Related
I am referencing a range of cells in a first sheet, to build a second sheet. Often I add rows in the middle of the first sheet. In the second sheet that is referencing the first, there is a skip in the cell number where I have added a row.
SHEET 1: Contains my main list, that is updated
A new row is added (A3) to SHEET 1:
SHEET 2: references Sheet 1 and pulls through the rows
However, you can see that where row 3 should contain the added row 'Rachael', it instead has shifted down to Sheet1!A4 and missed A3 out all together.
How can I fix this?
Try using this formula in sheet2:
(add it to Sheet2, A2, then copy it around.)
=offset(sheet1!$A$1,row(a2)-1,column(a2)-1,1,1)
Try to avoid formula volatilty, which means a formula recalculates on a change to the sheet even if its precedents have not changed.
Having numerous volatile formulas in a worksheet can cause performance issues.
Any formulas that utilize the OFFSET() function or the INDIRECT() function automatically become volatile. But of these two functions, INDIRECT is much worse than OFFSET. Both are volatile, but OFFSET is extremely fast, while INDIRECT is extremely slow.
DO NOT USE INDIRECT().
The best alternative is without question the INDEX() function. It is even faster than the OFFSET function and INDEX is not volatile.
So use the following formula in cell A2 of the 2nd sheet:
=INDEX(Sheet1!$1:$1048576,ROW(),COLUMN())
...and then copy as needed.
To directly answer your question - you can achieve this with the INDIRECT function. INDIRECT allows you to dynamically reference a cell through a formula, which doesn't necessarily follow Excel's "tracking" rules. Keep in mind that normally, Excel gives each cell a 'unique id', and when you initially reference any cell, the internal logic points to that specific 'unique id', and the visible reference points to the 'A1' style reference to that cell. This is done so you can insert rows and columns without unintentionally losing all of your references.
It is generally not a good idea to do what I'm about to show, because you lose the inherent benefit that direct references provide (in general: easier to maintain). However, to show you how it would work, see below [this assumes you want one header row, and that the column on your results sheet should match the column on your raw data sheet]:
=INDIRECT("Sheet1!R"&ROW()+1&"C"&COLUMN())
I have a table of results in MS Excel 2010 with formulas in each cell that I need to edit. I have INDIRECT cell references in the formulas that do not update when copied to other cells. So, I believe the easiest way in this case for me to edit all the formulas in the table is with two find-and-replaces (changing the beginning and end of each formula to have what I need). However, when I try to do the find and replace, Excel shoots a "The formula you typed contains an error" pop-up at me and refuses to execute the replace. I know there's an error, I'm not finished with the formula yet! So:
1) How can these errors be disabled?
2) Is there a way to make indirect cell references update the way a normal cell reference would (eg. make INDIRECT("'"&F5&"'!L7") update L7 to L8 in the next row) so that I can copy the new formula throughout the table of results, and avoid the find-and-replace entirely?
Sorry guys, I realize this is a somewhat strange question for stackoverflow.
1) I don't know.
2) I'm not 100% sure from the question, but I can think of two scenarios:-
(a) You have a list of references which your INDIRECT formula uses, and you want it to select each one in turn as you pull the formula down. This is trivial so it's probably not what you meant:-
=INDIRECT(A$1&"!"&A2)
assuming your sheet name is in A1 and the references are in A2,A3 etc.
(b) You have a reference to the beginning of a range of cells in sheet2, and when you pull the INDIRECT formula down, you want it to automatically get the next cell in the range:-
=INDIRECT(SUBSTITUTE(ADDRESS(1,COLUMN(INDIRECT($A$2)),4,1,$A$1),"1","")
&(ROW(INDIRECT($A$2))+ROW()-ROW($C$2)))
where this formula is placed in cell C2 and pulled down.
The idea is that you break the cell reference down into its column name (using the excellent suggestion here ) and its row number, then get the row number to increment using the ROW function.
Sheet 2:-
Sheet 1:-
Consider this: Cell C1 has a formula that calls another function many times:
eg =ExcelFuntionA(ExcelFunctionCallB(1), ExcelFunctionCallB(1)-1, ExcelFunctionCallB(1)-2, ExcelFunctionCallB(1)*3)
Note that the parameter(s) passed to ExcelFunctionCallB have the same value(s) each time.
If ExcelFunctionCallB(..) is a function that involves significant processing, would excel process the formula quicker if the result of ExcelFunctionCallB(..) was found in anther cell and the above formula was changed to reference this cell 4 times.
eg
Say A2 has the formula ExcelFunctionCallB(..)
C1 would then read =ExcelFuntionA(A2, A2-1, A2-2, A2*3)
I'm wondering how intelligent excel is!
Can is see that calls are identical and only process a call to the function once?
Is it intelligent enough to do this for array formulas as well as normal function formulas?
If you call a function that has been written in VBA how does it work?
Bear in might that a VBA function could reference cells directly
that are not passed as parameters ( I know this is naughty, but it
happens, and there is only small chance that it might return a different
value even if the parameters that are used with it are the same.)
Following on from the above, is there a way of telling the code that a VBA function does not access any excel cells directly? (A bit like application.volatile I would imagine)
A more realistic example: I've actually been experimenting with formulas like this:
=MID($A2, FIND("#",SUBSTITUTE("#" & $A2 & "#","#","#",B$1)), FIND("#",SUBSTITUTE("#" & $A2 & "#","#","#",B$1+1)) - FIND("#",SUBSTITUTE("#" & $A2 & "#","#","#",B$1)) - 1 )
which is well documented in one of the proposed by not approved answers to SO question 24182334/splitting-text-columns
Note that this formula uses the text FIND("#",SUBSTITUTE("#" & $A2 & "#","#","#",B$1)) three times.
[PS. I know about split in VBA and the text to columns menu option.]
If ExcelFunctionCallB(..) is a function that involves significant
processing, would excel process the formula quicker if the result of
ExcelFunctionCallB(..) was found in anther cell and the above formula
was changed to reference this cell 4 times.
This is correct, referencing an already calculated cell is faster than recalculating the same thing multiple times in an individual cell. Excel will calculate each one separately
Also, as pointed out by pnuts, this link may be of interest: http://msdn.microsoft.com/en-us/library/office/ff700515%28v=office.14%29.aspx
(posted as answer at chris neilsen's suggestion)
The key text from the link in the above answer (here) is
If you have a calculation-intensive formula where you want the result to be shown as zero if there is an error (this frequently occurs with exact match lookups), you can write this in several ways.
You can write it as a single formula, which is slow:
In cell A1 =IF(ISERROR(time expensive formula),0,time expensive formula)
You can write it as two formulas, which is fast:
In cell A1 =time expensive formula
In cell B1 =IF(ISERROR(A1),0,A1)
Starting in Excel 2007, you can use the IFERROR function, which is designed to be fast and simple, and it is a single formula:
In cell A1 =IFERROR(time expensive formula,0)
So the same logic would apply to other types of formulas it would seem.
Is it possible to prevent calculations happening to a single cell in Excel sheet? Let's say I have 1001 cells that are very fast to calculate, but 1 cell slows sheet down, is it possible to disable calculations for that 1 cell only?
What I'm NOT trying to do:
Disabling all of cell calculation programically
Calculating specific cells programically while global calculation is set to manual
Use Excel's =IF() function. It is set up to "short-circuit" -- it only evaluates the second parameter if the first parameter is true, oppositely for the third parameter.
So, if the cell is C1, and the cell's formula is currently
=LOOKUP(2,1/(A1:A100000=666),B1:B100000)
and you want it to only be calculated when D1 is true, use
=IF(D1,LOOKUP(2,1/(A1:A100000=666),B1:B100000),C1)
Notice it's a circular reference -- it's how you keep the value the same when D1 is false. Turn on iteration if you want to get rid of the warning message.
Another way is to use one of the third-party Add-Ins out there that lets you store a global variable off-sheet and then retrieve it, which would use syntax like this:
=IF(D1,SetGlobal("C1StoredCalculation",LOOKUP(2,1/(A1:A100000=666),B1:B100000)),GetGlobal("C1StoredCalculation"))
SetGlobal() and GetGlobal() can also be written in VBA, though they'll be a tiny bit slower than an XLL, and they'll lose the value if you reset your VBA project.
Excel does not have a method to disable calculation for a single cell.
You could move the slow formula to a separate sheet and use worksheet.enablecalculation to disable calculation for that sheet.
Or you could store the formula somewhere as text, store the result as a value in the cell, then restore the formula when you want to calculate it.
You can use a replacement UDF and take advantage of a lack of volatility.
Say we have a formula like:
=LOOKUP(2,1/(A1:A100000=666),B1:B100000)
Excel will re-calculate this if any cell in cols A or B change, but the UDF
Public Function myudf(r As Range) As Variant
myudf = Evaluate("LOOKUP(2,1/(A1:A100000=666),B1:B100000)")
End Function
will only be re-calculated when its argument changes. So pick a cell and enter:
=myudf(Z100)
make any changes you want to cells in cols A or B and myudf will remain un-re-calculated until you change Z100
You can use the same tiny trick to make "quasi-volatile" versions of =TODAY() or =NOW() for =RAND()
I don't think this can be done. You can turn off automatic calculation in entire workbooks (as you mentioned), but I don't think there is a way to do this on an individual cell.
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.