MS Office Forum / Word / Programming / November 2006
No Class or High Class
|
|
Thread rating:  |
Greg Maxey - 29 Nov 2006 17:27 GMT For the most part, Class modules are still a mystery to me. What little knowledge I have of them was imparted by Jezebel when I was working on a project to list, count and sort spelling errors.
Earlier today and OP wanted to simply list all spelling errors contained in a document in a separate document. I thought of my earlier project and passed on the link.
I then started thinking about a simpler code to do exactly what the OP requested "and" prevent duplicates. Here is the result of those thoughts:
Sub NoClass() Dim DupChk As Object Dim oCol As Collection Dim oSpError As Word.Range Dim i As Long Set oCol = New Collection 'Add to collection For Each oSpError In ActiveDocument.Range.SpellingErrors On Error Resume Next Set DupChk = oCol(oSpError.Text) On Error GoTo 0 If DupChk Is Nothing Then oCol.Add oSpError End If Set DupChk = Nothing Next 'Publish results Documents.Add For i = 1 To oCol.Count ActiveDocument.Range.InsertAfter oCol(i) & vbCr Next i End Sub
That seems straightforward and does the job.
To do the same thing with a class, I first inserted a class module, named it clsError and pasted in this code:
Private mName As String Public Property Get Name() As String Name = mName End Property Public Property Let Name(NewValue As String) mName = NewValue End Property
In the project module, I used this code:
Sub HighClass() Dim oError As clsError Dim oCol As Collection Dim oSpError As Word.Range Set oCol = New Collection 'Add to collection For Each oSpError In ActiveDocument.Range.SpellingErrors On Error Resume Next Set oError = oCol(oSpError.Text) On Error GoTo 0 If oError Is Nothing Then Set oError = New clsError oError.Name = oSpError.Text oCol.Add oError, oError.Name End If Set oError = Nothing Next 'Publish results Documents.Add With ActiveDocument.Range For Each oError In oCol .InsertAfter oError.Name & vbCr Next End With End Sub
This works equally as well.
What again is the benefit of using a Class? Is there any benefit in this example?
Thanks.
Greg Maxey - 29 Nov 2006 18:00 GMT Please ignore the moronic post above. Due to a massive brain flatuation, I was convinced that the No Class method worked. It doesn't.
Sorry for wasting your time.
> For the most part, Class modules are still a mystery to me. What > little knowledge I have of them was imparted by Jezebel when I was [quoted text clipped - 78 lines] > > Thanks. Karl E. Peterson - 29 Nov 2006 19:55 GMT > Please ignore the moronic post above. Due to a massive brain > flatuation, I was convinced that the No Class method worked. It > doesn't. That aside...
> Sorry for wasting your time. It's a valid question, that many folks struggle with initially...
>> What again is the benefit of using a Class? Is there any benefit in >> this example? There are numerous ways to approach any problem, and there are certainly non-class-based approaches you could have taken here. Frankly, it does seem like bringing classes into this is reaching for the heavy artillery, so perhaps it isn't the best example.
Classes offer *lots* of other benefits, though. There are obvious ones, like the ability to have code associated with unique data sets. This is very powerful, for things like validity checking and reaction. Which leads to what's probably the most *powerful* use -- the ability to raise and/or sink events. Once you embrace this capability, the possibilities immediately seem endless.
 Signature Working without a .NET? http://classicvb.org/
Karl E. Peterson - 29 Nov 2006 20:18 GMT >>> What again is the benefit of using a Class? Is there any benefit in >>> this example? [quoted text clipped - 3 lines] > Frankly, it does seem like bringing classes into this is reaching for > the heavy artillery, so perhaps it isn't the best example. Here's a simple variation of your initial try, that works:
Sub NoClass() Dim oCol As Collection Dim oSpError As Word.Range Dim i As Long Set oCol = New Collection
'Add to collection On Error Resume Next For Each oSpError In ActiveDocument.Range.SpellingErrors If Len(oCol(oSpError.Text)) = 0 Then If Err.Number = 5 Then Debug.Print oSpError.Text oCol.Add oSpError.Text, oSpError.Text End If End If Next
'Publish results Documents.Add For i = 1 To oCol.Count ActiveDocument.Range.InsertAfter oCol(i) & vbCr Next i End Sub
Later... Karl
 Signature Working without a .NET? http://classicvb.org/
