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 John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Word - Limiting PageSetup to Section 1

Status
Not open for further replies.

peejaykay

Programmer
Jan 10, 2007
12
US
Word VBA All versions through Office 2003 -

The document being generated uses "Different first page" headers for early sections. Switching to deselect "Different first page" in a later new Section header causes previous headers to switch to also reflect the same change, or to mangle the previous header information.

The change to deselect "Different first page" header works properly if done manually using the mouse, but not programmatically. Even a macro created from mouse selections fails to work properly:

Selection.HeaderFooter.LinkToPrevious = False
With Selection.PageSetup
.HeaderDistance = InchesToPoints(0.5)
.FooterDistance = InchesToPoints(0.5)
.SectionStart = wdSectionNewPage
.OddAndEvenPagesHeaderFooter = False
.DifferentFirstPageHeaderFooter = False
.VerticalAlignment = wdAlignVerticalTop
End With

Is this a bug in Word, or am I doing something wrong? Thanks.
 
I'm not entirely sure what is wrong but it does seem as if something is. I couldn't reproduce the problem in 2007 but when I tried in 2002 it crashed Word and then told me to install SP3 - so maybe there is a fix, I don't know. I haven't installed it yet because I don't want to do the large downloads right now and, after restarting Word (2002) I could reproduce more or less what you describe.

The Macro Recorder isn't perfect and what, I think, is causing the problem is using the Selection. If, instead, you explicitly refer to the Section you want to change does it work as you wish?

Enjoy,
Tony

--------------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.

Professional Office Developers Association
 
Could we get more details?

Are the later Sections being created programatically? If so, could you post that code please?

Also, as Tony mentions that you are using Selection, are you moving the Selection to the other Sections? If so, please post that code.

You are using:
Code:
Selection.HeaderFooter.LinkToPrevious = False[/vba]so I take it you are using View, and actually going into the Header?  If so, as Tony mentions explicitly using the Section (rather than Selection) would be advised.

I tried to duplicate this - as far I understand what it is you are doing - in 2002 and did not have a crash.




