Help me get my head around Select Case

G

Greg Maxey

I just spent 45 minutes trying to put together a Select Case statement. I
have something that works, but I really don't think that I am employing this
method like it is supposed to be used.

The object is to look at individual paragraphs and apply a style if the
opening words match a string. Example:


Match this text blah, blah, blah

No matching text blah, blah, blah

Match this text blah, blah, blah

Match some other text blah, blah, blah



I want "Match this text" lines Heading 1

I want "Match some other text" lines Heading 2



Here is my code:



Sub Test()
Dim oPar As Paragraph
Dim Match As Boolean
Match = True
For Each oPar In ActiveDocument.Paragraphs
Select Case Match
Case InStr(oPar.Range.Text, "Match this text") = 1
oPar.Style = "Heading 1"
Case InStr(oPar.Range.Text, "Match some other text") = 1
oPar.Style = "Heading 2"
End Select
Next oPar
End Sub


OK it is doing the intended but I nearly cracked my skull trying to figure
it out. Am I doing this right? Thanks.
 
J

Jay Freedman

Hi Greg,

The main thing to know about Select Case is that the test expression
should be a numerical or string expression. If you make it a Boolean
expression instead, you might as well just use If/Then structures.

Here's some code that does what you showed literally. Normally it
wouldn't be as explicit as checking three words at the start of each
paragraph. (The two test strings in each case are needed because the
final space won't be in the range if the paragraph consists of only
the three words followed by a paragraph mark -- just a quirk of the
Words collection.)

Sub Test2()
Dim StartWords As Range
Dim oPara As Paragraph

For Each oPara In ActiveDocument.Paragraphs
If oPara.Range.Words.Count > 2 Then
Set StartWords = ActiveDocument.Range( _
oPara.Range.Start, oPara.Range.Words(3).End)

Select Case StartWords.Text
Case "Match this text", "Match this text "
oPara.Style = "Heading 1"
Case "Match some other", "Match some other "
oPara.Style = "Heading 2"
Case Else
' do nothing
End Select
End If
Next oPara
End Sub

Be aware that in a large document, code like this is going to bog down
as you get toward the end, because the Set statement will take longer
and longer to count out the number of characters from the start of the
document to the start of the paragraph. There are better ways to get
the text; I just didn't waste a lot of time thinking about it because
this is an illustration of Select Case, not text extraction.
 
G

G.G.Yagoda

Select Case is a glorified If statement with a different structure.

If you were using an If statement in your macro, it would be:

For Each oPar in ActiveDocument.Paragraphs
If InStr(oPar.Range.Text, "Match this text") > 0 Then OPar.Style =
"Heading 1.
Next

With Select Case, the first line - Select Case - is what you want to
test, Case is the result of the test, and the next line is what to do
if they match.

(In your example, you did *not* need your Match boolean - that's may
have been confusing you.)

For Each oPar In ActiveDocument.Paragraphs
Select Case InStr(oPar.Range.Text, "Match this text")
Case Is > 0
oPar.Style = "Heading 1"
End Select
Next oPar
End Sub
========================================
Let's try another one.

If oPar.Range.Font.Bold Then oPar.Range.Font.Italics = True

Select Case oPar.Range.Font.Bold
Case True
oPar.Range.Font.Italics = True
End Select
========================================
Another example:

If MyRange.End > ThyRange.End Then Exit For

Select Case MyRange.End
Case Is > ThyRange.End
Exit For
End Select
========================================
Yet another example:

If MyRange.Characters.Last = "x" or MyRange.Characters.Last = "y" or
MyRange.Characters.Last = "z" Then MyRange.Delete

Select Case MyRange.Characters.Last
Case Is = "x"
MyRange.Delete
Case Is = "y"
MyRange.Delete
Case Is = "z"
MyRange.Delete
End Select
========================================
Moving right along:

If ActiveDocument.Range.Characters.Count = 1 Then ActiveDocument.Close
wdDoNotSaveChanges

Select Case ActiveDocument.Range.Characters.Count
Case 1
ActiveDocument.Close wdDoNotSaveChanges
End Select
========================================
And one final example:

If MyRange.Text <> "" Then MyRange.Style = "Title"

Select Case MyRange.Text
Case Is <> ""
MyRange.Style = "Title"
End Select

By Jove, I think you've got it. There's not too much to get!
 
G

G.G.Yagoda

That Case could have multiple results specified instead of just one
came as welcome news. Please revised my example above to read:

Select Case MyRange.Characters.Last
Case Is = "x", "y", "z"
MyRange.Delete
End Select

Live and learn.
 
G

Greg

Jay,

Thanks again. Would something like:

If oPara.Range.Words.Count > 2 Then
Set StartWords = oPara.Range
StartWords.SetRange Start:=StartWords.Start,
End:=StartWords.Words(3).End

Be one of the possible better ways and help eliminate the bogging you
mentioned?
 
J

Jay Freedman

Greg said:
Jay,

Thanks again. Would something like:

If oPara.Range.Words.Count > 2 Then
Set StartWords = oPara.Range
StartWords.SetRange Start:=StartWords.Start,
End:=StartWords.Words(3).End

Be one of the possible better ways and help eliminate the bogging you
mentioned?

I think it might (but I'd be more confident if I tested it on a real
document, which I might or might not get to).

Another way would be to use the Left function grab the first N characters of
oPara.Range.Text in a string, and use that string in the Select Case. You'd
have to choose N to be at least enough characters to distinguish all of the
cases you're interested in, and set up the Case statements with exactly that
many characters in the match strings.

It might be less work to use your original "If Instr" construction. :)
 

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