Resting Anchor

The Anchorage

Personal website of Gregory K. Maxey, Commander USN (Retired)

Convert Fixed Notes to Dynamic Footnotes/Endnotes
(A Microsoft Word Help & Tip page by Gregory K. Maxey)

DISCLAIMER/TERMS OF USE

The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.

Click to acces PayPal Verification Service Click to acces PayPal Verification Service

However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.

If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!

Click to donate British Pound Sterling                   Click to donate US dollars                   Click to donate EU euros

This Microsoft Word Tips & Microsoft Word Help page will show you how you can convert fixed reference notes located at the end of a document into dynamic document footnotes (or endnotes).

When technical articles, journals, or other documents are converted to plain text files for storage in a database file or .PDF format file, any dynamic references (i.e., footnotes/endnotes) are typically converted to fixed text reference identifiers, and the notes are place at the end of the document as fixed text reference notes.

Typically the revised document text will be flagged with numbered markers referencing the note (e.g., [1], [2] , etc.) and the fixed notes will be enumerated using a prefix (e.g., Note 1:,
Note 2:, etc.).

Site Note IconNote:  Lower case Roman numerals (e.g., [i], [ii] and Note i, Note ii) can also be used to identify the reference note ID and enumerator. 

In large documents, with a large number of notes, it can be very time consuming and frustrating to continually shift back and forth between the text and end of the document.

An abbreviated sample of typical text is shown below:

convert endnotes 01
Body text of document.

convert endnotes 02
Note text at end of document.

Using the macro provided below, you can easily convert the fixed notes into dynamic footnotes  that appear at the end of the page of text (or dynamic endnotes at the end of the document).

VBA Script:
Sub ConvertFixedNotesToWordNotes()
'Coded by Paul Edstein and Greg Maxey.
 
'The default note reference ID enumerator in the text is a Arabic format number
'enclosed in square-brackets (i.e., [#])
'The default note enumerator for each note at the end of the document is "Note #:"
'You can redefine either default value at run time.
 
'The fixed notes should be located at the end of the document or, with multi-sectional
'notes, the end of the section; otherwise extraneous text will be incorporated.
'If manual page breaks are contained within the notes range, the affected notes will
'be truncated at that point.
 
'Note numbering may be contiguous, incomplete or restart (e.g., at 1 in each section).
'The output applies sequential numbering, but that's easily addressed manually afterwards.
 
'Notes must be delimited from each other by a paragraph mark or a table's end-marker.
'Notes may contain multiple paragraphs and tables.
 
'When converted, the default footnote/endnote text paragraph style is applied to each
'paragraph in the note (except for table text). Any character style formatting applied
'to original notes is preserved. Direct formatting applied to original single paragraph
'notes is preserved. Formatting in tables is preserved.

