Strategy for Testing a Series of Words

R

Ridge Kennedy

Office 2003, Windows XP

I'm working on a macro that my users can use to select a headline that is
all uppercase, and convert it to a caps/lowercase headline. Title case gets
me part of the way there, but some words, like "and" and "for" and "to,"
etc., need to be lowercase.

I have some code that seems workable -- at least it works with *one* word,
but I want to have it check a list of common words (It can never be perfect,
but it can be pretty helpful, eliminated a lot of manual editing). Seems
like making a long list of if statements would be clumsy. So I'm looking for
a way to test a list of words, and ideally, a way to make the list fairly
easy to update.

I can use the LCASE or UCASE functions to get accurate tests -- be sure the
state of capitalization of the document won't goof the comparisons.

So here's the general approach I'm taking. Pointers in good directions are
appreciated.

*******

Public Sub HeadlineWordChecker()
'a procedure to inspect each word in a block of text
' that is all uppercase, and make it caps/lowercase
' in newspaper headline fashion

Dim MyRange As Range
Dim oDoc As Document
Dim wrd As Object
Dim strWrd As String

Set oDoc = ActiveDocument
' user will be prompted to select range manually
Set MyRange = Selection.Range
Selection.Collapse wdCollapseStart ' ready to edit the headline further,
if necessary

Set wrd = MyRange.Words(1)

For Each wrd In MyRange.Words
strWrd = Trim(wrd.Text) ' trim the extra space following a word

If strWrd = "IS" Then wrd.Font.Bold = True ' making it bold for test
purposes
' code goes here to
' to say if it's not the first word, and it is on my list of words,
' make it all lower case

Next

End Sub

Any assistance appreciated.

Sincerely,

Ridge in New Joisey [Exit 145]
 
J

Jezebel

The Words collection may bring you some grief. 'Word' in this context is not
defined as you might expect -- hyphens are treated as punctuation, so (eg)
"sub-process" is treated as three words; your code would end up with
Sub-Process which might or might not be want you want. Also, in this
context, using For...Each on the Words collection won't work if you make
changes to the words in the collection -- you'll end up processing the first
word for ever.

As for your main code, the main issue is the maintainability of the list of
words -- inevitably you'll want to tweak this. Maybe something along these
lines --

Const pWordCount As Long = 3

Dim pIndex1 As Long
Dim pIndex2 As Long
Dim pWord As Word.Range
Dim pFlag As Boolean
Dim pRange As Word.Range
Dim pText As String
Dim pWords(1 To pWordCount) As String

pWords(1) = "IS"
pWords(2) = "AND"
pWords(3) = "THE"

Set pRange = Selection.Range
For pIndex1 = 1 To pRange.Words.Count
Set pWord = pRange.Words(pIndex1)

pText = UCase$(Trim$(pWord))
pFlag = True
For pIndex2 = 1 To pWordCount
If UCase(pText) = pWords(pIndex2) Then
pFlag = False
Exit For
End If
Next

If pFlag Then
pWord = UCase$(Left$(pWord, 1)) & LCase$(Mid$(pWord, 2))
Else
pWord = LCase$(pWord)
End If

Next



But simpler still is to adopt the modern convention of using sentence case
for headings, in which case all you need is

Selection = UCase(Left(Selection, 1)) & LCase(Mid(Selection, 2))




Ridge Kennedy said:
Office 2003, Windows XP

I'm working on a macro that my users can use to select a headline that is
all uppercase, and convert it to a caps/lowercase headline. Title case
gets me part of the way there, but some words, like "and" and "for" and
"to," etc., need to be lowercase.

I have some code that seems workable -- at least it works with *one* word,
but I want to have it check a list of common words (It can never be
perfect, but it can be pretty helpful, eliminated a lot of manual
editing). Seems like making a long list of if statements would be clumsy.
So I'm looking for a way to test a list of words, and ideally, a way to
make the list fairly easy to update.

I can use the LCASE or UCASE functions to get accurate tests -- be sure
the state of capitalization of the document won't goof the comparisons.

So here's the general approach I'm taking. Pointers in good directions are
appreciated.

