Working with a Document

Working with the Range Object

The Range object in the Word object model is the primary way to interact with the content of the document. A Range represents a range of contiguous text and provides a way to interact with that range of text along with any additional elements that are contained in that range of text such as tables, shapes, lists, and bookmarks. You can get and use as many Range objects as you need in your code.

Working with a Range does not change the selection in the document unless you use Range's Select method, which will make the Range you have defined into the active selection. If you are interested in working with the active selection, you can use the Selection object, which shares many properties and methods with the Range object.

A Range has a start and end that are specified in units of characters in the document and include characters that do not print, such as the carriage return between paragraphs. A Range whose start and end are the same is sometimes called a collapsed Range and can be thought of as the equivalent of an insertion point at a particular location in the document.

Word also has the concept of a "story," which is the part of the document that the Range comes from. Most commonly, you work with the main text story, which is the main body of the document. You might also want to get to other text elements in the document such as headers, footers, comments, footnotes and endnotes. These other text elements are different stories from the main text story.

Getting a Range

You have several ways to get a Range. We have already considered several document-level collections such as Sentences, Words, and Characters that return Range objects. The most common way to get a Range is to use the Range method on the Document object. The Range method takes two optional object parameters passed by referencea Start and an End position. You can pass an int value to Start and End representing the start and end position of the Range you want to get within the document. If you omit the Start parameter, it defaults to 0, which is the first position in the document. If you omit the End parameter, it defaults to the last position in the document.

Listing 8-28 shows an example of getting a Range object using the Document object's Range method. The Range retrieved has a start index of 0 and an end index of 9. As Figure 8-10 shows, the retrieved Range includes nonprinting paragraph marks.

Listing 8-28. A VSTO Customization That Works with a Range Object

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = this.Range(ref missing, ref missing); r.Text = "This is a test."; object startIndex = 0; object endIndex = 9; Word.Range r2 = this.Range(ref startIndex, ref endIndex); r2.Select(); string result = r2.Text; MessageBox.Show(result.Length.ToString()); MessageBox.Show(r2.Text); }

Figure 8-10. The result of running Listing 8-28a range of length 9, including nonprinting paragraph characters.

Another way to get a Range is by using the Document object's StoryRanges collection. The StoryRanges collection enables you to get a Range that is not part of the main document, such as a Range within headers, footers, or endnotes. This collection has an index operator that takes a member of the WdStoryType enumeration that specifies what StoryRange you want to access. Listing 8-29 shows some code that iterates over the StoryRanges in the document and displays the type of each StoryRange.

Listing 8-29. A VSTO Customization That Iterates over the StoryRanges in the Document

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range mainTextStory = this.StoryRanges[ Word.WdStoryType.wdMainTextStory]; foreach (Word.Range range in this.StoryRanges) { MessageBox.Show(String.Format( "Story range {0} has length {1}.", range.StoryType.ToString(), range.StoryLength)); } }

Another way to a get a Range is by getting it from the current selection. The Application object's Selection property returns the active selection in the active document as a Selection object. The Selection object has a Range property that returns a Range object that you can work with without affecting the selection (unless you change the Range in some way that forces the selection to reset such as by replacing the text in the selection). Before getting a Range from a Selection object, verify that the Selection contains a valid Range by checking the Selection object's Type property. For example, the user could have selected a shape in the document, in which case the Range would not be applicable when retrieved from Selection.Range. Listing 8-30 shows an example that checks the Selection.Type property before using Selection.Range. It also checks whether Selection is null, which is a bit of overkill for this example. This case would only arise if no documents are open.

Listing 8-30. A VSTO Customization That Gets a Range Object from a Selection Object

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Selection s = this.Application.Selection; if (s != null) { if (s.Type == Word.WdSelectionType.wdSelectionNormal) { Word.Range r = s.Range; MessageBox(r.Text); } } }

 

Identifying a Range

A Range has several properties to help identify it. The Start and End property return the start and end character index of the Range. The Document property returns the document object the Range is associated with. The StoryType property returns a member of the WdStoryType enumeration identifying the StoryRange with which the Range is associated.

