Bonus chapter B: VBA Programming In Word - Wiley

12 downloads 179 Views 136KB Size Report

Bonus Chapter B

VBA Programming in Word In This Chapter 䊳 An overview of the Word object model 䊳 Key Word objects: Documents, windows, selections, ranges, and the Find object 䊳 Ranges versus selections — when to use which of them for working with text 䊳 Crucial methods and properties for manipulating text in your code 䊳 How to find and replace text in Word VBA

I

n the Office suite, Word’s object model offers the richest array of programming treasures. Understanding Word objects, such as Range and Find, can be a challenge, but getting the hang of them is crucial if you’re going to be constructing VBA routines of any power in Word. That’s where this chapter comes in. Word’s object model encompasses so many objects and collections that you’d need a sizable wall poster to portray the object hierarchy in graphical form. Obviously, I can only cover a fraction of the objects, properties, and methods you can tap for your own programs. This chapter turns the spotlight on the most important Word VBA techniques. You should turn to the Help files for details once you grasp these fundamentals.

Understanding the Application Object As in all VBA applications, the root object in Word’s object model is Application. In other words, the Application object contains all other Word objects. Because the Application object is so central to VBA programming in Word, you don’t need to explicitly mention it when working with many important Word objects. However, you shouldn’t forget its role because you need it to work with properties and methods of the application itself, as well as including in some object references. For example, the following statement triggers the ListCommands method of the Application object: Application.ListCommands ListAllCommands:=True

CD-18

VBA For Dummies, 3rd Edition By the way, the ListCommands method creates a new document and places in it a table containing the keyboard shortcuts and menu locations of all Word commands. When you supply True as the value of the ListAllCommands argument, the new document contains both custom keyboard and menu assignments. Switch to False if you only want to see custom assignments in the table.

Accessing Word Documents in VBA If the VBA procedure you’re writing acts directly on a document, you must specify that document object in your code. Often, you can do so implicitly, using the Selection object, which I cover later in this chapter. But in other situations, you must identify the target document explicitly.

Working with the active document The typical VBA procedure in Word performs its magic on the document that the Word user is currently editing. Use the ActiveDocument object to specify this active document. The following statement closes the active document, of course: ActiveDocument.Close

The point is, you don’t need to write any code to figure out which document is the one being edited at the time the procedure runs — just use the ActiveDocument object.

Specifying a particular document If you need to work with a particular document that isn’t necessarily active, you must specify it as a member of the Documents collection, which contains all the documents currently open in Word. As with a generic VBA collection, you can refer to an individual document in the collection by its title, which in this case is its file name (use the file name only, not the complete path). Here’s an example: Documents(“Toy Store Newsletter.doc”)

Because you may not know the file name of the target document in advance, and because the user can change the document’s file name, you may want to create a variable to hold the name. You can then use the variable to specify the document object, as in Documents(strDocName).

Bonus Chapter B: VBA Programming in Word You can also refer to a document by index number. The following object reference specifies the third document in the Documents collection: Documents(3)

As simple as this technique may be, it’s of limited value — typically, you don’t know the index number of the document that you want to work with. One use for it is to learn the name of an open document. The following statement places the second open document’s file name in a variable: strDocName = Documents(2).Name

Creating, opening, activating, and closing documents To create a brand-new document, use the Add method of the Documents collection. Used without arguments, the Add method starts a document based on the Normal template. To specify another template, add its full path as the argument as in the following: Documents.Add template:= _ “C:\Windows\Application data\Microsoft Office\Hidden templates”

To open an existing document, you need the Open method — again a method of the Documents collection. Of course, you have to include the complete path of the document file, as in Documents.Open FileName:= _ “C:\Toys\Toys for infants.doc”

Activate a document that’s already open with the Activate method. Suppose you want your VBA program to activate a specific document that may or may not be open already when the program runs. Use code similar to the following to activate the document if it’s already open, or to open it if not: Sub DocActivateOrOpen() Dim docFileName As String, docPath as String docFileName = “Pull toys.doc” docPath = “C:\Toys\” For Each targetDoc In Documents If targetDoc.Name = docFileName Then targetDocIsOpen = True End If Next targetDoc

CD-19

CD-20

VBA For Dummies, 3rd Edition If targetDocIsOpen = True Then Documents(docFileName).Activate Else Documents.Open FileName:=docPath & docFileName End If End Sub

