Office Space: Tips and Tricks for Scripting Microsoft Office Applications

Office Space

Welcome to Office Space, the column that offers tips and tricks for scripting Microsoft® Office applications. We’ll post new tips every Thursday; to see an archive of previous tips, visit the Office Space Archive. And if you have particular questions about Microsoft Office scripting, feel free to send them to scripter@microsoft.com (in English, if possible). We can’t promise to answer all the questions we receive, but we’ll do our best.

Printing Documents Using Microsoft Word

About 60 years ago, the ENIAC – generally accepted as the world’s first real computer – ran its initial set of calculations. (In case you’re wondering, ENIAC was originally developed to help calculate artillery firing tables for the Army.) We don’t know for sure what was said at that historic moment; our best guess is, “Abort, retry, or what?” However, we have little doubt that it wasn’t long before someone said, “Welcome to the world of the paperless office.”

In other words, ever since the time of the ENIAC people have been proclaiming the advent of the paperless office. And yet, reports of the death of paper and printing – like reports of the death of Mark Twain – have been greatly exaggerated.

What’s that? Mark Twain is dead? Wow; we need to read the papers more often. Sorry to hear about Mark, but from the piles of printouts stacked up around us we can definitely say that reports of the death of paper and printing have been greatly exaggerated. Printing is still an important part of our daily business lives. And, as usual, Microsoft Word is here to help.

You’re probably already aware of the fact that a simple script can get Microsoft Word to print the current document; that requires nothing fancier than a call to the PrintOut method:

Set objWord = CreateObject("Word.Application")
objWord.Visible = True

Set objDoc = objWord.Documents.Open("c:\scripts\test.doc")
objDoc.PrintOut

objWord.Quit

What you might not know, however, is that your scripts can also use Word to print out documents that aren’t open. In addition, you can have Word print only selected pages within a document; for example, you can ask it to print only pages 2 through 5. And that’s not even the half of it: all the printing options available to you in Word’s user interface are available to you in your scripts as well. We don’t have time to cover all those options today, we’ll go through only a few of the options we think system administrators might be most interested in. If you’re really gung-ho on printing documents using Microsoft Word, however, you’ll find complete information on the options available to you by perusing the Microsoft Word VBA Language Reference on MSDN.

As it turns out, the secret to doing “fancy” printing in Microsoft Word is to pass additional parameters to the PrintOut method. If you simply call PrintOut without any parameters (as we did in the sample script we just showed you), then Word prints the current document. But suppose you pass PrintOut a crazy-looking set of parameters like these:

Set objWord = CreateObject("Word.Application")
objWord.Visible = True
Set objDoc = objWord.Documents.Add()

objWord.PrintOut ,,,,,,,,,,,,"c:\scripts\test.doc"

objWord.Quit

What happens here? Well, in this case, Word will print the document C:\Scripts\Test.doc, even though Test.doc isn’t open. If all you want to do is print a document there’s no need to write additional code to open and close that document: just call the PrintOut method and pass it the appropriate parameters.

We had a feeling someone would ask that question: how does this script work? Well, it begins by creating an instance of the Word.Application object, and then sets the Visible property to True; that gives us a running instance of Word that we can see onscreen. (Note that Word doesn’t have to be visible onscreen for this script to work; we only do that so you can see what’s happening.)

Next we use this line of code to add a new, blank document to our instance of Word:

Set objDoc = objWord.Documents.Add()

This might seem silly: why add a new document if that’s not the document we’re going to print? Well, silly or not, that’s just something you have to do: without this line of code you’ll generate an error similar to this:

Microsoft Word

Having a document loaded into the application – even though we won’t actually use that document – solves the problem.

Now we get to the good stuff, the line of code that actually prints the document:

objWord.PrintOut ,,,,,,,,,,,,"c:\scripts\test.doc"