The get_Information method takes a parameter of type WdInformation and returns information as an object about the Range depending on the enumerated value that is passed to the method. Listing 8-31 shows an example of getting the information associated with a range. If you call get_Information on a Range with an enumerated type that is not applicable, get_Information will return 1 as a return value.

Listing 8-31. A VSTO Customization That Gets Information About a Range

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = this.Range(ref missing, ref missing); r.Text = "This is a test."; object startIndex = 0; object endIndex = 9; Word.Range r2 = this.Range(ref startIndex, ref endIndex); r2.InsertAfter(" "); for (int i = 1; i < 27; i++) { GetInfo(r2, (Word.WdInformation)i); } } private void GetInfo(Word.Range r, Word.WdInformation info) { string result = String.Format( "Range.Information({0}) returns {1}. ", info.ToString(), r.get_Information(info)); r.InsertAfter(result); }

 

Changing a Range

Given a Range object, a number of properties and methods enable you to change what a Range refers to. A simple way to modify a Range object is to set the values of the Start and End properties. In addition, you can use several methods to change the Range in other ways.

The Expand method expands a Range so that it encompasses the units of the enumeration WdUnits: wdCharacter, wdWord, wdSentence, wdParagraph, wdSection, wdStory, wdCell, wdColumn, wdRow, or wdTable. The Expand method takes a range that only partially covers one of these units and expands it so that the range includes the unit specified.

For example, consider Figure 8-11. For this and subsequent figures, we have turned on Word's formatting marks (Tools > Options > View > Formatting Marks > All) so that you can see clearly the spaces and any paragraph marks in the text. The original Range is shown in white text on a black background. The expanded Range after calling Expand with wdWord is shown by the larger border. The original Range only contained e quithe last part of the word The and the first part of the word quick. Calling Expand with wdWord expands the range so that it covers complete words. The expanded Range after calling Expand contains The quick as well as the space after the word quick.

Figure 8-11. Result of calling Expand(WdUnits.wdWord) on a Range.

Figure 8-12 shows another example where only three characters of a word are selected. Calling Expand with wdWord expands the Range so that it covers the complete word quick as well as the space after the word quick.

Figure 8-12. Result of calling Expand(WdUnits.wdWord) on a Range.

Note that calling Expand repeatedly on a Range passing wdWord does not expand the Range to cover additional words. After a Range no longer contains any partial words, calling Expand with wdWord has no effect. It also follows that a Range that does not start or end with any partial words to start with will not be changed when you call Expand and pass wdWord. This applies to the other members of the WdUnits enumeration. For example, when a Range does not contain any partial sentences, calling Expand with wdSentence has no effect.

Figure 8-13 shows an example of calling Expand passing wdSentence. The original Range contains parts of two sentences. The result of calling Expand is that two complete sentences are made part of the Range.

Figure 8-13. Result of calling Expand(WdUnits.wdSentence) on a Range.

Figure 8-14 shows another example of calling Expand passing wdSentence. The original Range contains just dog. Expanding the Range adds the rest of the sentence plus the spaces after the sentence.

Figure 8-14. Result of calling Expand(WdUnits.wdSentence) on a Range.

The Expand method can change both the start and the end of a Range. The EndOf method works in a similar way to the Expand method but only changes the end of a Range. The EndOf method takes by reference two optional parameters of type object: Unit and Extend. The Unit parameter can be passed a member of the WdUnits enumeration. The Extend parameter can be passed a member of the WdMovementType enumeration: wdMove or wdExtend. If you pass wdExtend, the EndOf method acts like the Expand method would if it were not allowed to change the start of a Range. Figure 8-15 shows an example of calling EndOf passing wdWord and wdExtend. It expands the Range to cover the partial word at the end of the Range but does not expand to cover the partial word at the beginning of the Range.

Figure 8-15. Result of calling EndOf(WdUnits.wdWord, WdMovementType.wdExtend) on a Range.

