Set distinct drop-down values based on vlookup - excel

Col A Col B
Fruit Grapes
Fruit Mango
Fruit Mango
Veg Carrot
Veg Brinjal
Fruit Banana
Veg Carrot
I have a similar requirement as shown in this thread
set drop-down values based on vlookup
This works fine, however now the requirement for me is in Column B there will be duplicates and the dropdown has to show only distinct values. Can any one help me with this
See file here Requirement
I want to achieve this by pure Excel formulas and not by VBA code.

Part 1 - This just shows how to create a unique list in a drop-down.
Here's a screenshot, but currently it requires that there is a row above the data(?). This provides a unique list of items in a Data Validation drop-down. (All the formulas below can be made easier to create by naming some ranges beforehand.)
The array formula in E2 is shown in the comment. Use Ctrl-Shift-Enter to enter an array formula, then drag this down as far as necessary - the #N/As will begin to appear at the bottom.
Gosh, it's hard to describe :). The COUNTIF essentially generates a sequence of 1s and 0s to indicate whereabouts in column B the previous (above) values in column E are positioned in column B. This sequence always starts with a 0 (for the formula in E2) because it's looking for a blank which doesn't occur in column B - so this will grab the first item, Grapes.
The MATCH then finds the first 0 in this sequence of 0s and 1s, which indicates that a value (in column B) hasn't already appeared in column E.
INDEX then uses this MATCHed value to retrieve the new unique item from column B.
Then a Defined Name is created (on the Formulas tab) that gets all the values in column E, but only down to the first occurrence of '#', which indicates there are no more unique values in the list.
This Defined Name is then used in the Data Validation.
Part 2 - The Answer (with VBA)
The following VBA code is required so that clicking in a cell in C11:C18 will change the value in F1, which generates the unique list underneath, which populates the data-validation list in C11:C18.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("C11:C18")) Is Nothing Then
Sheets("Sheet1").Range("F1").Value = ActiveCell.Offset(0, -1).Value
End If
End Sub
It requires the formulas and defined-name as shown in the following screenshot. The formula in F2 is different to F3, which is then copied down.
The number 10 in the formula in F3 is just a large number (of rows).
Column E are the unique items.
Column D are the corresponding categories.
Column F are the unique items for the category in cell F1 (extracted form column E).
Part 3 - Without VBA
Use the formula =INDIRECT(ADDRESS(CELL("row"),CELL("col")-1)) in cell F1. When you click into a cell in C11:C18 you need to press F9 to recalculate the worksheet, which updates the drop-down list.
Recalculating is necessary to update the CELL("row") and CELL("col") values.
Part 4 - Without pressing F9
It can be achieved without having to press F9, but it means spreading all the categories across different columns (G1 and to the right in the below screenshot). This can also be achieved with the array formula =INDEX($A$2:$A$8,MATCH(0,COUNTIF($F$1:F1,$A$2:$A$8),0)) in G1.
The #N/As can also be removed the the drop-down lists with strategic use of IFERROR() in the formulas from G2 onwards, substituting "". Alternatively, using:
=OFFSET(Sheet1!$G$1,1,MATCH(Sheet1!B11,Sheet1!$G$1:$J$1,0)-1,MATCH("#",OFFSET(Sheet1!$G$1,1,MATCH(Sheet1!B11,Sheet1!$G$1:$J$1,0)-1,COUNTA(Sheet1!$G:$G)-1,1),-1),1)
as the defined-name Items would not only remove the #N/As but also the redundant ("") values that IFERROR() would leave in the drop-down lists. (The cursor needs to be positioned in C11 when creating this defined-name.)
Apologies for the length of this, but hope it is of interest to someone.

Related

Sorting multiple sheets into 1 line and having each line display on a results page

