1
votes

I'm using Office 2016. I'd like to make a macro that loops through each heading in a document, and then creates a bookmark at the heading's location using the heading text (modified as necessary) as the bookmark name. Most of the headings are in X.X.X.X format, such as "3.3.4.1. sometexthere".

I'm still a beginner using VBA, but after a lot of googling I managed to adapt some Frankenstein code that almost works:

Sub HeadingsToBookmarks()
    Dim heading As Range
    Set heading = ActiveDocument.Range(Start:=0, End:=0)
    Do
        Dim current As Long
        current = heading.Start
        Set heading = heading.GoTo(What:=wdGoToHeading, Which:=wdGoToNext)
        If heading.Start = current Then
            Exit Do
        End If
        ActiveDocument.Bookmarks.Add MakeValidBMName(heading.Paragraphs(1).Range.Text), Range:=heading.Paragraphs(1).Range
    Loop
End Sub

Function MakeValidBMName(strIn As String)
    Dim pFirstChr As String
    Dim i As Long
    Dim tempStr As String
    strIn = Trim(strIn)
    pFirstChr = Left(strIn, 1)
    If Not pFirstChr Like "[A-Za-z]" Then
        strIn = "Section_" & strIn
    End If
    For i = 1 To Len(strIn)
        Select Case Asc(Mid$(strIn, i, 1))
            Case 49 To 58, 65 To 90, 97 To 122
                tempStr = tempStr & Mid$(strIn, i, 1)
            Case Else
                tempStr = tempStr & "_"
        End Select
    Next i
    tempStr = Replace(tempStr, " ", " ")
    tempStr = Replace(tempStr, ":", "")

    If Right(tempStr, 1) = "_" Then
        tempStr = Left(tempStr, Len(tempStr) - 1)
    End If

    MakeValidBMName = tempStr
 End Function

This code almost works, and makes appropriate bookmarks at some of the headings, but not all. Can anyone help me figure out what I need to fix here, or have other recommendations on how else I can clean up this code?

Edit: More information: The code above converts the first 5 or so headings in the document I've been testing it on, along with a few others scattered around. The second half of the code, which does the actual conversion, seems to work fine- the problem is located in the section that loops through each heading. The second half converts unusable characters to those that work with the requirements for bookmark names, and adds "Section_" to the beginning of bookmarks / headings that start with numbers (as bookmarks aren't allowed to start with numbers).

My goal is to be able to hyperlink to all sections within the document that has headings from a different word document. The standard Table of Contents creator allows only for links to be built within the same document, as far as I can tell. I'm aware that when word saves to PDF, it can convert headings to bookmarks; I would like to be able to do the same thing but retain the document in word format.

I unfortunately can't use the built in numbering. I'm working with documents that are already created and have a set and specific format.

2
You need to provide more detailed information. HOW exactly does the code you show us not work? Is it only that it doesn't find all the headings, or is there another problem? Are all the Headings you want to pick up formatted with the correct heading style? How, exactly, should the bookmarks be named? What do you want to do with the bookmarks, later? Without this information, it's not possible to provide you with an accurate answer...Cindy Meister

2 Answers

1
votes

You haven't described why you want bookmarks, or how a future user of the document would use/access the bookmarks.

MS Word has a number of built in features that act as bookmarks. The best way to do this is to use Styles. The built-in heading styles allow for some native navigation functionality (Word's own hidden bookmarks). Also, don't re-invent the wheel - use built in numbering.

This requires some document discipline. Use headings only for headings, and body text for the non-heading text.

The benefits make the discipline worth it. You can easily create tables of contents that use the headings (or even some of your custom styles), and headings show up in the navigation pane. When you save to PDF, you can use the headings as bookmarks in the PDF (show up on the Reader navigation bar).

Note that what I have described doesn't even touch VBA.

If you use set styles for your headings and you want to do a little more than what you can do natively, then you can simply:

Loop through all paragraphs in the document
See if that paragraph is set to your heading style
Place a bookmark (valid bookmark name!) over that paragraph

I have left the actual coding to you, but I think you will find it easy to do based on the pseudo code above. My pseudo code loop is not the only way to find the paragraphs, but it is the easiest to visualise.

Once you use the simplified method above and built-in numbering, you should find that you can modify your ValidBMName function - simplifying it. But, as noted and depending on why you want bookmarks, you may be able to avoid VBA altogether.

1
votes

This code works for me:

  Sub HeadingsToBookmarks()
    Dim heading As Range
    Set heading = ActiveDocument.Range(Start:=0, End:=0)
    Do
        Dim current As Long
        current = heading.Start
        Set heading = heading.GoTo(What:=wdGoToHeading, Which:=wdGoToNext)
        If heading.Start = current Then
            Exit Do
        End If
    'This is the part I changed: ListFormat.ListString
        ActiveDocument.Bookmarks.Add MakeValidBMName(heading.Paragraphs(1).Range.ListFormat.ListString), Range:=heading.Paragraphs(1).Range
        Loop
    End Sub