Excel sort function to "skip" 1st row - excel

My question is because I wanted to sort the data as provided in the following question:
How to select all the column based minimum date value in a sheet
What I wanted to do is select the data (Range A1:F9) and sort it:
NAME
CARD NUMBER
ACCOUNT NUMBER
SBL Transaction Type
SBL Transaction Amount
SBL Transaction Date
B
4779
1
POS purchase
280
02-08-2021
B
4779
1
POS purchase
1
03-05-2021
S
1475
2
POS purchase
389
05-04-2021
S
1475
2
POS purchase
755
05-11-2021
S
1475
2
POS purchase
1794
05-15-2021
A
0173
3
POS purchase
1
02-01-2021
A
0173
3
POS purchase
1
02-02-2021
A
0173
3
POS purchase
1
02-03-2021
What I did is select the data including header =SORT(A1:F9,6) and which results in sorting the header along with the data (of course):
I then got the idea to have the SORT function to disregard the first row and then sort the rest.
My first attempt was =IF(ROW(A1:F9)=1,A1:F9,SORT(A1:F9,6))
As you can see the header worked fine, but the sorted data includes the header, since it's the last in range after sorting A1:F9.
Excluding the header row from the sort range =IF(ROW(A1:F9)=1,A1:F9,SORT(A2:F9,6)) also doesn't work, since the range is then smaller than the output range resulting in the following error and still skips one data line:
I managed to get it correct by inserting a substitute header of al zeroes to the sort range and than sort stack the sorted range onto the headers with this function (which also gives room for two row headers):
=LET(D,A1:F9,rowD,ROW(D),rowsD,ROWS(D),colsD,COLUMNS(D),H,A1:F1,header,INDEX(D,1,1):INDEX(D,ROWS(H),COLUMNS(H)),subsHeader,SEQUENCE(1,colsD,0,0),subsD,IF(rowD<=ROWS(header),subsHeader,D),sortedSubsD,SORT(subsD,6),IF(SEQUENCE(rowsD)<=ROWS(header),header,sortedSubsD))
But I wondered if there's a more elegant way using formula to sort a data range without affecting the header.
Result is =LET(data;A1:F9;header;A1:F2;sortCol;6;SORTBY(data;IF(ROW(data)>ROWS(header);1;0);1;INDEX(data;;sortCol);1)) thanks to Darren Bartrup-Cook's contribution.

If you have a spare column add a 0 next to the header and leave the other rows blank. You can then sort on that column first, followed by the other column.
You can then SORTBY column A and then column F.
=SORTBY(B1:F6,A1:A6,1,F1:F6,1)

Related

Excel - getting a value based on the max value off another row in a Table

