I am rather new to excel formulas. I am using the Indirect function and it is working properly when I manually enter the formula into the data validation source. What I would like to do is to copy it down the entire row. I am currently using the formula: =INDIRECT($Y$2) Referencing Column (Y) and row (2).
After some research, it appears that I can use the row function to accomplish this, but I am unsure how to include that into the formula I already have.
The issue that the OP describes is that their formulas break when they duplicate the entire row where an indirect reference is made using =INDIRECT($Y$2) in the data validation source of a cell.
The problem has to do with the cell reference and how the "$" symbol is used. It is described in more detail here. However, the relevant information is that the symbol allows you to control how the referencing cell should behave toward the referenced cell. You can allow or prevent change to the relative positions between the two. If you want to copy/paste a referring cell you must decide if the referenced cell will be fixed or moved in the process.
fix the row and allow the column to change
=INDIRECT($Y2)
allow the row to change and fix the column
=INDIRECT(Y$2)
fix(prevent change) to both column and row
=INDIRECT($Y$2)
allow change to both column an row
=INDIRECT(Y2)
You can put a conditional IF function into the data validation source itself. Would that be sufficient?
You will have the static choices:
=$M$2:$M$4
And then the variable sets of choices:
=IF(A2="choice1",$Y$2:$Y$4,$Z$2:$Z$4)
Note that the first cell reference in the IF statement is relative, but all others are absolute.
To use the row the formula is on, you can use =Indirect("Y"&row())
Related
I am trying to reference a column in an external Excel document in my formula, and then expanding said formula to the right to auto-fill the remaining cells. I have some values in the formula that I want to not auto-increment, which have been locked using absolute references ($), and others that should increment. But when it comes to the references to the external worksheet columns, those increment even though it makes no sense for them to do so.
Consider this formula as an example, with A1 through A* being a series of dates:
=COUNTIFS(external_sheet[date]; ">="&A1; external_sheet[status]; "ACTIVE";)
If I were to expand this formula to the right, it will increment [date] and [status] to the next column in the sheet. I do not want this behavior, but as far as I can tell there is no way to lock down these values as you can with absolute references. I tried adding a $ symbol before the external sheet reference, but that just breaks the formula.
An option would be to do external_worksheet!$A:$A instead, but for my use case it would make more sense to use references to named columns, as the order of columns may change between data files.
Figured it out after some more Googling (and learning that this is called a "structured reference"). Apparently, the syntax is this:
=COUNTIFS(external_sheet[[date]:[date]]; ">="&A1)
This will make sure that date does not increment to the next column name when filling to the right.
Thanks, I hate it.
With the special character '$' I can prevent an Excel formula from changing its reference when the cell itself is copied (e.g '$A$1').
But is there also a special character that prevents an Excel formula from changing its reference when the referenced cell is moved?
Here's an example:
I have:
Now I move the cells 'A1:A3' down one row. So the formulas in the cells 'C1:C3' change:
But I don't want that the formulas in the cells 'C1:C3' change. They should remain unchanged:
Try formula:
=IF(INDEX(A:A,ROW(1:1))=INDEX(B:B,ROW(1:1)),"Same","Not same")
the formula always work, regardless of any column been delete besides columns A or B
If you always want to refer to A1, then you can't just use A1 as a reference, because, as you have seen, Excel will adjust that reference if rows are inserted above.
Instead, use Index(A:A,1) . That will always return the value from the first row of column A.
=if(index(A:A,1)=index(B:B,1),"same","not")
Edit after comment: If this does not suit your purpose, maybe you need to redesign your spreadsheet so that the position of things does not change all the time. This looks like you are adding new data at the top of a list.
Excel works from top to bottom and things will be a lot easier if new data is added at the bottom of a list. You can always use other Excel tools to change the sort order if you want to have the data sorted in reverse chronological order.
Use formula in C1:
=IF(INDEX(A:A,ROW(ZZ1))=INDEX(B:B,ROW(ZZ1)),"Same","Not same")
and copy down.
I am making a spreadsheet which has multiple sheets and one of the sheets has an equation that looks to see if there is anything written in a certain cell on all the other sheets. Right now I just use this equation to find out whether or not it has anything written in that cell.
=IF(LEN('A'!N18)>1,CONCATENATE('A'!C18," "),)
This is just checking to see if anything is in the cell. The problem is that I want this to keep working if I add a new row on A, but right now it bumps row 18 to 19 and I am left with no row 18 so it won't even check that new row!
If you want to add a row between row 1 and row 18 on worksheet A but keep your formula references to A!N18 and A!C18 then you need to use INDIRECT or INDEX. Of these two, INDEX is the better choice as it is not volatile. A volatile function like INDIRECT will recalculate whenever anything in the workbook chanmges. A non-volatile function like INDEX will only recalculate when something that affects its outcome is changed.
'INDIRECT method; works but not optimal
=IF(LEN(INDIRECT("'A'!N18"))>1,CONCATENATE(INDIRECT("'A'!C18"," "),)
'INDEX method; works and is non-volatile
=IF(LEN(INDEX('A'!N:N, 18))>1,CONCATENATE(INDEX('A'!C:C, 18)," "),)
The link that Slai posted in the comments to your question should be what you're looking for. If you don't want a reference to change when you add/delete rows/columns you need to use absolute references. As currently written "N18" and "C18" are relative references. If you change the columns/rows on sheet 'A', these references will automatically change with them. That's why it's moving to row 19 on you.
You can turn these into absolute references by adding "$" like this: "$C$18" and "$N$18". The first "$" sets the absolute reference for the column and the second sets the absolute reference for the row. You can mix and match these for various results.
Mixing relative and absolute values really comes in handy when you are reusing a formula with slight differences. For instance, if you want to multiply a number in column b (starting with row 4) by the number in A1 and show the result in column C (also starting with row 4). You'll always be using A1 so we can set this as an absolute value and in C4 enter the formula =$A$1*B4. Copy this down column C and it will automatically update the B value to the new column but will always use "$A$1" for the other part.
You can split the relative reference by only using the "$" on the column or row reference of the reference. Whichever one you use it on will be locked and the other can still adjust based on changes to the sheet or copying. Learning how to use absolute references can be a great time-saver.
I'm curious about part of your formula though. Why are you concatenating C18 with just a blank space? If you are using the info somewhere else, it may make sense to add the space in that concatenate but it's a personal choice.
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())
How do I obtain a reference to the current cell?
For example, if I want to display the width of column A, I could use the following:
=CELL("width", A2)
However, I want the formula to be something like this:
=CELL("width", THIS_CELL)
Several years too late:
Just for completeness I want to give yet another answer:
First, go to Excel-Options -> Formulas and enable R1C1 references. Then use
=CELL("width", RC)
RC always refers the current Row, current Column, i.e. "this cell".
Rick Teachey's solution is basically a tweak to make the same possible in A1 reference style (see also GSerg's comment to Joey's answer and note his comment to Patrick McDonald's answer).
Cheers
:-)
Create a named formula called THIS_CELL
In the current worksheet, select cell A1 (this is important!)
Open Name Manager (Ctl+F3)
Click New...
Enter "THIS_CELL" (or just "THIS", which is my preference) into Name:
Enter the following formula into Refers to:
=!A1
NOTE: Be sure cell A1 is selected. This formula is relative to the ActiveCell.
Under Scope: select Workbook.
Click OK and close the Name Manager
Use the formula in the worksheet exactly as you wanted
=CELL("width",THIS_CELL)
EDIT: Better solution than using INDIRECT()
It's worth noting that the solution I've given should be preferred over any solution using the INDIRECT() function for two reasons:
It is nonvolatile, while INDIRECT() is a volatile Excel function, and as a result will dramatically slow down workbook calculation when it is used a lot.
It is much simpler, and does not require converting an address (in the form of ROW() COLUMN()) to a range reference to an address and back to a range reference again.
EDIT: Also see this question for more information on workbook-scoped, sheet dependent named ranges.
EDIT: Also see #imix's answer below for a variation on this idea (using RC style references). In that case, you could use =!RC for the THIS_CELL named range formula, or just use RC directly.
You could use
=CELL("width", INDIRECT(ADDRESS(ROW(), COLUMN())))
=ADDRESS(ROW(),COLUMN(),4) will give us the relative address of the current cell.
=INDIRECT(ADDRESS(ROW(),COLUMN()-1,4)) will give us the contents of the cell left of the current cell
=INDIRECT(ADDRESS(ROW()-1,COLUMN(),4)) will give us the contents of the cell above the current cell (great for calculating running totals)
Using CELL() function returns information about the last cell that was changed. So, if we enter a new row or column the CELL() reference will be affected and will not be the current cell's any longer.
A2 is already a relative reference and will change when you move the cell or copy the formula.
=ADDRESS(ROW(),COLUMN())
=ADDRESS(ROW(),COLUMN(),1)
=ADDRESS(ROW(),COLUMN(),2)
=ADDRESS(ROW(),COLUMN(),3)
=ADDRESS(ROW(),COLUMN(),4)
Without INDIRECT(): =CELL("width", OFFSET($A$1,ROW()-1,COLUMN()-1) )
I found the best way to handle this (for me) is to use the following:
Dim MyString as String
MyString = Application.ThisCell.Address
Range(MyString).Select
Hope this helps.
Inside tables you can use [#] which (unfortunately) Excel automatically expands to Table1[#] but it does work. (I'm using Excel 2010)
For example when having two columns [Change] and [Balance], putting this in the [Balance] column:
=OFFSET([#], -1, 0) + [Change]
Note of course that this depends on the order of the rows (just like most any other solution), so it's a bit fragile.
There is a better way that is safer and will not slow down your application. How Excel is set up, a cell can have either a value or a formula; the formula can not refer to its own cell. You end up with an infinite loop, since the new value would cause another calculation... . Use a helper column to calculate the value based on what you put in the other cell. For Example:
Column A is a True or False, Column B contains a monetary value, Column C contains the folowing formula:
=B1
Now, to calculate that column B will be highlighted yellow in a conditional format only if Column A is True and Column B is greater than Zero...
=AND(A1=True,C1>0)
You can then choose to hide column C
Full credit to the top answer by #rick-teachey, but you can extend that approach to work with Conditional Formatting. So that this answer is complete, I will duplicate Rick's answer in summary form and then extend it:
Select cell A1 in any worksheet.
Create a Named Range called THIS and set the Refers to: to =!A1.
Attempting to use THIS in Conditional Formatting formulas will result in the error:
You may not use references to other workbooks for Conditional Formatting criteria
If you want THIS to work in Conditional Formatting formulas:
Create another Named Range called THIS_CF and set the Refers to: to =THIS.
You can now use THIS_CF to refer to the current cell in Conditional Formatting formulas.
You can also use this approach to create other relative Named Ranges, such as THIS_COLUMN, THIS_ROW, ROW_ABOVE, COLUMN_LEFT, etc.
EDIT: the following is wrong, because Cell("width") returns the width of the last modified cell.
Cell("width") returns the width of the current cell, so you don't need a reference to the current cell. If you need one, though, cell("address") returns the address of the current cell, so if you need a reference to the current cell, use indirect(cell("address")). See the documentation: http://www.techonthenet.com/excel/formulas/cell.php
Reference to a cell that include this formula (self reference):
address(row();column())
E.g. getting the value of the cell above:
indirect(address(row()-1;column()))
Or what the OP asked:
=Cell(width;address(row();column()))