Problem in avoiding overlapped bookings in my booking system application - vb.net

If a booking is present in database on 12/27/2011 at 5:00 pm for 2 hours and i try to make a new booking on 12/27/2011 between 5 to 7 pm then my code generates an error message. Even if i try to book at 4:00 pm for 2 hours it generates an error message as the 2nd hour will be overlapped here with already made booking from 5:00 to 7:00.
Now here comes the problem part. When day changes it doesn't generate error message i.e. IF a booking is there on 12/27/2011 at 11:00 pm for 3 hours then it should not allow new booking till 12/28/2011 2:00 am but when i try to book 12/28/2011 at 1:00 am it saves it in the database and doesn't generate an error message. I want an error message generated in such a case.
I am using two separate fields in database one for time and one for date. Both of them have DateTime datatype.
newtime refers to time on which i'm trying to make new booking
addednewtime refers to time after adding the duration to time on which i'm trying to make new booking
addeddbtime contains just time value (after adding duration for booking in database) extracted from datetime field stored in database
newdate refers to the next date as the day changes at 12:00 am so if database booking is at 11:00 pm on 12/12/2011 then new date will have 12/13/2011 in it
Problem lies in the last part of the If condition which checks overlapped bookings when a booking spans over two days
Here is my code:
Dim newtime, addednewtime, addeddbtime, changetime, newdate As DateTime 'defines variables
addeddbtime = dbonlytime.AddHours(dbdur)
newtime = TxtBookTime.Text
addednewtime = newtime.AddHours(TxtBookDur.Text)
changetime = "12:00:00 AM"
newdate = dbdate.AddDays(1)
If TxtBookDate.Text = dbdate And TxtPoolNo.Text = dbpoolno And TxtCrtNo.Text = dbcrtno And TxtTblNo.Text = dbtblno And CmboGame.SelectedItem = dbgame And ((newtime > dbonlytime And newtime < addeddbtime) Or (addednewtime > dbonlytime And addednewtime < addeddbtime) Or (newtime < dbonlytime And addeddbtime > changetime And addednewtime < dbonlytime And addednewtime <= addeddbtime And TxtBookDate.Text = newdate)) Then
MessageBox.Show("The date and time you have entered has already been booked " & vbCrLf & " Try Again!", "Bookings Overlapped", MessageBoxButtons.OK, MessageBoxIcon.Stop)
Exit Sub
End If

Want you want to do is have a routine which checks for overlappings between the current booking and existing ones. You should have a method for this, with the following input values:
Current booking dates
List of existing bookings
Let's say you have a class called Booking which has begin and end DateTimes (no need to have separate fields for date and time, a DateTime object contains both).
Public Class Booking
Public Sub New(ByVal beginDate As DateTime, ByVal endDate As DateTime)
Me.BeginDate = beginDate
Me.EndDate = endDate
End Sub
Public Property BeginDate As Date
Public Property EndDate As Date
'Other booking properties here
End Class
You could have a routine like this which checks if there is an overlapping with an existing booking:
Private Function BookingOverlapping(ByVal booking As Booking, ByVal existingBookings As IEnumerable(Of Booking)) As Boolean
For Each existingBooking In existingBookings
If booking.BeginDate < existingBooking.EndDate AndAlso booking.EndDate > existingBooking.BeginDate Then
Return True
End If
Next
Return False
End Function
Then you would use the method like this:
' Figure out begin and end DateTimes from user input,
' then create a booking object.
Dim currentBooking As New Booking(beginDate, endDate)
' The GetExistingBookings method would retrieve bookings from the database
' and add new Booking objects to a list.
Dim existingBookings As List(Of Booking) = GetExistingBookings()
If BookingOverlapping(currentBooking, existingBookings)
MessageBox.Show("The date and time you have entered has already been booked " & vbCrLf & " Try Again!", "Bookings Overlapped", MessageBoxButtons.OK, MessageBoxIcon.Stop)
End If

Related

The amount of possible working hours between two dates in MS Project using VBA