*******

Public Sub HeadlineWordChecker()
'a procedure to inspect each word in a block of text
' that is all uppercase, and make it caps/lowercase
' in newspaper headline fashion

Dim MyRange As Range
Dim oDoc As Document
Dim wrd As Object
Dim strWrd As String

Set oDoc = ActiveDocument
' user will be prompted to select range manually
Set MyRange = Selection.Range
Selection.Collapse wdCollapseStart ' ready to edit the headline
further, if necessary

Set wrd = MyRange.Words(1)

For Each wrd In MyRange.Words
strWrd = Trim(wrd.Text) ' trim the extra space following a word

If strWrd = "IS" Then wrd.Font.Bold = True ' making it bold for
test purposes
' code goes here to
' to say if it's not the first word, and it is on my list of words,
' make it all lower case

Next

End Sub

Any assistance appreciated.

Sincerely,

Ridge in New Joisey [Exit 145]
 
G

Greg Maxey

I use this:

Sub TitleCaseWithLowerCase()
Application.ScreenUpdating = False
'Capitalize all words in selection
Selection.FormattedText.Case = wdTitleWord
'Uncapitalize the listed words
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

Call DoTitleCase("The ")
Call DoTitleCase("Of ")
Call DoTitleCase("And ")
Call DoTitleCase("Or ")
Call DoTitleCase("But ")
Call DoTitleCase("A ")
Call DoTitleCase("An ")
Call DoTitleCase("To ")
Call DoTitleCase("In ")
Call DoTitleCase("With ")
Call DoTitleCase("From ")
Call DoTitleCase("By ")
Call DoTitleCase("Out ")
Call DoTitleCase("That ")
Call DoTitleCase("This ")
Call DoTitleCase("For ")
Call DoTitleCase("Against ")
Call DoTitleCase("About ")
Call DoTitleCase("Between ")
Call DoTitleCase("Under ")
Call DoTitleCase("On ")
Call DoTitleCase("Up ")
Call DoTitleCase("Into ")
'Uncomment the next line if you want the selection dismissed.
'Selection.Collapse wdCollapseStart
're-capitalize first word in title
Selection.Characters(1).Case = wdUpperCase
End Sub

Sub DoTitleCase(FindText As String)
'This procedure is called from TitleCaseWithLowerCase above
Dim oRng As Range
Set oRng = Selection.Range
With oRng.Find
.ClearFormatting
.Text = FindText
.Replacement.Text = "^&"
.Forward = True
.Wrap = wdFindStop
.MatchCase = True
.MatchWholeWord = True
While .Execute
oRng.FormattedText.Case = wdLowerCase
Wend
End With
End Sub

--
Greg Maxey/Word MVP
See:
http://gregmaxey.mvps.org/word_tips.htm
For some helpful tips using Word.

The Words collection may bring you some grief. 'Word' in this context
is not defined as you might expect -- hyphens are treated as
punctuation, so (eg) "sub-process" is treated as three words; your
code would end up with Sub-Process which might or might not be want
you want. Also, in this context, using For...Each on the Words
collection won't work if you make changes to the words in the
collection -- you'll end up processing the first word for ever.

As for your main code, the main issue is the maintainability of the
list of words -- inevitably you'll want to tweak this. Maybe
something along these lines --

Const pWordCount As Long = 3

Dim pIndex1 As Long
Dim pIndex2 As Long
Dim pWord As Word.Range
Dim pFlag As Boolean
Dim pRange As Word.Range
Dim pText As String
Dim pWords(1 To pWordCount) As String

pWords(1) = "IS"
pWords(2) = "AND"
pWords(3) = "THE"

Set pRange = Selection.Range
For pIndex1 = 1 To pRange.Words.Count
Set pWord = pRange.Words(pIndex1)

pText = UCase$(Trim$(pWord))
pFlag = True
For pIndex2 = 1 To pWordCount
If UCase(pText) = pWords(pIndex2) Then
pFlag = False
Exit For
End If
Next

