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 Tuesday and 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.

Adding Pictures to a Microsoft Word Document

You know, regardless of what they might tell you, a picture is not worth 1,000 words. How do we know that? Well, back in our school days we once received an assignment of writing a 5,000-word essay. Logically enough, we submitted a document with 5 pictures in it instead. Trust us, a picture is definitely not worth 1,000 words.

Of course, even if pictures aren’t worth 1,000 words they still make for a very nice addition to a report; at the very least, you might want to include a logo any time you generate a report using a script. But can you add a picture to a Word document using a script?

We know: you assumed that this was a rhetorical question and the answer – as always – would be “yes.” To tell you the truth, though, for awhile we thought the answer was “no.” That’s because the Microsoft Word VBA Language Reference (which we just sort of glanced at) implied that the way to add a picture to a Word document was to use the Shape object and the AddPicture method. That made sense, so we tried the following script:

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

objSelection.TypeText "Here is a sentence preceding the picture."
objSelection.TypeParagraph()

Set colShapes = objDoc.Shapes
Set objShape = colShapes.AddPicture("C:\Scripts\Chart.gif")

objSelection.TypeParagraph()
objSelection.TypeText "Here is a sentence following the picture."
objSelection.TypeParagraph()

And here’s what happened when we actually ran the script:

Microsoft Word

The good news is that the picture showed up; the bad news is that it’s lying on top of our text. (If you run the script and then delete just the picture, you’ll find the text underneath.) Although we could think of a number of uses for this—Bad news? Just hide it beneath a cheerful picture—this wasn’t really the effect we were striving for.

What followed was a long, frustrating, and ultimately-fruitless quest to figure out how to get the picture to show up inline with the text rather than floating over the top of it. Oh, if only we had put the word inline in boldface before we started that quest. As it turns out, a Shape object is supposed to float over the top of everything. (Technically, a Shape object is created on the drawing layer, which is separate from the text layer.) We have no doubt that there’s a way to insert a Shape object and correctly position it so that it doesn’t float over the top of the text. However, we’re positive that a much better way to insert a picture inline with the text is to – sigh – use the InlineShape object instead:

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

objSelection.TypeText "Here is a sentence preceding the picture."
objSelection.TypeParagraph()

Set objShape = objSelection.InlineShapes.AddPicture("C:\Scripts\Chart.gif")

objSelection.TypeParagraph()
objSelection.TypeText "Here is a sentence following the picture."
objSelection.TypeParagraph()

And here’s what our document looks like after we ran this script:

Microsoft Word

That’s a little more like it.

Let’s take a look at the script and figure out how it works. We start off by creating an instance of the Word.Application object and setting the Visible property to True; that gives us a running copy of Word that we can see onscreen. We use the Add method to create a new, blank document, then use this line of code to create an instance of the Word Selection object:

Set objSelection = objWord.Selection

So far so good, huh? Next we type in a sentence and a paragraph return; all that’s for is to give us a little bit of text preceding our picture. That means it’s time to insert the graphic, something that takes just a single line of code:

Set objShape = objSelection.InlineShapes.AddPicture("C:\Scripts\Chart.gif")

As you can see, we reference the InlineShapes collection (rather than the Shapes collection) and then call the AddPicture method, passing AddPicture the path to the picture file. That’s all we have to do. We then type a paragraph return and some additional text; that’s just to prove that the picture really is inline and not floating over the top of everything.

Yes, much better. Is there a lesson here about how the Scripting Guys should read the documentation before blindly stumbling around writing scripts that don’t work? Well, you’d think so, wouldn’t you? But ….

Incidentally, you might have noticed that, when we inserted the picture, we also created an object reference to that picture (objShape). Does that matter? Not necessarily. However, this does make it easy for us to format the picture after the fact. For example, here’s a revised script that puts a border around the picture:

Const wdLineStyleSingle = 1

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

objSelection.TypeText "Here is a sentence preceding the picture."
objSelection.TypeParagraph()

Set objShape = objSelection.InlineShapes.AddPicture("C:\Scripts\Chart.gif")
objShape.Borders.OutsideLineStyle = wdLineStyleSingle

objSelection.TypeParagraph()
objSelection.TypeText "Here is a sentence following the picture."
objSelection.TypeParagraph()

It’s the same script as last time, with two additions. First, the script kicks off by defining a constant named wdLineStyleSingle and setting the value to 1; that tells Word the type of line we want to use when drawing the border. Later, we use this line of code to configure the OutsideLineStyle for our picture:

objShape.Borders.OutsideLineStyle = wdLineStyleSingle

Oh, yeah: we also added a couple extra paragraph returns, just to put a little more space between the picture and the text.

How cool is that? This cool:

Microsoft Word

Granted, it’s not 1,000 words worth of cool. But that should be worth at least 700 or 800 words, wouldn’t you think?