Prof. Powershell
Get the Word Out
PowerShell is all-seeing. Even Word document data can be viewed using some PowerShell cmdlets.
- By Jeffery Hicks
- 09/29/2009
In today's lesson we'll look at using the Microsoft Word COM object in Windows PowerShell to handle a few basic tasks. First off we need to create an object to represent Microsoft Word using the New-Object cmdlet:
PS C:\>
$word=new-object -COM "word.application"
If you pipe $word to Get-Member you'll see a wealth of information. Word is really running, even if you don't see it:
PS Z:\> ps winword
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
749 13 18320 41948 237 11.83 2712 WINWORD
If you really want to see the application, make it visible:
PS C:\> $word.visible=$True
You should now see an empty Word window. Let's open a document:
PS C:\> $doc=$word.Documents.Open("z:\more fun with get-command.docx")
I'm not going to make any changes, but perhaps I'd like some statistics like the number of words and pages:
PS C:\> $doc.computestatistics("wdStatisticWords")
615
PS C:\> $doc.computestatistics("wdStatisticPages")
3
Pretty neat if I do say so myself. The document object has some other properties you might want to experiment with. Pipe the object to Get-Member. When you are finished, close the document and quit the application:
PS C:\> $doc.close()
PS C:\> $word.quit()
Of course what I can do a single document I should be able to do for many. How about a stats report on the Word docs in a given folder?
dir z:\*.docx | foreach -begin {
$word=new-object -com word.application } -process {
$doc=$word.Documents.Open($_.fullname)
$_ | Add-Member NoteProperty -name "Pages" -value $doc.computestatistics("wdStatisticPages")
$_ | Add-Member NoteProperty -name "Words" -value $doc.computestatistics("wdStatisticWords") -passthru
$doc.close() } -end {$word.quit()} | Select Fullname,CreationTime,LastWriteTime,Pages,Words
I'm piping the file object to a ForEach construct with Begin, Process, and End script blocks. The code in the Begin script block executes once before any pipelined objects are processed. I only need one Word application object so I'll create it here.
For each file object, I'll create a document object. The file object gets piped to Add-Member where I define a custom property using my Word statistic values.
The tricky part to remember is to add -Passthru after the last Add-Member so the object is written to the pipeline.
The end of each Process block ends with closing the file. After all files have been processed the End script block executes once, quitting Word.
When I execute I'll get output like this for each Word document:
FullName : Z:\Get The Word Out.docx
CreationTime : 8/26/2009 3:15:01 PM
LastWriteTime : 8/26/2009 3:15:01 PM
Pages : 1
Words : 229
Or perhaps you'd like to print each document? That's just as easy. I'll leave you with this:
dir z:\*.docx | foreach -begin {
$word=new-object -com word.application } `
-process {
$doc=$word.Documents.Open($_.fullname)
write-host "Printing $($_.fullname)" -foregroundcolor Green
$doc.printout()
$doc.close() } `
-end {
$word.quit()
}
although I suggest you try this with a folder with only a few short Word documents.
About the Author
Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.