Working with document sections Because each Word document has one or more sections, you might expect Word VBA to provide a Sections collection and individual Section objects to work with these elements. And so it does. One important use of Section objects is to access their headers and footers (via the HeaderFooter object). You can add new sections to a document by using the Add method of the Sections collection or the InsertBreak method of a range or selection object.

Opening Windows with VBA Each open document has at least one window, but a Word user can open as many windows as desired for any given document. Each of these windows is an object in its own right. In the Word object model, the Application object has a Windows collection containing all the windows of all open documents. In addition, each Document object has its own separate Windows collection that contains only the windows for that document. Two main reasons to work with Window objects in Word are to control the appearance of the window and to manipulate document content via the Selection object. The topic that I discuss in the next section is the Selection object; here, I focus on the technique for specifying a particular window and also on introducing the properties you can use to alter window appearance.

Specifying windows in code The easiest window to work with in code is the one that’s currently being edited when the procedure runs. Use the ActiveWindow object to specify this window. To designate a specific window in code, identify it as a member of one of the Windows collections. You don’t have to name the Application object when you work with the global Windows collection. When you access a specific document’s Windows collection, however, a reference to that document is

required. You can identify the window by its name or index number in the

Bonus Chapter B: VBA Programming in Word collection. A window’s name is the same as the name of the document it displays — except if more than one window is open for the same document, you add a colon and the window number after the document name. The following are typical object references for Window objects:

Reference

Comments

Windows(“Document4”)

Valid if Document4 has only one open window

Windows(“Kites and skip ropes.doc:3”)

Specifies the third window of the named document

Documents(“Window display. doc”).Windows(2)

Specifies the second window of the named document’s Windows collection

Working with window panes When you split a window vertically by using the Window➪Split command, the top and bottom portions of the window are separate panes. A Word window has at least one pane, but it can have more than just one. The areas where Word displays headers, footers, footnotes, endnotes, and comments are also panes. If you have to access the appearance settings or the selection in an individual pane, you must first identify the target Pane object in your code. Refer to it by index number in its window’s Panes collection. However, you can omit pane references when you want to work with the default pane, which is the main part of the window (or the top pane if the window is split).

Changing window appearance Window objects offer a host of properties representing the state of all the elements you see on-screen that are pertinent to an individual window. A number of these properties act as toggles — their values can be either True or False. For example, to turn on the Document Map for the active window, enter this statement in your code: ActiveWindow.DocumentMap = True

Use similar statements to turn on or off properties such as DisplayScreenTips or DisplayVerticalScrollBar. Remember that the keyword Not reverses the current value of a Boolean variable or property. It’s the easiest way to toggle such properties, as shown here:

CD-21

CD-22

VBA For Dummies, 3rd Edition ActiveWindow.DisplayRulers = _ Not ActiveWindow.DisplayRulers

The Left, Top, Height, and Width properties enable you to set the size and location of a non-maximized window.

Using the View object The subsidiary View object governs many aspects of the appearance of a window or pane. A few of the View object’s many properties include:

Property of View Object

What It Does

Type

Corresponds to the selection at the top of the View menu (Normal, Outline, Print Layout, and so on). To change the view type, use one the following predefined constants: wdMasterView, wdNormalView, wdOutlineView, wdPrintView, wdWebView, or wdPrintPreview. For example, the statement ActiveWindow.View.Type = wdPrintPreview switches the ActiveWindow to the Print Preview view.

FullScreen

Controls whether the window is displayed in standard or full-screen view.

TableGridlines

Determines whether table gridlines are visible or not.

ShowAll, Show

ShowAll determines whether all non-printing characters are visible — it corresponds to the setting of the All check box on the View tab of the Tools➪Options dialog box. You can turn the display of each individual type of non-printing characters on or off, as well as other items such as text highlighting and boundaries with various properties that start with Show, such as ShowBookmarks and ShowHighlight.

Zooming in code To control the window’s magnification, you need to drill down still deeper into the object hierarchy to the Zoom object, and then modify its Percentage property. Here’s an example: ActiveWindow.View.Zoom.Percentage = 135

Bonus Chapter B: VBA Programming in Word If you want to preset the zoom factor for a view type that isn’t currently displayed, include the constant for its type as an argument to the View property, as in ActiveWindow.View.Zoom.Percentage = 75