If you pass wdMove for the second parameter (which is the default if you omit the parameter), EndOf returns a Range whose start and end is equaleffectively returning you an insertion point at the end of the expansion. Figure 8-16 shows a Range that initially partially covers two words. Calling EndOf on this Range and passing wdMove for the second parameter yields a Range whose start and end is 10at the end of the second word.

Figure 8-16. Result of calling EndOf(WdUnits.wdWord, WdMovementType.wdMove) on a Range.

The StartOf method works like the EndOf method but only changes the start of the range. The StartOf method takes by reference two optional parameters of type object: Unit and Extend. The Unit parameter can be passed a member of the WdUnits enumeration. The Extend parameter can be passed a member of the WdMovementType enumeration: wdMove or wdExtend. If you pass wdExtend, the StartOf method acts like the Expand method would if it were not allowed to change the end of a range. Figure 8-17 shows an example of calling StartOf passing wdWord and wdExtend. It expands the Range to cover the partial word at the beginning of the Range but does not expand to cover the partial word at the end of the Range.

Figure 8-17. Result of calling StartOf(WdUnits.wdWord, WdMovementType.wdExtend) on a Range.

As with EndOf, the StartOf method when passed wdMove for the second parameter returns a Range whose start and end is equaleffectively returning you an insertion point at the beginning of the expansion. Figure 8-18 shows a Range containing a word at the end of a sentence. Calling StartOf and passing wdSentence and wdMove yields a Range where start and end are 0effectively an insertion point at the beginning of the sentence.

Figure 8-18. Result of calling StartOf(WdUnits.wdSentence, WdMovementType.wdMove) on a Range.

 

Moving a Range

The Move method can be called repeatedly to move a Range by WdUnit through the document. It does not expand the Range, but instead moves the Range, creating a Range whose start and end are equal. The Move method takes by reference optional Unit and Count parameters of type object. For Unit, you pass the member of the WdUnit enumeration that you want to move by. The default value of Unit is wdCharacter. For Count, you pass a positive or negative int specifying how many units you want to move forward or backward. The Move method returns the number of units by which the Range was moved or returns 0 if the Range was not moved. Figure 8-19 shows an example of calling Move passing wdWord and 1. Figure 8-20 shows an example of calling Move passing wdWord and 1. In the first case, the Range moves to the start of the next word. In the latter case, the Range moves to the beginning of the partially selected word.

Figure 8-19. Result of calling Move(WdUnits.wdWord, 1) on a Range containing h from The.

Figure 8-20. Result of calling Move(WdUnits.wdWord, -1) on a Range containing h from The.

The Next method works like Move when passed a positive count. Instead of modifying the Range directly, it returns a new Range that would be the result after calling Move. The Previous method works like Move when passed a negative count and also returns a new Range instead of modifying the existing Range. In the case where the Move method would have returned 0 because the Move was not possible, Next and Previous return a null Range.

The MoveUntil method takes a required object by reference parameter to which you can pass a string containing the characters that you want to find. It takes a second optional object parameter by reference to which you can pass the number of characters after the Range to search. If MoveUntil cannot find a specified character within the number of characters you pass, it will not change the Range. You can pass a negative number of characters to search the characters before the range. You can also pass to the second optional object parameter the constant WdConstants.wdForward or WdConstants.wdBackward to specify to search forward or backward without specifying a limit on the number of characters to search.

Figure 8-21 shows the result of calling MoveUntil passing "abc" as the string and WdConstants.wdForward for the second parameter. It searches forward until it finds either character a, b, or c. The first of those it finds is the c in the word quick. It sets the start and end of the Range to 7.

Figure 8-21. Result of calling MoveUntil("abc", WdConstants.wdForward) on a Range containing h from The.

Range has a MoveStart and MoveUntilStart method that work like Move and MoveUntil but only affect the start position of the Range unless the start is moved forward to a position beyond the end, in which case Start and End are set to the same value. Similarly, Range has a MoveEnd and MoveUntilEnd method that work like Move and MoveUntil but only affect the end position of the Range.

