Sum only values which fall Monday to Friday - excel

I receive a statement (as a .xls) each month which list a bunch billable items with an associated date. I want to create a formula (using either =sum() or =sumifs() to total the billable items, but only those which fall Monday to Friday (i.e., not weekends). Is that possible?
A B
------+--------------+-------------
1 | 05/12/2016 | $10.00
2 | 06/12/2016 | $10.00
3 | 07/12/2016 | $10.00
4 | 08/12/2016 | $10.00 dates are formatted as
5 | 09/12/2016 | $10.00 dd/mm/yyyy
6 | 10/12/2016 | $10.00
7 | 11/12/2016 | $10.00
8 | 12/12/2016 | $10.00
------+--------------+-------------
| Sum | $80.00
------+--------------+-------------
| Sum |
| (no weekends)| $60.00
------+--------------+-------------
EDIT:
I've just looked closer at the excel doc, and it's actually a datetime field, e.g. 31/10/2016 12:44:00 pm (displayed as 31/10/16 12:44).
I'm also not looking for a formula which works line by line, I'd like something which I can just copy and paste into a single cell at the bottom of the doc each month which examines A:A.

You need to use this formula:
=SUMPRODUCT(B1:B8,--(WEEKDAY(A1:A8,2)<6))
This is a hack which behaves like SUMIF but lets you use a function in your criteria. Otherwise, you would need to create an auxiliary column with WEEKDAY (in C for example) and then use =SUMIF(C1:C8,"<6",B1:B8).
WEEKDAY by default returns 1-7 for SUN-SAT. As this doesn't help, you can change the return type to type 2 with the optional second parameter to make the function return 1-7 for MON-SUN, which lets you do the easy <6 comparison. You can also use type 3, which returns 0-6 for MON-SUN, and then obviously use <5 instead.
More about the -- hack here.

Related

How do I advance a date timestamp forward to the beginning of the next work day if the timestamp occurs outside of working hours?

I have a list of date timestamps and if any of the times happen outside of our working hours, I need to advance them forward to the start of the next workday.
Our work hours are M-F 8:30am-5:30pm, Saturday 8:30am-1:30pm, Sunday closed and we are also closed on holidays.
Examples:
Friday June 26, 2020 6:30pm should be advanced to Saturday June 27, 2020 8:30am
Friday July 3, 2020 6:30pm should be advanced to Monday July 6, 2020 8:30am. Because Saturday was a holiday and we are closed on Sunday.
Friday July 3, 2020 5:29pm should not be advanced because it began during work hours
Column A |Column B | Column C | Column B | Column E
Underwriter | LoanNumber | EntryTime_+3hrs | Desired Outcome | HOLIDAY
TOM | 1 | 07/31/2020 8:28:42 AM | 08/01/2020 8:30:00 AM | 01/01/2020
DICK | 2 | 07/30/2020 6:32:36 PM | 07/31/2020 8:30:00 AM | 01/20/2020
JANE | 3 | 07/30/2020 4:18:57 PM | 07/30/2020 4:18:57 PM | 02/17/2020
BETH | 4 | 07/30/2020 3:06:18 AM | 07/30/2020 8:30:00 AM | 05/25/2020
SALLY | 5 | 07/29/2020 6:35:37 PM | 07/30/2020 8:30:00 AM | 07/04/2020
GEORGE | 6 | 07/03/2020 7:45:26 PM | 07/06/2020 8:30:00 AM | 09/07/2020
| | | | 10/12/2020
| | | | 11/11/2020
| | | | 11/26/2020
| | | | 12/24/2020
| | | | 12/25/2020
Start date time stamps need to be validate and converted to next available time slot.
Current thinking is you have three potential outcomes:
The date will need to be shifted next possible day starting at 0830
The date will remain the same but the time will be shifted to 0830
The date and time are valid and no adjustment is required.
so a generic formula might look something like this:
IF(OR(HOLIDAY,SUNDAY,AFTERHOURS),FIND NEXT WORKDAY,
IF(BEFORE WORKHOURS, SET TIME TO START TIME, ITS VALID TIME))
In order to check each condition individually for a potential day shift we can use the following formulas:
(ASSUME C2 is the start date being tested)
WEEKDAY AFTER 1730
=AND(MOD(C2,1)>TIME(17,30,0),OR(WEEKDAY(C2)={2,3,4,5,6}))
SATURDAY AFTER 1330
=AND(MOD(C2,1)>TIME(13,30,0),WEEKDAY(C2)=7)
HOLIDAY (list in E2:E12)
=COUNTIF($E$2:$E$12,INT(C2))=1
SUNDAY
=WEEKDAY(C2)=1
The MOD function in the first two formulas is stripping the Integer/date value and just keeping the decimal/time portion
The { } is a manual list/array is a nice way of doing multiple OR checks with out writing out each individual check. Since these are sequential, you do have other options.
Now there is a way of flagging each case, So now just rearrange and group together so you have three choices in a nested IF function:
=IF(OR(AND(MOD(C2,1)>TIME(17,30,0),OR(WEEKDAY(C2)={2,3,4,5,6})),AND(MOD(C2,1)>TIME(13,30,0),WEEKDAY(C2)=7), COUNTIF($E$2:$E$12,INT(C2))=1, WEEKDAY(C2)=1), FIND NEXT DATE, IF(BEFORE WORK, SET TIME TO 0830, DO NOTHING))
Since each valid day starts at 0830 and invalid days have already been taken care of with the first IF, only the start time needs to be checked.
=MOD(C2,1)<TIME(08,30,00)
And the valid time is the only case left over so there is nothing to check for.
And you pseudo formula becomes something like:
=IF(OR(AND(MOD(C2,1)>TIME(17,30,0),OR(WEEKDAY(C2)={2,3,4,5,6})),AND(MOD(C2,1)>TIME(13,30,0),WEEKDAY(C2)=7), COUNTIF($E$2:$E$12,INT(C2))=1, WEEKDAY(C2)=1), FIND NEXT DATE, IF(MOD(C2,1)<TIME(08,30,00), SET TIME TO 0830, DO NOTHING))
So now you just need to figure out how to add some days, change the time, and keep what you have for a value.
Adjusting the number of days to add had me looking at multiple nested IF equal to the number of days in a row that could be invalid. Right now I have the worst case scenario being Thursday at 17:31 something starts. Friday is a holiday as a result of a holiday on Saturday, Sunday is a holiday, and Monday is a holiday due to the Sunday holiday. So first potential day would be 5 days away. Ugly nested IF. As an alternative I looked at AGGREGATE and adding 1 day at a time up to 5 and checking if its a valid date. Then take the lowest/earliest date and setting start time to 0830. To achieve this I tried the following formula:
=AGGREGATE(15,6,(INT(C2)+{1,2,3,4,5})/((COUNTIF($E$2:$E$12,(INT(C2)+{1,2,3,4,5}))<1)*(WEEKDAY(C2+{1,2,3,4,5})<>1)),1)+TIME(8,30,0)
Then next function you need to do is keep the date but set the time to 08:30
=INT(C2)+TIME(08,30,00)
and your do nothing is:
=C2
so now if we combine the crap out of that into one formula we wind up with:
=IF(OR(AND(MOD(C2,1)>TIME(17,30,0),OR(WEEKDAY(C2)={2,3,4,5,6})),AND(MOD(C2,1)>TIME(13,30,0),WEEKDAY(C2)=7), COUNTIF($E$2:$E$12,INT(C2))=1, WEEKDAY(C2)=1), AGGREGATE(15,6,(INT(C2)+{1,2,3,4,5})/((COUNTIF($E$2:$E$12,(INT(C2)+{1,2,3,4,5}))<1)*(WEEKDAY(C2+{1,2,3,4,5})<>1)),1)+TIME(8,30,0), IF(MOD(C2,1)<TIME(08,30,00), INT(C2)+TIME(08,30,00), C2))
I believe the desired date in D2 (red background) is wrong and should instead be 20/07/31 08:30
reference to your previous question
Now in theory this could be substituted for every B2 reference in the first formula, but A) the thing would become even more damned unreadable and hard to maintain than it already is, and B) may cause multiple repetitive calculations.