Greg Maxey - 29 Nov 2006 20:39 GMT Karl,
I had come up with this earlier before I started exploring the class method:
Sub ListErrorsNoDups() Dim oErr As Word.Range Dim oCol As Collection Dim i As Long Dim bDup As Boolean Set oCol = New Collection For Each oErr In ActiveDocument.Range.SpellingErrors bDup = False For i = 1 To oCol.Count If oCol(i) = oErr Then bDup = True Next i If Not bDup Then oCol.Add oErr Next Documents.Add For i = 1 To oCol.Count ActiveDocument.Range.InsertAfter oCol(i) & vbCr Next i End Sub
I like you method better.
Would you have anything that demonstrated this raise and sink events idea that you mentioned?
> >>> What again is the benefit of using a Class? Is there any benefit in > >>> this example? [quoted text clipped - 31 lines] > > Later... Karl Karl E. Peterson - 29 Nov 2006 21:29 GMT Hi Greg --
> Would you have anything that demonstrated this raise and sink events > idea that you mentioned? Lots! Most of it, though, is geared towards VB5/6 as that's where I do most of my work. As far as raising events goes, I do have a few that are very useful in VBA. For example, I have an INI class that will raise an event for each section in an INI file, and for each entry in an INI file section. Very useful for exploring one of those to see what's there...
http://vb.mvps.org/samples/kpIni
Another one geared directly at VBA provides a timer object, and raises events at a specified interval...
http://vb.mvps.org/samples/TimerObj
Here's another that drills into a directory, and optionally its subdirectories, and raises an event for each file/folder found...
http://vb.mvps.org/samples/DirDrill
Sinking events is very often associated with windows in my world. For instance, I have a class that will search a listbox as the user types. In order to do that, you pass the ListBox to the class, and it monitors keystrokes...
http://vb.mvps.org/samples/ListSearch
You can have classes arranged hierarchically, such that they send information "up the chain." For instance, taking this to the extreme, I have a set of classes that break down a Long integer into its constituent 16-bit Integers, and further into each Byte within that. When one of the smaller portions changes, it fires an event so the larger whole is aware. This sample's classes both raise and sink events...
http://vb.mvps.org/samples/Twiddle
Now, if you want to really get adventurous, you can start subclassing, and rerouting system callbacks to appropriate class instances, then re-raising those as events for your client objects, then . . . <vbg>
 Signature Working without a .NET? http://classicvb.org/
Greg Maxey - 29 Nov 2006 22:27 GMT Karl,
Thanks for these links. I sense it may be really deep end stuff and over my head. Still, I'll dive into a few and see if any of it sticks.
 Signature Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
> Hi Greg -- > [quoted text clipped - 40 lines] > rerouting system callbacks to appropriate class instances, then re-raising > those as events for your client objects, then . . . <vbg> Karl E. Peterson - 29 Nov 2006 23:15 GMT > Thanks for these links. I sense it may be really deep end stuff and > over my head. Still, I'll dive into a few and see if any of it > sticks. It's the concept of communication that's important. Not sure if you can do it in Word, but I've set up a class in Excel to sink events raised by the Application. If I read the Object Browser correctly, it should be doable in Word as well. Just create a new class, and add this up top:
Private WithEvents app As Application
Then, select "app" in the left-side dropdown, and take a look at all the events offered in the right-side dropdown! Here, you can react to all sorts of useful things. The only difference between this case, and the ones I described earlier, is that it was my classes raising the events as well. It goes two ways.
Later... Karl
 Signature Working without a .NET? http://classicvb.org/