The SetRange method takes a Start and End parameter as an int to set the start and end position of the Range in characters. Using the SetRange is the equivalent of setting the Start and End properties on Range.

Ranges and Stories

Given a Range, you can expand the range to include the full story associated with the Range using the WholeStory method. Some stories are split into multiple linked text elements in a document (text box stories can be linked, and header and footer stories can be linked), so calling WholeStory cannot give you each of the multiple linked text elements. For these cases, you can use the NextStoryRange property to get the next linked story of the same type.

Navigating a Range

Earlier in this chapter, you read about the Browser object, which lets you access the same functionality that is available in the browser control shown in Figure 8-3. The Browser object enables you to easily go to the next element of a particular type in a document such as the next bookmark, comment, or field. However, the Browser object affects the selection in the document, which is often undesirable.

To go to the next element of a particular type without affecting the selection, you can use the GoTo method of the Range object. GoTo does not affect the Range object it is called on but instead returns a new Range object that represents the resulting Range after calling GoTo. The GoTo method takes by reference four optional object parameters. The first parameter, the What parameter, can be passed a member of the WdGoToItem enumeration:

The second parameter, the Which parameter, can be passed a member of the WdGoToDirection enumeration: wdGoToAbsolute, wdGoToFirst, wdGoToLast, wdGoToNext, wdGoToPrevious, or wdGoToRelative. The wdGoToAbsolute value can be used to go to the n-th item of the type specified by the What parameter.

The third parameter, the Count parameter, is passed the number of the item to get and is affected by the second parameter. For example, if What is passed wdGoToLine and Count is passed 1, then depending on the Which parameter, GoTo could go to the next line after the Range (wdGoToNext) or the first line in the document (wdGoToAbsolute) or the line previous to the current Range (wdGoToPrevious).

The fourth parameter, the Name parameter, can be passed a name if the What argument specifies an element identifiable by name: wdGoToBookmark, wdGoToComment, or wdGoToField.

GoToNext and GoToPrevious are simpler versions of the GoTo method that only take the What parameter and go to the next or previous instance of the type of object specified by the What parameter.

Listing 8-32 shows an example of using the GoTo method on a Range to navigate through the pages in a document and display the first sentence on each page. We also use get_Information to get the page count and Expand to expand the collapsed Range returned by GoTo to include the first sentence on the page.

Listing 8-32. A VSTO Customization That Uses the GoTo Method

