Word clinic

Restarting list numbering using VBA

   

 Syntagma logo Syntagma 

Document structure,
content and form


                                        

Margaret Aldis received a Microsoft MVP award in April 2003 and 2004 This is a copy of a FAQ submitted by Margaret Aldis to the Microsoft Word MVP site.

With acknowledgements to Steve Hudson and John McGhie.

This article provides details of how to restart list numbering by using VBA code to manipulate the list format, and discusses the workarounds needed to cope with the inherent problems of this method (and of the Restart Numbering command method). For other methods of restarting list numbering, see How to restart style-based numbering.

Using this macro code to apply the restart marker is the equivalent of using the Restart Numbering command, which was not available before Word 2002.

Macros to restart numbering

The following macro will restart list numbering on the first item of a selected list:

Public Sub RestartListNumbering(Optional Scope As Range)
'(c) 1999-2004 Word Heretic steve@wordheretic.com
' Everyone has permission to redistribute and use this code at will,
' providing the (c) notice is left intact.
'Restarts list numbering, 97-XP, all list implementations

Dim KillScope As Boolean

If Scope Is Nothing Then
     Set Scope = Selection.Range
     KillScope = True
End If

'Use first listpara

With Scope.ListParagraphs
     If .Count > 0 Then
          With .Item(1).Range.ListFormat
               .ApplyListTemplate .ListTemplate, False
          End With
     End If
End With

'Destroy our objects

If KillScope Then Set Scope = Nothing
End Sub

This method can be used in combination with applying numbering using styles. For example, the following code formats the selected paragraphs as a complete list, including applying the restart to the first item and special spacing for the final item.

Sub ListNumber()
' Macro created by John McGhie
With Selection.Paragraphs
     .Style = "List Number"
     With .First.Range.ListFormat
          .ApplyListTemplate .ListTemplate, False
     End With
     With .Last
          .KeepWithNext = False
          .SpaceAfter = 10
     End With
End With
End Sub

Note that the code steers clear of the ListGalleries collection and works directly with the current ListTemplate, thus avoiding any unwanted changes to styles and list template linking. However, like the built-in RestartNumbering command available from the user interface, it still applies the numbering as direct formatting, and creates a 'restart marker'.

For more background and discussion on this method see the newsgroup thread ListNumbering Street, Revisited. For more information on the Word object model for list formatting, see the Word VBA Help for the List, ListFormat and ListTemplate objects.

   

Problems and workarounds

There are two basic problems with applying a restart using the code above or the Restart Numbering command:

Steve Hudson has produced a number of macros to address these and other problems - in particular his RestartListsAfterHeadings macro solves the problem of lost restarts by recreating them based on the document outline structure. Another strategy would be to mark the restarted paragraphs in some way, so that after they are reset to style or pasted the restarts can be reinstated. The following code illustrates a possible approach to this.

The first macro finds all items numbered 1 for the List Number style and marks them with a temporary bookmark. This code could be run before copying text containing lists to the clipboard, and before any change to the style. If the paste is to be to a different document, similar code would need to be run there (using a distinct bookmark sequence).

Public Sub MarkRestarts()
' Sample code to mark restarted List Number paragraphs
Dim ListItem As Paragraph
Dim n As Integer ' bookmark id
n = 1
For Each ListItem In ActiveDocument.ListParagraphs
   If ListItem.Style = _
        ActiveDocument.Styles(wdStyleListNumber).NameLocal Then
      If ListItem.Range.ListFormat.ListValue = 1 Then
         ActiveDocument.Bookmarks.Add "restart" & n, ListItem.Range
         n = n + 1
      End If
   End If
Next ListItem
End Sub

Even if the source list loses its restart, it will retain the bookmark, which allows the restart to be reapplied as follows:

Public Sub ReapplyRestarts()
' Sample macro to reapply restarts lost by a copy and paste
Dim aBookmark As Bookmark
Dim RestartPoint As Range
For Each aBookmark In ActiveDocument.Bookmarks
   If aBookmark.Name Like "restart*" Then ' it's a restart point
      Set RestartPoint = aBookmark.Range
      RestartPoint.Collapse wdCollapseEnd
      RestartPoint.MoveEnd unit:=wdCharacter, Count:=-1
      With RestartPoint.ListFormat
         .ApplyListTemplate .ListTemplate, ContinuePreviousList:=False
      End With
      aBookmark.Delete
   End If
Next aBookmark
End Sub
     

After a paste into a different document, or an update to the style, you would need first to reset the paragraph formatting, so as to reapply the correct numbering scheme for the current document, and then reapply the restarts which will have been lost on the reset. The final example illustrates this.

Public Sub ReapplyLists()
' Sample macro to correct errors after paste
' to another document and style changes
Dim aPara As Paragraph
Dim aBookmark As Bookmark
Dim StyleName As String
Dim RestartPoint As Range
' reset the paragraph formatting of the style if the paragraph
' should be numbered in this document
For Each aPara In ActiveDocument.Paragraphs
   StyleName = aPara.Style
   If ActiveDocument.Styles(StyleName).ListLevelNumber > 0 Then
      aPara.Reset
   End If
   Next aPara
' reapply restarts to bookmarked paragraphs and tidy up
For Each aBookmark In ActiveDocument.Bookmarks
   If aBookmark.Name Like "restart*" Then ' it's a restart point
      Set RestartPoint = aBookmark.Range
      RestartPoint.Collapse wdCollapseEnd
      RestartPoint.MoveEnd unit:=wdCharacter, Count:=-1
      With RestartPoint.ListFormat
         .ApplyListTemplate .ListTemplate, ContinuePreviousList:=False
      End With
      aBookmark.Delete
   End If
Next aBookmark
End Sub
     

Who we are ~ What we do ~ Portfolio ~ Word clinic

Home ~ Contact us ~ Site search ~ About this site