The next time the user switches to that view, the document appears at the specified zoom percentage. Alternatively, you can use the PageFit property of the Zoom object to duplicate the Page Width and Full Page choices in the Zoom drop-down toolbar button. With either of these settings active, Word re-zooms the document whenever the window size changes, ensuring that the correct fit is maintained. This statement is equivalent to selecting Page Width in the Zoom button: ActiveWindow.View.Zoom.PageFit = wdPageFitBestFit

The Full Page choice is only available in Print Layout view, but you can duplicate it with the following code: Windows(“Document1”).View.Zoom.PageFit = _ wdPageFitFullPage

To shut off automatic re-zoom, set the PageFit property to wdPageFitNone.

Working with the Selection Object In Word VBA, the Selection object refers to whatever is currently selected in a window pane. That’s right, the Selection object belongs to a window pane, not a document. Because a document can have more than one open window, each window can have more than one pane, and each of these contains a selection. (Although a Selection object technically belongs to a window pane, it’s okay to think of it as belonging to a window instead, unless you specifically want to work with the selection in a special pane, such as a header or footer.) Although you can manipulate selections in your code by using the Selection object, it’s often better to use a Range object instead. See the section “Working with Text in Word VBA” later in this chapter for a discussion of when to use each of these objects. The content of a selection can be a block of text, a table, a text box, a graphic, or anything else you can select with the mouse or keyboard. Key point: If nothing is selected, the Selection object represents the current location of the insertion point.

CD-23

CD-24

VBA For Dummies, 3rd Edition Although every window pane contains a selection, you only need to refer explicitly to the target window if the selection you want isn’t in the main pane of the active window. To work with the selection in the main pane of whatever window is active when the procedure runs, just use the Selection object by itself. For example, you can use the following statement to replace the active window’s selection with the text in quotation marks: Selection.Text = “My dog has fleas.”

If you want to refer to a selection in one of the inactive windows, you must specify that window in full. Here’s an example: Documents(“Songs.doc”).Windows(2).Selection.Text = _ “My bonnie lies over the ocean.”

Because the Selection object can refer to many different types of content, it’s always best to check to see what type of content is selected before you perform some action on it. Otherwise, you risk unexpected results or errors. Use the Selection object’s Type property to provide this information. For example, the following code tests the selection to be sure it’s a regular text selection of one or more consecutive characters before proceeding to cut the selection to the Clipboard: With Selection If .Type = wdSelectionNormal Then .Cut End If

You can use the following selection constants in such tests:

Selection.Type Constant

What’s Selected

wdNoSelection

No selection at all

wdSelectionBlock

A vertical block of text

wdSelectionColumn

A table column

wdSelectionFrame

A frame

wdSelectionInlineShape

A graphic residing in text

wdSelectionIP

Just an insertion point — nothing is actually selected

wdSelectionNormal

A standard selection consisting of consecutive text characters

wdSelectionRow

A table row

wdSelectionShape

A floating graphic, not in-line with text

Bonus Chapter B: VBA Programming in Word

Understanding Range Objects When you’re editing a document yourself, you must position the insertion point or make a selection before adding, deleting, or formatting the text. In VBA, however, Word’s Range objects free you from that necessity. A Range object simply specifies a continuous block of text of one or more characters anywhere in a document. Range objects are completely independent of the insertion point or highlighted selection that the user sees in the document window. After you’ve created a Range object, you can then manipulate the text it encompasses with VBA equivalents for all of Word’s powerful editing commands, just as you can with Selection objects. You can specify Range objects in your code in the following two ways: ⻬ By accessing predefined ranges via the Range property ⻬ By defining ranges yourself by using a Document object’s Range method

Using the Range property An open Word document already contains Range objects that correspond to many document elements. Each paragraph defines a range, as does each table, individual table cell, comment, and footnote, to name just a few examples. You can think of these ranges as existing only in a sort of virtual reality until you access them using the Range property of the object in question. For example, to specify the Range object represented by the first paragraph in the active document, you would use the following object reference: ActiveDocument.Paragraphs(1).Range

Because these predefined ranges already exist in Word’s mind, you can use object references to them directly, without assigning them to object variables. This is the way to go if you need a given range for a single operation. The following statement copies the document’s second table to the Clipboard using the Range object’s Copy method: ActiveDocument.Tables(2).Range.Copy

When multiple consecutive statements use the same range, you can use a With... block to speed up code entry and the program. Here, this technique is used with a range representing the document’s third section to sort the paragraphs in the range and then make the first sentence bold: With ActiveDocument.Section(3).Range .Sort SortOrder:=wdSortOrderAscending .Sentences(1).Range.Bold = True End With