private void ThisDocument_Startup(object sender, EventArgs e) { // Generate some random text in the document. Word.Range r = Range(ref missing, ref missing); System.Text.StringBuilder builder = new System.Text.StringBuilder(); Random rand = new Random(); for (int i = 0; i < 200; i++) { builder.AppendLine(rand.NextDouble().ToString()); } r.Text = builder.ToString(); int maxPage = (int)r.get_Information( Word.WdInformation.wdNumberOfPagesInDocument); // GoTo to navigate the pages for (int page = 1; page <= maxPage; page++) { object what = Word.WdGoToItem.wdGoToPage; object which = Word.WdGoToDirection.wdGoToAbsolute; object count = page; object sentence = Word.WdUnits.wdSentence; Word.Range r2 = r.GoTo(ref what, ref which, ref count, ref missing); r2.Expand(ref sentence); MessageBox.Show(String.Format( "First sentence is {0} starting at position {1}.", r2.Text, r2.Start)); } }

 

Collapsing a Range

We have already mentioned several times the concept of a collapsed Rangea Range whose start and end is equal. The Collapse method takes a Range and collapses it. It takes by reference an optional parameter Direction of type object. You can pass a member of the WdCollapseDirection enumeration: wdCollapseEnd, which makes Start equal to End; or wdCollapseStart, which makes End equal to Start. If you omit the Direction parameter, the default is wdCollapseStart.

Getting Text from a Range

The Text property returns a string containing the text in the Range. The behavior of the Text property can be changed by using the TextRetrievalMode property, which returns a TextRetrievalMode object. Setting the TextRetrievalMode object's IncludeFieldCodes property to true makes it so the Text property returns field codes. The default is the setting of the Field Codes check box in the View page of the Options dialog.

Setting the TextRetrievalMode object's IncludeHiddenText property to TRue makes it so the Text property returns hidden text in the document. The default is the setting of the Hidden Text check box in the View page of the Options dialog.

The TextRetrievalMode object's ViewType property can also affect what the Text property returns. The ViewType property can be set to a member of the WdViewType enumeration: wdMasterView, wdNormalView, wdOutlineView, wdPrintPreview, wdPrintView, wdReadingView, or wdWebView. When set to wdOutlineView, for example, Text only returns the text visible in outline view.

Listing 8-33 shows the creation of some text in a document that includes a field and some hidden text. The Text property is then used in several ways, showing the effect of changing TextRetrievalMode settings.

Listing 8-33. A VSTO Customization That Modifies TextRetrievalMode Settings

private void ThisDocument_Startup(object sender, EventArgs e) { // Generate some random text in the document. Word.Range r = Range(ref missing, ref missing); r.Text = "Hello "; object collapseDirection = Word.WdCollapseDirection.wdCollapseEnd; object date = Word.WdFieldType.wdFieldDate; // Add a field r.Collapse(ref collapseDirection); r.Fields.Add(r, ref date, ref missing, ref missing); // Hide some text r.SetRange(1,2); r.Font.Hidden = 1; r = Range(ref missing, ref missing); r.TextRetrievalMode.IncludeFieldCodes = false; r.TextRetrievalMode.IncludeHiddenText = false; MessageBox.Show(r.Text); r.TextRetrievalMode.IncludeFieldCodes = true; MessageBox.Show(r.Text); r.TextRetrievalMode.IncludeHiddenText = true; MessageBox.Show(r.Text); }

 

Setting the Text in a Range

Setting the Text property to a string value is the most basic way to set text in a Range. Setting the Text property replaces the text in the Range with the string value and changes the end of the Range so the start and end cover the length of the new string. If the Range is collapsed, setting the Text property does not replace any existing text, but it inserts the new string at the location of the Range and changes the end of the Range so that the start and end cover the length of the new string.

Setting the Text property only changes the characters of the Range, not the formatting. If you have one Range formatted a particular way and a second Range you want to copy both the text of the first Range and its formatting to, you can use the FormattedText property, which takes a Range. Listing 8-34 shows an example of using the FormattedText property to take one Range that is formatted and set the text and formatting of a second Range to the first.

Listing 8-34. A VSTO Customization That Uses FormattedText to Set Text and Formatting

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = Range(ref missing, ref missing); r.Text = "Hello Hello Happy"; object start1 = 0; object end1 = 5; r = Range(ref start1, ref end1); r.Bold = 1; object start2 = 12; object end2 = 17; Word.Range r2 = Range(ref start2, ref end2); r2.FormattedText = r; }

Each time you set the Text property, it replaces the existing Range and changes the end of the Range so that the start and end cover the new string. The InsertAfter method lets you add text immediately after the Range without replacing the existing Range. The InsertAfter method takes a string for the text you want to insert after the Range. InsertAfter changes the end of the Range so that the start and end cover the old Range and the string you have added after the Range.

The InsertBefore method lets you add text immediately before the Range without replacing the existing Range. The InsertBefore method takes a string for the text you want to insert before the Range. InsertBefore changes the end of the Range so that the start and end cover the old Range and the string you have added before the Range.

Inserting Nonprinting Characters and Breaks

You have several ways to insert nonprinting characters such as tabs and paragraph marks. A simple way is to use escaped string literals. In a C# string, you can specify a tab with the character sequence . You can specify a paragraph mark (a new line) by using either or . Listing 8-35 shows some examples of using escaped string literals to insert nonprinting characters. Figure 8-22 shows the result of running Listing 8-35 with nonprinting characters showing.

Listing 8-35. A VSTO Customization That Uses Escaped String Literals and the Text Property

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = Range(ref missing, ref missing); r.Text = "Item Name "; r.InsertAfter("111 1/4" pipe "); r.InsertAfter("112 1/2" pipe "); r.InsertAfter(" "); r.InsertAfter("File path: c:\Temp\Doc1.doc"); }