Customizing Weekday/Workday Function to reflect actual working hours

So my company services clients with insurance products and we have two teams: Liability and Crime. There are generally one 4 different types of task: Binding, Issuance, Quoting and Rapids.
I currently have made a spreadsheet based on data obtained through our workflow.
The main formulas I use to calculate service due date for Crime/Liability team is:
=IF(OR(WEEKDAY(IF(A2="Binding",C2+(1/8),IF(A2="Quoting",C2+(1/8),IF(A2="Issuance",C2+2,IF(A2="Rapids",C2+(1/8),"")))))=1,WEEKDAY(IF(A2="Binding",C2+(1/8),IF(A2="Quoting",C2+(1/8),IF(A2="Issuance",C2+2,IF(A2="Rapids",C2+(1/8),"")))))=7,IF(A2="Binding",C2+(1/8),IF(A2="Quoting",C2+(1/8),IF(A2="Issuance",C2+2,IF(A2="Rapids",C2+(1/8),"")))))+2,IF(A2="Binding",C2+(1/8),IF(A2="Quoting",C2+(1/8),IF(A2="Issuance",C2+2,IF(A2="Rapids",C2+(1/8),"")))))
Where you have 3 hours to finish binding, quoting, rapids, and you have two days for issuance.
We are now expanding our service to California, which is three hours behind EST time, so now comes the issue: We want to expand our working hours (est time) to 9 am - 8 pm to cover west coast. But, does is it possible to tell excel to do that via a weekday/workday function?
The goal is to have the due dates wrap around weekends to Monday and anything after 8 pm (est time) to being due next day.
For example: If a binding task comes in at 7:00 pm, then you would have 1 hour till 8 pm, and so the task would be due at 11:00 am the next day. Is this even possible to do with just excel? Any help would be immensely appreciated guys, thank you!
Your formula can be simplified greatly if you have a lookup table in your workbook somewhere that returns the due time values. For the example below, my lookup table is in Sheet2, A1:
Sheet 1 - Example Data
| A | ... | C | D |
+--------+ ... +-----------------+----------------+
1 | Task | | Received | Due |
2 |Binding | |19/02/2018 09:00 |19/02/2018 12:00|
3 |Quoting | |19/02/2018 13:00 |19/02/2018 15:00|
Sheet 2 - Lookup table:
| A | B |
+--------+-------+
1 |Binding | 0.125 |
2 |Quoting | 0.125 |
3 |Issuance| 2 |
4 |Rapids | 0.125 |
Formula
The formula in Sheet1 D2 is:
=C2+INDEX(Sheet2!B:B,MATCH(Sheet1!A2,Sheet2!A:A,0))
From there it should be a lot simpler to construct an IF STATEMENT to rollover to the next day if the order is received past 5pm (would be due after 8pm).

