Solved

.net MS Word Interop - Find text and return a Word.Range

Posted on 2008-10-24
7
2,309 Views
Last Modified: 2012-05-05
What I'm trying to do is take Indentifiers that I type into a word doc and set bookmarks on them.

Say I have a Word Doc with the following text

"The Raven" is a narrative poem by the American <Goody> Edgar Allan Poe, first published in January 1845. It is noted for its musicality, <HereIAm> language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, <AnotherWord> the man's slow descent into madness. The lover, often identified as being a student,[1][2] is lamenting the loss of his love, Lenore. The raven, sitting on a bust of Pallas, seems to further instigate his distress with its constant repetition of the word, "Nevermore". Throughout the poem, Poe makes allusions to folklore and various classical works.

I Would like to use something like a Regex to find strings formated like <[SomeText]> and then create a bookmark over <[SomeText]>. IE, in the above paragraph I would create bookmarks fro <AnotherWord>, <Goody>, And <HereIAm>

To do this using Word, I would highlight the <[SomeText]> then goto Insert->Bookmark.

I believe I can figure out how to add the bookmark as long as I get can a Range object that covers the text range of the <[SomeText]> identifier. I've tried running a regex on the Word.Content.Text using Text.RegularExpression.Regex and I get find the matches but when I try to create a range from the starting index of the match and the index of the last character its not selecting the right text.

Another problem that I noticed, is if Word.Content.Text is used, it does not return text that is inside a head or footer. I will also need code that can find these identifiers within header and footer fields.

Thanks
0
Comment
Question by:joshkrak
  • 4
  • 3
7 Comments
 
LVL 76

Expert Comment

by:GrahamSkan
Comment Utility
Word has its own Find method which can use Wild Cards similar to Regular expressions.

It is a method of a Range (or Selection) object and will set the object to the found range.

This is a VBA snippet to set a series of bookmarks. I accepts text between the <> signs provided that is comprises letters or space characters.
    Dim doc As Word.Document

    Dim rng As Word.Range

    '...

    Set rng = doc.Range.Duplicate

    Dim i As Integer

    With rng.Find

        .Text = "\<[A-Za-z ]{1,}\>"

        .MatchWildcards = True

        Do While .Execute()

            i = i + 1

            doc.Bookmarks.Add "bmk" & i, rng

            rng.Collapse wdCollapseEnd

            rng.End = doc.Range.End

        Loop

    End With

Open in new window

0
 

Author Comment

by:joshkrak
Comment Utility
Thank you for the help. Your solution does for for the most part but there are some problems

First, just so I'm clear, I'm not working inside of the Word app so its not just a macro I'm looking for. However, the interop dll supplied by microsoft to automate Word in .Net uses the same basic syntax and object naming so I was easily able to convert your solution.

The problems I still have are

1) The loop never advances. It just keeps returning the first identifier and loops indefinitely. I Did get around this by Changing the text in the found range to something that would not watch the RegEx so its not that big of a deal but just wanted to let you know.

2) This method does not find identifiers that are within Header or Footer fields. Goto View->Header and Footers then type some text and some indentifiers in there and try your script again. I MUST have it able to find and bookmark within the Header and Footers as well.


All in all though, I'm much further than I could have ever gotten on my own, so thank you for that. Just try to take a stab at the Header/Footer problem and we'll call it done.

-Josh
0
 
LVL 76

Expert Comment

by:GrahamSkan
Comment Utility
I do realise that you are not writing for a Word macro, but I don't have the application that you are using or the experience to write in the precise code that will work in your scenario, but I hope to provide enough for you to see how it is done and to apply it in your situation.

Given that, I am not sure why it is not working as designed. The intention is that, once an instance that matches the criteria has been found, the next search looks for another occurrence in the rest of the main part of the document.
Headers and Footers are not part of the main document range. They are displayed and - more important,ly -  printed around each page to which they apply.

Word has several separate range types, called Stories, and it is possible to step through the first of each :

Dim stry As Range
For Each stry In wdDoc.StoryRanges
'...
 
 
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 76

Accepted Solution

by:
GrahamSkan earned 500 total points
Comment Utility
Sorry - hit Submit too soon.
I actually prefer to walk through each document section, and through each header and/or footer within the section.
    Dim doc As Word.Document

    Dim rng As Word.Range

    Dim hdr As Word.HeaderFooter

    Dim ftr As Word.HeaderFooter

    Dim sec As Word.Section

    Dim i As Integer

    '...

    For Each sec In doc.Sections

        For Each hdr In sec.Headers

            Set rng = hdr.Range.Duplicate

            With rng.Find

                .Text = "\<[A-Za-z ]{1,}\>"

                .MatchWildcards = True

                '...

            End With

        Next hdr

        For Each ftr In sec.Footers

            Set rng = ftr.Range.Duplicate

            With ftr.Find

                .Text = "\<[A-Za-z ]{1,}\>"

                .MatchWildcards = True

                '...

            End With

        Next hdr

    Next sec

Open in new window

0
 

Author Comment

by:joshkrak
Comment Utility
Lol, np, as soon as you said storys I was able to play around and get it working before your next post. My final solution in VB.NET is shown below.

Thanks again, GrahamSkan! Wish I could give ya more than 500.
                wordApp = New Word.ApplicationClass

                wordDoc = wordApp.Documents.Add(DirectCast(FullFileName, Object))

                Dim SearchStorys() As Word.WdStoryType = {Word.WdStoryType.wdFirstPageHeaderStory, Word.WdStoryType.wdMainTextStory, Word.WdStoryType.wdFirstPageFooterStory}

                For Each Story As Word.WdStoryType In SearchStorys

                    Dim Range As Word.Range = wordDoc.StoryRanges.Item(Story)

                    Dim i As Integer = 0

                    Range.Find.Text = "\<[A-Za-z0-9_]{1,}\>"

                    Range.Find.MatchWildcards = True

                    While Range.Find.Execute

                        Dim BmText As String = Range.Text.Trim(New Char() {"<"c, ">"c})

                        Range.Text = "<!" & BmText & "!>"

                        If Not Al.Contains(BmText) Then

                            Dim objRange As Object = Range

                            wordDoc.Bookmarks.Add(BmText, objRange)

                            Al.Add(BmText)

                        End If

                        Range.Collapse(Word.WdCollapseDirection.wdCollapseEnd)

                        Range.End = wordDoc.Range.End

                    End While

                Next

                Dim objFullFileName As Object = FullFileName

                wordDoc.SaveAs(objFullFileName)

Open in new window

0
 

Author Closing Comment

by:joshkrak
Comment Utility
Excellent expert advice! He definitely knows his shit!
0
 
LVL 76

Expert Comment

by:GrahamSkan
Comment Utility
That's excellent news. Thank you.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

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…
This article describes how to use the Send to Mail Recipient command. The instructions apply generally to Office 2007 and later versions, but Microsoft® Word 2013 was used for the specific steps and figures.  What is Send to Mail Recipient? Send…
The viewer will learn how to use a discrete random variable to simulate the return on an investment over a period of years, create a Monte Carlo simulation using the discrete random variable, and create a graph to represent the possible returns over…
XMind Plus helps organize all details/aspects of any project from large to small in an orderly and concise manner. If you are working on a complex project, use this micro tutorial to show you how to make a basic flow chart. The software is free when…

743 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

8 Experts available now in Live!

Get 1:1 Help Now