How to use the INDIRECT function in Excel - excel

I am using in Excel the following formula that works to get the value of a cell:
=INDEX(Sheet1!$1:$1048576,MATCH("Component 1",Sheet1!$A:$A,0)+MATCH("Component 2",Sheet2!$B:$B,0),2)
For a new application, the sheet and component names are dynamic, meaning that they are allowed to change and are not necessarily "Sheet1", "Sheet2", "Component 1" and "Component 2". Therefore I have tried to twist the above formula using the build-in INDIRECT function. I have tried two different ways to make it work:
1-
=INDEX(INDIRECT(A1&"!$1:$1048576"),INDIRECT("MATCH("&CHAR(34)&B1&CHAR(34)&","&A1&"!$A:$A,0)+MATCH("&CHAR(34)&B2&CHAR(34)&","&A2&"!$B:$B,0)"),2)
2-
=INDIRECT("INDEX("&A1&"!$1:$1048576,MATCH("&CHAR(34)&B1&CHAR(34)&","&A1&"!$A:$A,0)+MATCH("&CHAR(34)&B2&CHAR(34)&","&A2&"!$B:$B,0),2)")
where cells A1 and A2 values are the sheets' names and cells B1 and B2 receive the components' names.
Both approaches gives an error #Ref!. But I really cannot see what is wrong.
I would really appreciate any information for me to understand my mistakes and any suggestions to improve these formulas.
Thanks in advance!

Reason
You are using INDIRECT to compile parts of your formula, including the function names (e.g. "MATCH" in your "1-").
Instead, only use INDIRECT to build the actual references to ranges or cells (including qualifiers such as worksheet, workbook etc) inside those functions within your formula. Leave the rest of the formula outside the INDIRECT function.
So in your "1-", move "MATCH" back outside the "INDIRECT" function.
To get the "Component 1" to be volatile, just reference a cell containing that string in the normal way.
In your attempt "2-", you tried putting more of the formula inside the INDIRECT function, but it should have been less.
Answer
For example, you could try:
=INDEX(INDIRECT($A$1&"!$1:$1048576"),MATCH($B$1,INDIRECT($A$1&"!$A:$A"),0)+MATCH($B$2,INDIRECT($A$2&"!$B:$B"),0),2)
Even better
The difficulty is arising in part due to putting the sheet name in a range and the range reference hard coded in the formula.
You could consider putting "Sheet1!$1:$1048576" into A1 (for example), instead of just "Sheet1", and adjust formula accordingly. That way you can just edit A1, B1, B2 if the ranges change or grow, rather than editing the formula. Note that you would not be able to reuse A1 for the reference to "Sheet1!$A:$A", you would need a different cell to store that reference.
Also consider naming the cells A1, A2, B1 & B2, and referring to the named ranges in your lookup formula. That way if you move those cells around in certain ways it will be less prone to breaking your lookup formula.
Further thoughts
I presume you are across the performance tradeoffs of using volatile functions such as INDIRECT. If not, happy searching!

Related

Why use INDIRECT in place of direct reference in excel

