Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Need to loop through all types of footers in multi-section document

Status
Not open for further replies.

Jtorres13

Technical User
Nov 11, 2006
162
US
Hello. Oh, I have a problem. I need to loop through all types of footers in a multi-section, multi footer document. This document has several sections and each section has all the footer types: FirstPage, EvenPage and Primary.

My code below can show you how i'm not the smartest knife in the drawer so any help will be welcome.

I have a For/Next to loop through the sections and inside I have a DO/While that loops through the types of footer.

So, I go to the first section and open the primary fotoer to see if it's empty. I fnot empty, I have to go through each type of footer to search for a document number. This is the problem. The statement:

ActiveDocument.Sections(i).Footer(swfootercount).Range.Select

always wants to go to section one no matter what values the "For" variable "i" has. Any ideas?



Code:
For i = 1 To ActiveDocument.Sections.Count
    Selection.GoTo wdgotoselection, wdGoToAbsolute, i
    ActiveDocument.Sections(i).Footers_
    (wdHeaderFooterPrimary).Range.Select
    Selection.HomeKey unit:=wdLine
    
    'if the footer is empty, then I can't move the cursor
    swfooterempty = Selection.MoveRight(wdCharacter, 1)
    
    'I'm done evaluating the footer so I'll close it so it
    'won't interfere with edits.
     ActiveWindow.View.Type = wdPageView
     WordBasic.closeviewheaderfooter
     ActiveWindow.View.Type = wdPageView

    
    'If the footer is populated we want to loop 
    'through all 3 types of footers:
    '(Primary, FirstPage, and EvenPage) and search for the
    'document number in it
    If swfooterempty = 1 Then
            'Search for document number
            'I'll do this until 4 because there are 3 types
            'of footer I want to check
            Do Until swfootercount = 4
            'The following is the statement that doesn't work
            ActiveDocument.Sections(i).Footers_
                (swfootercount).Range.Select
                'Do other stuff, etc.
            swfootercount=swfootercount+1
            Loop
     end if
Next i
 
There are a couple of problems with this. You using Selection, View, and a counter.

'if the footer is empty, then I can't move the cursor
Moving the cursor is a Selection action. if you do not use Selection, this is never an issue.

Far better to use objects and ranges, and a For Each.
Code:
Dim oSection As Section
Dim oHF As HeaderFooter
' loop through every Section
For Each oSection In ActiveDocument.Sections
   ' loop through all footers
   For Each oHF In oSection.Footers
      ' do your stuff
Yes indeed there are three types of footers. So you can use either a For Each statement like above, or a incrementing variable, like this:
Code:
Sub EachSec()
Dim oSection As Section
Dim oHF As HeaderFooter
Dim var
Dim j As Long
Dim myText()
myText = Array(" Primary", " First Page", " Even Page")
For Each oSection In ActiveDocument.Sections
   j = oSection.Index
   For var = 1 To 3
      Set oHF = oSection.Footers(var)
      With oHF
         .LinkToPrevious = False
         .Range.Text = "Section " & j & myText(var - 1)
      End With
   Next
Next
End Sub
This would go through all the sections in the document and put the following into the footers.

Assumption: the section has DifferentFirstPage and DifferentOddEven turned on.