CD-25

CD-26

VBA For Dummies, 3rd Edition The above example illustrates how a Range object typically contains other objects that encompass ranges. The statement on the third line accesses the range corresponding to the first sentence in the original range, and then makes that sentence bold. Note too that you can’t apply formatting directly to objects, such as words, sentences, or paragraphs — you must use their Range properties to do so. If you plan to use the range in multiple statements that aren’t consecutive, go ahead and assign the range to an object variable. Again, doing so makes your code easier to type and your procedure a bit faster. Selection objects also have the Range property. That fact makes it easy to use the properties and methods belonging to Range objects on existing selections. The following example assigns the selection’s range to a variable, moves the selection, and then converts the text of the original range to all lowercase characters: Set deRange = Selection.Range Selection.Move Unit:=wdParagraph, Count:=3 deRange.Case = wdLowerCase

Defining your own ranges by using the Range method When existing objects don’t contain the text you want to work with, create your own Range object. You can define as many Range objects as you need in any open documents. The technique relies on the document’s Range method, which requires you to specify the new range’s starting and end points in terms of character position in the document. Check out this example: ActiveDocument.Range (Start:=10, End:=20)

The preceding expression is an object reference to a range beginning with the 11th character and ending with the 20th character in the document. The character position values actually refer to the place just to the left of a given character where the insertion point would go. A value of 0 corresponds to the location immediately to the left of the first character in the document, and a value of 10 to the spot just past the 10th character and just left of the 11th character. Word counts all characters in the document, including hidden and non-printing characters, whether or not they’re currently visible. To create a range that’s just a location and contains no text, set the Start and End properties to the same number. To include the entire document in the Range object, use the document’s Range method with no arguments, or use the document’s Content property.

Bonus Chapter B: VBA Programming in Word It’s easy enough to create a Range object — as long as you know the values for the starting and ending characters that you want to include in it. The trouble is, you rarely want to work with an arbitrary number of characters at an arbitrary location in your document. More often, you’re interested in text at meaningful places in the document. You might want to begin a range at an existing bookmark, at the start of the current selection or an existing range, or at a particular word or phrase that you know is somewhere in the document. To define a range based on some such item, use the Start or End properties of a Selection, Range, or Bookmark object to learn the character position value that you need. If you want to create a 10-character range starting at a bookmark named ForgetMeNot, these statements do the trick: With ActiveDocument Set myBkMark = .Bookmarks(“ForgetMeNot”) Set homeOnTheRange = _ .Range (Start:= myBkMark, End:= myBkMark + 10) End With

The following is another example showing how you can use the Range property to locate a paragraph, focus in on a particular word it contains, and then use the beginning of the word as the start of a new range. Here, the End argument is omitted, so the range extends from that point to the end of the document: With ActiveDocument Set firstWord = .Paragraphs(160).Range.Words(3) Set RangeTop =.Range (Start:= firstWord.Start) End With

As I discuss in the section “ Finding and Replacing in Word VBA,” later in this chapter, using Find with a range or selection redefines the object to encompass only the text that it finds. So, after Find locates a phrase in a range or selection, the Start or End properties for the same range or selection now identify the start and end positions of the found text.

Working with Text in Word VBA Range and Selection objects are the starting points for almost everything

you can do to text in Word VBA. Some text manipulations can be applied to documents as a whole, but in general, you need a range or selection before you can make changes. Range and Selection objects have a great deal in common, but they also have important differences. Both represent continuous sequences of characters, upon which you can perform all kinds of editing magic. They share the majority of their properties and methods. However, some properties and methods are unique to selections and some to ranges. The big differences, of course, are that

CD-27

CD-28

VBA For Dummies, 3rd Edition a Selection object corresponds to a window pane’s one visible selection — which can be text, graphics, or other items — while Range objects exist independently of the selection, always consist of text, and can be accessed in any number. Use the Selection object when your procedure depends on the user to identify the text to be manipulated, or when you want to show the user the text being changed. Range objects are better otherwise. They make your program faster and less distracting to the user — Word updates the screen every time the selection changes, but leaves the screen alone when modifying a range. In addition, range modifications politely leave the user’s selection undisturbed.

