I am attempting to create an Excel formula to return an array of values based on logic.
I am aware of Excel functions like SUMIFS that accept parameters for range and condition, but instead of returning a sum of range, I want to return a (cell overflow) array of values based on condition.
This answer helped, but I do not want the return array to be sorted. I need the array indexes to be the same as if they were filtered.
Example cells:
Name Type Shares Price
STA Buy 12 5.7
STA Buy 15 3.8
STA Buy 100 5.4
STA Sell -50 5.8
GA Buy 55 3.55
Current formula:
# works but sorted least to greatest, want to return non sorted
=SMALL(IF((NameRange="STA")*(TypeRange="Buy"),PriceRange),ROW(INDIRECT("1:"&COUNTIFS(NameRange,"STA", TypeRange,"Buy"))))
This returns:
3.80
5.40
5.70
I am attempting to return non-sorted, as in original display order of matches:
5.7
3.8
5.4
If you have access to Microsoft 365 you can use FILTER to produce your output:
=FILTER(D2:D6,(A2:A6=H3)*(B2:B6=H4))
You could also return your values in a comma seperate string by nesting the above formula in TEXTJOIN(", ", TRUE, [FORMULA ABOVE]) which would yield 5.7, 3.8, 5.4
Related
this data set below. It has 3 columns (PTQ, % Growth, $ Growth) that all need ranked individually then summed up and then ranked again for a total power rank of each region. Is there any way I can do this with a single formula? I do this a lot and it would be nice not to have to rank everything individually each time.
To clarify, I do not want to rank first on one column then another, they all need to be ranked equally together.
Data:
Region
PTQ
% Growth
$ Growth
TR ARIZONA
103
17.5
201330
TR IDAHO UTAH
75.5
-6.3
-69976
TR LA HAWAII
99.4
19.2
194840
TR LA NORTH
125
32.7
241231
TR NORTHERN CALIFORNIA
102.3
26.2
308824
TR NORTHWEST
91.1
-0.6
-4801
TR SAN FRANSISCO
76.9
-16.7
-158387
TR SOUTHERN CALIFORNIA
106.9
30.8
495722
TR TUCSON
100.3
7.6
34888
Assuming the same layout as P.b., in I4:
=1+SUMPRODUCT(N(MMULT(CHOOSE({1,2,3},RANK(C$4:C$12,C$4:C$12),RANK(D$4:D$12,D$4:D$12),RANK(E$4:E$12,E$4:E$12)),{1;1;1})<SUM(RANK(C4,C$4:C$12),RANK(D4,D$4:D$12),RANK(E4,E$4:E$12))))
and copied down.
This is quite challenging in older Excel, but possible nonetheless:
=IFERROR(
INDEX(
MMULT(--(RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12)>=TRANSPOSE(RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12))),ROW($C$4:$C$12)^0),ROW($A1))
-SUMPRODUCT(--(MMULT(--(RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12)>=TRANSPOSE(RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12))),ROW($C$4:$C$12)^0)
=INDEX(MMULT(--(RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12)>=TRANSPOSE(RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12))),ROW($C$4:$C$12)^0),
ROW($A1))))+1
,"")
(requires being entered with ctrl+shift+enter)
Explanation:
First an array is made of the sum of the 3 rankings:
RANK($C$4:$C$12,$C$4:$C$12)+RANK($D$4:$D$12,$D$4:$D$12)+RANK($E$4:$E$12,$E$4:$E$12)
This results in your so called Rank Sum - array.
Then - since RANK requires a range, not an array, we need an alternative to create a ranking of the array: MMULT can do that.
MMULT(RankSum>=RankSum,ROW(RankSum)^0) creates an array of the ranked RankSum, however. If 2 are ranked equally - for instance rank 1 - it's rank both as 2, not 1. Therefore I used SUMPRODUCT to calculate the number of items in the calculated MMULT-array that equal the indexed MMULT-array result as an alternative to COUNTIF, which is also limited to take a Range, not Array. So MMULTarray-SUMPRODUCT(--(MMULTarray=IndexedMMULTarray)) is your end result.
Calculation is based on your data being in B4:E12 and formula above is entered (with ctrl+shift+enter) in a cell in row 4 and copied down; I4 in the shared screenshot.
Even though this formula answers your question, I doubt this is what you thought what it would be. Changing the range to a different range by itself could be very teasing. And calculating the rankings manually and sum/rank them is probably easier to maintain. You may make it more dynamical by adding INDEX in the ranges.
I'm trying to use XLOOKUP to find a value based on user inputs.
The table looks like this:
Type Start End 33 36 42 48
---------------------------------------
4002 1 7 1.17 1.34 1.5 1.84
4002 8 12 1.84 1.67 2.1 3.45
User selects type, number (can be between start and end), and 33-48
I can nest an XLOOKUP to specify the 3 criteria
=XLOOKUP(*type* & *number* , *typeRange* & *numberRange* ,XLOOKUP(*33-48* , *33-48Range* , *ResultRange* ))
And I can find if a value is between the columns
=IF(AND(*number*>=*Start*,*number*<=*End*),TRUE,FALSE)
Can I combine the two? The data is redundant for numbers 1-7, and I would like to keep the table small.
You sort-of can combine them. I have added a couple of extra rows to the table to see what would happen if you had different Type values as well as number values. The problem then is that if you used approximate match and put in a number like thirteen which is out of range, you might end up getting the next row of the table which would be incorrect. One way round it would be to use the options in Xlookup to search for next-smaller-item in the Start column and next-larger-item in the End column and see if the results match:
=IF(XLOOKUP(I2&TEXT(J2,"00"),A2:A7&TEXT(B2:B7,"00"),XLOOKUP(K2,D1:G1,D2:G7),,-1)=XLOOKUP(I2&TEXT(J2,"00"),A2:A7&TEXT(C2:C7,"00"),
XLOOKUP(K2,D1:G1,D2:G7),,1),XLOOKUP(I2&TEXT(J2,"00"),A2:A7&TEXT(C2:C7,"00"),XLOOKUP(K2,D1:G1,D2:G7),,1),"Error")
If you have some checks in place which make it impossible for number to be out of range, then you can simplify the formula:
=XLOOKUP(I2&TEXT(J2,"00"),A2:A7&TEXT(B2:B7,"00"),XLOOKUP(K2,D1:G1,D2:G7),,-1)
or
=XLOOKUP(I2&TEXT(J2,"00"),A2:A7&TEXT(C2:C7,"00"),XLOOKUP(K2,D1:G1,D2:G7),,1)
I am trying to create a formula in Excel that returns the highest decimal value for every integer in a list.
For example, my sheet may have the values [10, 10.1,10.4, 11.3] and I need it to return both 10.4 and 11.3 since 10.4 is larger than 10 and 10.1, and 11.3 is the largest decimal value for 11.
I need this so that a pivot table can filter out the values as IDs and only return the highest value, but I can't get anything working to the point that providing my existing 'code' wouldn't help whatsoever.
Thanks for the help
If your list is sorted, you could use the Advanced Filter to generate a list of the highest decimal value for each integer.
Given:
Criteria Formulas:
A2: =A6<>INT(A6)
B2: =OFFSET(A6,1,0)=INT(OFFSET(A6,1,0))
Criteria Dialog
Note that you can choose to have the results copied elsewhere
Results
Solve as follows:
value bracket decimal
10 =int(a2) =a2-b2
10.4 =int(a3) =a3-b3
10.1 =int(a4) =a4-b4
11 =int(a5) =a5-b5
11.3 =int(a6) =a6-b6
or values:
value bracket decimal
10 10 0
10.4 10 0.4
10.1 10 0.1
11 11 0
11.3 11 0.3
Now pivot by:
bracket (columns/rows)
and in the value section add the "original value", aggregate by "max".
Pivot table and then group.
pivot table
change PivotTable Fields values to Max of values
group
result
I have big amount of data (60k rows) in Excel that is similar to this:
Temperature Humidity Date
20.1 68 22-dec-14
20.3 67 22-dec-14
20.4 65 22-dec-14
20.0 64 23-dec-14
20.5 64 23-dec-14
20.9 65 24-dec-14
21.4 64 24-dec-14
23.4 64 25-dec-14
23.8 65 25-dec-14
23.9 64 25-dec-14
18.4 64 25-dec-14
I created new columns outside this table that contains the individual dates and I want to extract the MAX, MIN and possibly the AVERAGE of that date
DATE MIN MAX AVG
22/Dez/14
23/Dez/14
24/Dez/14
25/Dez/14
I tried but I can't seem to find a way for Excel to work for me. Could you help me?
I suggest you try a PivotTable:
Suppose column A contains the dates, and column B the values. I've allowed 6 rows in each; extend as necessary.
Consider a sample date in $D$1. The formulas you need are:
MIN: =MIN(IF(D1=A1:A6,B1:B6,MAX(B1:B6))). (You need to enter this as an array formula).
MAX: =MAX(IF(D1=A1:A6,B1:B6,MIN(B1:B6))). (You need to enter this as an array formula).
Use AVERAGEIF out of the box.
Remember that you need to press Ctrl + Shift + Return to enter an array formula. Then it's a simple case of copying that formula downwards.
They return the minimum or maximum value of the entire sample if a given date is not present in the set, which might not be desirable. You could adjust this behaviour with a containing IF.
You can take care of the pseudo-MIN/MAX with the AGGREGATE¹ function using the 14 (LARGE) and 15 (SMALL) sub-functions together with the 6 (ignore errors) option and the AVERAGEIF function can take care of the rest.
The standard formulas in F2:H2 are,
=AGGREGATE(15, 6, ($A$2:$A$60000)/($C$2:$C$60000=$E2), 1)
=AGGREGATE(14, 6, ($A$2:$A$60000)/($C$2:$C$60000=$E2), 1)
=AVERAGEIF($C$2:$C$60000, $E2, $A$2:$A$60000)
Fill down as necessary. An advantage of this method is that you can get the second, third, etc smallest or largest simply by raising the 1 (k ordinal) number at the right end of the AGGREGATE formula.
¹ The AGGREGATE function was introduced with Excel 2010. It is not available in earlier versions.
I'm looking for a formula which will give me the date of the last version of the order.
To illustrate, the sheet looks as follows:
A B C
1 Sales Order Version Date
2 SO#12345 1 21/02/2013
2 SO#12345 2 28/04/2013
3 SO#12345 3 04/08/2013
4 SO#12345 4 27/09/2013
5 SO#54321 1 02/03/2014
6 SO#54321 2 31/03/2014
7 SO#54321 3 07/10/2014
8 SO#54321 4 13/12/2014
So I would like to get the date of SO#12345, version 4 (29/09/2013).
I've tried several combinations of INDEX, MATCH, IF and MAX functions, but I can't seem to get the right value.
It either gives me the corresponding date of the highest value in the version column or it gives me the correct version number, but I can't make it show the appropriate date.
I did use CTRL+SHIFT+ENTER for these formulas, so they are executed as a matrix function.
Again, assuming the Order Number is in E2, try:
=LOOKUP(1,0/FREQUENCY(0,1/(1+(A2:A8=E2)*B2:B8)),C2:C8)
Regards
If the versions are listed in order for each Sales Order numberyou can use LOOKUP like this:
=LOOKUP(2,1/(A$2:A$8=E2),C$2:C$8)
Where E2 contains a specific order number
....or you can use the order number directly
=LOOKUP(2,1/(A$2:A$8="SO#12345"),C$2:C$8)