PDA

View Full Version : Solved: Accessing Header after Template is Opened



jasoncw
07-27-2007, 10:45 AM
Hi, everyone. New guy here. I am mildly proficient in VBA, although most of my programming has been in Excel. I am having an issue in Word trying to merge in a letterhead template.

Here is a quick explanation of what I am trying to accomplish:

We have a generic document that is going to be used by many different offices. Each office has their own letterhead, each of which are stored on our intranet. I am trying to develop a procedure that will allow the user to select their office, then apply the letterhead to the document. The letterhead templates are nothing more than blank Word templates with an image file in the header.

What I was trying to do is open the template (*.dot), copy the image from the header, and paste into the current document. Here is the code I am using:

Private Sub cmdLetterhead_Click()
Dim tmpDir As String, tmpFile As String, tmpFileRev As String
Dim thisDoc As Document
Set thisDoc = ActiveDocument
tmpDir = "...myintranet/letterhead/" 'edited for forum use

frmOffice.Show 'user form for users to select office

If strOffice = "" Then 'no office selected
MsgBox "You must select an office in order to apply the letterhead.", vbCritical, _
"Letterhead Error"
Exit Sub
End If

Select Case strOffice
Case "Bohemia, NY": tmpFile = "NY%20PA%2025%20855.4356.dot"
Case "Camarillo, CA": tmpFile = "CA%205151%20380.4745.dot"
Case "Charleston, WV": tmpFile = "WV%20PA%20300%20340.5251.dot"
Case "Chicago, IL": tmpFile = "IL%20PA%20225%20419.9457.dot"
Case "Cincinnati, OH": tmpFile = "OH%20PA%20801A%20419.9457.dot"
Case "Cleveland, OH": tmpFile = "OH%20PA%208333%20419.9457.dot"
Case "Indianapolis, IN": tmpFile = "IN%20PA%208115%20419.9457.dot"
Case "Jericho, NY": tmpFile = "NY%20PA%20100%20855.4356.dot"
Case "Lansing, MI": tmpFile = "MI%20PA%203815%20702.3240.dot"
Case "Louisville, KY": tmpFile = "KY%20PA%209901%20419.9457.dot"
Case "Middletown, CT": tmpFile = "CT%20PA%20100%20855.4356.dot"
Case "Milwaukee, WI": tmpFile = "WI%20PA%206775%20883.0130%20IVR.dot"
Case "Mt. Vernon, IL": tmpFile = "IL%20PA%204203%20244.4770.dot"
Case "Oakland, CA": tmpFile = "CA%20PA%207677%20633.4200.dot"
Case "Portland, ME": tmpFile = "ME%20PA%20PO919.dot"
Case "Richmond, VA": tmpFile = "VA%20PA%208002%20521.2300.dot"
Case "Springfield, IL": tmpFile = "MI%20PA%2026555%20355.7850.dot"
Case "Southfield, MI": tmpFile = "IL%20PA%203200%20419.9457.dot"
Case "Syracuse, NY": tmpFile = "NY%20PA%20400%20855.4356.dot"
Case "Toledo, OH": tmpFile = "OH%20PA%206056%20419.9457.dot"
Case "Yorktown Heights, NY": tmpFile = "NY%20PA%202651%20855.4356.dot"
End Select

Application.ScreenUpdating = False
Documents.Open tmpDir & tmpFile
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.HeaderFooter.Shapes(1).Select
Selection.Copy
ActiveDocument.Close False
Documents(thisDoc).Activate
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.Paste
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
Application.ScreenUpdating = True

End Sub
The bolded lines above are where I am stuck. The problem is that when the template is opened, and I try to access the header, the header is accessed on the original document, rather than the template. Therefore, there is no image file, so it obviously can't copy. I have stepped through this, and the template is the active window, so I'm not sure why it will not allow me to access the header in the template.

I hope I explained this adequately. If not, please let me know. Also, if there is an easier or more efficient way of accomplishing this, I'm all ears. :)

TIA

Jason

fumei
07-27-2007, 12:21 PM
Please use the underscore character in your code to make the code lines a bit shorter. Thanks.

This seems a bit odd to me. I have read it a couple of times, and it does not really make sense.

Why not just use the template????? If it has the correct image in the header, and it is related to the office...then once you have the office, why not just use the template that is matched to that office???

It is absolutely contrary to template use to copy something out of a template file itself, into a document.

