G
Greg
Chuck,
I am leaving the rights issue to you or G.G. I know that either of you
would be fair.
I am posting back "my" version of our code for evaluation. My version
has two
SearchAndReplaceInStory routines an A and B. The A version is closer to
what we had prevsiously while the B is closer to yours.
For your thoughts.
Word will not index in text boxes, comments or headers and footers.
That is the purpose of the error handler in my version. In your
version I added a IF statement to bypass INDEX field insertion IF the
storyType was 4 or above (in Word2000 that is comments, text boxes and
all headers and footers) 1-3 is maintext footnotes endnotes.
I also don't see the need for "DefinedTermsIndex". I added code to
show field codes for both TOC and INDEX prior to indexing. That way
when the document is reindexed the actual terms are hidden.
I still have one nagging problem that I haven't been able to resolve.
If a word or term is bookmarked and then a REF field is used to that
bookmark the Indexing field overwrites the bookmark and then a Error is
generated in the REF field. The work around now is to ensure the
bookmark is extended to include the space after the term. Then things
work. I need to work that out. Any ideas:
Here is the code. You can switch back and forth between A and B to see
which will work best:
Option Explicit
Public Sub WordMarkerWithIndexer()
'Developed by Greg Maxey, G. G. Yagoda and Chuck Henrich
Dim rngStory As Word.Range
Dim ListArray
Dim myRange As Range
Dim enableSmartQuotes As Boolean
Dim oFld As Field
'Stores users AutoCorrect "smart quote" options. True if enabled
enableSmartQuotes = Options.AutoFormatAsYouTypeReplaceQuotes
StripPreviousIndexing
'Hide XE Field text while processing
ActiveWindow.View.ShowHiddenText = False
'Convert curly quotes if used
Options.AutoFormatAsYouTypeReplaceQuotes = False
For Each rngStory In ActiveDocument.StoryRanges
Do
If rngStory.StoryLength >= 2 Then
SmartQuoteToggle rngStory
End If
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
'Build Defined Terms list and create array
Set myRange = ActiveDocument.Range
Do
With myRange.Find
'Find Defined Terms (i.e., terms quoted an in bold text)
.Text = """*"""
.MatchWildcards = True
.Execute
' Strip quotation marks
myRange.Start = myRange.Start + 1
myRange.End = myRange.End - 1
If myRange.Font.Bold Then
'Elimate zero length strings and erroneous white space
Select Case myRange.Text
Case Is <> ""
myRange.Text = Trim(myRange.Text)
'Add to list
ListArray = ListArray & myRange.Text & "|"
End Select
End If
'Step range past last found quotation mark
myRange.End = myRange.End + 1
myRange.Collapse wdCollapseEnd
End With
Loop While myRange.Find.Found
'Clip trailing separator character
ListArray = Left(ListArray, Len(ListArray) - 1)
'Define the array
ListArray = Split(ListArray, "|")
'Call sort function to sort array longest term to shortest term
ListArray = ListSort(ListArray)
MsgBox ("Document contains " & UBound(ListArray) + 1 & " Defined
Terms")
'Validate blank headers and footers (ensure code sequences to next HF
storyrange
MakeHFValid
'Restore curly qoutes per user option
If enableSmartQuotes Then
RestoreSmartQuotes
End If
'Main routine
Application.ScreenUpdating = False
For Each rngStory In ActiveDocument.StoryRanges
Do
If rngStory.StoryLength >= 2 Then
'SearchAndReplaceInStoryA rngStory, ListArray 'My Version
SearchAndReplaceInStoryB rngStory, ListArray 'Chuck's Version
End If
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
'Clear bold in TOC entries
For Each oFld In ActiveDocument.Fields
If oFld.Type = wdFieldTOC Then
oFld.Result.Font.Bold = False
Exit For
End If
Next
RestoreTextColor
Application.ScreenUpdating = True
ActiveWindow.View.ShowHiddenText = True
Selection.HomeKey unit:=wdStory
MsgBox "Defined terms have been indexed.", vbOKOnly, "Done"
End Sub
Public Sub MakeHFValid()
Dim lngJunk As Long
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
End Sub
Sub SmartQuoteToggle(ByVal rngStory As Word.Range)
With rngStory.Find
.Text = Chr$(34)
.Replacement.Text = Chr$(34)
.Forward = True
.Wrap = wdFindContinue
.Format = False
.Execute Replace:=wdReplaceAll
End With
End Sub
Function ListSort(ListArray) As Variant
'Modified from code found in Google Groups
Dim i As Integer
Dim j As Integer
Dim first As Integer
Dim last As Integer
Dim temp As Variant
Dim sortedList As Variant
Dim myString As String
first = LBound(ListArray)
last = UBound(ListArray)
ReDim sortedList(last)
For i = first To last
For j = i + 1 To last
If Len(ListArray(i)) < Len(ListArray(j)) Then
temp = ListArray(j)
ListArray(j) = ListArray(i)
ListArray(i) = temp
End If
Next j
Next i
For i = first To last
sortedList(i) = ListArray(i)
Next i
ListSort = sortedList
'See the result
myString = Join(ListSort, "|")
End Function
Sub RestoreTextColor()
Dim rngStory As Word.Range
MakeHFValid
For Each rngStory In ActiveDocument.StoryRanges
Do Until (rngStory Is Nothing)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Font.Color = wdColorBlueGray
.Replacement.Font.Color = wdColorAutomatic
.Execute Replace:=wdReplaceAll
End With
Set rngStory = rngStory.NextStoryRange
Loop
Next
End Sub
Sub StripPreviousIndexing()
Dim oFld As Field
Dim rngStory As Range
MakeHFValid
For Each rngStory In ActiveDocument.StoryRanges
Do Until (rngStory Is Nothing)
For Each oFld In rngStory.Fields
If oFld.Type = 4 Then
'If oFld.Type = wdFieldIndex Or oFld.Type = wdFieldIndexEntry
Then 'Index entry
oFld.Delete
End If
Next oFld
Set rngStory = rngStory.NextStoryRange
Loop
Next
End Sub
Sub RestoreSmartQuotes()
'Restores smart quotes then replaces smart quotes appearing in fields
with
'straight quotes
Dim rngStory As Word.Range
Dim oFld As Field
For Each rngStory In ActiveDocument.StoryRanges
Do
If rngStory.StoryLength >= 2 Then
Options.AutoFormatAsYouTypeReplaceQuotes = True
'Call SmartQuoteToggle macro
SmartQuoteToggle rngStory
'Restore straight quotes in fields
Options.AutoFormatAsYouTypeReplaceQuotes = False
For Each oFld In ActiveDocument.Fields
oFld.Select
'Need selection find for fields
'range find not available
With Selection.Find
.Text = """"
.Replacement.Text = """"
.Forward = True
.Wrap = wdFindStop
.Format = False
.Execute Replace:=wdReplaceAll
End With
If oFld.Type = wdFieldTOC Then
oFld.Result.Font.Bold = False
Exit For
End If
Next oFld
Options.AutoFormatAsYouTypeReplaceQuotes = True
End If
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next rngStory
End Sub
Public Sub SearchAndReplaceInStoryA(ByVal rngStory As Word.Range, _
ByRef ListArray As Variant)
Dim i As Long
Dim oFldIndexEntry As Field
Dim oFld As Field
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = True
End If
Next oFld
For i = LBound(ListArray) To UBound(ListArray)
Selection.HomeKey unit:=wdStory
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop
.Text = ListArray(i)
While .Execute
With rngStory
.Text = .Text
.Font.Bold = True
.Font.Color = wdColorBlueGray
.Collapse Direction:=wdCollapseEnd
End With
If rngStory.Font.Color <> wdColorBlueGray Then
On Error Resume Next
ActiveDocument.Indexes.MarkEntry Range:=rngStory,
Entry:=Trim(ListArray(i))
On Error GoTo 0
End If
Wend
End With
rngStory.Expand unit:=wdStory
Next i
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = False
End If
Next oFld
End Sub
Public Sub SearchAndReplaceInStoryB( _
ByVal rngStory As Word.Range, _
ByRef ListArray As Variant)
Dim i As Long
Dim oFldIndexEntry As Field
Dim oFld As Field
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = True
End If
Next oFld
For i = LBound(ListArray) To UBound(ListArray)
Selection.HomeKey unit:=wdStory
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop
.Text = ListArray(i)
While .Execute
With rngStory
.Text = .Text
.Font.Bold = True
.Font.Color = wdColorBlueGray
.Collapse Direction:=wdCollapseEnd
End With
If rngStory.Font.Color <> wdColorBlueGray Then
If rngStory.StoryType < 4 Then
Set oFldIndexEntry =
ActiveDocument.Indexes.MarkEntry(Range:=rngStory, _
Entry:=Trim(ListArray(i)))
oFldIndexEntry.Code.Text = oFldIndexEntry.Code.Text & "\f
""DefinedTermsIndex"" "
rngStory.MoveEnd unit:=wdCharacter,
Count:=oFldIndexEntry.Code.Characters.Count + 2
End If
End If
Wend
End With
rngStory.Expand unit:=wdStory
Next i
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = False
End If
Next oFld
End Sub
I am leaving the rights issue to you or G.G. I know that either of you
would be fair.
I am posting back "my" version of our code for evaluation. My version
has two
SearchAndReplaceInStory routines an A and B. The A version is closer to
what we had prevsiously while the B is closer to yours.
For your thoughts.
Word will not index in text boxes, comments or headers and footers.
That is the purpose of the error handler in my version. In your
version I added a IF statement to bypass INDEX field insertion IF the
storyType was 4 or above (in Word2000 that is comments, text boxes and
all headers and footers) 1-3 is maintext footnotes endnotes.
I also don't see the need for "DefinedTermsIndex". I added code to
show field codes for both TOC and INDEX prior to indexing. That way
when the document is reindexed the actual terms are hidden.
I still have one nagging problem that I haven't been able to resolve.
If a word or term is bookmarked and then a REF field is used to that
bookmark the Indexing field overwrites the bookmark and then a Error is
generated in the REF field. The work around now is to ensure the
bookmark is extended to include the space after the term. Then things
work. I need to work that out. Any ideas:
Here is the code. You can switch back and forth between A and B to see
which will work best:
Option Explicit
Public Sub WordMarkerWithIndexer()
'Developed by Greg Maxey, G. G. Yagoda and Chuck Henrich
Dim rngStory As Word.Range
Dim ListArray
Dim myRange As Range
Dim enableSmartQuotes As Boolean
Dim oFld As Field
'Stores users AutoCorrect "smart quote" options. True if enabled
enableSmartQuotes = Options.AutoFormatAsYouTypeReplaceQuotes
StripPreviousIndexing
'Hide XE Field text while processing
ActiveWindow.View.ShowHiddenText = False
'Convert curly quotes if used
Options.AutoFormatAsYouTypeReplaceQuotes = False
For Each rngStory In ActiveDocument.StoryRanges
Do
If rngStory.StoryLength >= 2 Then
SmartQuoteToggle rngStory
End If
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
'Build Defined Terms list and create array
Set myRange = ActiveDocument.Range
Do
With myRange.Find
'Find Defined Terms (i.e., terms quoted an in bold text)
.Text = """*"""
.MatchWildcards = True
.Execute
' Strip quotation marks
myRange.Start = myRange.Start + 1
myRange.End = myRange.End - 1
If myRange.Font.Bold Then
'Elimate zero length strings and erroneous white space
Select Case myRange.Text
Case Is <> ""
myRange.Text = Trim(myRange.Text)
'Add to list
ListArray = ListArray & myRange.Text & "|"
End Select
End If
'Step range past last found quotation mark
myRange.End = myRange.End + 1
myRange.Collapse wdCollapseEnd
End With
Loop While myRange.Find.Found
'Clip trailing separator character
ListArray = Left(ListArray, Len(ListArray) - 1)
'Define the array
ListArray = Split(ListArray, "|")
'Call sort function to sort array longest term to shortest term
ListArray = ListSort(ListArray)
MsgBox ("Document contains " & UBound(ListArray) + 1 & " Defined
Terms")
'Validate blank headers and footers (ensure code sequences to next HF
storyrange
MakeHFValid
'Restore curly qoutes per user option
If enableSmartQuotes Then
RestoreSmartQuotes
End If
'Main routine
Application.ScreenUpdating = False
For Each rngStory In ActiveDocument.StoryRanges
Do
If rngStory.StoryLength >= 2 Then
'SearchAndReplaceInStoryA rngStory, ListArray 'My Version
SearchAndReplaceInStoryB rngStory, ListArray 'Chuck's Version
End If
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
'Clear bold in TOC entries
For Each oFld In ActiveDocument.Fields
If oFld.Type = wdFieldTOC Then
oFld.Result.Font.Bold = False
Exit For
End If
Next
RestoreTextColor
Application.ScreenUpdating = True
ActiveWindow.View.ShowHiddenText = True
Selection.HomeKey unit:=wdStory
MsgBox "Defined terms have been indexed.", vbOKOnly, "Done"
End Sub
Public Sub MakeHFValid()
Dim lngJunk As Long
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
End Sub
Sub SmartQuoteToggle(ByVal rngStory As Word.Range)
With rngStory.Find
.Text = Chr$(34)
.Replacement.Text = Chr$(34)
.Forward = True
.Wrap = wdFindContinue
.Format = False
.Execute Replace:=wdReplaceAll
End With
End Sub
Function ListSort(ListArray) As Variant
'Modified from code found in Google Groups
Dim i As Integer
Dim j As Integer
Dim first As Integer
Dim last As Integer
Dim temp As Variant
Dim sortedList As Variant
Dim myString As String
first = LBound(ListArray)
last = UBound(ListArray)
ReDim sortedList(last)
For i = first To last
For j = i + 1 To last
If Len(ListArray(i)) < Len(ListArray(j)) Then
temp = ListArray(j)
ListArray(j) = ListArray(i)
ListArray(i) = temp
End If
Next j
Next i
For i = first To last
sortedList(i) = ListArray(i)
Next i
ListSort = sortedList
'See the result
myString = Join(ListSort, "|")
End Function
Sub RestoreTextColor()
Dim rngStory As Word.Range
MakeHFValid
For Each rngStory In ActiveDocument.StoryRanges
Do Until (rngStory Is Nothing)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Font.Color = wdColorBlueGray
.Replacement.Font.Color = wdColorAutomatic
.Execute Replace:=wdReplaceAll
End With
Set rngStory = rngStory.NextStoryRange
Loop
Next
End Sub
Sub StripPreviousIndexing()
Dim oFld As Field
Dim rngStory As Range
MakeHFValid
For Each rngStory In ActiveDocument.StoryRanges
Do Until (rngStory Is Nothing)
For Each oFld In rngStory.Fields
If oFld.Type = 4 Then
'If oFld.Type = wdFieldIndex Or oFld.Type = wdFieldIndexEntry
Then 'Index entry
oFld.Delete
End If
Next oFld
Set rngStory = rngStory.NextStoryRange
Loop
Next
End Sub
Sub RestoreSmartQuotes()
'Restores smart quotes then replaces smart quotes appearing in fields
with
'straight quotes
Dim rngStory As Word.Range
Dim oFld As Field
For Each rngStory In ActiveDocument.StoryRanges
Do
If rngStory.StoryLength >= 2 Then
Options.AutoFormatAsYouTypeReplaceQuotes = True
'Call SmartQuoteToggle macro
SmartQuoteToggle rngStory
'Restore straight quotes in fields
Options.AutoFormatAsYouTypeReplaceQuotes = False
For Each oFld In ActiveDocument.Fields
oFld.Select
'Need selection find for fields
'range find not available
With Selection.Find
.Text = """"
.Replacement.Text = """"
.Forward = True
.Wrap = wdFindStop
.Format = False
.Execute Replace:=wdReplaceAll
End With
If oFld.Type = wdFieldTOC Then
oFld.Result.Font.Bold = False
Exit For
End If
Next oFld
Options.AutoFormatAsYouTypeReplaceQuotes = True
End If
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next rngStory
End Sub
Public Sub SearchAndReplaceInStoryA(ByVal rngStory As Word.Range, _
ByRef ListArray As Variant)
Dim i As Long
Dim oFldIndexEntry As Field
Dim oFld As Field
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = True
End If
Next oFld
For i = LBound(ListArray) To UBound(ListArray)
Selection.HomeKey unit:=wdStory
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop
.Text = ListArray(i)
While .Execute
With rngStory
.Text = .Text
.Font.Bold = True
.Font.Color = wdColorBlueGray
.Collapse Direction:=wdCollapseEnd
End With
If rngStory.Font.Color <> wdColorBlueGray Then
On Error Resume Next
ActiveDocument.Indexes.MarkEntry Range:=rngStory,
Entry:=Trim(ListArray(i))
On Error GoTo 0
End If
Wend
End With
rngStory.Expand unit:=wdStory
Next i
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = False
End If
Next oFld
End Sub
Public Sub SearchAndReplaceInStoryB( _
ByVal rngStory As Word.Range, _
ByRef ListArray As Variant)
Dim i As Long
Dim oFldIndexEntry As Field
Dim oFld As Field
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = True
End If
Next oFld
For i = LBound(ListArray) To UBound(ListArray)
Selection.HomeKey unit:=wdStory
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop
.Text = ListArray(i)
While .Execute
With rngStory
.Text = .Text
.Font.Bold = True
.Font.Color = wdColorBlueGray
.Collapse Direction:=wdCollapseEnd
End With
If rngStory.Font.Color <> wdColorBlueGray Then
If rngStory.StoryType < 4 Then
Set oFldIndexEntry =
ActiveDocument.Indexes.MarkEntry(Range:=rngStory, _
Entry:=Trim(ListArray(i)))
oFldIndexEntry.Code.Text = oFldIndexEntry.Code.Text & "\f
""DefinedTermsIndex"" "
rngStory.MoveEnd unit:=wdCharacter,
Count:=oFldIndexEntry.Code.Characters.Count + 2
End If
End If
Wend
End With
rngStory.Expand unit:=wdStory
Next i
'Show field codes for TOC to prevent looping
For Each oFld In ActiveDocument.Fields
If oFld.Type = 13 Or oFld.Type = 8 Then '13 TOC fields/8 Index fields
oFld.ShowCodes = False
End If
Next oFld
End Sub