• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 141
  • Last Modified:

Word VBA - looping and Paragraphs

I'm finding that looping through 5,000+ paragraphs in a document, to find approx 40 that have a Heading 1 style, is slow (takes minutes, and not milliseconds).

Is there a quick way of 'finding the next Heading 1 style'?

I heard that with the Paragraphs collection we don't need to loop through to work with the paragraphs. I don't know if that helps with my quest.

Thanks for any help.
  • 4
  • 4
  • 3
6 Solutions
hindersalivaAuthor Commented:
Ah sorry. Found the answer. There appears to be a Find.Style = Heading 1"

I'll leave the question open as there may be useful contributions to the topic from others.
crystal (strive4peace) - Microsoft MVP, AccessRemote Training and ProgrammingCommented:

Good you found the answer

not that it really matters, but Heading 1 is typically in a document just one time and is the title.  The main sections of the document would then be tagged with Heading 2.  My example was bad in another thread, sorry.

For others reading ...

it is nice that Word has a macro recorder. To see it, show the developer ribbon:

.1. Options
.2. Customize Ribbon
.3. check the Developer checkbox on the right under Customize Ribbon, Main Tabs
To see what VBA looks like for finding a style, click the Record Macro button on the Developer ribbon

a little trick to get the Find DIALOG BOX, which the macro recorder can capture, is to press Ctrl-H for Replace (Heplace, to remember shortcut key), or Ctrl-G for Goto, then change the tab to Find.

Click More >> to see options to customize the search and/or add format and special characters.
Word Find Style step 1 -- open dialog box and click More
To search for a style, click the Format command button and then choose Style...
Word Find Style step 2 - specify you want o find a Style
then in the Find Style dialog box, choose the style name you are looking for and click OK
Word Find Style step 3 -- choose style name
back in the Find and Replace dialog box, click Find Next
Word Find Style step 4 -- Find Next
Cancel the Find and Replace dialog box.

Then click the Stop Recording button on the Developer ribbon.

To see the VBA that got written:
click the Macros button or press Alt-F8

click ONE time on the macro you just made
click the Edit button

A lot of stuff you didn't set and don't care about is probably in there ... what is important is that what you want may be there too -- most likely it will be something like this:
   Selection.Find.Style = ActiveDocument.Styles("Heading 2")
   With Selection.Find
      .Text = ""
      .Replacement.Text = ""
      .Forward = True
      .Wrap = wdFindContinue
      .Format = True
      .MatchCase = False
      .MatchWholeWord = False
      .MatchByte = False
      .MatchWildcards = False
      .MatchSoundsLike = False
      .MatchAllWordForms = False
   End With

Open in new window

that you can change to something like this:

Sub FindHeading2()
' 171224 strive4peace

   Dim oDoc As Document _
      , oRng As Range
   Dim nPosStart As Long _
      , nPosEnd As Long
   Set oDoc = ActiveDocument
   'start lookikng one character after where we are
   nPosStart = Selection.End + 1
   'end at the end of the document
   nPosEnd = oDoc.Characters.Count
   'set a variable for the range
   'to be where we are in the document to the end
   Set oRng = oDoc.Range(nPosStart, nPosEnd)

   'find next paragraph with Heading 2
   With oRng.Find
      .ClearFormatting 'in case anything was previously set
      .Format = True
      .Style = "Heading 2"
      .Text = ""
      .MatchWildcards = False
      .Forward = True
      If .Execute Then 'you can loop .Execute if you want more than one
         'orng is redefined to be what you are looking for
         oRng.Select 'this is only to check -- SELECT slows performance
         'add what you want to do
Debug.Print oRng.Start, oRng.End, oRng.Text
      End If
   End With
   Set oRng = Nothing
   Set oDoc = Nothing
End Sub

Open in new window

to run from Access or somewhere else like Excel, define oApp to be the Word application and preface references with oApp.

I did not add error handling, but it is good to include it. Here is a video that show what to do:

have an awesome day,
Eric FletcherCommented:
"Heading 1 is typically in a document just one time and is the title.  The main sections of the document would then be tagged with Heading 2."

Not necessarily Crystal. While Heading 1 may be okay for the title for a small paper or report, a table of contents will include it unless you edit the TOC field code (by default, Heading 1s get tagged as TOC 1 styles). For books and more complex documents, I recommend either using a custom style for the title or using Word's default style (named "Title"). This allows Heading 1 to be used for chapter or section titles that do need to be included in a ToC. Lower levels can use Heading 2, 3, etc. styles — where they can then be included in a ToC.

For hindersaliva's OP though, do you need to use VBA? If you use the UI's Find dialog, click More>> to see additional options, then use Format > Style to select Heading 1. You can either leave the modal Find dialog up and click Find Next to cycle through them, or press Shift-F4 to repeat the find.
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

crystal (strive4peace) - Microsoft MVP, AccessRemote Training and ProgrammingCommented:
Eric, thanks for commenting. I see your point.  The reason I like to use one Heading 1 tag and the rest Heading 2 and below is:

The TOC picks up levels of Heading tags, as do other built-in features
on a web page, for SEO*, if there is more than one H1 (Heading 1) tag, or it is missing, it does not get read for H1

*Search Engine Optimization. While this is a Word doc, not a web page, whenever possible it is good to keep the same rules -- besides, it might become a web page someday ... or get searched like one.

I've been using the Heading styles built into Word for a few decades. It works great and is, in my opinion, a good habit.

If you are writing a book and have lots of chapters, it is good to use Master Document and Subdocuments with each chapter in a separate file -- in which case, each chapter may have one heading 2, and no heading 1 since the master document would have heading 1.