You seem to be using a template to get an image from another template. If those are blank with just the image....why on earth use them as templates? In fact - you are NOT using them as templates. You are using them as some sort of image file storage container. Weird.

Also, the code apppears to be a userform command button click event. Where is THAT coming from? Especially as it seems it is calling [another userform (frmOffice).

In any case, you can do something like replacing this: Documents.Open tmpDir & tmpFile
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.HeaderFooter.Shapes(1).Select
Selection.Copy
ActiveDocument.Close False
Documents(thisDoc).Activate
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.Paste
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
with this:Dim r As Range
' declared in the usual place
' yaddda yadda

Documents.Open FileName:=tmpDir & tmpFile
Set r = ActiveDocument.Sections(1) _
.Headers(wdHeaderFooterPrimary).Range
r.CopyAsPicture
ThisDoc.Sections(1).Headers(wdHeaderFooterPrimary) _
.Range.Paste
ActiveDocument.Close wdDoNotSaveChangesThis will copy the header from the template file AsPicture, into the header of ThisDoc.

NOTE: this assumes that the template file header content IS in Section(1).Headers(Primary), and that you want it to go into ThisDoc Section(1).Headers(Primary).

You can access headers directly, as it is always better to do so. Selecting, using View, is very inefficient, and IMO, prone to errors.

Also, it may be better to use Arrays.Dim City()
Dim FileLocation()
Dim lngOffice
City() = Array("Bohemia, NY", "Camarillo, CA", _
"Charleston, WV", "Chicago, IL", "Cincinnati, OH", _
"Cleveland, OH", "Indianapolis, IN", "Jericho, NY", _
"Lansing, MI", "Louisville, KY", "Middletown, CT", _
"Milwaukee, WI", "Mt. Vernon, IL", "Oakland, CA", _
"Portland, ME", "Richmond, VA", "Springfield, IL", _
"Southfield, MI", "Syracuse, NY", "Toledo, OH", _
"Yorktown Heights, NY")

FileLocation = Array(“NY%20PA%2025%20855.4356.dot", _
"CA%205151%20380.4745.dot", _
"WV%20PA%20300%20340.5251.dot", _
"IL%20PA%20225%20419.9457.dot", _
"OH%20PA%20801A%20419.9457.dot", _
"OH%20PA%208333%20419.9457.dot", _
"IN%20PA%208115%20419.9457.dot", _
"NY%20PA%20100%20855.4356.dot", _
"MI%20PA%203815%20702.3240.dot", _
"KY%20PA%209901%20419.9457.dot", _
"CT%20PA%20100%20855.4356.dot", _
"WI%20PA%206775%20883.0130%20IVR.dot", _
"IL%20PA%204203%20244.4770.dot", _
"CA%20PA%207677%20633.4200.dot", _
"ME%20PA%20PO919.dot", _
"VA%20PA%208002%20521.2300.dot", _
"MI%20PA%2026555%20355.7850.dot", _
"IL%20PA%203200%20419.9457.dot", _
"NY%20PA%20400%20855.4356.dot", _
"OH%20PA%206056%20419.9457.dot", _
"NY%20PA%202651%20855.4356.dot")
Once you have these, then - I am assuming on your userform frmOffice has a combobox listing the offices - you can use the City Array to populate the combobox.

You can use the selected item (the office) to set lngCity. In which case (with the FileLocation array)Documents.Open Filename:=tmpDir & FileLocation(lngCity)No need to go through the Select Case. Just use the index numbers of the arrays directly.

jasoncw
07-27-2007, 12:51 PM
Hi, Gerry. Thanks for the prompt reply. You ask some good questions.

First, you have to understand that I need to work with what is already in existence. I am developing a document, and several users have requested me to be able to incorporate company letterhead into this document. Our letterhead for some reason is stored as various templates (*.dot) on our intranet, and the only contents of these templates is the letterhead image in the header. I am just trying to figure out an easy way to be able to take my document and add the letterhead from these templates. I understand this is "weird," but it is what I have to work with.

To clarify, this procedure is being called from the click event of a command button attached to the document; not a userform.

As for selecting. Yes, I know how inefficient this is. Like I stated, I am new to Word VBA, so I didn't know quite how to do this without selecting. If this was Excel, it would be much easier for me.

Now with that being said, I did try your code, and it appears to be doing the same as mine. I am guessing that it is copying from the document header, rather than the template header, as nothing is in the document header after the procedure is run.

BTW, thanks so much for the array code. :)

