Word: Fix numbered items
The problem
Word doesn't really know how to handle numbering when it comes to multiple separated lists. e.g.
Some text describing a set of points:
a. item 1.1
b. item 2
More text describing the next set of points:
c. widget 1 <-- this should say a. widget 1
d. widget 2 <-- this should say b. widget 2
They seem to have a mind of their own - they restart their number, or the lists aren't joined properly, or they skip numbers. Sometimes if you copy paste a numbered list in, all the numbers change in other lists as well.
There are quite a macros floating around that fix some problems with numbering. But they don't seem to work in all cases and they are slow because of the way Word handles styles.
Here's a set of macros that I've written, that IMHO works much better, faster, and more consistently.
- RestartLists goes through the document from the current cursor position and restarts all the lists after this point.
- ContinueListsFast quickly resets all the numbering through the whole document so everything is one single huge list. You should do this first before RestartLists.
- ContinueListsSlow is a slower more traditional programmatic way, similar to other macros you'll find on the interwebs. But boy it is slow. Only use this if for some reason the fast method doesn't work.
How to use
- Assign a style ("Sub Para List" is the default) to each and every numbered list you want it to fix. It won't touch any other lists.
- Go to the beginning of the document.
- Run ContinueListsFast
- Run RestartLists
How it works
I've chosen to use a reasonable method of determining when to restart lists: If the previous paragraph isn't a list item, then this paragraph must be a new list!
This logic is what most people use when starting a new list. It's sensible and conventional.
NOTE: If you need to have an unnumbered paragraph nestled within a list, you should consider using line breaks (SHIFT-ENTER) instead of paragraph breaks. Using line breaks will also ensure that indenting is preserved. Don't do strange things like turn off numbering for that paragraph. Technically this text is part of the same numbered item so it should be in the same paragraph.
The code
Sub RestartLists()
' Restarts all lists where the previous paragraph is not the numbering style.
' It starts from the current cursor location.
' You should run ContinueListsFast first to reset all the numbering.
' Edward Chan 2017
Dim listName As String
Dim myPara As Paragraph
Dim boolRestart As Boolean
' Set bookmark for return.
ActiveDocument.Bookmarks.Add Name:="WhereYouWere", Range:=Selection.Range
' ListName for the style of the list.
listName = "Sub Para List"
' Pass one: Change all first occurrences to 1.
Selection.Find.ClearFormatting
Selection.Find.Style = ActiveDocument.Styles(listName)
Selection.Find.Execute
While Selection.Find.Found
DoEvents
Set myPara = Selection.Paragraphs(1)
If myPara.Previous.Style Is Nothing Then myParaName = " " Else myParaName = myPara.Previous.Style ' get around strange string comparison bug when the style is empty
If myParaName <> listName Then
DoEvents
' Need to click the "Restart Numbering" button. It's the only way to reset numbering reliably.
' See https://stackoverflow.com/questions/7010478/word-2007-use-commands-via-macro
' See https://www.thedoctools.com/index.php?show=wt_find_command
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Application.Run MacroName:="RestartNumbering"
Selection.Find.Execute
End If
' Now set the second item to continue to resolve Word bug
If Selection.Range.Listformat.ListValue = 2 And Selection.Range.Listformat.ListLevelNumber = 1 Then
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Application.Run MacroName:="ContinueNumbering"
Selection.Find.Execute
End If
Selection.Find.Execute
Wend
Selection.GoTo What:=wdGoToBookmark, Name:="WhereYouWere"
Selection.GoTo What:=wdGoToBookmark, Name:="WhereYouWere"
ActiveDocument.Bookmarks("WhereYouWere").Delete
End Sub
Sub ContinueListsFast()
' This subroutine selects all instances of a defined style and changes it to "Continue Lists"
' Edward Chan 2017
'
Dim listName As Style
' Set bookmark for return.
ActiveDocument.Bookmarks.Add Name:="WhereYouWere", Range:=Selection.Range
' ListName for the style of the list.
Set listName = ActiveDocument.Styles("Sub Para List")
Selection.Find.ClearFormatting
Selection.Find.Style = listName
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute
' Emulate the "Find All" button
WordBasic.SelectSimilarFormatting
' Need to click the "Continue Numbering" button. It's the only way to continue numbering reliably.
' See https://www.pcreview.co.uk/threads/program-click-on-ribbon-button-using-vba.3919025/
' Office 2010 IDs: https://www.microsoft.com/en-gb/download/details.aspx?id=6627
CommandBars.FindControl(ID:=6125).Execute
Selection.GoTo What:=wdGoToBookmark, Name:="WhereYouWere"
ActiveDocument.Bookmarks("WhereYouWere").Delete
End Sub
Sub ContinueListsSlow()
' Continues all lists of a certain numbering style.
' It starts from the current cursor location.
' It's pretty slow because Word is slow when applying a list template.
' Edward Chan 2017
Dim listName As String
Dim myPara As Paragraph
Dim boolRestart As Boolean
' Set bookmark for return.
ActiveDocument.Bookmarks.Add Name:="WhereYouWere", Range:=Selection.Range
' ListName for the style of the list.
listName = "Sub Para List"
Selection.Find.ClearFormatting
Selection.Find.Style = ActiveDocument.Styles(listName)
Selection.Find.Execute
While Selection.Find.Found
DoEvents
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.Paragraphs(1).ResetAdvanceTo
Selection.Paragraphs(1).SelectNumber
Selection.Range.Listformat.ApplyListTemplateWithLevel ListTemplate:= _
ActiveDocument.Styles(listName).ListTemplate, ContinuePreviousList:=True
Selection.Find.Execute
Selection.Find.Execute
Wend
Selection.GoTo What:=wdGoToBookmark, Name:="WhereYouWere"
ActiveDocument.Bookmarks("WhereYouWere").Delete
End Sub