Attributing values depending of another value w/ VBA ? Excel 2010 - excel

First of all, sorry if it already exists but I can't find the words in English to describe rapidly my question, hence I don't know how to search for it. Skip to third paragraph if you only need the question.
I'm using Excel to build a complete document about my work hours (arrived at, finished at, if I've been late and of how long was I late, overtime, etc etc).
I'm using VBA to smooth this task.
My workplace cuts everything into quarter of hours, which means that if you're late by one minute, you'll lose 15 minutes. If you work overtime for 14 minutes, it won't be seen as overtime. If I point at 07:45 (I'm using 24H format, not AM/PM) I'm fine. If I do it at 07:46 it'll be counted as 08:00. Same with 16:14, it'll show up as 16:00 (details are shown but on the corrected sheet used for salary, it'll show this way). If I do it at 16:15 I've confirmed my 15 minutes of overtime.
So while I could do some workarounds, what I've got in mind is shitcode, really. I'd like to know a good (clean) way to do this : I want for every timestamps I input to be cut in degressive quarter of hours (for instance, I want 17:12 to show up as 17:00 or 08:57 as 08:45).
Thanks for your help, if you didn't understand something or doubt about something I've said, it's probably because of the way I explained it, please ask whatever's needed :)
Update 01: Values are indeed Time processed by Excel, not Strings looking like a timestamp.
Update 02: Solved by #FunThomas with TimeSerial-command and some explanations. Thanks, I hope this can be of help for future reference, however I lack the words to write a better title for this problem.

Assuming that you data is really time (and not a string that looks like time) and is stored in Cell A1, you can use a formula like this:
=TIME(HOUR(A1), INT(MINUTE(A1)/15) * 15, 0)
The time-command gets three paramater (hour, minute, second).
The hour-part is simple.
For the minute, we make an integer division by 15 (resulting in values from 0..3) and multiply it back with 15 (to get 0, 15, 30 or 45).
The second is simply set to 0.
Update:
As VBA-function:
Function roundTime(t As Date) as date
roundTime = TimeSerial(Hour(t), Int(Minute(t) / 15) * 15, 0)
End Function

Related

Excel subtract X days from date and then find last specific workday date

