Max IF While Filtering dates? - excel

How can I find the max date that is less than today in a range that is mixed with both ACTUAL and PROJECTED Dates:
as you see here I have a row of dates. Some dates are actual, others are projected. I want to open the spreadsheet and say "What is the latest PROJECTED date that is less than today?"

If you want to do it in a single formula, you will need to use an Array formula. Array formulas calculate something multiple times, once for each cell in a range, and provide you with an array of responses. To solve part 1 of what you're asking, the array formula would look like this (Assuming your columns end at H, and are on row 2 only):
=MAX(if(A1:H1="PROJECTED",A2:H2,""))
When this is typed into the formula bar, confirm with CTRL + SHIFT + ENTER, instead of just ENTER. It will look like this afterwards (do not type the {} yourself):
{=MAX(if(A1:H1="PROJECTED",A2:H2,""))}
This looks at each cell from A1:H1. Where it says "PROJECTED", it then gives the value in A2:H2 for that column [otherwise it gives ""]. To find which date is the highest, we wrap it in the MAX function.
But we're not done, because you have other criteria. Normally you could use the AND function for this, but AND functions take array results and collapse them into a single value. So we need to use the natural TRUE / FALSE function of the IF statement instead, like so:
=MAX(if(A1:H1="PROJECTED",if(A2:H2<today(),A2:H2,""),""))
This checks where in row 1 = "PROJECTED", while at the same time that column in row 2 is less than the value of today's date. It then provides you with that date. It takes the highest date shown. Remember to confirm with CTRL + SHIFT + ENTER, instead of just ENTER.

Related

Trying to write an If statement that will show date of last item selected and change as updated

I have a series of data. That goes down the left side column of dates...
8/2, 8/3, and such. Then 2 columns over I have a column left for if the date is checks so 8/2:X, 8/3:X, 8/4: ,8/5: and such. I'm wanting to reference the date in the last field that has a X in it
A B C D
8/1 X
8/2 X
8/3 x
8/4
8/5
Trying to reference the date for the last A cell if there is an X in the D cell. So it would be for 8/3 would be the date. I'm not sure how to run with this.
I've looked through but now sure how to state an if statement
To return the date in column A that is in the same row as the last "X" (or "x") in column D:
=LOOKUP(2,1/(D:D="X"),A:A)
If you only want you cells to calculate if there's an X in column E you could write it like this:
=if(E3="x","", [put your calculation here] )
If you only care if there's anything there, not necessarily an "x" or if you're worried about case sensitivity:
=if(isblank(E3),"", [put your calculation here] )
Then just drag this formula down.
Based on what you had told me use the following formula in cell H1:
=maxifs($A$3:$A$24,$E$3:$E$24,"x")
If I understood correctly, you want to return the highest date with a X in it right? You can simulate a MAX IF with array formulas:
{=MAX(IF(E:E="X",A:A,FALSE))}
(You have to enter the formula with CTRL + SHIFT + ENTER to get those brackets and to it work properly)
The IF part inside that formula returns only a list of values (inside the TRUE part) that the condition returns true
Edit: If you're using Excel 2013 and above, you should check #Mark answer, as it is a cleaner way to do it
Just going to throw my hat in the ring here for a formula that will display the value of date that corresponds to the largest row number with an X in it in column D.
AGGREGATE will find the row number as follows:
=AGGREGATE(14,6,ROW(D:D)/(D:D="x"),1)
That can be nested inside an INDEX function to return the cell address of corresponding date which in turns display the value of the cell as follows:
=INDEX(A:A,AGGREGATE(14,6,ROW(D:D)/(D:D="x"),1))
While the above does work, AGGREGATE is performing array operations. Therefore full column references like D:D should be avoided and reduced to a smaller range that would closer match your data in order to avoid excess calculations on blank cells.
If you can ONLY enter the X consecutively without skipping a date, for instance you would not mark 8/6 X if 8/5 has no X marked, then you can find the last date using the following formula:
=INDEX(Column_Date,COUNTIF(Column_X,"X"))
The look up is case insensitive which means you can also enter lowercase x instead of uppercase X in column D or mix them up, the formula will return the same result anyway.
The solution is using COUNTIF function to locate the position of the last X in Column E of your worksheet, and then use INDEX function to return the corresponding date in Column A.
COUNTIF is a combination of COUNT and IF function. I guess this might be the "IF" function you are after.
Please note if the X is not marked consecutively day by day, you may need to use someone else' answer.
Cheers :)

i want to find count of text for a date range as criteria 1 and criteria 2 in the array