"Section 1 First Page" (pg #1)
"Section 1 Even Page" (pg #2)
"Section 1 Odd Page" (pg #3)
"Section 2 First Page" (pg #4)
"Section 2 Odd Page" (pg #5)
"Section 2 Even Page" (pg #6)
"Section 3 First Page" (pg #7)
"Section 3 Even Page" (pg #8)
"Section 3 Odd Page" (pg #9)

and so on, and so on.

If there are more than three pages per section - the example above does not - the footers will reflect that appropriately.

The point being is that you can action footers (or headers) directly without using View, and without using Selection. You just action them directly.
Code:
If ActiveDocument.Section(7) _
   .Footers(wdHeaderFooterPrimary) _
        .Range.Text = ""  Then
   ActiveDocument.Section(7) _
   .Footers(wdHeaderFooterPrimary) _
        .Range.Text = "Yahooooo!"
End If
Checks to see if Section 7 footer Primary is blank, and if it is, make it "Yahooooo!". No going into the footers with the cursor (Selection), no use of View (ActiveWindow.View.Type = wdPageView blah blah blah). Just performs action directly to the footer.

Note: Primary = 1; FirstPage = 2, EvenPages = 3

So ActiveDocument.Section(7) _
.Footers(wdHeaderFooterPrimary)

can be written as:

ActiveDocument.Section(7).Footers(1)

faq219-2884

Gerry
My paintings and sculpture
 
Wow, thank you for so much detail. This helps alot. Unfortunately, in my code, I have to manipulate what's in the footer. I have to look for a certain phrase and number and I can't manipulate it without using Selection.

I knew I could loop through the items in the collection but I didn't know how to do it. I was able to get a lot done with you suggestion. I'll bark again if I get stuck.

 
Ok, now I need help figuring out if the footer actually exists. The EvenPage footer is not checked in Page Setup but the code thinks it's there.

I'm using this:
If ActiveDocument.Sections(i).Footers(swView).Exists = True Then

and it says it's true for swView=6. That's the EvenPage footer. But I don't have one.

What now?
 
Unfortunately, in my code, I have to manipulate what's in the footer. I have to look for a certain phrase and number and I can't manipulate it without using Selection."

This is flatly, utterly, wrong/incorrect, and I have explained why.

Further, I explained how you can manipulate it without Selection. You can manipulate anything in a footer 'til the cows come home, without EVER using Selection.

Please re-read my post.
Ok, now I need help figuring out if the footer actually exists. The EvenPage footer is not checked in
Page Setup but the code thinks it's there.

I'm using this:

If ActiveDocument.Sections(i).Footers(swView).Exists = True Then

and it says it's true for swView=6. That's the EvenPage footer. But I don't have one.

1. "I don't have one." Oh yes you do. The three footers always exist. The .Exists property only checks to see if it is being used.

2. If ActiveDocument.Sections(i).Footers(swView).Exists = True

If swView = 6, then you will get a run-time error 5941. 6 is not a valid number for this. I have no idea why you think 6 is EvenPages. I clearly stated that EvenPages = 3.

Maybe you should re-post your current code.

faq219-2884

Gerry
My paintings and sculpture
 
Honestly, swView=6 and I don't get a runtime error. But still, I see where I'm wrong. I'm using wdSeekView constants 0 - 10 and not Header/Footer contants of 1,2 or 3. My bad.

I have been informed that we won't use Even Pages Header/Footer at all so I don't need to check inside that one. I can code around it. So, I'll review and fix to only go to ActiveDocument.Sections(i).Footers(swView) where i=total number of sections in document (For/Next)and xsView = 1 and 2 (For/Next).

I'll still be using a loop and the Footers collection. I'll try to access the contents without Selection and repost when I get stuck, which I have a feeling will be pretty soon. Thank you for all your help and for insisting I apply your method. It'll do me good to learn a better way.
 
Hi Jtorres13,

Is there a particular reason you need to know which type of footer you're dealing with? If not (eg the existing content is unique to the footer type), you could use:
Code:
Sub UpdateFooters()
Dim oSection As Section
Dim oFoot As HeaderFooter
For Each oSection In ActiveDocument.Sections
    For Each oFoot In oSection.Footers
        If Not oFoot.LinkToPrevious Then
            With oFoot.Range
            'Test & manipulate
            End With
        End If
    Next oFoot
Next oSection
End Sub
If you do need to know (eg the existing content is NOT unique to the footer type), you could use:
Code:
Sub UpdateFooters()
Dim oSection As Section
For Each oSection In ActiveDocument.Sections
    With oSection
        With .Footers(wdHeaderFooterFirstPage)
            If Not .LinkToPrevious Then
                'Test & manipulate
            End If
        End With
        With .Footers(wdHeaderFooterPrimary)
            If Not .LinkToPrevious Then
                'Test & manipulate
            End If
        End With
        With .Footers(wdHeaderFooterEvenPages)
            If Not .LinkToPrevious Then
                'Test & manipulate
            End If
        End With
    End With
Next
End Sub
Note that in both cases, the testing is only done if the footer is not linked to the previous Section. If you want to make all footers independent, you'd need to change the If tests to something like:
Code:
        If oFoot.LinkToPrevious Then
            .LinkToPrevious = False
            With oFoot.Range
            'Test & manipulate
            End With
        End If
or
Code:
            If .LinkToPrevious Then
                .LinkToPrevious = False
            End If
            'Test & manipulate
As Jerry says, there is no need to select anything to make your changes. If you could tell us more about what it is you're trying to do (and inlude the code you're using), some more pointers could be given.

Cheers

[MS MVP - Word]
 
OK, everything very nice so far. I've removed 90% of my code using selection. Still using your code to understand what I'm doing so that's good.
Now, if the footer is empty, I don't want to type anything in it, I want to leave it empty.

I've tried:
Code:
dim i, swView as integer
swView=1
if ActiveDocument.Sections(i).Footers(swView).Range.Text = "" then
'Do stuff
as suggested in another post in this forum. That didn't work.

Neither does:
Code:
if ActiveDocument.Sections(i).Footers(swView).Range.characters.count=0 then
'Do stuff

It just goes through it as if there was something in it but I go in the document's footer to look (both Primary and FirstPage) and it's empty of text. The only thing there is a paragraph mark if I use the Show/Hide button. Is the paragraph mark being detected as text? How can I tell if the stupid footer is empty?

Thanks for your help guys. It's so frustrating cause I'm almost done and then the requirements change again.
 
Hi Jtorres13,

Using the code I posted, the test is as simple as:
Code:
                If .Text = vbCr Then
                    MsgBox "empty footer"
                Else
                    'manipulate
                End If
or
Code:
                If .Range.Text = vbCr Then
                    MsgBox "empty footer"
                Else
                    'manipulate
                End If
depending on which version of it you're using.

Cheers

[MS MVP - Word]
 
Ugh, that's precisely was I've been saying all along. How am I supposed to know there's a way to evaluate the contents of a footer in 100 different ways!!!

So, mine didn't work because a carriage return IS a character??? Do you have to be soooo nitpicky in VB??

Can someone recommend a way of studying or a book or something that will hint to these things? I would have never thought or looping through the Header/Footers collection, or to avoid the Selection method or to figure out the carriage return is a character. Although now that I think of it, it's in the font/symbols thingie...

Sorry for my rantings, you've been very helpful.
 
If you think that's counter-intuitive, wait until you start working with tables and shapes ...

As for the studying, most of what I've learnt is through studying other peoples' code, using the macro recorder, and heuristics.

Cheers

[MS MVP - Word]
 
As I have mentioned, stop using counters. Stop using counters.

Use objects. Use objects.

As far as I am concerned:

ActiveDocument.Sections(i).Footers(swView).Range.Text

neither the variable i, nor swView, is need, or desired.

The variable i can be handled, as both macropod and myself have suggested, by using an object

For Each oSection In ActiveDocument.Sections

The object oSection will handle ALL Sections in the document. Period. Therefore....no counter ( your "i") is needed.
Code:
Dim oHF As HeaderFooter
For Each oHF In oSection.Headers

will handle all the headers.....
Code:
For Each oHF In oSection.Footers

will handle all the footers....

so no counter (your swView) is needed.

I freely admit my code for testing was a little misconstruing. By "blank" I meant, no inserted text. Which is what we normally mean by "blank". Explicitly though, headers and footers are not literally blank. Ever.

Make a new document. DO NOTHING. Absolutely nothing. Do not type anything into the document. Do not put anything into the footers. Do not even go into the footers. Copy the following into the ThisDocument code module, and run it.
Code:
Sub SeeThis()
Dim oHF As HeaderFooter
For Each oHF In ActiveDocument.Sections(1).Footers
   If oHF.Range.Text = "" Then
      MsgBox "Empty"
   Else
      MsgBox "Not empty   " & oHF.Range.Text
   End If
Next
End Sub
You will NEVER, EVER, get the "Empty" message. Because headers and footers are NEVER, EVER, "empty".

" Is the paragraph mark being detected as text? "

Ummm.....a paragraph mark IS text.

In the code above the message will display:

Not empty

oHF.Range.Text will show as nothing.

But try this.
Code:
   Else
      MsgBox "Not empty   " & Asc(oHF.Range.Text)

NOW you will get:

Not empty 13

with 13 being the ASCII code of.......a paragraph mark.

Which is why macropod suggested:
Code:
If .Range.Text = [b]vbCr[/b] Then
   MsgBox "empty footer"
Else
   'manipulate
End If

You may want to add more detailed error trapping. Suppose someone typed an Enter key, a paragraph mark. So a footer has two paragraph marks. No text. Just two paragraph marks.

Both my If oHF.Range.Text = "" and macropod's If .Range.Text = vbCr will fail.

You may want to add something like:
Code:
If Len(oHF.Range.Text) > 1 And _
   Asc(oHF.Range.Text) = 13
This would tell you that it is more than one character, and the ASCII code of the first one is 13, a paragraph mark.

I will ask again, perhaps it would help if you posted your current code.
macropod said:
If you could tell us more about what it is you're trying to do (and inlude the code you're using), some more pointers could be given.

Oh, one last thing.

When you use an object to loop through a collection, the actual object will be created in the index order of the collection.

Say you have a document with DifferentFirstPage, DifferentOddEven set as True.

Say the footers are:

"First Page" (pg. #1)
"Even Page" (pg. #2)
"Odd Page" (pg. #3)

Dim oHF As HeaderFooter
For Each oHF In ActiveDocument.Sections(1).Footers

will run the For Each in this order, NOT the order in the document:

Odd Page (Primary = index 1)
First Page (FirstPage = index 2)
Even Page (EvenPages = index 3)

faq219-2884

Gerry
My paintings and sculpture
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top