Prevent cell from being calculated - excel

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.

Related

EXCEL: When dragging cells to the right I need to use information stored in columns not rows (Not sure how to ask this properly)

It's probably a simple problem, but I did not even know the keywords to google it ;/. Let's say I have this data :
Now I also have this litle formula:
If I know drag the C cell to the right, Excel will attempt the following caluclation:
=2+B1
What I want him to do is to attempt this calculation
=2+A2
Of course the easiest solution would be to store my initial data in one row instead of 1 column, but it is really inconvenient for me. Thanks for any help
You can use the indirect() method to reference a cell by it's "String identifier", i.e. "A3". When filling out to the right, use CONCATENATE() and COLUMN() to create your String identifiers {A1,A2,A3,A4,A5...} as required:
=2+INDIRECT(CONCATENATE("A";COLUMN()-2))
This will result in the following:
Side-Node: If you want this for some x/y-Grid-Generation, you can also be lazy,
and just insert =COLUMN() for every cell from "A1 - Z1" and ROW() for every cell from "A2 - A24".
(Or even avoid these at all and directly perform your actual calculation by using column() and row() as replacement for your x/y.
You may try using a combination of the INDIRECT and COLUMN functions:
=2+INDIRECT("A"&(COLUMN()-2))
You would paste the above formula into cell C1, and then drag across to the right however many columns/rows you wanted to cover.
This would result in the following:
This works because COLUMN()-2 returns 1 for the C column, 2 for the D column, and so on. Therefore, the formula will be calling INDIRECT on A1, A2, etc. for column C, D, and so on.
In general, if you want relative references to move down as cells are dragged to the right, you can use this:
Instead of:
= 2+A1
Do:
= 2+INDEX($A:$A,COLUMN()+<offset>)
Where <offset> is whatever offset you need. The offset will change depending on which column the starting formula is located in.
INDEX should be preferred over INDIRECT because INDIRECT is volatile (must recalculate after any change to the workbook) but INDEX is not (only recalculated when one of the inputs the formula, in this case $A:$A, changes).

Creating something like an Excel "Loop" without VBA

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.

Excel cell showing value from formula while still allowing manual entry

I have a column of cells populated through a VLOOKUP. However, I've now been asked to make those cells allow for a manual override, while still showing the VLOOKUP value if there's no override.
Unfortunately there's a requirement to have the override entered in the same cell - otherwise I'd just add a couple of helper columns and it'd be trivial.
Is there another way to let a cell show a formula-based value, accept an override and restore the formula if there's no manual value?
The usual practice is to use an extra cell. For example, put the Vlookup() formula in cell B1 and the override value in cell C1,
Then in A1 enter:
=IF(C1="",B1,C1)
This allows A1 to display either the Vlookup() or the override (if it has been entered)
As mentioned, there'd no way to make it automatically restore the formula; you have to do it using VBA; I recommend a Command Button with a script that resets the cell.
If you want to have minimal reliance on VBA, and not lose the formula, you could set it so that the result is actually calculated in a cell hidden elsewhere, and the cell that the user inputs to just points there automatically.

Reference a range of cells and keep the order when adding new rows

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())

Alternate for Indirect used with Sumifs?

I am using the formula to ~300 cells which takes the address dynamically using INDIRECT function, but it is slowing down the calculation time.
please suggest me an alternative method to make the calculation faster.
I have done basics as it has macro with screen updating= false and calculation=xlmanual.
=SUMIFS(Sheet1!$L:$L,Sheet1!$I:$I,Bookings_QTD!$F51,Sheet1!$B:$B,Bookings_QTD!I$2,INDIRECT($I$8),$K$8,Sheet1!$C:$C,$M$8)/1000000
here cell $I$8 is dynamic where values will varies based eg:-Sheet5!$A:$A, Sheet5!$B:$B...
$I$8=Sheet5!$E:$E
I need to use it for many cells ~400+ with other criterias in future.
kindly suugest me better formula or method which will decrease the calculation time.
Thanks in advance
INDIRECT() will be slow for many sheets as it is a Volatile function. i.e. every time there is a change in any cell in the workbook, it will get triggered.
If your cell values are relatively static. i.e. if you are indirectly referring to cell "B6" and you expect the content of B6 to remain the same and only expect the input of your function to change, say from "B6" to "Z8", you can use the following code:
Function MyIndirect(RangeStr as String) as Variant
MyIndirect = ActiveSheet.Range("RangeStr").Value
End Function
This should work. And should you need to 'refresh' this value, simply run an Application.Calculation (i.e. press Ctrl-Alt-F9)

Resources