Why would one use INDIRECT(cell) instead of a direct reference to cell?
Eg, I see a sheet where there are many references
A B C
1 SHEET1 B1 =INDIRECT("'"&A1&"'!"&B1)
2 SHEET1 B2 =INDIRECT("'"&A2&"'!"&B2)
3 SHEET1 B3 =INDIRECT("'"&A3&"'!"&B3)
Why not just
A B C
1 =SHEET1$B1
2 =SHEET1$B2
3 =SHEET1$B3
Indirect vs Direct Cell Reference
does not generally auto update vs does update
example adding or removing columns
arithmetic to change row or column vs what you type is what you get
example indirect("A"&3+5) vs =A3+5 is totally different
If you want to organize your formula references and change them all on the fly it is easier with indirect (although even easier just using the naming feature) but the real reason you "need" indirect is how else are you going to change the reference in your formula without manually typing it (answer: indirect)?
use case - programmatically list and loop a range of worksheets:
sheet references using formulas and values useful for addressing cells at scale.
Build references to many different cells, worksheets or workbooks that follow a logic
The most common use of the INDIRECT function is probably when someone wants to reference to many cells which cell references follow a logical rule. For example, assume you have an Excel workbook with hundreds of sheets, one for each day and the sheet names are the dates. Now you would like to summarize some of the values in those sheets on an overview sheet. In this case, you can type in your starting date, drag it down to your final date (Excel will increment the dates). Using the INDIRECT function, you can now easily build up the references within seconds.
However, consider that INDIRECT is a volatile function which will slow down your workbook. Further, if you insert rows/columns, the INDIRECT function won’t adapt. It get’s even worse when you reference to external sheets. Since INDIRECT updates it’s value with every change in the workbook, you will get #REF errors as soon as you close the referenced sheets.
I personally avoid INDIRECT for such cases (either using VBA or by choosing a different design for my workbooks, so no INDIRECT function is necessary)
Lock a cell reference
If you have a cell reference like let’s say =A10, Excel will always adapt the reference when you insert new rows or columns (if you for example insert a row above row 10, the reference changes to =A11). You can use the INDIRECT function in order to always keep the absolute cell reference: =INDIRECT(“A10”).
With named ranges
INDIRECT can be handy with named references. Have a look at the example where you have three named ranges:
NorthAmerica: B2:B5
Europe: C2:C5
Asia: D2:D5
You can now combine the INDIRECT function with many other Excel functions like SUM, MIN, MAX and so on. In the example, the drop down selection in G1 is referenced using INDIRECT to perform the calculation for the selected range.
Dynamic dropdowns
A similar example where you can use the INDIRECT function are dynamic drop downs. In this example there are two named ranges:
Fruits: A2:A4
Vegetables: B2:B4
In cell D3, there is a dropdown where you can select “Fruits” or “Vegetables”. In E3, we have a dynamic drop down with the source =INDIRECT($D$3). If you choose “Fruits” in D3, you will have a list with the fruits in the drop down.
So, there are definitely some things where INDIRECT might be an easy solution. But as I said, it is a volatile function that locks the cell reference. In most cases you can find different, better solutions. The main reason people use it is probably the lack of knowledge of better alternatives. In addition, I assume that the average Excel user is not aware of possible problems you might run into when using INDIRECT.
Indirect is very useful with Tables. For example, I create a table tblFindings with 10 rows. Then I assign the list to =Indirect("tblFindings"). Now I add 5 rows to the table, the dropdown list automatically updates.

Mixing external and internal cell referencing in formula