I want to count number of values (N/D) in the array (below:table: list) for criteria 1 is date range( from date and through Date) and criteria 2 is Shift A, b acros ( as shown in below table-output). I want to fill column D/N with how many times D/N occur for a date range and shift A,B,C,D?
output
From Date Through Date Shift D/N
25-May-19 26-May-19 A ?
25-May-19 26-May-19 B ?
Table- list
Dates A B C D
25-May-19 N D - -
26-May-19 N D - -
27-May-19 - D N -
INDEX(A:E,MATCH(H7:I7,A:E,0),MATCH(J7,A:E,0))
Value -?
Part of the problem you may be having is dates. Make sure your dates are excel dates and not string/text that looks like a date. Simply changing the formatting of a cell does not make it a date, it simply tells excel how to try and display the information in a cell.
Dates in excel are stored as integers and they represent the days since 1900/1/1 with that date being day 1. One of the easiest ways to test if a cell contains a date or a string is:
=ISTEXT(A1)
or
=ISNUMBER(A1)
Where A1 is the cell with the date to be tested.
If it returns TRUE for the first formula it is a string/text. FALSE means it is a number. The opposite TRUE and FALSE results apply for the second formula.
In your formula's when you have something between quotes "", it will be interpreted as a string. SO something like "<=19/05/26" mean its looking for a string less than that, not a date less than that. For doing a date comparison, either concatenate the text comparison with with a cell containing a date to compare to "<="&B2 where B2 has the date or if you want to hard code it use something like "<="&Date(19,05,26)
In order to make the following solution work, your dates all need to be stored as a number. AKA Excel serial date format.
Based on the data being layed out as per the image below, you can use COUNTIFS, INDEX, and MATCH to get the date your are looking for. I recommend find your count of D and N separately and adding them together after for a total. However if you want it in a single cell formula solution it can be achieved as well as demonstrated by the results in column N. however the formula starts to get long and can be difficult potentially read/maintain at a later date.
The core of the solution will be the COUNTIFS functions. The format of the COUNTIFS function is as follows:
COUNTIFS(Range to count 1, Criteria 1, Range to count 2, Criteria 2,...,Range to count n, Criteria n)
Let start building your formula one criteria at a time. The first Criteria will be all dates that are greater than or equal to the from date. If you only want the dates after the from date, drop the equal sign or the criteria.
=COUNTIFS($A$2:$A$4,">="&$G2,
Note the $ to lock the cell references. This is done so that when the formula gets copied, the column or row references beside the $ does not change.
Then second criteria is similar to the first except you want to grab all the dates less than or equal to the through date. Again include/drop the equal sign to suit your needs.
=COUNTIFS($A$2:$A$4,">="&$G2,$A$2:$A$4,"<="&$H2,
The next criteria will be to get all the cells that match D or N the column header. Lets just focus on D for now. The tricky part is to define which column to look in. For now lets call the column to look in XXX which will make the formula become:
=COUNTIFS($A$2:$A$4,">="&$G2,$A$2:$A$4,"<="&$H2,XXX,J$1)
OR
=COUNTIFS($A$2:$A$4,">="&$G2,$A$2:$A$4,"<="&$H2,XXX,"="&J$1)
NOTE: both formulas are the same. When no comparison operator is provided
it is taken as "=" by default.
Now in order to define XXX, INDEX and MATCH will be your friends. An important side note about INDEX is that it does not directly return the value of a cell but instead returns a cell address which in turn pulls a cell value. The basic format of INDEX is:
INDEX(Range to look in, Range's ROW to look in, Range's COLUMN to look in)
That is for a 2 dimensional range. If your range is 1 dimensional, either just a column or just a row, then only the second argument "Range's Row..." need to be provided and it represents how far down the list to go.
What gets interesting about a 2D INDEX is that when 0 is provided for ROW to look in or the Column to look in, instead of throwing an error, it instead returns all rows or columns. THIS IS IMPORTANT because you want all rows of just 1 specific column. That mean your INDEX formula is going to start to look like:
INDEX($B$2:$E$4,0,SPECIFIC COLUMN NUMBER)
So now you need to find a specific column number. That is where MATCH will be your friend. MATCH takes the following format:
MATCH(Value to find, 1D range to look in, what type of search)
You already know you are going to try and match your shift column so that will be your look up value, and the range to look in will be your column headers. The type of search you will want in this case is an exact match which is represented by 0. That means your MATCH formula will look like:
MATCH($I2,$B$1:$E$1,0)
Now to combine the various pieces, throw the MATCH formula into your INDEX and replace the "SPECIFIC COLUMN...". Your INDEX will now look like:
INDEX($B$2:$E$4,0,MATCH($I2,$B$1:$E$1,0))
And the formula above can now replace the XXX in your COUNTIFS formula and you will get:
=COUNTIFS($A$2:$A$4,">="&$G2,$A$2:$A$4,"<="&$H2,INDEX($B$2:$E$4,0,MATCH($I2,$B$1:$E$1,0)),J$1)
Place the above formula in J2 and copy the cell down and to the right.
In L2 use one of the two formulas to get the total of D and N in the date range:
=SUM(J2:K2)
OR
=J2+K2
Now to get your formula all in one cell, look at the second formula above. You can simply go to the contents of cell J2 and copy the entire formula. Then edit cell L2 and replace the cell reference for for J2 with the copied formula. Repeat the process by copy formula in K2 and replacing the reference to K2 in L2. You will wind up with a formula that looks like:
=COUNTIFS($A$2:$A$4,">="&$G2,$A$2:$A$4,"<="&$H2,INDEX($B$2:$E$4,0,MATCH($I2,$B$1:$E$1,0)),J$1)+COUNTIFS($A$2:$A$4,">="&$G2,$A$2:$A$4,"<="&$H2,INDEX($B$2:$E$4,0,MATCH($I2,$B$1:$E$1,0)),K$1)
Much longer and harder to read which is why I recommend breaking the formula down into its parts for D and N separately.
Now as an alternate method you could use SUMPRODUCT and get into array operations. Your SUMPRODUCT formula to place in I2 and copy down and right could be:
=SUMPRODUCT(($A$2:$A$4>=$G2)*($A$2:$A$4<=$H2)*(INDEX($B$2:$E$4,0,MATCH($I2,$B$1:$E$1,0))=J$1))

Averaging Offset Cells of Future Data in Excel

My current spreadsheet has integers that I'd like to average in every 9th cell in the K Column, starting from K10. So right now my current formula reads,
=AVERAGE(K9,K18,K27)
I'd like the EQ to consider [K36, K45, K54] even though those cells aren't filled in yet.
I believe I can use something like;
*pseudocode*
Find the average of K1+(K1+9)
*Attempt*
\\
=AVERAGE(OFFSET(K10,9,,,)
\\
I think I'm missing the complete knowledge of OFFSET, or I'm thinking maybe an AverageIF() may be in order? I've spent probably an hour on it so far
This array formula will return every 9nth cell starting with K10 and expand to include new data as it is put in:
=AVERAGE(INDEX(K:K,N(IF({1},(ROW(A1:INDEX(A:A,(MATCH(1E+99,K:K)-9)/9))-1)*9+10))))
The -9 is the number of rows to get the starting row to row 1 10-9=1
The /9 and the *9 are the spacing
The +10 is the starting row.
Confirm with Ctrl-Shift-Enter instead of Enter when exiting edit mode
If you can add a column as a flag, you could us the MOD function to check the row number like this:
=MOD(ROW(K10)+1,9) - this returns 0 for every 9th cell starting at K10
Then you could use the AVERAGEIF function to average if the MOD function returns 0.
If you can't add a flag, you may need to look into using an array formula like this:
=AVERAGE(IF(MOD(ROW(K10:K30)-1,9)=0,K10:K30))
You can activate the array formula by hitting Ctrl+Shift+Enter. If done correctly, braces ({}) will be put around the formula in the formula bar.
EDIT:
**both of the following methods counts empty cells as 0
This array formula will work for column K if there is a value in every row of column K:
=AVERAGE(IF(MOD(ROW(INDIRECT("K10:K" & COUNTA(K:K)+10))-1,9)=0,INDIRECT("K10:K" & COUNTA(K:K)+10)))
Or if you don't have continuous data in column K, this method gets the last filled cell.
=AVERAGE(IF(MOD(ROW(INDIRECT("K10:K" & MAX((K:K<>"")*(ROW(K:K)))))-1,9)=0,INDIRECT("K10:K" & MAX((K:K<>"")*(ROW(K:K))))))

MAX + Left Function Excel

I am trying to get the max value of a column based on the Left function
What I am doing is the following :
These are the results I get when i write this into column C :
=MAX(LEFT(A:A, 2))
But what I truly want is to get in column C the max value of all column A not for each cell.
So the result should be in this case 90 for all rows.
What should be the formula here?
Just another option that gets entered normally:
=AGGREGATE(14,6,--LEFT($A$1:INDEX(A:A,MATCH("ZZZ",A:A)),2),1)
Array formulas will calculate the enitre referenced array. So care should be taken to limit the number of iterations to only the data set.
The $A$1:INDEX(A:A,MATCH("ZZZ",A:A)) part of the formula does that. It finds the last cell in column A with data in it and sets that as the upper bound. So in this instance the reference range is A1:A3. But, it will grow dynamically as data in Column A is added, so no need to change the formula each time data is added.
Update 2
Here is another solution which I think is better than my original (below)
=INT(SUMPRODUCT(MAX(SUBSTITUTE(A:A,"-",".")*1)))
it can be entered as normal (just Enter)
Orignal Answer
You need numbers and arrays
=MAX(IFERROR(LEFT(A:A,2)*1,0))
Let's break this down. Multiplying by turns your strings into numbers - since Left only returns a string
LEFT(A:A,2)*1
Unfortunately this method returns #Value if you multiply an empty string by 1. You will definitely have some empty strings in the range A:A so we wrap the whole thing with an IFERROR function.
IFERROR(LEFT(A:A,2)*1,0)
Now we still need excel to treat this as an array (i.e. a whole column of numbers, rather than just one number). So we put the MAX formula in and enter it with Ctrl+Shift+Enter rather than just Enter. The result is that the formula looks like this in the formula bar
{=MAX(IFERROR(LEFT(A:A,2)*1,0))}
which would return 90 in your example, as required
Update 1
If you are using Excel 2013 or later, you can also use the NUMBERVALUE function
=MAX(NUMBERVALUE(LEFT(A:A,2)))
again, enter it with Ctrl+Shift+Enter

How to find minimum and maximum values in Column B based on a specific string in column A?

I have a list of items in Column A and have corresponding year and month values in Column B and C respectively. I am looking to find the minimum and maximum year in Column B (based on specific value in Column A), then find the corresponding month in Column C (only for max and min value) and then generate and fill in a Start and End date in Column E and F respectively.
E.g. IF #Item = Laptop THEN FIND MIN,MAX of #YEAR and THEN FIND adjacent value in #Month. Finally formulate and display a date accordingly.
Could i achieve this using a formula or is it out of scope and is better achieved using a macro?
For the Start date, in E2:
=IF(A2<>A1,DATE(AGGREGATE(15,6,$B$1:$B$1000/($A$1:$A$1000=A2),1),AGGREGATE(15,6,$C$1:$C$1000/(($A$1:$A$1000=A2)*($B$1:$B$1000 = AGGREGATE(15,6,$B$1:$B$1000/($A$1:$A$1000=A2),1))),1),1),"")
And for the end date in F2:
=IF(A2<>A1,EOMONTH(DATE(AGGREGATE(14,6,$B$1:$B$1000/($A$1:$A$1000=A2),1),AGGREGATE(14,6,$C$1:$C$1000/(($A$1:$A$1000=A2)*($B$1:$B$1000 = AGGREGATE(14,6,$B$1:$B$1000/($A$1:$A$1000=A2),1))),1),1),0),"")
Then copy down the desired rows.
The aggregate function was introduced in 2010 so it will not work in excel 2007 or earlier.
I over thought they can be simplified to:
=IF(A2<>A1,AGGREGATE(15,6,DATE($B$1:$B$1000,$C$1:$C$1000,1)/($A$1:$A$1000=A2),1),"")
And:
=IF(A2<>A1,AGGREGATE(14,6,EOMONTH(DATE($B$1:$B$1000,$C$1:$C$1000,1),0)/($A$1:$A$1000=A2),1),"")
Thanks to #Jerry for showing a more succinct method.
Here is something that I think should work for any version of Excel, and thanks to the comment from #ScottCarver you can now copy it down and it will put the dates on the first row of each Item:
Enter this in E2 as an array formula and then copy down:
=IF(A2<>A1,MIN(IF(A:A=A2,DATE(B:B,C:C,1))),"")
Enter this in F2 as an array formula and then copy down:
=IF(A2<>A1,MAX(IF(A:A=A2,DATE(B:B,C:C+1,0))),"")
Because these are array formulas you need to press control-shift-enter instead of just enter. After they are entered they will be surrounded by { } to indicate that they are array formulas.
Original Answer:
Here is something that I think should work for any version of Excel, but you can't copy it down - you have to enter one separately for every Item. If you really want them spread out so that the dates are on the row of the first occurance of the Item (like in your screenshot) then this won't really work for you.
For the start date of the Laptop Item:
=MIN(IF(A:A="Laptop",DATE(B:B,C:C,1)))
For the end date of the Laptop Item:
=MAX(IF(A:A="Laptop",DATE(B:B,C:C+1,0)))
These are array formulas so you need to press control-shift-enter instead of just enter. After they are entered they will be surrounded by { } to indicate that they are array formulas.

Resources