I'm trying to create a dropdown menu in excel which eliminates values once they have been selected.
Let's assume that the dropdown offers the values 1...10. If I select 1 in the first dropdown, then the other dropdowns needs to offer only 2...10. Likewise, if I picked to, the the other should offer only 1,3,4,5,6,7,8,9,10.
Basically we want managers to rank their employees based on the performance value.
But if they rate everyone a 4, we need a ranking - but we then dont want them ranking everyone as 1.
I tried with IF statements, but we can have rankings of up to 100 people, so it was becoming a nightmare.
Not sure if I am clear?
Any help would be appreciated.
You can use data validation custom formula to avoid duplicates. It would not be a dropdown but it would work exactly as you wish:
In my example, I've selected range B2:B5 and then I applied a data validation custom formula like this:
=COUNTIFS($B$2:$B$5;B2)=1
You can even customize the error message:
With that formula, any entered value will be accepted exactly once. If it's used again, it will raise an error.
Notice I can't type a second time the value 1 because it's been already used.
You can do this by creating a helper table which lists all the valid ranks and whether or not they have been used yet. This can be on the same sheet or another, hidden sheet if you prefer:
The formula in the "Used?" column is a simply counts the number of times that rank appears in the "Rank" column and checks if it is greater than 0 - returning TRUE or FALSE:
=COUNTIFS($B$2:$B$11,$H2)>0
The "Remaining Ranks" column then uses this in a MINIFS formula to remove the used ranks:
= MINIFS(
$H$2:$H$11,
$H$2:$H$11,">"&MAX($K$1:$K1),
$I$2:$I$11,FALSE
)
This is saying to select the lowest number from the "All Ranks" column, where the rank hasn't already been listed in the "Remaining Ranks" column AND the "Used?" column is FALSE.
This will result in zeros at then bottom of the "Remaining Ranks", so we can wrap it in an if statement to replace the zeros with an empty string "":
=IF(
MINIFS($H$2:$H$11,$H$2:$H$11,">"&MAX($K$1:$K1), $I$2:$I$11,FALSE)=0,
"",
MINIFS($H$2:$H$11,$H$2:$H$11,">"&MAX($K$1:$K1),$I$2:$I$11,FALSE)
)
You can now use the "Remaining Ranks" column as your source for the data validation list, and it will update as the ranks are entered.
This will result in some blank options at the bottom of the list.
If these are an issue for you, they can be removed by using an INDEX formula in a named range. Let me know if you would like me to explain how that can be done.
Related
I'm, looking for a way to return an array of text based off of titles or headers if you will. My brain isn't working today and I keep struggling to find the best method. I originally was going to have a bunch of IF statements and ran into problems, and I can't seem to figure out if Aggregate is a viable method.
Essentially if "Title 1" is selected from a drop down I would like to return the names within Title 1, and so on. If "All" is selected I would like all to populate from each title. The speed bumps I have is that some names repeat and I only want to show each name once always in alphabetical order. Can someone please get me started on how to tackle this?
In Excel O365 with the FILTER function, you can do this with a helper column (which you can hide, or position elsewhere).
I created a Table and am using structured references, but you can change to ordinary addressing if you prefer.
TitleList is a named range that includes all or your titles (presumeably you will use this for your dropdown).
For the Helper Column, I have it adjacent to your Names column with the formula:
=IF(OR(A2=TitleList),ROW(),B1)
This creates a unique number for each title.
Then, for your formula, under the dropdown, you can use:
=FILTER(Table3[Names],(Table3[Names]<>G1)* (Table3[Index]=XLOOKUP(G1,Table3[Names],Table3[Index])))
where G1 contains the dropdown
With Column B visible:
Some with O365 do not have the FILTER function. If you do not have the FILTER function, you can use:
=INDEX(Table3[Names],AGGREGATE(15,6,1/(INDEX(Table3[Index],MATCH(G1,Table3[Names],0))=Table3[Index])*ROW(Table3)-ROW(Table3[#Headers]),ROW(INDEX($A:$A,2):INDEX($A:$A,COUNTIF(Table3[Index],INDEX(Table3[Index],MATCH(G1,Table3[Names],0)))))))
EDIT
To return a non-duplicate list of ALL of the names, add ALL to TitleList and use this formula instead.
This formula makes a special case for ALL and filters out the rows that contain a Title
=IF(G1="ALL",UNIQUE(FILTER(Table3[Names],COUNTIF(TitleList,Table3[Names])=0)),FILTER(Table3[Names],(Table3[Names]<>G1)*(Table3[Index]=XLOOKUP(G1,Table3[Names],Table3[Index]))))
.imgur.com/apkHh.png
I have a list of prices for products that are variations (different size, color) of multiple parent product. Some products (for reasons not important to this question) have a price of zero.
I'm trying to write an excel formula that will return the lowest price for each parent product that is not zero
I've got this far:
=IF(SUMIFS(I:I,A:A,A3)=0,0,IF(AND(SUMIFS(I:I,A:A,A3)>0,MINIFS(I:I,A:A,A3)>0),MINIFS(I:I,A:A,A3),SMALL(IF(A:A=A3,I:I),2)))
Where I:I is the price column and A:A is the parent reference column
This works in all cases except where I have multiple variations of a parent product that have a zero value.
I need variables in a SMALL or MINIF function that will:
A. Only include the values for a single parent product in the calculation
B. Ignore any zeros in the calculation of the lowest value
Any help would be appreciated.
You can use a Pivot Table to easily create a dynamic list of minimums. Blank cells are ignored by default, and zero's (or any other number you want) can be excluded a few ways; I think the easiest would be using the Pivot Table's Filter feature.
They say a picture is worth a thousand words so an animated GIF must be worth a million... :)
More Information:
Office.com : Filter data in a PivotTable
Office.com : Display or hide zero values
tips.net : Excluding Zero Values from a PivotTable
You can use a 'traditional' PivotTable to do this. See ashleedawg's great answer.
You can also use a 'OLAP' PivotTable that's based off something called the Data Model to do it, that has a small advantage over the 'traditional' PivotTable in that you don't need to clear the PageFilter after refreshing. (More on this at the bottom of my answer).
Any Excel version from Excel 2013 later has the DataModel built in by default, and you also get access to the DataModel in 2010 if you install Microsoft's free PowerPivot add-in. Using the DataModel, here's what you need to do:
Turn your data into an Excel Table using the Ctrl + T keyboard shortcut:
Make a PivotTable out of it, but be sure to check the Add this data to the Data Model option:
Add Group to the Rows pane of the PivotTable, then right-click on Table1 in the fields pane and select Add Measure...:
Give the new Measure a name (I've called it Min Without Zero) and type =CALCULATE(MIN(Table1[Price]),Table1[Price]>0) in the Formula box then push OK:
Put a tick in the Min Without Zero checkbox in the PivotTable fields list.
Bing! The PivotTable shows the min (excluding zero) of each group by price.
Edit: I'd probably use ashleedawg's answer if I was doing this myself. But there's one caveat: If you add additional data in future and refresh, then you need to clear the filter and reapply the zero exclusion to be absolutely sure that any new numbers in the data are included. By way of a demonstration, if I filter out zero from a PageField, then I get just the result I expect:
...and here's how the filter looks:
But if I add new data and refresh, note that nothing has changed in the PivotTable:
...and if I look at the filter I can see why:
That's because when you deselect something from a filter, you're not actually saying "Give me everything except this thing" but rather "Give me the other things currently visible in this list, but leave any new things unselected."
Easily enough fixed: Just clear the filter and deselect zero again (or write some VBA code to do it automatically on refresh).
If the input data is sorted based on the parent reference level you can simply
use offset to find the required parent reference cells containing the price
Find the k-th smallest value using the SMALL formula (i.e. the smallest value)
Put a if condition to give you the 2nd smallest value if the smallest is 0
Place this in the 1st row
=IF(SMALL(OFFSET($I$1,MATCH(C1,$C:$C,0)-1,0,COUNTIF($C:$C,C1)),1)=0,SMALL(OFFSET($I$1,MATCH(C1,$C:$C,0)-1,0,COUNTIF($C:$C,C1)),2),SMALL(OFFSET($I$1,MATCH(C1,$C:$C,0)-1,0,COUNTIF($C:$C,C1)),1))
If you want a formula approach, you can use an IF statement to return a value if that value is over zero, and otherwise return FALSE, as functions like MIN conveniently ignore FALSE.
As per my other answer I recommend you turn the data into an Excel Table first with the Ctrl + T keyboard shortcut, as shown below. Then in a summary table you can use the following array-entered formula in E2:
=MIN(IF(Table1[Price]>0,IF(Table1[Group]=D2,Table1[Price])))
(Array-entered means you push Ctrl + SHIFT+ ENTER instead of pushing ENTER like you usually do)
And here's the result:
I was building a financial model and ran into this problem. Cell C2 contains the dropdown list and the value E25 changes according to the dropdown list. What I want is for the present value column in K22:K25 to change automatically. FOr example, if I choose normal in the dropdown list, I want the value of E25 to update automatically in K22. Thanks in advance!
You might use a formula like this in K22:K24.
=Index($J$22:$J$24, MATCH($C$2, $I$22:$I$24, 0), 1)
This will give you one of the values in J22:J24, depending upon what was chosen in C2. I presume you would want to multiply that value with something. That might be a value you extract from another range using a similar function.
J22:J24 must contain the same values as the dropdown. Normally, you would do all of this with named ranges and use the same named range to feed the dropdown as you use for determining the choice the user made.
Try the MATCH function independently to get a better feel for it.
= MATCH($C$2, $I$22:$I$24, 0)
It will return a number between 1 and 3, depending on the choice in A3.
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")
Okay, I have exhausted my feeble knowledge of Excel VBA coding and have not been able to figure out this solution.
I have a single column range of values as part of a table. The values in this column are groups of sequential strings such as:
ABC-001
ABC-002
XYZ-001
EFDDGE-001
ABC-003
XYZ-002
ABC-004
What I need to do is assign a value in the next row that is the next value in the whatever the group is.
Example:
If the next item is an "ABC" item, I need the value in the column to be ABC-005
If the next item is a "EFDDGE" item, I need the value in the column to be EFDDGE-002
etc.
The values in the column are in ascending order, by group (ie. XYZ-005 would never be before XYZ-003).
I have been working with the Range.Find method, but I can't seem to get it to work properly.
Here is a screen-shot of a sample portion of the table:
(Edit: apparently I can't post images since my "reputation is not a 10 or higher!)
Try to picture this series of columns:
[Next ID] [Item ID] [Description] [Disposition] [Original] [Final] [Weight]
In answer to some of the questions:
Yes, I am indeed trying to add the Item ID in the next available row in the table.
The group portion of the "Item ID" is determined by a VLookup into the "LocationID" table related to the entries in the "Original" or "Final" columns, depending on the "Disposition" value.
As you can see from the above screen shot, I have actually managed to implement a workable method of determining the "Next ID" and then having my VBA userform code copy that value and paste it into the adjacent "Item ID" column. It works, but it is ugly. Here is the bloated formula (take a deep breath):
=IF(NOT(ISERROR(CONCATENATE(VLOOKUP(IF(NOT(ISBLANK(G13)),G13,F13),LocationID,2,FALSE),"-",TEXT(SUMPRODUCT((ItemID>VLOOKUP(IF(NOT(ISBLANK(G13)),G13,F13),LocationID,2,FALSE))(ItemID<=CONCATENATE(VLOOKUP(IF(NOT(ISBLANK(G13)),G13,F13),LocationID,2,FALSE),"-999")))+1,"000")))),(CONCATENATE(VLOOKUP(IF(NOT(ISBLANK(G13)),G13,F13),LocationID,2,FALSE),"-",TEXT(SUMPRODUCT((ItemID>VLOOKUP(IF(NOT(ISBLANK(G13)),G13,F13),LocationID,2,FALSE))(ItemID<=CONCATENATE(VLOOKUP(IF(NOT(ISBLANK(G13)),G13,F13),LocationID,2,FALSE),"-999")))+1,"000")))," ")
So ... I have forced this to work, but I was thinking (hoping) that a bit of VBA code in the userform would obviate the need for such a messy method.
BTW, thanks to all of you for even looking at this and for asking pertinent questions and offering possible solutions.
-Bill
What I need to do is assign a value in the next row
Pretty sure you meant next column. Assuming that, try
=LEFT(A1,FIND("-",A1))&TEXT(VALUE(MID(A1,FIND("-",A1)+1,3))+1,"000")
It looks pretty messy. Let's break it down a little:
=LEFT(A1,FIND("-",A1)) ; isolates the non-numerical portion
=VALUE(MID(A1,FIND("-",A1)+1,3)) ; isolates the numerical portion, converts text to number
The remaining code concatenates the two pieces, adding one to the number we isolated, which is converted back to text while ensuring the 3-digit numerical format is preserved.
If you really need VBA we can go there. The technique is the same.