Word Hacks [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Word Hacks [Electronic resources] - نسخه متنی

Andrew Savikas

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







Hack 43 Cross-Reference Automatically

Using the Cross-reference dialog to insert
references, particularly in a lengthy document, can be frustrating
because it shows you only a few headings at a time. This hack shows
you how to create references automatically, without a visit to the
dialog.

Whoever decided that the
Cross-reference dialog in Word
(InsertReferenceCross-reference or
InsertCross-reference, depending on your version of Word)
should display only nine items at a time clearly
didn't have your best interests in mind. Most
lengthy documents include more than nine headings, captions, or other
items to reference.

In many cases, creating a cross-reference means converting static
text into a dynamic reference by selecting it, then replacing it with
the corresponding item from the Cross-reference dialog (as shown in
Figure 4-27). But since there's
that nine-item limit, you're in for some serious
scrolling if you need to make many references. In a Sisyphean spiral,
the longer your document is, the more references you likely need, and
the longer it will take to find each item in that teeny, tiny list.


Figure 4-27. Only nine items at a time are visible in the Cross-reference dialog

This hack shows you two ways to use VBA to automatically create
cross-references to headings. In each case, the selected text is
compared to the headings in a document, trying to find a match and
create a cross-reference.


4.18.1 Referencing the Way Word Does


The procedure shown in this section uses Word VBA's
GetCrossReferenceItems method, which returns a
list of potential reference targets in a document. Because Word
continually updates and indexes this list, accessing it is very
fast. This code runs
significantly faster than the code in the next section, but that
speed comes at a price: you're limited to creating
cross-references to items that Word considers potential targets, such
as headings that use one of the built-in heading styles. If
you've also got a different kind of heading style in
your document, such as SidebarTitle, those headings
don't "count" as
possible reference targets.

Place this macro in the template of your choice [Hack #50]
and either run it from the ToolsMacroMacros
dialog or put a button for it on a menu or toolbar [Hack #1].

If your current selection includes more than one paragraph, the macro
exits without taking any action.

Sub InsertAutoXRef( )
Dim sel As Selection
Dim doc As Document
Dim vHeadings As Variant
Dim v As Variant
Dim i As Integer
Set sel = Selection
Set doc = Selection.Document
' Exit if selection includes multiple paragraphs
If sel.Range.Paragraphs.Count <> 1 Then Exit Sub
' Collapse selection if there are spaces or paragraph
' marks on either end
sel.MoveStartWhile cset:=(Chr$(32) & Chr$(13)), Count:=sel.Characters.Count
sel.MoveEndWhile cset:=(Chr$(32) & Chr$(13)), Count:=-sel.Characters.Count
vHeadings = doc.GetCrossReferenceItems(wdRefTypeHeading)
i = 1
For Each v In vHeadings
If Trim (sel.Range.Text) = Trim (v) Then
sel.InsertCrossReference _
referencetype:=wdRefTypeHeading, _
referencekind:=wdContentText, _
referenceitem:=i
Exit Sub
End If
i = i + 1
Next v
MsgBox "Couldn't match: " & sel.Range.Text
End Sub

There are two important limitations to note about this code. First,
if multiple headings match the selected text, the code creates a
reference to the first match and ignores subsequent matches. This
limitation is a problem if you have multiple headings with the same
text, such as "The Code," used
throughout this book.

Second, the code offers no protection against creating a
self-reference. If the match found by the code is the text
you've selected, the reference
that's created will replace the text
it's supposed to reference, resulting in a broken
reference, as shown in Figure 4-28.


Figure 4-28. Self-referencing creates a broken reference

This kind of inadvertent text deletion is also possible when creating
references from the Word Cross-reference dialog. When you create a
self-reference, Word displays a message telling you the reference is
emptybut only after the text has been deleted.


4.18.2 A Better Way to Reference


This method won't match the speed offered by the
code shown above, but its flexibility makes it a better starting
point for hacking your own solutions.

Rather than looking only at paragraphs that use one of
Word's built-in heading styles, this code examines
every paragraph in the document, looking for a match to the selected
text. That means you can easily create a reference to a heading that
uses a custom paragraph style, such as SidebarTitle.

Unlike the code in the previous section, this procedure also checks
to be sure the match it's found
isn't the selected text, avoiding the possibility of
a self-reference.

This code is divided into five separate procedures: the
MakeAutoXRef procedure and four supporting
procedures, each of which performs an operation needed to create the
reference. Place all five procedures in the template of your choice
[Hack #50]
and run the one named MakeAutoXRef to create a
reference in place of the selected text.

The first procedure, named MakeAutoXRef, is shown
first. In conjunction with the supporting procedures shown afterward,
it examines each paragraph in the document. If it finds one that
matches the selected text, it creates a bookmark around the match and
then replaces the selected text with a reference pointing to the
bookmark. If the matched paragraph has already been referenced
elsewhere, the existing bookmark is used.

Sub MakeAutoXRef( )
Dim sel As Selection
Dim rng As Range
Dim para As Paragraph
Dim doc As Document
Dim sBookmarkName As String
Dim sSelectionText As String
Dim lSelectedParaIndex As Long
Set sel = Selection
Set doc = sel.Document
If sel.Range.Paragraphs.Count <> 1 Then Exit Sub
lSelectedParaIndex = GetParaIndex(sel.Range.Paragraphs.First)
sel.MoveStartWhile cset:=(Chr$(32) & Chr$(13)), Count:=sel.Characters.Count
sel.MoveEndWhile cset:=(Chr$(32) & Chr$(13)), Count:=-sel.Characters.Count
sSelectionText = sel.Text
For Each para In doc.Paragraphs
Set rng = para.Range
rng.MoveStartWhile cset:=(Chr$(32) & Chr$(13)), _
Count:=rng.Characters.Count
rng.MoveEndWhile cset:=(Chr$(32) & Chr$(13)), _
Count:=-rng.Characters.Count
If rng.Text = sSelectionText Then
If Not GetParaIndex(para) = lSelectedParaIndex Then
sBookmarkName = GetOrSetXRefBookmark(para)
If Len(sBookmarkName) = 0 Then
MsgBox "Couldn't get or set bookmark"
Exit Sub
End If
sel.InsertCrossReference _
referencekind:=wdContentText, _
referenceitem:=doc.Bookmarks(sBookmarkName), _
referencetype:=wdRefTypeBookmark, _
insertashyperlink:=True
Exit Sub
Else
MsgBox "Can't self reference!"
End If
End If
Next para
End Sub

The code shown in bold is the part of the procedure that actually
creates the reference. Note that it's very similar
to part of the code shown in the previous section.


4.18.2.1 The supporting procedures

The following function removes from a string characters that Word
won't allow in bookmark names (except for spaces,
which are replaced by underscores in a different procedure):

Function RemoveInvalidBookmarkCharsFromString(ByVal str As String) As String
Dim i As Integer
For i = 33 To 255
Select Case i
Case 33 To 47, 58 To 64, 91 To 96, 123 To 255
str = Replace(str, Chr (i), vbNullString)
End Select
Next i
RemoveInvalidBookmarkCharsFromString = str
End Function

The next function takes a string and turns it into a valid bookmark
name, including prefacing it with
"XREF" for easier identification
and adding in a five-digit random number [Hack #68]
to ensure that it's unique.

In addition, the function replaces underscores with spaces. So, for
example, the heading "Foo the bar"
would be converted into something like
"XREF56774_Foo_the_bar"a bit
easier to work with than the
"_Ref45762234"-style names that
Word assigns to its own cross-reference bookmarks.

Function ConvertStringRefBookmarkName(ByVal str As String) As String
str = RemoveInvalidBookmarkCharsFromString(str)
str = Replace(str, Chr$(32), "_")
str = "_" & str
str = "XREF" & CStr(Int(90000 * Rnd + 10000)) & str
ConvertStringRefBookmarkName = str
End Function

This next function just determines a paragraph's
index in the document (e.g., the second paragraph in the document has
an index of 2):

Function GetParagraphIndex(para As Paragraph) As Long
GetParagraphIndex = _
para.Range.Document.Range(0, para.Range.End).Paragraphs.Count
End Function

The final function creates cross-reference
bookmarks in paragraphs that do not
contain bookmarks and returns the bookmark name for use in the
cross-reference. If the paragraph already has a cross-reference
bookmark, it simply returns the existing bookmark name for use in the
cross-reference.

Function GetOrSetXRefBookmark(para As Paragraph) As String
Dim i As Integer
Dim rng As Range
Dim sBookmarkName As String
If para.Range.Bookmarks.Count <> 0 Then
For i = 1 To para.Range.Bookmarks.Count
If InStr(1, para.Range.Bookmarks(i).Name, "XREF") Then
GetOrSetXRefBookmark = para.Range.Bookmarks(i).Name
Exit Function
End If
Next i
End If
Set rng = para.Range
rng.MoveEnd unit:=wdCharacter, Count:=-1
sBookmarkName = ConvertStringRefBookmarkName(rng.Text)
para.Range.Document.Bookmarks.Add _
Name:=sBookmarkName, _
Range:=rng
GetOrSetXRefBookmark = sBookmarkName
End Function


4.18.2.2 Running the hack

This hack wouldn't be much of a time-saver if you
had to go through a menu to run it. This code is most helpful when
assigned to a keyboard shortcut.

To assign a macro to a keyboard shortcut, select
ToolsCustomize and click the Keyboard button. Save your
changes in the same template in which you installed the code. In the
Categories column, select Macros, and in the Commands column, select
MakeAutoXRef. Choose and assign a keyboard shortcut
using the dialog.


/ 162