Figure 8-22. Result of running Listing 8-35.

It is also possible to insert paragraphs using the InsertParagraph method. The InsertParagraph method inserts a new paragraph at the start position of the Range, replacing the current Range. It changes the Range so that it covers the start position and the newly inserted paragraph mark. InsertParagraph is the equivalent of setting the Text property to /n. InsertParagraphBefore inserts a new paragraph at the start position of the Range and changes the end of the Range to expand it to cover the old Range and the newly inserted paragraph mark. InsertParagraphBefore is the equivalent of calling the InsertBefore method and passing /n. InsertParagraphAfter is the equivalent of calling the InsertAfter method and passing /n.

Figure 8-23 shows some additional kinds of breaks that a user can insert into a document using the Break command from the Insert menu. These types of breaks can be inserted programmatically using Range's InsertBreak method. The InsertBreak method takes by reference an optional parameter of type object to which you can pass a member of the WdBreakType enumeration. The members of the WdBreakType enumeration correspond to the breaks in Figure 8-23: wdPageBreak, wdColumnBreak, wdTextWrappingBreak, wdSectionBreakNextPage, wdSectionBreakContinuous, wdSectionBreakEvenPage, or wdSectionBreakOddPage. InsertBreak works like setting the Text property wouldthe current Range is replaced with the break, or if the Range is collapsed, the break is inserted at the position of the Range.

Figure 8-23. The Insert Break dialog.

 

Working with Formatting

The Font property returns a Font object that controls font settings for the Range. Many of the properties associated with Font, such as the Bold property, that you would expect to be of type bool are instead of type int. This is because a particular Range could be all bold, partially bold, or not bold, for example. If the Range is partially bold, it returns WdConstants.wdUndefined. If the Range is not bold, it returns a 0. If the Range is all bold, it returns a 1; this is another example where the COM implementation of the Word OM peeks through because 1 corresponds to a true value in COM object models. This can cause confusion because the bool value for true in .NET when cast to an integer is 1, not 1. So when checking the value of these properties, remember to not make the mistake of comparing to 1 or the bool value of true cast to an int because this will cause your code to fail to detect the state properly. Instead, always compare to 0 or the bool value of false cast to an int.

Table 8-14 lists several of the most frequently used properties associated with the Font object.

Table 8-14. Frequently Used Properties Associated with the Font Object

Property Name

Type

What It Does

AllCaps

int

Set to 1 to format the font as all capital letters.

Bold

int

Set to 1 to format the font as bold.

Color

WdColor

Set to a member of the WdColor enumeration to set the color of the font.

ColorIndex

WdColor-Index

Set to a member of the WdColorIndex enumeration to set the color of the font.

Hidden

int

Set to 1 to hide the text of the Range.

Italic

int

Set to 1 to format the font as italic.

Name

string

Set to a string representing the name of the font.

Size

float

Set to a size in points.

SmallCaps

int

Set to 1 to format the font as small caps.

Underline

WdUnderline

Set to a member of the WdUnderline enumeration to set the underline format of the font.

Another way to set the formatting of a Range is to use the set_Style method. The set_Style method takes by reference an object parameter. You can pass a string representing the name of the style you want to use to format the Range.

Listing 8-36 shows some formatting of a Range using Font properties and the set_Style method. Figure 8-24 shows the document created by Listing 8-36.

Listing 8-36. A VSTO Customization That Formats a Range

