Excel: Insert blank row if non consecutive date - vba

We have a process at work that runs every 31 hours and would like to have a column in an Excel 2010 spreadsheet that reflects the time and dates the process is due to run each day over the coming year e.g.
start date (Cell:A1):
10/31/2016 1:00
11/1/2016 8:00
11/2/2016 15:00
11/3/2016 22:00
11/5/2016 5:00
11/6/2016 12:00
11/7/2016 19:00
11/9/2016 2:00
11/10/2016 9:00
11/11/2016 16:00
11/12/2016 23:00
11/14/2016 6:00
I am currently using the formula: A2 =A1 + (31/24) to populate the dates and times in the column which appears to work ok. I need to insert a blank row between days that are not consecutive (in order to highlight that fact, to make it easier for the operators to read and not instigate the process at the wrong time!) which is where the difficulty lies. I am assuming that I will need a separate VBA function to step through each cell and compare the day date (ignoring time value.) in the previous cell, if day date is greater than 1 (as in not the following day.) insert a blank row.
I am looking for a solution to the following scenario but am struggling to get my head round it and would appreciate any guidance/ help anyone is able to provide.
Many thanks

You do not need a VBA Function for that, it can be accomplished with the function
A3 = IF(A2="",A1+31/24, IF(INT(A2+31/24)=INT(A2)+1,A2+31/24,""))
*For that to work, you will have to populate cells A1 and A2 manually, though.
You can use the INT() function to get the date part of a DateTime field, so it becomes simple to check if adding 31 hours will leave a 1 day gap in the sequence by checking INT(A2+31/24) = INT(A2)+1.
So, to explain the function, the part
IF(INT(A2+31/24)=INT(A2)+1,A2+31/24,"")
will check if the days are consecutive, and if so, it will fill the DateTime. If not, it will leave it blank.
The outer IF checks if the cell above is blank. If it is, the function will use the one above that.

Related

How to calculate time difference (in second) in excel vba for different group of unique values?

I know this question appears often previously, but what I have is in the different case. I have some data about date and time which is for two groups. I want to know the duration for each group, but I dont know how to write it in the Excel VBA codes. Could you please help me to solve it?
Here is my excel sheet. enter image description here
The hard thing is that when in the same group it has changed to other date but when I try to substract the difference, it can be minus not positive. for example :
02.09.2017 19:00:00
03.09.2017 01:00:00
In this case I can't substract 01:00:00 - 19:00:00 because that would be minus, thus I have to consider the change of the date. How can I solve it if it is the case? Thank you very much for the help.
If your cells are formatted as data and time, you can use DateDiff function, with "n" as the interval (represnting the dif in seconds).
I've tested with your data:
A1 02.09.2017 19:00:00
A2 03.09.2017 01:00:00
Code:
Option Explicit
Sub CalcSecond()
Dim NumofSec As Long
NumofSec = DateDiff("n", Range("A1").Value, Range("A2").Value)
MsgBox NumofSec
End Sub

Excel how to set a given value to date ranges