>> Hi Greg -- >> [quoted text clipped - 44 lines] >> Working without a .NET? >> http://classicvb.org/ Jean-Guy Marcil - 30 Nov 2006 17:35 GMT Greg Maxey was telling us: Greg Maxey nous racontait que :
> Karl, > > Thanks for these links. I sense it may be really deep end stuff and > over my head. Still, I'll dive into a few and see if any of it > sticks. As a practical example, recently I had a contract that required creating a Meeting Agenda Template.
Their meeting documents were complex and numerous, so, in the agenda, they always had hyperlinks to point to those reference documents. But, when adding a hyperlink to a reference document, that reference document needed to be "treated" (Information from the agenda had to be adder to that document). Also, a list needed to be created at anytime listing the currently attached documents, their agenda paragraphs text and list number, etc.
I wrote code to automate those procedures as much as possible.
I created a class I called "Attachment" (or something like that) This class had four methods: Attach a document Detach document Detach all documents List all document currently attached to the agenda Some of them accepted a Range parameter (the Attach and Detach ones).
So, wherever in my code I need to do these things, all I needed to do was, for example:
Dim myAttach As New Attachment myAttach.Add_Attach Selection.Paragraphs(1).Range
where Add_Attach is a method of the Attachment class.
The method I used the most through out the code was the one for listing the attachments.
I needed that every time I attached a document (to make sure it was not already attached), when I detached, When I validated the whole document, when I created PDF files from the Agenda (so I could get to the Attachments easily and convert them as well), etc.
It made my code in the standard module easier to read, less cluttered and overall shorter. And if the client had wanted to attach the documents in a different manner, all I would have to do is modify the code in the class and leave the code in the standard module intact.
I hope I did not contribute to your headaches and made sense here...
 Signature Salut! _______________________________________ Jean-Guy Marcil - Word MVP jmarcilREMOVE@CAPSsympatico.caTHISTOO Word MVP site: http://www.word.mvps.org
Greg Maxey - 30 Nov 2006 23:42 GMT JGM,
Thanks for the post. Right now my skull is cracking with frustration of content controls and XML mapping. All new stuff to me. When I get my head clear I will come back to these class pieces and try to get a better understanding. Appreciate your time and input.
 Signature Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
> Greg Maxey was telling us: > Greg Maxey nous racontait que : [quoted text clipped - 49 lines] > > I hope I did not contribute to your headaches and made sense here... Jonathan West - 30 Nov 2006 16:38 GMT > What again is the benefit of using a Class? That is a very good question to ask.
First of all, there are some people who are so enamoured of classes that they believe you should never ever write purely procedural code and that *everything* should be a class. They are attached to that position with a fervour that borders on the religious. If that is an arrangement that happens to work for them, all well and good. Their certainty can be infectious, but it is wiser to avoid it and look at the actual evidence.
For simpler tasks (which, let us be blunt, includes the vast majority of Word macros) procedural code is perfectly adequate. There are very few cases where my answer to a question in these groups starts with the words "first, create a class module".
So it is worth looking at what classes are good for.
Of course, you *use* classes all the time, you just don't think of them as such. The whole of the Word object model is an intricate interlinked series of classes. The Application object is a class, which has lots of properties and methods and events. One of those properties is the ActiveDocument property which is a Document class, again with its own set of properties, methods and events. You probably haven't been thinking of them as classes because they aren't written in VBA and you can't see the code, but the way you use them is almost exactly the same as how you would use your own custom-built class.
This gives us a clue as to when it would be useful to write a class. The key is when you are likely to want to re-use the code in a variety of projects and different ways.
Properties of a class can look on the surface much the same as items in a user-defined type. The difference is that with a class, you can if you choose have a change to one property trigger a change to others. For instance, in the PageSetup object in Word, if you set the PageHeight property to be some value, the PageSize property is automatically set to Custom, rather than A4 or Letter or whatever it was before. You can do the same sort of thing in the property procedures of your own class module.
Events are also potentially very useful things to have. An event is essentially a way of saying "tell anybody who is listening that xyz has happened, and wait until they have done whatever they need to do as a result". It may be that other process is listening to that event, in which case the code in the class carries on immediately. This gives you great flexibility on how you use a class, once you have taken the trouble to create it.
I don't often write classes, but I am a regular consumer of them, and owe a considerable debt of gratitude to Karl for some of his published classes which I use on a regular basis. Almost every commercial project I do makes use of one or more of his Drvinfo, FileInfo, kpIni, NCMetrics, PrnInfo, RegSettings and StrBldr code samples, all of which make use of class modules. RegSettings and NCMetrics are used in almost everything I do, the others are used as needed. (see http://vb.mvps.org/samples/ for the list of Karl's samples)
If you want a tutorial on how to create classes (I have been concentrating in this post on "why" rather than "how"), take a look at these two excellent articles by Ken Getz and Mike Gilbert. It appears they are no longer available on the Microsoft website, but the Wayback Machine rides to the rescue!
Class Modules: Simplify and Accelerate Your Development Processes http://web.archive.org/web/20050306011820/http://www.microsoft.com/OfficeDev/Art icles/classmod.htm
Advanced Class Modules http://web.archive.org/web/20050306005832/http://www.microsoft.com/OfficeDev/Art icles/AdvClMod.htm
 Signature Regards Jonathan West - Word MVP www.intelligentdocuments.co.uk Please reply to the newsgroup Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
Karl E. Peterson - 30 Nov 2006 17:43 GMT >> What again is the benefit of using a Class? > > That is a very good question to ask. And a fine answer indeed! I bow to your wordsmithing, and slither off to my IDE. :-)
Thanks... Karl
 Signature Working without a .NET? http://classicvb.org/
Greg Maxey - 30 Nov 2006 18:15 GMT Jonthan/Karl
Yes it was and thank you both for answering. Karl I looked at some of your examples and as feared they are deep end stuff. Perhaps after reviewing the two articles that Jonathan referenced I will understand a bit better.
Jonathan, I am looking at the first article now and must say the section on
"Creating Object Collections" is a little incomplete and if I was completely ignorant of VBA then I would have had to give up in frustration.
First it doesn't declare a Collection. It doesn't initiate the collection. It doesnt' initiate an new instance of the class for the second new student
Sub TestclsStudentCollection() Dim Students As Collection Dim oNewStudent As Student Set Students = New Collection Set oNewStudent = New Student With oNewStudent .FirstName = "Bart" .LastName = "Simpson" .BirthDate = "12/31/1958" End With Students.Add oNewStudent, oNewStudent.FirstName Set oNewStudent = New Student With oNewStudent .FirstName = "Lisa" .LastName = "Simpson" .BirthDate = "07/14/1962" End With Students.Add oNewStudent, oNewStudent.FirstName Students.Item("Lisa").Speak End Sub
> >> What again is the benefit of using a Class? > > [quoted text clipped - 4 lines] > > Thanks... Karl Jonathan West - 30 Nov 2006 18:49 GMT > Jonthan/Karl > [quoted text clipped - 9 lines] > completely ignorant of VBA then I would have had to give up in > frustration. If you were completely ignorant of VBA, I wouldn't have pointed you to the article in the first place :-)
> First it doesn't declare a Collection. It doesn't initiate the > collection. It doesnt' initiate an new instance of the class for the > second new student I agree that the Collection declaration and initialisation are missing. But see my comments below about the Student instances
> Sub TestclsStudentCollection() > Dim Students As Collection 'This is the collection declaration 'which is missing from the article
> Dim oNewStudent As Student > Set Students = New Collection 'This initializes the collection 'currently contains nothing
> Set oNewStudent = New Student 'this defines an instance of a Student > With oNewStudent 'this block assigns values to the [quoted text clipped - 3 lines] > End With > Students.Add oNewStudent, oNewStudent.FirstName 'the line above adds the Student instance to the collection, 'assigning the student's Firstname to the item name. 'Since the instance is now in the collection, the original 'reference to it can be dropped, and oNewStudent reused.
> Set oNewStudent = New Student 'Which is precisely what happens here. > With oNewStudent 'The properties are assigned to the [quoted text clipped - 3 lines] > End With > Students.Add oNewStudent, oNewStudent.FirstName 'and it is added to the Collection
> Students.Item("Lisa").Speak > End Sub
 Signature Regards Jonathan West - Word MVP www.intelligentdocuments.co.uk Please reply to the newsgroup Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
Greg Maxey - 30 Nov 2006 23:45 GMT Jonathan,
I follow all of your comments. I am both honored and appalled that you don't feel that I am completely ignorant of VBA ;-)
Thanks for the help.
 Signature Greg Maxey/Word MVP See: http://gregmaxey.mvps.org/word_tips.htm For some helpful tips using Word.
>> Jonthan/Karl >> [quoted text clipped - 48 lines] >> Students.Item("Lisa").Speak >> End Sub
|
|
|