have an awesome day,
hindersalivaAuthor Commented:
Eric, yes I have to use VBA. It's to automate the authoring of 400+ page specifications with 900+ Headings 1, 2 and 3. The procedures will Hide/Show the required parts selectable from cascading UserForms, which themselves are built 'on  the fly' from the parts that exist on the document. So, yes -.not a manual authoring scenario.

Crystal's code has got me most of the way. See earlier questions.

BTW I'm using Find, rather than looping over the paragraphs. It's a lot faster.
Eric FletcherCommented:
I hope this doesn't divert this thread from the OP's question Crystal, but I wouldn't want to have readers spend time struggling with the Master Document feature. It is buggy and not very convenient for producing a book. I have used it for manuals where there are multiple authors — but even then, it is very difficult to enforce the rigour needed to keep it all together for formatting and consistency.

Over the past 30+ years of producing many hundreds of books with Word, I've never found a problem with having the full content in a single document. In fact, even a fully-paginated book of 600+ pages with many chapters, several tables of contents (chapters, figures, illustrations), an index and many dozens of images, formulae, charts and complex tables was less than 3MB. It opened quickly, and navigation through it was easy. (Images and charts were linked to avoid having them included in the Word file.) Most books in the 100-300 page range are <1MB, and open practically instantly on modern systems. The key is to use Word's supposedly-advanced features as they were designed; in particular, styles, sections and field codes.

Regarding the TOC field code, note that it can be edited to collect from any named style. As well, switches can be used to isolate bookmarked parts of a document (for example, to create one ToC for the main body and another for the appendices, or to exclude front- and/or back-end content in a ToC).

I was not aware that some SEO tools will ignore the Heading 1 style tag if >1 is used. When I need to convert a book from print or eBook format to a web page, I have always used 3rd party tools to manage the conversion since Word's "save as HTML" options can't adequately cope with many of the features I typically use to prepare a book.

Thanks for your useful comments — and I hope @hindersaliva doesn't mind the asides!

Eric FletcherCommented:
Your comment came through as I was typing the above hindersaliva.

I can see why you'd need to use VBA — and I'm glad to see that you are using Find instead of looping. Find is frequently overlooked (in both the UI and VBA), but it is a surprisingly powerful tool. Unfortunately, the move to the ribbon "dumbed down" the capabilities of the UI version of Find by adding extra steps to get at the "More >>" options available in the dialog box.

It may not be applicable to your project, but for some trainer manuals I've done, I set the trainer notes in styles that were based on one style, and the student content in styles based on another. This way, a button that runs a VBA macro could hide the instructor content by redefining the "based on" style to set its font attribute to invisible. This made it possible to have both manuals printed form a single document — and greatly simplified editing and updating.
crystal (strive4peace) - Microsoft MVP, AccessRemote Training and ProgrammingCommented:
Eric, thanks for your comments. You've done a lot of writing with Word!

Good idea about putting trainer notes in another style and hiding them for printing student manuals. Hidden text is useful other ways too.

I first used Word in 1987* to format a book. Back then, printers could do more than the software had features for, so I used hidden text to embed PostScript commands for the printer; for instance, to shade "screens" and draw keycaps that look like buttons.  After that that I drew all the keycaps in PowerPoint, copied the drawings to Word and saved each in AutoText.

* 30 years ago! I've been using Word longer than Access (which is where I am most the time these days). Well, today I am drawing piano keys and musical stuff in PowerPoint ~~- making handouts to teach music to children ... one of my New Years resolutions is to reach more of the community. I've been volunteering informally at a church -- the little ones love learning ... in short spurts ;) ~

While master/subdocument is buggy, it is still a good way to dish out chapters, especially when there are multiple authors. Word starts bogging down for me after 200-300 pages (my computer is old! really old! I plan to get a new one soon)

I like the built-in heading levels because of the shortcut keys too ... I define Alt-Ctrl-4, 5, 6,  ... don't know why Word stopped at Heading 3!

The "style" of my Heading styles is different than the default definitions.

While it is true that you can use any styles you want for the TOC, using the built-in styles saves that step.

on SEO and H1 ... yes, there can be only one for it to register with SEO -- and the document should be properly stepped -- H1 is first heading tag, then H2, then H3, back to H2 or another H3 or H4, ... not H4 after H2 and skip H3 cause you like the way it looks, and so on.

hindersaliva, it sounds like your app is really coming along ... I'd love to see it when you are done.

have an awesome day,
hindersalivaAuthor Commented:
I have one further question re. Find.
Find works great, much quicker than looping through all the paragraphs. But I have an issue. This is the code I use to find only Heading 1.

    With rngContent.Find
     .ClearFormatting           'why is this here? what does it do?
     .Style = "Heading 1,Section Heading,Head 1,VS1"
     .Execute Forward:=False
    End With

Open in new window

But, some of the items will be Hidden. The above Find doesn't find those. So I tried ...
.Font.Hidden = True

Open in new window

But that would only find those that are Hidden.

I need to Find both Hidden and Not Hidden, in the order in the document so it needs to be a 'top-to-bottom' run (not two runs). And grab the Hidden state while I'm at it, of course. (I stuff the data into an array during the run BTW)

I'd be grateful for ideas. Thanks.
Eric FletcherCommented:
If you toggle visibility of hidden text, the Find will find all instances. For a VBA reference about how to manage it, see this Microsoft page.

In your code, you can test & toggle the status before your Find(s), then restore it before you finish the routine.
hindersalivaAuthor Commented:
Eric, that's brilliant!
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

  • 4
  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now