I'm looking for a solution for a problem I'm facing in Excel. This is my table simplified:
Every sale has an unique ID, but more people can have contributed to a sale. the column "name" and "share of sales(%)" show how many people have contributed and what their percentage was.
Sale_ID
Name
Share of sales(%)
1
Person A
100
2
Person B
100
3
Person A
30
3
Person C
70
Now I want to add a column to my table that shows the name of the person that has the highest share of sales percentage per Sales_ID. Like this:
Sale_ID
Name
Share of sales(%)
Highest sales
1
Person A
100
Person A
2
Person B
100
Person B
3
Person A
30
Person C
3
Person C
70
Person C
So when multiple people have contributed the new column shows only the one with the highest value.
I hope someone can help me, thanks in advance!
You can try this on cell D2:
=LET(maxSales, MAXIFS(C2:C5,A2:A5,A2:A5),
INDEX(B2:B5, XMATCH(A2:A5&maxSales,A2:A5&C2:C5)))
or just removing the LET since maxSales is used only one time:
=INDEX(B2:B5, XMATCH(A2:A5&MAXIFS(C2:C5,A2:A5,A2:A5),A2:A5&C2:C5))
On cell E2 I provided another solution via MAP/XLOOKUP:
=LET(maxSales, MAXIFS(C2:C5,A2:A5,A2:A5),
MAP(A2:A5, maxSales, LAMBDA(a,b, XLOOKUP(a&b, A2:A5&C2:C5, B2:B5))))
similarly without LET:
=MAP(A2:A5, MAXIFS(C2:C5,A2:A5,A2:A5),
LAMBDA(a,b, XLOOKUP(a&b, A2:A5&C2:C5, B2:B5)))
and here is the output:
Explanation
The trick here is to identify the max share of sales per each group and this can be done via MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...). The size and shape of the max_range and criteria_rangeN arguments must be the same.
MAXIFS(C2:C5,A2:A5,A2:A5)
it produces the following output:
maxSales
100
100
70
70
MAXIFS will provide an output of the same size as criteria1, so it returns for each row the corresponding maximum sales for each Sale_ID column value.
It is the array version equivalent to the following formula expanding it down:
MAXIFS($C$2:$C$5,$A$2:$A$5,A2)
INDEX/XMATCH Solution
Having the array with the maximum Shares of sales, we just need to identify the row position via XMATCH to return the corresponding B2:B5 cell via INDEX. We use concatenation (&) to consider more than one criteria to find as part of the XMATCH input arguments.
MAP/XLOOKUP Solution
We use MAP to find for each pair of values (a,b) per row, of the first two MAP input arguments where is the maximum value found for that group and returns the corresponding Name column value. In order to make a lookup based on an additional criteria we use concatenation (&) in XLOOKUP first two input arguments.

Excel - Lookup date in matrix and return column heading

