1
votes

I have a macro-enabled Word document (.docm) and am using Word 2007.

One macro applies the 'Intense Reference' style to all cross references.

I'm trying to use Fields.ToggleShowCodes to show the fields before searching for references.

The problem is that this only works when the document is not protected. Is there a way to do this when the document is protected?

I have a workaround; I can use SendKeys("%{F9}") to press ALT+F9. This works, but it's ugly. I'm nitpicking really, but I think there could be a better way.

EDIT:

For some background: this is a template for revision-controlled documents. The protection limits the styles that can be used and locks parts of the document, e.g. the header and footer, which contain document properties and revision history. These properties are entered using forms (many are custom properties). The editable parts of the main text are implemented as exceptions applicable to everyone - this is where the cross references are.

EDIT 2:

Here's the code (minus the CharFormat macro, which isn't relevant):

Sub InitUpdate()
'
' InitUpdate Macro - shows field codes (ALT+F9), waits 1ms (to allow for
'   key presses), then calls the ExecUpdate macro.
'   Used at the start of the Update Refs procedure.
'
SendKeys "%{F9}"

Application.OnTime When:=Now + 0.001, Name:="ExecUpdate"

End Sub

Sub IntenseRef()
'
' IntenseRef Macro - changes all cross references to
'   'intense reference' style (bold and blue text).
'   Used in Update Refs procedure.
'
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles("Intense Reference")

With Selection.Find
    .Text = "^19 REF"
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindContinue
    .Format = True
    .MatchCase = False
    .MatchWholeWord = False
    .MatchKashida = False
    .MatchDiacritics = False
    .MatchAlefHamza = False
    .MatchControl = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
End With

' Replace method causes an error if it runs before the active doc. has been
'   clicked (i.e. when the file is first opened) or header/footer editing mode
'   is enabled.
On Error GoTo ErrHandler
    Selection.Find.Execute Replace:=wdReplaceAll
    Exit Sub

ErrHandler:
    If Err <> 0 Then
        MsgBox ("Select anywhere in the main text first...")
        Err.Clear
    End If

End Sub

Sub ExecUpdate()
'
' ExecUpdate Macro - changes reference styles.
'   Field codes are then hidden (ALT+F9) and the fields are updated.
'   Used in Update Refs procedure (final part).
'
CharFormat
IntenseRef

SendKeys "%{F9}"
ActiveDocument.Fields.Update

End Sub

EDIT 3:

Added a comment to the code explaining the need for the error handler.

1
Why do you need to display the field codes in order to search? It's certainly possible to search / use the field codes without displaying them. Might help if you click EDIT under your qustion and add the relevant bit of code involved...Cindy Meister
@CindyMeister Please see the latest edit for the code. How would one search for cross references without showing the codes?user57709

1 Answers

0
votes

There are a number of possibilities for "targeting" field codes for action. I believe I duplicated your protection settings in my tests...

  1. Closest to the approach you've used up until now:

    ActiveWindow.View.ShowFieldCodes = True 'False to turn them back off

  2. Personally, I don't like changing things on-screen, in front of the user, unless there's no other way to accomplish the task, or unless it makes an appreciable difference in the speed. That means I use the Range object where possible instead of Selection. The Range object has a property that allows you to access field codes even when they aren't displayed: Range.TextRetrievalMode.IncludeFieldCodes. But then you should also use Range instead of Selection for the Find.

To get you started:

Dim rng As word.Range
Set rng = ActiveDocument.content
rng.TextRetrievalMode.IncludeFieldCodes = True
With rng.Find
    'And so on, as you already have

Another difference between Range.Find and Selection.Find is that the settings for the latter affect the dialog box in the UI, while using Range.Find does not change the dialog box.

  1. Instead of using Find, loop the Fields collection in the document, checking the Field.Type and, if it's a REF field, apply the style.

Something along these lines:

Sub LoopRefFields()
  Dim fld As word.Field

  For Each fld In ActiveDocument.Fields
    If fld.Type = wdFieldRef Then
        fld.code.Style = "Intense Reference"
    End If
  Next
End Sub

If the document contains a lot of fields you might want to test which approach is fastest. Personally, I tend to prefer (3) as it's clearer about what's going on and less code.