Retain cell address when sorting list - excel

Here is a reduced version of what I need. Essentially, we have a list of components and their status (imagine they have been tested). Component BBB has two sub-components, BBB1 and BBB2. I want their status to reflect that of the BBB component 'parent'. Easily done, apart from the list is very long, and I need to retain the option to sort it as I wish. If I user a simple cell reference to "=B3", then this is invalid once the list is sorted. Similarly with a named range as B3; the named range address is static and does not dynamically alter when the list is sorted.
I could fix this by having a 'static' BBB status somewhere that is not in the sort area, but this is inelegant, and I don't like inelegance!
Any ideas?
http://FileHost.JustFreeSpace.Com/158complist.xls

I'm not fully sure of your use and needs, but try this litte formula:
=ADDRESS(MATCH("BBB",A:A,0),1)
It will return the cell address where BBB sits.
If you remove the ADDRESS portion of the formula, it will return the Row number.
It can also be modified to pull the Value in your 'Status' Column.
If you put this formula in the 'Status' column for rows BBB1 & BBB2, then it will update when BBB changes:
=INDEX(A:C,MATCH(LEFT(A2,3),A:A,0),2)
Let me know if I'm only warm, or if I got it.

Perhaps the VLOOKUP worksheet function does what you need? See http://office.microsoft.com/en-us/excel/HP052093351033.aspx

There's a very easy solution. Just used an absolute reference, e.g. =$B3 or =B$3 or =$B$3
If I user a simple cell reference to "=B3", then this is invalid once the list is sorted.
Sorting won't invalidate these absolute references.

If you're just using =B3, on sorting Excel will update that on its own when you sort, as long as you don't sort using VBA. If you want to keep a handle on that cell, you may need to find it again manually or keep tabs on where it goes to as you move it around.

For references within the same row, use relative references. (This is not your question.)
For references to other rows, use VLOOKUP (with FALSE as the last parameter) if you can identify a unique key to each row. If there is not a natural key, construct a surrogate and make sure it is and remains unique. [I display the next value to use in the table header and use conditional formatting to highlight the non-uniques. This breaks quite easily, if you insert a copied row, for example.]
Absolute references won't work. They retain the exact cell reference - but after sorting this now points to whatever value was sorted into that position. I believe this is a bug in Excel, either in the code or in the specification. The behaviour one would expect is that the values in a tuple remain unchanged, even when that tuple is moved around by a sort. With absolute references, the value in the cell with the absolute reference changes, even if - or rather because - the reference itself remains the same.

If the cell reference is to a cell in another ROW, it will change after sorting even in spite of locking the cell reference with the $ sign.

Related

Dropdown list with a conditional statement

