Consider this data:
Project Name Due Completed
P1 T1 04/10/14 04/10/14
P1 T2 05/10/14 06/10/14
P2 T22 07/10/14 07/10/14
P1 T3 17/10/14
Is there a formula that can look at this list and pick out all the P1's and evaluate the dates to work out whether they were completed on time. I.E. the data above should produce no as the second task was completed late.
Assuming your data is in columns A - D, add your Project name to cell E1, and enter this as an array formula (Ctrl + Shift + Enter):
=IF(MAX(IF($A:$A=E$1,$D:$D-$C:$C))>0,"no","yes")
Output:
How it works
Excel stores dates as numbers, so you can subtract one date from another.
Here, I'm subtracting Due from Completed:
If the result is a positive number (row 3), the project was completed late. The negative number occurs because a blank cell is treated as 0 when doing calculations. Oct 17, 2014 is stored by Excel as the number 41929, so 0 - 41929 = -41929.
This part of the array formula compares each project in column A to the project name in E1, and it returns an array of the results:
IF($A:$A=E$1,$D:$D-$C:$C)
In our example, the array looks like this: {0,1,-41929}
The MAX function takes the maximum value from the array – in this case the number 1.
The outer IF function tests if MAX's result is greater than 0, which would indicate that the project was completed late. If so, it returns "no." Otherwise, it returns "yes."
Related
I would like to create a Gantt chart like with excel based on task start and duration cell values. I have an excel as below:
Item
Start
Duration(months)
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
1
Q1
6
2
Q2
3
3
Q2
1
Start column indicates the quarter-calender the task starts.
Duration indicates the number of months the task can take to complete.
Based on these two value I would like to have a formula in columns Jan-Aug to fill with x appropriately
Desired output:
Item
Start
Duration(months)
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
1
Q1
6
x
x
x
x
x
x
2
Q2
3
x
x
x
3
Q2
1
x
I dabbled with XLOOKUP and OFFSET with no luck. Tried creating defined names as in Microsoft template with no luck
You can try the following formula in cell D2:
=LET(months, MONTH(D1:O1), dur, C2:C4, Qs, B2:B4,
QsUx, SORT(UNiQUE(Qs)), start, XLOOKUP(Qs, QsUx, SEQUENCE(ROWS(QsUx),,1,3)),
end, start + dur - 1,
GEN_X, LAMBDA(idx, MAP(start, end, LAMBDA(ss, ee,
LET(month, INDEX(months,,idx), IF(MEDIAN(ss, ee, month) = month, "x",""))))),
DROP(REDUCE("", months, LAMBDA(acc, m, HSTACK(acc, GEN_X(m)))),,1)
)
and here is the output:
Note: The formula generates the entire grid, there is no need to expand the formula.
Explanation
It uses the following two ideas:
To populate the grid using the MEDIAN function. Check the answer provided by #JosWoolley: Sum unique day count within a date ranges.
DROP/REDUCE/HSTACK pattern to iterate over all the month's columns to generate the x's for a given column. Check the answer provided by #DavidLeal to the question: how to transform a table in Excel from vertical to horizontal but with different lengths.
The rest is just to prepare/transform the input data in the format we want. The LET function is used for easy reading and composition.
The row with the months: D1:O1 was generated in date format as follows:
=EDATE(DATE(2022,1,1), SEQUENCE(1,12,0))
Now the months variable will have the corresponding months via the MONTH function, it returns the following sequence of values: 1,2,..,12.
QsUx has the unique names of quarters sorted. Then we can calculate the start date as follow:
XLOOKUP(Qs, QsUx, SEQUENCE(ROWS(QsUx),,1,3))
SEQUENCE generates the following sequence: 1,4,7,..etc. (as many values as rows have QsUx). Representing the starting month of each quarter.
Note: This is just one approach. The start can be obtained, by extracting the number of the Quarter and building a sequence: 1, prev. value + 3, for example. Alternatively, since we have only four quarters just a simple constant array with all the Qs and their corresponding start dates. The approach used in the main formula is more generic because the Gantt can be expanded to more than one year and it still works.
Having the start date, then we can calculate the corresponding end date as follows: start + dur - 1.
The user LAMBDA function GEN_X generates the x's values for a given column of months indicated by the idx as input argument (representing the corresponding month).
Finally, we use the DROP/REDUCE/HSTACK pattern to append each column to complete the grid.
Note: The solution assumes no excel version constraints as per the tag listed in the question, so all existing excel functions are available. If you have some limitations for example you don't have the DROP function, let me know to try to find some alternative.
Consider the following sheet/table:
A B
1 90 71
2 40 25
3 60 16
4 110 13
5 87 82
I want to have a general formula in cell C1 that sums the greatest value in column A (which is 110), plus the sum of the other values in column B (which are 71, 25, 16 and 82). I would appreciate if the formula wasn't an array formula (as in requiring Ctrl + Shift + Enter). I don’t have Office 365, I have Excel 2019.
My attempt
Getting the greatest value in column A is easy, we use MAX(A1:A5).
So the formula I want in cell C1 should be something like:
=MAX(A1:A5) + SUM(array_of_values_to_be_summed)
Obtaining the values of the other rows in column B (what I called array_of_values_to_be_summed in the previous formula) is the hard part. I've read about using INDEX, MATCH, their combination, and obtaining arrays by using parenthesis and equal signs, and I've tried that, without success so far.
For example, I noticed that NOT((A1:A5 = MAX(A1:A5))) yields an array/list containing ones (or TRUEs) for the relative position of the rows to be summed, and containing a zero (or FALSE) for the relative position of the row to be omitted. Maybe this is useful, I couldn't find how.
Any ideas? Thanks.
Edit 1 (solution)
I managed to obtain what I wanted. I simply multiplied the array obtained with the NOT formula, by the range B1:B5. The final formula is:
=MAX(A1:A5) + SUM(NOT((A1:A5 = MAX(A1:A5))) * B1:B5)
Edit 2 (duplicate values)
I forgot to explain what the formula should do if there are duplicates in column A. In that case, the first term of my final formula (the term that has the MAX function) would be the one whose corresponding value in column B is smallest, and the value in column B of the other duplicates would be used in the second term (the one containing the SUM function).
For example, consider the following sheet/table:
A B
1 90 71
2 110 25
3 60 16
4 110 13
5 110 82
Based on the above table, the formula should yield 110 + (71 + 25 + 16 + 82) = 304.
Just to give context, the reason I want such a formula is because I’m writing a spreadsheet that automatically calculates the electric current rating of the short-circuit protective device of the feeder of a group of electric motors in a house or building or mall, as required by the article 430.62(A) of the US National Electrical Code. Column A is the current rating of the short-circuit protective device of the branch-circuit of each motors, and column B is the full-load current of each motor.
You can use this formula
=MAX(A1:A5)
+SUM(B1:B5)
-AGGREGATE(15,6,(B1:B5)/(A1:A5=MAX(A1:A5)),1)
Based on #Anupam Chand's hint for max-value-duplicates there could also be min-value-duplicates in column B for corresponding max-value-duplicates in column A. :) This formula would account for that
=SUM(B1:B5)
+(MAX(A1:A5)-AGGREGATE(15,6,(B1:B5)/(A1:A5=MAX(A1:A5)),1))
*SUMPRODUCT((A1:A5=MAX(A1:A5))*(B1:B5=AGGREGATE(15,6,(B1:B5)/(A1:A5=MAX(A1:A5)),1)))
Or with #Anupam Chand's shorter and better readable and overall better style :)
=SUM(B1:B5)
+(MAX(A1:A5)-MINIFS(B1:B5,A1:A5,MAX(A1:A5)))
*COUNTIFS(A1:A5,MAX(A1:A5),B1:B5,MINIFS(B1:B5,A1:A5,MAX(A1:A5)))
The explanation works for bot solutions:
The SUM-part just sums the whole list.
The second line gets the max-value for column A and the corresponding min-value of column B for the max-values in column A and adds or subtracts it respectively.
The third line counts, how many times the corresponding min-value for the max-value occurs and multiplies it with the second line.
Can you try this ?
=MAX(A1:A5)+SUM(B1:B5)-MINIFS(B1:B5,A1:A5,MAX(A1:A5))
What we're doing is adding the max of A to all rows of B and then subtracting the min value of B where A is the max.
If you have Excel 365 you can use the following LET-Formula
=LET(A,A1:A5,
B,B1:B5,
MaxA,MAX(A),
MinBExclude, MINIFS(B,A,MaxA),
sumB1,SUMPRODUCT(B*(A=MaxA)*(B<>MinBExclude)),
sumB2,SUMPRODUCT(B*(A<>MaxA)),
MaxA +sumB1+sumB2
A and B are shortcuts for the two ranges
MaxA returns the max value for A (110)
MinBExclude filters the values of column B by the MaxA-value (25, 13, 82) and returns the min-value of the filtered result (13)
sumB1 returns the sum of the other MaxA values from column B (26 + 82)
sumB2 returns the sum of the values from B where value in A <> MaxA (71 + 60)
and finally the result is returned
If you don't have Excel 365 you can add helper columns for MaxA, MinBExclude, sumB1 and sumB2 and the final result
I need a count of how many date items fall within Data 1 & Data 2
ie:
x-1 will have a count of 2
x-2 will have a count of 1
-x-3 will have a count of 2
-y-1 will have a count of 2
What would be the best way to go abouts when approaching this?
Data 1
Data 2
Date
x
1
Date 1
x
1
Date 1
x
1
Date 2
x
2
Date 3
x
2
Date 3
y
1
Date 1
y
1
Date 1
I see only one way to interpret with the available information:
To count the number of times Date_to_test falls within Date_1 and Date_2 (screenshot below, sheet here), you could use either the sum or something like a countifs (with interim calc):
sum approach
=SUM(1*($C$2:$C$11<=$B$2:$B$11)*($A$2:$A$11<=$C$2:$C$11))
countifs + interim calc
helper
=1*(C2<=B2)*(A2<=C2)
(additional column, drag down)
countifs
=COUNTIFS($D$2:$D$11,1)
Screenshot
Alternative
as for the 'sum' approach, sumproduct variants (e.g. =SUMPRODUCT(1*($C$2:$C$11<=$B$2:$B$11),1*($B$2:$B$11>=$A$2:$A$11))) are calculation/memory intensive
despite the countifs + helper approach containing more 'visible' data - these values need only be calculated once, the countifs can then be determined independently (assuming no updates to the helper column) - thus making it more memory/calculation efficient depending upon your calculation mode, screen-updating preferences
Caveat
if, by some misfortune re: interpreting your question, you are referring to some other means of establishing whether "date items fall within Data 1 & Data 2", then without knowing what this is, there very low likelihood of being able to guess this correctly
I'm creating an excel spreadsheet to track when an item is received as well as when a response to the item having been received has been made (ie: my mail was delivered at 1:00pm (item received) but I didn't check the mail until 5:00pm (response to item having been received)).
I need to track both the date and time of the item being received and want to separate these in two separate columns. At the moment this translates to:
Column A: Date item received
Column B: Time item received
Column L: Date item was responded to having been received
Column M: Time item was responded to having been received
In essence I'm looking to run calculations on the response time between when the item is received and when it has been responded to (ie: average response time, number of responses in less than an hour, and even things like the number of responses that took between 2 and 3 hours where Bob was the person who responded).
The per-line pseudo code would look something like:
(Lr + Mr) - (Ar + Br) ' where L,M,A,B are the columns and 'r' is the row number.
An example, with the following data:
1. A B L M
2. 1/5/19 10:00 1/5/19 12:00
3. 1/5/19 21:00 1/6/19 1:00
4. 1/5/19 22:00 1/5/19 23:00
5. 1/6/19 3:00 1/6/19 4:00
The outcome for the average response time would be 2 hours (average(rows 2-5) = average(2, 4, 1, 1) = 2)
The number of items with an average response times would be as follows:
(<=1 hour) = 2
(>1 & <=2) = 2
(>2 & <=3) = 0
(>3) = 1
I don't know (or can find) a function that will perform this and then let me use it within something like a countifs() or averageifs() function.
While I could do this (fairly easily) in VBA, the practical implementation of this spreadsheet limits me to standard Excel. I suspect that sumproduct() will be fundamental to make this work, but I feel that I need something like a sumsum() function (which doesn't exist) and I'm not familiar with sumproduct() to better understand what to even look for to set something like this up.
If you are not so familiar with SUMPRODUCT() or the likes I would suggest one helper column. Like so:
You can see the formula used is:
=((C2+D2)-(A2+B2))
You can probably do all type of calculations on this helper column. Note, column is formatted hh:mm. However, if you want to look into SUMPRODUCT() you could think about these:
Formula in H2:
=SUMPRODUCT(--(ROUND((((A2:A5+B2:B5)-(C2:C5+D2:D5))*-24),2)<=1))
Formula in H3:
=SUMPRODUCT((ROUND((((A2:A5+B2:B5)-(C2:C5+D2:D5))*-24),2)>1)*(ROUND((((A2:A5+B2:B5)-(C2:C5+D2:D5))*-24),2)<=2))
Formula in H4:
=SUMPRODUCT((ROUND((((A2:A5+B2:B5)-(C2:C5+D2:D5))*-24),2)>2)*(ROUND((((A2:A5+B2:B5)-(C2:C5+D2:D5))*-24),2)<3))
Formula in H5:
=SUMPRODUCT(--(ROUND((((A2:A5+B2:B5)-(C2:C5+D2:D5))*-24),2)>3))
The helper column is the easiest approach. It gives you the time differences that you can then easily analyse however you want. Analysis without the helper column is possible, but the approach differs depending on what type of analysis you want to do.
For the example you provided, which is counting the number of time differences grouped into ranges, you would use the FREQUENCY function:
=FREQUENCY(C2:C5+D2:D5-A2:A5-B2:B5,F2:F4)
In F2:F4 (called the "bins"), enter the upper limit of each range you want to count. The Frequency function counts up to and including the first value, then counts from there up to and including the second value, and so on. Enter the bins as times, e.g. 1:00 for 1 hour.
Note that Frequency is an array-entered and an array-returning function. This you means you need to first select the range that will contain all output values, G2:G5 in this example, then enter the function, then press CTRL+SHIFT+ENTER
Also note that Frequency returns an array that is one element larger than the number of bins specified. The extra element is the count of all values greater than the largest bin specified.
I have a data set with four columns: Start Date, End Date, Scheduled Qty, and Actual Quantity:
Start Date End Date Scheduled Qty Actual Qty
04/13/15 04/17/15 35 19
04/20/15 04/24/15 35 42
04/27/15 05/01/15 35 41
05/04/15 05/08/15 35 41
I want to find the total actual, except when the actual exceeds the scheduled I want to used the scheduled number.
In an already answered question (Sum minimum of corresponding column values) I found an array formula that works to total the lesser values of each row for the Qty columns (quotes used to display the less than symbol):
=SUM(IF(C1:C4"<"D1:D4, C1:C4, D1:D4))
This gives me a total for my whole range, but now I'd like to limit it to a date range such as end dates within a given month. I've used SUMIFS in other situations to look at my end dates and only sum data that falls within a given month, but I'm not figuring out how to combine that idea with the one from the array formula.
Any ideas how to make this happen? I'm working in Excel 2013.
Here's an extension of chancea's approach:
Excel's SUM function (and AVERAGE, STDEV, etc.) have the useful behavior of "skipping" over text values. For example AVERAGE(3, 4, "dog", 5) returns 4. You can leverage this behavior nested IF's inside a sum. For instance,
=SUM(IF(MONTH(B1:B4)=4,IF(C1:C4<D1:D4,C1:C4,D1:D4),"NO"))
will sum
(a) the lesser of scheduled and actual
(b) when the month is 4
This is accomplished by nested IF's. The outer IF is
IF(MONTH(B1:B4)=4,...,"NO") [if month <> 4, IF returns text ("NO"), which SUM skips]
The inner IF is the same one that chancea showed.
You can nest as many tests/filters for your data as you need
To add criteria onto an array function most of the time you are just going to be multiplying the extra condition onto whatever set of conditions you already have.
The reason why this works is simply because we start with our list of numbers we want to sum:
IF(C1:C4<D1:D4, C1:C4, D1:D4) => { 19, 35, 35, 35 }
Then we multiply 1's or 0's to each of the values that meet the extra criteria.
So for an example lets say that we only want to check the quantity of values that have an end date within the month of 4. We can do that with:
MONTH(B1:B4)=4
Just multiply that criteria in the SUM function to basically create a boolean and condition for that criteria:
=SUM(IF(C1:C4<D1:D4, C1:C4, D1:D4)*(MONTH(B1:B4)=4))
= SUM({ 19, 35, 35, 35 } * { 1, 1, 0, 0}) => SUM( {19, 35, 0, 0} ) = 54
This is the same if we want to add n condition's:
=SUM(IF(C1:C4<D1:D4, C1:C4, D1:D4)*(MONTH(B1:B4)=4)*(`Condition2`)*(`Condition3`)...)
You can use any formula or operator that returns a true/false value within your conditions.
Such as: = > < >= <= <> IF(...,TRUE)
To add OR logic as a criteria you need to use addition instead of multiplication and then group them inside a (..)>0 like this:
(((Or_Condition1)+(Or_condition2)+...+(Or_conditionN))>0)
So if we wanted to sum months 4 OR 5 we can write:
=SUM(IF(C1:C4<D1:D4, C1:C4, D1:D4)*(((MONTH(B1:B4)=4)+(MONTH(B1:B4)=5))>0))