VBA queries return data beyond end date - sql

I am running a VBA query which returns data beyond end date .
The code is as follows:
startdate = Format(Sheets("sheet1").Range("B2").Value, "####")
enddate = Format(Sheets("sheet1").Range("B3").Value, "####")
Set conn = New ADODB.connection
Set rs = New ADODB.Recordset
connection = "provider = sqloledb ; data source = &user; initial catalog = &data ; integrated security = sspi ; "
conn.Open connection
Set rs = conn.Execute("select * from sale_table where datetime >= " & startdate & " and datetime <= " & enddate & "")
If Not rs.EOF Then
Sheets(1).Range("I12").CopyFromRecordset rs
Else
MsgBox ("no record")
End If
if enddate = 31/08/2016
result shown upto 02/09/2016 ( two days beyond end date)

Your date formatting is the problem:
startdate = Format(Sheets("sheet1").Range("B2").Value, "####")
enddate = Format(Sheets("sheet1").Range("B3").Value, "####")
These will produce date serials, or the number of days elapsed since January 1st, 1900. For 31/08/2016 (08/31/2016 for those in the US), your enddate will be 42613 when using Excel.
In SQL Server, you can either use DATEADD(DAY, ..., ...) or CAST( ... AS DATETIME) to convert this to a date. Implicitly, when you perform a logical operation against a date serial i.e. <= enddate or >= startdate it'll convert that serial into a datetime.
However, if you have tried DATEADD or CAST on 42613 in SQL Server you'll notice it returns 02/09/2016 (US: 09/02/2016) which is why your returned data is beyond the end date. Also, if you tried DATEDIFF(DAY, '2016-08-31', '1900-01-01') it returns 42611 on SQL Server; 2 days difference to Excel's interpretation of 31/08/2016 date serial.
Why is this?
Mr Chip Pearson explains it in Dates and Times in Excel, but I'll summarize it. Keep in mind that when I say date serial I mean days elapsed since 01/01/1900. Both in Excel and SQL Server, default date value is 01/01/1900. However:
Excel stores dates and times as a number representing the number of days since 1900-Jan-0
00/01/1900 (US: 01/00/1900) is not a valid date. So already we have to offset any Excel date serial by -1. Why so?
The number 1 represents 1900-Jan-1. It should be noted that the number 0 does not represent 1899-Dec-31. Actually, this number is one greater than the actual number of days. This is because Excel behaves as if the date 1900-Feb-29 existed. It did not. The year 1900 was not a leap year (the year 2000 is a leap year). In Excel, the day after 1900-Feb-28 is 1900-Feb-29. In reality, the day after 1900-Feb-28 was 1900-Mar-1 . This is not a "bug". Indeed, it is by design.
So, in your particular case, since date serial 1 represents 01/01/1900 in Excel (because date serial 0 is 00/01/1900) which is first of your extra 2 days and the leap year 2000 has 366 days rather than 365 which is your second extra day, that's why it's returning data up to and including 02/09/2016.
In short, you need to account for Excel's date representation as being days from 00/01/1900 rather than from 01/01/1900 and also any leap years when using an Excel date serial in a SQL Server statement.

Related

If using DateDiff function, using the interval "yyyy", is the function simply subtracting the difference between the year value of date1 and date2?

Macro does not appear to be taking days into account when calculating a person's age.
Sub alcohol_test()
Dim strBirthday As Date
strBirthday = CDate(InputBox("Input date of birth to be verified: ", "Date of Birth"))
If DateDiff("yyyy", strBirthday, Date) < 21 Then MsgBox ("Customer underage, sale of alcohol illegal.") _
Else MsgBox ("Age Confirmed: Alcohol may be sold")
End Sub
It is even worse:
When comparing December 31th to January 1st of the immediately succeeding year,
DateDiff for Year ("yyyy") returns 1, even though only a single day has elapsed, says Microsoft.
So you better compare two dates, e. g. if the birthday was before the day 21 years ago.
Dim datBirthday as Date
datBirthday = CDate(InputBox("Input date of birth to be verified: ", "Date of Birth"))
If datBirthday < DateSerial(Year(Date) - 21, Month(Date), Day(Date)) Then
I changed the variable name, as a beginning with "str" is a little misleading when you use date values.

Subtract 2 days from International Network Days in vba

I am trying to get 2 days behind the current date provided Saturday, Sunday and Holidays or not included.
Table where my holidays are stored - [DateTable[Holidays]]
I know it requires the usage of Application.NetworkDays_Intl, but I am not able to get the logic going.
Does Anyone know what is the easy way to achieve this >
The function NetworkDays_Intl takes a start date and an end date and calculates the number of workdays in the range. This forces a slightly cumbersome approach:
Dim StartDate As Date
Dim EndDate As Date
Dim Duration As Integer
Duration = 2
EndDate = CDate("2017-07-08")
' Pick theoretically latest start date
StartDate = DateAdd("d", -Duration + 1, EndDate)
' Step one day back until we get it right
Do While Application.NetworkDays_Intl(StartDate, EndDate) <> Duration
StartDate = DateAdd("d", -1, StartDate)
Loop
Debug.Print StartDate

