Solved

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

Posted on 2010-08-27
21
897 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
 
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Preface: When I started this series, I used the term CommandBars because that is the Office Object class that it discusses. Unfortunately, when Microsoft introduced Office 2007, they replaced the standard Commandbar menus with "The Ribbon" and rem…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Office 365 is currently available in five editions. Three of them are for business use: Office 365 Business Essentials, Office 365 Business, and Office 365 Business Premium. Two of them are for home/personal use: Office 365 Home and Office 365 Perso…
This Experts Exchange video Micro Tutorial shows how to tell Microsoft Office that a word is NOT spelled correctly. Microsoft Office has a built-in, main dictionary that is shared by Office apps, including Excel, Outlook, PowerPoint, and Word. When …

757 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now