If pFlag Then
pWord = UCase$(Left$(pWord, 1)) & LCase$(Mid$(pWord, 2))
Else
pWord = LCase$(pWord)
End If

Next



But simpler still is to adopt the modern convention of using sentence
case for headings, in which case all you need is

Selection = UCase(Left(Selection, 1)) & LCase(Mid(Selection, 2))




Ridge Kennedy said:
Office 2003, Windows XP

I'm working on a macro that my users can use to select a headline
that is all uppercase, and convert it to a caps/lowercase headline. Title
case gets me part of the way there, but some words, like "and"
and "for" and "to," etc., need to be lowercase.

I have some code that seems workable -- at least it works with *one*
word, but I want to have it check a list of common words (It can
never be perfect, but it can be pretty helpful, eliminated a lot of
manual editing). Seems like making a long list of if statements
would be clumsy. So I'm looking for a way to test a list of words,
and ideally, a way to make the list fairly easy to update.

I can use the LCASE or UCASE functions to get accurate tests -- be
sure the state of capitalization of the document won't goof the
comparisons. So here's the general approach I'm taking. Pointers in good
directions are appreciated.

*******

Public Sub HeadlineWordChecker()
'a procedure to inspect each word in a block of text
' that is all uppercase, and make it caps/lowercase
' in newspaper headline fashion

Dim MyRange As Range
Dim oDoc As Document
Dim wrd As Object
Dim strWrd As String

Set oDoc = ActiveDocument
' user will be prompted to select range manually
Set MyRange = Selection.Range
Selection.Collapse wdCollapseStart ' ready to edit the headline
further, if necessary

Set wrd = MyRange.Words(1)

For Each wrd In MyRange.Words
strWrd = Trim(wrd.Text) ' trim the extra space following a
word If strWrd = "IS" Then wrd.Font.Bold = True ' making it bold
for test purposes
' code goes here to
' to say if it's not the first word, and it is on my list of
words, ' make it all lower case

Next

End Sub

Any assistance appreciated.

Sincerely,

Ridge in New Joisey [Exit 145]
 
R

Ridge Kennedy

"Jezebel" said:
The Words collection may bring you some grief. 'Word' in this context is
not defined as you might expect -- hyphens are treated as punctuation

And a headline may have colons, commas as such. Good to know.
As for your main code, the main issue is the maintainability of the list
of words --

Yup, I could see that was an issue.
Const pWordCount As Long = 3

In this case, the constant will be set equal to the number of words in the
list? Add a word, then increment the constant?

Foolish question: Why to you preface all the variable names with the
lowercase "p"?
Dim pIndex1 As Long
Dim pIndex2 As Long
Dim pWord As Word.Range
Dim pFlag As Boolean
Dim pRange As Word.Range
Dim pText As String
Dim pWords(1 To pWordCount) As String

pWords(1) = "IS"
pWords(2) = "AND"
pWords(3) = "THE"

Set pRange = Selection.Range

Now we go through all the "words" in the selected range. The puncutation
marks
don't have an upper or lowercase, so they're not affected
For pIndex1 = 1 To pRange.Words.Count
Set pWord = pRange.Words(pIndex1)

pText = UCase$(Trim$(pWord))
pFlag = True

And now we go through the list of words to be set as lowercase
If it's on the list, pFlag is going to be set false
For pIndex2 = 1 To pWordCount
If UCase(pText) = pWords(pIndex2) Then
pFlag = False
Exit For
End If
Next

The default for pFlag is true? If pFlag is true, then cap the word -- rest
is lowercase
If pFlag Then
pWord = UCase$(Left$(pWord, 1)) & LCase$(Mid$(pWord, 2))

If pFlag is false, lowercase the word
Else
pWord = LCase$(pWord)
End If

Next

And I'd need to do something, at some point, to be sure that the first word
is capitalized. Maybe an "if" that says if pIndex2 = 1, then pFlag must be
true??
But simpler still is to adopt the modern convention of using sentence case
for headings, in which case all you need is

I guess Word would do it's best to identify proper names. I guess I could
float that
but the designer in me says that I really like C/LC. I love ink (well,
toner) on paper,
what can I say.
Selection = UCase(Left(Selection, 1)) & LCase(Mid(Selection, 2))