I have some materials in column B, a few among these are in a Table definition called Material_List. In D49 I am trying to write a conditional statement such that, if the data in B49 already exists in the table definition, then print the header name or else INDIRECT($49). C49 has the independent dropdown list and D49 will be the dependent.
In D49 I have used the following formula within the Data-->Data Validation-->Source=
=IF(MAX((ISNUMBER(MATCH(Material_List;$B49;0))*COLUMN(Material_List)))=0;
INDIRECT($C49);
INDEX(Material_List[#Headers];1;MAX((ISNUMBER(MATCH(Material_List;$B49;0))*
COLUMN(Material_List))))))
with Allow=List. But it says Error "There is a problem with this formula"
When typed the following formula in cell D50 directly, it works well but obviously without dropdown.
=IF(MAX((ISNUMBER(MATCH(Material_List;$B50;0))*COLUMN(Material_List)))=0;
INDIRECT($C50);
INDEX(Material_List[#Headers];1;MAX((ISNUMBER(MATCH(Material_List;$B50;0))*
COLUMN(Material_List))))))
I am trying to build a dropdown list based on the mentioned criteria. could anyone please tell what is wrong with my formula?
I think the main issue with your formula is that you cannot use table references in the data validation.
Don't ask me why. I think it is just an outstanding Excel bug which hasn't been fixed yet. Please see this link for further info: https://exceloffthegrid.com/using-an-excel-table-within-a-data-validation-list/
The best way I have found to work around this is to create a named range which refers to the table references you need ("Material_List" and "Material_List[#Headers]" in your case). Then you can use those named ranges in your data validation instead of the table references directly.
However, I think there are also other issues with your formula. For example, this part:
MATCH(Material_List;$B50;0)
Normally a MATCH would be in the format of:
MATCH(<single value to look for>, <range to look in>, 0)
You appear to have that reversed, meaning that it should always return a #VALUE! error.
Also, I don't think you can use match on a 2D array, so if your "Material_List" table is more than a single column, that would also cause it to return a #VALUE! error.
UPDATE:
The way I would tackle dependent dropdowns would be as follows.
I would create a "Material_List" table similar to below (could be on a hidden sheet):
Then I would create 3 named ranges.
One for the table body range, called "MaterialList_TblRange":
=Material_List
One for the table header range, called "MaterialList_TblHeaderRange":
=Material_List[#Headers]
And one to refer to the dependant dropdown options, called "DropDownOptions" (this is by far the most complicated part):
=INDEX(MaterialList_TblRange,1,MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0)):INDEX(MaterialList_TblRange,COUNTA(INDEX(MaterialList_TblRange,1,MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0)):INDEX(MaterialList_TblRange,ROWS(MaterialList_TblRange),MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0))),MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0))
I will explain what this is doing in a moment.
The last step is to set up the data validation where we want our lists.
Where we want the master lists to appear, we can simply enter:
=MaterialList_TblHeaderRange
And the defendant dropdown validation can be entered as:
=DropDownOptions
This is the result:
Now back to the long "DropDownOptions" named range formula...
Basically, we use INDEX:INDEX to select the first/last cell in the range we want to use in out dropdown.
The first INDEX:
=INDEX(MaterialList_TblRange,1,MATCH(Sheet1!$B23,MaterialList_TblHeaderRange,0))
Simply selects the first cell from the column whose header matches the selection in our first dropdown.
The second index does the same, except that instead of selecting the first cell in the column, it counts the number of cells that contain text and uses that as the last cell in the range.
This does mean that we mustn't have any gaps in this table, otherwise an option might be missed off the end.
I hope this makes sense.

Excel: Lookup multiple values in one cell and return results in another

