Completing Calendars with VBScript Date Functions

In my last article, we began building a script that could produce and display a formatted calendar for a specified month and year. In this article, I’ll show you how to wrap up this project by putting all of the pieces together.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 1
February 02, 2009
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement
We began our script by accepting a user’s input for the month and year.  We then used those two values to determine all of the other necessary values we would need, such as the first day of the month, the weekday that the first falls on, and the last day of the month.  Now we can complete the main portion of our script.

We need to begin building an array to handle the dates involved in our calendar month.  This array will contain each day in the month.  I elected to house this in a separate function.

arrThisMonth = BuildArray()

The BuildArray function is only slightly complicated.  Let’s take a look at it in pieces.

Function BuildArray()

   arrMonth = Array()

   intEmptyDays = intFirstWeekDay - 1

   For i = 1 To intEmptyDays

       ReDim Preserve arrMonth(UBound(arrMonth) + 1)

       arrMonth(UBound(arrMonth)) = "      "

   Next

It begins by creating an empty dynamic array.  If you remember, a calendar week always begins on Sunday.  The first day of the month may not be on Sunday, so we need to determine the number of empty days before it.  Since the WeekDay function has returned an integer for the weekday of the first month, we can just subtract 1 from this value to determine the number of empty days in that week.

For example, if Jan 1 were to appear on Thursday (a value of 5), there would be 5 minus 1, or 4, empty days preceding it: Sunday, Monday, Tuesday and Wednesday.

Building the array

Now I can create a loop to add the correct number of empty values to the beginning of my array.  I’m just adding spaces as strings.  You can see the columns in my example output allow three spaces to display a given date.  I’m also padding that with three leading spaces to space out my columns a little more and make it look pretty.  So each empty date should contain a string of six spaces.

   For i = 1 To intDaysInMonth

       ReDim Preserve arrMonth(UBound(arrMonth) + 1)

       strDay = CStr(i)

       intPad = 6 - Len(strDay)

       strDay = Space(intPad) & strDay

       arrMonth(UBound(arrMonth)) = strDay

   Next

Next I add the individual days of the month to my array by looping through each value between 1 and the last day of the month.  Notice again that I’m padding each value as necessary so that each date string contains six characters.

   intEmptyDays = 7 - intLastWeekDay

   For i = 1 To intEmptyDays

       ReDim Preserve arrMonth(UBound(arrMonth) + 1)

       arrMonth(UBound(arrMonth)) = "      "

   Next

Once all the dates are in place, I’m finding the number of empty days at the end of the month.  This is done by taking the highest possible weekday, 7 for Saturday, and subtracting the weekday of the last day in the month.  These are added to the array as strings of spaces as before.  Adding these empty days ensures that our array contains complete weeks.

   BuildArray = arrMonth

End Function

Finally, an array of complete weeks for our given month is returned to the main script.

Back in our main script, we’re ready to begin displaying the calendar.

WScript.Echo "  ", MonthName(intMonth), intYear

WScript.Echo ""

WScript.Echo "   Sun", "   Mon", "   Tue", "   Wed", "   Thu", "   Fri", "   Sat"

A few lines are used to set up the basic look by providing the month and year titles and well as the weekday headers for our table.

For i = 0 To UBound(arrThisMonth) Step 7

   WScript.Echo arrThisMonth(i), arrThisMonth(i + 1), arrThisMonth(i + 2), arrThisMonth(i + 3), arrThisMonth(i + 4), arrThisMonth(i + 5), arrThisMonth(i + 6)

Next

Next, we rely on a For loop to move through the values in our array of days.  We want to return them in one-week intervals so that each week can be printed on a new line.  To do this we simply move through the entire array with a Step value of 7, essentially reading seven values at a time.  Then it’s just a matter of printing each of those seven values on a single line.

Completing the code

At this point we have a complete working script.  If you would like to learn how to add validation to this code, be sure to continue on to the next page.  In the meantime, here’s what the completed script currently looks like:

If LCase(Right(WScript.FullName, 11)) <> "cscript.exe" Then

    strPath = WScript.ScriptFullName

    strCommand = "%comspec% /k cscript " & Chr(34) & strPath & chr(34)

    CreateObject("WScript.Shell").Run(strCommand)

    WScript.Quit

End If

 

strDate = InputBox("Please enter a month and year as MM/YYYY.", "Microsoft Scripting Games 2008")

If strDate = "" Then WScript.Quit

 

arrDateParts = Split(strDate, "/")

intMonth = arrDateParts(0)

intYear = arrDateParts(1)

 

dteFirstDay = DateSerial(intYear, intMonth, 1)

intFirstWeekDay = WeekDay(dteFirstDay)

intDaysInMonth = DaysInMonth(intMonth, intYear)

intLastWeekDay = WeekDay(DateSerial(intYear, intMonth, intDaysInMonth))

 

arrThisMonth = BuildArray()

 

WScript.Echo "  ", MonthName(intMonth), intYear

WScript.Echo ""

WScript.Echo "   Sun", "   Mon", "   Tue", "   Wed", "   Thu", "   Fri", "   Sat"

For i = 0 To UBound(arrThisMonth) Step 7

   WScript.Echo arrThisMonth(i), arrThisMonth(i + 1), arrThisMonth(i + 2), arrThisMonth(i + 3), arrThisMonth(i + 4), arrThisMonth(i + 5), arrThisMonth(i + 6)

Next

 

