Help With Code

F

Fred Goldman

Ok, I just wrote my first code. I was wondering if anyone could tell me how
it could be written better and maybe help me on a few points.

Here's the code:

Set myCharStyle = ActiveDocument.Styles("Drop P'nim")
Set myPara = ActiveDocument.Styles("Body Text2")
Set myChar = ActiveDocument.Styles("Ha'aros")
Do
If Selection.Style = myPara Then
Selection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
Selection.Style = myCharStyle
Selection.MoveDown Unit:=wdParagraph, Count:=1
Selection.HomeKey Unit:=wdLine
Else
Selection.MoveDown Unit:=wdParagraph, Count:=1
End If
Loop Until Selection.Style = myChar


What it does is find every style that I specify and tag the first word with
a character style. I couldn't find a way to tell the loop to exit when it
reaches then end of the document so what I did was tag the last paragrah as
myChar and set the loop to exit when it reaches the last paragraph.

Is there anyway I can improve this code? How would I set myPara to more than
one style?

Thanks in advance!
 
G

Greg Maxey

Fred,

I suppose there are lots of ways to skin a cat (no offense to cat lovers
intended).

Here is one:

Sub Test()
Dim oPar As Paragraph
Dim myRng As Range
For Each oPar In ActiveDocument.Range.Paragraphs
If oPar.Style = "Body Text" Then
Set myRng = oPar.Range.Words(1)
If InStr(myRng.Text, " ") Then
myRng.MoveEnd wdCharacter, -1
End If
myRng.Style = "TestStyle"
End If
Next
End Sub

Greg Maxey
 
H

Helmut Weber

Hi Fred,

try to get used to range-objects.
The macro recorder always uses the selection object,
which may lead beginners to stick to the selection.

Most often it is not necessary to use selection,
it's also slow and needs too much code to control.

Use "Option explicit"
see: Tools, Options, Editor, Require Variable Declaration.
Set myPara = ActiveDocument.Styles("Body Text2")
This is probably not what you want.
You are creating a style object, IMHO,
if Selection.Style = myPara
will return false if you modified a paragraph directly,
by e.g. defining a right indent,
as all of the style of the selection is not equal
to all of the style of the template.

If you use selection.style like
if selection.style = "Normal",
then this returns true, even if you modified the paragraph,
as it checks only for the name of the style, not for all of it.
How would I set myPara to more than one style?

No way. You have to use "or" or "select case".

if selection.style = "Normal" or selection.style = "Normal2"

or:

Sub test500()
Dim oPrg As Paragraph
For Each oPrg In ActiveDocument.Paragraphs
With oPrg.Range.Words(1)
.Select ' for testing using F8, delete after testing!
Select Case oPrg.Style
Case "Normal": .Style = "ChStyle1"
Case "Heading 2": .Style = "ChStyle2"
Case "Heading 3": .Style = "ChStyle3"
End Select
End With
Next
End Sub


Greg's code takes care in addition of the fact,
that an ordinary word in Word may encompass a trailing space,
and avoids formatting of the space by setting up a temporary
range, moving the end of the range to the left, and applying
the formatting to the so shortened range.

Sure, lots of questions left...

HTH

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
F

Fred Goldman

Helmert,

Thank you very much, while Greg gave me working code (thank you, too), you
answered a few of the questions I really wanted to know.

Just a couple more questions:

1) I've noticed both you are setting variables with "Dim As", what exactly
is the difference between "Set" and "Dim As"?

2) What does "Case" mean?

3) I've noticed a lot of people say that they don't want the space after a
word tagged with a character style, what is wrong with that?
 
G

Greg Maxey

Fred,

I am just a novice myself, but I will take a shot at your questions.

Dim As - Is the start of a declaration statement. See:
http://word.mvps.org/FAQs/MacrosVBA/DeclareVariables.htm

Set assigns an object reference to a variable or property. (from VBA help)

You can select "Dim" or "Set" in your VB Editor and then press F1 to see
the help description.

Case is part of the Select Case statement. Again, select the word Case in
your VBE and press F1. It is sort of like saying:
I want to look at the color of the wall. Then "if" the color is blue do
this, "if" red do that, "if" pink then puke.

