Search code examples
vbams-wordfooterpage-numbering

How can I insert page numbering field logic into a footer on my Word template using VBA?


I have a word template which uses different footer fields depending on the section. Occasionally, users of this template will mess up the footers, and so I'm writing a macro to fix the footers by putting the default footer fields back in.
The footer fields have some field logic in them based on the section, and basically I need to do the following:

  1. Restart page number from Section 5

  2. Insert text into a table in the footer in row 1, column 2 based on the sections as per below

Sections 1 to 4: { PAGE } //Note that this is in Roman numeral format, with 'Different first page' option set for the footer

Sections 5 onward { if { page } < { = { pageref ReferencesEnd } + 1 } "Page { = { page } } of { = { pageref ReferencesEnd }" "{Styleref "Att-Appendix Heading" \n }"

I've managed to get the first step done and the field inserted for sections 1 to 4, however I'm struggling with How can I programmatically insert the complex field logic for Section 5+ into the relevant footers in my template using VBA? The code I need is commented in the code block below as: 'NEED CODE HERE TO INSERT THE FOLLOWING FIELD LOGIC INTO FOOTER

Sub FixPageNumbering()

    Dim intSect As Integer

   On Error Resume Next

    'Insert footer code for Sections 1-4 into row1,col1 of 2x2 table
    For intSect = 1 To 4

        With ActiveDocument.Sections(intSect).Footers(wdHeaderFooterPrimary)
            .PageNumbers.NumberStyle = wdPageNumberStyleLowercaseRoman
            .Range.Tables(1).Rows(1).Cells(2).Select
            Selection.TypeText Text:="Page "
            Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
            "PAGE ", PreserveFormatting:=True
        End With
    Next intSect

    'Set page numbering to restart at #1 from Section 5
    With ActiveDocument.Sections(5).Footers(wdHeaderFooterPrimary).PageNumbers
     .RestartNumberingAtSection = True
     .StartingNumber = 1
    End With

    'Insert footer code for Sections 5 and onwards into row1,col1 of 2x2 table
    For intSect = 5 To ActiveDocument.Sections.Count
        With ActiveDocument.Sections(intSect).Footers(wdHeaderFooterPrimary)
            .PageNumbers.NumberStyle = wdPageNumberStyleArabic
            .Range.Tables(1).Rows(1).Cells(2).Select

            'NEED CODE HERE TO INSERT THE FOLLOWING FIELD LOGIC INTO FOOTER
            '{ if { page } < { = { pageref ReferencesEnd } + 1 } "Page { = { page } } of { = { pageref ReferencesEnd }" "{Styleref "Att-Appendix Heading" \n }"

          End With

    Next intSect

    ActiveWindow.View.Type = wdPrintView


End Sub

For sections 5 and onward, the footer field should either display Page # of &, or when there is an Appendix (for pages existing after a ReferencesEnd bookmark) it will display "Appendix #"


Solution

  • Although it is possible to create complex field structures via VBA, you'd do better to store the required field codes in two separate paragraphs in a source document from where your macro can copy & paste them into the appropriate locations in the target documents. With that approach you might use code like:

    Sub Demo()
    Application.ScreenUpdating = False
    Dim DocSrc As Document, DocTgt As Document
    Dim i As Long, Rng As Range, HdFt As HeaderFooter
    Set DocSrc = ThisDocument
    With Application.FileDialog(FileDialogType:=msoFileDialogFilePicker)
      .Title = "Select the target file"
      .AllowMultiSelect = False
      If .Show = -1 Then
        Set DocTgt = Documents.Open(.SelectedItems(1))
      Else
        MsgBox "No target file selected. Exiting", vbExclamation
        GoTo ErrExit
      End If
    End With
    With DocTgt
      For i = 1 To .Sections.Count
        Select Case i
          Case 1 To 4: Set Rng = DocSrc.Paragraphs(1).Range
          Case Else: Set Rng = DocSrc.Paragraphs(2).Range
        End Select
        With .Sections(i)
          For Each HdFt In .Footers
            With HdFt
              If .Exists Then
                If .LinkToPrevious = False Then
                  .Range.FormattedText = Rng.FormattedText
                  .Range.Characters.Last.Delete
                End If
              End If
            End With
          Next
        End With
      Next
    End With
    ErrExit:
    Set Rng = Nothing: Set DocSrc = Nothing: Set DocTgt = Nothing
    Application.ScreenUpdating = True
    End Sub
    

    If necessary, though it seems unlikely, you can supplement the above with code to apply the desired numbering format - or you can add the appropriate switches to the field codes themselves.

    PS: Your second field code could be reduced to-

    {IF{PAGE}< {={PAGEREF ReferencesEnd}+1} "Page {PAGE} of {PAGEREF ReferencesEnd}" {STYLEREF "Att-Appendix Heading" \n}}