Selecting phone calls in where date is today

I'm trying to retrieve phone calls from our Avaya database in SQL 2012 and i can't seem to get the dates on my code right.
cmdCalls = String.Format("SELECT * FROM dbo.tblCallList WHERE CreateDate > cast('" & DateYesterday & "' as date)")
This is my query string
Dim DateYesterday As Date = Date.Today.AddDays(<insert number of days>).ToString("yyyy-MM-dd")
I can't seem to pull the data i need from the database, it does subtract the days from the date variable but the problem is its using the days as months on the query and it shows all the records from the month instead of day
The Dates formats on the database are '2017-06-08 12:04::00:000' for example
Use the current date in the database:
SELECT *
FROM dbo.tblCallList
WHERE CreateDate >= CAST(getdate() as date);

VB.net work out number of days between two dates [duplicate]

This question already has answers here:
How to find the number of days between two dates / DateTimePickers
(3 answers)
Closed 6 years ago.
I am trying to work out the number of days between two dates and whether it is a full month or not.
I currently have this code:
Dim fromdate As Date
Dim todate As Date
Dim timespan
Dim num_days As String
Dim month As DateTime
fromdate = Date.Parse("01/01/2017")
todate = Date.Parse("31/01/2017")
TimeSpan = todate - fromdate
num_days = TimeSpan.Days
MsgBox(num_days)
And then I try to work out if it is a full month:
month = todate
If (month.Month = "02" And num_days = "28") Or num_days = "29" Or num_days = "30" Or num_days = "31" Or num_days = "0" Then
'do code here
Else
'do code here
End If
But this is proving to not work in February because it only sees the num_days as 27
Is there a way I can get the correct number of days between the two dates including the dates themselves being full days?
And how can I check if it is a full, correct month or not
UPDATE
The purpose of this is for a billing system so files are read into a database with from and to dates then it needs to work out the pricing from those dates.
So a product has a specific price, but first of all we need to work out whether to bill for part of a month or a full month (basically part of the product price or the full price)
So these 'Full Month' date range examples will bill the full price
Full Month:
01/01/2017 - 31/01/2017
25/01/2017 - 25/01/2017
18/01/2017 - 18/02/2017
10/01/2017 - 10/01/2018
Whereas, this date range for 'Part Month' will only bill for the number of days between the from and to date (+1 day)
Part Month
15/01/2017 - 31/01/2017
This would get what you specified:
Dim IsOneFullMonth = (d1.Day = 1 And d2 = d1.AddMonths(1).AddDays(-1))
Dim IsOnMonthLater = (d2 = d1.AddMonths(1))
The two states are not really the same thing in my understanding.
The second check is one month and one day.
(The first would match 'Jan 01 - Jan 31', the second one 'Jan 01 - Feb 01'.)
Also consider that neither check would match 'end of months' like 2016-02-29 - 2016-03-31 - you have to really define what you want to achieve in those cases.

Sales Year To Date From End Of Previous Week AND For Last Year

I am trying to write a query in Access to poll year to date sales records to build a report. I think I need to write a VBA module to calculate these dates.
I need a date range for Year to Date from Last Saturday (ex. from 1/1/2015 to 10/24/2015 for this week's report). I also need to poll the records from Last Year To Date (ex. from 1/1/2014 to 10/25/2014 for this week's report).
Any suggestions on how I can query this date range?
Thanks!
Consider using a temporary table such as a YTDDates of two fields (ID, SalesDate) that holds the date range which can be cleaned out per needed use. Then join your sales data to this table for daily reporting.
VBA can run a loop through all days from beginning (1/1/2015) to end (10/24/2015) and iteratively append to temp table using the DateAdd() function.
Dim db As Database
Dim startDate As Date, endDate As Date, d As Date
Dim diff As Integer, i as Integer
Set db = CurrentDb()
startDate = #1/1/2015#
endDate = #10/24/2015#
diff = DateDiff("d", startDate, endDate)
' CLEAN OUT PRIOR DATE RECORDS
db.Execute "DELETE FROM YTDDates", dbFailOnError
For i = 0 To diff
d = DateAdd("d", i, startDate)
db.Execute "INSERT INTO YTDDates ([SalesDate]) VALUES (#" & d & "#);", dbFailOnError
Next i
Set db = Nothing
Instead of a temp table I would just use a formula in your query using a BETWEEN clause on your date field with a formula like this:
vba.DateSerial(Year(Now()),Month(Now()),Day(Now())-Weekday(Now(),vbSunday))
The Weekday function returns an integer from Sunday (vbSunday). So on a Monday it will return '2' and on Saturday it will return '7' which will give you the previous week's Saturday date.
For getting the beginning of the year date you could use a function like this:
vba.DateSerial(Year(Now()),1,1)