Selecting ranges, and creating ranges from selections Despite their differences, Selection and Range objects can be created easily from one another. This capability is key. Many important editing functions work only with ranges. Contrariwise, the only way to display the contents of a range to the user is by selecting the range. Use these simple techniques: ⻬ To select a range, use the range’s Select method. For a range object called RangeR, the code is RangeR.Select. ⻬ To access a range representing the same contents as a selection, use the selection’s Range property, as in Selection.Range. Remember, if a text-related method calls for a range but you want to use it on the selection, just include Selection.Range.MethodName in your code.

Redefining ranges and selections Word VBA offers a scad of methods for moving and resizing ranges and selections. I cover some of the most important of these in this section, but you can find more by carefully studying the Help files.

Expanding a range or selection The Expand method makes an existing range or selection bigger by tacking a unit of text onto its end. The unit can be a character, word, or paragraph, or any of a number of other predefined chunks. You can only add one of the specified units at a time, however, and you can’t add units to the beginning of the range or selection. To add to the selection the word that immediately follows it, use the following statement: Selection.Expand(wdWord)

Bonus Chapter B: VBA Programming in Word You can use any of the following constants to expand the object: wdCharacter, wdWord, wdSentence, wdParagraph, wdSection, wdStory, wdCell, wdColumn, wdRow, wdTable, and (for Selection objects only) wdLine. wdWord is the default. Now for a potentially confusing point: Selection objects (but not ranges) also have an Extend method. This method turns on Word’s extend mode, which extends the selection when the user moves the insertion point. Each time that your program calls the Extend method, the selection grows by a larger unit of text to encompass — in sequence — the current word, sentence, paragraph, section, and document. If you specify a character argument, as in Selection.Extend(“C”), the selection extends to the next occurrence of that character instead.

Moving a range or selection Word VBA permits you to redefine the beginning and end of a range or selection at will. Just be aware that the methods that include “Move” in the name change the location of the range or selection — they don’t actually move the text contained in the object. The Move method alters the range or selection by first collapsing it so that it marks a location only and no longer contains any text. This location is the starting position of the original object. The method then moves this collapsed object according to your instructions. After the move is complete, you can use the Expand or MoveEnd methods to make the object encompass text. The following example moves the named range backward in the document by two paragraphs. Note that you use a named constant for the Unit argument (see the section “Expanding a range or selection,” earlier in this chapter, for a list of these constants). The Count argument is a positive integer if you want to move forward in the document (toward the end), negative to move backward. If the range or selection isn’t already collapsed, or if it falls inside a unit, the beginning or end of the current unit is counted as the first one of the move. In this example, no parentheses appear around the arguments because the method’s return value — how many units were actually moved — isn’t used here. onTheRange.Move Unit:=wdParagraph, Count:= -2

The MoveStart and MoveEnd methods work like Move, except that they only change the starting or ending position of the range or selection. The following statement moves the beginning of the selection three words closer to the end of the document: Selection.MoveStart Unit:=wdWord, Count:=3

Note that if you move the object’s starting point past the end, Word collapses the range or selection and moves it as specified. The reverse occurs when moving the object’s end before the start.

CD-29

CD-30

VBA For Dummies, 3rd Edition Yet another pair of methods, StartOf and EndOf, move or extend the start or end position of a range or selection. StartOf moves the start of the object backward to the start of the current unit while EndOf moves the end of the object forward to the end of the current unit. You can use the Extend argument with either method to control whether Word moves both the start and end simultaneously, collapsing the object or only the side that’s being moved. If the side of the object being moved is already at the side to which you’re moving, nothing happens. Use the wdMove constant to collapse the object or wdExtend to move only the specified side. Here’s an example: Selection.StartOf Unit:=wdSentence, Extend:=wdMove

Collapsing a range or selection Often, you must collapse a range or selection to a single position that doesn’t enclose any text. In technical terms, a collapsed range or selection is one in which the start and end are the same. Collapsing these objects is critical when you want to insert a field, table, or other item before or after a selection or range without replacing the object’s text. (You can insert plain text, new paragraphs, and some other items at a non-collapsed range or selection.) Use the Collapse (what else?) method to collapse a range or selection. You can collapse the object to the original starting or ending position, as you prefer, by using the optional Direction argument. The following example collapses the selection to its start: Selection.Collapse

This second example collapses a range object to its end: Selection.Collapse(Direction:=wdCollapseEnd)

If you collapse a range that ends with a paragraph mark to its end (by using wdCollapseEnd), Word places the collapsed range after the paragraph mark (that is, the collapsed range is located at the start of the next paragraph). If you want to insert something in front of the original range’s paragraph mark, you must first move the range backward with the MoveEnd method via a statement such as this: someRange.MoveEnd Unit:=wdCharacter, Count:=-1

