In VB, what coding could I use to calculate the 5th working day of every month? And if the 5th day is a holiday to go up one day.
You would need a list of holiday dates with which to compare. You would need to build and store that list separately. You did not say what variant of VB (VBA? VB.NET?) but in VB.NET you could do:
Dim datevalue As DateTime = New DateTime(DateTime.Year, DateTime.Month, 1)
Dim dayIsFound As Boolean = False
Dim workDays As Integer
workDays = 1
While Not dayIsFound
If ( dateValue.DayOfWeek <> DayOfWeek.Saturday _
And dateValue.DayOfWeek <> DayOfWeek.Sunday _
And Not HolidayList.Contains( dateValue ) _
workDays = workDays + 1
End If
If index >= 5 Then
dayIsFound = True
Else
dateValue = dateValue.AddDays(1)
End If
End While
Technically, it is possible to build an algorithm that determines the major holidays based on Federal guidelines (in the US) but it is complicated and may not conform to the holidays of the company to whom you are building this component.
The problem has 2 main components - first you need a list of public holidays, and second you need to count days of the week which are working days in your locale.
You can hard code your holidays for a quick solution, and if you want this code to keep working without modification you will need to Google for some algorithms / functions to calculate your holidays. Here is a link to some sample calculation functions for holidays, including Easter. http://www.cpearson.com/EXCEL/holidays.htm
Your main function can use the VB functions Weekday and WeekdayName (if needed) in conjunction with your list of public holidays to count all days that fall on a normal working day which isn't in your list of public holidays.
Use Weekday function for Saturday and Sunday. Holidays are dependent on the location and country and you need to implement your own function for that.
You need to count each valid working day until you get to the fifth one. E.g.
index = 0
Do
If dateValue.DayOfWeek <> DayOfWeek.Saturday _
AndAlso dateValue.DayOfWeek <> DayOfWeek.Sunday _
AndAlso Not HolidayList.Contains( dateValue ) Then
index = index + 1
If index >= 5 Then _
Exit Do
End If
dateValue = dateValue.AddDays(1)
Loop
Related
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
Having some trouble locating a function to determine the week number of a quarter period in a standard date based (i.e. Day 1 = 2017-01-01) calendar table.
My table has the following information stored :
Quarter Number, Beginning Date, End Date, Number of Days;
As an example, for the first quarter of calendar year, the result for Week 1 would be 1, Week 14 would be 1, going through each quarter until the final week of quarter 4.
Any ideas please help?
I don't believe there is a built-in function for this. If I understand what you're asking, this is a trivial function to write. You don't include any code so I'm just giving you the most basic example. You want to do something similar to this.
Public Function GetWeekInQuarter(ByVal WeekNumber As Integer) As Integer
Const intWeeksInQuarter = 13
Dim intResult As Integer
intResult = WeekNumber Mod intWeeksInQuarter
'if intResult <> intWeeksInQuarter = 0 then this is the 13th week
GetWeekInQuarter = IIf(intResult <> intWeeksInQuarter, intResult, intWeeksInQuarter)
End Function
I'm currently working on a database that stores software licensing information such as software name, purchase date, cost, quantity, etc... After the software has been owned for 12 months, we must pay a maintenance fee.
My question therefore, is how to design a query that will take the purchase date and compute the next occurrence of that date to be stored in the maintenance date field. Ex) If a license was purchased on 12/31/1999, I would need to pay maintenance on 12/31/2016.
I don't have a lot of experience with MS Access or SQL queries, and after researching this for a while, I am not even sure this is possible. I would appreciate any help you guys could give me!
Here's a function that will do exactly this:
Public Function DateNextAnnualDay( _
ByVal AnnualDay As Date) _
As Date
Dim SomeDate As Date
Dim NextAnnualDay As Date
Dim Years As Integer
SomeDate = Date
NextAnnualDay = AnnualDay
Years = DateDiff("yyyy", AnnualDay, SomeDate)
If Years < 0 Then
' Don't calculate hypothetical annual days.
Else
NextAnnualDay = DateAdd("yyyy", Years, AnnualDay)
If DateDiff("d", SomeDate, NextAnnualDay) <= 0 Then
' Next annual day falls earlier in the year than SomeDate.
NextAnnualDay = DateAdd("yyyy", Years + 1, AnnualDay)
End If
End If
DateNextAnnualDay = NextAnnualDay
End Function
Here is the syntax
SELECT DateAdd("yyyy",1,[MyDate]) AS MaintDate
FROM Table;
If you need to do more complicated querying you can write a function in a module and then access it in a query using VBA. For instance you can iterate through a loop to match a condition
Function GetNextDate(ByVal dteOriginalDate As Date) As Date
While dteOriginalDate <= DateTime.Now
dteOriginalDate = DateAdd("Yyyy", 1, dteOriginalDate)
Wend
GetNextDate = dteOriginalDate
End Function
Will iterate adding one year from the original date to the point at which the date is in the future. You can the build it into a query (using right-click -> build) so that each row runs through your code and applied the logic.
This will allow you to store the original licence date in your database and calculate the next due date without having to know (or amend) the intervening years.
I want to use the Days360 function in VB.Net. I need to know the difference in days between two dates assuming 360 days in a year (not 365 days the DateDiff function uses).
For example DateDiff(DateInterval.Day,"16/10/2015", "04/02/2016") = 111 days, but Days360 should return 109 days.
Days360 function in Excel calculates the days between two dates using a fictional calendar that has 30 days in each month. This method is used for some financial purposes.
You can write a function to do the same calculation.
[Edit]
Excel supports two versions of the calculation: one common in the US (this is the default) and the other common in Europe (see the documentation of the DAYS360 function for details).
The code I originally posted implemented the European version. I have updated it to support both versions. Thanks to Nikhil Vartak for pointing this out.
Function Days360(startDate As DateTime, endDate As DateTime, euMethod As Boolean) As Integer
Dim months As Integer = (endDate.Year - startDate.Year) * 12 + endDate.Month - startDate.Month
If euMethod Then
'Use European method (start or end dates after the 30th of the month are changed to 30th)
Return months * 30 + Math.Min(30, endDate.Day) - Math.Min(30, startDate.Day)
Else 'Use US method
'If the start date is the last day of the month, change it to the 30th
Dim startDay As Integer = startDate.Day
startDay = If(startDate.Day >= DateTime.DaysInMonth(startDate.Year, startDate.Month), 30, startDate.Day)
'If end date is last of the month, change it to the 30th
Dim endDay As Integer = endDate.Day
endDay = If(endDate.Day >= DateTime.DaysInMonth(endDate.Year, endDate.Month), 30, endDate.Day)
'If end date is last of the month and start date is before 30th, change end date to 1st of the next month
If endDate.Day >= DateTime.DaysInMonth(endDate.Year, endDate.Month) And startDay < 30 Then
endDay = 1
months += 1
End If
Return months * 30 + endDay - startday
End If
End Function
I would like some feedback on what's wrong with these codes. I'm trying to output a full week based on a week number. For instance if I input "2014/45" I would like to output all dates spanning from November 2nd to November 8th. Now I need to figure out the first date in that week (hence November 2nd) before grabbing the rest of the days and this is where everything gets messed up for me. This is what I've come up with:
' getyear = 2014, getweek = 45
Dim DateOfFirstWeekDay As DateTime = GetDateOfFirstDayOfWeek(getyear, getweek)
Dim FirstDateInSequence As DateTime = CDate(DateAdd("d", _
CInt(Abs(Integer.Parse(Weekday(DateOfFirstWeekDay, WeekStartsWith))) * -1) + 1, _
DateOfFirstWeekDay)).ToShortDateString()
Protected Friend Shared Function GetDateOfFirstDayOfWeek(ByVal getyear As Nullable(Of Integer), _
ByVal getweek As Nullable(Of Integer)) As DateTime
Dim firstWeekDay As DateTime = GetFirstDayOfWeek(newYearDay)
If getweek = 1 Then
getweek -= 1
End If
Return DateAdd(DateInterval.WeekOfYear, CInt(getweek), firstWeekDay)
End Function
Protected Friend Shared Function GetFirstDayOfWeek(ByVal dt As DateTime) As DateTime
If dt.DayOfWeek = DayOfWeek.Sunday Then
Return dt.AddDays(-6)
Else
Return dt.AddDays(1 - CInt(dt.DayOfWeek))
End If
End Function
As my question implies November 2nd is not the result I get. Instead FirstDateInSequence returns December 22, 2013 when I input 2014/45. It's pretty safe to assume something fails me here. I just can't get my head around it. I'd like your point of view to this. Where should I focus my attention in the code above?
I'm having a hard time quickly following your code logic. So here's mine.
You could start by finding the first day of the first week of that year
Dim d As New DateTime(year, 1, 1)
d = d.AddDays(-d.DayOfWeek)
And then add the number of days (week_number -1) * 7
d = d.AddDays((week_number - 1) * 7)
I do a -1 since I assume that week_number will be equal to 1 to get the first week. Since d is already equal to the first week, we start counting at 0.
To get the last day, just add 6 (or 7) days to the result