Hack 66 Hack Documents with For Each Loops![]() ![]() 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 Table 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![]() 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 Tools 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( )A generalized version of that macro would be the following: Sub DoForEach( )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 ChangeCommentsFor Each loops are ideal for single-use macros because you can code them fast without investing a lot of development time.
7.11.1 When to Avoid For Each LoopsA 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( )For... Next loops can also count backward, when you use the optional Step statement, as the following macro shows: Sub CountDown( )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( )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 |