Solved

Using VBA Find out if range is the first word of a sentence

Posted on 2010-08-27
21
906 Views
Last Modified: 2013-11-25
Hello,

Using VBA in MS Word is there a way to find out if a range is the first word of a sentence.  Suppose my document contains the following sentence:

The quick brown fox jumped over the lazy programmer.

MyRange = "The"

How do I test if MyRange is the first word of the sentence.  Assume the sentence is not the first in the document.

Thanks
0
Comment
Question by:eshurak
  • 7
  • 4
  • 4
  • +2
21 Comments
 
LVL 13

Expert Comment

by:Surone1
ID: 33547109
if myrange = left("The quick brown fox jumped over the lazy programmer."",3) then
msgbox "I WIN"
end if
0
 
LVL 13

Expert Comment

by:Surone1
ID: 33547110
if myrange = left("The quick brown fox jumped over the lazy programmer.",3) then
msgbox "I WIN"
end if
0
 
LVL 13

Expert Comment

by:Surone1
ID: 33547124
0
Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 
LVL 3

Author Comment

by:eshurak
ID: 33547209
Let me put this into context as it's not as simple as you think.  I'm looping through my document searching for words that start with caps.  I want to do something with the words that are not the first word in a sentence.  Lets also say the document is forty pages just to give it some scope.
With searchrange.find
.text = "<[A_Z]"
.MatchWildcards = true
.forward = true
end with

Do while searchrange.find.execute

if not first word in sentence then

debug.print searchrange.text

end if

loop

Open in new window

0
 
LVL 45

Expert Comment

by:aikimark
ID: 33553760
A bit more detail will be helpful.  Your problem description uses a variable (MyRange) that might lead us to believe that it is a word object, rather than a string variable.  Are you describing a selected word in the document?

============
The problem we face will be distinguishing multiple words in the sentence might be identical to the first word in the sentence.  In the example below, I had selected the first word in the sentence in the document and then typed the question marked statements into the Immediate Window.  

How are you iterating the document content?
The SentLoop() routine iterates through the sentences in the document and prints the first "word" in each sentence in the Immediate Window.

NOTE: In MS-Word, a "word" includes the trailing space.
?selection
The 

?selection.Sentences(1)
The quick brown fox jumped over The lazy programmer.  

?selection.Sentences(1).Words(1)
The 


?selection.Sentences(1).Words(7)
The 

===================
Public Sub SentLoop()
  Dim oSent As Range
  For Each oSent In ActiveDocument.Sentences
    Debug.Print oSent.Words(1)
  Next
End Sub

Open in new window

0
 
LVL 3

Author Comment

by:eshurak
ID: 33555162
Hey aikimark - Thanks for your reply see my second post above for the details.
0
 
LVL 45

Accepted Solution

by:
aikimark earned 450 total points
ID: 33555379
This might work.  If you comment the IF and EndIF statements, you will see all the capitalized words, not just those that occur other than the first word.
Option Explicit

Public Sub NotFirstWordCaps()
  Dim searchrange As Range
  Set searchrange = ActiveDocument.Range
  With searchrange.Find
    .Text = "<[A-Z]*[ .,\?]"
    .MatchWildcards = True
    .Forward = True
    .MatchWholeWord = True
  End With
  
  Do While searchrange.Find.Execute
    If searchrange.Start <> searchrange.Sentences(1).Words(1).Start Then
      Debug.Print searchrange.Text, searchrange.Start, searchrange.Sentences(1).Words(1).Start
    End If
  Loop

End Sub

Open in new window

0
 
LVL 45

Expert Comment

by:aikimark
ID: 33555422
For the following document text:
"Now is the Time for all good men to come to the aid of their country.  The quick brown fox jumped over The lazy programmer.  The good the bad the UGLY."

The commented version of the code produces the following lines:

Now            0             0 
Time           11            0 
The            71            71 
The            103           71 
The            125           125 
UGLY.          146           125 

Open in new window

0
 
LVL 76

Assisted Solution

by:GrahamSkan
GrahamSkan earned 50 total points
ID: 33557658
This should answer the original question.
Function IsFirstWord(rng As Range) As Boolean
    Dim sen As Range
    Dim wrd As Range
    
    Set sen = rng.Sentences(1)
    Set wrd = sen.words(1)
    IsFirstWord = rng.InRange(wrd)
End Function

Open in new window

0
 
LVL 16

Expert Comment

by:JohnBPrice
ID: 33557713
Word already has built in sentence parsing, try this



Sub showSentences()
For i = 1 To ActiveDocument.Sentences.Count
    MsgBox ActiveDocument.Sentences(i)
Next

End Sub

Open in new window

0
 
LVL 16

Expert Comment

by:JohnBPrice
ID: 33557721
oops, GrahamSkan beat me to it.
0
 
LVL 45

Expert Comment

by:aikimark
ID: 33558673
@Graham & JohnB

Please try your code with sentences containing the same word in BOTH the first and non-first position in a sentence.  Neither of your routines is able to discriminate between the first and non-first words.
0
 
LVL 16

Expert Comment

by:JohnBPrice
ID: 33558849
erm, the first word is the first word in the sentence.  This, for example, makes every non-first word bold.


Sub showSentences()
For i = 1 To ActiveDocument.Sentences.Count
    For w = 1 To ActiveDocument.Sentences(i).Words.Count
        MsgBox ActiveDocument.Sentences(i).Words(w)
        If w > 1 Then
            ActiveDocument.Sentences(i).Words(w).Bold = True
        End If
    Next
    
Next

End Sub

Open in new window

0
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 33558998
aikimark,

The function works in my tests.
0
 
LVL 45

Expert Comment

by:aikimark
ID: 33559147
@JohnBPrice

Your code is significantly different than what you posted previously.  While it does format (bold) the non-first words in every sentence, it does not handle the scenario posed in the question.  The member is iterating a FIND.EXECUTE method, looking for capitalized words and taking some action if the word is not the first word in the sentence.  You are iterating through all words in all sentences.

Performance tip: Use a For Each...Next looping construction when iterating across collections rather than a regular For...Next loop.  Use a different variable (boolean or long integer) as the basis for programmatic action, such as skipping the first item in a collection.

===============
@GrahamSkan

Your code should return a false positive on the second of my three test sentences:

"The quick brown fox jumped over The lazy programmer."

If passed the word "The"
0
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 33559183
It isn't passed text, it is passed a range.
0
 
LVL 45

Expert Comment

by:aikimark
ID: 33559396
@GrahamSkan

I stand corrected.  I had misread the code and not recognized the InRange() method as the equivalent to Excel VBA's Intersect() method.  Both of our methods use the starting position of the word in their calculations.  My rudimentary tests indicate that their performance is practically identical.

Here is the version of my routine, using the InRange() method, that I used for my testing.
Option Explicit

Public Sub NotFirstWordCaps()
  Dim searchrange As Range
  Set searchrange = ActiveDocument.Range
  With searchrange.Find
    .Text = "<[A-Z]*[ .,\?]"
    .MatchWildcards = True
    .Forward = True
    .MatchWholeWord = True
  End With
  Dim sngStart As Single
  sngStart = Timer
  Do While searchrange.Find.Execute
    If searchrange.InRange(searchrange.Sentences(1).Words(1)) Then
      Debug.Print searchrange.Text, searchrange.Start, searchrange.Sentences(1).Words(1).Start
    End If
  Loop
  Debug.Print "Elapsed ", Timer - sngStart
End Sub

Open in new window

0
 
LVL 76

Expert Comment

by:GrahamSkan
ID: 33559539
I would plug it in to a find loop like this.
Sub FindCapWords()
Dim rng As Range
Set rng = ActiveDocument.Range

With rng.Find
    .MatchWildcards = True
    .Text = "<[A-Z][a-z]{1,}>"
    Do While .Execute
        If Not IsFirstWord(rng) Then
            MsgBox "Propercase word: " & rng.Text & " found"
        End If
        rng.Collapse wdCollapseEnd
        rng.End = ActiveDocument.Range.End
    Loop
End With
End Sub

Function IsFirstWord(rng As Range) As Boolean
    Dim sen As Range
    Dim wrd As Range
    
    Set sen = rng.Sentences(1)
    Set wrd = sen.words(1)
    IsFirstWord = rng.InRange(wrd)
End Function

Open in new window

0
 
LVL 3

Author Comment

by:eshurak
ID: 33559716
Thank you all so much.
0
 
LVL 3

Author Comment

by:eshurak
ID: 33559735
Aikimark, I'd love to understand the second half of

.Text = "<[A-Z]*[ .,\?]"

specifically what's happening after the *
0
 
LVL 45

Expert Comment

by:aikimark
ID: 33560017
>>specifically what's happening after the *

It is looking for the word terminator, following the capitalized word.  It isn't perfect.

==============
GrahamSkan uses a different search string to find capitalized words (a cap letter followed by at least one lower case letter, bounded by the end of the word).
    .Text = "<[A-Z][a-z]{1,}>"

Note: If a word is all caps, the string won't be found.  However, it does have the advantage of not including the word-terminating character.

==============
@GrahamSkan

If packaging the IsFirstWord() code as a function, I would eliminate the variable declarations as a stream-lining method.

Example:

Function IsFirstWord(rng As Range) As Boolean
    IsFirstWord = rng.InRange(rng.Sentences(1).words(1))
End Function

Open in new window

0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Using Word 2013, I was experiencing some incredible lag when typing.  Here's what worked for me....
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
This video walks the viewer through the process of creating Hyperlinks for the web and other documents. Select the "Insert" tab: Click "Hyperlink":  Type "http://" followed by a web address to reference a website or navigate to a document to ref…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question