Gerry
[url=http://www3.telus.net/public/fumei/]My paintings and sculpture[/url]
 
The code from the original post is in subroutine SourceCodeHeaderSetup called from within the NewSection subroutine.

I'm using VB6, and the Word object is declared a W

This routine gets called as text files are read in and processed. Each file becomes a new section. The code at the end puts a formula into the header.

I originally used the following line to establish the 1st page header setup, but that also caused the previous headers to adopt the same properties.

W.Selection.HeaderFooter.PageSetup.DifferentFirstPageHeaderFooter = False

The lines following the call to SourceCodeHeaderSetup are the manual steps that perform what I want to happen programmatically.

Thank you
'===================================================================
'===================================================================
Private Sub NewSection()
Dim i As Integer, intPgNo As Integer
Static beenHereB4 As Boolean
On Error GoTo Ehandler
'---------------------
'Go to end of document (but not in WinXP)
'---------------------
If beenHereB4 Then
'-----------------------------------------
'Note: added backspace because the EndKey
'wdStory is now producing a new page, this
'may be due to the upgrading of the Office
'Applications
'-----------------------------------------
W.Selection.EndKey Unit:=wdStory
W.Selection.TypeBackspace
End If
'-----------------------
'Get current page number
'-----------------------
CurPgNo = W.Selection.Information(wdActiveEndPageNumber)
'--------------------
'Insert section break
'--------------------
W.Selection.InsertBreak Type:=wdSectionBreakNextPage
'------------------------------
'Opens the header / footer view
'------------------------------
If W.ActiveWindow.View.SplitSpecial <> wdPaneNone Then
W.ActiveWindow.Panes(2).Close
End If
If W.ActiveWindow.ActivePane.View.Type = wdNormalView _
Or W.ActiveWindow.ActivePane.View.Type = wdOutlineView _
Then
W.ActiveWindow.ActivePane.View.Type = wdPrintView
End If

'--------------------------
'Select last Section header
'--------------------------
i = W.Selection.Information(wdActiveEndSectionNumber)
W.Selection.Goto What:=wdGoToSection, Which:=wdGoToFirst, count:=i, name:=""

'----------
W.ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
W.Selection.HeaderFooter.LinkToPrevious = False
'Next line commented out - doesn't work
' W.Selection.HeaderFooter.PageSetup.DifferentFirstPageHeaderFooter = False
'----------
'------------------------------------
'Switch to footer then back to header
'This is required or the contents of the previous
'header / footer gets selected and changed
'------------------------------------
W.ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
W.ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader

If beenHereB4 = False Then
'Manually setup the page setup because Word command
'doesn't work properly
SourceCodeHeaderSetup 'Doesn't work (Word problem)
' MsgBox "Switch to the open Word document" & Wrap$ & Wrap$ & _
' "1) Press the 'Page Setup' button on Header/Footer toolbar (open book)" & Wrap$ & _
' "2) Select the Layout tab" & Wrap$ & _
' "3) Deselect - 'Different first page'" & Wrap$ & _
' "4) Select OK" & Wrap$ & Wrap$ & _
' "5) Deselect - 'Link to Previous' back on the Header/Footer toobar" & Wrap$ & Wrap$ & _
' "6) Return to this message and Select 'OK'"
frmTowl.Refresh
beenHereB4 = True
End If
'-------------------------------
'Delete prior header information
'-------------------------------
W.Selection.WholeStory
W.Selection.HeaderFooter.LinkToPrevious = False
W.Selection.Delete Unit:=wdCharacter, count:=1
W.Selection.TypeParagraph
W.Selection.TypeBackspace

'---------------------------------
'Setup header restart numbering
'---------------------------------
With W.Selection.HeaderFooter.PageNumbers
.NumberStyle = wdPageNumberStyleArabic
.HeadingLevelForChapter = 0
.IncludeChapterNumber = False
.ChapterPageSeparator = wdSeparatorHyphen
.RestartNumberingAtSection = True
End With
'-------------------------
'Establish tabs for header
'-------------------------
W.Selection.ParagraphFormat.TabStops.ClearAll
W.Selection.ParagraphFormat.TabStops.Add position:=InchesToPoints(3.375), _
Alignment:=wdAlignTabCenter, Leader:=wdTabLeaderSpaces
W.Selection.ParagraphFormat.TabStops.Add position:=InchesToPoints(6.75), _
Alignment:=wdAlignTabRight, Leader:=wdTabLeaderSpaces

'-------------------------------
'Enter new header information
'-------------------------------
intPgNo = CurPgNo - LastPgNo
If Left$(frmMain.txtTPS.Text, 3) = "TPI" Then
W.Selection.TypeText Text:=frmMain.txtTPS & vbTab & vbTab & "WP 007 00" _
& Wrap$ & frmMain.txtDate & vbTab & vbTab & "Page "
Else
W.Selection.TypeText Text:="TPI " & frmMain.txtTPS & vbTab & vbTab & "WP 007 00" _
& Wrap$ & frmMain.txtDate & vbTab & vbTab & "Page "
End If
W.Selection.Fields.Add Range:=W.Selection.Range, Type:=wdFieldEmpty, _
PreserveFormatting:=False
W.Selection.TypeText Text:="=("
W.Selection.TypeText Text:=intPgNo & " + "
W.Selection.Fields.Add Range:=W.Selection.Range, Type:=wdFieldPage
W.Selection.TypeText Text:=")"
W.Selection.MoveRight Unit:=wdCharacter, count:=2
W.Selection.TypeText Text:=Wrap$ & vbTab
W.Selection.TypeText Text:="File: " & UCase$(FileName$) & " "
W.Selection.TypeText Text:="Page "
W.Selection.Fields.Add Range:=W.Selection.Range, Type:=wdFieldPage
W.Selection.TypeText Text:=" of pjk"

'-------------------------
'Provide for AFTER spacing
'-------------------------
With W.Selection.ParagraphFormat
.SpaceBefore = 0
.SpaceBeforeAuto = False
.SpaceAfter = 12
.SpaceAfterAuto = False
End With
Fmt.BorderBottom 'put border after 2nd line of header

'--------------------------
'Close header / footer view
'--------------------------
W.ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument

'----------------------------------------------------------
Exit Sub
Ehandler:
MsgText$ = ""
Call Main.Print2Err("NewSection")
End Sub 'NewSection
'===================================================================
'===================================================================
 
'Note: added backspace because the EndKey
'wdStory is now producing a new page, this
'may be due to the upgrading of the Office
'Applications
Really? I have never heard of such. EndKey Direction:=wdStory is simply an instruction to move to the end of the document. I have never heard anything that it creates a new page that was not there before.

'Insert section break
'--------------------
W.Selection.InsertBreak Type:=wdSectionBreakNextPage
'------------------------------
'Opens the header / footer view
'------------------------------
If W.ActiveWindow.View.SplitSpecial <> wdPaneNone Then
W.ActiveWindow.Panes(2).Close
End If
If W.ActiveWindow.ActivePane.View.Type = wdNormalView _
Or W.ActiveWindow.ActivePane.View.Type = wdOutlineView _
Then
W.ActiveWindow.ActivePane.View.Type = wdPrintView
End If

'--------------------------
'Select last Section header
'--------------------------
i = W.Selection.Information(wdActiveEndSectionNumber)
W.Selection.Goto What:=wdGoToSection, Which:=wdGoToFirst, count:=i, name:=""

This is all way too much extraneous code. You do not need to do this.

You insert a Section break, go into header/Footer view, get the Section number (i), then use that to go to the Section.

Excuse me...but you are already there!

This seem messy. Perhaps this may help. It creates a new Section, and ensures that everything is cleaned out of ALL three headers, and ALL three footers. All of them are set to LinktoPrevious=False, and the Section has DifferentFristPage = False.
Code:
Sub EmptyNewSection()
Dim oHF As HeaderFooter
Dim i As Integer
Selection.InsertBreak Type:=wdSectionBreakNextPage
' i includes new Section
i = ActiveDocument.Sections.Count
For Each oHF In ActiveDocument.Sections(i).Headers
    oHF.LinkToPrevious = False
    oHF.Range.Delete
Next
For Each oHF In ActiveDocument.Sections(i).Footers
    oHF.LinkToPrevious = False
    oHF.Range.Delete
Next
     ActiveDocument.Sections(i). _
        PageSetup.DifferentFirstPageHeaderFooter = False
End Sub

I strongly recommend you do not use View to work with headers or footers. The:
Code:
    'Opens the header / footer view
    '------------------------------
    If W.ActiveWindow.View.SplitSpecial <> wdPaneNone Then
        W.ActiveWindow.Panes(2).Close
    End If
    If W.ActiveWindow.ActivePane.View.Type = wdNormalView _
yadda yadda yadda is not needed. Working with the header object and its Range directly is much better.




Gerry
My paintings and sculpture
 
Thank you for the post...

How do you write the header information without opening the view? Do you use oHF.Range also to do that?
 
In a way, yes. You use objects. You have access to all the objects required. The Section. The HeaderFooter. Range objects.

For example:
Code:
Dim r As Word.Range
Set r = ActiveDocument.Sections(3). _
     Headers(wdHeaderFooterPrimary).Range
r.Text = "Section 3 Header Primary"
Set r = Nothing
Makes a Range object of the Primary headerfooter of Section 3, and makes the text "Section 3 Header Primary".

Done. No View. No Selection Typetext blah blah blah

Say there was text in a header, and you wanted to put something after it.
Code:
Dim r As Word.Range
Set r = ActiveDocument.Sections(2). _
     Headers(wdHeaderFooterPrimary).Range
With r
   .Collapse Direction:=wdCollapseEnd
   .InsertAfter Text:= "  more text after"
End With
Set r = Nothing
This makes the Range object r the range of Section 2 Primary header, collapses the range to the end, and then inserts text " more text after".

Say you had a document with six pages, like this:

Section 1 - pages 1 to 3
Section 2 - pages 3 to 6

Section 1 had DifferentFirstPage, but it is a title page so the footer text is blank. Pages 2 and 3 have, oh, a Table of Contents and their footer has the text "Table of Contents"

Section 2 does NOT have DifferentFirstPage, it is just Primary for the whole Section.
Code:
Dim r As Word.Range
Dim oHF As HeaderFooter
Dim oSection As Section
Set oSection = ActiveDocument.Sections(2)
  If oSection.PageSetup. _
       DifferentFirstPageHeaderFooter = False Then
    oSection.PageSetup.DifferentFirstPageHeaderFooter _
       = True
  End If
  Set oHF = oSection.Footers(wdHeaderFooterFirstPage)
  With oHF
    .LinkToPrevious = False
    .Range.Text = "Footer text  - Section 2 First Page" _
        & vbTab
       Set r = oHF.Range
       r.Collapse Direction:=wdCollapseEnd
   .Range.Fields.Add Range:=r, Type:=wdFieldFileName
  End With
Set r = Nothing
Set oHF = Nothing
This:

1. makes a Section object of Section 2
2. checks to see if it is DifferentFirstPage
3. if it is not, makes it DifferentFirstPage
4. makes a HeaderFooter object of the DifferentFirstPage footer
5. unlinks the HeaderFooter object to Previous, remember the previous is ""
6. adds text "Footer text - Section 2 First Page", and Tab
7. makes a Range object of the footer (ie. the text)
8. collapses the Range to the end
9. adds the Field for the filename

The point being is that you can pretty do anything you want with headers and footers directly. You do not have to use View, or Selection to type in text. It can all be done behind the scenes, as it were.

It really helps to understand how Word deals with headers and footers.

ALWAYS remember that every Section has three headers (whether you have put anything in them, or not), and three footers (whether you put anything in them, or not).

ALWAYS remember that any time you make a new Section, those headers and footers WILL be set as Same as previous. If you do not want them repeated from the previous Section you must turn off Same as previous (or in code .LinkToPrevious = False).

What I do is have three procedures which I added to the Insert menu.

SectionNewSame - makes a new Section WITH same as previous

SectionNewEdit - makes a new Section WITH same as previous structure, but displays a userform to make possible partial (or even full) changes. Current settings and values are displayed on the form, and I can make any changes to all SIX headers and footer settings and text from one form. This makes it easy to say, keep a DifferentFirstPage footer text, but change a DifferentFirstPage header text.

SectionNewClear - makes a new Section clearing all Same as previous settings, AND text, ie. all headers and footers are blank.

Just for comparison, here is the code that results from recording a macro to get the EXACT SAME results as my code above.
Code:
    With Selection.PageSetup
        .LineNumbering.Active = False
        .Orientation = wdOrientPortrait
        .TopMargin = InchesToPoints(1)
        .BottomMargin = InchesToPoints(1)
        .LeftMargin = InchesToPoints(1.25)
        .RightMargin = InchesToPoints(1.25)
        .Gutter = InchesToPoints(0)
        .HeaderDistance = InchesToPoints(0.5)
        .FooterDistance = InchesToPoints(0.5)
        .PageWidth = InchesToPoints(8.5)
        .PageHeight = InchesToPoints(11)
        .FirstPageTray = wdPrinterDefaultBin
        .OtherPagesTray = wdPrinterDefaultBin
        .SectionStart = wdSectionNewPage
        .OddAndEvenPagesHeaderFooter = False
        .DifferentFirstPageHeaderFooter = True
        .VerticalAlignment = wdAlignVerticalTop
        .SuppressEndnotes = False
        .MirrorMargins = False
        .TwoPagesOnOne = False
        .BookFoldPrinting = False
        .BookFoldRevPrinting = False
        .BookFoldPrintingSheets = 1
        .GutterPos = wdGutterPosLeft
    End With
    If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
        ActiveWindow.Panes(2).Close
    End If
    If ActiveWindow.ActivePane.View.Type = wdNormalView _
      Or ActiveWindow.ActivePane.View.Type = wdOutlineView Then
        ActiveWindow.ActivePane.View.Type = wdPrintView
    End If
    ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
    If Selection.HeaderFooter.IsHeader = True Then
        ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
    Else
        ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
    End If
    Selection.TypeText Text:="Footer text - Section 2 First Page " & vbTab
    Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
        "FILENAME  ", PreserveFormatting:=True
    ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
Bleeeech. Other than the fact that using Selection uses system resources (as it uses the user interface), recorded macros often have all this extraneous stuff. Recorded macros ALWAYS use Selection. They can not create objects.

Gerry
My paintings and sculpture
 
Thank you very much Gerry. As you could tell, all of my Word code was based on incorporating recorded macros. Is there a reference (online or book) that demonstrates using objects for programming all of Word's functions? The Object Browser is helpful when you know what you're looking for, but frustrating when you don't.
Paul
 
F1 (Help) is your friend.

You can see most of the Object Model by looking up "Object Model" in Help. You can at least see what objects are child objects of what other objects. It is a bit daunting figuring it out I admit.

Also search Microsoft for the Object Model of the version you are using.

It is more important to understand the concept of objects (and collections of objects) themselves.

For example, I have seen where someone was doing something with all the bookmarks in a document. They were making a separate document listing the contents of all the bookmarks in a source document. They did it like:

Go to each bookmark, by name (so they had to look up the name, and they hard coded this), select it, copy it, switch to the other document, type in the name of the bookmark, type in a paragraph mark, paste the bookmark contents, type in a paragraph mark, type in a paragraph mark. The last two paragraph marks were to add space between the bookmark contents. Kind of like this:
Code:
Selection.GoTo What:=wdGoToBookmark, Name:="xxxxxx"
Selection.Copy
OtherDocument.Activate
Selection.TypeText Text = "xxxxxx"
Selection.TypeParagraph
Selection.TypeParagraph
Selection.Paste
SourceDocument.Activate
and on and on. They did this for every bookmark.

Here is code that does it with objects.
Code:
Dim oBM As Bookmark
Dim ThisDoc As Document
Dim Thatdoc As Document

Set ThisDoc = ActiveDocument

Documents.Add
Set Thatdoc = ActiveDocument

For Each oBM In ThisDoc.Bookmarks
   Thatdoc.Range.InsertAfter _
      Text:=oBM.Name & vbCrLf & _
         oBM.Range.Text & vbCrLf & vbCrLf
Next
Set ThatDoc = Nothing
Set ThisDoc = Nothing
Step 1. declare Bookmark object, and two Document objects

Step 2. It sets a document object for the current document. This allows direct use of the child objects of the document.

Step 3. It adds a new document, and sets a document object of THAT, which also allows use of the child objects of it.

Step 4. For Each (and every, so no need to get names, or count them) Bookmark (using the bookmark object) in the ThisDoc object Bookmark collection (a child object collection) - For Each oBM In ThisDoc.Bookmarks

insert at the end of the other document - Thatdoc.Range.InsertAfter - and this will always put it at the NEW end, even with the added text.

the bookmark name (from the source doc), a paragraph mark, the bookmark contents, and two paragraph marks.

Text:=oBM.Name & vbCrLf & _
oBM.Range.Text & vbCrLf & vbCrLf


NO selecting. NO copying. NO pasting. NO switching back and forth between documents. The objects do the work.
Is there a reference (online or book) that demonstrates using objects for programming all of Word's functions?
My bold.


No. The VBA Developer's Handbook is a good reference.

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

Part and Inventory Search

Sponsor

Back
Top