Written by Allen Wyatt (last updated September 30, 2025)
This tip applies to Word 2007, 2010, 2013, 2016, 2019, 2021, 2024, and Word in Microsoft 365
Eric has a document that has many bookmarks that were either created by Word itself or are remnants of previous bookmarks no longer needed. He wonders if there is a quick way to delete all the unused bookmarks in the document.
The answer depends on what is meant by "unused." In general, there are two ways you could possibly determine if a bookmark is unused or not. If the bookmark is not the target of a cross-reference, then you might consider it unused. If the bookmark is "empty," meaning it doesn't contain text, you might also consider it unused.
Notice that in these two measures, I used the term "might." That was deliberate, because you could have empty bookmarks that have a use—you might use them to jump to locations within your document, for instance. In that case, calling an empty bookmark "unused" would be a misnomer.
The same could be said about bookmarks that aren't targets of cross-references. You might, again, have them defined to mark places to which you want to jump or text that you might way to reference in a macro or text that will be referenced by some other type of field.
When it comes to bookmarks created by Word—generally referred to as "system bookmarks"—things get even murkier. Word routinely creates bookmarks for use by many fields. The names of these system bookmarks begin with an underscore, and bookmarks whose names begin with underscores are considered "hidden" by Word. So, these system bookmarks are normally maintained in the background, out of sight. But, they are there, and they may serve a purpose, even a purpose that may be hard to discern.
Let's say, though, that you decide you do want to delete all the empty bookmarks and all the system bookmarks defined in your document. The easiest way to do this is to use a macro, such as the following:
Sub DeleteUnusedBookmarks1()
Dim bm As Bookmark
Dim J As Integer
Dim C1 As Integer
Dim C2 As Integer
Dim sMsg As String
C1 = ActiveDocument.Bookmarks.Count
For J = ActiveDocument.Bookmarks.Count To 1 Step -1
Set bm = ActiveDocument.Bookmarks(J)
' Delete if bookmark is empty or system-generated
If bm.Range.Start = bm.Range.End Or Left(bm.Name, 1) = "_" Then bm.Delete
Next J
C2 = ActiveDocument.Bookmarks.Count
sMsg = "There were originally " & C1 & " bookmarks, "
sMsg = sMsg & "and " & C1-C2 & " unreferenced bookmarks "
sMsg = sMsg & "have been deleted. "
sMsg = sMsg & "There are " C2 & " bookmarks remaining."
MsgBox sMsg, vbInformation
End Sub
The macro steps through all bookmarks and, if the bookmark is empty (it doesn't refer to a range of text) or its name begins with an underscore, it is deleted. When done, you'll see a message about how many bookmarks were deleted.
If you want to get just a bit more selective and delete only system bookmarks and those that are not referenced anywhere in your document, then the macro needs to be a bit longer:
Sub DeleteUnusedBookmarks2()
Dim bm As Bookmark
Dim C1 As Integer
Dim C2 As Integer
Dim bname As String
Dim found_it As Boolean
Dim sMsg As String
Dim sfc As Boolean
' Remember whether field codes are shown or not
sfc = ActiveWindow.View.ShowFieldCodes
' Show field codes, so that their code string
' is available to Find
ActiveWindow.View.ShowFieldCodes = True
C1 = ActiveDocument.Bookmarks.Count
For Each bm In ActiveDocument.Bookmarks
bname = bm.Name
If Left(bname, 1) = "_" Then
' System-generated bookmark
bm.Delete
Else
' Start search at beginning of document
ActiveDocument.Range(0, 0).Select
With Selection.Find
.Text = bname
.Execute
found_it = .Found
End With
If found_it = False Then bm.Delete
End If
Next bm
C2 = ActiveDocument.Bookmarks.Count
ActiveWindow.View.ShowFieldCodes = sfc
sMsg = "There were originally " & C1 & " bookmarks, "
sMsg = sMsg & "and " & C1-C2 & " unreferenced bookmarks "
sMsg = sMsg & "have been deleted. "
sMsg = sMsg & "There are " & C2 & " bookmarks remaining."
MsgBox sMsg, vbInformation
End Sub
In this case the macro turns on the display of field codes so that Find and Replace can be used to locate text within the codes. This allows the macro to find whether a bookmark name is used in any of the field codes. If it is not used in any field codes, then the bookmark is deleted. The bookmark is also deleted if its name begins with an underscore. Upon completion, a recap of what was deleted is also presented.
Note:
WordTips is your source for cost-effective Microsoft Word training. (Microsoft Word is the most popular word processing software in the world.) This tip (13958) applies to Microsoft Word 2007, 2010, 2013, 2016, 2019, 2021, 2024, and Word in Microsoft 365.
Create Custom Apps with VBA! Discover how to extend the capabilities of Office 365 applications with VBA programming. Written in clear terms and understandable language, the book includes systematic tutorials and contains both intermediate and advanced content for experienced VB developers. Designed to be comprehensive, the book addresses not just one Office application, but the entire Office suite. Check out Mastering VBA for Microsoft Office 365 today!
Bookmarks are commonly used in Word documents as a way to cross-reference information. If the bookmark referenced by the ...
Discover MoreNeed to get rid of a lot of bookmarks all at once? Word doesn't provide a way to do it, but you can use the short macro ...
Discover MoreBookmarks are a great feature you can use to mark the location of text or to mark a position within a document. They can ...
Discover MoreFREE SERVICE: Get tips like this every week in WordTips, a free productivity newsletter. Enter your address and click "Subscribe."
2025-09-29 10:36:07
Andrew
Additional possibilities/probabilities are that a bookmark may be referenced in a story outside of the main story and that an empty bookmark may be used to reference a position in the document (not just the text bookmarked). For example, I very commonly find the need to use an empty bookmark to mark the last page of a multi-section portion of a document so that page numbers in a footer may be of the "Page X of Y" type (in which case the {SectionPages} field doesn't work).
Second, I try not to use Find in macros unless necessary. Greg Maxey's article at https://gregmaxey.com/word_tip_pages/words_fickle_vba_find_property.html is absolutely definitive and *must* be studied in order to use .Find in VBA for anything other than simple searches of "easy" text. So for my version of a macro on solving the bookmark problem I use string search of the bookmark name in the field text. My implementation is sort of naive in that it is case sensitive--so far not a problem in that I almost always create references using the cross-reference command in the ribbon--and I do not check that the fields are only of an appropriate type (Ref, PageRef, etc.), but this seems not to have been a problem in my work.
Sub Delete_Unreferenced_Bookmarks()
' Delete unreferenced bookmarks in ActiveDocument.
Const ProcedureID = "Delete_Unreferenced_Bookmarks()"
Dim b As Bookmark
Dim r As Range
Dim F As Field
Dim InUse As Boolean
Dim Stories As Collection
Set Stories = AllStories() ' Obtain a collection of all of ActriveDocument's stories.
ActiveDocument.Bookmarks.ShowHidden = True
Application.UndoRecord.StartCustomRecord ProcedureID
For Each b In ActiveDocument.Bookmarks
InUse = False
For Each r In Stories
If Not InUse Then
For Each F In r.Fields
If Not InUse Then If InStr(1, r.Text, b.Name) Then InUse = True
Next F
End If
Next r
If Not InUse Then b.Delete
Next b
Application.UndoRecord.EndCustomRecord
End Sub
Function All_Stories() As Collection
' Return a Collection of all Stories in ActiveDocument to permit the caller to
' conveniently deal with the ActiveDocument's stories (abstracting the
' baggage of the ActiveDocument.StoryRanges.NextStoryRange business).
Const ProcedureID = "All_Stories()"
' Fix the skipped blank Header/Footer problem as provided by Peter Hewett (bridging any empty unlinked headers and footers).
Dim Junk As Long: Junk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
Set All_Stories = New Collection
Dim Story As Range
For Each Story In ActiveDocument.StoryRanges
Do
All_Stories.Add Story.Duplicate
Dim Shape As Shape
For Each Shape In Story.ShapeRange
If Shape.TextFrame.HasText Then All_Stories.Add Shape.TextFrame.TextRange.Duplicate
Next Shape
Set Story = Story.NextStoryRange
Loop Until IsNothing(Story)
Next Story
End Function
2025-09-27 06:09:16
Barry
Whoa! Thanks again Allen. Some useful tips, but... This one seems a bit of a darastic idea. Along with the mentioned caveats there is the possibility that an 'idle' looking bookmark may be referenced from another document. Using these macros would presumeably ignore that fact and delete the bookmark?
Got a version of Word that uses the ribbon interface (Word 2007 or later)? This site is for you! If you use an earlier version of Word, visit our WordTips site focusing on the menu interface.
Visit the WordTips channel on YouTube
FREE SERVICE: Get tips like this every week in WordTips, a free productivity newsletter. Enter your address and click "Subscribe."
Copyright © 2025 Sharon Parq Associates, Inc.
Comments