Jason

fumei
07-27-2007, 01:14 PM
Hmmm. I tested this with a template file, and the code opened the template file, and copied the header image from it, into the document.

Are you sure the template file is being opened?

jasoncw
07-27-2007, 01:33 PM
Yes, I'm sure it's being opened; I have stepped through the code. Would it be possible to email you the document, along with one of the templates for you to try it out? I could post the document here, but I would prefer not to post the letterhead...

Jason

fumei
07-28-2007, 11:30 AM
Yes. Send it to me at

myhandle at telus dot net

fumei
07-30-2007, 04:22 AM
Got the files.

OK folks. Another misdirection due to header objects in the Word Object Model. In my post I wrote:
NOTE: this assumes that the template file header content IS in Section(1).Headers(Primary), and that you want it to go into ThisDoc Section(1).Headers(Primary).

I could make no other assumption, as any other information was not there.

However.....the content you want to copy is NOT, repeat NOT, in Primary. For some reaosn (I have no idea why), you have the header content you want in wdheaderFooterFirstPage - as you have the template file set as Different first page.

Therefore getting the content from Primary (which of course DOES exist), gets....blank. As it is blank. It works if you use the correct header, like this:Documents.Open FileName:=tmpDir & tmpFile
Set r = ActiveDocument.Sections(1) _
.Headers(wdHeaderFooterFirstPage).Range
r.CopyAsPicture
ThisDoc.Sections(1).Headers(wdHeaderFooterPrimary) _
.Range.Paste
ActiveDocument.Close wdDoNotSaveChanges This takes the content from wdHeaderFooterFirstPage in the template, and puts it in wdHeaderFooterPrimary in the document.

As the document does NOT have Different first page.

So, no, it was not copying from the document header, it was in fact copying from the template header.....but THAT header does not have anything in it.

Remember even though you may not have put anything in it, there is ALWAYS Primary.

It helps to use the proper objects. Either change your templates to be Primary (which makes sense as there is only one page); change the code to use FirstPage; or do some error checking to make sure you get the content from the header WITH the content.

Fixed. Your file has been returned to you.

jasoncw
07-30-2007, 07:50 AM
Hi, Gerry. Thanks so much for the simple solution. I am not the author of the letterhead templates on our intranet, so I must work with what I am provided. I made the ASS-umption that since they are only 1 page, they were not set up to be different first page headers. Whoops!

Thanks again for the help, and with my Word VBA knowledge. :)

Jason

fumei
07-30-2007, 11:58 AM
You are welcome. If you have no control of the template files, then you can do some error trapping.

It is an odd part of the Object Model, that the .Exists property of a header has nothing to do with its content.

Check Different first page in Page Setup.

Put "This is first page text crap." into the FirstPage header.

Test with:Sub Whatever()
Dim aDoc As Document
Set aDoc = ActiveDocument

If aDoc.Sections(1).Headers(wdHeaderFooterFirstPage) _
.Exists Then
MsgBox "Yes, it is exists." & vbCrLf _
& aDoc.Sections(1).Headers(2).Range.Text
Else
MsgBox "No, it does NOT exist. But here is " & _
" the text anyway." & vbCrLf _
& aDoc.Sections(1).Headers(2).Range.Text
End If
Set aDoc = Nothing
End SubYou get a message box with:

"Yes, it exists.
This is first page text crap."

Now go into Page Setup, and turn off Different first page. So, no different first page.....right? Run the code again. You get a message box with:

"No, it does NOT exist. But here is the text anyway.
This is first page text crap."

I can not stress this enough. The header structure of sections persists. The .Exist property only states if that header is toggled as active. It does NOT have anything to do with whether it "exists" or not. The three headers of every Section (Primary, FirstPage, OddEven) are always there. They can not be deleted. The OddEven header has content (even if it is "") whether you use it or not. AND once content other than "" is put into a header, it will STAY there, whether you uncheck it in Page Setup.

In the example above, if you RECHECK Different first page, the previous content will reappear. It persists.

So, back to your issue. you can error trap by:

1. check if Different first page is toggled. Use the .Exists property.

2. check if Primary has content.

Between these you can easily make sure you do in fact get the header you want.

jasoncw
07-30-2007, 12:36 PM
Beautiful! Thanks again, Gerry. :)

Jason