I need to automatically set a value of 8.45 hours work for the winter schedule (01 October till 15 June) and 6 hours work for a summer schedule (16 June till 30 September) for a time sheet done in Microsoft Excel.
The equation I am trying is the following:
=IF(AND(DATE($G$1,6, DAY(15))>=(DATE($G$1-1, 10, DAY(1))));(DATE($G$1,6, DAY(15))<A8;8.45;"")
But this keeps on returning formula errors and this still omits the rate value for the summer schedule.
$G$1 is the year that is manually inputted for the yearly time sheet.
A8 is the current date.
Any guidance into this equation would be appreciate.
With best regards Fab
Edit
Thanks DirkReichel, Scott Craner, Alex Bell, Michael Uray for your great intervention.
I tried all the suggestions but some returned a =VALUE error and some did not omit the winter schedule as from the 1 October ->
This is the correct equation:
=IF(AND(DATE($G$1,9,30)>=A8,DATE($G$1,6,15)<=A8),6,8.45)
The equation checks the current date being A8 and checks if it falls withing the summer period (date range). If current date falls within the summer period the value is returned to 6, if the current date falls outside the summer period, it returns a value of 8.45.
Thanks to all that guided.
Depends on the regional settings, you may use comma "," instead of ";" as shown in the following example:
=IF(AND(NOW()>DATEVALUE("6/15/2016"), NOW()<DATEVALUE("9/1/2016")),6,8.45)
Hope this may help.
Try this:
=IF(AND(DATE($G$1,6,15)>=A8,DATE($G$1-1,10, 1)<=A8),8.45,6)
The following solution should work for you:
A1 is the date which gets checked, the formula is placed in B1.
On this way you can pull down a list of dates and formulas in your sheet.
=IF(AND(A1>DATE(YEAR(A1),6,15),A1<DATE(YEAR(A1),8,1)),6,8.45)
It checks if the data is in the range of YYYY-06-15 and YYYY-08-01 and sets then the output to 6, or if it is not in this range to 8.45
I did test it with e German Excel Version with the following formula and I translated it then manually in Notepad to the English formula version.
=WENN(UND(A1>DATUM(JAHR(A1);6;15);A1<DATUM(JAHR(A1);8;1));6;8,45)
I hope my formula translation will work for you in the English Excel version.

When a start date and end date span more than one week, I need to split a row up in 2 or more new rows

I would like to begin by saying I'm quite new to sql.
That said, here is my question/problem:
I have a view that has two date columns, a variable column and a text column (for comments).
I need to be able to split up all rows where the two dates are not in the same week. And I need to be able to split the variable value as well, so that it gets evenly distributed, based on how many days were in each week. The comment must be copied as well, so to be shown in each row.
My dataset looks like this:
DateIn DateOut Amount Comment
2014-11-01 2014-11-08 600 Good
And what I want is this:
DateIn DateOut Amount Comment
2014-11-01 2014-11-07 525 Good
2014-11-08 2014-11-08 75 Good
And if the time period spreads over more weeks, I would need it to split up to equivalent number of rows.
I would be very greatful if somebody could take the time to tell me how to achive my goal, using an sql-query.
As this is my first post on the forum, I apologize for any format errors in my post.
First, you need a weeks table. I mean physical table or view, where exists one row for every week possible. (We have dates table here, +/- 30 years from now - allows easily create weeks view and similar).
Then you need link your data to weeks table with left join; join condition should check date ranges overlap with week date range (probably you have to have both week start and week end fields in your weeks table - makes comparisons easier).
Then you need to divide amounts between weeks. Because you know date range length, week length and overlapping date range length, this should be trivial :)

Sql Query To get data

i have a table called DrTimings ,in which Doctors time for each day is this.
DrID(int identity) StartTime(DateTime) EndTime(DateTime)
1 3/31/2009 8:00:00 AM 3/31/2009 10:30:00 AM
I have another table called TimeList which contain 3 fields
SlotID SlotStartTime(varchar) SlotEndTime(varchar)
1 8:00AM 8:15AM
2 8:15AM 8:30AM
3 8:30AM 8:45AM
and goes on till 7:00PM
I have another table DrDutyDetails in which DrTiming is set for whole month like this.
DrID StartTime EndTime DateOfAllocation
1 4/5/2009 8:00:00 AM 4/5/2009 9:30:00 AM 4/5/2009 12:00:00 AM
2 4/12/2009 8:00:00 AM 4/12/2009 9:30:00 AM 4/12/2009 12:00:00 AM
likewise
I have another table called AppointmentSchedule which gets filled when patient requests appointment
AppointmentID SlotID AppointmentDate
1 1 4/5/2009
2 3 4/12/2009
i have a appointment schedule form in which i selects DrID and Appointment date.Then slots corresponding to date that has not been in Appointmentschedule,but slots should be in between starttime and endtime that in DrTimings and in TimeSlots should get filled in a dropdownlist.I need a query to implement this.
for eg:If Patient enters '4/5/2009' Then slots other than 1 and 3 but biw DrTimings i want to get.
Similarly i want to search by time.Means if Patient enters any time b/w DrTimings for eg:8:30AM,Then available first date has to be displayed in textbox
You are going to need to look at doing some Casting/COnverting of date values. This MSDN article gives you a bit of information on what you need to work with.
There are a number of ways that you can do this, but ideally you can do something like CONVERT(VARCHAR(50), StartTime) to get the fully formatted time. Then, since you know that the ending format of that is 08:00AM, you can do a RIGHT(CONVERT(VARCHAR(50), StartTime), 7), which will get you just the time value.
Now, with that you know how to manipulate the date into parts, you can from here, do the various things needed to query your items.
For comparison sake, I would be storing the "TimeList" data as DateTime values, that way you can use standard time comparisons to actually allow you to use functions such as "Between" and similar. You could store them as 1/1/1900 08:00AM or similar. But this would require a data model change. If you want some helpful SQL for this type of thing, here is a great article on "Essential SQL Server Date, Time, and DateTime Functions".

How do I compare overlapping values within a row?