I'm trying to find a way to lookup each of several comma separated values in one cell, and return the results as a comma separated list in another cell.
The number of values to lookup is not constant, it may be only one, or several hundred.
Example - Sheet A has the initial values and will hold the returned values. Sheet B is the table with the data to lookup.
EDIT: I've gotten better and learned how to make this a 1-liner. I'll leave my original answer below, but here's my updated one (as this hasn't been accepted or even commented on, yet):
=TEXTJOIN(", ",TRUE,INDEX(SheetB!$A$2:$B$6,MATCH(FILTERXML("<x><y>"&SUBSTITUTE($B2,",","</y><y>")&"</y></x>","//y"),SheetB!$A$2:$A$6,0),2),"")
I think INDEX/MATCH was the key component I hadn't learned yet when I tried answering this before. :)
The FILTERXML/SUBSTITUTE I had learned from another site where it takes in your delimited values and replaces the delimiter and wraps the rest with the needed xml tags for FILTERXML to then return an array of your values.
INDEX/MATCH then does your lookup, first getting the row number via MATCH (note the final value of 0 in MATCH means exact match), then INDEX returns the value of the corresponding matching column (the 2 at the end of INDEX's arguments).
Finally, TEXTJOIN joins the results together with the delimiter of your choice (and the second argument set to TRUE allows it to skip blanks).
As a final note, I think this solution may work without Office 365. FILTERXML appears to have been available as early as Office 2013.
Original, outdated answer follows:
I've been searching for an answer to this myself and was rather dismayed to find your question - exactly the question I have - without an answer.
Almost 4 years late, this answer does require Office 365 Excel, and it's not the most elegant, but here's what I've been able to come up with.
Pick an unused column on your Sheet B (with enough contiguous unused columns to its right to handle spillover of however many values you'll need to be splitting, or use a new sheet dedicated to this) and put this formula into the 2nd row's cell for that column, dragging it down through each cell that has corresponding data back on Sheet A (and assuming your column header "File #s" is column B): =TRANSPOSE(FILTERXML("<x><y>"&SUBSTITUTE(SheetA!$B2,delim,"</y><y>")&"</y></x>","//y"))
Replace delim with your delimiter wrapped in quotes, or a cell reference to a cell that has your delimiter in it. Also, if it's possible to have no value in the corresponding cell in Sheet A, then you'll need to wrap the FILTERXML() function (or the whole thing) with IFERROR().
Then, back on Sheet A in your Results column, use this formula: =TEXTJOIN(delim,TRUE,FILTER(SheetB!$B$2:$B$6,COUNTIF(SheetB!D2#,SheetB!$A$2:$A$6),if_no_match))
Again, replace delim with the delimiter or cell reference with your delimiter of choice. SheetB!$B$2:$B$6 and SheetB!$A$2:$A$6 are your lookup table's columns (and thus extend them to encompass the whole thing). The SheetB!D2# references the column where you put the TRANSPOSE(FILTERXML()) formula. Finally, replace if_no_match with whatever you want to appear if there was no match.
I'd ideally like to find a way that uses a single, self-contained formula, but alas, this is as far as I've managed so far.

Use INDEX/MATCH to select formula written as string, and enable it?

I have a pricelist, with currently 5 different categories of products. Each product will have to have two different prices. Depedning of the product and the type of price, the calculation will be different. Therefor I've used INDEX/MATCH to find the formula needed, from a table I created.
Below a screendump, and I wanted to attach the Excel fil, but canøt seem to work out how.
Question: HOW do I then "run" the formula I fetched? -I've tried different suggestions on using EVALUATION, but it doesn't seem to cut it? Also I've tried "Indirect' on the whole formula, without success.
I would like to avoid any VBA for this case.
Can anybody provide some insight?
You could but if I understand properly, the only thing changing in the formulas is the "muliplier" number, then it's better to lookup that number instead of the whole formula. The other method (which would use Evaluate etc) is not be considered "good practice" for a number of reasons.
EDIT:
I didn't see the 2nd varying value (since I was on the SO mobile app) but it's still not an issue since it would a target column. You could be thinking of the opposite: sometimes lookups based on multiple criteria can get complicated, but this a matter of more data, as opposed to adding criteria for the lookup.
VLookup would have been the simplest method, like G2 could have been:
=VLOOKUP(E2, $J$4:$L$8, 2, False)
...to return the second column of range J4:L8 where the first column equals E2. (Then for the next required column, same formula except with 3 instead of 2.)
Since I wasn't sure more columns could be added one day, I allowed for that by, instead of specifying "Column 2 or 3" etc, it finds the column dynamically by name. (So the multiplier/factor used in G2 will change if you change the title in G1 to the name of a different column existing in the target data chart.
For the sake of neatness as well as potential of additional columns like G & H, I moved the lookup table to a separate sheet. It can stay out of the way since you won't need to see or change it very often. (If the same chart was going to be referenced by many workbooks, you could even move it to a separate workbook and point all formulas at that, since it's always best to have one copy of identical data instead of many in different workbooks.
Also to assist with potential future changes (and just to be tidier), instead of referring to the target table range addresses (like "J4:L8" etc) I named two ranges:
the table of multiplier/factor data can be referred to by it's address, or by myMultipliers
the titles of the same table is also called myMultiplierTitles (used to match to the titles of column G & H on the original sheet.
Formula
After those changes, the lookup formula in G2 is:
=INDIRECT(VLOOKUP($E2,myMultipliers,MATCH(G$1,myMultiplierTitles,0),FALSE)&ROW())*VLOOKUP($E2,myMultipliers,MATCH(G$1,myMultiplierTitles,0)+1,FALSE)
INDIRECT returns the value of a cell that you refer to by name (text/string) as opposed to directly (as a range). For example:
=INDIRECT("A1")
returns the same as
=A1
...but with INDIRECT we can get the name from elsewhere (a cell, function or formula). So if x="A1" then =INDIRECT(x) returns the same as the 2 above examples.
Your original plan of storing the entire formula in a table as text would have worked with the help of INDIRECT and/or EVALUATE but I think this way is considered better practice partly because it facilitates easier future expansion.
The formula is longer than it would have been, but that's mostly because it's dynamically reading the field names. And size doesn't matter. :-)

Excel VLOOKUP returning same value in all rows

The vlookup function appears to be broken. It is returning the same value for all lookups, but it should not.
I have it set like so:
=VLOOKUP(A3, Asset_Mapping!A$2:B$673, 1)
Where the lookup value is in the B column and the result is in the A column.
I use the $ so the rows are not auto-updated to A3:B674 etc as I paste the formula down the rows. However, even if I manually enter that formula into the next row, it is not finding the correct value.
IF i remove the "$", the correct values are found for the first rows where the values fall within the modified range (e.g. Asset_Mapping!A3:B674) but eventually as expected it stops finding the values as the range is invalid.
What am I doing incorrectly here? I have formulas set to auto-calculate.
Without testing on your actual data it's hard to confirm this will work but add the false parameter. This will find exact matches and not the first partial match.
=VLOOKUP(A3, Asset_Mapping!A$2:B$673, 1, false)
Collating the points together and clarifying the formula
Parameter 1: The value you are looking for
Parameter 2: The table with the data. First column is the value you are looking for.
Parameter 3: The column number of the value you want to show.
Parameter 4: If you want an exact match or partial match.
#Jeeped made the point of ordering data to get more reliable results. Good advice.
Andres has the right idea, but there is a faster way to fix the problem.
If it is returning the same value over and over again for your whole range, you probably have your Calculation Options set to "Manual".
Go into Formulas on the top ribbon and choose Calculation Options. There, you can change your calc method to "Automatic".
Also lookup value must be in first column.
Where the lookup value is in the B column and the result is in the A column.
VLOOKUP always lookup in the left-most column and returns a value from the column number specified. If you want to reverse the lookup/return order then use INDEX(..., MATCH(...))
=INDEX(Asset_Mapping!A$2:A$673, MATCH(A3, Asset_Mapping!B$2:B$673, 0))
Note that you were using a sorted, binary lookup; I've changed this to an exact match lookup which does not require sorted data.
Just in case adding a solution to this topic.
Don't know why in big tables Vlookup and Index+Match tend to show just the value of the first result in all the other cells.
In my case to fix this, after I've copied the formula in the whole range, I choose any cell containing it, press F2 and then Enter. It kind of forces excel to process everything.
I've been working on this for a week with no results. I've created this same spreadsheet for another apartment community without any issues, but for some reason, I cannot get the proper results in this spreadsheet. I've tried vlookup as well, but that didn't help either. any more advice?
Formula
Result and lookup vectors

Excel Function Return Max Two Values

I am looking to get some help with a function that I am sure is an option but I sadly have no clue on how to implement.
Basically, I'd like a formula to go from C21:C50 and look for the top two values. Based upon which two are the top, it would reference the name in B column and populate that value in the another cell (the cell the formula resides in)
If you look at the image, in the primary field, we'd have Steve. Secondary would be Alan.
Is this something anyone can help with? I simply am lost :(
Try
=INDEX($B$3:$B$7,MATCH(LARGE($C$3:$C$7,ROW(A1)),$C$3:$C$7,0))
with Bob in cell B3 and the "primary" formula in cell C9. Copy down to cell C10.
If dealing with integers, you can simply add +1/ROW([range]) to avoid doubles:
=INDEX($B$3:$B$7,MATCH(LARGE($C$3:$C$7+1/ROW($C$3:$C$7),ROW(A1)),$C$3:$C$7+1/ROW($C$3:$C$7),0))
This is an array-formula and must be confirmed with ctrl+shift+enter!
However, this may fail for numbers like 5.01 or 4.99. For that case just use it in combination with RANK.EQ:
=INDEX($B$3:$B$7,MATCH(LARGE(RANK.EQ($C$3:$C$7,$C$3:$C$7,1)+1/ROW($C$3:$C$7),ROW(A1)),RANK.EQ($C$3:$C$7,$C$3:$C$7,1)+1/ROW($C$3:$C$7),0))
This is an array-formula and must be confirmed with ctrl+shift+enter!
The steps as picture:
The first table shows the direct adding of 1/ROW which is used for LARGE and MATCH to get the row if doubles exist (so INDEX can pick the correct one)
The second table shows how the values get replaced by their rank with RANK.EQ and then are treated the same like the first table.
The third (grey) table shows, what would happen if the first formula is applied to the second table (to demonstrate how the ranks get messed up).
For Excel 2007 just replace the RANK.EQ($C$3:$C$7,$C$3:$C$7,1) with RANK($C$3:$C$7,$C$3:$C$7,1).
If you still have any questions, just ask :)

Resources