I have a matrix between Products and Enablers, where the intersection between the two represents a point in time.
Product list
Enabler 1
Enabler 2
Enabler 3
Product 1
10-Oct
11-Oct
20-Oct
Product 2
20-Nov
25-Nov
01-Dec
Product 3
10-Oct
21-Oct
25-Oct
I need to turn this into a 'timeline' view so visually there are two ways to see the data, where the dates are across the top and based on the timing in the first table, it returns the corresponding 'Enabler' at the correct date...something like
Product list
10-Oct
11-Oct
12-Oct
Product 1
Enabler 1
Enabler 2
Product 2
Product 3
Enabler 1
Does anyone have any ideas how I'd do this? I think it requires an INDEX MATCH array formula as it needs to look across the matrix to find the date in that row, then return what is in the header column...but this isn't my area of expertise and I just can't seem to figure out how to make it work.
One approach might be to return this as an array. You could do:
=IF( ( Table1[[Enabler 1]:[Enabler 3]] = B7:D7 ) * ( Table1[Product list] = A8:A10),
Table1[[#Headers],[Enabler 1]:[Enabler 3]],
"" )
where Table1 is an Excel Table that holds your Product List and Enablers as columns (as shown in your first table); A8:A10 is the list of products in your second table; and B7:D7 is the list of dates in your second table shown as column headers. The formula would be placed in the upper left cell of your second table - in my example, B8 as shown here:
The result will spill into the second table.
If you wanted your second table to be an Excel Table, the approach
would be different as arrays cannot spill into Excel Tables.

Aggregating records with two main IDs in [VBA macro]

I want to make a macro in Excel that summarizes data from rows that match a composite ID generated from 2 ID columns. In my excel sheet, each row has 2 main ID columns: ID_1 is the main key, and ID_2 is a secondary key from which I only care about the first 2 letters (Which I have gotten using LEFT). I want to group rows with the same ID_1 and first 2 letters of ID_2 and report the SUM of the value, count, and sum columns.
In the example picture below, I want to turn the data in columns A:J into the data in columns M:V
So, with this example -> We have 6 records 1015 (ID_1) with 3 different ID_2 (AB, AZ, AE). I want to sum them up to a one cell each (1015 AB ; 1015 AZ ;1015 AE) with values which each record had (there is 3 records: 1015 AB with VALUE of 2,3,4 so in result I want to get just one row 1015 AB 9(sum of value) 4(sum of count) 17 (sum of(value * count)). It's important to see that this 17 dosn't come from 9 * 4. It's =sum(I4:I6) (but it may be spread out like in 1200 FF example below! I am still trying to sort them both at one time, but I cant get past it..)
Add a helper column in D to combine the ID_1 and the first 2 characters of ID_2. =A4 & LEFT(C4,2). Copy that down then go to L4 and type in:
=+INDEX($D$4:$D$25,MATCH(0,COUNTIF(L$3:L3,$D$4:$D$25),0)
and hold down Ctrl + Shift + Enter to make it an array function. Copy down to get a list of unique combinations, and then split these values into the separate columns.
Finally to pull in the numbers, put this in Q4:
=SUMIFS(E$4:E$25,$A$4:$A$25,M4,$C$4:$C$25,O4 & "*")
and then copy down and across.

Excel multi tiered lists in data validatation using alphanumeric fields

I am using multi tiered lists and data validation and have an issue when the fields are alpha numeric
eg
Col 1 Col 2
100 Dairy 101 Milk
102 Cheese
200 Bakery 201 Bread
202 Cake
If you choose 100 Dairy in the drop down list Col1 Col2 will not give the 2 fields to choose from however if you remove one of the sets of numbers then data validation will provide the 2 options in col 2
In Column 2 Data validation I am using =Indirect(A1)
How can I have both Number and letters in both of my drop down lists
Any assistance appreciated
A Name (named range) cannot start with a digit or contain spaces. So, in your validation formula, you have to change your entry in column A into the actual name that is being used for your dependent dropdown.
If you used the Excel Create Name wizard, then something like:
=INDIRECT(SUBSTITUTE(" " & $A$1," ","_"))
That will only work if ALL of your dependent lists start with a digit. If not, you will need a different algorithm.
eg:
=INDIRECT(SUBSTITUTE(IF(ISNUMBER(-LEFT($A$1))," ","")&$A$1," ","_"))
If you made up your own names, again, you will need a different algorithm.

Find the top n values in a range while keeping the sum of values in another range under x value

I'd like to accomplish the following task. There are three columns of data. Column A represents price, where the sum needs to be kept under $100,000. Column B represents a value. Column C represents a name tied to columns A & B.
Out of >100 rows of data, I need to find the highest 8 values in column B while keeping the sum of the prices in column A under $100,000. And then return the 8 names from column C.
Can this be accomplished?
EDIT:
I attempted the Solver solution w/ no luck. 200 rows looks to be the max w/ Solver, and that is what I'm using now. Here are the steps I've taken:
Create a column called rank RANK(B2,$B$2:$B$200) (used column D -- what is the purpose of this?)
Create a column called flag just put in zeroes (used column E)
Create 3 total cells total_price (=SUM(A2:A200)), total_value (=SUM(B2:B200)) and total_flag (=(E2:E200))
Use solver to minimize total_value (shouldn't this be maximize??)
Add constraints -Total_price<=100000 -Total_flag=8 -Flag cells are binary
Using Simplex LP, it simply changes the flags for the first 8 values. However, the total price for the first 8 values is >$100,000 ($140k). I've tried changing some options in the Solver Parameters as well as using different solving methods to no avail. I'd like to post an image of the parameter settings, but don't have enough "reputation".
EDIT #2:
The first 5 rows looks like this, price goes down to ~$6k at the bottom of the table.
Price Value Name Rank Flag
$22,538 42.81905675 Blow, Joe 1 0
$22,427 37.36240932 Doe, Jane 2 0
$17,158 34.12127693 Hall, Cliff 3 0
$16,625 33.97654031 Povich, John 4 0
$15,631 33.58212402 Cow, Holy 5 0
I'll give you the solver solution as a starting point. It involves the creation of some extra columns and total cells. Note solver is limited in the amount of cells it can handle but will work with 100 anyway.
Create a column called rank RANK(B2,$B$2:$B$100)
Create a column called flag just put in zeroes
Create 3 total cells total_price, total_value and total_flag
Use solver to minimize total_value
Add constraints
-Total_price<=100000
-Total_flag=8
-Flag cells are binary
This will flag the rows you want and you can grab the names however you want.

Resources