Word Automation in Python (for testing etc.)

I have been doing some development of an Office based COM plugin (Word, Excel etc), and have been wanted to do some unit testing of it for a long time. Given that the majority of the code is in VB, it doesn’t lend itself to good test harnesses.

I then realised that I might be able to do something in Python which has excellent COM interfaces. The main pre-requisite was a COM control to look for windows appearing etc for which I used the excellent AutoIt Control.

The thing that took a little investigation was the realisation that you often can’t drive menu options in Word very easily via keystrokes. I then realised that I could drive them by finding the menu controls and directly executing them.

Demo

The following script does a simple demo. Comments at end.

from win32com.client import Dispatch, GetActiveObject
import pythoncom
import threading

class MenuCommand(threading.Thread):
    def __init__(self, menu_name, option):
        threading.Thread.__init__(self)
        self.menu_name = menu_name
        self.option = option

    def run(self):
        pythoncom.CoInitialize()
        self.wd = GetActiveObject("Word.Application")
        self.wdapp = self.wd.Application
        self.menu = self.wdapp.CommandBars(self.menu_name)
        print self.menu.Name
        self.ctl = self.menu.Controls(self.option)
        print self.ctl.Caption
        if not self.ctl.Enabled:
            self.ctl.Enabled = True
        self.ctl.Execute()
        pythoncom.CoUninitialize()

auto = Dispatch('AutoItX3.Control')
# First we stop any running version of Word to avoid messing things up
try:
    wd = GetActiveObject("Word.Application")
    wd.Quit()
except:
    pass
wd = Dispatch('Word.Application')	# Create a Word OLE object
wd.Application.Documents.Open(r'C:\work\fred-new1.doc')

t = MenuCommand("Help", "&About Microsoft Office Word")
t.start()

title = 'About Microsoft Office Word'
print "waiting window active"
if auto.WinWaitActive(title, '', 5)
	print "window active"
	auto.WinActivate(title, '')
	auto.Send("{ENTER}")
	info = auto.ClipGet()
	print info
wd.Application.Quit()

Comments

Note that I execute the menu command in its own thread, since if not, the call to execute it will block synchronously and I then can’t check to see if the Window is there or not and click any buttons etc.

In my working version, I also have a similar utility class to open files and suchlike things.

The above has allowed to me to put quite a lot of testing around my app driven by fairly simple keystroke sending and copying things out via the clipboard to see if commands were successful or not.

http://www.robertcowham.com/blog/wp-content/plugins/sociofluid/images/digg_48.png http://www.robertcowham.com/blog/wp-content/plugins/sociofluid/images/reddit_48.png http://www.robertcowham.com/blog/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://www.robertcowham.com/blog/wp-content/plugins/sociofluid/images/technorati_48.png
blog comments powered by Disqus