Dim strNoteEnum As String, strNote_ID As String, strNoteType As String
Dim bSuperscript As Boolean, bFound As Boolean
Dim lngIndex As Long, lngNoteCount As Long, lngCount As Long, i As Long
Dim oDoc As Word.Document, oRng As Word.Range, oRngNotes As Word.Range
Dim oRngRef As Word.Range, oRngNoteToCut As Word.Range, oRngNote As Word.Range
Dim oPar As Paragraph
Dim StrChars As String, StrChr As String, strLS As String, strSty As String

  Set oDoc = ActiveDocument
  Set oRng = oDoc.Range
  strLS = Application.International(wdListSeparator)
  bFound = False
  
  'Get variable values from user. Exit if there's an input error.
  On Error GoTo lbl_Exit
  strNoteType = InputBox("What type of notes do you want to convert -" _
                & vbCr & "1. Footnotes" & vbCr & "2. Endnotes" _
                & vbCr & vbCr & "Please input 1 or 2 for the note type.", _
                "Note Type Determination", "1")
  If strNoteType < 1 Or strNoteType > 2 Then GoTo lbl_Exit
  
  strNoteEnum = InputBox("Enter the text string that identifies\enumerates " _
                & "each note in the notes text." & vbCr & vbCr _
                & "Be sure to use:" & vbCr & "o ""#"" to represent Arabic numbers " _
                & "(e.g. ""Note #:"")." _
                & vbCr & "o ""x"" to represent Roman numerals (e.g. ""Note x:"").", _
                "Note Enumerator", "Note #:")
  If StrPtr(strNoteEnum) = 0 Then GoTo lbl_Exit
  
  strNote_ID = InputBox("Enter the text string that flags each note reference " _
                & "enumerator ID in the document text.  " & vbCr & vbCr _
                & "Be sure to include any leading spaces and to use:" _
                & vbCr & "o ""#"" to represent Arabic numbers (e.g. ""[#]"")." _
                & vbCr & "o ""x"" to represent Roman numerals (e.g. ""[x]"").", _
                "Note Enumerator Reference", "[#]")
  If StrPtr(strNoteEnum) = 0 Then GoTo lbl_Exit
  
  If MsgBox("Is the reference ID enumerator text superscripted?", _
             vbQuestion + vbYesNo, "Supercript") = vbYes Then
    bSuperscript = True
  Else
    bSuperscript = False
  End If
  'Restore normal error handling.
  On Error GoTo 0
  
  'Parse the input strings for processing. The characters in StrChars need '\' prefixes.
  'Roman numerals need to be fully expressed, in upper & lower case forms.
  StrChars = "[,],{,},(,)"
  For i = 0 To UBound(Split(StrChars, ","))
    StrChr = Split(StrChars, ",")(i)
    strNoteEnum = Replace(strNoteEnum, StrChr, "\" & StrChr)
    strNote_ID = Replace(strNote_ID, StrChr, "\" & StrChr)
  Next
  strNoteEnum = Replace(strNoteEnum, "#", "[0-9]{1" & strLS & "3}")
  strNoteEnum = Replace(strNoteEnum, "x", "[iIvVxXlLcC]{1" & strLS & "11}")
  strNote_ID = Replace(strNote_ID, "#", "[0-9]{1" & strLS & "3}")
  strNote_ID = Replace(strNote_ID, "x", "[iIvVxXlLcCdD]{1" & strLS & "11}")
  
  With oRng
    'Look for fixed note references.
    With .Find
      .ClearFormatting
      .Replacement.ClearFormatting
      .Text = strNote_ID
      .Format = True
      .Font.Superscript = bSuperscript
      .Wrap = wdFindContinue
      .MatchWholeWord = True
      .MatchWildcards = True
      .Execute
    End With
    'Was a note reference found?
    If .Find.Found = False Then
      MsgBox "No fixed Note Reference was found.", _
              vbInformation + vbOKOnly, "No Note References"
      GoTo lbl_Exit
    End If
    
    'Loop through the document and identify all fixed note content.
    oRng.Collapse wdCollapseEnd
    Do
      With .Find
        .ClearFormatting
        .Replacement.ClearFormatting
        .Text = strNoteEnum
        .Format = False
        .Wrap = wdFindStop
        .MatchWildcards = True
        If .Execute Then Beep
      End With
      'Was any text matching the defined fixed note enumerator found?
      Do While .Find.Found = True
        'Is it a "qualified" instance (i.e., starts a new paragraph)?
        If .Duplicate.Start = .Duplicate.Paragraphs.First.Range.Start Then
          bFound = True
          Exit Do
        End If
        .Find.Execute
      Loop
      'Was a "qualified" fixed note enumerator found?
      If bFound = False Then
        MsgBox "No fixed Note Content was found.", vbInformation + vbOKOnly, "No Note Content"
        GoTo lbl_Exit
      End If
      'Reset the working fixed notes range.
      Set oRngNotes = .Duplicate
      With oRngNotes
        'Kill the fixed note enumerator text.
        .Text = vbNullString
        'Attempt to extend the range to the next section break or manual page break.
        .MoveEndUntil Cset:=Chr(12)
        'Was the range endpoint moved?  If not, extend it to the document end.
        If .Start = .End Then .End = oDoc.Range.End
        'Each fixed note must end with a paragraph mark.
        'If the last character is not a paragraph break, insert one.
        If .Characters.Last <> vbCr Then .InsertAfter vbCr
      End With
      'Find and count any remaining notes.
      .Find.Wrap = wdFindStop
      Do While .Find.Found = True
        'Are we still in the notes range?
        If .Duplicate.InRange(oRngNotes) = True Then
          'Is the reference at the start of a paragraph?
          If .Duplicate.Start = .Duplicate.Paragraphs.First.Range.Start Then
            lngNoteCount = lngNoteCount + 1
          End If
        Else
          Exit Do
        End If
        .Collapse wdCollapseEnd
        .Find.Execute
      Loop
      If lngNoteCount = lngIndex Then GoTo lbl_Exit
      'Let Word do its housekeeping.
      DoEvents
      'Replace static fixed note reference IDs with dynamic notes.
      For lngIndex = 1 To lngNoteCount
        'Find the static reference ID.
        With .Find
          .Text = strNote_ID
          .Wrap = wdFindContinue
          .Format = True
          .Font.Superscript = bSuperscript
          .MatchWholeWord = True
          .MatchWildcards = True
          .Execute
        End With
        If .Find.Found Then
          'Define a working Note reference range.
          Set oRngRef = .Duplicate
          'Kill the fixed note reference ID.
          oRngRef.Text = vbNullString
          'Define a working note range to cut.
          Set oRngNoteToCut = oRngNotes.Duplicate
          If lngIndex < lngNoteCount Then
            'Define the indexed fixed note range by looking for the *next*
            'fixed note enumerator.
            With oRngNotes.Duplicate
              With .Find
                .ClearFormatting
                .Text = strNoteEnum
                .Format = False
                .MatchWildcards = True
                .Execute
              End With
              'Was the *next* enumerator text found?
              If .Find.Found Then
                'Fix the range to cut end point.
                oRngNoteToCut.End = .Start
                  'Kill the *next* fixed note enumerator.
                  .Text = vbNullString
              End If
            End With
          End If
          'Place the fixed note text in the clipboard.
          oRngNoteToCut.Cut
          If strNoteType = 1 Then
            'Create an empty dynamic footnote.
            .Footnotes.Add Range:=oRngRef, Text:=""
            i = oDoc.Footnotes.Count
            Set oRngNote = oDoc.Footnotes(i).Range
            strSty = oRngNote.Style
          Else
            'Create an empty dynamic endnote.
            .Endnotes.Add Range:=oRngRef, Text:=""
            i = oDoc.Endnotes.Count
            Set oRngNote = oDoc.Endnotes(i).Range
            strSty = oRngNote.Style
            
          End If
          StatusBar = "Creating Note: " & i
          'Insert the note content.
          With oRngNote
            .Collapse wdCollapseEnd
            .Paste
            .End = .End + 1
            While .Characters.Last.Previous = vbCr
              .Characters.Last.Previous.Text = vbNullString
            Wend
            'Note: If you incorporate multiple paragraphs in your fixed notes, the
            'default footnote paragraph will be reapplied to them (except for tables).
            For lngCount = 1 To .Paragraphs.Count - 1
              If .Paragraphs(lngCount).Range.Information(wdWithInTable) = False Then
                .Paragraphs(lngCount).Style = strSty
              End If
            Next lngCount
          End With
        End If
        'Let Word do its housekeeping.
        DoEvents
      Next lngIndex
      'Reset the index and counter and look for another set of fixed note enumerators.
      lngIndex = 0: lngCount = 0
    Loop Until oRngNotes.End = oDoc.Range.End
  End With
  With oDoc
    While .Characters.Last.Previous = vbCr
      .Characters.Last.Previous.Text = vbNullString
    Wend
  End With
lbl_Exit:
  Set oRng = Nothing: Set oRngNotes = Nothing: Set oRngRef = Nothing
  Set oRngNoteToCut = Nothing: Set oRngNote = Nothing: Set oDoc = Nothing
  StatusBar = "Done!!"
  Application.ScreenUpdating = True
End Sub

Site Note IconNotes:
    1. See: Installing Macros for instructions on how to set up and use the macros provided in this Microsoft Word Help & Microsoft Word Tips page.
    2. This code was developed and provided in cooperation with Paul Edstein (aka macropod).

After running the code, the reference notes are converted to footnotes at the end of each page. or endnotes at the end of the document. You can then use Word’s footnote/endnote options to alter these settings, if you prefer something different.

convert endnotes 03

Of course adding dynamic footnotes to text will result in changes to text flow and pagination of the document.  Sometimes this can introduce undesirable results.  For solutions to this issue, see Word MVP Suzanne Barnhill's: Why do my footnotes sometimes end up on a different page?

You can reverse the process demonstrated above in documents containing dynamic footnotes. To convert dynamic footnotes to fixed reference notes at the end of the document, use the following code:

VBA Script:
Sub FixedNotesFromDynamicFootnotes()
Application.ScreenUpdating = False
Dim lngIndex As Long
Dim oRng As Word.Range
Dim oFN As Footnote
  With ActiveDocument
    Set oRng = .Range
    oRng.Collapse wdCollapseEnd
    oRng.InsertBreak wdPageBreak
    For Each oFN In .Footnotes
      Set oRng = .Range
      lngIndex = lngIndex + 1
      oRng.InsertAfter vbCr & "Footnote " & lngIndex & ": "
      oFN.Range.Copy
      oRng.Collapse wdCollapseEnd
      oRng.Select
      oRng.Paste
      Set oRng = oFN.Reference
      oRng.Text = " FN" & lngIndex
    Next oFN
    While Len(.Paragraphs.Last.Range) = 1
      .Paragraphs.Last.Range.Delete
    Wend
    .Paragraphs.Last.Style = .Paragraphs.Last.Previous.Style
  End With
  Application.ScreenUpdating = True
lbl_Exit:
  Set oRng = Nothing
  Exit Sub
End Sub

That's it! I hope you have found this tips page useful and informative.

Share

DISCLAIMER/TERMS OF USE

The information, illustrations and code contained in my "Microsoft Word Tips" are provided free and without risk or obligation.

Click to acces PayPal Verification Service Click to acces PayPal Verification Service

However, the work is mine. If you use it for commercial purposes or benefit from my efforts through income earned or time saved then a donation, however small, will help to ensure the continued availability of this resource.

If you would like to donate, please use the appropriate donate button to access PayPal. Thank you!

Click to donate British Pound Sterling                   Click to donate US dollars                   Click to donate EU euros

Search my site or the web using Google Search Engine

Google Search Logo