vbams-word

Making links to Places in this document work in vba


I'm trying to make a VBA script that will take all the headings in a document and make a table of contents out of them, with hyperlinks to each of the headings. The headings are all found, parsed and all the hyperlinks are made, however they don't correctly reach their destination which is a place within the document. The default 'create hyperlink to Place in this document' code looks like this:

Selection.Range.Hyperlinks(1).Range.Fields(1).Result.Select
Selection.Range.Hyperlinks(1).Delete
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:="", _
    SubAddress:="_Test_Heading"
Selection.Collapse Direction:=wdCollapseEnd

This is the code that you would get if you recorded a macro while using the 'Edit hyperlink' window.

Edit hyperlink window

The address field where normally there would be a URL is empty, while the subaddress field is filled by the name of the header with underscores.

I think the problem is that Word defaults to 'Existing file or web page' rather than 'Place in this document', even if 'Place in this document' were specified prior. If I switch the mode of a link to 'Place in this document' without changing the subaddress or anything else, it works - but having to go and do that for each link defeats the purpose of the script. I've been looking all over for a way to express 'Place in this document' in VBA but haven't found anything. Tried bookmarks as an alternative and that didn't work either. Any help would be appreciated.


Solution

  • I found a workaround using cross-referencing. In case it helps anyone in the future:

    Private Function GetLevel(strItem As String) As Integer
    
        Dim strTemp As String
        Dim strOriginal As String
        Dim longDiff As Integer
    
        strOriginal = RTrim$(strItem)
        strTemp = LTrim$(strOriginal)
        longDiff = Len(strOriginal) - Len(strTemp)
        GetLevel = (longDiff / 2) + 1
        
    End Function
    
    Sub TableofContents()
    
    Dim i As Integer
    Dim AllHeadings As Variant
    
    AllHeadings = ActiveDocument.GetCrossReferenceItems(wdRefTypeHeading)
    
    Selection.HomeKey Unit:=wdStory
    Selection.HomeKey Unit:=wdLine
    
    For i = LBound(AllHeadings) To UBound(AllHeadings)
        strtext = Trim$(AllHeadings(i))
        Level = GetLevel(CStr(AllHeadings(i)))
    
        If Level = 2 Then            
            Selection.InsertCrossReference ReferenceType:="Heading", ReferenceKind:= _
            wdContentText, ReferenceItem:=i, InsertAsHyperlink:=True, _
            IncludePosition:=False, SeparateNumbers:=False, SeparatorString:=" "
            Selection.TypeParagraph
        End If
    
    Next
    
    End sub
    

    The first function gets the level of the heading.

    The second part moves to the top of the document and starts inserting cross-references to the headings that I want (in this case I want it to be = 2).