In my "other" life, I'm a writer. I was recently thinking about books that have been bypassed by the march of time such as 1984 and 2001: A Space Odyssey. When they were written, their dates were far into the future. Now, they're artifacts of history. The idea of using Visual Basic to write an "eternal" story that would always be current came to me, so I wrote both the story and the code insert current dates and times so the the content will always be up to date whenever someone reads it.
If you're interested in calling Microsoft Word from VB.NET, both to display the updated text of the story and for date and time calculations, this program might be of interest to you. In addition, the interface is WPF (Windows Presentation Foundation) rather than Windows Forms based. It's also written using VB.NET 2008 Express Edition.
In this article, I'll simply present the code first. If you just want to read the story, you can download it here, unzip the file and click the top button to read it.
As you browse the code, you'll notice that the program ...
- Opens a Word document using Word Application automation.
- Adds a list of DateTime objects using bookmarks embedded into the text of the document.
- Closes the Word environment again.
To recreate this program on your computer, start a new WPF application, and add a reference to "Microsoft Word Object Library". (I tested both 11.0 and 12.0 and both work.) Add two WPF Button components, naming the first "readStory" and the second "finishedReading". Then add the code below to the appropriate Click events for the two components. Click Here for a beginning tutorial on WPF.
Here's the code. Event subroutine arguments are omitted to shorten lines. VB.NET will add them back when you add the events in your code. I've added comments "in line" in this article and if you just copy and paste the code, you'll have to delete these lines.
Imports Microsoft.Office.Interop
Imports System.IO
Class EternalStory
Friend oWord As Word.Application
Private Sub readStory_Click( ...
oWord = New Word.Application
oWord.Visible = True
The base Word document, complete with bookmarks, must be in the same directory as the executable for the program. When you're developing the code, this is the Bin directory. If you want to use my document and my bookmarks, download the system using the link above and copy out "Eternal Story.doc".
oWord.Documents.Open(FileName:=Directory.GetCurrentDirectory() & _
"\Eternal Story.doc", ReadOnly:=True)
I set an initial datetime once in the baseDate variable equal to Now and use that in the rest of the code.
Dim baseDate As DateTime = Now
The collection of all bookmarks is in the Bookmarks object in the document.
--------
Click Here to display the illustration
Click the Back button on your browser to return
--------
Dim BMs As Word.Bookmarks = oWord.ActiveDocument.Bookmarks
BMs("dayOfWeek").Range.Select()
The VB.NET ToString object is the most convenient way to select and format parts of dates and times for display. You can get just about anything using combinations of the format specifiers. In this case, I add the text of the current year as the title of the story.
oWord.Selection.Text = baseDate.ToString("dddd")
BMs("daysYTD").Range.Select()
oWord.Selection.Text = baseDate.DayOfYear
BMs("etYear").Range.Select()
oWord.Selection.Text = baseDate.Date.Year
BMs("fiftyYearsAgo").Range.Select()
oWord.Selection.Text = _
DateAdd(DateInterval.Year, -50, baseDate).ToString("yyyy")
To find the most recent Friday the 13th, I start at the current date and go back in time checking each day.
BMs("lastFri13").Range.Select()
Dim Fri13 As Date = Now
Do Until (Fri13.DayOfWeek = DayOfWeek.Friday And Fri13.Day = 13)
Fri13 = Fri13.AddDays(-1)
Loop
oWord.Selection.Text = Fri13.ToString("MMMM dd")
BMs("minutesSinceMidnight").Range.Select()
Dim lastMidnight As Date = baseDate.Date ' At midnight
Dim minutesSinceMidnight As Integer = _
CInt(DateDiff(DateInterval.Minute, lastMidnight, baseDate))
oWord.Selection.Text = minutesSinceMidnight.ToString
BMs("seventyYearsAgeDate").Range.Select()
oWord.Selection.Text = _
DateAdd(DateInterval.Year, 20, baseDate).ToString("MMMM dd, yyyy")
BMs("today").Range.Select()
oWord.Selection.Text = baseDate.ToString("MMMM dd, yyyy")
BMs("theTime").Range.Select()
oWord.Selection.Text = baseDate.ToShortTimeString
BMs("lastLeapYearPhase").Range.Select()
Dim lastLeapYear As DateTime = baseDate
The current year or a previous year might be a leap year. I substitute entirely different text into the story depending on which it is.
If DateTime.IsLeapYear(lastLeapYear.Year) Then
oWord.Selection.Text = _
"This year had been horrible so far since it is a leap year."
Else
Do
lastLeapYear = DateAdd(DateInterval.Year, -1, lastLeapYear)
Loop Until DateTime.IsLeapYear(lastLeapYear.Year)
oWord.Selection.Text = _
lastLeapYear.ToString("yyyy") & _
" was a horrible year all year long."
End If
The most convenient way to return to the top of the document is to select the bookmark that is already there.
BMs("etYear").Range.Select() ' To go back to top
End Sub
The user might close the Word documents using the control menu in Word. If that happens, I catch the exeception when the program tries to close it and do nothing.
Private Sub finishedReading_Click( ...
Try
oWord.Quit(False)
Catch ex As Exception
' Nothing
End Try
End
End Sub
End Class

