vbams-wordhyperlink

Facing issues with creating multiple hyperlinks in a single cell in word


I have a script in which there is a consolidated table at the end of the word doc, and the scripts starts from row 3 and look for same matches based on column 2 and 3 and create hyperlinks to add to cell 5 in the last table.

The issue is that the hyperlinks get overwritten by the other hyperlinks, and I only get a single hyperlink which is the last match for that row.

When I checked using ctrl z, I noticed-

  1. Text for first hyperlink added.
  2. Become hyperlink.
  3. Paragraph added.
  4. Text for second hyperlink added.
  5. It didn't become hyperlink, but this hyperlink overwrites the first hyperlink.
  6. Paragraph added.
  7. Text for third hyperlink added.
  8. But this hyperlink overwrites the first hyperlink, so in this case for this row there have to be 3 hyperlinks, but it got overwrites in the first, and text for hyperlinks remain same.

This is what I get-

Match in Table19 Row 16 Match in Table4 Row 7 Match in Table19 Row 16

The output in this case should be-

Match in Table3 Row 7 Match in Table4 Row 7 Match in Table19 Row 16

If someone has a solution for this, it would be much appreciated.

Sub FindAndLinkMatches()
    Dim doc As Document
    Dim consolidatedTable As Table
    Dim otherTable As Table
    Dim i As Long, j As Long
    Dim valueCol2 As String
    Dim valueCol3 As String
    Dim tableIdentifier As String
    Dim tableCount As Long
    Dim foundMatch As Boolean
    Dim cellRange As Range
    Dim firstLink As Boolean

    Set doc = ActiveDocument

    Set consolidatedTable = doc.Tables(doc.Tables.Count)

    For i = 3 To consolidatedTable.Rows.Count
        foundMatch = False
        valueCol2 = CleanCellText(consolidatedTable.Cell(i, 2).Range.Text)
        valueCol3 = CleanCellText(consolidatedTable.Cell(i, 3).Range.Text)

        Set cellRange = consolidatedTable.Cell(i, 5).Range
        cellRange.Text = ""

        firstLink = True

        tableCount = 1
        For Each otherTable In doc.Tables
            If otherTable Is consolidatedTable Then GoTo NextTable

            If Trim(CleanCellText(otherTable.Cell(1, 1).Range.Text)) = "Parts Required" Then
                tableIdentifier = "Table" & tableCount

                For j = 2 To otherTable.Rows.Count
                    Dim otherValueCol2 As String
                    Dim otherValueCol3 As String
                    otherValueCol2 = CleanCellText(otherTable.Cell(j, 2).Range.Text)
                    otherValueCol3 = CleanCellText(otherTable.Cell(j, 3).Range.Text)

                    If NormalizeText(valueCol2) = NormalizeText(otherValueCol2) And NormalizeText(valueCol3) = NormalizeText(otherValueCol3) Then
                        otherTable.Rows(j).Range.Bookmarks.Add tableIdentifier & "Row" & j

                        If firstLink = False Then
                            cellRange.InsertAfter vbCr
                        End If

                        cellRange.InsertAfter "Match in " & tableIdentifier & " Row " & j
                        cellRange.Hyperlinks.Add _
                            Anchor:=cellRange.Paragraphs.Last.Range, _
                            Address:="", _
                            SubAddress:=tableIdentifier & "Row" & j, _
                            TextToDisplay:="Match in " & tableIdentifier & " Row " & j
                        
                        firstLink = False
                        foundMatch = True
                    End If
                Next j
                tableCount = tableCount + 1
            End If
NextTable:
        Next otherTable

        If Not foundMatch Then
            cellRange.Text = "No matches found"
        End If
    Next i
End Sub

Function CleanCellText(cellText As String) As String
    cellText = Replace(cellText, Chr(7), "")
    cellText = Replace(cellText, vbCr, "")
    cellText = Replace(cellText, vbLf, "")
    cellText = Replace(cellText, Chr(160), " ")
    CleanCellText = Trim(cellText)
End Function

Function NormalizeText(inputText As String) As String
    inputText = Trim(inputText)
    inputText = Replace(inputText, vbTab, " ")
    inputText = Replace(inputText, "  ", " ")
    inputText = LCase(inputText)
    NormalizeText = inputText
End Function


Solution

  • Try:

    Sub FindAndLinkMatches()
    Application.ScreenUpdating = False
    Dim Tbl As Table, Rng As Range,i As Long, j As Long, t As Long
    Dim StrCol2 As String, StrCol3 As String, TblNm As String
    Dim StrTCol2 As String, StrTCol3 As String
    With ActiveDocument
      Set Tbl = .Tables(.Tables.Count)
      With Tbl
        For i = 3 To .Rows.Count
          StrCol2 = Cleaned(.Cell(i, 2).Range.Text)
          StrCol3 = Cleaned(.Cell(i, 3).Range.Text)
          .Cell(i, 5).Range.Text = "Matched in:"
          For t = 1 To ActiveDocument.Tables.Count - 1
            With ActiveDocument.Tables(t)
              If Cleaned(.Cell(1, 1).Range.Text) = "parts required" Then
                TblNm = "Table" & t
                For j = 2 To .Rows.Count
                  StrTCol2 = Cleaned(.Cell(j, 2).Range.Text)
                  StrTCol3 = Cleaned(.Cell(j, 3).Range.Text)
                  If StrCol2 & StrCol3 = StrTCol2 & StrTCol3 Then
                    .Rows(j).Range.Bookmarks.Add TblNm & "Row" & j
                    Set Rng = Tbl.Cell(i, 5).Range
                    With Rng
                      .Collapse wdCollapseEnd
                      .End = .End - 1
                      .InsertBefore Chr(11) & Chr(11) ' or .InsertBefore "  "
                      .Hyperlinks.Add Anchor:=.Characters.Last, Address:="", _
                        SubAddress:=TblNm & "Row" & j, TextToDisplay:=TblNm & " Row" & j
                    End With
                  End If
                Next
              End If
            End With
          Next
          Set Rng = Tbl.Cell(i, 5).Range
          With Rng
            .End = .End - 1
            If .Text = "Matched in:" Then .Text = "No matches found"
          End With
        Next
        With .Range
          For j = 1 To .Hyperlinks.Count
            .Hyperlinks(j).Range.Style = wdStyleHyperlink
          Next
        End With
      End With
    End With
    Application.ScreenUpdating = True
    End Sub
    
    Function Cleaned(StrText As String) As String
    Cleaned = LCase(Trim(Replace(Replace(Replace(Split(StrText, vbCr)(0), Chr(160), " "), vbTab, " "), "  ", " ")))
    End Function