Reputation: 344
I want to temporarily remove hyperlinks. This is my function to remove them:
Sub HideHyperlinks()
Dim oField As Field
For Each oField In ActiveDocument.Fields
If oField.Type = wdFieldHyperlink Then
Debug.Print oField.Code.Text
oField.Unlink
End If
Next
Set oField = Nothing
End Sub
Then, I would like to change the document somehow and at a later stage add them again. Of course, that doesn't work because the field was turned into regular text and all information was lost.
How can I best do this? Should I turn wdFieldHyperlink into another wdField or some sort of Object, with the hyperlink URL as a hidden property? If so, how? This is my idea in pseudocode:
'Turn hyperlinks into newWdFieldType'
Sub HideHyperlinks()
For Each oField In ActiveDocument.Fields
If oField.Type = wdFieldHyperlink Then
'create newWdFieldType with hidden property oField.Code.Text'
'delete oField from document'
End If
Next
End Sub
'Turn newWdFieldType back into hyperlinks'
Sub ShowHyperlinks()
For Each oField In ActiveDocument.Fields
If oField.Type = newWdFieldType Then
're-create wdFieldHyperlink with hyperlink from newWdFieldType'
'delete oField from document'
End If
Next
End Sub
VBA is annoying to debug and the documentation is bad, or am I looking in the wrong place?
Upvotes: 0
Views: 146
Reputation: 1301
Some not well-tested possibilities:
If the hyperlinks can be hidden rather than deleted then you could do something like this. At the moment it assumes that all hidden hyperlinks should be unhidden, so if you hide material for other reasons you would need to make some kind of distinction between the ones you want to unhide and the ones you don't
Option Explicit
Const bookmarkPrefix As String = "wasahl"
Sub hideHyperlinks()
Dim h As Word.Hyperlink
Dim i As Long
Dim r As Word.Range
' This should deal with hyperlinks in the document body.
' If you have them elsewhere you will need to process other ranges/objects
i = 0
For Each h In ActiveDocument.Hyperlinks
' ignore hyperlinks that are already hidden
If Not h.Range.Font.Hidden Then
Set r = h.Range
' copy and hide the original
r.Copy
r.Font.Hidden = True
' Insert a copy and unlink it
r.Collapse WdCollapseDirection.wdCollapseEnd
r.Paste
r.Fields.Unlink
' This may not be needed but it makes finding and removing the
' unlinked material easier when we unhide the hyperlinks
' need a unique bookmark name, but this relies on the time, so don't
' run it twice in the same second!
i = i + 1
r.Bookmarks.Add bookmarkPrefix & format(Time(), "HHmmss") & CStr(i)
Set r = Nothing
End If
Next
End Sub
Sub unhideHyperlinks()
Dim b As Word.Bookmark
Dim h As Word.Hyperlink
' remove all our unlinked hyperlinks
' NB, as a user, you will need to be careful not to add material into
' the bookmarks as it will all be deleted!
For Each b In ActiveDocument.Bookmarks
If Left(b.Name, Len(bookmarkPrefix)) = bookmarkPrefix Then
b.Range.Text = ""
End If
Next
' Find the SET fields, extract the formatted text (code+result)
' copy it into the document and delete the SET field
For Each h In ActiveDocument.Hyperlinks
h.Range.Font.Hidden = False
Next
End Sub
I originally had a version of this that "hid" the original { HYPERLINK }
field by nesting it inside a { SET }
field, but if you can't retain hyperlinks in the document then that wouldn't be much use.
To save the link information in the general case is not trivial because in theory a { HYPERLINK } field could have nested field codes and non-text items in either its code or its result. In practice I think the only time when it makes sense to nest fields is probably when the document is a mail merge main document, and I don't think I've actually seen anyone insert any non-text item in either the field's code or result. So if all you ever have is text and no nesting, perhas something like this. NB, you would need to run the clearHLVariables() sub to get rid of the DOcument Variables. I didn't want to put that in the restore subroutine in case it fails.
Option Explicit
Const bookmarkPrefix As String = "wasahl"
Const codePrefix As String = "hlcode"
Const resultPrefix As String = "hlresult"
Sub saveHyperlinks()
Dim hc As Long
Dim i As Long
Dim r As Word.Range
Dim t As String
i = 0
' This should deal with hyperlinks in the document body.
' If you have them elsewhere you will need to process other ranges/objects
' We could either save the various possible components in the hyperlink, or we
' could just save the field code and perhaps the result. The latter seems a bit
' simpler so let's do that
With ActiveDocument
For hc = .Hyperlinks.count To 1 Step -1
i = i + 1
t = format(Time(), "HHmmss")
Set r = .Hyperlinks(hc).Range
.Variables(codePrefix & t & CStr(i)).Value = r.Fields(1).Code
' Probably do not have to store the result as it should be in the document when we
' restore the links, but I'm going to anyway
.Variables(resultPrefix & t & CStr(i)).Value = r.Fields(1).Result
' unlink the field and bookmark it with a name that will let us retrieve the
' associated variables later
r.Fields.Unlink
r.Bookmarks.Add bookmarkPrefix & t & CStr(i)
Set r = Nothing
Next
End With
End Sub
Sub restoreHyperlinks()
Dim b As Word.Bookmark
Dim r As Word.Range
Dim s As String
With ActiveDocument
For Each b In .Bookmarks
If Left(b.Name, Len(bookmarkPrefix)) = bookmarkPrefix Then
s = Mid(b.Name, Len(bookmarkPrefix) + 1)
b.Range.Fields.Add b.Range, WdFieldType.wdFieldEmpty, Trim(.Variables(codePrefix & s).Value)
End If
Next
End With
End Sub
Sub clearHLVariables()
' Probably safest to run this separately when you know you don't need
' the variables any more.
Dim v As Word.Variable
For Each v In ActiveDocument.Variables
If (Left(v.Name, Len(codePrefix)) = codePrefix) Or (Left(v.Name, Len(resultPrefix)) = resultPrefix) Then
v.Delete
End If
Next
End Sub
Upvotes: 1
Reputation: 13505
You can employ a custom undo record. For example:
Sub HideHyperlinks()
Application.ScreenUpdating = False
Dim objUndo As UndoRecord
Set objUndo = Application.UndoRecord
objUndo.StartCustomRecord ("Hyperlinks")
With ActiveDocument
MsgBox "# Hyperlinks: " & .Hyperlinks.Count
Do While .Hyperlinks.Count > 0
.Hyperlinks(1).Range.Fields(1).Unlink
Loop
MsgBox "# Hyperlinks: " & .Hyperlinks.Count
objUndo.EndCustomRecord
.Undo
MsgBox "# Hyperlinks: " & .Hyperlinks.Count
End With
End Sub
Upvotes: 0