I seem to have a problem with this SQL query:
SELECT * FROM appts
WHERE timeStart >='$timeStart'
AND timeEnd <='$timeEnd'
AND dayappt='$boatdate'
The time is formatted as military time. The logistics is that a boat rental can be reserved at 7am til 1pm or 9am til 1pm or 9am til 5pm. If there is an appt within that range, it should return appts but it has proven to be inconsistent. If I pick 9am til 1pm, it will ignore appts that started with 7am even though it overlaps 9am-1pm. If I pick 9 to 5, it will return nothing even though it should with the 7am to 1pm. How do I make a SQL statement that includes the whole range from timeStart to timeEnd including those that overlap?
Shahkalpesh answered the question with:
I think you need an OR.
SELECT * FROM appts
WHERE (timeStart >='$timeStart'
OR timeEnd <='$timeEnd')
AND dayappt='$boatdate'
I posted a comment that I consider this to be wrong, giving a pair of counter-examples:
This is plain wrong - #ShaneD is correct. For example, this will pick out a booking between 05:00 and 06:00 because the actual end time is less than any of the end times you ask about. It will also pick up rentals from 18:00 onwards, for the equivalent reason.
In a response to my comment, Shahkalpesh requested:
Could you post a separate reply with data & input parameters with expected output?
Fair enough - yes. Slightly edited, the question says:
The logic is that a boat rental can be reserved
from 7am until 1pm, or
from 9am until 1pm, or
from 9am until 5pm.
If there is an appointment within that range, it should return appointments but it has proven to be inconsistent. If I pick 9am until 1pm, ...
Enough background. We can ignore the date of the appointments, and just consider the times. I'm assuming that there is an easy way to limit the times recorded to hh:mm format; not all DBMS actually provide that, but the extension to handle hh:mm:ss is trivial.
Appointments
Row timeStart timeEnd Note
1 07:00 13:00 First valid range
2 09:00 13:00 Second valid range
3 09:00 17:00 Third valid range
4 14:00 17:00 First plausibly valid range
5 05:00 06:00 First probably invalid range
6 18:00 22:30 Second probably invalid range
Given a search for appointments overlapping the range 09:00 - 13:00, Shahkalpesh's (simplified) query becomes:
SELECT * FROM Appointments
WHERE (timeStart >= '09:00' OR timeEnd <= '13:00')
This will return all six rows of data. However, only rows 1, 2, 3 overlap the time period 09:00 - 13:00. If rows 1, 2, and 3 are the only valid representative appointment values, then Shahkalpesh's query produces the correct answer. However, if the row 4 (which I think is plausibly valid) is permitted, then it should not be returned. Similarly, rows 5 and 6 - if present - should not be returned. [Actually, assuming timeStart <= timeEnd for all rows in the table (and there are no NULL values to mess things up), we can see that Shahkalpesh's query will return ANY row of data for the 09:00-13:00 query because either the start time of the row is greater 09:00 or the end time is less than 13:00 or both. This is tantamount to writing 1 = 1 or any other tautology in the WHERE clause.]
If we consider ShaneD's query (as simplified):
SELECT * FROM Appointments
WHERE timeStart <= '13:00' AND timeEnd >= '09:00'
we see that it also selects rows 1, 2, and 3, but it rejects rows 4 (because timeStart > '13:00'), 5 (because timeEnd < '09:00') and 6 (because timeStart > '13:00'). This expression is an archetypal example of how to select rows which 'overlap', counting 'meets' and 'met by' (see "Allen's Interval Algebra", for instance) as overlapping. Changing '>=' and '<=' alters the set of intervals counted as overlapping.
The correct check would look like this:
SELECT * FROM appts
WHERE timeStart <='$timeEnd'
AND timeEnd >='$timeStart'
AND dayappt='$boatdate'
Other good explanations have been given but I'll go ahead and update it with an alternative explanation of how I visualize this myself. Most people are looking for each possible overlap, considering two time periods, they are trying to think of each combination of start and end that can make an appointment overlap. I think about it as when do two time periods not overlap which for some reason is easier for me.
Say the time period I am checking for is today, I want to find any time period that does not overlap today. There are really only two scenarios for that, either the time period starts after today (PeriodStart > EndOfToday) or the time period ends before today (PeriodEnd < StartOfToday).
Given that we havea simple test for not overlapping:
(PeriodStart > EndOfToday) OR (PeriodEnd < StartOfToday)
A quick flip around and you have a simple test for overlap:
(PeriodStart <= EndOfToday) AND (PeriodEnd >= StartOfToday)
-Shane
Thanks Shane, Shahkalpesh, and Jonathan.
I actually overlooked the fact that Shane "swapped" the variables (I was still using timeStart<=$timeStart when it should be timeStart <= $timeEnd). I ran with the modified statement as Jonathan/Shane suggested and it works. As Jonathan did point out, I did obviously missed out some time ranges that I should have tested against.
Now with Jonathan's explanation, I now get a better picture of my mistake is and it's helpful.
I think you need an OR.
SELECT * FROM appts
WHERE (timeStart >='$timeStart'
OR timeEnd &LT;='$timeEnd')
AND dayappt='$boatdate'
Assuming each record cares about only a specific day.
i.e. Boats rented don't run across more than 1 day.