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.
Related
What I would like to achieve is that sellers can choose the STORE in the blue cell (either with a drop down list or by hard-typing the STORE name) and, based on the selection on the blue cell, the available POSITIONS for that particular PRODUCT and that particular STORE are show in the green cell as a drop down list.
Let's say I have an Excel workbook, which contains a worksheet with this table with products data, which is automatically imported daily from our Nav server with this layout. It has 4 columns including PRODUCT CODE, DESCRIPTION, STORE IN WHICH IT CAN BE LOCATED and POSITION INSIDE DE STORE (please, check screenshot). It contains 1.5k rows and it changes dynamically, for example, new items are added or positions are exchanged.
As you can see, the same product (PRODUCT 2) can be located in several stores (STORES 1, 2 and 3), and it can be in several locations on each store (POSITIONS 2, 3, 1 and 4).
Now I need sellers to report which of these items they pick and from where, not only the STORE but its POSITION inside the store too. They do it with another worksheet inside the same Excel workbook. It looks more or less like this (please, check screenshot).
I know the drop down list is achieved via Data Validation but I can't figure out the formula for this. I have tried several approaches like:
Array formula to return all POSITIONS in the same ROW, following this (Formula 2.): https://www.ablebits.com/office-addins-blog/2017/02/22/vlookup-multiple-values-excel/. It is quite slow to calculate on the 1.5k items and, once done, I can't figure out how to make Data Validation to look for the 4 or 5 or 10 POSITIONS returned by the array formula, which also need to be filtered by STORE (please, check screenshot for the closest that I have been, array formula returning POSITIONS from column E).
Same formula as above directly on the Data Validation list box, which returns only the first POSITION found.
VBA custom fucntions which are not allowed in the Data Validation box.
I feel comfortable with both Power Query and VBA, and forumla as well, and can adapt most of the code I see but I don't know why I just can't figure out how to achieve this, maybe it is only I am blocked or something but every path I start to follow ends up in a dead end.
Does anyone have an idea on how to approach this? It doesn't really seem that complicated but it is becoming impossible for me.
Thank you very much for your time!!
This is what I have finally done, just in case someone else is facing this situation.
Instead of a plain-text table for the POSITIONS, I created a PowerQuery importing that CSV. Named that worksheet _LOCATIONS.
Added a custom column (Column E) combining the PRODUCT and the STORE so I had something like a Unique Identificator, resulting something like this but in PowerQuery.
Combined column:
Sorted column E and sub-sorted column D, so I make sure the list will always be ordered as I need, and saved the query.
Then, in worksheet REPORT, I entered this formula to create the drop down list in Data Validation in cell D2:
OFFSET(_LOCATIONS!$D$1,MATCH($A2&"-"&$C2,_LOCATIONS!$E:$E,0)-1,0,COUNTIF(_LOCATIONS!$E:$E,$A2&"-"&$C2))
And I am able to choose from the available POSITIONS for the selected PRODUCT in the selected STORE.
Brief explanation:
I set the reference for the OFFSET function in the very first POSITION (D1), and then I move it the amount of rows detected by the MATCH function (which searches for the "PRODUCT 2-STORE 2" string in the newly created combined column) minus 1 (PoweryQuery table has headers) and 0 columns. This leaves me on the first occurrence of my string (but on the POSITIONS column). Then I make the offset as high as the amount of rows detected by the COUNTIF function (which counts all occurrences of my PRODUCT-STORE pair), returning an array of all the positions (column D) matching the PRODUCT-STORE pair.
Ask for formula in Spanish if you need it.
Short question: Is there a way to get a formula that references a column in an Excel table to always refer to only the column with that name? This is a straight-up formula question, not VBA-related.
Formula:
=COUNTIFS(Table35[[dc]:[dc]],$A6)
In this case column A has a data center name in it. Table 35 is the output of another program that produces data for an ETL and also most of the same data for this spreadsheet that is used for both analysis and status reporting.
Problem
Due to the nature of analysis, the shape of the data changes. It seems like about once a week there is another variable (column) that needs to be added to the ETL and analysis. I've simply been copying the program output, going to the upper left hand of the table and pasting. For all of my PivotTable analysis of this data it works exactly the way I want it to.
The problem happens to my dashboard built with various Countifs() formulas like the one above. My initial expectation of behavior is that by referencing the data (first by column name and now as a range of columns that contain only one column of data) that Countifs() would select the data based on column header value (much like using vlookup() + match() together).
Instead what happens is that when a column gets added the names in all of my formulas change. It appears the internal representation essentially says I want column #N. No matter what data happens to be in column N, that is what shows up. So for example, [dc] above turns into [CS Windows Error Message]
Is there any way to indicate that I want the column named "dc" regardless of where in the table dc is located? Even the great and omniscient Google has failed me on this one. Help appreciated.
Try wrapping the table reference into the Indirect function. That will preserve the column name and return the correct value.
=COUNTIFS(INDIRECT("Table1[dc]"),2)
or, with your formula
=COUNTIFS(INDIRECT("Table35[[dc]:[dc]]"),$A6)
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.
This seems a straightforward requirement but I'm struggling to find an answer.
I have a simple table with a column listing product codes and another column listing whether it is active or not.
On a separate sheet, I want to use data validation to only list those products which are active.
I have found a number of examples which would require an initial selection of Yes/No for the status, which would then filter the list but I just want the list pre-filtered to show only the active products.
Is there a formula I can use in Data Validation which allows a preset criteria?
Thanks for any assistance.
After a bit more research I found the answer using OFFSET, MATCH and COUNTIF.
With a data validation type of List, the following formula only displays the rows where cell to the left (range named Active_Prod in this case) says Yes.
=OFFSET(Active_Prod,MATCH("Yes",Active_Prod,0)-1,1,COUNTIF(Active_Prod,"Yes"),1)
Hopefully this is of use to others.
While a number of other posts address similar issues, I was unable to find one that met my specific needs, using multiple sheets, etc.
What I need is the ability to select a value from a validation list in one column, and then have a second validation list be narrowed to just the values that can be selected based on the first validation list, and then a third that follows the same logic, etc.
So for example, I have 5 sheets:
Log - This sheet is used for input and will contain the columns that
have the dropdown validation lists.
Clients - This sheet is a two column list of clients. Column A has
the Client ID, column B has the Client Name.
Matters - This sheet is a three column list of Matters. Column A has
a Client ID, Column B has the Matter ID, column C has the Matter
Name.
Timekeepers - This sheet is a two column list of Timekeepers. Column
A has the Timekeeper ID, Column B has the Timekeeper Name.
Rates - This sheet is a three column list of Rates. Column A has a
Matter ID, Column B has a Timekeeper ID, Column C has a Numeric
Rate.
The log sheet:
Column A (Timekeeper) will be a simple validation list dropdown from which I will select a timekeeper (by name). This validation list is populated by the list on the Timekeeper sheet.
Column B (Client) will be another simple validation list dropdown from which I will select (by name) a client. This validation list is populated by the list on the Clients Sheet.
Column C (Matter) will have a validation list of Matters. This is the first dynamic validation list, as the list should only show the matters that belong the to client that was selected in Column B. We know which matters belong to a client by the Column A (Client ID) in the Matters sheet.
Column D (Rate) will simply display the rate for a given timekeeper/matter combination. We would now have the matter id and client id from the input into columns A and C, so we just need to locate the row in the Rates sheet that has that matter id and timekeeper id.
The solution can use VBScript or not, whatever you prefer. I'm a software developer, so I'm comfortable with VBScript, and I'm relatively familiar with Excel, so nested built in functions would be fine too.
Thanks in advance!
EDIT:
This workbook is going to be dynamically generated from a database, so I need to utilize an approach that can be generated programmatically.
The "Log" sheet will contain many rows where the user will select a Timekeeper from a dropdown, then select the Client from a dropdown (which will limit the Matter dropdown list) then select a matter from the Matter dropdown (which, combined with the selection in the timekeeper field will determine the "Rate").
The dropdowns will show the "name" values (i.e. timekeeper name, client name, matter name) but the limitations to subsequent lists based on these selections has to be based on the "ID" value for the selected "Name".
An example showing how to use subsequent list limitations would be most helpful. All of the examples I have seen show how to select one value and limit a second list, but I need to be able to have the selection from the second list limit a third list, the third list limit a fourth list, and finally, the "rate" is determined by what is selected in two of the lists.
The gist of dynamic validations is using =INDIRECT(SomeNamedRange) as the Source data in the List type of Data Validation.
Now, the hardest part is to dynamically generate this list of partners. For the sake of this example, I'll assume you have three sheets: Sheet1, Config, and Validation. I'm also assuming you are selecting a Partner based on a Region, as that is a simpler example.
Let's start with Validation.
Here's an example of my data:
Notice how I've sorted the data based on the most general criteria (Region, in this case). This will be important later on. Also notice that I've named A1:A26 as Validation.Region. I've also named B1:B26 as Validation.Partner.
Config is where your magic happens.
Moving over to the Config, we're going to need to add a list of unique regions, and an address describing where they're located. We'll name this address Region.Choices.
For this example, I used the COUNTIF function to find the last partner in the list. The exact formula was ="Config!$B$2:"&CELL("address";OFFSET(B$2;COUNTIF(B$2:B$230;"?*")-1;0)). Unfortunately, Excel doesn't have a built-in function for the sheet's name, so I had to hardcode that. I went ahead and hardcoded $B$2 to improve performance (maybe?), but you could do that dynamically too.
Sheet1 is where you'll be making your dynamic selection.
In this sheet, we have the following structure.
Take B4, name it "Region.Selected", and add Data Validation as a List of Source =INDIRECT(Region.Choices).
Creating the logic behind the dynamic drill down
Now go to Config, and replicate the contents of B1 on C1, making sure to alter the hardcoded $B$2). Finally, name Partner.Choices, and type in the following Array Formula in C2:C100:
=IF(Region.Selected="";OFFSET(Validation.Partner;1;0;COUNTA(Validation.Partner);1);OFFSET(Validation.Region;MATCH(Region.Selected;Validation.Region;0)-1;1;COUNTIF(Validation.Region;Region.Selected)))
Note: to add an Array Formula, select C2:C100 before typing the formula, and once you're done typing, hit Ctrl+Shift+Enter instead of Enter.
While it may seem convoluted at first, this is basically returning every Partner if no Region is selected, or returning the partners from a selected Region by calculating where it ends and starts and shifting one column to the right with OFFSET.
Wrapping up the dynamic drill down
Now go back to Sheet1, take C4, name it "Partner.Selected" (for consistency), and add Data Validation as a List of Source =INDIRECT(Partner.Choices), as displayed below:
For this example, I used the COUNTIF function to find the last partner in the list. The exact formula was ="Config!$C$2:"&CELL("address";OFFSET(C$2;COUNTIF(C$2:C$230;"?*")-1;0)). Unfortunately, Excel doesn't have a built-in function for the sheet's name, so I had to hardcode that. I went ahead and hardcoded $C$2 to improve performance, but you could do that dynamically too.
Now go ahead and test your dynamic validation! It should look like this: