Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
DiscussionsAccessExcelInfoPathOutlookPowerPointPublisherWord
DirectoryUser Groups
Related Topics
Outlook ExpressInternet ExplorerWindowsMS Server ProductsMore Topics ...

MS Office Forum / Word / Programming / November 2006

Tip: Looking for answers? Try searching our database.

No Class or High Class

Thread view: 
Enable EMail Alerts  Start New Thread
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

Rate this thread:






 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.