I don't have a decent way of explaining this but I'm going to try. Sorry.
I have two documents. I'm linking one document to the other to present some info from that first document into the second one inside a specific cell.
Let's say I want the data from B2 from my first sheet. Is the only way to do this is by typing B2 into the formula itself or can I create a variable and have that space be filled in by putting the appropriate cell number into another cell? If I want it to reference B2 from the external sheet, can I type B2 into a specific cell on the page and that cell is defined as my_number and I can place that variable my_number into the importrange formula?
Or can I not mix external and internal referencing? I tried to search for something similar online but I didn't have a lot of luck.
If this is still not explained very well, this is kind of a visual:
=IMPORTRANGE("mydocsheet.com/spreadsheet", "Sheet1![my_number]") instead of
=IMPORTRANGE("mydocsheet.com/spreadsheet", "Sheet1!B2")
Those are quoted strings representing cell range references; not true cell range references. You should have no problem using concatenated strings. With B2 in a named cell called my_number,
=IMPORTRANGE("mydocsheet.com/spreadsheet", "Sheet1!" & Sheet1!my_number")

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

How to reference cell within '' worksheet title

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.

INDEX(INDIRECT("DefinedName"),1)=#REF while INDEX(DefinedName,1) works

In an excel workbook, I'm referencing a defined name from another tab (to get dependent data validation). Accessing the defined name directly works, but accessing it through INDIRECT doesn't.
=INDEX(DefinedName,1) returns the first value of the range
=INDEX(INDIRECT("DefinedName"),1) returns #REF!
I have also tried
=INDEX(INDIRECT("SheetName!DefinedName"),1), but it also returns #REF!
Sample file can be downloaded here.
Thomas,
I hadn't come accross this before.
It appeas that INDIRECT and dynamic range names are incompatible. There is a useful reference here from Dicks blog
Not quite an answer, but it may have something to do with the fact that your named range is returning an array instead of a cell reference (in this case {"VALL";"GENADMIN";"HOSP";"CELLAR"}).
You can replicate the error by removing the named range and replacing it with its actual formula, and then F9'ing the formula:
=INDIRECT(OFFSET(Defaults!$C$1,1,0,COUNTA(Defaults!$C:$C)-1))
=INDIRECT({"VALL";"GENADMIN";"HOSP";"CELLAR"})
Since Excel is expecting some sort of reference to a sheet range, it is failing here since it can't resolve the array to anything specific (pressing F9 again yields ={#REF!;#REF!;#REF!;#REF!}).
The INDEX formula works because it can handle the array reference:
=INDEX(OFFSET(Defaults!$C$1,1,0,COUNTA(Defaults!$C:$C)-1),1)
=INDEX({"VALL";"GENADMIN";"HOSP";"CELLAR"},1)
={"VALL"}
Not an expert, but that's my best crack at it.
This absolutely will work. Maybe they were incompatible in 2012, but they certainly work in 2018. I imagine it would have also worked in 2012 if used correctly.
The INDIRECT function attempts to turn TEXT into a range reference. That TEXT must be a valid reference.
A named range is already a Range Reference. There is no need to get a reference from a reference. This is why the OP example works without using INDIRECT.
A more likely implementation would be if you had the value "DefinedName" from the OP, or any named range in a cell. Then point INDIRECT to that cell where it find plain ol' text. Then it turns that text into a range reference.
You can even use formulas in the INDIRECT to modify the reference. A common approach might be to have a Sheet name in a cell and then use INDIRECT to pull data from various sheets. This is primarily useful when you want to copy and paste formulas and have the sheet (or cell) reference dynamically adjust to a new target.
Setup
Start with a blank workbook which should contain three blank worksheets, (Sheet1, Sheet2, and Sheet3) If not, get to that point. Then enter the following basics:
Sheet 1
Cell A1, enter "Range Reference"
Cell A2, enter "SUM from Sheet"
Cell B1 enter "Sheet2!A1:A4" (Note there is no "=" This text is a range reference.)
Cell C1, enter "THIRD_SHEET" (This text is equivalent to a named range we'll create in a second.)
Then in Sheet2,
Cell A1, enter 1
Cell A2, enter 2
Cell A3, enter 3
Cell A4, enter 4
In Sheet3
Cells A1-A4 enter 100 through 400 respectively.
Then create a named range called "THIRD_SHEET" which refers to cells A1-A4 on Sheet3.
Try
In Sheet1:
Cell B2, enter the formula:
"=SUM(INDIRECT(B1))"
Copy that formula to Cell C2.
Results:
The INDIRECT uses the text in the column headings to point to a valid range reference. This is just illustration. You wouldn't likely use a mixture of named ranges and text ranges, and its not very clean to write out, "Sheet1!A1:A4" but you can use any of the standard formula to arrive at a textual reference.
Try
Change the formula in B2:
"=SUM(INDIRECT("Sheet"&COLUMN()))&"!A1:A4"))"
Now copy that to cell C2.
Results
Well, are the same. The SUM from cells A1:A4 is being returned from Sheets 2 and 3 respectively. This time, however, the column headers are not being used, and the range reference is being assembled in the INDIRECT call itself using the string join "&" operator and the COLUMN number.
Named ranges can be used in the same way. What's important to understand is that anything inside the INDIRECT parenthesis needs to first be resolved to a vaild TEXT range reference.
I hope that helps!

Resources