Hey, Scripting Guy! I saw your article on adding page numbers to the footer of a Word document. However, I need my page numbers to be in the format “Page X of Y,” where X is the current page number and Y is the total number of pages. How can I do that?
— JS
Hey, JS. You know, several years ago the grocery store by the Scripting House included one of those claw-type arcade games; you know, the kind where you maneuver this big claw around and try to grab a prize. Back then the Scripting Son was infatuated with the idea of winning one of the big prizes. For awhile the Scripting Dad indulged his son, but it wasn’t long before Dad got tired of wasting a dollar each time they went to the store; after all, despite his best efforts the Scripting Son never even came close to winning any prize, let alone a really cool prize.
“This game is impossible,” the Scripting Dad told the Scripting Son. “I’m not wasting any more money on it. You can’t win; there’s no way.”
“No, Dad, there’s a trick to it, and I figured out what the trick is,” replied the Scripting Son. “Please, let me have just one dollar? I know I can do it.”
But the Scripting Dad remained resolute. After all, if the Scripting Dad says something is impossible then it must be impossible. End of discussion.
We mention this simply because the Scripting Dad also believed it was impossible to programmatically add a Page X of Y footer to a Word document. This question has come up before, and the Scripting Guy who writes this column couldn’t figure out how to do. And if the Scripting Guy who writes this column can’t figure out how to do something then it must be impossible. End of discussion.
Except, as it turns out, there’s a trick to it. And once you figure out the trick, well, guess what? You really can add a Page X of Y footer to a Word document:
Set objWord = CreateObject(“Word.Application”) objWord.Visible = TrueSet objDoc = objWord.Documents.Add()
Set objRange = objDoc.Sections(1).Footers(1).Range
Set objTemplate = objDoc.AttachedTemplate objTemplate.AutoTextEntries(“Page X of Y”).Insert objRange
So what is this trick? We’ll explain that in just a second. Before we do that, however, let’s talk about the rest of the script. We start out by creating an instance of the Word.Application object and setting the Visible property to True; that gives us a running instance of Microsoft Word that we can see onscreen. After using the Add method to add a new, blank document to our instance of Word, we then use this line of code to create a Range object corresponding to the first footer in the first section of our document:
Set objRange = objDoc.Sections(1).Footers(1).Range
And you’re right: because we don’t have any other sections in the document (let alone any other footers) that means this Page X of Y footer will apply to the entire document.
Here comes the tricky part. Our next step is to create an instance of the Template object; we do that by binding to the document’s AttachedTemplate property:
Set objTemplate = objDoc.AttachedTemplate
And then we insert one of the template’s AutoTextEntries; to be a more specific, we insert the Page X of Y entry:
objTemplate.AutoTextEntries(“Page X of Y”).Insert objRange
Needless to say, this is way easier than we thought. We bind to the AutoTextEntries collection and call the Insert method, specifying Page X of Y as the autotext to be entered. We also have to specify where we want the text entered. Where do we want this text entered? You got it: objRange, the object reference specifying the document footer.
And that, believe it or not, is all we need to do.
OK, that’s not true; with this kind of footer you probably want the text center-aligned. If that’s the case, then just tack this line of code onto the end of the script:
objRange.ParagraphFormat.Alignment = 1
And that is all we need to do.
Incidentally, you might be interested in knowing how the Scripting Guy who writes this column finally solved this riddle. He knew it was possible to do a Page X of Y footer using the Word GUI. Therefore, he started a macro recording and went ahead and used the GUI to add the desired footer. When he was done he edited the macro in order to view the macro code. After wading through the VBA code he found this:
NormalTemplate.AutoTextEntries(“Page X of Y”).Insert Where:=Selection. _ Range, RichText:=True
That was the hint he was looking for. That’s something to remember when writing scripts that interact with Microsoft Word: any time you get stuck try recording a macro that carries out the desired action. The VBA code will often be a little obtuse, but it will usually point you in the right direction.
So does the Scripting Dad feel bad that he didn’t give the Scripting Son a dollar and let him try to win a really cool prize? No, not really. For one thing, the Scripting Son has found plenty of other ways to pry money from the Scripting Dad. For another, the prizes you could win back then really weren’t all that cool. For example, did the claw game offer you the chance to win a Dr. Scripto bobblehead doll or a Scripting Guys gift pack? What, are you kidding? No, there are only two ways you can win a really cool prize like those:
• |
If you’re attending TechEd 2007 swing by the CMP Media Booth (booth number 1301), find the Scripting Guys, get a copy of Dr. Scripto’s Fun Book, and enter the drawing for a Dr. Scripto bobblehead doll. If you aren’t sure who the Scripting Guys are, just look for a cheapskate in a baseball hat. That’s the Scripting Dad. |
• |
Even if you’re not attending TechEd 2007 you have a shot at winning a cool prize by entering the TechEd Challenge. Don’t delay, though; that contest ends June 30th. |
So is there a trick to winning the TechEd Challenge? You bet there is. However, the Scripting Editor always gets a little nervous when we say things like, “Send us $100 and we’ll rig the contest and make sure you win.” Therefore, we won’t say that.
But it is something to think about, isn’t it? (Editor’s Note: No.)
0 comments