private void ThisDocument_Startup(object sender, EventArgs e) { object collapseEnd = Word.WdCollapseDirection.wdCollapseEnd; Word.Range r = Range(ref missing, ref missing); r.Text = "Item Name "; r.Font.Name = "Verdana"; r.Font.Size = 20.0F; r.Collapse(ref collapseEnd); r.InsertAfter("111 1/4" pipe "); r.HighlightColorIndex = Word.WdColorIndex.wdGray25; r.Italic = -1; r.Font.Size = 10.0F; r.Font.Name = "Times New Roman"; r.Collapse(ref collapseEnd); r.InsertAfter("112 1/2" pipe "); r.Shading.BackgroundPatternColor = Word.WdColor.wdColorBlack; r.Font.Color = Word.WdColor.wdColorWhite; r.Font.Size = 10.0F; r.Font.SmallCaps = -1; r.Font.Name = "Verdana"; r.Collapse(ref collapseEnd); r.InsertAfter("This should be a heading."); object style = "Heading 1"; r.set_Style(ref style); }

Figure 8-24. Result of running Listing 8-36.

 

Find and Replace

The Find property returns a Find object that you can use to search a Range. The Find object allows you to set options similar to the ones you find in Word's Find dialog. The Find object's Text property can be set to the string you want to search for. The Find object's MatchWholeWord property can be set to false to allow matching of the string against a partial word in the Range. After the find options have been setup, the Find object's Execute method executes the find against the Range. Execute takes a number of optional parameters by referencesome of which correspond to properties on the Find object. So you have an option of either presetting Find properties and then calling Execute and omitting the optional parameters by passing ref missing, or you can skip presetting Find properties and pass optional parameters to the Execute method. In Listing 8-36, we take the former approach. Execute returns true if it is able to find the text specified and modifies the Range so that it covers the found text. In Listing 8-37, calling Execute modifies the Range to have a start of 20 and an end of 24.

Listing 8-37. A VSTO Customization That Uses the Find Object

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = Range(ref missing, ref missing); r.Text = "The quick brown fox jumped over the lazy dog."; Word.Find f = r.Find; f.Text = "jump"; f.MatchWholeWord = false; if (f.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing)) { MessageBox.Show(String.Format( "Found {0} at position {1},{2}.", f.Text, r.Start, r.End)); } }

It is also possible to iterate over multiple found items using the Find object's Found property instead of checking the return value of Execute each time. Listing 8-38 shows an example of iterating over every occurrence of the string "jump" in a document. This example bolds every instance of jump that it finds in the document.

Listing 8-38. A VSTO Customization That Uses the Find Object's Found Property to Iterate over Found Items

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = Range(ref missing, ref missing); r.Text = "Jumping lizards! Jump on down to Mr. Jumpkin's jumpin' trampoline store."; Word.Find f = r.Find; f.Text = "jump"; f.MatchWholeWord = false; f.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,ref missing, ref missing); while (f.Found) { MessageBox.Show(String.Format( "Found {0} at position {1},{2}.", f.Text, r.Start, r.End)); r.Font.Bold = -1; f.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); } }

The Find object has a Replacement property that returns a Replacement object, which allows you to set options for doing a find and replace. The Replacement object's Text property lets you set the text you want to use to replace found text with. In addition, to perform a replacement, you must pass a member of the WdReplace enumeration to the Replace parameter of the Execute method (the eleventh optional parameter). You can pass wdReplaceAll to replace all found occurrences or wdReplaceOne to replace the first found occurrence. In Listing 8-39, we use the Replacement.Text property to set the replace string, and then call Execute passing wdReplaceAll to the Replace parameter.

Listing 8-39. A VSTO Customization That Performs a Replace

private void ThisDocument_Startup(object sender, EventArgs e) { Word.Range r = Range(ref missing, ref missing); r.Text = "The quick brown fox jumped over the lazy dog."; Word.Find f = r.Find; f.Text = "jump"; f.MatchWholeWord = false; f.Replacement.Text = "leap"; object replace = Word.WdReplace.wdReplaceAll; if (f.Execute(ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref replace, ref missing, ref missing, ref missing, ref missing)) { MessageBox.Show(String.Format( "Replaced {0} at position {1},{2}.", f.Text, r.Start, r.End)); } }

Категории