Field Macros

Home Up Odds & Ends Photo Gallery Search Contact Me Privacy Notice

 

 

The information in this website is provided without risk or obligation and free of charge.  However, if you have benefitted from my efforts here and would like to make a contribution to help me continue and maintain this work then any donation will be greatly appreciated. Please click the adjacent button to access PayPal.  Thank you.
 

I love Word fields.  They are a semi-advanced Word feature and with the exception of VBA, I think that they are  the most powerful and useful feature in the application. 

But this Microsoft Word Help & Tips page isn't about fields.  It is about macros designed for working with the field collection (e.g. deleting fields, updating fields, etc.).  I also wanted to use this page to post what I consider a brilliant method for creating nested fields using VBA as shown to me by a regular Word newsgroup contributor, Dave Lett.  

Deleting fields. 

1.  There is no "pure" VBA equivalent of the User Interface Edit>Replace method for globallly deleting all fields througout a document.  With VBA you can accomplish the same objective, but you must cycle through each of the various StoryRanges of the document (e.g., main text story, first page header story, primary header story, etc.).   Given that handicap, either of the following two macros can be used to delete all of the fields throughout a document: 

Sub DeleteAllFields1()
Dim pRange As Word.Range
Dim iLink As Long
iLink = ActiveDocument.Sections(1).Headers(1).Range.StoryType
ActiveWindow.View.ShowFieldCodes = True
For Each pRange In ActiveDocument.StoryRanges
    Do
        With pRange.Find
            .Text = "^d"
            .Replacement.Text = ""
            .Execute Replace:=wdReplaceAll
        End With
        Set pRange = pRange.NextStoryRange
    Loop Until pRange Is Nothing
Next
ActiveWindow.View.ShowFieldCodes = False
End Sub

Sub DeleteAllFields2()
Dim pRange As Word.Range
Dim iLink As Long
iLink = ActiveDocument.Sections(1).Headers(1).Range.StoryType
For Each pRange In ActiveDocument.StoryRanges
    Do
        With pRange.Fields
            While .Count > 0
                .Item(1).Delete
            Wend
        End With
        Set pRange = pRange.NextStoryRange
    Loop Until pRange Is Nothing
Next
End Sub

2.  Let's say that you only want to delete a particular type of field.  Again, VBA can accomplish the same objective as the Edit>Replace dialog, but it must slog its way through every storyrange (it is a pretty fast slog).  For example, let's delete all {Page} fields:

Sub DeleteSpecificFields()
Dim pRange As Word.Range
Dim oFld As Word.Field
Dim iLink As Long
iLink = ActiveDocument.Sections(1).Headers(1).Range.StoryType
For Each pRange In ActiveDocument.StoryRanges
    Do 
        For Each oFld In pRange.Fields
            Select Case oFld.Type
                Case wdFieldPage
                    oFld.Delete
                Case Else
              
     'Do nothing
            End Select
        Next
        Set pRange = pRange.NextStoryRange
    Loop Until pRange Is Nothing   
Next
End Sub

3.   Now let's say that you want to delete a particular type of field in the footers only.  For this situation, the Edit>Replace dialog begins to fall short and you can achieve better results using VBA.  For example, we want to deleted { Author } fields from even page footers only. 

Sub DeleteSpecificFieldsInSpecifStoryRange()
Dim pRange As Word.Range
Dim oFld As Field
Dim iLink As Long
iLink = ActiveDocument.Sections(1).Headers(1).Range.StoryType
For Each pRange In ActiveDocument.StoryRanges
    Do
        Select Case pRange.StoryType
            Case wdEvenPagesFooterStory
                For Each oFld In pRange.Fields
                    Select Case oFld.Type
                        Case wdFieldAuthor
                            oFld.Delete
                        Case Else
                       
    'Do nothing
                    End Select
                Next
            Case Else
         
      'Do Nothing
        End Select
        Set pRange = pRange.NextStoryRange
    Loop Until pRange is Nothing
Next
End Sub

Updating (also Unlinking, Locking, or Unlocking) fields in the field collection. 

1.  With minor modification to the fields provided above, you can update all or any specified fields with a macro.  The macro below can be used to update all fields.
Sub myUpdateFields()
Dim rngStory As Word.Range
Dim oShp As Word.Shape
For Each rngStory In ActiveDocument.StoryRanges
    Do
        On Error Resume Next
        rngStory.Fields.Update
        Select Case rngStory.StoryType
            Case 6, 7, 8, 9, 10, 11
                If rngStory.ShapeRange.Count > 0 Then
                    For Each oShp In rngStory.ShapeRange
                        If oShp.TextFrame.HasText Then
                            oShp.TextFrame.TextRange.Fields.Update
                        End If
                    Next oShp
                End If
            Case Else
                'Do Nothing
        End Select
        On Error GoTo 0
        'Get next linked story (if any)
        Set rngStory = rngStory.NextStoryRange
    Loop Until rngStory Is Nothing
Next rngStory
End Sub

Note:  I have assigned this macro to the F9 function key.  Anytime I want to udate all fields I simply press F9.
2.  The principle command in the above code is "pRange.Fields.Update."  By simply changing this line, you can unlink, lock or unlock all fields.  For example, substituting "pRange.Fields.Update" with the following line will unlink all the fields in a document:

 pRange.Fields.Unlink

3.  To go a little deeper, lets say that we only want to unlink certain DOCPROPERTY fields that  use a uniquen DOCPROPERTY identifier.  For example, we have fields like {DOCPROPERTY Title}, {DOCPROPERTY Author}, etc. dispersed throughout a document and we only want to unlink all of the {DOCPROPERTY Title} field.  To do this we have to look at the field code itself.  Like this:

Sub UnlinkSpecificFields()
Dim pRange As Word.Range
Dim oFld As Word.Field
Dim iLink As Long
iLink = ActiveDocument.Sections(1).Headers(1).Range.StoryType
For Each pRange In ActiveDocument.StoryRanges
    Do
        For Each oFld In pRange.Fields
            Select Case oFld.Type
                Case wdFieldDocProperty
                    If InStr(oFld.Code.Text, "Title") Then
                        oFld.Unlink
                    End If
                Case Else
                  
'Do nothing
            End Select
        Next
        Set pRange = pRange.NextStoryRange
    Loop Until pRange Is Nothing
Next
End Sub

Finally, I wanted to use this page to post what  I consider a crown jewelSparkleof VBA code for inserting nested fields in a document.  For this example the objective is to create a nested conditional field to display the page number on all pages excluding the first page (i.e., { IF { PAGE } = "1"""{ PAGE}})
Public Sub ConstructFieldsWithVBA2()
Dim oRng As Range
Dim oFooterRng1 As Range
Dim oFooterRng2 As Range
Set oRng = ActiveDocument.Sections(1).Footers(wdHeaderFooterPrimary).Range
With oRng
    .Text = "IF PAGE = ""1""""""PAGE"
    Set oFooterRng1 = .Duplicate
    Set oFooterRng2 = .Duplicate
End With
'Insert the field code around the complete expression
fInsertFields2 oFooterRng1, "IF PAGE = ""1""""""PAGE"
'Insert the field code around the Page expressions
fInsertFields2 oFooterRng2, "PAGE"
oRng.Fields.Update
ActiveWindow.View.ShowFieldCodes = False
End Sub

Public Sub fInsertFields2(oRng As Range, Optional sText As String)
With oRng
  
 'Find the expression and add a field around it 
    With .Find
        .Text = sText
        .MatchCase = True
        While .Execute
            oRng.Fields.Add oRng, wdFieldEmpty, , False
            oRng.Collapse wdCollapseEnd
        Wend
    End With
End With
End Sub
These are just a few examples of using macros to work with Word field collection.  I hope you find them useful.
Need help applying macros?  See fellow MVP Graham Mayor's  Guide for Installing Macros 

Looking for something else?

Google