Deleting, copying, and pasting text Erasing all the text in a range or selection is easy — just use the object’s Delete method. You can use the Cut method instead if you want to remove the text and place it on the Windows Clipboard. Of course, the Copy method puts the text on the Clipboard without affecting the text in the range or selection.

Bonus Chapter B: VBA Programming in Word You can insert text placed on the Clipboard into any range or selection with that object’s Paste method. If the destination object isn’t already collapsed, the pasted text replaces the text in the object — just the way the Paste command works in Word. Although using the Clipboard to transfer text from one location to another is a familiar method, it’s not the most efficient one. A better approach is to use the Text or FormattedText properties of the destination range or selection. Set these properties equal to the range or selection containing the text that you want to transfer and you’re in business. The destination object should be collapsed unless you want the transferred text to replace the object’s existing text. The following example transfers the text from the selection to a collapsed range based on a bookmark (the fourth line actually performs the transfer). Only the text itself, without any formatting, gets copied to the new location. With ActiveDocument.Bookmarks(“TheBookmark”) Set RangeY = _ ActiveDocument.Range(Start:=.Start, End:=.Start) End With RangeY.Text = Selection.Text

To transfer all the formatting along with the text, just substitute the FormattedText property for the Text property on both sides of the equal sign.

Inserting new text The easiest text-adding technique to remember is to set the Text property of a range or selection to the text you want to insert. The following statement illustrates this: Range2.Text = “Hey, ho, nobody home”

Just remember that setting the Text property replaces the existing text, if any, in the range or selection. To avoid replacing existing text (unless that’s your intention), collapse the object first. Use the InsertBefore or InsertAfter methods of a range or selection object to insert text at a specific location in a document without destroying the object’s existing text. These methods place the new text immediately before the start or after the end of the object in question, respectively. Word includes the inserted text in the selection or range. With either method, the only argument is the text you want to insert. The following example inserts a new paragraph containing the text “Diary entry” at the beginning of the selection (note the use of the VBA constant vbCr to

CD-31

CD-32

VBA For Dummies, 3rd Edition insert a paragraph mark). It then adds a paragraph stating today’s date at the end. If you select an entire paragraph before running this code, the date paragraph appears after the paragraph mark in the selection. Dim strInsertText As String Selection.InsertBefore “Diary entry” & vbCr strInsertText = “Today” & Chr(146) & “s date is “ strInsertText = _ strInsertText & Format(Now, “Long date”) & “. “ Selection.InsertAfter strInsertText & vbCr

The example shows how inserted text can include string variables and VBA functions that return strings, as well as literal text and VBA constants. See Chapter 11 for information on formatting and modifying strings in VBA. The easiest way to add a new, empty paragraph to a document is to insert a paragraph mark (represented by the constant vbCr) with the Text property or InsertBefore/InsertAfter methods. The Add method used on a Paragraphs collection also works, but it’s more cumbersome. Use it only if you want to place the new paragraph within a range or selection rather than at the beginning or end.

Formatting text Several key properties of a range or selection are your gateways to changing the appearance of the text. These properties correspond to the items in Word’s Format menu, and they function as follows:

This Property

Gives Access To

Font

Subsidiary properties for each aspect of character formatting, such as Name, Size, and Bold. For some reason, you can directly access the most common character formatting properties on Range objects, without going through the Font property, but not on selections.

ParagraphFormat

Subsidiary properties for each aspect of paragraph formatting, such as LeftIndent and LineSpacing.

Style

The name of the character or paragraph Style applied to the range or selection.

Borders

The borders around the text.

TabStops

Types and locations of tab stops. You can access this property only through Paragraph objects, not directly via ranges or selections.

Bonus Chapter B: VBA Programming in Word

Finding and Replacing in Word VBA Although it sounds like an imperative, Find is an object in Word VBA. Find objects belong to ranges and selections. Locating text or formatting with a Find object requires the following steps: 1. Access the Find object for a particular range or selection. If you want to search the entire document, use the Document object’s Content property to access the corresponding range, as in the following: ActiveDocument.Content.Find

2. Set the Find object’s properties corresponding to what you’re looking for and how you want to look for it. 3. Trigger the Find object’s Execute method. Here’s an example of the technique: With OpenRange.Find .ClearFormatting .Text = “pogo sticks” .Execute End With