looking for some help speeding up sorting pages on a spreadsheet.
Currently we have 4 sheets absolutely packed with UK postcodes/zip codes.
At the moment we go into each sheet and sort the entire sheet to show the information for the specific postcode we enter. (Always returns one line of info each sheet)
Is it possible to just have a separate sheet where we enter the postcode it it finds the match from each sheet and displays 1 line from all 4 sheets? Hopefully that makes sense.
A idiot's guide tutorial would be great
So, let's say we have four sheets (sheet1, sheet2, sheet3 and sheet4). They all look like this:
Create your 5th sheet. Here, I'm calling it "lookup_here". You should look up how to use vlookup formulas as I'll fail to completely explain it here for lack of time. Basically, you are :
Looking up a value (such as 5F3322 postal code) in a table array
(such as sheet1 columns A, B, C and D.... keeping in mind that your
lookup value must be in the first column of the array)
Then returning the column index (like column B is 2, column C is 3, etc).
And finally stating if you want an exact match (false) or approximate
match (true). Almost always use false.
Here is what the final output would look like, and I'll put some sample formulas below the picture.
So, you'll input your postal code value in cell B1. Then you will have formulas in B3 through D6. It will take some time to build these.
B3 Formula: =VLOOKUP($B$1,Sheet1!$A:$D,2,FALSE)
B4 Formula: =VLOOKUP($B$1,Sheet2!$A:$D,2,FALSE)
B5 Formula: =VLOOKUP($B$1,Sheet3!$A:$D,2,FALSE)
B6 Formula: =VLOOKUP($B$1,Sheet4!$A:$D,2,FALSE)
Column C formulas are similar, but the 2 before false will be a 3.
Column D formulas are similar, but the 2 before false will be a 4.

Trying to get 2 field to match data in a second sheet and return a value