Function BuildArray()

   arrMonth = Array()

   intEmptyDays = intFirstWeekDay - 1

   For i = 1 To intEmptyDays

       ReDim Preserve arrMonth(UBound(arrMonth) + 1)

       arrMonth(UBound(arrMonth)) = "      "

   Next

 

   For i = 1 To intDaysInMonth

       ReDim Preserve arrMonth(UBound(arrMonth) + 1)

       strDay = CStr(i)

       intPad = 6 - Len(strDay)

       strDay = Space(intPad) & strDay

       arrMonth(UBound(arrMonth)) = strDay

   Next

 

   intEmptyDays = 7 - intLastWeekDay

   For i = 1 To intEmptyDays

       ReDim Preserve arrMonth(UBound(arrMonth) + 1)

       arrMonth(UBound(arrMonth)) = "      "

   Next

 

   BuildArray = arrMonth

End Function

 

Function DaysInMonth(intMonth, intYear)

   If intMonth = 12 Then

       dteNextMonth = DateSerial(intYear + 1, 1, 1)

   Else

       dteNextMonth = DateSerial(intYear, intMonth + 1, 1)

   End If

 

   DaysInMonth = DateDiff("d", dteFirstDay, dteNextMonth)

End Function

Validating user input

I promised that I would should you how to validate the user input.  There are a number of ways to accomplish this, but I’ve chosen to use regular expressions because they are quite often used for validating user input. To do this, it’s best to create a separate function that retrieves the user’s input and validates it.  This way, the function can be repeated if the user's input isn’t valid.

Replace this:

strDate = InputBox("Please enter a month and year as MM/YYYY.", "Microsoft Scripting Games 2008")

If strDate = "" Then WScript.Quit

 

With this:

strDate = GetValidDate()

The portion of the main script that retrieves user input should be replaced.  We’ll be handling this within our new function instead.

Function GetValidDate

   strDate = InputBox("Please enter a month and year as MM/YYYY.", "Microsoft Scripting Games 2008")

   If strDate = "" Then WScript.Quit

 

   GetValidDate = strDate

Now our function should start out by receiving the user’s input.  We immediately assign this value as our function’s return value.  Since our function will only loop if the data is not valid, we want to set an initial return value for our function so that it doesn’t return empty if all is well.  We can change the return value later in our function if necessary.

   Set re = New RegExp

   re.IgnoreCase = True

   re.Pattern = "^(dd?)/(dddd?)$"

   If re.Test(strDate) Then

       Set colMatches = re.Execute(strDate)

       intMonth = CInt(colMatches(0).SubMatches(0))

       intYear = CInt(colMatches(0).SubMatches(1))

       If intMonth < 1 Or intMonth > 12 Or intYear < 100 Then

          WScript.Echo "You have not entered a valid date.  Please try again."

          GetValidDate = GetValidDate()

       End If

   Else

       WScript.Echo "Your entry was not valid.  Please try again."

       GetValidDate = GetValidDate()

   End If

End Function

The rest of the function looks like this.  It uses a regular expression to check the validity of the user’s string.  Without going into too much detail about regular expressions, let me see if I can break this down a little bit for you.  Let’s take it in parts.

   Set re = New RegExp

   re.IgnoreCase = True

   re.Pattern = "^(dd?)/(dddd?)$"

These lines create a new regular expression object and initialize some basic properties.  The most important one here is the Pattern property.  This determines what the regular expression considers valid.  Patterns are far beyond the scope of this article.  This particular pattern checks that the whole user’s string contains either one or two digits immediately followed by a forward slash, which is in turn followed by either three or four more digits.  In other words, it allows a one or two digit month and a three or four digit year.

   If re.Test(strDate) Then

       Set colMatches = re.Execute(strDate)

       intMonth = CInt(colMatches(0).SubMatches(0))

       intYear = CInt(colMatches(0).SubMatches(1))

Next we have this code.  We use the regular expression’s Test method to determine if the user input matches our pattern.  If so, we retrieve the month and year values.

       If intMonth < 1 Or intMonth > 12 Or intYear < 100 Then

          WScript.Echo "You have not entered a valid date.  Please try again."

          GetValidDate = GetValidDate()

       End If

   Else

       WScript.Echo "Your entry was not valid.  Please try again."

       GetValidDate = GetValidDate()

   End If

Finally, we test those values to make sure that they are in the acceptable range.  We’re simply telling the function to fail if the month is less than 1 or greater than 12, or if the year is less than 100 (VBScript Dates are supported from 100 AD).  This allows the full range of supported Dates in VBScript.  In the event that any of the parts are not valid, we notify the user and then set the function’s return value equal to the function itself.  This causes a looping action, forcing the validation process to begin again.

And there you have it.  A fully-operational calendar-building script that will work for any month in VBScript’s acceptable Date range, which is January 100 AD through December 9999 AD.  Now you’re ready to put it to the test.

So on what day of the week was Napoleon born?  Well, he was born August 15, 1769.

   August 1769

   Sun    Mon   Tue  Wed  Thu   Fri     Sat
                      1       2       3       4       5
     6      7       8       9       10     11     12
    13     14     15     16     17     18     19
    20     21     22     23     24     25     26
    27     28     29     30     31             

According to our trusty script, that was a Tuesday.  Until next time, keep coding!

You can download the full code for this article here.

blog comments powered by Disqus
WINDOWS SCRIPTING ARTICLES

- More Windows Scripting Workarounds from Nilpo
- Overloading Methods and More in VBScript
- Improving MFC for Windows Vista
- Regular Expressions in VBScript
- Working with Dates in WMI
- Completing Calendars with VBScript Date Func...
- Building Calendars with VBScript Date Functi...
- Working With Dates and Times in VBScript
- Designing WCF DataContract Classes Using the...
- Understanding Dates and Times in VBScript
- Working With Arrays in VBScript
- Compressed Folders in WSH
- Using .NET Interops in VBScript
- Nilpo`s Scripting Secrets, Vol I
- Database operations using Silverlight 2.0 WC...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 5 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials