PDA

View Full Version : Autotexts in HeadersFooters



gotmatt
07-14-2011, 03:23 PM
Hi all,

I'm quite new to the VBA game, and I'm slowly figuring out Headers and Footers. I'm working in Word 2003. The goal of my project is to insert a unique (predefined) Auto Text entry into different even/odd footers and headers. I think I'm pretty close, but I keep getting "Run-time error '438': Object doesn't support this property or method. It calls out the line where I try to "set" the myHeaderEven/Odd...

When I move my cursor over "myHeaderEven," it pops up "=nothing" for a value. Could that be the source of my problems?

The counter is so that it begins on section 2. I'm also hoping to stop this macro before it reaches the last section, but I have to figure this out first!

Private Sub Insert_Headers()
'
' Inserts Auto Text (HeaderOdd/HeaderEven) into Even/Odd Headers, sections 2-end of document
'

Dim counter As Integer
counter = 1
Dim myTemplate As Template
Dim mySection As Section
Dim myHeaderOdd As HeaderFooter
Set myHeaderOdd = ActiveDocument.mySection(counter).Headers(wdHeaderFooterPrimary)
Dim myHeaderEven As HeaderFooter
Set myHeaderEven = ActiveDocument.mySection(counter).Headers(wdHeaderFooterEvenPages)
Dim myFooterOdd As HeaderFooter
Set myFooterOdd = ActiveDocument.mySection(counter).Footers(wdHeaderFooterPrimary)
Dim myFooterEven As HeaderFooter
Set myFooterEven = ActiveDocument.mySection(counter).Footers(wdHeaderFooterEvenPages)
Set myTemplate = ActiveDocument.AttachedTemplate


For Each mySection In ActiveDocument.Sections

If counter > 1 Then

For Each myHeaderOdd In mySection.Headers
myTemplate.AutoTextEntries("HeaderOdd").Insert Where:=Selection.Range
Next myHeaderOdd

For Each myHeaderEven In mySection.Headers
myTemplate.AutoTextEntries("HeaderEven").Insert Where:=Selection.Range
Next myHeaderEven

For Each myFooterOdd In mySection.Footers
myTemplate.AutoTextEntries("FooterOdd").Insert Where:=Selection.Range
Next myFooterOdd

For Each myFooterEven In mySection.Footers
myTemplate.AutoTextEntries("FooterEven").Insert Where:=Selection.Range
Next myFooterEven

End If

counter = counter + 1

Next mySection

End Sub
There may be more issues ahead of my "Dim" section, but I haven't been able to discover them yet.

Thanks ahead of time for any expertise or help you can offer! :hi:

Frosty
07-14-2011, 04:00 PM
First, thanks for post the code-- makes it so much easier than having someone try to explain something they don't fully understand.

Couple of comments--
1. It looks like you want to skip the first section, but I'm not sure why. Can you explain? If you want to skip the firstpage header in each section, then simply comment out the wdHeaderFooterFirstPage block in the Select Case statement in the code I've provided below.

2. You're mixing up the concept of For Each...Loops and For...Loops. You don't set your variable if you plan on using a For Each loop.

Dim oSec as Section
Dim hf as HeaderFooter
For Each oSec in ActiveDocument.Sections
For Each hf in oSec.Headers
Next
Next
Will cycle through all the header objects.

Dim i as Integer
Dim y as Integer
Dim hf as HeaderFooter
For i = 1 to ActiveDocument.Sections.Count
For y = 1 to ActiveDocument.Sections(i).Headers.Count
Set hf = ActiveDocument.Sections(i).Headers(y)
Next
Next
Will also cycle through all the header objects (you could also mix and match, but not the way you've done it-- which is to set to the beginning, and then promptly wipe it out by using the For Each on the same object)


Sub IterateThroughSections()
Dim hf As HeaderFooter
'Dim oFooter As HeaderFooter
Dim oSec As Section
Dim rngWhere As Range
Dim oTemplate As Template
Dim oDoc As Document

'you can move this to a parameter, and then dispense with activedocument, if you like
Set oDoc = ActiveDocument
Set oTemplate = oDoc.AttachedTemplate

'now go through the sections
For Each oSec In ActiveDocument.Sections
'cycle through the header objects in this section
For Each hf In oSec.Headers
Set rngWhere = hf.Range
'don't mess with linked headers, and make sure it exists before doing anything
If hf.LinkToPrevious = False And hf.Exists = True Then
Select Case hf.Index
Case wdHeaderFooterPrimary
oTemplate.AutoTextEntries("HeaderOdd").Insert rngWhere
Case wdHeaderFooterFirstPage
oTemplate.AutoTextEntries("HeaderOdd").Insert rngWhere
Case wdHeaderFooterEvenPages
oTemplate.AutoTextEntries("HeaderEven").Insert rngWhere
End Select
End If
Next

'cycle through the footer objects in this section
For Each hf In oSec.Footers
Set rngWhere = hf.Range
'don't mess with linked headers, and make sure it exists before doing anything
If hf.LinkToPrevious = False And hf.Exists = True Then
Select Case hf.Index
Case wdHeaderFooterPrimary
oTemplate.AutoTextEntries("FooterOdd").Insert rngWhere
Case wdHeaderFooterFirstPage
oTemplate.AutoTextEntries("FooterOdd").Insert rngWhere
Case wdHeaderFooterEvenPages
oTemplate.AutoTextEntries("FooterEven").Insert rngWhere
End Select
End If
Next
Next
End Sub

Frosty
07-14-2011, 04:03 PM
Whoops, forgot the main response. The reason you're getting the error is because "mySection" is not a property of the activedocument object, regardless if you declare it as a section variable.

ActiveDocument.Sections is what you need, not ActiveDocument.MySection

You can use your counter variable, but you don't really need to.

gotmatt
07-15-2011, 07:22 AM
Wow! I never expected such an in-depth response, but thank you! I've been pouring over your code example and really like what I see! I'm still a bit unsure about some of it, though.

First off, I don't necessarily want to skip the first page of the document, but the first section. I'm producing my Word document with a program that separates the published job into several sections. I'd like to prevent any autotext from being placed in the first and last section of the document, which are the first and last pages basically. (The first section is only one page long, and the last section is a single page as well.)

I'm working with your code now and it looks like this:
Private Sub AddHeaders()
'
' Inserts Auto Text (HeaderOdd/HeaderEven) into Even/Odd Headers, sections 2-end of document
'

Dim hf As HeaderFooter
Dim oSec As Section
Dim rngWhere As Range
Dim oTemplate As Template
Dim oDoc As Document
Dim oFooter As HeaderFooter

Set oDoc = ActiveDocument
Set oTemplate = oDoc.AttachedTemplate

Dim x As Integer
Dim y As Integer
For x = 1 To oDoc.Sections.Count
For y = 1 To oDoc.Sections(x).Headers.Count
Set hf = oDoc.Sections(x).Headers(y)
Next
Next


For Each oSec In ActiveDocument.Sections
For Each hf In oSec.Headers
Set rngWhere = hf.Range
If hf.LinkToPrevious = False And hf.Exists = True Then
Select Case hf.Index
Case wdHeaderFooterFirstPage
oTemplate.AutoTextEntries("HeaderOdd").Insert rngWhere
Case wdHeaderFooterPrimary
oTemplate.AutoTextEntries("headerOdd").Insert rngWhere
Case wdHeaderFooterEvenPages
oTemplate.AutoTextEntries("HeaderEven").Insert rngWhere
End Select
End If
Next

For Each hf In oSec.Footers
Set rngWhere = hf.Range
If hf.LinkToPrevious = False And hf.Exists = True Then
Select Case hf.Index
Case wdHeaderFooterFirstPage
oTemplate.AutoTextEntries("FooterOdd").Insert rngWhere
Case wdHeaderFooterPrimary
oTemplate.AutoTextEntries("FooterOdd").Insert rngWhere
Case wdHeaderFooterEvenPages
oTemplate.AutoTextEntries("FooterEven").Insert rngWhere
End Select
End If
Next

Next

End Sub

In trying to omit the first and last section I tried this variant of the For...loop
Dim x As Integer
Dim y As Integer
For x = 2 To oDoc.Sections.Count -1
For y = 2 To oDoc.Sections(x).Headers.Count
Set hf = oDoc.Sections(x).Headers(y)
Next
Next
But it seems I still need to research how the syntax and For...loops work in general. When left as you wrote it, it works great! (Although, it seems to skip the First page, odd header of section 3 consistently. I think it has something to do with my section breaks.)

One last thing - all of my Auto Texts have images and fields. Fields are set in frames for placement in the header. When this macro applies the Auto Text, the images look great, but all of the fields loose their formatting. That includes font/style and frames. I looked up fields and heard that headerfooter objects have trouble with them, but I thought I was working around that by using Auto Texts. Those same Auto Texts work fine when applying them by hand.

Thanks again for the time you spent on your response! Your help is GREATLY appreciated!!! :-)

gotmatt
07-15-2011, 08:16 AM
Ah, I discovered that adding ", RichText:=True" at the end of the AutoTextEntries (function?) maintains the placement and format of the text fields in the Autotext!

Now, if I can properly navigate the macro through the sections, I'll be in business! :)

Frosty
07-15-2011, 09:08 AM
Yep-- RichText is the key on that one.

For the other...

You're close... you just need to know that your two For...Loops iterate through two different things:

The sections (thus, For x=2 to .Sections.Count - 1 is going to be perfect for your need to skip the first and last section).
And the header TYPES... (thus y = 1 to .headers.Count is what you want-- since you always want to cycle through the 3 different types).

Make sense?

gotmatt
07-15-2011, 10:34 AM
I'm pretty sure I understand it! Unfortunately it still does not seem to work. With my VBA code, the 13th of 13 sections still has the Header and Footer applied...
Dim x As Integer
Dim y As Integer
For x = 2 To oDoc.Sections.Count - 1
For y = 1 To oDoc.Sections(x).Headers.Count
Set hf = oDoc.Sections(x).Headers(y)
Next
Next

Dim a As Integer
Dim b As Integer
For a = 2 To oDoc.Sections.Count - 1
For b = 1 To oDoc.Sections(a).Footers.Count
Set oFooter = oDoc.Sections(a).Footers(b)
Next
Next
I suspect it's something odd about my document that is throwing it off, so I'll try a different, simpler on to test it on!

It may not be necessary, but I added the For...loop to handle the footers. If it is redundant, it oddly still works!

Even without having 100% success, I'm still so excited! I'm disappointed that I never got into programming before now!


I have another question. And if this calls for a new thread, I'll gladly start one! There is a second Auto Text that I need to apply in each HeaderOdd, but it is chapter(section) sensitive. My page numbers include the chapter number, which is formatted as a letter. So, Chapter 2, page 1 reads as, "B.1"

I was thinking I could find the page number (Selection.Information(wdPageNumber/wdActiveEndPageNumber) and then use a "Left" function to return the "A/B/C..." that signals what chapter I'm in. I'd then use a simple list of If...Then statements to have the VBA apply the proper Auto Text to that header. Unfortunately, when I use "wdPageNumber" I get a unrecognizable number (usually with a decimal). When I use "wdActionEndPageNumber), I get the page number out of total pages, and no mention of the chapter number.

Seems that "chapters" are not really a recognized measurement in Word, and Sections take their place. Unfortunately, I'm never 100% sure, in what section, my first chapter will start. Maybe it would be best to prompt the user for information about what section the first chapter is in, and then use those variables to limit or enable placement of the Auto Text?

Frosty
07-15-2011, 10:41 AM
I'll address your larger question shortly, but the simple answer for why your 13th section is the same as your 12th, despite your For...Loop skipping it, is probably because Same As Previous is on in the 13th section.

gotmatt
07-15-2011, 10:54 AM
Great, Thanks!

And Frosty, I tried to send you a PM, but I don't yet have enough posts apparently. So I'll just say this here:

I know this is nothing new on the internet, but I'm always a bit left in awe to see the effort strangers take to help bring understanding on forums. I know I would not have made much progress if it weren't for your help in this VBA forum.

I frequent a website called "Reddit," and it gave me an idea today. Several of it's members have started a forum called "random acts of pizza," where members send a pizza to someone across the country as a gesture of kindness. If you're into pizza, I'd love to buy ya one sometime as a gesture of appreciation for taking time to answer my questions!

I think all you'd need to do is call your local pizzeria, give em your delivery info and order, and I can make a follow up call to make cover the cost!

If you're interested, just let me know. I'd be happy to set you up anytime!

Frosty
07-15-2011, 11:16 AM
Thanks for the offer and the thanks. Always nice to be appreciated!

By the way, you don't need to do an entirely different loop for the footers. (the whole Dim a as integer stuff) Just re-use your existing variables (and use a With statement to make stuff easier to read):

For x = 2 to oDoc.Sections.Count - 1
With oDoc.Sections(x)
For y = 1 to .Headers.Count
Set hf = .Headers(y)
'do stuff with your hf header object
set hf = .Footers(y)
'then do stuff with your hf (now repurposed) footer object
Next
End With
Next

However, if you're running into problems with the last section not being right, you may need to use something like the following at the top of your code

For Each hf In oDoc.Sections.Last.Headers
hf.LinkToPrevious = False
Next
For Each hf In oDoc.Sections.Last.Footers
hf.LinkToPrevious = False
Next

Frosty
07-15-2011, 11:20 AM
And for your other question...I'd start a new thread. There are several ways to set up chapter headings in Word, and it is probably not necessary to use VBA (certainly not string functions) to do it.

I'd probably lean towards using a StyleRef, but I don't have a lot of experience in the proper set up for good publishing set ups (I've rarely even used the odd/even header footer functionality.

I think at 5 posts you should be able to post a mock up document... that might be a good starting point. A blank document (in the new thread) with some dummy chapter headings, same as previous (or link to previous, depending on version), turned off... and then just manually typed in headers/footers with what you want. And then we can sort out the proper way to set up the document.

You won't be the only person to benefit from this, I'm sure.

- Jason aka Frosty