Im trying to get the following working in excel and i just cant seem to do it.
I have 2 sheets, one with data in (Sheet 2), one where ive created a questions box with a response field (Sheet 1).
So in the data sheet there are columns A, B and C.
On the questions box (Sheet 1) i need to know if a figure put into A and a figure put into B, both match the data in columns A and B in Sheet 2 if they do i want to return the figure which corresponds in column C in sheet 3 to column C in sheet 1.
Ive assumed i need to use an IF AND formula and have tried the following in various different ways, but all it gives me back each time is 0.
=IF(AND(A1=Sheet3!A:A,B1=Sheet3!B:B),Sheet3!C:C,0)
Im at the end of my tether with this so any help would be appreciated.
This is an array formula, apply this by hitting Ctrl+Shift+Enter while still in the formula bar.
=IFERROR(INDEX(Sheet3!C:C,SMALL(IF(A1=Sheet3!A:A,IF(B1=Sheet3!B:B,ROW(Sheet3!A:A)),1)),"No Match Found")
This should work by building an array of the row numbers that have a match for both A and B then take the first match, SMALL([array],1), by taking the first smallest number from the array and feeding that to INDEX().
This formula can be adjusted to be dragged so that it returns multiple matches by changing small to SMALL([array],ROW(1:1) and dragging the formula down, though I would suggest changing "No Match Found" to "" so that you just have blank cells once you have displayed all of the matches.
If you're happy using an array formula (press Ctrl and Shift when you press Enter), then this formula should work fine:
I originally read it as you wanted to get the info from Sheet 3, so this would have worked:
=INDEX(Sheet3!B1:B6,MATCH(INDEX(Sheet2!C1:C6,MATCH(A1&B1,Sheet2!A1:A6&Sheet2!B1:B6,0),1),Sheet3!A1:A6,0),1)
But re-reading, I don't think that's the case, so this should do...
=INDEX(Sheet2!C1:C6,MATCH(A1&B1,Sheet2!A1:A6&Sheet2!B1:B6,0),1)
This is using:
A1 as your first answer to compare values in A1:A6 in Sheet2
B1 as your first answer to compare values in B1:B6 in Sheet2
Gets the corresponding value where both the above two match from C1:C6 in Sheet2.
Then, it looks for that value in A1:A6 in Sheet3 and returns the corresponding value from B1:B6 in Sheet3

Subject =LARGE to a condition

I am trying to create a dashboard that will find the largest ten values based on data in column D and display the contents of column C while excluding from the selection any row that contains a specific value in column B.
I am currently using =INDEX($C$1:$C$100,MATCH(LARGE($D$1:$D$100,1),$D$1:$D$100,0)) to find the largest value in D and display C.
I can't figure out how to exclude from the LARGE call any rows that have SKIPME in column B.
You can use an IF statement to do that:
=INDEX($C$1:$C$100,MATCH(LARGE(IF($B$1:$B$100<>"SKIPME",$D$1:$D$100),1),$D$1:$D$100,0))
Except that it also converts the formula into an array equation, so that you now have to press Ctrl+Shift+Enter to make it work.
You can also use this equivalent function, also called with CSE but slightly shorter:
=INDEX($C$1:$C$100,MATCH(LARGE(($B$1:$B$100<>"SKIPME")*$D$1:$D$100,1),$D$1:$D$100,0))
Or if you're only looking for the biggest value, then MAX works just as well:
=INDEX($C$1:$C$100,MATCH(MAX(($B$1:$B$100<>"SKIPME")*$D$1:$D$100),$D$1:$D$100,0))
In order to avoid problems with duplicate values in column D you can use this setup:
In F2 down to F11 list the values 1 to 11
In G2 use this formula confirmed with CTRL+SHIFT+ENTER and copied down to get the associated values from column D
=IFERROR(LARGE(IF(B$2:B$100<>"SKIPME",IF(D$2:D$100<>"",D$2:D$100)),F2),"")
then to get the column C items for the top 10 values use this formula in H2 confirmed with CTRL+SHIFT+ENTER and copied down
=IF(G2="","",INDEX(C$2:C$100,SMALL(IF(B$2:B$100<>"SKIPME",IF(D$2:D$100=G2,ROW(D$2:D$100)-ROW(D$2)+1)),COUNTIF(G$2:G2,G2))))
If there are fewer than 10 qualifying values you get blanks - see example here

Count values in groups

I have a table with student IDs separated in groups. I need a handy way to count the total number of students in each group and populate it after the last row of each group (marked with ??)
Currently I just enter =COUNT() and then manually figure out the top and bottom borders of the range for each group. Not convenient at all.
I was thinking that a possible solution could be one of the following:
A some kind of pivot table permutation. I failed on this one.
Excel Data->Outline->Subtotals functions. Again, fail. It keeps creating new rows in my table.
A universal formula that can be pasted into each ?? cell. Not the most graceful solution, but still would do.
A macro. As a last remedy if nothing else works.
The following steps will calculate the subtotals while preserving the structuring and formatting of your worksheet.
Put this formula in cell C1 and copy the formula down the column:
=IF(NOT(ISERROR(SEARCH("Total",A1))),COUNTA(INDIRECT("B"&MATCH(LEFT(A1,LEN(A1)-7),A:A,0)+1&".B"&(MATCH(A1,A:A,0)+1))),IF(B1="","",B1))
Apply a conditional format to cell C1 with the formula rule =(MOD(ROW(C1),2)=0) and blue fill to match the shading on the other rows. Copy the format down the column using Paste Special Format.
Either hide column B, or copy the values in column C to column B using Paste Special Values and hide Column C. If you decide to copy the values to column B, you won't need to set the conditional formats.
Here is what the formula does:
First, check whether the formula's row is a Total row, by searching the cell in column A of the row for the word "Total," using the SEARCH function.
If the word "Total" is found:
Determine the range in the worksheet of the student IDs for the group for that total row:
a) Identify the rows in which the words "GroupX" and "GroupX Total" are found by using the MATCH function. With that, you know that the IDs for the group are in a range that starts at, say, row x and ends at row y.
b) With the starting and ending row numbers, construct the address range in which the IDs lie, which has to be the string "B" + (row x) + "." + "B" + (row y).
c) Turn the string into a range reference that can actually used in a formula using the INDIRECT function.
Count the number of students in the group using the COUNTA function and the range, and show that as the formula's result.
If the word "Total" is not found
Check whether the cell in column B is empty
a) If it is empty, show a blank as the formula's result
b) if it is not empty, it must be a student ID, so show the ID as the formula's result.
Add a column (I usually add it to the LEFT of the existing matrix) where you enter a formula from row 2 onwards that fills the blanks in the old column A. Then the old matrix including your new column can be used in a pivot.
So Insert a column left of your matrix, this is column A now. Put a header in Cell A1, for example "Group Name1"
Enter the following formula in cell B2 and extend it to the end:
=IF(B2="",A1,B2) This way your blanks will be filled.
Now apply a pivot on this matrix and there you are.
Maybe not the nicest looking solution, but its quick and works well.
If u have table like this
Students id Name of students group ........
then u can use countif/countifs formula