Look at this simple example.

Type Fred and Greg in a new blank document and then copy the below code to
the VBE. Select Fred in the document and run the code. Then select Greg
and run the code again. Finally, don't select anything.

Sub Test()
Dim oRng As Range 'Declare oRng as as Range Object
Set oRng = Selection.Range 'Make it equal to the Selection.Range
Select Case oRng.Text 'We want to look at the oRng.Text
Case Is = "Fred" 'If it is Fred, then do this:
MsgBox "Hi Fred"
Case Is = "Greg"
MsgBox "Hi Greg" 'If it is Greg then do this:
Case Else
MsgBox "The selected isn't ""Fred"" or ""Greg"""
End Select
Set oRng = Nothing
End Sub

HTH
 
H

Helmut Weber

Hi Fred,
3) I've noticed a lot of people say that they don't want the space after a
word tagged with a character style, what is wrong with that?

hmm, well,
to Word the space is part of a word,
and that's counterintuitive and pointless,
and may lead to confusion.

Formatting spaces as red and blue and black,
for example, could be a way to drive an ordinary user
up the wall, if you would like to do so.

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
G

Greg Maxey

Fred,

Yes, I neglected to answer your last question. There is nothing wrong with
it if it is what you want. Say the character style was "underlined."
Personally I think it would look odd to underline the space after.
 
F

Fred Goldman

Greg and Helmut,

You've both been a great help. Your explanation of "Case" was exceptional. I
think I've got Dim down, too, but it's not clear. At first I thought Dim was
just to name the Data Type, but then why did you have to be so specific to
say it was in the Paragraphs object?