Excel: Remove Duplicates based on time condition

I'm looking to remove duplicates from a 250,000 row excel sheet based on a 3 month rolling time condition.
We have a lot of usersIDs and the dates which they visited but a lot of these visits are very far apart (sometimes over a year) and a lot of them are within the same day/couple day period.
The best way to explain what I want to do is with an example. So if they first visited on 1st Jan, 1st Jan, 3rd Jan, 8th Feb, 4th June, 5th June, 1st Dec, 1st Dec, 2nd Dec, I would want to grab that first date of 1st Jan, 4th June and 1st Dec.
If they visited 1st Jan, 1st Jan, 3rd Jan, 8th Feb, 9th Apr then 1st August, 1st Sept, I would want 1st Jan and 8th August.
So we want to grab the first date, then see how often they visit within 3 months of each visit and if they leave for more than a 3 month period, grab the first date that they return. Sometimes they come back 4 or 5 times after 3 months and the data can span several years.
Is there a way for me to achieve this? It would be great to get some help as this is driving me mad.
Cheers
If the UserID is in column A and the VisitDate is in B with the headings in row 1 and then a blank row in 2 and the data starting in row 3 then try this (explanation below):
Array Formula version:
sort the rows ascending by VisitDate
in B2 put 1/1/1900 so it won't match anything (but it has to be a date)
in C3 put this array formula (press control-shift-enter instead of just enter):
=SUM((B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))*(A$2:A2=A3))=SUM((A$2:A2=A3)*1)
Copy the formula in C3 down to every row of data
Filter on Unique = TRUE
if you want to resort you will need to copy and paste back column C by values
New non-array formula version:
sort the rows ascending by VisitDate
in B2 put 1/1/1900 so it won't match anything (but it has to be a date)
in C3 put this normal formula (just press enter):
=COUNTIFS(B$2:B2,"<"&DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)),A$2:A2,A3)=COUNTIF(A$2:A2,A3)
Copy the formula in C3 down to every row of data
Filter on Unique = TRUE
if you want to resort you will need to copy and paste back column C by values
This produces the following with my sample data (array formulas may take a very long time to calculate for lots of rows):
| A | B | C
---+--------+------------+--------
1 | UserID | VisitDate | Unique
2 | | 1/01/1900 |
3 | a | 1/01/2017 | TRUE
4 | a | 1/01/2017 | FALSE
5 | b | 2/01/2017 | TRUE
6 | b | 2/01/2017 | FALSE
7 | a | 3/01/2017 | FALSE
8 | c | 3/01/2017 | TRUE
9 | c | 3/01/2017 | FALSE
10 | b | 4/01/2017 | FALSE
11 | c | 5/01/2017 | FALSE
12 | a | 8/02/2017 | FALSE
13 | b | 9/02/2017 | FALSE
14 | c | 10/02/2017 | FALSE
15 | a | 4/06/2017 | TRUE
16 | a | 5/06/2017 | FALSE
17 | b | 5/06/2017 | TRUE
18 | b | 6/06/2017 | FALSE
19 | c | 6/06/2017 | TRUE
20 | c | 7/06/2017 | FALSE
21 | a | 1/12/2017 | TRUE
22 | a | 1/12/2017 | FALSE
23 | a | 2/12/2017 | FALSE
24 | b | 2/12/2017 | TRUE
25 | b | 2/12/2017 | FALSE
26 | b | 3/12/2017 | FALSE
27 | c | 3/12/2017 | TRUE
28 | c | 3/12/2017 | FALSE
29 | c | 4/12/2017 | FALSE
Because the formula compares the current row with all the rows above looking for rows with dates in the past the data needs to be sorted with the oldest dates first.
How the array formula works:
=SUM((B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))*(A$2:A2=A3))=SUM((A$2:A2=A3)*1)
DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)) is 3 months ago (even if it is 92 days)
(B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3))) is an array of TRUE/FALSE values which has a TRUE for every row above that is older than 3 months ago
(A$2:A2=A3) is an array of TRUE/FALSE values which has a TRUE for every row above that matches the user ID
(B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))*(A$2:A2=A3) does an AND of the arrays so 1 is returned (TRUE*TRUE=1) for each row above that has the same name and a date that is older than 3 months ago
SUM((B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))*(A$2:A2=A3)) adds all the TRUE rows above that have the same name and a date that is older than 3 months ago
SUM((A$2:A2=A3)*1) adds the number of rows above that have the same name (TRUE*1=1)
=SUM((B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))*(A$2:A2=A3))=SUM((A$2:A2=A3)*1) compares the two sums and returns TRUE if all the rows above that have the same name are all older than 3 months ago
Methodology:
I originally just played with a column of dates - no userID. I wanted to find a way to know if the date on a particular was more than 3 months after all the dates before it (I implicitly assumed that the dates were sorted). I reasoned that if a count of the dates before the current row matched a count of the dates before the current row that were older than 3 months in the past then I would have the answer I wanted. So I originally put this formula in C3 and copied it down:
=COUNTIF(B$2:B2,"<"&(B3-90))=COUNTA(B$2:B2)
Then change it to 3 months instead of 90 days:
=COUNTIF(B$2:B2,"<"&DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))=COUNTA(B$2:B2)
And then to add the userID we need a way to compare multiple criteria - this is where COUNTIFS comes in (if you have Excel 2007 or better):
=COUNTIFS(B$2:B2,"<"&DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)),A$2:A2,A3)=COUNTIF(A$2:A2,A3)
And then I converted it to this array formula:
=SUM((B$2:B2<DATE(YEAR(B3),MONTH(B3)-3,DAY(B3)))*(A$2:A2=A3))=SUM((A$2:A2=A3)*1)
In retrospect I don't know if giving the array formula was a good idea or not: I don't know whether the array formula would be better/faster than COUNTIFS or not. So use whichever you prefer.

