Excel VBA - remove weekends from automatic timesheet print - excel

I slightly amended some code I found online.
Purpose:
Click on a 'Print with Dates' button, then enter start date, and have Excel automatically generate/print a months worth of timesheets (much better than the previous spreadsheet having 6 weeks of pages to print, and you had to edit every date manually).
Issues:
It prints weekends, which wastes paper. Is there a way it can refer to a list of dates (weekends, public holidays), and not generate those for printing?
You'll see the date format is m/d/yyyy in the code, which strangely prints as dd/mm/yyyy (which is what I wanted). When the code was dd/mm/yyyy it was printing correctly (20/03/2019), but if it goes to the following month it was switching to American format m/d/yyyy (04/20/2019). I know it doesn't seem to make sense, but having it as m/d/yyyy actually prints as dd/mm/yyyy across any start/end dates. I'd like to know why, and also have dd/mm/yyyy in the code correctly printing across any date range.
CODE:
Sub PrintSheet()
Dim s As String
Dim d As Date
s = InputBox(Prompt:="Please enter the start date")
If Not IsDate(s) Then
MsgBox "Incorrect date", vbExclamation
Exit Sub
End If
For d = CDate(s) To DateAdd("m", 1, CDate(s)) - 1
Range("F2").Value = Format(d, "dddd")
Range("I2").Value = "" & Format(d, "m/d/yyyy")
ActiveSheet.PrintOut
Next d
End Sub
Cheers in advance :)

You can use the weekday function. It returns a number from 1 to 7. You can filter for 1-5 only for weekdays.
Sub PrintSheet()
Dim s As String
Dim d As Date
s = InputBox(Prompt:="Please enter the start date")
If Not IsDate(s) Then
MsgBox "Incorrect date", vbExclamation
Exit Sub
End If
For d = CDate(s) To DateAdd("m", 1, CDate(s)) - 1
If Weekday(d, vbMonday) < 6 Then
Range("F2").Value = Format(d, "dddd")
Range("I2").Value = "" & Format(d, "m/d/yyyy")
'MsgBox ("printing ") 'for testing
ActiveSheet.PrintOut
End If
Next d
End Sub

Related

How to use a formula to generate a date as a default value in an input msgbox?

I am trying to make my input message box a bit more sophisticated by using a formula to generate a default date in an input message box in excel.
Currently, it just gives a default value of "dd-mm-yyyy" to guide the user and then deposits it in cell B2. Code below:
Dim DispatchDate As Variant
Sheets("Template").Select
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", "dd-mm-yyyy")
Range("B2").Value = DispatchDate
Id like the default value to be the result of the following formula =IF(WEEKDAY(NOW()*1,2)>4,NOW()+3,NOW()+1)
Essentially making the default date today + 1 day unless on a Friday, which would be be today + 3 days (to account for weekends and no Friday dispatch).
I don't even know where to start with this. Any help would be appreciated.
This can be done with the IIF structure, that corresponds to the IF of the front-end:
Sub fnEvaluateDate()
Dim DispatchDate As Date
Sheets("Template").Select
With Excel.WorksheetFunction
DispatchDate = Format(IIf(.Weekday(VBA.Now() * 1, 2) > 4, VBA.Now() + 3, VBA.Now() + 1), "dd-mm-yyyy")
End With
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", DispatchDate)
Range("B2").Value = DispatchDate
End Sub
you can use evaluate method to extract value from formula:
Dim DispatchDate As Date
DispatchDate = Evaluate("=IF(WEEKDAY(TODAY(),2)>4,TODAY()+3,TODAY()+1)")
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", DispatchDate)
or you can convert sheet formula into VBA code:
Dim DispatchDate As Date
DispatchDate = IIf(Weekday(Date, 2) > 4, Date + 3, Date + 1)
DispatchDate = InputBox("Enter next business day after today. Must use dd-mm-yyyy format", "Dispatch Date", DispatchDate)