About the spaces, that's a relief because I take care of my own docs anyway.
I think I might hit a major problem down the road (BTW when underlining etc.
I don't tag the space with a char. style).
 
F

Fred Goldman

Scratch that last question. Rather, am I correct if I would say you use Dim
to name a Object as a variable and Set when you want to use a part of a
object (like the name of a paragraph style in your document)?
 
G

Greg Maxey

Fred,

I am not ignoring you. I simply don't feel comfortable trying to provide a
technical explanation to your question. I am a novice and dabbler in VBA
with no formal or professional experience.

It is a little like when I want to draw with a black crayon I pick up a
black crayon. I don't know why it is black I just know it is black ;-)

Since your question is buried several levels deep in this thread, you might
want to post as a new question in a day or so if someone doesn't come in
here to answer.

Sorry I couldn't make it all clear. To tell you the truth there is plenty
in VBA that is still a mystery to me.
 
J

Jay Freedman

Hi Fred,

The Dim statement has two purposes. First, it says what the data type
of the variable is. Second, it causes VBA to allocate memory for the
variable (that is, set aside a specific number of bytes at a specific
address; the number of bytes depends on the data type).

By default, VBA (like VB) lets you be sloppy about this; if you use a
variable name in an assignment statement without naming it in a Dim
statement first, VBA will type it as a Variant. This is a very bad
practice because it won't warn you when you misspelled the name of an
existing variable. To make VBA strict about declarations, include an
Option Explicit statement at the top of each module. See
http://www.word.mvps.org/FAQs/MacrosVBA/DeclareVariables.htm for
discussion.

The Set keyword is a completely different animal. You must use Set at
the beginning of any assignment of an object (as opposed to a simple
data type). An object variable is one that has properties and/or
methods instead of just a value. In Word VBA, simple types are String,
Integer, Long, Boolean, etc. while common object types are Document,
Selection, Range, Paragraph, Shape, etc.

I don't really understand why the Set keyword is necessary. VBA knows
when you need one and when you don't, since it will complain if a
required one is missing or if an invalid one is included. Why not just
drop it from the language? Dunno -- it's just one of those leftovers
from many versions of VB (another one is the insistence on parentheses
around parameters in function calls but not subroutine calls,
described in
http://www.word.mvps.org/FAQs/MacrosVBA/BracketsWithArgmnts.htm).

--
Regards,
Jay Freedman
Microsoft Word MVP
Email cannot be acknowledged; please post all follow-ups to the
newsgroup so all may benefit.
 
T

Tony Jollans

I don't really understand why the Set keyword is necessary. VBA knows
when you need one and when you don't, since it will complain if a
required one is missing or if an invalid one is included. Why not just
drop it from the language? Dunno -- it's just one of those leftovers
from many versions of VB

When neither Let nor Set is specified, VBA assumes Let. If Let is invalid in
the circumstances VBA will complain where it could perhaps assume Set.

Even if VBA did that, however, Set would still be required in the language
as long as Variant types and/or default Properties are allowed. Consider the
statement ...

MyVar = ActiveDocument

When MyVar is (implicitly or explicitly) a Variant, does it mean

Set MyVar = ActiveDocument

Or

Let MyVar = ActiveDocument.Content.Text ' or whatever the default is

Without an explicit Set keyword what should VBA do? You could argue that
MyVar should be explicitly typed - and indeed it should - but there are
occasions when data have to be Variants and there is much existing code
which would fail if Set were dropped from the language.
 
F

Fred Goldman

Thank you, Jay, for the info. That is what I thought in the beginning, but
then why did Greg and Helmut write "Dim oPrgh As Paragraph" shouldn't they
have written Dim oPrgh As Object" since "Paragraph" isn't a data type?
 
J

Jay Freedman

When neither Let nor Set is specified, VBA assumes Let. If Let is invalid in
the circumstances VBA will complain where it could perhaps assume Set.

Even if VBA did that, however, Set would still be required in the language
as long as Variant types and/or default Properties are allowed. Consider the
statement ...

MyVar = ActiveDocument

When MyVar is (implicitly or explicitly) a Variant, does it mean

Set MyVar = ActiveDocument

Or

Let MyVar = ActiveDocument.Content.Text ' or whatever the default is

Without an explicit Set keyword what should VBA do? You could argue that
MyVar should be explicitly typed - and indeed it should - but there are
occasions when data have to be Variants and there is much existing code
which would fail if Set were dropped from the language.

Hi Tony,

I grant you your point, and "dropped from the language" is too strong
-- I should have said "made optional whenever possible". It indicates
that the developers of the VBA interpreter haven't really done as much
as they could do to ease the burden on programmers.

If MyVar *is* explicitly declared as an object type, then the Set
keyword should be optional. That is,

Dim MyVar As Document
MyVar = ActiveDocument

should not result in an error; the interpreter has all the information
it needs to decide what to do. Only in the ambiguous case should it
complain -- and then the error message should say there's an
"ambiguous reference" and both options (using Set with the object
reference or omitting Set and using an explicit property of the
object) should be listed.

--
Regards,
Jay Freedman
Microsoft Word MVP
Email cannot be acknowledged; please post all follow-ups to the
newsgroup so all may benefit.
 
J

Jay Freedman

Hi Fred,

Actually, Paragraph is a data type, or at least a kind of object. The
one called Object with a capital O is only the most general kind of
object, but there are dozens of more specialized ones.

The Help topic for the Dim statement says that the "type" parameter
is:

"Data type of the variable; may be Byte, Boolean, Integer, Long,
Currency, Single, Double, Decimal (not currently supported), Date,
String (for variable-length strings), String * length (for
fixed-length strings), Object, Variant, a user-defined type, or an
object type."

That last item, "an object type", includes any of the more specialized
objects -- Document, Paragraph, Sentence, Character; Dialog; Shape,
InlineShape; Range; and on and on. Whenever you know exactly what kind
of object your variable is, you should put that into the Dim
statement. Otherwise you won't have easy access to the properties and
methods that belong to the more specialized type.

--
Regards,
Jay Freedman
Microsoft Word MVP
Email cannot be acknowledged; please post all follow-ups to the
newsgroup so all may benefit.
 
F

Fred Goldman

Thanks Jay, I think I finally have it down now thanks to you and the rest of
the gang.
 
T

Tony Jollans

I do agree. Where there is no ambiguity, Set could (and probably should) be
assumed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top