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

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

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

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

Andrew Savikas

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

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

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







Hack 66 Hack Documents with For Each Loops

When you need a quick and dirty solution, you
don't always have time to find the best tool for the
job. This hack introduces you to the Swiss Army Knife of VBA
programming.

In the Unix world, a handy utility program called
sed has been doing the dirty work of editing
text files for more than 30 years. Other programs and languages have
come along that can do the same thing sed does (and more), but
thousands of users still fire up sed every single day. Why? Because
sed reads and edits text files the same way people do: line by line;
so it's easy for people to
"tell" sed what to do.
It's not the fastest, and it's not
the prettiest, but it's hard to beat for automating
rote tasks. A technique for writing macros in VBA shares that same
trait of "thinking" the way people
do, but about Word documents. It's a
For Each loop, and you should
consider it your tool of first resort for quick and dirty solutions
to everyday problems.

A lot of the simple but tedious tasks you do in Word come about when
you need to modify something. For example, say
you've got a document peppered with dozens of tables
of varying size. Some of the tables have a heading row with bold
applied to all the text in the row. Since some of those tables might
span multiple pages, you want the heading row to repeat [Hack #20]
on each page.

One option is to use Word's "Browse
by Object" feature to scan the text for each table,
as shown in Figure 7-15. To browse a document table
by table, click the blue circle between the two double arrows, just
below your vertical scrollbar. After you choose
"Browse by Table," click one of the
double arrows to jump to the next or previous table in the document.
If the table has a bold heading row, select it, and then select
TableHeading Rows Repeat. This procedure is just
complicated enough to require your full attention but simple and
repetitive enough to make it a real chore.


Figure 7-15. Browsing a document, one object at a time

When the instructions are simplelook at each table
in the document, and if the first row is in bold, then select the
option to repeat that row across
pagesit's often easy to translate
them into terms a macro can understand. A big hint that a
For Each loop might be useful
here is the presence of the word
"each" in the instructions.

If you want to run the sample macros in this hack, place them in the
template of your choice [Hack #50]
and run them either from the ToolsMacroMacros
dialog or from within the Visual Basic Editor.

Excluding comments and the required Sub and
End Sub parts, you can take
care of the tables with just six lines of fairly understandable VBA
code:

Sub CheckTableHeadings( )
' Declare a variable of type "Table"
Dim tbl As Table
' Look at each table in the document
For Each tbl In ActiveDocument.Tables
' If the first row is bold
If tbl.Rows(1).Range.Font.Bold = True Then
' Select the option to repeat that row across pages
tbl.Rows.HeadingFormat = True
End If
Next tbl
End Sub

A generalized version of that macro would be the following:

Sub DoForEach( )
Dim variablename As Thing
For Each variablename in ActiveDocument.Things
' Do stuff to the current "Thing"
Next variablename
End Sub

The Thing in this code could be tables,
comments, bookmarks, fields, paragraphs, revisions, and so forth. For
example, the following macro changes the author of any comment
written by Marlowe to Shakespeare:

Sub ChangeComments
Dim oComment as Comment
For Each oComment In ActiveDocument.Comments
If oComment.Author = "Marlowe" Then
oComment.Author = "Shakespeare"
End If
Next oComment
End Sub

For Each loops are ideal for
single-use macros because you can code them fast without investing a
lot of development time.


The Word object model does include Characters and
Words collections, but there's no
corresponding singular Character or
Word object. If you want to visit each character
or word in a document, as in [Hack #32], declare a
Range variable for use in your loop:

Sub BoldLongWords( )
Dim oWord as RangeFor Each oWord In ActiveDocument.Words
If oWord.Characters.Count > 10 Then
oWord.Bold = True
End If
Next oWord
End Sub


7.11.1 When to Avoid For Each Loops


A For Each loop is a poor
choice if your macro needs to delete any of the
"things" mentioned in the previous
section. In these cases, you'd want to use another,
more traditional type of loop: a For...
Next loop. For...
Next loops use a counter
variable to keep track of their place, as the
following macro, which counts from 1 to 5, shows:

Sub CountUp( )
Dim i As Integer ' This is the counter variable
For i = 1 to 5
MsgBox i & " Mississippi"
Next i
End Sub

For... Next loops can also
count backward, when you use the optional Step
statement, as the following macro shows:

Sub CountDown( )
Dim i As Integer ' This is the counter variable
For i = 3 to 1 Step -1 ' Going backward from 3 to 1
MsgBox i
Next i
MsgBox "Contact!"
End Sub

So why are there two different kinds of loops? Well, the
For Each loops described in the
previous section are really just modified For...
Next loops, designed to iterate through objects in
a collection using a simpler syntaxand, more importantly, to
execute much faster.

To show the difference in the syntax, here's the
CheckTableHeadings macro from the previous section
rewritten using a regular For...
Next loop:

Sub SlowerCheckTableHeadings( )
Dim tbl As Table
Dim i as Integer
For i = 1 To ActiveDocument.Tables.Count
Set tbl = ActiveDocument.Tables(i)
If tbl.Rows(1).Range.Style = "TableHeading" Then
tbl.Rows.HeadingFormat = True
End If
Set tbl = Nothing
Next i
End Sub

With the For Each version, that
Set statement is implicit, and the loop
automatically goes one at a time from the first to the last item. But
that speed comes at a price: if you delete any of the
"things" that a
For Each loop is visiting, the
loop can lose its place and may skip over items.

Instead, to delete some (or all) of the objects in a collection, as
in [Hack #28],
use a For... Next loop and run
it backward from the end of the document:

Sub DeleteFootnotes
Dim i as Integer
For i = ActiveDocument.Footnotes.Count to 1 Step -1
ActiveDocument.Footnotes(i).Delete
Next i
End Sub


/ 162