here's my problem:
We have an Excel sheet at work in order to manage various tasks all set on individually specified timelines - we're talking hundreds of tasks per month with dates that are currently all being maintained manually.
Let's say we have Task A and that task has a Due Date. That Task is split into several subtasks, all with their individual due dates. Date 1 would then always be Due Date - 10 days, Date 2 would be Due Date - 20 days, Date 3 would be Due Date - 17 days and so on. This then creates a neat timeline of when everything needs to be done.
That in itself would be easy enough, problem is that all of these subtasks have to be done on a specific workday as well. Meaning that subtask 1 would not only have to be done Due Date - 10 days, but it would also have to fall on a Monday - if for whatever reason Due Date - 10 would happen to fall on like a Wednesday, it would have to subtract another 2 days. And then the real problem is that Date 2 and 3 each have to fall on different workdays and Task B has an entirely different schedule again.
Now, the first thing that came to my mind was attempting to just nest a couple IFs - and I've even managed to come up with a working formula for that. Problem here is that it's so stupidly long and (thanks Excel) utterly unreadable - if for some reason someone else had to change something about it or troubleshoot the entire file 1-2 years from now, they'd probably have to spend at least an hour reconstruct how the hell any of it actually worked. Which doesn't sound particularly appealing to us.
Here's a screenshot to help illustrating the situation:
And here's a draft of the current formula that I'm really not happy with, despite it somewhat doing the job:
=IF(AND(WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11)>5,VLOOKUP(B2,Table1,5,FALSE)=0),(K2-VLOOKUP(B2,Table1,3,FALSE))-(WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11)-5), IF(VLOOKUP(B2,Table1,5,FALSE)=0,K2-VLOOKUP(B2,Table1,3,FALSE), IF(WEEKDAY((K2-VLOOKUP(B2,Table1,3,FALSE)),11)=0,K2-VLOOKUP(B2,Table1,3,FALSE), (VLOOKUP(B2,Table1,5,FALSE)-WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11))+K2-VLOOKUP(B2,Table1,3,FALSE))))
My question is now: Does anyone have an idea how to solve this in a less confusing and unclear manner? I was trying to get something done using =CHOOSE() but ultimately ended up with the same problem of eventually having to resort to 7 IFs and dozens of LOOKUPs, making the final formula just as long. I wouldn't be disinclined towards some kind of helper table that asigns the last 7 days and their workdays to every single day of the year... but I don't think tossing another 20,000 calculated cells into a file that already has tens of thousands other calculated cells would really be a serviceable alternative... or make the situation any less obscure at all tbh.
So, anyone any idea how to go about this? Or is there really no realistic alternative than to use a bunch of IFs?
Edit: Forgot to mention that 1 special case:
There's also the situation when a date doesn't have to fall on a specific workday - in which case it's simply due date - X days. The problem here is that in those cases the dates could fall on a weekend, so the formula would have to move these dates to the previous Friday as well.
Assume you have some date and you want to "back up" ten days and then to the preceding Monday, unless the resultant date is a Monday. The general formula would be something like:
=A2-10+1-WEEKDAY(A2-10-DOW)
Where DOW translates into
Sunday=0
Monday=1
Tuesday=2
...
You should be able to modify your formulas to use this algorithm for day of the week.
If the two tables are named thisTable and keyTable, the following 365 formula is one way of implementing:
If your tables are as below, you can enter the formula in B2 and fill down and across. The references should self-adjust and return the proper dates.
Note that in keyTable, I enter the day of the week DOW as defined above, and not the textual date.
=LET(dys,VLOOKUP(thisTable[#[Task]:[Task]],KeyTable,COLUMNS($A:A)*2,FALSE),
dow,VLOOKUP(thisTable[#[Task]:{Task]],KeyTable,COLUMNS($A:A)*2+1,FALSE),
due,thisTable[#[DueDate]:[DueDate]],
IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+1-WEEKDAY(due-dys-dow)))
If you want to have the result be the closest workday, instead of the preceding workday, then you need to add two clauses to the LET function
Calculate the subsequent workday date
Then use an IF to return the closest one to the original target
eg:
=LET(dys,VLOOKUP(thisTable[#[Task]:[Task]],KeyTable,COLUMNS($A:A)*2,FALSE),
dow,VLOOKUP(thisTable[#[Task]:[Task]],KeyTable,COLUMNS($A:A)*2+1,FALSE),
due,thisTable[#[DueDate]:[DueDate]],
dayPrev,IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+1-WEEKDAY(due-dys-dow)),
daySubseq,IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+7-WEEKDAY(due-dys-1-dow)),
IF((daySubseq-due+dys)>3,dayPrev,daySubseq))

Excel Time addition

First time poster and new joiner.
So I’m having a little difficulty is attempting to take a “lapsed time” with a format of 0:00:00 from a stated time (in this case I’m using a time stamp)
What I would like to achieve is the following.
Let’s say I attain some data from an external source that shows me the lapsed time someone hasn’t been logged In from their expected time. Now unfortunately the time due isn’t readily available so I want to put in A1 (CTRL + shift and ; for my time stamp) and then in B1 I want to minus the lapsed time. And in C1 a subtraction formula that will give me (there or about a the time that should be due to log in)
The issue I’m facing is this, I’ve tried a simple minus, a TIME function and both give a value error
I’m unsure whether firstly the fact that my time stamp being only hours and minutes is an issue but also when I attempt to remove the seconds from the lapsed time it won’t easily format out without manual input from me.
I feel like I’m being stupid here but cannot seem to get say;
14:55 to minus 0:25:00 to give me 14:00 !!
For clarity I have tried to format the time to include seconds but still not use...
Is there an easy way to conver the lapsed time to minutes for easier use of TIME ?
14:55 to minus 0:25:00 to give me 14:00
I think you wanted to say "... to give me 14:30".
Well, you can do subtraction of time values:

Calculate if time period is contained within a start and end time

I have a problem where I am trying to calculate in Excel if any part of a provided work duty time period is contained within a user defined period which specifies the night working hours e.g. 2330-0559 or 0000-0630.
If I provide a work duty time I want and any part of the duty is within the specified period it needs to be identified. E.g. 2230-0630 duty time is within both examples above.
I can tried a few different solutions and still not got the right way solve it.
Maybe someone can help. I also know that 24:00 in excel is used for midnight at the end of the day and 00:00 is used for midnight starting the day as excel works from 0-1 as part of the day.
=OR(MOD(A5,1)>$E$2,MOD(A5,1)<$F$2)
I would work with the number of minutes as decimal and with it make a valid range from "Duty start time" and "Duty end time".
Check if you can make any sense out of this:
Here the example:
https://drive.google.com/file/d/1O1B76srlY8sYQHsV_TiZVzi-7B_18eSj/view?usp=sharing
Update: Sorry for the lack of explanation. Here I try my best to clarify how I did it.
Conversion
First of all I try to convert any time into minutes, so 00:00 is 0 minutes, 01:00 is 60 minutes, 24:00 (excel shows 00:00) is 1440 minutes, 25:00 (excel shows 01:00) is 1500 minutes.
That conversion I do with CONVERT(E2,"day", "mn"), which does convert from day to minutes.
Range Normalization and inclusion
Now every range has to be normalized, that means the "End" has to be always bigger than "Start". For 00:00 to 06:00 this works fine, but for 22:00 to 06:00 it needs to be tweaked. So if "Start" is bigger than "End" then I add 1440 mins (24 hours) to "End". That I do with IF(A6>B6, 1440,0).
You then need to see if any "Duty range" contains the "Night range". That normally is done with the formula if (DutyEnd > NightStart AND DuttyStart < NightEnd) then TRUE.
Challenge 1
That was the main concept. But then if you try to compare a range like 00:00-06:00 contained in 24:00-06-00 it does not work. And that is because the converted minutes are 0-360 and 1440-1830, they don't contain each other.
In E3 to fix this I cut down 1440 with modulo (MOD()), then MOD(1440, 1440) = 0. So even if you use values like 25:00 or 52:00, they will be cut down to the smallest amount of minutes. E.g. 25:00 (1500 mins) = 1:00 = 60 mins, 52:00 (3120 mins) = 4:00 = 240 mins
Challenge 2
We have yet another challenge, the possible comparisons are as follows:
00:00-06:00 contained in 00:00-06:00 which in minutes is 0-390 contained in 0-390
00:00-06:00 contained in 22:00-06:00 which in minutes is 0-390 contained in 1320-1830
22:00-06:00 contained in 00:00-06:00 which in minutes is 1320-1830 contained in 0-390
These last two will not match. So that is why in the "Contains" column (E.g.: E6) I compare against the "Night criteria" - 1400 and + 1400.
Hope it is a bit clear. Let me know otherwise..
UNDERSTANDING DATE AND TIME IN EXCEL
Dates in excel are stored as INTEGERS. They represent the days since 1900/01/1 with that date being 1.
Time is stored as a decimal which represents a fraction of a day. 24 hours is 1, 0.5 is 12 noon. etc.
In other words, everything to the left of the decimal is date and everything to the right is time.
JUST USING TIME AND CROSSING MIDNIGHT
This is problematic from the view point that early morning times are less than the late times of the previous day. The fact of the matter is that they are larger. In our heads we do the mental math of knowing the are the following day but we ignore the date aspect.
A quick way to rectify this is to add the date to your time. Life will become much easier with the math. You may however not want to add full dates to start and end times. WITH THE ASSUMPTION that start and end times are not more than 24 hours the simple work around is is to add 1 to the end time when the end time is less than the start time. This means its the next day.
It the example date you provided, column C was insert to CORRECT the end time. It did the check of end less than start if so add one using the following formula:
=B6+(B6<=A6)
The part in brackets is a logic check. It either evaluates to TRUE or FALSE. When excel runs a boolean (TRUE or FALSE) through a math operator (not a function like sum) it will convert TRUE to 1 and FALSE to 0.
LENGTH
Straight forward math of C minus A since C is always after you start and is the larger of the two numbers.
=C6-A6
CROSSING MIDNIGHT
Need to be a little careful in your definition of crossing midnight when a start time or end time is exactly midnight. Technically speaking you did not cross it if you start or stop on it. The difference is really < versus <= or > versus >=. I will leave that to you to sort out. For the math I used:
=AND(A6<1,C6>=1)
Though I did not use this column for anything else
START CHECK
=OR(A6>$F$2,A6<$G$2)
END CHECK
=OR(B6>$F$2,B6<$G$2)
ANY TIME CHECK
I broke this into three columns. It can be combined into one but wanted to show the working parts. The first check is to see if the start time is before the night start and that the shift end time was after the night start time. The second check was similar for the the fisrt except you want to know if the start time is before the night end time and the shift end time is after the night end time. For the OR case you want to check to see if ANY of columns F through I are true:
COLUMN H
=AND(A6<=$F$2,C6>$F$2)
COLUMN I
=AND(A6<$G$2+1,C6>$G$2+1)
Note the +1 for night end time. This is to reflect that the end time is actually on the following day.
COLUMN J
=OR(F6,G6,H6,I6)
or
=(F6+G6+H6+I6)>=1
Place the above formulas in row 6 and copy down as needed
Well, I think I'm missing something but let's see if this works for you. To make this work:
All hours must be typed in hh:mm format
Night Criteria End must be on a different day. This means it must be over 00:00 or formulas won't work. If you type something
like start criteria=22:00 and night criteria= 23:50, both times
would be in the same day, so formulas won't work
This formulas only work in periods less than 24 hours. If anytime the different between criterias is over 24 hours, formulas won't work
properly.
Now, I replied your data like this:
The trick here is dealing with times without dates. Dates in Excel are înteger numbers and decimal parts are the hours/minutes/seconds. So to compare properly hours like this, you need to add an integer part.
Let me explain. In Excel, 18:00 would be 0,75. And 06:00 would be 0,25. If you try to get the difference between both times, you will get -0,5. In decimal it makes sense, but when trying to convert to time, it makes no sense for Excel. So, as I said before, the trick here is adding integers (in this case, because 06:00 is lower than 18:00, we would add +1), so Excel would make 1,25 - 0,75 = 0,5. And Excel can convert 0,5 to hours, and it will return exactly 12 hours, the right result.
So knowing this, the trick in formulas for your data is comparing ends with starts and add 1 or 2 to compare then properly with your criteria. That way Excel can figure out if a time is later or sooner than a criteria.
All my formulas are these ones:
LENGHT: =IF(B5<A5;B5+1-A5;B5-A5)
CROSS MIDNIGHT: =IF(Y(B5<A5;B5<>0);TRUE;FALSE)
START BETWEEN CRITERIA: =IF(AND(IF(A5<$E$2;A5+2;1+A5)>=1+$E$2;IF(A5<$E$2;A5+2;1+A5)<=$F$2+2);TRUE;FALSE)
END BETWEEN CRITERIA: =IF(AND(IF(B5<$E$2;B5+2;1+B5)>=1+$E$2;SI(B5<$E$2;B5+2;1+B5)<=$F$2+2);TRUE;FALSE)
ANY PART:=IF(OR(E5=TRUE;F5=TRUE;AND(A5<$E$2;A5+C5>1+$F$2));TRUE;FALSE)
Anyways, I uploaded a file to my Gdrive, in case it may be helpful to download and check the formulas.
This is the best I got. Probably there is a better way, but I hope this can help you, or at least, you can adapt it to your needs.
https://drive.google.com/open?id=1nrZKfyUhED_y6iiPRSUwRf7GhJlBYt-O

Repair incorrectly formatted time 'hh:nn:ss' when h=0

I'm doing a report which calculates people's time to determine their pay. We pull reports from our servers and paste them into Excel to do the calculations. I have run into an issue when pulling the data: if the time they logged in for was less than an hour our formula is not working:
=IF(E159="","",((HOUR(E159)+(MINUTE(E159)+(SECOND(E159)/60))/60)))
This gives an error (#value) if the time is :34:15, but if it's 00:34:15 then it's fine.
Formatting the cell does not appear to work.
I'd like to go through this column and add the 00 to all values missing it, and I need some help or guidance from there.
Another question on SO looks like it may help, but I'm unsure on how to use it.
Assuming that The tiem is in cell E159 from your above formula, you can append a 0 to the start of the time. This will fix all the times that have the hour missing and won't affect the other lines.
="0"&E159
You can then replace all of the E159 references in your original formula with this edit so that it looks like this:
=IF(E159="","",((HOUR("0"&E159)+(MINUTE("0"&E159)+(SECOND("0"&E159)/60))/60)))
While it's hard to read, it does the trick.
While that answers you question.. I think that there is a better way to achieve this formula.
It looks like the end result you're looking for is the time converted to hours, with mulutes and seconds as a decimel to the next hour. You can achieve this by doing:
=E159*24
Which will give you the same result as your original formula.
And then to combine that with my first answer to get a formula that looks like:
=("0" & E159)*24
This approach is much easier to read / edit and provides the same output.
Why This Works
Excel stores all dates as whole numbers, and all times as a decimel % to a day.
So when Excel is stores 12 hours it saves it as .5 because it is half of a day.
By dividing the time output by 24 we are converting the entire time value down from a % of day to a % of hours.

Converting TEXT that represents NEGATIVE TIME value to a number or time value for adding (Excel)

I've got a spreadsheet (Office 2007 version of Excel) full of text entries that are negative time values, example "-0:07" as in an employee took 7 mins less to complete a job than expected. I need to perform mathematical calculations on these entries and am looking for a more elegant formula/method than I've come up with so far.
I know about 1904 date system and * or / by 24 to convert back and forth, the problem is getting a formula that will recognize the text entry as a negative time value.
I've tried value(), *1, which both work on the text fields if the number is positive, but the "-" seems to mess those up. Even paste-special/add fails to recognize these as numbers.
Here's what I came up with that gets the job done, but it's just so ugly to me:
=IF(LEFT(E5,1)="-",((VALUE(RIGHT(E5,LEN(E5)-1)))*-1.0),VALUE(E5))
Obviously my text entry is in cell E5 in this example.
This works, so I'm not desperate for a solution, but for educational purposes (and smaller code) I'd like to know if there's a better way to this. Does anyone have a suggestion for something shorter, easier?
Thanks.
P.S. - an interesting tidbit here, I use Excel at work, but not at home, so I uploaded a sample spreadsheet to Google Docs, and it actually handles the Value() command on those entries properly. Weird, huh?
Thanks again for any suggestions.
Excel doesn't handle time spans in cells. It only deals with time. When you do "00:07" it is then converted to 0.0048611 which is the same as Jan 1st 1900 12.07 am. So if you did 2 minutes minus 7 minutes it would give at best 11.55pm.
The way you do it is the only way.

Resources