How can I remove an item from a cell's validation list when the cell already contains a value on that list? - excel

I would like to remove an item from a cell's validation list when the cell already contains an item that has been selected from that validation list, in order to prevent the same item being re-selected in that cell.
Suppose an empty cell has the validation list {10,20,30,40,50}. When I select, say, '20' and then go back into that cell's validation list, I want to just see {10,30,40,50}. If I then select, say, '40' and go back into the validation list again, I want to see {10,20,30,50}, etc. It's important this also works for text values.
I originally viewed this problem as being about creating 2 lists and joining them together; e.g. in my first example, removing '20' can be thought of as creating lists {10} and {30,40,50}, so I tried using the 'comma' operator to join two ranges in the Data Validation dialogue, without success. I tried the same approach in a named formula and using that in the DV dialogue. Same result.
I created a UDF:
Function UNION(rRng1 As Range, rRng2 As Range) As Range
Dim rRng12 As Range
Set rRng12 = Union(rRng1, rRng2)
UNION = rRng12
End Function
and tried this in both the DV dialogue and via a named range. Still didn't work.
[EDIT]: This functionality needs to work in a structured table, where one of the columns is updated from the validation list.
I've concluded that I need to use an array formula within a named range, and reference this from the DV dialogue, but I'm not clear on how this can be done?

Here's what I came up with. It will work for numbers, but will probably need some work if your list is text.
In E1:E5, put your list (10,20,30,40,50). In G1:G5, put the formula
{=SMALL(IF($E$1:$E$5*($E$1:$E$5<>$A$1),$E$1:$E$5,""),ROW())}
That takes the list from E, removes the number in A1 that matches, and sorts it. Now create a named range called dvExclude with this as the RefersTo
=Sheet1!$G$1:INDEX(Sheet1!$G$1:$G$5,COUNT(Sheet1!$G$1:$G$5))
The G range will have errors at the bottom and this will exclude those - COUNT only counts numbers, not errors.
Finally, set up your data validation in A1 as List and =dvExclude.

Related

Excel: Dependant Data Validation Listing values from table with criteria without Macro

I would like to create a data validation field that draws values from a table, but only those values where a corresponding value matches a cell reference: the Month
Ideally this should be done dynamically, rather than having to create multiple named ranges.
I have included an image highlighting the target values I want to pull for January.
Edit: I am exploring using the FILTER formula, but no luck so far.
Edit 2: I got FILTER to work to provide the set of values I'm looking for, but it doesn't seem to want to work as data validation.
=FILTER(tblDate[Date],(tblDate[Month]=E2),"")
As has been commented, the Data Validation list will not accept FILTER, but it will accept other formulae.
In the example, you can set the List validation as:
=OFFSET(B2,MATCH(F2,A2:A18,0)-1,0,COUNTIF(A2:A18,F2))
keying off cell F2 for the value of the month.
NB: This works if the months are ordered (as in the given data). Also note that the List formula doesn't seem to like the Table[] syntax, so you have to put the ranges in as R1C1 format.
Alternatively you can use FILTER() for non-ordered data but put the results in a hidden column (Column H in the example below) on the spreadsheet. It is not as neat, but is more flexible, and allows the Table[] syntax.
eg
H2 = FILTER(Table1[Date],Table1[Month]=F2)
List Range
=$H$2#
(The # uses the result of the FILTER array function from cell $H$2: Hat-tip to #Ike)

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.

VLookUp with Nested SUMIFS

I have been trying to make a form for some of my team members who are not that computer literate, and I essentially want to make it click and go. I thought I could do it...but alas I am not as good with nesting functions as I thought I was.
I have this spreadsheet where I want to put data into the yellow cell. On the next sheet I have the below table. What I want to do is use a formula to fill H4 with the "Request Branch's" Account Number. Now, I have currently filled the cells with information. They, in fact, have drop down options - which are pulled from the Account List table. As a result the value in H4 will continually change based on the needs of the user - but must be within the confines of the Account List Table.
What I have tried is here and enter link description here. I keep getting result of #Value, or N/A. I can't figure out what I am doing wrong. I know that I need to nest the SUMIFS withing VLookUp, but I am not sure as to why it won't work.
I'm providing you with two possible solutions.
1) The first one uses the SUMPRODUCT function. You may not have seen this kind of notation before.
When ranges are multiplied by each other like so (B3:B8=G3)*(C3:C8=G4) they are actually turned into boolean arguments. If you highlighted this part of the code and pressed F9 it would look like this: {0;0;0;0;1;0;0}. This is an array where TRUE for both criteria meet. So our Branch is "A" and our Carrier is "F". In the rest of the cases either or both are false resulting in zeroes.
Now if you multiply this array by the range with account numbers, obviously the only number remaining will be the one multiplied by 1 and so you have the answer however keep in mind that as you are multiplying if the account is not a number the function will fail!
2) This is why we have a second method using =INDEX() and =MATCH() functions.
To overly simplify this - the INDEX function grabs contents from an array at a specified position (row and column), while the MATCH function gets the position of an item in an array.
The idea with using ranges as multiple criteria is the same as in the first example, however this time when we get our array of zeroes and ones {0;0;0;0;1;0;0} we use the match function to find at which position our criteria cross (as seen on the screenshot it's the 5th position, as it's in the 5th row of the entire column D, the match function searches the {0;0;0;0;1;0;0} array for a 1 and returns its position in the array) and so this is our ROW.
Knowing the position of the contents we searched for we use the INDEX function to grab the contents of the cell in that position so =INDEX(D2:D8,MATCH(1, INDEX((B2:B8=G3)*(C2:C8=G4),0),0)) is actually =INDEX(D2:D8, 5) meaning that the INDEX function grabs contents of the 5th row from the range D2:D8 which is cell D6.
The green boxes are just there to show the instance where both of our criteria are met (cross).
Please try this formula.
=INDEX(Table1[Account],SUMPRODUCT((Table1[Branch]=F$3)*(Table1[Carrier]=F$4)*ROW(Table1[Account]))-1)
Note that you may have to adjust the final -1. This is because the indexed table starts in row #2 and the SUMPRODUCT function returns a sheet row number. If your table would start in a different row the difference between the sheet row and table row would be larger. It must be adjusted here. Or you might work with sheet references (named ranges) and require no adjustment at all.

