Hey, Scripting Guy! We have a folder full of Word documents in which the author had an unfortunate tendency to use a strange font from time-to-time. How can I use a script to go in and replace just that strange font with Arial?
— Z D-F
Hey, Z D-F. You know, when “desktop publishing” first came into vogue, the Scripting Guy who writes this column was in graduate school at the University of Washington. As such, he remembers reading several scholarly articles showing how desktop publishing was perhaps the worst thing that ever happened to business, at least from a productivity standpoint. Why? Well, back in the old days, before desktop publishing, anyone who needed to produce a document simply rolled a sheet of paper into a typewriter and typed it up. There was no concern about layout, no fiddling with graphics, and, above all, no debates about which font to use.
The font issue was especially interesting, because it led to more problems than just people wasting time trying different fonts and sizes. That was bad enough in and of itself, but the issue was exacerbated by the fact that most people simply aren’t very good at graphic design. Not only did they waste time messing around with fonts, but more often than not they ended up choosing the wrong fonts, thus producing a document that was much harder to read. In other words, productivity was lost not only in writing the documents but also in reading the documents.
Isn’t progress wonderful?
So can scripts help us to regain this lost productivity? Heck no, not unless you can write a script that will go around, bop people on the head, and tell them, “Hey, stop using these fonts that no one can read!” But at least a script can help us go in and replace crazy fonts with something a little more readable and a little more professional:
Const wdReplaceAll = 2Set objWord = CreateObject(“Word.Application”) objWord.Visible = True
Set objDoc = objWord.Documents.Open(“C:\Scripts\Test.doc”) Set objSelection = objWord.Selection
objSelection.Find.Font.Name = “Gigi” objSelection.Find.Forward = TRUE
objSelection.Find.Replacement.Font.Name = “Arial”
objSelection.Find.Execute “”, ,False, , , , , , , ,wdReplaceAll
To begin with, Z D-F, we’re assuming that you have a document that looks something like this:
As you can see, the main body of the document is written in Times New Roman, which is fine. However, the section headings are written in a font named Gigi; a pretty good argument can be made that fonts with names like Gigi should never be used in business proposals or other formal documents. Because of that what you’d like to do is search this document and replace the Gigi font with Arial. The tricky part, of course, is that you only want to replace Gigi; anything written in Times New Roman should be left alone. Believe it or not, our script does just that.
So how does our script do that? Well, to begin with, we define a constant named wdReplaceAll and set the value to 2; we’ll use this constant to tell the script to replace any and all the instances of the Gigi font. We then use this block of code to create a visible instance of the Word.Application object, open the document C:\Scripts\Test.doc, and then create an instance of the Word Selection object:
Set objWord = CreateObject(“Word.Application”) objWord.Visible = TrueSet objDoc = objWord.Documents.Open(“C:\Scripts\Test.doc”) Set objSelection = objWord.Selection
You’re right: that is a lot of stuff packed into four lines of code, isn’t it? No wonder we’re so tired this morning!
At this point we’re ready to start having some fun. In order to do a find-and-replace operation in Word we need to assign values to two different objects: the Find and Replacement objects. With that in mind, we thus use these two lines of code to assign values to the Find object:
objSelection.Find.Font.Name = “Gigi” objSelection.Find.Forward = TRUE
Nothing too terribly complicated here. We want to search for all instances of the Gigi font, so in line one we assign the value Gigi to the Find.Font.Name property. And because we’re starting with the cursor positioned at the beginning of the document we then assign the value True to the Find.Forward property; this tells the script to move forward through the document when searching (that is, to start at page 1 and continue on through the end of the document).
That’s the only search criteria we need to specify. As you can see, we don’t even specify the text we want to search for; that’s because we don’t care about the text itself. All we’re looking for here is the formatting.
As everyone knows, it takes two to tango; turns out that it also takes two to do a find and replace operation. That means that, having configured the Find object, our next step is to configure the Replacement object. This turns out to very easy; all we need to do is specify that the replacement font is Arial:
objSelection.Find.Replacement.Font.Name = “Arial”
In other words, we’ve now told the script to start at the beginning of the document, look for all instances of the Gigi font, and replace all those instances with Arial. But rather than sit here and talk about what our script could do why don’t we just go ahead and do it:
objSelection.Find.Execute “”, ,False, , , , , , , ,wdReplaceAll
All we’re doing here is calling the Execute method, which tells the script to actually go do the find and replace operation. As you can see, we need to pass a crazy-looking set of parameters to this method:
“”, ,False, , , , , , , ,wdReplaceAll
What does all that mean? Well, for detailed information about the Execute method and its parameters you should check the Microsoft Word VBA Language Reference on MSDN. For now we’ll note that the very first parameter indicates the text we want to search for. Because we’re searching only for formatting, the Word convention is to use an empty string (“”) to represent the search text. And you know the Scripting Guys: we always follow the standard conventions.
The second parameter has to do with case sensitivity. For this script case doesn’t matter; however, it’s crucial that the Execute parameters be passed by position. Admittedly, we aren’t going to use the second parameter. However, we can’t leave this parameter out altogether; if we did then the third parameter, which we do need, wouldn’t be the third item in the parameter list. Therefore, we leave the second parameter blank, inserting a blank space followed by a comma to indicate that this represents parameter 2.
And yes, that is kind of confusing, isn’t it? Well, suppose we had a parameter list that looked like this:
1, 2, 3, 4
Suppose, further, that some hypothetical method requires four parameters; however, we only need to use parameters 1 and 4. Could we pass this hypothetical method a parameter string that looks like this:
1, 4
No, we can’t; after all, we list only two parameters here, and our method requires four parameters. Because of that we need to pass a parameter string that looks like this, with the blank spaces indicating that parameters 2 and 3 should be left alone:
1, , , 4
It’s the same thing with the Execute method.
Now, where we were? Oh, right. After inserting a blank space for parameter 2 we then set parameter 3 to False. The third parameter tells Word to search for whole words; if this is set to True (the default value) the font for certain items (like punctuation marks) might not get changed. We then have a series of blank parameters (again, representing parameters we don’t need for this script). Our parameter list then culminates with the constant wdReplaceAll, which tells Word to replace every instance of the Gigi font. Without this parameter Word will find and replace only the first instance of Gigi.
And what are we going to get when we run this script? We’re going to get this:
Hasta la vista, Gigi!
Actually you’re right: we shouldn’t gloat. After all, Gigi might be gone, but it’s not forgotten; no doubt this crazy font will turn up again sometime. But that’s all right. We’ll just keep running our script and – in the true spirit of the modern age – spend our time undoing everything that our fellow employees spent hours and hours doing in the first place.
Isn’t progress wonderful?
0 comments