What’s with all the commas? Well, with the PrintOut method (as with most methods) parameters must be passed in order; otherwise the method won’t have any idea what you want to do. If you want to print a file that isn’t currently open, the FileName parameter must be the thirteenth parameter passed to the PrintOut method. That’s why we have 12 commas preceding the path c:\scripts\test.doc. Granted, we don’t want to set any of those parameters, but if we don’t put a placeholder in for them then FileName won’t be parameter No. 13. And then our script won’t work. Insert the commas as placeholders, though, and you’re in business.

Now, admittedly, this is kind of cool: you can print a document without writing as much code, and your script will run a tiny bit faster because it doesn’t have to open and close Test.doc. On the other hand, let’s be real: the time-savings will be minimal if you’re only printing a single document. Where this technique really comes in handy are those occasions when you want to print out a bunch of documents; after all, those minimal time savings begin to add up if you’re printing 15 or 20 documents. Plus the fewer lines of code the less chance for something to go wrong.

For example, here’s a script that returns all the files found in the folder C:\Scripts and then checks each file to see if it’s a Word document (that is, if it has a file extension of .doc). If it finds a Word document, it prints it:

Set objWord = CreateObject("Word.Application")
objWord.Visible = True
Set objDoc = objWord.Documents.Add()

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set FileList = objWMIService.ExecQuery _
    ("ASSOCIATORS OF {Win32_Directory.Name='c:\Scripts'} Where " _
        & "ResultClass = CIM_DataFile")

For Each objFile In FileList
    If objFile.Extension = "doc" Then
        objWord.PrintOut ,,,,,,,,,,,,objFile.Name
    End If
Next

objWord.Quit

As you can see, we use an ASSOCIATORS OF query to return all the files (instances of the class CIM_DataFile) found in the folder C:\Scripts. We set up a For Each loop to walk through the returned collection, and, inside that loop, use this line of code to see if we’re dealing with a Word document:

If objFile.Extension = "doc" Then

If we are, then we use this line of code to print out the file, this time passing the Name property (which happens to equate to the file path) as the thirteenth parameter:

objWord.PrintOut ,,,,,,,,,,,,objFile.Name

We then loop around and print the next file in the collection.

Good point: how did you survive all these years without knowing you could do this?

But that’s not all you can do, not by a long shot. As we noted earlier, you can also print specific pages (and only those pages) in a document. To do that, we need to deal with the ninth parameter (Pages) passed to the PrintOut method. For example, suppose we want to print only page 2 of the document C:\Scrips\Test.doc. Okey-doke:

objWord.PrintOut ,,,,,,,,"2",,,,"c:\scripts\test.doc"

Note. Yes, even though 2 is a number, you need to surround it with double quotes. You’ll see why in a moment.

Suppose we want to print pages 2, 4, and 6. In that case, we’d include all three page numbers in the parameter, using commas to separate each one:

objWord.PrintOut ,,,,,,,,"2,4,6",,,,"c:\scripts\test.doc"

That, by the way, is the reason for the double quotes around the page numbers: it allows us to specify multiple pages to print. If we tried putting page numbers in without the double quotes we’d get a line of code that looks like this:

objWord.PrintOut ,,,,,,,,2,4,6,,,,"c:\scripts\test.doc"

Is that bad? You bet it is. Count the parameters, and you’ll see that c:\scripts\test.doc is no longer parameter 13. That means our script is not going to print Test.doc. Period. Make sure you put double quotes around the page numbers.

What’s that? Did someone say, “How about a range of pages, like pages 5 through 10?” All you had to do was ask:

objWord.PrintOut ,,,,,,,,"5-10",,,,"c:\scripts\test.doc"

Very cool. Here’s another useful parameter: Copies. Suppose you need to print 10 copies of your document. No problem: just specify the number of copies as parameter number 8 (double quotes not required in this case):

objWord.PrintOut ,,,,,,,10,,,,,"c:\scripts\test.doc"

We know: it’s hard to believe that, prior to reading this article, you were printing documents by laboriously opening each file and then clicking the Print button. Good news: those days of tedium and drudgery are long gone! Had people known 60 years ago that someday you’d be able to write a script that prints 10 copies of a Word document, well, the term “paperless office” would never have been invented.