I have a 3 column worksheet with columns Date, Time, Value. I need to calculate a fourth column with a running total for each row for all Value where Date+Time is in the past 24 hours. The number of readings vary over the 24 hours, being as little as once a second to once every few minutes.
A SELECT would look something like:
select
ot.dt
, ot.tm
, ot.value
, sum(it.value)
from
readings ot
inner join readings it
on addtime(ot.dt,ot.tm) >= addtime(it.dt,it.tm)
and convert(timediff(addtime(ot.dt, ot.tm), addtime(it.dt, it.tm)), decimal) < 240000
group by
ot.dt
, ot.tm
, ot.value
The screenshot below gives an idea of what the resulting output should look like. Different from actual requirement is that here a reading is provided for every hr and the fourth column (SumPast3Hours) only sums the current Value and the previous two. In actuality the. number of rows to sum will vary.
It seems ungrateful not to use your test data, but I wanted to answer the original question and consider what would happen across different days.
I can think of two possible approaches:
(1) Use sumifs, one for the case where the readings are in the current day and one for the case where they are in the previous day
=SUMIFS(C$2:C2,A$2:A2,A2)+SUMIFS(C$2:C2,A$2:A2,A2-1,B$2:B2,">="&B2)
(2) Use sum (or sumproduct)
=SUM(C2:C$2*((A2:A$2+B2:B$2)>=(A2+B2-1)))
This relies on the fact that dates are consecutive whole numbers, and hours are fractions (1 hour = 1/24th of a day)
You may want to change >= to > to exclude readings which are exactly 24 hours before the current reading.
Related
I have a column that needs split based on "morning" and "evening" although the morning and evening times move every day (it's based on sidereal day). Calling them morning and evening is a little deceiving though because eventually the time will creep into the next day and I want to keep the groups distinct. It is more accurate to call them group 1 and group 2. It just so happens that they are around 12 hours apart so it looks like you can just separate based on time of day but once the later group creeps into the AM hours, it would start to get counted as "morning" and the earlier group would roll into the afternoon and be counted as "afternoon" See screenshot below for example data.
I need them split so I can perform operations on the value column so I can distinguish the values in the first group from the values in the second group. I thought of doing some sort of flip flop algorithm based on the previous cell but there may be a more elegant way to do it. Also, it's not shown on the example data but sometimes the day may skip but the times more or less continue in the same pattern of increasing by 3-5 minutes each day.
A date with a time stamp is stored as a number in Excel. Days are stored as whole numbers, time is stored in decimals. So, disregarding the date part, look at the decimal of the number and determine if that is before or after the time you want.
0.5 for example is midday, or 12 noon. So if the decimal part of A1 is less than 0.5, the time stamp would be in the morning.
=if(A1-int(A1)<0.5,"before noon","after noon")
It is not clear from your question how sidereal relates to the data in your sample.
In assessing how many agents can be added to certain times of day without exceeding the number of seats in the call center, I'm trying to discern how many agents are scheduled for each half hour interval on each day of the week.
Using the =SUMPRODUCT(((A$2:A$1000<=D2)+(B$2:B$1000>D2)+(A$2:A$1000>B$2:B$1000)=2)+0) formula I've been able to identify how many total agents work for each interval, however this doesn't take the day of week into account.
I currently have my spreadsheet setup this way:
K is the start time of the shift, L is the end time of the shift, M to S pulls data from another sheet that shows a 1 if the agent works on that day of the week and 0 if they do not, and then U has all the time intervals listed out. In the example, it's cut off but the columns continue down as needed. U goes to 49 and I've just been using a range from 2 to 500 for the others as we currently do not have that many shifts and I'm leaving space for the moment.
After some Googling, I tried =SUMPRODUCT(--(M2:M500="1"),(((K$2:K$1000<=U2)+(L$2:L$1000>U2)+(K$2:K$1000>L$2:L$1000)=2)+0)) but it only returns #VALUE! so I'm not sure what I'm doing wrong.
Any suggestions of how I can make this work? Please let me know if more information would be useful. Thanks.
=sumproduct(($K$2:$K$1000<=U2)*($L$2:$L$1000>=U2))
That will count the number of occurrences where the start time is less than or equal to the time in U2 AND the end time is greater than or equal to U2. It will check time from row 2 to row 1000. Any time one condition is checked and its true the comparison will result in value of TRUE and FALSE when its not true. The * act like an AND condition while at the same time converts TRUE and FALSE values to 1 and 0. So both conditions have to be true for a value of 1 to result. Sumproduct then totals up all the 1 and 0 to get you a count.
In order to consider the days of the week, you will need one thing to be true. Your headers in M1:S1 will need to be unique (which I believe they are). You will need to either repeat them in adjacent columns to M or in say V1 you have a cell that can change to the header of the day of the week you are interested in. I would assume the former so you can see each day at the same time.
In order to do this you want to add more conditions and pay attention to you reference locks $.
In V2 you could use the following formula and copy down and to the right as needed:
=sumproduct(($K$2:$K$1000<=$U2)*($L$2:$L$1000>=$U2)*(M$2:M$1000))
UPDATE #1
ISSUE 1 Time ranges ending the following day (after midnight)
It is based on the assumption that the ending time is later than the start time. When a shift starts at 22:00 and end at 6:30 as an example, our mind says that the 0630 is later than 22:00 because it is the following day. Excel however has no clue that 0630 is the following day and without extra information assumes it to be the same day. In excel date is stored as an integer and time is stored as a decimal. When you only supply the time during entry it uses 0 for the date.
In excel the date is the number of days since 1900/01/00. So one way to deal with your time out is to add a day to it. This way excel will know your out time is after your in time when the hour is actually earlier in the day.
See your sample data below.
Using your sample data, I did a straight copy of the value in L and placed it in M (=L3 and copy down). I then changed the cell display format from time to general. This allows you to see how excel sees the time. Note how all the time is less than 1.
In column N I added 1 to the value when the out time was less than the in time to indicate that it was the following day and we had not actually invented time travel. I also used the trick of a math operation will convert a TRUE/FALSE result to 1 or 0 to shorten the equation. I used =M3+(L3<K3) and copied down. You will notice in the green bands that the values are now greater than 1.
In the next column I just copied the values from N over using =N3 copied down, and then I applied just a time display format for the cell. Because it is only time format, the date is ignored and visually your time in column O looks the same as column L. The big difference is excel now knows that it is the following day.
you can quickly fix your out times by using the following formula in a blank column and then copying the results and pasting them back over the source column using paste special values.
=M2+(L2<K2)
The next part is for your time check. When looking at the 12:00 time you need to look at 1200 of the current day incase a shift started at 12:00 and you need to look at the 1200 period of the following day. In order to do that we need to modify the the original formula as follows:
=sumproduct(($K$2:$K$1000<=$U2)*($L$2:$L$1000>=$U2)*(M$2:M$1000)+($K$2:$K$1000<=$U2+1)*($L$2:$L$1000>=$U2+1)*(M$2:M$1000))
Note that the + in the middle of (M$2:M$1000) + ($K$2:$K$1000<=$U2+1)? This + acts like an OR function.
Issue 2 Time In/Out 15 minute increments, range 30 minute increments
You may be able to achieve this with the ROUNDDOWN Function or MROUND. I would combine this with the TIME function. Basically you want to have any quarter hour start time be treated as 15 minutes sooner.
=ROUNDDOWN(E3/TIME(0,30,0),0)*TIME(0,30,0)
Where E3 is your time to be converted
So your formula may wind up looking something like:
=sumproduct((ROUNDDOWN($K$2:$K$1000/TIME(0,30,0),0)*TIME(0,30,0)<=$U2)*($L$2:$L$1000>=$U2)*(M$2:M$1000)+((ROUNDDOWN($K$2:$K$1000/TIME(0,30,0),0)*TIME(0,30,0)<=$U2+1)*($L$2:$L$1000>=$U2+1)*(M$2:M$1000))
similar option could be used for the leaving time and rounding it up to the next 30 minute interval. In which case just use the ROUNDUP function. Though I am not sure it is required.
I have a set of dates, in total 7 periods spanning 6 months each with corresponding calculation factor.
I will have user input of period for which they'd want the calculation to be done, which can fall within one of the 6 months periods or encompass between two or more such periods wholly or partially.
Illustration:
The preset periods:
User input:
I've obtained decimal value (monthly basis) of the periods input by the user for calculation. For first instance (see user input), the decimal value for the period 01-01-2015 to 29-04-2015 will be 3.97 on monthly basis. The calculation for that period would be like:
n*3.97*113%
For the second instance, the decimal value for the period 30-04-2015 to 30-06-2015 would be 2.03, which would be used to do calculation at 113% and then the result will be added to the calculation done at 119% using the decimal value 5.65 for the period 01-07-2015 to 20-12-2015:
(n*2.03*113%)+(n*5.65*119)
Think I can handle the breaking up of periods since the revision event is bi-annual on particular dates but advice regards to that is welcome. More importantly, I need help tracing the preset calculation factor (say 132%) corresponding to the period input by the user as illustrated above. Is it feasible?
I will use the standard approach for finding the overlap between two dates and will split the task into three parts as in my answer to this recent question.
(1) The first part is finding the overlap between the user's range of dates and one or more revision periods in whole months and will need an array formula. I have chosen to use the Datedif function 1 to get the difference in months between the beginning and end of the overlaps. If there is no overlap, the start date fed in to Datedif will be after the end date, and it will return an error which can be trapped by Iferror. If the user's dates start in A2 and B2, this gives in C2:
=SUM(IFERROR((DATEDIF(IF(K$2:K$8>A2,K$2:K$8,A2),IF(L$2:L$8<B2,L$2:L$8,B2),"m")+1)*M$2:M$8,0))
which has to be entered as an array formula using CtrlShiftEnter
The above result includes the first and last months entered by the user even if they are incomplete months. It's then necessary to subtract any missing days in the first and last months.
(2) Missing days in first month as a fraction of the number of days in that month in D2:
=SUMIFS($M$2:$M$8,$K$2:$K$8,"<="&A2,$L$2:$L$8,">="&A2)*(A2-EOMONTH(A2,-1)-1)/(EOMONTH(A2,0)-EOMONTH(A2,-1))
A noted by OP, this could also have been done using sumproduct, vlookup or index/match.
(3) Missing days in last month as a fraction of days in that month in E2:
=SUMIFS($M$2:$M$8,$K$2:$K$8,"<="&B2,$L$2:$L$8,">="&B2)*(EOMONTH(B2,0)-B2)/(EOMONTH(B2,0)-EOMONTH(B2,-1))
The total is just (1)-(2)-(3) or
=C2-D2-E2
I have put the results of OP's two examples for comparison in H2 and H3: my results agree with them in the first 3 significant figures.
n*3.97*113%
(n*2.03*113%)+(n*5.65*119)
In all cases I have set n=1 and ignored the fact that the rate is a percentage.
This shows how the results would be calculated manually:
1 Pros of using Datedif:
(1) Works across year boundaries unlike just using Month function.
(2) Works conveniently with Iferror to identify non-matching date ranges.
Cons of using Datedif:
(1) It is an undocumented function and may be withdrawn in future.
(2) In this particular case, all date calculations are within the same year so Month would be useable.
I have a sheet that I use to calculate my taxes, deductions, and 401k based on a timesheet. It also calculates my PTO, sick, and comp days (I don't get overtime, when I work overtime I get that time back at the end of the year as extra paid days off). My issue is that with the timesheet, it's tough to calculate my sick days, all other times are hour for hour or based on the pay period. But with sick days I get a specific amount every year.
Basically, I get 10 days (80 hours) per year. So I take that 80 hours, divide it by 26, and that gives me how much sick time I get per pay period. Problem is, since I get a biweekly pay, that's not actually correct. So for example, this month I have 2 paychecks, I'd get .92 days of sick time, but I should actually get 1. On the 2 months out of the year where I have 3 paychecks I would get 1.38 days of sick time, which of course isn't correct either.
So the issue is I'm trying to figure out how to write a formula to give me the the correct number of days. Refer to the screenshot:
So basiclaly on G6, the formula takes the rolled over sick days from the previous year (G39) and adds the current sick time to it. It decides that by checking if the gross pay for that pay period is there, then multiplies that amount by the sick time accrual rate (G40) and divides that by 8 to give me the days.
But what I want to do is to check how many months have been filled out and return that. So in this example May has been completed, so it would return 1 day. Since September has 3 pay periods, you will need to have all three September paychecks filled out for it to increment from 4 to 5 (may, jun, jul, aug makes 4).
Any ideas? Everything I've tried to do this it just fails. Keep in mind that those dates are dynamic, next year when I change the start date for the tax year, the months that have 3 months will change to match the actual pay periods for that year. So this formula will need to actually be able to count that any month has 3 pay periods to advance the sick day count, otherwise to do it if there are only 2 that have been filled.
Attempt #2 to answer! >8(
The end equation to do this all in one cell is going to get ugly,but it will work. In order to explain this and basically how I developed it, I am going to break it down into parts. At the end the parts will be back substituted into the big equation.
The first thing I did was determine what row was last filled, or as per the comments what is the last row of column P that has a value greater than 0. In order to determine this I used the aggregate function in a temporary cell of T15 (yes, in the middle of your spreadsheet but it wont matter in the end):
=AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)
To break this function down:
14 tells it we want to do an array type calculation sorting the array from largest to smallest.
6 tells it to ignore errors
(P5:P30>0) tells it to build a true (or 1) and false (or 0) array of cells greater than 0
(ROW(P5:P30)-ROW(P5)+1) generates an array listing row numbers
1 tells it to return the largest value in the array, if it was 2 the second largest.
Now the important thing here is what happens when you multiply the greater than 0 array with the row number array. You wind up getting only the row numbers where there is a value in P greater than 0. And when we sort that and ask for the largest number we get the last row you have completed. Something to work with.
So now we can look up the last date completed, do some checks to see if its the end of the month or not and figure out how many sick days. The ugly formula starts out as:
=IF(MONTH(INDEX(I5:I30,T15))=MONTH(INDEX(I5:I30,T15)+14),MONTH(INDEX(I5:I30,T15))-1,MONTH(INDEX(I5:I30,T15)))
The logic test here is to find our if the last filled out date and the date 14 days in the future are still the same month. If they are the same month, you are not at the end of the month yet and there for have only earn up to the previous month's number in sick days. As such this part will tell us the previous month's number os sick days:
MONTH(INDEX(I5:I30,T15))-1
Now if the date 14 days in the future is not the same month then we know the last entry for the month has been completed and therefore we have accrued that month's number in sick days and use basically the same formula:
MONTH(INDEX(I5:I30,T15))-1
well I can see we have called on cell T15 4 times just to determine if we are subtracting 1 or 0. While the IF formula may feel more inline with your thought process, we can rearrange things and still get the same results but shortening the formula, reducing the calls to cell t15 by 1 and dropping the IF all together. This only works because we are dealing with 1 and 0 which is also true and false.
=MONTH(INDEX(I5:I30,T15))-(MONTH(INDEX(I5:I30,T15))=MONTH(INDEX(I5:I30,T15)+14))
Now lets bypass that T15 calculation and back substitute it in to the month formula above to get:
=MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)))-(MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)))=MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1))+14))
Not done yet. That only tells you the number of days you have accrued this year. Not what you really want to know. you need to convert it to hours. It also need to be reduced by the number of sick days used. The following need to be added to the big ugly above:
*8 for 8 sick hours to a sick day
-sum($L$5:$L$30) to account for sick time used
this results in:
=(MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)))-(MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)))=MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1))+14)))*8-sum($L$5:$L$30)
Now I did notice during testing that if no entries are in the spreadsheet, then the row of the last entry become 0 and this is simply not acceptable as it causes some strange results. So we will wrap this whole formula in a small error catcher to make sure 0 is the results when no payperiods have been completed.
=if(sum(P5:P30)=0,0,(MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)))-(MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1)))=MONTH(INDEX(I5:I30,AGGREGATE(14,6,(P5:P30>0)*(ROW(P5:P30)-ROW(P5)+1),1))+14)))*8-sum($L$5:$L$30))
The icing on the cake is adding on the accrued sick days from the previous year. Since I am not sure how the sick rate and sick start work together I will leave that calculation up to you and simply let you know that whatever number gets carried over from the previous year, simply add it to the above formula after the very last ).
Here is my test bed showing proof of concept:
WARNING: This method ##WILL## produce false results for a pay period is =0 before the last date with a pay period >0 see example below:
I I'm have small headache caused today by excel and the way it takes control of everything. I have two time values I need to add together then divide by a value I got charged for that time to work out how much it cost me an hour.
so say I was charged day on for 12:30:00
on day 2 I was charged for 13:20:00
and day 3 I was charged for 20:30:00
In total it cost me £1000
The calculation would be
£1000 / (12:30:00 + 13:20:00 + 20:30:00 = 46:20:00)
I would guess to get the answer I would
1000 / Sum(12:30:00+13:20:00+20:30:00) = price per hour
But it doesn't...
I guess I need some sort of convert function on the time or to divide it by 24 to get hours but I'm stuck
Help would be hugely appreciated!
Excel represents times as fractional days, so your function is actually representing the rate per day.
Assuming your times are in cells A1:A3, you can adjust your function to something like:
1000 / Sum(A1:A3) / 24
which will give you the rate per hour (by my calculations, £21.58/hr).
As others have mentioned, you will need to set the cell to a currency format.
Excel should be performing the calculation correctly, but it is just showing as a time. Format the result cell as "number" instead.
You can use the HOUR and MINUTE functions to get the hour and minute portions of the time values, however as lc mentions, you do need to ensure that the formatting of the cell is set to Number, as it will default to a time.
Assuming you have your hh:mm:ss values running down the page (column A), in the next column put the formula
=(A1-INT(A1))*24
underneath this you can put your formula
= 1000 / SUM(A1:A3)
but don't forget to format it as Number.