For properties you don’t explicitly set, the Find object takes on the options that were last used or that are currently set in Word’s Find and Replace dialog box. That’s why you should always include the ClearFormatting method when you’re starting a new search — it removes any formatting that may have been previously specified from the search request.

Working with found text The Execute method’s job is to locate the first occurrence of the search text or formatting in the specified range or selection. After the Execute method runs, your first programming concern is to see whether or not it found the text you were looking for. Use the Find object’s Found property with an If...Then statement to perform this test, as in this sample code skeleton: If .Found = True Then (take action on the found text) Else (display an appropriate message) End If

If the Execute method finds the search text, the original range or selection is redefined so that it encompasses the found text. This is a key point, because it means that you can work directly with that text through the original object’s properties and methods. In the following code, an expansion of the first example in this section, the statement .Parent.Italic = True refers

CD-33

CD-34

VBA For Dummies, 3rd Edition to the parent of the Find object, that is, the range called OpenRange. If that statement runs, OpenRange now encompasses only the found text — so only that text will be formatted in italic. With OpenRange.Find .ClearFormatting .Text = “pogo sticks” .Execute If .Found = True Then .Parent.Italic = True Else MsgBox “No pogo sticks found.” End If End With

Replacing text or formatting The Replacement object belongs to (that is, it’s a property of) the Find object. To code a search and replace operation, you set properties and trigger methods of the Replacement object. The following example replaces all occurrences of the word “pogo sticks” with “skateboards.” The selection changes when the find criterion is found because the Find object is accessed from the Selection object. With ActiveDocument.Content.Find .ClearFormatting .Text = “pogo sticks” With .Replacement .ClearFormatting .Text = “skateboards” End With .Execute Replace:=wdReplaceAll End With

Note that the Execute method can take a Replace argument, used to control whether all occurrences of the found text, or only the first, get replaced.

Finding and replacing formatting To search for text that’s formatted a certain way, use the Find object’s formatrelated properties. These are identical to the properties you use to work with formatting of a range or selection, as I discuss in the section “Formatting text,” earlier in this chapter. You use these same properties on the Replacement object if you want to specify formatting for the replacement text.

Bonus Chapter B: VBA Programming in Word To search for any text with particular formatting, set the relevant Find properties and then set the Text property to an empty string using a pair of adjacent quotation marks. To change the formatting of found text without altering the text itself, use an empty string for the Text property of the Replacement object. The following code searches for paragraphs currently assigned to the Drab style and applies the Frilly style to them instead: With Selection.Find .ClearFormatting .Style = “Drab” .Text = “” With .Replacement .ClearFormatting .Style = “Frilly” .Text = “” End With .Execute Replace:=wdReplaceAll .ClearFormatting .Replacement.ClearFormatting End With

Including the two format-clearing statements in your procedures after the Execute method is a good idea. Otherwise, the next time the user opens the Find and Replace dialog box, she’ll have to clear formatting options manually.

Using Document Variables Unique among the Office applications, Word allows you to define special document variables in your code that it records with an individual document for later use. Document variables make it possible to store values used by a procedure between editing sessions. Create and access document variables as members of the document’s Variables collection. Like ordinary variables, document variables have names. The following statement places the value of a document variable called Henry into an ordinary variable called FriendOfAnais. FriendOfAnais = _ ActiveDocument.Variables(“Henry”).Value

To create a new document variable, use the Variables collection’s Add method, as shown here: Documents(“Document1”).Variables.Add _ Name:=”TimesThisMacroHasRun”, Value:=0

CD-35

CD-36

VBA For Dummies, 3rd Edition Because you get an error if you try to add a document variable that already exists, the safe way to create variables is by checking to see if the variable name already exists. If so, you can retrieve the value; if not, you can create the variable and assign it an initial value. The following code illustrates this technique: For Each DocVar In ActiveDocument.Variables If DocVar.Name = “LastCaption” _ Then DocIndex =DocVar.Index Next DocVar If DocIndex = 0 Then ActiveDocument.Variables.Add _ Name:=”LastCaption”, Value:=1 CaptionCounter = 1 Else CaptionCounter = _ ActiveDocument.Variables(DocIndex).Value End If

Even though the object models of the other Office applications don’t explicitly provide document variables, you can commandeer custom document properties for the same purpose. See the “VBA Programming in Office” chapter on the CD for information regarding the use of custom properties as document variables.