Is it possible to return the amount of possible working hours between a start and finish time in MS Project using VBA? For example if the start and end time was from 12pm to 5pm in the same day and there was a lunch break from 12:30p to 1:30pm than the value returned would be 4 hours (instead of the total time passed of 5 hours).
EDIT: Also can you count the total number of shifts (breaks) in a day using VBA?
Question #1: Calculate working hours between two dates
The Microsoft Project application object has a method called DateDifference which does just that--it calculates the working time between two dates and you can optionally supply a calendar object (the project calendar is used by default). The return value is in minutes, so divide by 60 to get hours.
Use the Intermediate Window* to test:
? Application.DateDifference (#3/11/19 12:00 PM#, #3/11/19 5:00 PM#) / 60
4
? Application.DateDifference (#3/11/19 12:00 PM#, #3/11/19 5:00 PM#, ActiveProject.BaseCalendars("24 Hours")) / 60
5
Note: The optional Calendar argument is a calendar object, not the name of a calendar and it must be a calendar in use by the active project.
* From the VB Editor, do Ctrl+G to bring up the Intermediate Window.
Question #2: Calculate the number of shifts for a given day
This function will return the number of shifts for a given day for a particular calendar. If no calendar name is supplied, the project calendar is used.
It works by using the fact that booleans can be converted to integers (False = 0, True = -1) to count the number of true expressions. Specifically, if a shift is used, the Start time is returned as a string representation (e.g. "8:00 AM"), but if the shift is not used, it is returned as an integer (0).
Function ShiftCount(d As Date, Optional calendarName As Variant)
Dim c As Calendar
If IsMissing(calendarName) Then
Set c = ActiveProject.Calendar
Else
Set c = ActiveProject.BaseCalendars(calendarName)
End If
Dim NumShifts As Integer
With c.Period(d)
NumShifts = -CInt(VarType(.Shift1.Start) = vbString) _
- CInt(VarType(.Shift2.Start) = vbString) _
- CInt(VarType(.Shift3.Start) = vbString) _
- CInt(VarType(.Shift4.Start) = vbString) _
- CInt(VarType(.Shift5.Start) = vbString)
End With
ShiftCount = NumShifts
End Function

Find the day given date and number of days

Am looking a function that would aid me to auto detect due date when duration period number is entered in duration textbox.Am having challenge since all the months do not end with same date number i.e. 31 as some end on 30.
NOTE: The function should be able to automatically calculate up to next year if lets say user inputs 3 while in November 2018 its means the duration period will go up January 2019
See the picture below
Dim start_date As Date = dtpStart.Value
Dim totalDays As Integer = 3 * 30
Dim ts As TimeSpan = start_date.Add(totalDays)
Dim end_date As Date = ts
I have tried the above but its giving me an error "value of type integer can not be converted to system.TimeSpan."
If i understand you correctly, if a user enters 3 you want to advance 3 times 30 days later from the start_date.
Dim start_date = dtpStart.Value
Dim end_date = start_date.AddDays(3* 30)
In terms of a function, you could have:
private function AddDays(Byval start_date as Date, Byval amount as integer) as Date
Dim end_date = start_date.AddDays(amount)
return end_date
end function
The usage would be:
Dim new_date = AddDays(dtpStart.Value, 3*30)

Earliest date in VBA/Excel gives 00:00:00

I have a set of dates pulled from a PivotTable (which can either be accessed straight from the PT or I can copy it into a new sheet - I'm not fussed either way) and I need both the earliest and latest date e.g.
Scheduled date
01/01/17
05/08/17
08/11/16
03/12/16
...
So all I want is for VBA to tell me that the earliest date is 08/11/16 and the latest is 05/08/17 (This is part of a macro that cycles through different versions of different assessments, so a manual fix won't suffice and the model is so large that an array formula in the sheet is going to make it ridiculously slow).
So far I have tried the following for the earliest date:
Dim AllDates As Variant
Dim NumberDates As Integer
Dim Earliest As Date, Latest As Date
Set AllDates = ThisWorkbook.Sheets("Pivot Table 5 - To Use").Range("A4:A203")
'Attempt 1
Earliest = WorksheetFunction.Min(AllDates)
'Attempt 2
Earliest = Format(Application.Min(AllDates), "dd/mm/yyyy")
'Attempt 3
Earliest = Format(WorksheetFunction.Min(AllDates), "dd/mm/yyyy")
'Attempt 4
Debug.Print CDate(Application.Max(AllDates))
Every attempt results in "00:00:00" so I'm assuming I am actually working with Date values (I doubled checked and ensured that the worksheets were formatted to the correct date format) but beyond that I am COMPLETELY stumped.
This worked for me:
Sub test()
Dim Earliest As Date
Dim Latest As Date
AllDates = "$A$2:$A$204"
Earliest = Application.WorksheetFunction.Min(ActiveSheet.Range(AllDates))
Latest = Application.WorksheetFunction.Max(ActiveSheet.Range(AllDates))
MsgBox Earliest & Chr(13) & Latest
End Sub

vb.net Refresh DatePicker value after everyday

I have this code under a Timer's tick event to refresh the value of a DateTimePicker after everyday/at 7:19 (tTmNow)
`Private Sub tmrNewDay_Tick(sender As Object, e As EventArgs) Handles tmrNewDay.Tick
If tTmNow.Text.Contains("7:19:") Then 'at this time pick yesterday's date
Dim ystd As String
ystd = Today.AddDays(-1) 'yesterday
dtPicker1.Value = ystd 'put yesterday's date into the date time picker
End If
End Sub`
Unfortunately, at the first run of the program, I achieve my aim successfully. But the second day (The program is to run everyday and pick yesterday's date), when picking the date, it adds the time; giving 19-04-2017 00:00:00, instead of 19-04-2017. Is there a way to refresh the contents of the DateTimePicker or is there an entirely new way of picking yesterday's date, day after day.

Selecting rows from Access database by date search criteria in VB.NET form

I have a very simple problem. I have a couple of datepicker controls on my VB.NET form and users select "startDate" and "endDate", and all rows from the related table are displayed which have an orderDate between the user's selected start and end dates.
The following is the relevant code:
Private Sub generate_report_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles generate_report.Click
Try
Dim con As New OleDb.OleDbConnection
con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\KHMSDB.accdb"
con.Open()
Dim sql As String
Dim selected As String = ""
Dim ds As DataSet = New DataSet
Dim adapter As New OleDb.OleDbDataAdapter
sql = "SELECT OrderDate AS `Order Date and Time`, Items AS `Ordered Items` FROM Orders WHERE Format(Orders.OrderDate,'mm/dd/yyyy') >= #" + startDate.Value.Date + "# AND Format(Orders.OrderDate,'mm/dd/yyyy') <= #" + endDate.Value.Date + "#"
adapter.SelectCommand = New OleDb.OleDbCommand(sql, con)
adapter.Fill(ds)
gridReport.DataSource = ds.Tables(0)
Catch ex As Exception
MsgBox("Operation failed. " + ex.ToString)
End Try
If I save a new row in the database under today's date, and I leave the "start" and "end" dates both as the default date (i.e. today's date), it doesn't show the new row I just saved. The new row entered today only shows up if I move the "start date" up to the 30th of November. Then I add a new row with date 12th December. Again, it won't show up when I select the end date to be >= 12 December, it'll only show up when I move the start date up to 1st December. I decided to enter a row dated 21st November, and running the query with start and end date both on 21st November shows up that row. I then entered a new row in January 8th.. and now any combination of moving up startDate and or moving down endDate just doesn't display the January order. What's going on?? I've actually already tried this code out before in November and it worked perfectly fine!
What could be the issue with this is the string format. I'm not sure if Access will convert the string to a Date and then compare or convert the Date to a string and then compare. You can try this:
Format(Orders.OrderDate,'mm/dd/yyyy') >= Format(#" + startDate.Value.Date + "#,'mm/dd/yyyy')
Or you could always just use the date directly,
OrderDate >= #" + startDate.Value.Date + "#"
Edit:, to do my due diligence, you really should be doing the query like this
OrderDate >= #StartDate
Then add this code
adapter.Parameters.Add("#StartDate", startDate.Value.Date);
Using parameters is important for robust code and to avoid the dreaded SQL injection attack.