The Anchorage
Personal website of Gregory K. Maxey, Commander USN (Retired)
The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.
However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.
If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!
This Microsoft Word Tips & Microsoft Word Help page introduces "Hangman for Word," a game developed in Microsoft Word with Visual Basic for Applications (VBA).
For the more serious minded, I hope to offer a "class study" or introduction and demonstration of the versatility and benefits of using custom class objects in your VBA projects. In any case, perhaps "Hangman for Word" will provide hours of fun for the players.
To play Hangman for Word, download the template file here. After downloading the file, you can initiate play in one of three ways:
For more on template add-ins and how to load them, see: Organizing Your Macros/Template Add-ins at: Installing Macros
Documents containing the code and class modules for the demonstrations that follow are also available in the download link.
Using either method above adds a ribbon control to the ribbon Add-Ins tab.
After clicking the ribbon control, the game console is displayed:
There are two modes of play:
The game console is setup to automatically begin a single player game. A random game word is already defined. All you have to do to begin play is guess and select a letter.
For the two player game, the challenger can define and set a game word before beginning play. After a new game word is defined and play begins the game console is reconfigured.
From this point on, game play is self explanatory.
If you are a beginner (dabbler) or intermediate (tinkerer) with VBA then you are probably familiar with the project standard code modules and perhaps even Userform. When you insert a new userform or standard module in your project you might wonder, "What is a Class?"
VBA is a pseudo "Object Oriented Programming" (OOP) language; meaning that it works with "objects" and the "properties" and "methods" of those objects. I say pseudo OOP, because unlike a true OOP language, VBA doesn't have "inheritance" or "polymorphism." You can Google OOP, inheritance or polymorphism to learn more about each of them.
Note: Anything you do learn about inheritance or polymorphism will be more than I know!
The truth is that if you have ever used VBA then you have been using classes from the very beginning. The classes you have used are all built-in to the application object model. For example, in Word, a document is an object of the document class because:
Sub SimpleStuff() Dim oDoc As Word.Document 'The ActiveDocument is and instance of the document class because: '1. It is an object. MsgBox IsObject(ActiveDocument) '2. It has properties such as "Name." MsgBox ActiveDocument.Name '3. It has methods such a "Printout" ActiveDocument.PrintOut 'You can create new instances of the document class and each instance _ 'follows the rules established in the class: Set oDoc = Documents.Add MsgBox oDoc.Name End Sub
So a "Class Module" or better a "custom class" is just an object that you can define yourself. You define its properties and methods, and when done properly you can create new instances of your class which will follow the rules that you define.
Think about you and me. As a person your and I are a class in a sense. Yes, and some persons are are more classy than others. Regardless we are an object.
The human class developer being far more omnipotent than me has created our classy selves with nearly an infinite number or properties and methods. Furthermore, when two of us person objects with the right properties get together new objects of the class are often instantiated (created).
A class object like a person is created, it has properties and methods, and still like people it eventually reaches the end of its useful life and dies (terminated or disposed of in VBA speak).
I think you get it now, so it is time to demonstrate a custom class in simplest form. In this demonstration you will see how an object of the class is instantiated, assigned properties and a method, and eventually terminated.
Our person object will have two properties "Name" and "Age" and a single method "Aging."
The class properties in this demonstration are "simple" properties meaning they are declared as public variables in the class.
Note: Purist will frown on using public variable declarations in a class and the debate is one that I am not really qualified to enter. They have their advantages and disadvantages. I use them sparingly in my projects and I feel that you should be aware of them. I will cover private variable declarations and Get/Let property pairs in the next demonstration.
To create the demonstration you will need to:
Sub DemoClass() 'Place your cursor here and step through this code using the F8 key. Dim oPerson As clsPerson 'Create the object. Set oPerson = New clsPerson 'Define the public property "Name" oPerson.Name = "Billy" Do 'Time marches on. oPerson.Ages If oPerson.Age > 70 Then Exit Do Loop lbl_Exit: 'Note what happens in the clsPerson terminate event when _ the procedure exits and the oPerson object falls out of scope. Exit Sub End Sub
Option Explicit 'Publicly declared variables. Public Name As String Public Age As Long Private Sub Class_Initialize() 'The object is born and its Age property is set to 0. Age = 0 End Sub Sub Ages() 'The aging method. Age = Age + 25 End Sub Private Sub Class_Terminate() MsgBox "Like all of us, our person grows older eventually dies." End Sub
There you have it. You've created and demonstrated your first simple class and hopefully you are grasping the concept.
Now let's complicate things. Classes like people can be as simple or complex as the developer makes them.
First let's look at the advantages and disadvantages of the simple publicly declared class variables "Name" and "Age" in our simple custom person class.
The advantage of course is simplicity. By declaring the variable public, you automatically expose it externally to other modules (i.e., the standard module) as a read\write property of the class.
No problem there for "Name" property as a persons name can be nothing or anything at all. However, consider if you added this line of code in your standard module:
As you surely know a person's age is based on their date of birth and it certainly cannot be a negative number!
In the next demonstration you will see how to use private class variables and property Get, Let or Set statements in your class module code. This allows you to define "Read Only or Write Only" class properties as well a validate the property and keep your cod encapsulated.
To create the demonstration you will need to:
Sub DemoClass() 'Place your cursor here and step through the code using the F8 key. 'A custom class is a an object. To use a grammar analogy, _ a class is like a noun (person, place, or thing). Dim oPerson As clsPerson Dim lngIndex As Long 'Objects must be created. Like in the real world, people must be born, _ cities must be built, things must be manufactured. Set oPerson = New clsPerson 'Objects have decriptive properties. _ The person has a birth date, gender and name. oPerson.Gender = "Male" 'Determined as inception. oPerson.BirthDate = "9/1/2003" If oPerson.Gender = "Male" Then oPerson.Name = "Dick" Else oPerson.Name = "Jane" End If 'Objects can have other objects. A tree has leaves, the person object has hair. 'These objects have properties. The person's hair has color and length. If oPerson.Gender = "Male" Then oPerson.Hair.Color = "Red" oPerson.Hair.Length = 2 Else oPerson.Hair.Color = "Blonde" oPerson.Hair.Length = 10 End If 'What is our person like like? MsgBox "The " & oPerson.Development & "'s name is " & oPerson.Name & "." & vbCr _ & oPerson.Name & " is " & oPerson.Age & " years old with " _ & oPerson.Hair.Color & " hair." & vbCr _ & oPerson.Name & "'s hair is " & oPerson.Hair.Length & " inches long." & vbCr _ & oPerson.Name & " is spending the summer at the beach." 'During the summer: 'In addition to properties, objects can have methods. Using the grammar analogy _ again, methods are like verbs. For lngIndex = 1 To 3 'The persons hair hair grows. oPerson.Hair.Grow Next lngIndex If oPerson.Gender = "Male" Then MsgBox oPerson.Name & " is back home now." & vbCr _ & oPerson.Name & "'s hair is now " & oPerson.Hair.Length & " inches long." Else oPerson.Hair.Cut MsgBox oPerson.Name & " is back home now." & vbCr _ & "She went to the hair dresser's before coming home." & vbCr _ & oPerson.Name & "'s hair is now " & oPerson.Hair.Length & " inches long." End If 'Like all things, classes must eventually come to an end or be terminated. _ People die, cities crumble, things are destroyed. Do 'The person ages. oPerson.Ages Debug.Print oPerson.Age 'As the person ages his or her development changes. If oPerson.Age = 40 Then MsgBox "Lordy, Lordy our " & _ oPerson.Development & " is now forty." If oPerson.Age > 70 Then Exit Do Loop lbl_Exit: 'Note what happens in the clsPerson terminate event when the procedure exits _ and the oPerson object falls out of scope. Exit Sub End Sub
Option Explicit 'Class objects can have Public or Private variables. 'Public variables are by default exposed as read\write properties of _ the class that cannot be validated. Public Name As String 'Private class variables used in Property Get/Let/Set statements _ to define class properties. Private m_strGender As String Private m_dtdBirthDate As Date Private m_lngAge As Long Private m_oHair As clsHair 'Private utility variable. Private m_lngPassageOfTime As Long Private Sub Class_Initialize() 'From the dust our person object is formed. 'Objects can have other objects as properties. Trees have leaves, our person has hair. Set Hair = New clsHair End Sub 'Gender is a Read\Write property of class. Requires paired Get\Let property statements. Property Get Gender() As String Gender = m_strGender End Property Property Let Gender(strGene As String) m_strGender = strGene End Property 'BirthDate, just becuase I wanted it this way, is a Write only property of the class. Property Let BirthDate(oDate As Date) m_dtdBirthDate = oDate End Property 'Age is a Read only property of the class. _ The value is determined by the BirthDate and passage of time. Property Get Age() As Long Age = CLng(DateDiff("yyyy", m_dtdBirthDate, Now)) + m_lngPassageOfTime End Property 'Hair is a Read\Write "object" property of the class. _ Requires paired Get\Set property statements. Property Get Hair() As clsHair Set Hair = m_oHair End Property Property Set Hair(Object As clsHair) Set m_oHair = Object End Property 'Development is a Read only property of the class. Property Get Development() As String If m_lngAge < 19 Then If m_strGender = "Male" Then Development = "boy" Else Development = "girl" End If Else If m_strGender = "Male" Then Development = "man" Else Development = "woman" End If End If End Property Sub Ages() 'A method of the class. m_lngPassageOfTime = m_lngPassageOfTime + 15 m_lngAge = m_lngAge + m_lngPassageOfTime End Sub Private Sub Class_Terminate() MsgBox "Like all of us, our person grows older becomes a " & Development & ", " _ & "eventually dies and returns to dust." End Sub
Option Explicit Private strColor As String Private lngLength As Double Property Get Color() As String Color = LCase(strColor) lbl_Exit: Exit Property End Property Property Let Color(strInput As String) strColor = strInput lbl_Exit: Exit Property End Property Property Get Length() As Double Length = lngLength lbl_Exit: Exit Property End Property Property Let Length(lngInput As Double) lngLength = lngInput lbl_Exit: Exit Property End Property Sub Grow() 'A method of the class. lngLength = lngLength + 0.4 End Sub Sub Cut() 'A method of the class. lngLength = lngLength - 3 End Sub Private Sub Class_Initialize() 'The object is born. Beep End Sub
If you've followed the demonstrations and made it this far then you should have a better understanding of what classes are and how to use them.
Don't worry if you have to step through the demonstrations more than once. Classes are not easy to understand. For a long, long time I avoided them like the plague. The Get/Let property pairs have kicked my butt more than once. However, they do get easier with use and learning about them can offer the following advantages:
Now you are ready to look at the code in "Hangman for Word" many of the concepts and methods you've seen in the demonstrations were employed to create it.
That's it! I hope you enjoy the game and that you've have found this tips page useful and informative.
The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.
However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.
If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!