I am trying to create an excel function that categorizes the time of day.
I have a column of DateTimes, Format: 3/3/2017 13:30 (but can change the format if needed). I need a second column declaring "ON" for the hours 9 pm to 5 am, "AM" for 5 am to 9 am, "BH" for 9 am to 5 pm, and "PM" for the hours 5 pm to 9 pm. I need weekends too but I figure I can pull those manually.
Result would look like (where I have column 1 and need to calculate column 2):
DateTime Time period
3/3/2017 13:30 BH
3/3/2017 17:30 PM
3/4/2017 3:30 ON
3/5/2017 5:30 AM
Make a table with the lower time and expected out put:
Then a simple VLOOKUP:
=VLOOKUP(MOD(A2,1),F:G,2)
We can save a few characters by only testing one end of each range. Once we have tested a value for less than 5 am, we no longer need to test to see if it is greater than 5 am. (The AND( statements aren't necessary.)
=IF(HOUR(A1)<5,"ON",IF(HOUR(A1)<9,"AM",IF(HOUR(A1)<17,"BH",IF(HOUR(A1)<21,"PM","ON"))))
If you want to detect weekends, wrap the whole thing in a weekend test. Two methods presented:
The better approach, suggested by #ScottCraner in the comments:
=IF(weekday(a1,2)>5,"WEEKEND","THE WHOLE THING")
The first argument for weekday( is obviously the date we are testing. The second forces Monday to be the first day of the week, which leaves Sat & Sun as the last two.
Combined with the rest, we would get:
=IF(weekday(a1,2)>5,"WEEKEND",IF(HOUR(A1)<5,"ON",IF(HOUR(A1)<9,"AM",IF(HOUR(A1)<17,"BH",IF(HOUR(A1)<21,"PM","ON")))))
An unnecessarily long, and somewhat fragile approach (breaks in non-English)
=IF(LEFT(TEXT(A1,"ddd"),1)="S","WEEKEND","THE WHOLE THING")
This works because TEXT(A1,"ddd") formats the date as the three-letter day of week. In English, at least, both weekend days starts with an "S", and we use left( to grab that first letter.
Together, it would end up looking like:
=IF(LEFT(TEXT(A1,"ddd"),1)="S","WEEKEND",IF(HOUR(A1)<5,"ON",IF(HOUR(A1)<9,"AM",IF(HOUR(A1)<17,"BH",IF(HOUR(A1)<21,"PM","ON")))))
Just to show a different way:
=IF(NETWORKDAYS(A2,A2),CHOOSE(SUM((({"5:00";"9:00";"17:00";"21:00"}*1)<MOD(A2,1))*1)+1,"ON","AM","BH","PM","ON"),"WEEKEND")
This is an array formula and must be confirmed with ctrl+shift+enter.
Can be extended as you like without getting in trouble of the bracket-limit.
Also like the Scott's answer: this works with times like 17:43. ;)
A little long, but works:
=IF(AND(HOUR(A2)>=9,HOUR(A2)<17),"BH",IF(AND(HOUR(A2)>=17,HOUR(A2)<21),"PM",IF(AND(HOUR(A2)>=5,HOUR(A2)<9),"AM","ON")))
Related
I've run into a dilemma that I thought I would overcome easily but ended in getting different results.
So I've been using the following formula:
=(NETWORKDAYS(H6,N6)-1)*($F$2-$E$2)+IF(NETWORKDAYS(N6,N6),MEDIAN(MOD(N6,1),$F$2,$E$2),$F$2)-MEDIAN(NETWORKDAYS(H6,H6)*MOD(H6,1),$F$2,$E$2)
This formula works perfectly, as I've modified it to use NETWORKDAYS.INTL because all workdays are working days, but the working hours are from 8:00 AM to 11:00 PM.
My modified code is:
=(NETWORKDAYS.INTL([#[DC_CREATION_DATE]],[#[ACTUAL_END_DATE]],"0000000")-1)*(upper-lower)
+IF(NETWORKDAYS.INTL([#[ACTUAL_END_DATE]],[#[ACTUAL_END_DATE]],"0000000"),MEDIAN(MOD([#[ACTUAL_END_DATE]],1),upper,lower),upper)
-MEDIAN(NETWORKDAYS.INTL([#[DC_CREATION_DATE]],[#[DC_CREATION_DATE]],"0000000")*MOD([#[DC_CREATION_DATE]],1),upper,lower)
Where:
DC_CREATION_DATE = Start Date
ACTUAL_END_DATE = End Date
upper = Named Range containing the End Time i.e. 11:00 PM
lower = Named Range containing the Start Time i.e. 8:00 AM
Now the problem is that for a particular month, the working hours in a day change to shifts:
Start Time 1 = 11:00 AM
End Time 1 = 5:00 PM
Start Time 2 = 9:00 PM
End Time 2 = 2:00 AM
Any time outside the above-mentioned times are non-working hours. The TTs we receive CAN be outside working hours, but I will only calculate time duration inside working hours.
What I tried doing was to use the same formula twice on the same date range (first time, upper becomes 5:00 PM and lower becomes 11:00 AM and the result is stored in the cell, the second time, upper becomes 2:00 AM and lower becomes 9:00 PM and the result is stored in a different cell), and then add the two results in separate cells to get the overall working hours between the working hours range.
Alas, I thought it was that simple but what I'm seeing are different results, for both formulas when they're run.
Because if the time is outside of the working range, even for start and end, it should return 0. (I believe I can overcome this by using IF)
The ######## is the field showing the value in negative. Since I'm formatting all cells to [h]:mm
Anyone who can help me in this regard?
Since your Upper 2 time is next day, you need to enter it as such.
The underlying value of 2:00 AM is 0.083333333. To make it next day, enter it as 1.083333333. You can stil format it as 2:00 AM if you wish, it's the underlying value your formula is using.
Some examples, with your formula unchanged (other than including Upper/Lower 1 and 2)
Last time I posted a quite vague story about a date difference challenge which I haven't solved yet. I will try to elaborate since I have tried everything in my power and the problem still isn't fixed.
I currently have three columns.
Column 1 (F)
the date a car starts its repairs (format DayOfWeek-DD-MM-YYYY)
Column 2 (G)
the number of days in which the car is repaired (service level agreement [SLA]; the standard is 10 days)
Column 3 (H)
the output, which is the date the car should be finished. So the number of days after the startdate*
*Th thing which makes this case difficult is that only weekdays are included.
So, for example:
If a car starts repairs on Monday 1st of August, the finish date is Tuesday the 14th of August.
I tried to solve this with the following formula:
=IF(WEEKDAY(F218)=2;(F218+11);
IF(WEEKDAY(F218)=3;F218+12;
IF(WEEKDAY(F218)=4;F218+13;
IF(WEEKDAY(F218)=5;F218+14;
IF(WEEKDAY(F218)=6;F218+15)))))
In other words:
If startdate = Monday then startdate + 11,
if startdate = Tuesday then startdate + 12, etc.
This works, but I have 300+ rows and dragging this function down doesn't change the cell references.
I know about the NETWORKDAYS and WEEKDAY functions, but I encounter problems with any Monday where only 1 weekend passes and other days where 2 weekends pass.
First of all, I am assuming that your first day - whatever day that may be - is considered day one (1). So in my scenario, if a SLA states 2 days to complete a repair and the start date is a Monday, I'm assuming the repair should be completed by Tuesday.
My assumption is based off this comment by #RonRosenfeld:
...although you might have to subtract 1 from the number of days
With all that being said, try this formula in your cell instead:
NOTE: You may need to change things like commas and semi-colons to adjust for your region.
=WORKDAY($F2,$G2-1)+LOOKUP(WEEKDAY(WORKDAY($F2,$G2-1),16),{1;2;3},{2;1;0})
What it does:
WORKDAY($F2,$G2-1)
First we want to find out exactly what day the repairs should be completed by if weekend days (Saturday and Sunday) were included. This part of the formula will simply give us a place to start.
$F2 is your repair start date
$G2 is the number of days a repair is supposed to take (you may need to add a column for this, because, as you stated, the SLA may change and you need the formula to be easily adjusted)
WEEKDAY(WORKDAY($F2,$G2-1),16)
The WORKDAY function from above is wrapped inside a WEEKDAY function. This WEEKDAY function is written to account for each day of a week to be assigned numbers. The [return_type] parameter of 16 tells Excel to label them as "Numbers 1 (Saturday) through 7 (Friday)". We chose 16 so that our LOOKUP function is easier to write. This part of the formula only returns a one-digit number, which in turn will be used to figure out what day of the week we actually want when excluding weekends.
LOOKUP(WEEKDAY(WORKDAY($F2,$G2-1),16),{1;2;3},{2;1;0})
We finish the formula by adding the result from a LOOKUP function using the first form of the function: LOOKUP(lookup_value,lookup_vector,[result_vector])
We found our lookup_value in the previous bullet point using the WEEKDAY function. Now we want Excel to use the lookup_vector - {1;2;3} in our formula - to find the correct value to add to the first part of our formula (which is found using the [result_vector] - {2;1;0} in our formula).
The lookup_vector only has three values: 1, 2, and 3.
1 signals Saturday
2 signals Sunday
3 signals all other days
Think of the lookup_vector and [result_vector] as forming a matrix/table from which our value is found:
1 2
2 1
3 0
If our number of repair days pushes us to:
a Saturday (1), the formula adds 2.
a Sunday (2), the formula adds 1.
any weekday, the formula adds 0 (since weekdays are acceptable).
Hopefully all of this makes sense. Best of luck to you!
I would like to have a formula which will tell me if a time in a cell is between 2 separate vlaues in other cells and to return a value if so.
I have already created the below code but this is not returning any values back at all.
=IF(AND(F4>=$R$1,F4<P1),"Night Shift",IF(AND(F4>=$P$1,F4<$Q$1),"AM Shift",IF(AND(F4>=$Q$1,F4<$R$1),"PM Shift","")))
In this example the cell values are (P1 = 06:00, Q1 = 14:00, R1 = 22:00). The value in the F4 is 00:31:38.
Any help would be appreciated.
Your first AND needs to adjust a little.
Excel sees TIME as a fraction of 1 whole day. So 00:31:38 though you meant it to be the next day from 22:00, Excel does not know that and as such will not see it greater than 22:00
We also do not need to test for the Night Shift. It is the only option left if the time is not in one of the others:
=IF(F4<>"",IF(AND(F4>=$P$1,F4<$Q$1),"AM Shift",IF(AND(F4>=$Q$1,F4<$R$1),"PM Shift","Night Shift")),"")
You could also create a small table like such:
0 6:00 14:00 22:00
Night Shift AM Shift PM Shift Night Shift
Then use a HLOOKUP to return the correct value:
=HLOOKUP(F4,O1:R2,2,TRUE)
I took a slightly different path that Scotts.
A Night Shift occurs if the time is greater or equal to 10PM, OR is less than 6AM.
=OR($F$4<$P$1,$F$4>=$R$1)
An AM Shift occurs when the time is greater or equal to 6AM, AND is less than 2PM.
=AND($F$4>=$P$1,$F$4<$Q$1)
A PM Shift occurs when the time is greater or equal to 2PM, AND is less than 10PM.
=AND($F$4>=$Q$1,$F$4<$R$1)
Stick the three conditions together and you have:
=IF(OR($F$4<$P$1,$F$4>=$R$1),"Night Shift",IF(AND($F$4>=$P$1,$F$4<$Q$1),"AM Shift",IF(AND($F$4>=$Q$1,$F$4<$R$1),"PM Shift","")))
Edit
During testing I entered 00:00:00 in A1 and =A1+TIMEVALUE("00:01:00") in A2:A1440.
At 06:00:00, 14:00:00 and 22:00:00 the changeover in shift happened a minute later.
If, however, I manually typed in 06:00:00 the changeover happened on the hour. This seems to be because TIMEVALUE is calculating 6AM as 0.2499999 rather than 0.25.
=IF(OR(HOUR(NOW())>22,HOUR(NOW())<7),"NIGHT","")&IF(AND(HOUR(NOW())>6,HOUR(NOW())<15),"MORNING","")&IF(AND(HOUR(NOW())>14,HOUR(NOW())<23),"LATE","")
I know a bit late but simplifies everything without the need of using other cells (note there are different times used).
Night - 23-07
AM - 07-15
PM - 15-23
I have a worksheet that has a start date and end date. I need to get the number of months between these dates. I used the formula =MONTH(B1)-MONTH(A1) to get that #. However this formula fails when my dates span multiple years - if start date is 1/1/2014 and end date is 1/1/2015, then it returns a "1", when I'd like to get a "12".
I then tried DATEDIF(A1,B1,"m") to get the # of months between the dates, and that worked. My issue, however, can be summarized by the following example:
Situation 1:
Start Date: 1/5/2014
End Date: 3/1/2014
"MonthDif": 2
DateDif: 1
Situation 2:
Start Date: 1/5/2014
End Date: 3/10/2014
"MonthDif": 2
DateDif: 2
As you can see, the DATEDIF function returns the # of complete months, while my month - month function returns the number of months "occupied" by the difference between the start and end dates, regardless if they are complete months.
I need the number of months, regardless if full months, over any date period! Basically, I need exactly what the MONTH(B1)-MONTH(A1) returns, except it will work over multiple years.
Also, I was considering designing a custom VBA function to achieve the above. If anyone has any suggestions there.
If you use DATEDIF but always count from the 1st of the first month you'll get what you need, e.g. if you use =A1-DAY(A1)+1 that will give you the first of the A1 month, so use that in DATEDIF like this
=DATEDIF(A1-DAY(A1)+1,B1,"m")
Assuming B1 contains your end date and A1 contains your start date,
=IF(DAY(B1)>=DAY(A1),0,-1)+(YEAR(B1)-YEAR(A1))
*12+MONTH(B1)-MONTH(A1)
I need exactly what the MONTH(B1)-MONTH(A1) returns, except it will work over multiple years.
Ok, well, at the risk of stating the obvious:
=MONTH(B1)-MONTH(A1) + 12*(YEAR(B1)-YEAR(A1))
Rationale: a year is composed of twelve months.
I am trying to get a calculation of h:mm between two different times. I am using this formula
=TEXT(D21+E21, "h:mm")
When the Two cells are 12:00 and 12:30 or 12:00 and 1:00 it shows :30 and 1:00 respectively. When it is between 12:30 and 1:00, it shows 1:30. Note, all times are times of day.
Ultimately I want four cells, Time In, Time Out, Lunch In, and Lunch out, with a timespan showing time minus lunch. I am having trouble getting excel to give my anything close to accurate for nearly any input.
I recommend you don't use TEXT function. As the name implies - the result of TEXT function is a text value, which you might not be able to use in subsequent calculations. It should be sufficient to use just
=E21-D21
...then format result cell as [h]:mm
Change it to:
=TEXT(E21-D21, "h:mm")
(changed E2 to E21 to match the original question JMG)
Change it to TEXT(E21-D21, "h:mm") and also use 13:00 instead of 1:00, or add dates. It will fail if E21 is less than D21, and 1:00 is translated as 1AM. If you want to get the difference across days then add date information as well.