Excel Create Data Validation Unique items for dynamic Drop Down List without new Column

My Table A list which grows on data refresh is as follows:
Balham Halfords - P83690
Balham Halfords - P83690
Gloucester & Durham St - P83680
Gloucester & Durham St - P83680
In another sheet, I want data validation on the drop down list to show only:
Balham Halfords - P83690
Gloucester & Durham St - P83680
The trouble is, I don't want to create a distinct list off Table A anywhere in the book, and I want the data validation list to be intelligent to new records coming into to Table A.
If you want to use Helper column approach with formula, try this solution.
if your data is in column A, enter this formula =IFERROR(INDEX($A$2:$A$900, MATCH(0,COUNTIF($D$1:D1, $A$2:$A$900), 0)),"") in cell D2 and drag it down as long as you estimate there will be distinct values. You must enter it using CTRL+SHIFT+ENTER since it is an array formula.
Then use data validation, select list and under source enter this formula =OFFSET(D2,0,0,198-COUNTBLANK(D2:D200),1)
Now whenever new values are added to table, they are also automatically added to your data validation list.
#DasalKalubowila, here is a modification on #KresimirL's answer that may be what you're looking for.
First, create a defined name for your input data. Do this by going to Formulas on the ribbon and then clicking Name Manager under the Defined Names group.
In my example, I called the input data range InputData. The formula I used is
=Sheet1!$A$2:INDEX(Sheet1!$A$2:$A$501,MATCH("Ω",Sheet1!$A$2:$A$501))
where
Sheet1 is the name of the worksheet where the input data lives,
$A$2 is the first cell containing data in your input range (I call this the anchor),
$A$2:$A$501 is the max area of the column where your data either lives and could potentially live in the future, and
"Ω" is the Omega letter. You can get this by holding down ALT and pressing 2 then 3 then 4 on the 10-key number pad (it can also be found in the character map application in Windows).
This formula effectively grows or shrinks your range of data based on how many entries exist.
Next, you need to create a helper column. I know this wasn't desired, but it's going to be one of the only/better ways out there. I placed mine on the same worksheet as my Input Data, but you don't have to. The formula I used in E2 is
=IFERROR(INDEX(InputData,MATCH(0,COUNTIF($E$1:$E1,InputData),0)),"")
You'll need to commit this with Ctrl+Shift+Enter as it's an array formula. Then drag that formula down as far as you to. You'll basically want to go down as many rows as you think you'll have unique entries.
I then needed to create one more defined name, which is what will be used under my Data Validation in the next step. I called this new defined name ValidationList (this needs to be scoped to the Workbook). The formula I used for ValidationList is
=Sheet1!$E$2:INDEX(Sheet1!$E$2:$E$501,COUNTIF(Sheet1!$E$2:$E$501,">*"))
See the notes for InputData above to understand this formula better. The only difference is that instead of MATCH, this formula uses COUNTIF. This is because if your unique values don't yet fill the entire range you dragged your formula down in Column E (in the previous step), using MATCH in the same way was before would end up grabbing a whole bunch of blanks we don't want. COUNTIF therefore only counts those cells that contain a value greater than "*", with asterisk being a wildcard for any character (and "" contains no characters, so it excludes those items).
Now, create your data validation and set it up like such:
Now you should be left with this:
And when you add information to your InputData area, your range of ValidationList should expand to include the newest uniques, which in turn will populate inside your Data Validation area, like such:
I find that this doesn't seem to slow my workbooks down too significantly, but I'd be interested in hearing how it performs in yours.