Excel Pivot Table: How do I count the number of working days for employees based on date-time values?

In my theoretical data set, I have a list which shows the date-time of a sale, and the employee who completed the transaction.
I know how to do grouping in order to show how many sales each employee has per day, but I'm wondering if there's a way to count how many grouped days have more than 0 sales.
For example, here's the original data set:
Employee | Order Time
A | 8/12 8:00
B | 8/12 9:00
A | 8/12 10:00
A | 8/12 14:00
B | 8/13 10:00
B | 8/13 11:00
A | 8/13 15:00
A | 8/14 12:00
Here's the pivot table that I have created:
Employee | 8/12 | 8/13 | 8/14
A | 3 | 1 | 1
B | 1 | 2 | 0
And here's what I want to know:
Employee | Working Days
A | 3
B | 2
Split your Order Time column (assumed to be B) into two, say with Text to Columns and Space as the delimiter (might need a little adjustment). Then pivot (using the Data Model) as shown:
and sum the results (outside the PT) such as with:
=SUM(F3:H3)
copied down to suit.
Columns F:G may then be hidden.
I fully support #Andrea's Comment (a correction) on the above:
I think this could have been made simpler. If you remove the "Time" in values of the pivot table and then move "Order" from columns to values and use distinct count as in the example. It should count Employee per date making the sum not needed. If you scale this to make it larger. Say 50 dates then the =Sum() needs to be moved each time.