Thank you, ma'am.

R.
 
R

Ridge Kennedy

Greg Maxey said:
I use this:

I really like idea of the function -- it makes it look more maintainable.
One question inserted below.

Sub TitleCaseWithLowerCase()
Application.ScreenUpdating = False
'Capitalize all words in selection
Selection.FormattedText.Case = wdTitleWord
'Uncapitalize the listed words
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

Call DoTitleCase("The ")
Call DoTitleCase("Of ")
Call DoTitleCase("And ")
Call DoTitleCase("Or ")
Call DoTitleCase("But ")
Call DoTitleCase("A ")
Call DoTitleCase("An ")
Call DoTitleCase("To ")
Call DoTitleCase("In ")
Call DoTitleCase("With ")
Call DoTitleCase("From ")
Call DoTitleCase("By ")
Call DoTitleCase("Out ")
Call DoTitleCase("That ")
Call DoTitleCase("This ")
Call DoTitleCase("For ")
Call DoTitleCase("Against ")
Call DoTitleCase("About ")
Call DoTitleCase("Between ")
Call DoTitleCase("Under ")
Call DoTitleCase("On ")
Call DoTitleCase("Up ")
Call DoTitleCase("Into ")
'Uncomment the next line if you want the selection dismissed.
'Selection.Collapse wdCollapseStart
're-capitalize first word in title
Selection.Characters(1).Case = wdUpperCase
End Sub

Sub DoTitleCase(FindText As String)
'This procedure is called from TitleCaseWithLowerCase above
Dim oRng As Range
Set oRng = Selection.Range
With oRng.Find
.ClearFormatting
.Text = FindText

Following just replaces the search word with itself?
More efficient that just using find or ... ?
 
R

Ridge Kennedy

Thank you, wise and experienced ones, for the warnings and ideas about how
best to do this.

So, one more, more general question, related to the maintainability of it.

The capability is something that wants to be available to some specific
templates I'm working on. But if it's template specific, it's going to be
harder to maintain.

Is this the sort of thing that would likely be stored in a global template
copied frsh daily at logon using logon script to the Word>Startup directory?
If so, Would a macro button reference it directly, or would you have some
code that would "call" this from the global template (I think I know the
answer -- fully qualify the name of the procedure and go straight to the
template??).

Thnaks,

Ridge
 
J

Jezebel

Ridge Kennedy said:
"Jezebel" said:


And a headline may have colons, commas as such. Good to know.


Yup, I could see that was an issue.


In this case, the constant will be set equal to the number of words in the
list? Add a word, then increment the constant?


Exactly so.


Foolish question: Why to you preface all the variable names with the
lowercase "p"?


I sue the first letter of the variable name to identify the scope of the
variable: p = procedure, m = module, g = global. The other common convention
is to use a prefix to show data type (o = object, s = string, etc). My
experience is that scoping is a much more critical issue. If you get the
data types wrong, provided you're not using variants, you find out about it
right away because the compiler tells you about it and points to the line
where you got it wrong. Scoping errors are much harder to deal with. There's
also a naming convention that shows both type and scope -- but the variable
names end up long and ugly.


Now we go through all the "words" in the selected range. The puncutation
marks
don't have an upper or lowercase, so they're not affected


And now we go through the list of words to be set as lowercase
If it's on the list, pFlag is going to be set false


The default for pFlag is true? If pFlag is true, then cap the word -- rest
is lowercase

If pFlag is false, lowercase the word


And I'd need to do something, at some point, to be sure that the first
word
is capitalized. Maybe an "if" that says if pIndex2 = 1, then pFlag must be
true??

Good point.

I guess Word would do it's best to identify proper names. I guess I could
float that
but the designer in me says that I really like C/LC. I love ink (well,
toner) on paper,
what can I say.


You could say that in good design, form follows function, and the better the
design, the less ink on the page.
 
J

Jezebel

Put it in an add-in (a template stored in Word's STARTUP folder). Add a menu
or toolbar to the add-in.
 

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