Excel: Dependent Dropdown Lists on Dynamic Content

I've imported a list of clients and their websites from the Google Analytics (GA) API in the following format:
Account Profile
Client 1 www.client1.com
Client 1 sub.client1.com
Client 1 tst.client1.com
Client 2 www.client2.com
Client 3 www.client3.com
Client 3 sub.client3.com
What I need is a dropdown list with the unique accounts names and then a second dropdown list with the dependent profiles of the chosen account. Something that looks like this:
Account Profile
Client 1 www.client1.com
sub.client1.com
tst.client1.com
We add accounts and profiles to GA all the time, so the list will need to be refreshed every time we run the report.
How would I go about doing this?
As long as you have this list sorted by Account, you can use a mixture of Offset CountA to give you all the ranges you need.
Steps would be:
a. Get unique values from Account column (i'm using VBA for this step but you could use Frequency formula to mash this too -- I'd avoid it if you can use VBA for this). Something along the lines:
Sub FindUniqueValues(SourceRange As Range, TargetCell As Range)
SourceRange.AdvancedFilter xlFilterCopy, , TargetCell, True
End Sub
(I've called this from my worksheet_change event for ease but if you are using vba to pull G.A. data, just integrate into that)
b. Feed this to Named Range (Say AccountsRange) that has the forumla =$D$2:INDEX($D$2:$D$5000,COUNTA($D$2:$D$5000)) -- This assumes you specified D1 as TargetCell for previous step and unique values won't be more than 4999 (1st value is row title in my case -- Hence starting from D2)
c. Add this Named Range AccountsRange as source for Data Validation List -- Your account combo box is done at this point. I'm going to assume you put this combo box in E2 and I'll build on this to derive the second ComboBox
d. Create a new Named Range say ProfilesRange with formula =INDEX($B$1:$B$5000,MATCH($E$2,$A$1:$A$5000,0),1):INDEX($B$1:$B$5000,COUNTIF($A‌​$1:$A$5000,$E$2)+MATCH($E$2,$A$1:$A$5000,0)-1,1)
Note: if you copy paste from here the above formula will contain a line-break invisible character after COUNTIF($A and excel will complain about invalid formula, just retype $A$1 part of COUNTIF and it should be fine
A2 is the start of Account column of G.A. imported data (A1 being the title and assuming maximum of 4999 data rows here) E2 is the Comboboxed cell from previous AccountsRange dropdown step. -1 in Match step is needed as the offset needs to be 0 for first value row and not 1 which will be returned from Match. Second 1 is column offset (it can be more if you need to hop several columns to get secondary data). CountIf is pretty self explanatory :) This basically gets us the number of cells we need in final range from the starting point.
e. Create your new Data Validation List that uses ProfilesRange as its source and your secondary combo box is done.
Issues that may arise:
When you change Accounts Combobox, Profiles combobox will probably error out as the values in profiles are unlikely to be present in new client. You could either ignore the error (it will fix itself once you select correct value from newly refreshed dropdown or throw a bit more of VBA fairy dust in there to clear the drop down cell when the value changes in E2.
Data Validation List compalains about evaluating to an error when you try to setup ProfilesRange. It is safe to ignore this error and continue. It basically means nothing computable was returned by ProfilesRange (most probably because you haven't selected anything in AccountsRange that actually computes to a ProfilesRange -- of course assuming your actual cell ranges for formulae used here are actually correct for your sheet)
Thanks to osknows for his tip and improvement on forumlae (in comments below): Avoid use of OFFSET its very slow over large ranges and is volatile. =OFFSET($D$2,0,0,COUNTA($D$2:$D$5000) can be replaced with =$D$2:INDEX($D$2:$D$5000,COUNTA($D$2:$D$5000)) for the named range. (this tip has been incorporated into this solution now, so you won't see the original Offset forumlae unless you check version history)

Resources