How to select the last cell in a range in Excel

I've got a spreadsheet that updates throughout the day with data, I need to be able to grab the last cell in a column but for certain date ranges, not just the last cell in the column.
Column C contains the data I need, column A and B update with the date and time, (some cells in column A could be blank too). Column D I can change to make column E display the latest data for the selected date.
Here's what I've got so far to put in column E:
VLOOKUP(D1, $A:$C,3,FALSE)
I've managed to get data from my formula but only the first entry. For example if I enter the date 17/05/2016 it will return '5'. Whereas I need the more recent data '28'.
Example sheet:
A | B | C | D | E
16/05/2016 | 08:00:00 | 3 | date | data
16/05/2016 | 12:00:00 | 7
16/05/2016 | 18:00:00 | 15
16/05/2016 | 22:00:00 | 27
17/05/2016 | 08:00:00 | 5
17/05/2016 | 12:00:00 | 11
17/05/2016 | 18:00:00 | 21
17/05/2016 | 22:00:00 | 28
18/05/2016 | 08:00:00 | 4
18/05/2016 | 12:00:00 | 13
18/05/2016 | 18:00:00 | 19
18/05/2016 | 22:00:00 | 30
I've only just started getting my head around excel formulas so any help would be greatly appreciated!
=INDEX(C2:C13,MATCH(D3,A2:A13,1))
INDEX/MATCH is a very powerful combination. It can perform the same job as VLOOKUP and then a bit more. VLOOKUP is restricted to searching the first column and returning information to the right. With MATCH you can search any column, and you can return information from any column (even to the left which vlookup cant do)
If you start reading with the MATCH function, it searches for the value in D3 within the range A2:A13 and return an integer representing the row the value of D3 was found it. The 1 at the end of match tell match to look for that last entry that D3 exceeded. This means that column A needs to be sorted in ASCENDING order
INDEX uses the integer from MATCH and goes down that many rows in in specified range. so if match returned 1, then it would read C2.

Resources