Excel: Dependent Dropdown Lists on Dynamic Content - excel

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)

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.

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 Formula with OFFSET Fails When Copied to Different Sheet

I've been struggling with this longer than I care to admit, but I have a fairly simple OFFSET function call which works on one sheet, but if I copy it to a different sheet it gives a #VALUE error.
On a sheet named "Deliverable" I have this formula in a cell:
=OFFSET(Deliverable!$B$72,1,0,,3)
and it works fine.
If I go to any other sheet and use the same exact formula, or use it in the Name Manager, it gives a #VALUE error.
If I leave off the final parameter indicated the number of columns I want, it does work:
=OFFSET(Deliverable!$B$72,1,0)
but of course isn't giving me the range I need.
Any idea what's going on with this?
I'm using Excel 2016 on Windows 7.
-- Updated Info --
In a nutshell, my spreadsheet has two cells which I'm using as dropdown lists, where the 2nd cell's list feeds off the selection in the first. The data they are based on has this format:
OptionA A B C D
OptionB A B
OptionC D E F
So the first dropdown uses a simple Data Validation source pointing to the column with OptionA, OptionB, etc. Once that's chosen, the second dropdown list should contain the appropriate options for the one selected. So if OptionB is selected, then the 2nd dropdown list should show A and B.
When I initially wrote this, the data validation source was just a simple VLOOKUP entry, but the lists often had blanks since the number of options varies for each entry. Wanting to fix it up a bit, I ended up with this formula:
=OFFSET(Deliverable!B72,Deliverable!B87,0,1,COUNTA(OFFSET(Deliverable!B72,Deliverable!B87,0,1,5)))
There won't be any more than 5 options, and there are no empty cells in the middle of the data to filter out.
In one spreadsheet I have I used this as a named range definition, then specified the named range for the cells data validation source and it worked. In this other spreadsheet however, it gave me the error described earlier.
However, it looks like when I enter the statement directly into the data validation source field and not in the name manager, it works as expected.
Am I taking the totally wrong approach?
What is it that you want this formula to do? As written, it is returning a block of three horizontal cells. The #VALUE error is Excel's way of telling you "Hey, you're trying to return three cells, but I can't fit them all in the one cell that you are calling this formula from".
The reason you see a result in some places and not others is because of something called Implicit Intersection. Give it a spin on Google. But basically, it just returns whichever one of those three results corresponds to the column that the formula is entered into. If you copy that exact same formula to say row F you will see that it returns a #VALUE error there, because it doesn't know what cell it should return given the column you're calling it from doesn't match any of the cells it is returning. The fact that you don't know this indicates that the formula you're using doesn't in fact do what you think it does.
--UPDATE --
Okay, following your further clarificaiton it seems that you're talking about Cascading Dropdowns aka Dynamic Dropdowns. Lots of info on Google about how to set these up, but you may be interested in an approach I blogged about sometime back that not only provides this functionality, but also ensures that someone can't later on go and change the 'upstream' dropdown without first clearing the 'downstream' one should they want to make a change.
Note that those links talk about a slightly complicated method compared to others, but the method has it's advantages in that it also handles more levels than two, and your DV lists are easily maintained as they live in an Excel Table.
This sounds like an array equation. Try hitting Ctrl+Shift+Enter in the other sheets to validate it as an array equation.
Whenever you need to reference ranges instead of single cells, Excel needs to know that you are working with arrays.

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 table default value and data validation without VBA

I have a table in Excel for tracking projects. Whenever I create a new row for the table I'd like it to auto-populate one column that the project has "Not Invoiced". I would ALSO like that this column use Data Validation to only allow either "Not Invoiced" or "Invoiced" as content.
I have been able to make both of these things work, but I cannot seem to make them work together without error! The closest I have gotten:
Put a formula in the relevant column. Have tried both the super basic ="Not Invoiced" as well as an =IF formula based on the blankness of another column. This correctly carries down each time I make a new row.
I then add Data Validation on the column which also works fine at first since my default value from my formula is one of the options, HOWEVER when the project does invoice and I select "Invoiced" I then get an error that I'm violating the above formula. From what I've read selecting something from the drop down should just replace the auto-populated formula, but that doesn't seem to happen, it gives me an error that I've violating the column's formula instead.
I've read multiple places that if you correctly order things (create table, add formula for default value, then add data validation) the above method should work, but it will not for me and I continue to get the error every time I change to "Invoiced".
you can enter the stati "Not Invoiced" and "Invoiced" into cells that are close together, e.g. $G$3 and $G$4. Then, create a named range for $G$3:$G$4, let's say "ValList" (menu: Formula / Define Name).
Imagine column A to be the controlling column, and B the status column ("Invoiced" / "Not Invoiced"). Example for cell B5:
The initial status is =IF(A5=""; ""; $G$3)
The Validation (type "List") must be controlled by a formula =IF(A5=""; " "; ValList)
Good luck!
There's a simple way to do this.
Before you start using a new table, add list data validation to the cell in the first and only row:
Invoiced,Not Invoiced
Then, in the first row of your table in that same cell write:
=IF(TRUE,"Not Invoiced";"Not Invoiced")
This will put Not Invoiced as the default value on every new row that is added to the table and also keep data validation in place. You will still have access on every new row's cell to the dropdown list stored in the initial cell's data validation list parameter.
For some reason, data validation is overwritten if you try the same IF-function approach in reference to another cell, as you described it.
One way to solve this would be to use a helper column.
You can use the data validation list for the entry column, say column A.
You can use a formula in the hidden column B with the formula =IF(A1,"Invoiced","Invoiced","Not invoiced")

Resources