Excel Lookup Return Unique Value

I have two sheets one has
Item ID
Box 78
Glue 105
Box 85
The other sheet
Item ID
Box
Box
Glue
On the second sheet I want to look up the an ID from the first sheet.
Where there I duplicates (as in Box) I want to return the IDs one at a time.
So the lookup on Box would return 78 the first time, and 85 the second time.
Like this:
Item ID
Box 78
Box 85
Glue 105
Alternate solution. Does not require helper columns, does not require array entry. In Sheet2 cell B2 and copy down:
=INDEX(Sheet1!$B$2:$B$4,MATCH(1,INDEX((Sheet1!$A$2:$A$4=A2)*(COUNTIF(B$1:B1,Sheet1!$B$2:$B$4)=0),),0))
You can use a slight variation of INDEX/MATCH:
=INDEX(B$2:B$4,SMALL(IF(A$2:A$4=C2,ROW(B$2:B$4)-1,""),COUNTIF(C$2:C2,C2)))
Confirm as an array formula with Ctrl+Shift+Enter, then autofill down.
Explanation of cell references:
A$2:A$4 - Item Column (sheet1)
B$2:B$4 - ID Column (sheet1)
C$2:C2 - Item Column (sheet2)
C2 - The item you're looking up
At first glance this seems impossible, because VLOOKUP doesn't know how to deal with multiple Boxes.
But using this ingenious answer you actually CAN make this work.
On Sheet 1, enter the formulae:
Which results in:
item instance combined id range_above
Box 1 Box1 78 $A$2:$A$2
Glue 1 Glue1 105 $A$2:$A$3
Box 2 Box2 85 $A$2:$A$4
You can now VLOOKUP off combined instead of off item. (Obviously you'll have to do an identical trick in sheet 2.)
Note this all these formulae can just be extended down however long your table is. It will always just work.
A good method for doing this would be to use an array formula to look up the values from the first sheet using the number of repetitions of each item from the second sheet. This method requires no "helper" columns.
The formula that will accomplish this is: {=INDEX(Sheet1!A:B,SMALL(IF((Sheet1!A:A)=Sheet2!A2,ROW(Sheet1!A:A),""),COUNTIF($A$2:$A2,"="&$A2)),2)}
This formula is an array formula. You can copy it into cell B2 on Sheet2, and press Ctrl+Shift+Enter to enter it. You must press Ctrl+Shift+Enter to make this an array formula. You can drag this formula down column B for as many rows as you would like.
Your worksheet, when finished, will contain the following formulas:
Let's break this formula down into its components:
Identify how many times a given item has been repeated in column A. We accomplish this with the following code, which will count the number of times that the current row's item has appeared in all previous rows in column A. The absolute reference for the start of the range and the relative reference for the end ensures that the range will be automatically updated as we drag the formula down in column B:
COUNTIF($A$2:$A2,"="&$A2)
Identify the kth row in Sheet1 containing the item in column A of Sheet2. The following code first uses an IF statement to find all rows in Sheet1 containing the item in Column A of Sheet2. This uses array syntax to compare all rows in the specified range against a value. The IF statement returns an array containing the rows that were identified if any were found. If none were found, it returns the empty string.
IF((Sheet1!A:A)=Sheet2!A2,ROW(Sheet1!A:A),"")
Look up the value of the nth row that was identified using the SMALL function, which selects the nth smallest item from an array. For k, we pass the count that was calculated in step 1.
SMALL(IF((Sheet1!A:A)=Sheet2!A2,ROW(Sheet1!A:A),""),COUNTIF($A$2:$A2,"="&$A2))
Finally, we put it all together in the INDEX function, which will look up the value at the specified row (identified in step 3) and column (2), in a given range.
{=INDEX(Sheet1!A:B,SMALL(IF((Sheet1!A:A)=Sheet2!A2,ROW(Sheet1!A:A),""),COUNTIF($A$2:$A2,"="&$A2)),2)}

Resources