PDA

View Full Version : Updating all field codes in doc with >1 section break



bstephens
07-19-2010, 07:51 PM
Hi, I am having a difficult time trying to write a macro that efficiently updates all the fields in a document (both in the body of the document and in the header and footer) in a document which has multiple section breaks.

I don't want to use the print-preview trick because I don't want my users losing their current editing position on the document.

I tried various code on the internet, and it worked except that it only worked as to the first section break.

I came up with the following code that seems to update all the field codes in the header and footer in multiple section breaks, but it doesn't seem to work in the body of the document.

Does anyone know how to edit this code so that, in addition to updating the field codes in the header and footer in each section break of a document, it will also do any field codes in the body?

'Updates All Fields in a Document
Sub UpdateAllFields()

Dim section As section
Dim myRange As Range
Dim myHF As HeaderFooter

'Loop through the header/footer for each section to update the header/footer of sections after section 1.
For Each section In ActiveDocument.Sections

For Each myHF In section.Headers
Set myRange = myHF.Range

For Each aField In myRange.Fields
aField.Update
Next aField

Next myHF

For Each myHF In section.Footers
Set myRange = myHF.Range

For Each aField In myRange.Fields
aField.Update
Next aField

Next myHF

Next section
End Sub
Also, is this code efficient? I noted that where there is a table of contents it seems like the saves are really slowed down.

Appreciate any input on achieving updates in the body, or if there is a way to make this code more efficient.

Best,

-Brian

Tinbendr
07-19-2010, 08:09 PM
Try using StoryRanges
Sub LoopStoryRanges()
'http://word.mvps.org/faqs/customization/ReplaceAnywhere.htm
Dim rngStory As Range
Dim lngJunk As Long
'Fix the skipped blank Header/Footer problem as provided by Peter Hewett
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
'Iterate through all story types in the current document
For Each rngStory In ActiveDocument.StoryRanges
'Iterate through all linked stories
Do
With rngStory
.Fields.Update
End With
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
End Sub

bstephens
07-19-2010, 08:26 PM
Tinbendr, I tried that code, and it worked for a filename field code in the header/footer in a document with two sections (updated in Section 1 and in Section 2), but I couldn't get it to update a filename field code in the body (field code did NOT update in Section 1 or Section 2 of the body).

What could I be missing here? Anyone else able to verify that Tinbendr's code works as described in my original post?

Tinbendr
07-20-2010, 05:13 AM
This article (http://www.vbaexpress.com/kb/getarticle.php?kb_id=459) is in the KB entries. Other messages refering to this article seem to indicate that it worked.

bstephens
07-20-2010, 10:28 AM
Thanks for the input tinbendr, I tried the following code, and it updates the header/footer in section 1 (but not any subsequent sections), it also updates the body in section 1 and any subsequent sections.

Anyone know how to rewrite it so it updates the header/footer in section 1 and any subsequent sections and also the body in section 1 and any subsequent sections?

Here is the code as referenced by tinbendr:

Option Explicit

'This one updates all the fields in the document:
Sub UpdateALL()
Dim oStory As Object
Dim oToc As Object

'exit if no document is open
If Documents.Count = 0 Then Exit Sub
Application.ScreenUpdating = False

For Each oStory In ActiveDocument.StoryRanges
oStory.Fields.Update 'update fields in all stories
Next oStory

For Each oToc In ActiveDocument.TablesOfContents
oToc.Update 'update TOC's
Next oToc

Application.ScreenUpdating = True
End Sub

bstephens
07-20-2010, 10:31 AM
OK, so I came up with the following two macros that, when combined, accomplish what I was after:

'Updates All Fields in multiple sections of a Document
Sub UpdateAllFields()
UpdateBodyFields
Dim section As section
Dim myRange As Range
Dim myHF As HeaderFooter

'exit if no document is open
If Documents.Count = 0 Then Exit Sub
Application.ScreenUpdating = False
'Loop through the header/footer for each section to update the header/footer of sections after section 1.
For Each section In ActiveDocument.Sections

For Each myHF In section.Headers
Set myRange = myHF.Range

For Each aField In myRange.Fields
aField.Update
Next aField

Next myHF

For Each myHF In section.Footers
Set myRange = myHF.Range

For Each aField In myRange.Fields
aField.Update
Next aField

Next myHF
Next section

End Sub

'Updates Fields in the body of the document
Sub UpdateBodyFields()
Dim oStory As Object
Dim oToc As Object

'exit if no document is open
If Documents.Count = 0 Then Exit Sub
Application.ScreenUpdating = False

For Each oStory In ActiveDocument.StoryRanges
oStory.Fields.Update 'update fields in all stories
Next oStory

For Each oToc In ActiveDocument.TablesOfContents
oToc.Update 'update TOC's
Next oToc

Application.ScreenUpdating = True
End Sub
I have linked the two above procedures to the "AutoOpen" procedure as follows:

Sub AutoOpen()
UpdateAllFields
End Sub
and to re-purposed "Save" and "SaveAs" commands as follows:

'REPURPOSED SAVE COMMAND - Automatically updates the field upon a file SAVE event
Sub FileSave()
ActiveDocument.Save
UpdateAllFields
End Sub

'Callback for FileSave onAction
Sub rxFileSave_repurpose(control As IRibbonControl, ByRef cancelDefault)
Call FileSave
End Sub

'REPURPOSED SAVEAS COMMAND - Automatically updates the field upon a file SAVEAS event
Sub FileSaveAs()
Application.Dialogs(wdDialogFileSaveAs).Show
UpdateAllFields
End Sub

'Callback for FileSaveAs onAction
Sub rxFileSaveAs_repurpose(control As IRibbonControl, ByRef cancelDefault)
Call FileSaveAs
End Sub
This seems to accomplish my objective of always having fields (in multiple sections, and in header/footer and body) automatically updated for users in the event they (1) save the file with a new name in word, or (2) open a file after renaming it in windows explorer.

I wish I could find a more efficient way, but my skills are pretty basic. Would appreciate any input on making this more efficient.

Best,
Brian

fumei
07-21-2010, 10:49 AM
I am a bit confused with the reported difficulties. The basic field updating should not be affected by Sections at all. In fact, I can not duplicate this. In any case, some suggestions:

For Each myHF In section.Headers
Set myRange = myHF.Range

For Each aField In myRange.Fields
aField.Update
Next aField

Next myHF
can be written as:
For Each myHF In ActiveDocument.Sections.Headers
For Each aField In myHF.Range.Fields
aField.Update
Next aField
Next myHF
There is no need to set a range object.

I would be careful about using syntax like:

Dim section As section

It is never a good idea to name a variable the same as a reserved word.