Textbox converts date into number

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If Mid(TextBox1.Value, 4, 2) > 12 Then
MsgBox "Invalid date, please re-enter", vbCritical
TextBox1.Value = vbNullString
TextBox1.SetFocus
Exit Sub
End If
StartDate = DateSerial(Year(Date), Month(Date), Day(Date))
TextBox1.Value = Format(TextBox1.Value, "dd.mm.yyyy")
StartDate = TextBox1.Value
End Sub
This code works well for me and my colleagues to make sure the value entered in the textbox is a date. However, a colleague from a different country (but also with the dd.mm.yyyy date-format) gets weird results.
For example: If he enters 01.10.2017 the TextBox automatically format the date into 20.03.4917.
I suspect that in this case the entered value is not recognized as a date but as a number because 01102017 will transform into 20.03.4917 in Excel if you convert it as a date.
Does anyone have a suggestion or a guess how to work around this problem?
Thanks and best regards
You could split the date by . into an array ArrInput and then use DateSerial to make it a real date, that you can format.
Dim ArrInput As Variant
ArrInput = Split(TextBox1.Value, ".")
'StartDate = DateSerial(Year(Date), Month(Date), Day(Date)) 'I see no use in this at all
TextBox1.Value = Format$(DateSerial(ArrInput(2), ArrInput(1), ArrInput(0)), "dd.mm.yyyy")
StartDate = TextBox1.Value
The issue with Format(TextBox1.Value, "dd.mm.yyyy") is that here you let Excel guess which date format the string in TextBox1.Value is. It automatically casts into a number which is then converted into a string again.
To avoid date misunderstandings I recommend always to use the YYYY-MM-DD format according to ISO 8601. This is the only date format that is human readable and cannot be misunderstood. It also has benefits when sorting by dates that are actually strings.
To make your validation even more solid use something like:
Dim ArrInput As Variant
ArrInput = Split(TextBox1.Value, ".")
Dim ValidDate As Boolean
If UBound(ArrInput) = 2 Then 'make sure there are exactly two dots in the date
If ArrInput(1) > 0 And ArrInput(1) <= 12 And _ 'month <= 12
ArrInput(0) > 0 And ArrInput(0) <= 31 Then 'day <= 31
ValidDate = True
End If
Else
ValidDate = False
End If
If Not ValidDate Then
MsgBox "Invalid date, please re-enter in format dd.mm.yyyy", vbCritical
TextBox1.Value = vbNullString
TextBox1.SetFocus
Exit Sub
End If
TextBox1.Value = Format$(DateSerial(ArrInput(2), ArrInput(1), ArrInput(0)), "dd.mm.yyyy")
StartDate = TextBox1.Value
I do believe that your colleague enters the text string "01102017" without dots.
You might want to convert such kind of entries into a valid date:
' "01102017" => 01.10.2017 - 8 chars variant
' "011017" => 01.10.2017 - 6 chars variant
This needs to be done of cause prior to a date conversion.
Add a log of the input value to a free cell range and
have the workbook sent back to you:
...
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
Range("Z1").value = "'" & TextBox1.Value
If Mid(TextBox1.Value, 4, 2) > 12 Then
...
Check if only numbers are used:
How to check if a string contains only numbers?
and check the length of the string (6 or 8 chars variant) and check if the year part is within a valid range => try to convert to a date and offer it to the user.

How to find number of working days for a month?

In an Excel sheet I have a date (October,2018).
From this I have to populate start date and end date of that month and number of working days in another column.
the format you're looking for would be something like this: reference
Range("C5") = Format(date_example, "mmm-yy")
Try this
Sub DateTest()
'convert the cell to text format and prints the date
Range("C5").NumberFormat = "#"
Range("C5") = Format(#10/18/2018#, "mmm-yy")
'gets the no of days between two dates
MsgBox "No of days : " & DateDiff("d", #1/1/2019#, Date, vbMonday)
'gets the no of working days between two dates
MsgBox "No of working days : " & WorksheetFunction.NetworkDays(#1/1/2019#, Date)
End Sub

Creating exact dates in Excel VBA by inputing only the day

In the following picture of an Excel sheet, the heading of the first column, and then of every 7th column after that, contains a month and a year.
I am trying to think of some code which would make entering complete dates under these headings faster. Since the month and the year are already present, I'm thinking there must be a way to enter just the day, and get the whole thing. For example, if "21" were entered in cell A26, "2/21/2015" would result.
Anyone have an idea for how I might get this output?
Edit: Thanks to the helpful replies on this forum, I figured out exactly how to do this. Here is the code for my finished product, in case anyone wants to do something similar:
Private Sub Worksheet_change(ByVal Selection As Range)
Set Sel = Selection
If Sel.Count > 1 Then
Exit Sub
End If
If (Sel.Column - 1) Mod 7 = 0 Or Sel.Column = 1 Then
'In my case, date columns always follow the pattern of 1, 8, 15...
If Sel.Value > 31 Or Sel.Value = "" Then
Exit Sub
Else
Sel.NumberFormat = "General"
Sel.Value = Left(Cells(1, Sel.Column), InStr(Cells(1, Sel.Column), ",") - 1) & " " & _
Sel.Value & Right(Cells(1, Sel.Column), 6)
Selection.NumberFormat = "m/d/yyyy"
End If
End If
End Sub
How about entering the day numbers, selecting the range where these day numbers are entered, and running the below:
Sub Add_month_year()
Dim c As Range
For Each c In Selection
c = Left(Cells(1, c.Column), InStr(Cells(1, c.Column), ",") - 1) & " " & _
c.Value & Right(Cells(1, c.Column), 6)
Next
End Sub
This should return the full dates in date code, which you can then format as you see fit.

Excel VBA - compare date in cell to current date

(Excel 2010 VBA)
I have a cell (A1) containing a date in the format of mmm-yy ("Custom" category).
Foe example, if I enter 1/6/13 the cell shows June-13. That's fine.
In my VB macro I need to check this date whether the month is the current month and whether the year is the current year. I don't care about the day.
Does this help you:
Public Sub test()
d = Sheet1.Range("A1")
n = Now()
If Year(d) = Year(n) And Month(d) = Month(n) Then
MsgBox "It works"
End If
End Sub
Thanks to Dave and MiVoth I did :
Dim xdate As Date
xdate = Worksheets("sheet1").Range("A1")
If Month(Date) = Month(xdate) And Year(Date) = Year(xdate) Then
MsgBox "OK"
Else
MsgBox "not OK"
End If
That did the job!
Thank a lot to everyone,
Gadi
How about this:
Function MonthYear() As Boolean
MonthYear = False
If Not IsDate(Cells(1, 1)) Then Exit Function
If Month(Date) = Month(Cells(1, 1)) And Year(Date) = Year(Cells(1, 1)) Then
MonthYear = True
End If
End Function
The function returns true if month and year are the same as current date. If not it returns false.

Resources