I am trying to piece together some VBA code that would apply data validation (creating a list to use) to a cell based on the value of the cell next to it. I have this functionality working in a Google Spreadsheet which I just linked but I don't know anything about VB so I'm struggling with this.
The layout is a little odd with the spreadsheet since the sheet(s) that need this validation have the headers of the rows starting at row 2.
The basics of what's going on is:
The header of the column that is determining the validation is called "Attribute Group". I want to avoid needing a fixed position so I went with the header name instead of a column index
When a value changes in "Attribute Group" the cell adjacent to it to the right will have a dropdown created with values corresponding to the value in "Attribute Group"
Please check out the linked spreadsheet to see this functionality in action. I'm trying to get as close to this as possible in Excel.
Edit: The main question is: how do you create dynamic data validation in Microsoft Excel?
Unfortunately I don't have time to get this working exactly as I would like.
The solution I have now was to create tables for each column that had data that would correspond with the appropriate "Attribute Group".
Insert > Table
Rename table to match corresponding "Attribute Group" value, removing spaces and special characters
Remove duplicates to get rid of most blank cells then Resize Table if needed to get rid of any others
Then I added data validation in cell E3 using =indirect() as well as substitute() since my "Attribute Group" values had spaces and special characters.
Data > Data Validation
Under "Settings" I used "List" in the Allow section
The source was =INDIRECT(SUBSTITUTE(SUBSTITUTE($D3," ",""),"&","And"))
Then I copied cell E3 and pasted all the way down.
This method solves my current issue but doesn't allow for the level of flexibility that I was hoping to accomplish.
Use a named range (Eg "MyDataRng") for the range of cells in the Attribute Group then in a list type data validation enter =MyDataRng
Related
I am trying to do a data validation list where the drop down only contains text like "US" or "EU" to isolate the PO numbers. The table column I am pulling from can have things like "US12345" or "EU76543" or "ID10987". I need the list to only show the items that have that US in them.
I tried:
=IF(INDIRECT(Table[PO_Number])="US*",INDIRECT(Table[PO_Number]),"")
This gives a Value Error.
Is what I am trying to do possible? If so, how?
You'll need to create the desired filtered list somewhere within the workbook, as dynamic lists cannot be entered directly within Data Validation.
For example, assuming you have Office 365, this formula in cell D1:
=FILTER(Table[PO_Number],LEFT(Table[PO_Number],2)="US")
will spill all matching entries.
(Amend the condition - here checking if the initial two letters of the PO Number are "US" - as required.)
For the Data Validation, you can then use the List option and set the Source to:
=$D$1#
Include the sheet name in the above expression if the cells being validated are not in the same sheet as the FILTER formula.
I got a problem with some popular Excel question, dynamic ranges and data validation drop-downs and auto-populate. Lets say I got 2 sheets, and on one sheet I got drop-downs to choose from another sheet, and that is not a problem when I define cells and range using:
=OFFSET($A$19;;;COUNTA('0528 - info'!$E$2))
..but what about when I wanna add some new cells in between,so that they can be automatically recognized in which group they belong:
As you see for instance Column B has some "groups" where you can find more different "values" like in Column C, like Power Supply has MV1 and MV2... and so on. My drop-downs on the sheet 1 are called exactly like this "groups" and I did reference them manually using given function. But is it possible to populate my drop-downs automatically when I add for instance MV3 beneath MV2 in this table? Or RN7 on 14th row? Everytime I add new values I have to extend my dropdowns (what is fine..), but problem will be when I share this table to others, they gonna forget it 90%.
I hope you get my point, any suggest will be fine!
p.s. Indirect doesnt work in a way it should - It gives me all instances from the Column but not specific ones that I need.
=INDIRECT("Table4[VarEDS]")
Well this option gave me again what I already had before - all "matches" from the Column and still not ONLY matches that are for certain group. ...
If your Data Validation source is a "Table" as shown in your image then you can take advantage of "Table Column" Range which is dynamic. That means whenever you refer that column as NAMED range and if make changes to the column (Edit, Add, Delete) it will reflect in the referred cell.
You can use this technique even for ranges not in table. You need to NAME them with offset formula and make dynamic.
You can find dynamic address of your column as shown in the image below. Select entire column WITHOUT Header
Name your column data range with appropriate name as shown in image below
Then in Data Validation Window refer this name using F3 as shown in image below.
Then you can see... Even if you edit, add or delete any row in the column the data validation will change
Editing based on your comment below: If you want text from column B and Column C appear together in the validation dropdown list. Insert column in the table and join text from column B and C and then make data validation based on that column as shown in Colum D in image below
Finally I think I understood your question.
Watch this video
Excel: Find Multiple Matches & Dependent Drop Down List
After some days of searching and trying I got what I wanted - wasnt wasy job at all. Needed to combine more functions with the help of couple of videos from Leyla (Xelplus):
https://www.youtube.com/watch?v=gu4xJWAIal8
https://www.youtube.com/watch?v=7fYlWeMQ6L8&t=5s
First step was to make unique list of my values (text in my case) on separate sheet:
=IFERROR(INDEX(t_VarGroup[Vargrouptext];MATCH(0;INDEX(COUNTIF($J$2:J2;t_VarGroup[Vargrouptext]););0));"")
Then I needed to "extract" all the values that are belonging to the certain unique values:
=#IF($I3<COLUMNS($K$2:K$2);"";INDEX(t_EDS[[VarEDS]:[VarEDS]];AGGREGATE(15;3;(t_VarGroup[[Vargrouptext]:[Vargrouptext]]=$J3)/(t_VarGroup[[Vargrouptext]:[Vargrouptext]]=$J3)*(ROW(t_VarGroup[Vargrouptext])-ROW(t_VarGroup[[#Headers];[Vargrouptext]]));COLUMNS($K$2:K$2))))
FUrthermore, I created Unique drop down list:
=OFFSET($J$3;;;COUNTIF($J$3:$J$14;"?*"))
And then dependent drop down list nearby using:
=OFFSET($K$2;MATCH($H$2;$J$3:$J$17;0);;1;COUNTIF(OFFSET($K$2;MATCH($H$2;$J$3:$J$17;0);;1;20);"?*"))
And because I made it on other sheet, I had to reference them to an appropriate sheet name where my main sheet is - with drop downs, it is actually very useful for my future work and for everyone else who has struggling with drop downs but on a bit specific way =))
credits to: #Naresh Bhople for suggestion about Youtube videos.
Trying to create a drop-down list in a cell where the source is a dynamic named range. The named range refers to:
=$A$2:INDEX($A:$A,COUNTA($A:$A))
Essentially the range starts at A2 and extends down to the last value in the column so that when I add or remove a value I don't end up with blanks in my list or the new values missing. I can use the following as the data validation source for my list with no problem:
=Named_Range
It provides me with a drop-down list of everything in the named range.
However, when I type the named range's name (Named_Range) into a cell (say F1) and use the following as the data validation source for my list, I don't get the drop-down list:
=INDIRECT(F1)
Searching around revealed that this is a know issue, but I can't get my head around a workaround.
Instead of creating dynamic lists using the method you are using, I suggest using Tables.
Create a table for each dependent drop-down list.
- Be sure to select "my table has headers"
Then
Select the data area of each Table (not the header)
In the Name box to the left of the formula bar, type in the appropriate Name
Hit Enter to confirm the name for the databodyrange.
Repeat for each table.
Since this is a table, the lists will autoadjust as you add/delete rows
You can refer to them with the INDIRECT function as you set up your data validation list formula.
Problem
How can I automatically add rows to an array formula as I manually add rows to a table? Similar functionality seems to be offered by Google Docs at https://support.google.com/docs/answer/3093275?rd=1, and is adapted for Excel with a macro at http://www.wilmott.com/messageview.cfm?catid=10&threadid=62734. However, using this macro requires enabling Microsoft Scripting Runtime, which I'd rather not do, and would also be difficult for the end-user to maintain. I'm running Excel 2013.
I am creating this worksheet for an end-user who may not be knowledgeable about VBA or array formulas, but will need to add items to a Validation table (described below). As the user adds table rows, my data validation range and its array formula are not automatically increased in length, and it's probable that the data validation will no longer show all acceptable values.
Setup for Filtered Data Validation
You can view my stripped-down worksheet with macros disabled here. Data validation on the Process column in the Main table will only show values that are currently showing in the Testing Process column in the Validation table. Slicers are included for ease of filtering.
Using help from http://www.contextures.com/xlDataVal02.html and some other sources, I have created a table named Main_HIGHLIGHT with data validation that only allows the visible/filtered values of a column in a second table named Validation.
The second table has three relevant columns, Visible, Category, and Testing Process. The table is filtered with a slicer on the Category column and the data validation returns values from the Testing Process column. A three-step process is used to prevent filtered values from appearing in the data validation:
Cells in the Visible column shows a blank if the table row is filtered out, and show the value of Testing Process if it's not filtered out. Its formula is:
=IF(AGGREGATE(3, 5,[#[Testing Process]])>0,[#[Testing Process]],"")
An array formula directly to the left of the table, but not a part of the table, takes the range from Visible and sorts it so that all the blank cells are at the bottom of the range, and all the cells with a value are at the top. It fills a range with width 1 and height equal to the number of entries in the table. This range is given the Defined Name Visible_Tests_with_filtered_removed. The formula, entered with Ctrl-Shift-Enter as usual, is:
=INDEX(Validation[Visible],
SMALL(
IF( Validation[Visible]<>"",
ROW(INDIRECT("$A$1:$A$"&COUNTA(Validation[Category]))),
""
),
ROW(INDIRECT("A1:A"&COUNTA(Validation[Category])))
)
)
A Defined Name, Visible_Tests_with_blanks_removed, is created that includes only the values from Visible_Tests_with_filtered_removed, not any blanks or errors. Its formula is: =OFFSET(PPRNT!$A$34,0,0,MATCH("*",Visible_Tests_with_filtered_removed,-1),1)
Potential Solutions
Ideally I'd like to add the array formula to the Validation table, since that would automatically copy the array formula to any new row as it was added. When I try doing this, however, I get the error that "Multi-cell array formulas are not allowed in tables."
Alternatively, perhaps I could put this entire range into another Defined Name like Visible_Tests_with_blanks_removed, whose values are not actually located in cells on the worksheet. I don't know
If all else fails, I could use the macro I linked above, but it seems to me it shouldn't be this hard and I would probably just include instructions for expanding the Array formula in the HowTo tab.
Thanks #OldUgly for a bump in the right direction.
Download the example workbook from OneDrive at https://1drv.ms/x/s!Ak4Lq2gGjO8hleIyd60JuPkctlDhGw, but note the online preview doesn't support Data Validation! You must download the file to see it in action.
This three-step process creates the proper list for data validation, and it's part of the table so it updates automatically. Note that the CSE formula I used in my original question was multi-cell (select a bunch of cells, then enter the formula and hit Ctrl-Shift-Enter), but those aren't allowed in tables so this solution uses a single-cell array formula, which is automatically copied to every cell in the column in the table.
Create a Visible column on the table to determine which rows are currently hidden. This is a normal formula, not a CSE formula.
=IF(AGGREGATE(3, 5,[#[Testing Process]])>0,TRUE,FALSE)
Add a Filtered List column to the table, and enter this single-cell CSE formula (which should get automatically copied to the rest of the cells in the table, just like any other table formula). If you press Enter instead of Ctrl-Shift-Enter, you'll get the #NUM! error for all but the first cell.
=INDEX([Testing Process],
SMALL(
IF([Visible], ROW([Testing Process])-ROW(Validation[[#Headers],[Testing Process]]), ""),
ROW([#[Testing Process]])-ROW(Validation[[#Headers],[Testing Process]])
)
)
Create a Defined Name Testing_Processes_for_Data_Validation (Formulas->Define Name) with the formula =OFFSET(Validation[[#Headers],[Filtered List]], 1, 0, MATCH("*",Validation[Filtered List],-1), 1) so that the Data Validation doesn't have a bunch of #NUM! errors at the end of it.
When activating Data Validation on a cell, set Allow to be "List" and Source to be =Testing_Processes_for_Data_Validation.
And that's it! This creates an automatically-expanding dynamic list based on the filtered column of a table, and removes blanks and errors from that list.
I have two tables that get dynamically created from a database query; the first table is the source of the drop-down list, and the second is the table that I will apply the drop-down list via data validation. First table:
and the second table:
What I need, ideally through just Excel formulas, is an intelligently designed drop-down that shows only the dimension values associated to the dimension in question.
So in cells B3:B10, the drop-downs would show a,b,c. In cells C3:C10, the drop-downs would show 1,2,3. In cells D3:D10, the drop-downs would show x,y,z. Etc, etc.
I need this to be dynamic in the sense that a week from now my DB query may return a fourth dimension that would need to follow the same approach.
Not sure if this is even possible without writing some VBA, but I figure I'd see if anybody has any creative ideas. Cheers!
You have to use Name Manager and =INDIRECT() formula to achieve that.
First download the sample file.
Sample File
See this tip (By me). It will help you to see screenshots step by step. Link is here
Now in-case of your data you have to use some formula to filter data automatically when new data come. So that new data can organize for dynamic combo boxes. I can also do that for you if you are not able to do that. Then share your sample workbook with me.
It is very possible, but not simple. There are a several ways to implement this, depending on your requirements, how dynamic it needs to be, and the expected structure of the data (as I mentioned in a comment).
I will give one possible solution, that is mostly dynamic, and is the simplest to explain. You can use a similar logic to make it all dynamic.
This solution will retrieve the data from table #1 according to the dimension name, assuming it is not sorted, and return the values in the order they are given in the table.
For some of the ranges I create names for simplicity, and some are mandatory. In order to follow the formulas logic you need the named ranges I use.
Create named ranges for table #1: (Either by using the Name Box or using the Name Manager Ctrl+F3):
For the data in the column Dimension: DimName =B3:B11
For the column Dimenstion Value: DimValue =C3:C11
Create dimension values lists in a new sheet:
Put the dimension name in B2 ="Customer". (The available dimension names can be created dynamically as well, but I'm skipping this part for simplisity).
B3 (array formula - Ctrl+Shift+Enter) =IFERROR(INDEX(DimVal,SMALL(IF(DimName=B$2,ROW(DimName)-ROW(INDEX(DimName,1))+1),ROWS(B$3:B3)),1),""). This formula returns the k-th value for the "Customer" dimension.
Copy B3 down to as many rows you think you'll need. Let's say B4:B10, so B3:B10 will have the array formula. The first cells will have the available values and the remaining cells will be empty because of the IFERROR function.
In B1 we will count the available values using the formula =SUMPRODUCT(--(B3:B10<>"").
Do the same for "Product" and "Geography" in columns C and D.
Create dynamic named ranges for the lists: (using the Name Manager Ctrl+F3)
For the lists' data DimLists =B3:D10.
For the lists' headers DimListHeaders =B2:D2.
For the lists' counts DimListCounts =B1:D1.
*These names are mandatory for the data validation to work in another sheet.
Set table #2 data validation list sources:
Select B3:B10 in table #2.
Go to Data > Data Validation, and select Allow: List.
Put the following formula in the source: =OFFSET(INDEX(DimLists,,MATCH(B$2,DimListHeaders,0)),,,INDEX(DimListCount,,MATCH(B$2,DimListHeaders,0))). This formula finds the correct list in DimLists according to the column header in table #2, and also sets the returned range height according to the list count.
Hope this helps.