PDA

View Full Version : Newbie cannot find styles



antobal
02-18-2008, 03:58 AM
Hello,

In Word 2003, I have been trying to write a macro to detect whether any one of three specific styles ("Marker", "Marker1", "Marker2") are used in a document, show the first occurrrence, and warn the user (these styles are not allowed in the final stage of our workflows).

I have been able to do that for one style (mainly by googling and adapting code), but I cannot figure out how to to include the other two styels in the same macro. (Some kind of "Or" statement, or a succession of "Ifs"?

Sub SearchMarker()
'
' SearchMarker Macro
' Macro created 12/02/2008 by Antonio Ballesteros
'
Selection.HomeKey Unit:=wdStory
Selection.Find.Style = ActiveDocument.Styles("Marker")
Selection.Find.Execute
If Selection.Find.Found = True Then
lngUserChoice = MsgBox("Markers were found in this document")
Else
MsgBox ("Markers were not found in this document")
Selection.HomeKey Unit:=wdStory
End If

End Sub

I would really appreciate your help.

Also, I have been looking for a book to get me started in writing Word vba code. Any suggestion for someone with as little expertise as my earlier question shows? Amazon reviews are not helping me.

Antonio

fumei
02-18-2008, 11:52 AM
What...EXACTLY...do you want to happen? From your code, it appears that you simply want a message stating that ANY occurence happened. A straightforward Yes/No. If so, something like:Option Explicit

Sub Whatever()
Dim r As Range
Dim SearchStyles()
Dim var
Dim msg As String
SearchStyles = Array("Marker", "Marker1", _
"Marker2")

For var = 0 To UBound(SearchStyles)
Set r = ActiveDocument.Range
With r.Find
.Style = SearchStyles(var)
If .Execute(Forward:=True) = True Then
msg = msg & SearchStyles(var) & _
" style found." & vbCrLf
End If
End With
Next
MsgBox msg
End Subwould display:

Marker style found
Marker2 style found.

If, say, there is even ONE Marker style, no Marker1, and even ONE Marker2.

In other words, nothing is done other than seeing if there is even one instance of the style listed in the array ("Marker", "Marker1", "Marker2").

What it does:

1. declare two variants (SearchStyles as an array, and var), a Range object (r), and a string variable (msg)

2. set values SearchStyles

3. set r as document range

4. loops through the range object (r), using .Find to find an instance of each of the styles - using the For var = loop

5. if it finds one, it appends that fact as text to a message string. NOTE: if it finds ONE to exist the loop for that style - it does NOT look for any other instances.

6. displays message for named style(s) found.

Even if wanted a counter:Option Explicit

Sub Whatever2()
Dim r As Range
Dim SearchStyles()
Dim var
Dim j As Long
Dim msg As String
SearchStyles = Array("Marker", "Marker1", _
"Marker2")

For var = 0 To UBound(SearchStyles)
Set r = ActiveDocument.Range
With r.Find
.Style = SearchStyles(var)
Do While .Execute(Forward:=True) = True
j = j + 1
Loop
End With
msg = msg & j & " instances of the " & _
SearchStyles(var) & _
" style found." & vbCrLf
Next
MsgBox msg
End Subin which case, you could get a display of something like:

3 instances of the Marker style found.
2 instances of the Marker1 style found.
2,593 instances of the Marker2 style found.

What it does:

1. declare two variants (SearchStyles as an array, and var), a Range object (r), a string variable (msg), and a Long variable (j)

2. set values SearchStyles

3. set r as document range

4. loops through the range object (r), using .Find to find EACH instance of the styles - using the For var = loop

5. EACH instance found increments a counter - j

6. resets Range object to whole document, and goes to next style

7. display message with count of each style found.

If you wanted to change something - say change any instances of Marker style to Yadda style, any instance of Marker1 style to YogiBear style, any instances of Marker2 style to Yippeee style:Sub Whatever3()
Dim r As Range
Dim SearchStyles()
Dim ReplaceStyles()
Dim var
SearchStyles = Array("Marker", "Marker1", _
"Marker2")
ReplaceStyles = Array("Yadda", "YogiBear", _
"Yippeee")
For var = 0 To UBound(SearchStyles)
Set r = ActiveDocument.Range
With r.Find
.Style = SearchStyles(var)
Do While .Execute(Forward:=True) = True
r.Style = ReplaceStyles(var)
r.Collapse wdCollapseEnd
Loop
End With
Next
End Sub

What it does:

1. declare two variants (SearchStyles as an array, and var), a Range object (r), a string variable (msg), and a Long variable (j)

2. set values SearchStyles

3. set r as document range

4. loops through the range object (r), using .Find to find EACH instance of the styles - using the For var = loop

5. replaces EACH instance of the found style with a corresponding style. e.g. Marker becomes Yadda

6. resets Range object to the document

7. searches for next style in array.

Hopefully the above examples will point you in some sort of direction.

One of the first things that will help you write good code is to be very very very explicit in what are your requirements. Fuzziness will return fuzziness.

" warn the user (these styles are not allowed in the final stage of our workflows)."

What does that mean?

Warn them each time it is found? Could that be, say, 137 separate warnings? NOT a good idea.

Warn them that one is found (it would be the first one)...and then stop (for that style)?

Warn them that one is found (it would be the first one)...and then ask them if they want to change it...for THAT instance...but keep on going to the next instance where they may NOT want to change it?

Warn them that one is found (it would be the first one)...and then ask them if they want to change it...and ALL of found instances?

NOT warn them at all, and go right ahead and change the styles?


and on and on. This is logic. It is clearly thinking about what - EXACTLY - you want to happen.

You can write the most intricate elaborate and fancy code in the world, but if it has faulty, or poor, logic....it will remain crappy code.

fumei
02-18-2008, 12:01 PM
NOTE: in the third example it should be noted that if you are doing a replacement then obviously there must be a one-to-one relationship.

Three styles to search for.
Three styles to replace those with.

Could that be done differently? Say, replace all Marker styles (without asking), ask about each instance of Marker1 style, replace all Marker2 styles but ask first?

Yup, yup and yup. Pretty much anything, and any combination, you care to think of.

The coding part is not difficult at all. The logic part - the thinking - is where the work is.

antobal
02-19-2008, 05:16 AM
First of all, thank you for your invaluable help, I am overwhelmed.

Yes, your first guess was correct. I wanted a message simply stating whether or not any of the three styles were used in a document.

I used your Whatever2 code. However, I found a problem with

.Style = SearchStyles(var)

When the styles were not defined in the document template, I received the message:

Runtime error 5834 Item with specified name does not exist

I may have found a workaround by adding a couple of admittedly crude GoTos (my limitations) to your code (On Error GoTo Stylesnotdefined):

Sub SearchMarkers()
Dim r As Range
Dim SearchStyles()
Dim var
Dim j As Long
Dim msg As String
StatusBar = "Search Marker Styles..."
SearchStyles = Array("Marker", "Marker1", _
"Marker2")

For var = 0 To UBound(SearchStyles)
Set r = ActiveDocument.Range
With r.Find
On Error GoTo Stylesnotdefined
.Style = SearchStyles(var)
Do While .Execute(Forward:=True) = True
j = j + 1
Loop
End With
msg = msg & j & " instance(s) of " & _
SearchStyles(var) & _
" style found." & vbCrLf
Next
MsgBox msg
GoTo Yes
Stylesnotdefined:
MsgBox ("No Marker, Marker1 or Marker2 styles found")
Yes:
End Sub

Again, thank you

Antonio

fumei
02-19-2008, 10:58 AM
Yes, you would have to do that. The styles it searches for are hard-coded, in the array.

You have the error redirection in the wrong place though. Or rather, the text of the error message could be incorrect.

Say, there IS a Marker, Marker1 is not a listed style, there IS a Marker2. Here is how the logic will run.

For var = 0 to blah (in this case = 3)

Loop #1
SearchStyles(var) = Marker

Found. Code displays "X instances of Marker style found."

Loop #2
SearchStyles(var) = Marker1

There is no listed style. An error occurs.

Code displays "No Marker, Marker1 or Marker2 styles found"

Loop # 3
SearchStyles(var) = Marker2

Found. Code displays "X instances of Marker2 style found."

So you have THREE separate messages the user must click OK to get rid of.

"X instances of Marker style found."
"No Marker, Marker1 or Marker2 styles found"
"X instances of Marker2 style found."

Not only would this be incorrect information, but annoying.

Combine the messaging logic so it comes out as ONE message:

"X instances of Marker style found.
No Marker1 styles found"
X instances of Marker2 style found."

There is a basic logic question though.

WHY would you be searching for a style that is not there?

"When the styles were not defined in the document template, I received the message:"

Perchance you are actually looking for format rather than style? Here is from your OP:

"I have been trying to write a macro to detect whether any one of three specific styles ("Marker", "Marker1", "Marker2") are used in a document"

My bolding.

You state these ARE styles. If they are styles, how can they not be defined in the document? If they are "specific styles", then they are defined. It is either one way, or the other. If they are specific styles, they are defined. If they are not defined, they are not specific styles.

Better logic, better specs.
Better specs, better code

antobal
02-19-2008, 11:34 AM
"WHY would you be searching for a style that is not there?"

I am trying to find out whether actual text formatted with any of these three styles (they are character styles) is present in a document (styles are "used"), withouth having to check first whether the document template includes those styles; this latter issue is irrelevant for my final objective.

Instead of finding out first if the styles exist in the template, then search for occurrrences in the document, I opted for doing a direct search in the document, to find out if the styles were actually used to format a text string.

Because of that I need the error redirection: If styles do not exist in the template, to avoid the VBA error message

Where I should then place my error redirection?

Regards,

Antonio

fumei
02-21-2008, 11:25 AM
"I am trying to find out whether actual text formatted with any of these three styles (they are character styles) is present in a document (styles are "used"), withouth having to check first whether the document template includes those styles; this latter issue is irrelevant for my final objective. "

I will disagree. It most certainly is NOT irrelevant. Although, it is true that I do not know your final objective. I have sort of asked, but apparently that is irrelevant.

Where to put your error redirection? Where the logic needs it.

antobal
02-21-2008, 05:00 PM
Your first proposal (Whatever, see below) produces a blank message box when the styles exist in the template but they are not actually used to format any text in the document.

How could I have some informative content instead in the message box in such case?

Regards,

Antonio

fumei
02-22-2008, 11:35 AM
"How could I have some informative content instead in the message box in such case?"

By writing it into your logic.

fumei
02-22-2008, 11:42 AM
"Your first proposal (Whatever, see below) "

As I supplied THREE separate versions that you could play around with, I have no idea which one you are talking about.

I am sorry, but I don't think I can help any more as everything you are asking about now is logic, not code. I can not write the logic for you. Well, I could...but I will not.

"when the styles exist in the template but they are not actually used to format any text in the document. "

If the given style in the search pattern exists in the document, but is NOT used.....what do you think the logic is?
With r.Find
.Style = SearchStyles(var)
Do While .Execute(Forward:=True) = True


Logic? If the search does NOT find an example of what it is searching for......


Hint: look at the bold in the code snippet