Word Hacks [Electronic resources]

Andrew Savikas

نسخه متنی -صفحه : 162/ 122
نمايش فراداده

Hack 87 Hack Word from Ruby

Use Word from Ruby to create attractive printouts of HTML documents on the fly.

Ruby is a newer language than Perl or Python, and it works very well as a tool to automate Word. This hack shows you how to use Ruby to import an HTML document into Word, tweak the formatting, save the document in native Word format, and print it out to the default printer. This hack assumes you have a file named C:\resumel on your system. It also assumes that you have Ruby installed on your system and that you can run Ruby scripts from the DOS command line.

To download a free version of Ruby for Windows, go to [Hack #84], you can access Word from within a Ruby script using the win32ole module, which the standard Windows Ruby distribution includes.

9.9.1 Hello, Word

The following Ruby script creates a new document, inserts some text, and applies the Heading 1 style to the text:

require 'win32ole'
wd = WIN32OLE.new('Word.Application')
wd.Visible = 1
doc = wd.Documents.Add( )
doc.Range.InsertAfter("Hello, Word")
doc.Range.Style = "Heading 1"

Save this script as C:\HelloFromRuby.pl and run it from the DOS command line as follows:

> Ruby HelloFromRuby.pl

As discussed in [Hack #84], Word objects created as COM servers aren't visible by default. You must explicitly set the Visible property to 1 if you want Word to appear onscreen.

9.9.2 Controlling Word Interactively

Ruby includes an interactive command-line interpreter, which you launch by typing irb at a DOS prompt:

> irb

The interactive Ruby shell launches, and the prompt changes as follows:

irb(main):001:0>

You can now execute Ruby commands interactively, which is a useful way to experiment with Word because you can see the results in real time. Enter the following sequence of commands after you launch the Ruby shell (the commands you type are shown in bold, with the shell's response in plain text):

irb(main):001:0> require 'win32ole'
=> true
irb(main):002:0> w = WIN32OLE.new('Word.Application')
=> #<WIN32OLE:0x28cc070>
irb(main):003:0> w.Visible = 1
=> 1

At this point, a new Word window opens, although Word doesn't create a new, blank document (which makes sense considering that this instance of Word runs invisibly by default). Though no blank document is created, all the global templates in the STARTUP folder [Hack #50] are loaded.

With the Ruby shell running and a Word window open, you can actually go back and forth between the two as you fiddle with Word. However, if from within Word you modify or remove objects currently referenced from Ruby, those Ruby objects may become unstable and behave unexpectedly.

Now, create a new, blank document and insert a few lines of text (this time, only the commands you type are shown; the shell's response is omitted for the rest of this section):

irb(main):004:0> doc = w.Documents.Add( )
irb(main):005:0> rng = doc.Range( )
irb(main):006:0> rng.InsertAfter("To be or not to be - Shakespeare\n")
irb(main):007:0>rng.InsertAfter("Do be do be do be do - Sinatra")

Using the interactive interpreter, you can position the DOS window next to or on top of the Word window and watch your Ruby commands control Word, as shown in Figure 9-12.

Figure 9-12. Controlling Word interactively from Ruby

To close the document and quit Word, enter the following:

irb(main):008:0> doc.Close( )
irb(main):009:0> wd.Quit( )

Word will not close the document until you choose whether or not to save it. If you run Word invisibly and try the same thing, Word will stay hidden but its Save As dialog will appear. If you write scripts that run Word invisibly, take care to avoid situations that might launch an unexpected dialog (and probably cause an error in your script). To avoid this particular one, you must either save the document or make Word think you've saved it. The following code shows both scenarios:

irb(main):009:0>  doc.SaveAs('C:\Documents\Quotes.doc') # Save the file
irb(main):010:0>  doc.Saved = 1 # Or fool Word into thinking it's been saved

9.9.3 Running the Hack

Word does an excellent job of importing HTML filesespecially ones that use simple, standard HTML tags mapped to Word's built-in styles. You can easily translate existing HTML files into a useful printed format by importing them into Word. This process can be automated with Ruby and COM.

As an example, this hack will show you this process using an HTML file you might already have, and which is probably more up-to-date than any print version: your resume.

Again, this hack assumes you have a file named C:\resumel on your system. The code presented below starts Word, opens the file, changes the appearance of the Heading 2 and Hyperlink styles, saves the document, and prints it out to your default printer:

require 'win32ole'
wrd = WIN32OLE.new('Word.Application')
confirm = wrd.Options.ConfirmConversions
wrd.Options.ConfirmConversions = 0
wrd.Visible = 1
doc = wrd.Documents.Open("C:/resumel")
sty = doc.Styles("Heading 2")
sty.Font.Size = 18
sty.Font.Italic = 0
sty = doc.Styles('Hyperlink')
sty.Font.Underline = 0
sty.Font.Color = -16777216 
sty.Font.Italic = 1
doc.SaveAs('FileName' => "C:/resume.doc", 'FileFormat' => 0)
doc.PrintOut
doc.Close( )
wrd.Options.ConfirmConversions = confirm
wrd.Quit( )

Save this script as resumeprinter.rb and run it from a DOS command line:

> ruby resumeprinter.rb

A few parts of this script deserve closer attention.

9.9.3.1 Confirming conversions

Select ToolsOptions, click the General tab, and check the "Confirm conversion at open" box. With this option checked, Word will prompt you before opening a file not in the .doc format. If this setting is enabled when the script opens the file, a dialog will appear, even though the script runs Word invisibly. To make sure the resumel file opens without confirming the conversion, this script explicitly sets the ConfirmConversions option to False. Before doing so, the script stores the current state in a variable named confirm; it then resets the option before it exits.

9.9.3.2 Word constants

The Ruby script doesn't have access to Word's constants (such as wdUnderlineNone and wdColorAutomatic) via COM. You must use their actual values, as this script does for the Underline and Color properties of the Hyperlink style. To get the value of a constant, query its value in the Immediate window [Hack #2] of the Visual Basic Editor, as shown in Figure 9-11.

9.9.3.3 Named arguments

When using Word from Ruby, as with VBA, you can use named arguments, which means you can specify the values for a function or method by keyword. When you don't use named arguments, each value passed as an argument must be in a particular order. For example, the syntax for the MsgBox function in VBA is:

MsgBox(prompt[, buttons] [, title] [, helpfile, context])

If you call this function in VBA without using named arguments, the function expects and interprets the values in the order specified by its syntax. To tell the function to display the prompt "Hello, World" with "Message in a Box" as the dialog's title, but without specifying a button type, insert the following:

Msgbox "Hello, World", ,"Message in a Box"

Notice the empty value in between the two commas. It tells Word to use its default value for the buttons argument. If you left out that empty value, Word would try to use "Message in a Box" as the buttons value, which would cause an error. When you use the named argument syntax in VBA, you can do the same thing in a more readable way, and in any order you choose:

MsgBox Title:="Message in a Box", Prompt:="Hello, World"

Word uses its default settings for any of the arguments not specified. When using Word objects and methods from Ruby, you can use a similar syntax, as shown in the following line taken from the earlier resumeprinter.rb script:

doc.SaveAs('FileName' => "C:/resume.doc", 'FileFormat' => 0)