#requires -version 2.0 # ============================================================================================== # # Microsoft PowerShell Source File -- Created with SAPIEN Technologies PrimalScript 2009 # # NAME: Out-MSWord.ps1 # v2.0 # # AUTHOR: Jeffery Hicks # http://jdhitsolutions.com/blog # DATE : 9/17/2009 # # COMMENT: Pipe cmdlet output to this function and create a MS Word document. You must have # Microsoft Word installed. This has been tested with Microsoft Word 2007. If you don't specify # a filename, Microsoft Word will open upon completion and you can manually save the document. # Or you can specify a filename along with optional parameters -append or -noclobber. The # -noclobber parameter will not overwrite any existing files. Otherwise, if you specify a file # and it already exists, it will be overwritten. # The -Tee parameter will write piped input as well as send it to the Word file. # You can also specify font size, name and color for the document body and footer. The defaults are # 8pt Consolas # This script and functions requires PowerShell v2.0 # DISCLAIMER AND WARNING: # THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY # KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. # TEST THOROUGHLY IN A NON-PRODUCTION ENVIRONMENT. IF YOU DON'T KNOW WHAT THIS # SCRIPT WILL DO...DO NOT RUN IT! # # ============================================================================================== Function Out-MSWord { #requires -version 2.0 <# .Synopsis Accept pipelined input from a PowerShell expression and write output to a Microsoft Word document. .Description Pipe cmdlet output to this function and create a MS Word document. You must have Microsoft Word installed. This has been tested with Microsoft Word 2007. If you don't specify a filename, Microsoft Word will open upon completion and you can manually save the document. You can specify a filename along with optional parameters -append or -noclobber. The -noclobber parameter will not overwrite any existing files. Otherwise, if you specify a file and it already exists, it will be overwritten. The -Tee parameter will write piped input to the console as well as send it to the Word file. You can specify font size, name and color for the document body and footer. The defaults are 8pt Consolas. You will get best results using a fixed width font like Courier New or Lucida Console. Page numbering is automatically defined for the lower right corner of each page. If you don't specify a footer it defaults to Printed [datetime]. .Parameter Path The path and filename for the new Microsoft Word document. .Parameter InputObject Pipelined objects passed to this function. .Parameter Tee Display objects in the console and write to the Word document. .Parameter Append Append data to the Microsoft Word document .Parameter NoClobber Don't overwrite the Microsoft Word document if it already exists. .Parameter Font Font name to use in the document body. Default is Consolas. .Parameter FontSize Font size to use in the document body. Default is 8. This parameter has an alias of Size. .Parameter FontColor Font color to use in the document body. Valid choices are Auto,Black,Blue,Green,Red,Teal,Violet, and Yellow. The default is Auto. This paramater has an alias of Color. .Parameter FooterText Text to use for the document footer. The default is Printed [datetime]. This parameter has an alias of Footer. .Parameter FooterFont Font to use for the document footer. Default is Consolas. .Parameter FooterSize Font size to use for the document footer. Default is 8. .Example get-service | where {$_.status -eq "running"} | Out-MSWord This will create a Microsoft Word document with a list of all running processes. .Example gwmi win32_bios | ow -path "c:\files\my3.doc" -noclobber Save the output from Get-WMIObject for the Win32_Bios class to a file called c:\files\my3.doc. If the file already exists it will not be overwritten. .Example get-eventlog -list | ow c:\test\log.docx -tee Take the outpout from Get-Eventlog and not only save it to the specified file but also display the results in the console. This example assumes you are using the alias ow for the Out-MSWord function. .Example get-process | sort workingset -descending | where {$_.workingset -lt 100mb -and $_.workingset -gt 25mb} | ow c:\files\ps.doc -fontcolor yellow -font "Lucida Console" -fontsize 10.5 -append This expression will create a Word document of processes with a workingset of between 25MB and 100MB. The results will be appended to the file, ps.doc, written in a yellow Lucida Console 10.5 font. This example assumes you are using the ow alias for this function. .Example @((gwmi win32_operatingsystem),(gwmi win32_bios),(gwmi win32_computersystem)) | ow -footertext ("{0} captured: {1}" -f $env:computername,(get-date)) Take the output from the three Get-WMIObject expressions and write output to all of them to a Microsoft Word document. A custom footer will be included that shows the computername and the current datetime. .Example $file="c:\reports\eventreport.doc" C:\PS>"Eventlog report for $env:computername" | Out-MSWord $file -size 14 C:\PS>$events=get-eventlog System -newest 100 | group EntryType C:\PS>for ($i=0;$i -lt $events.count;$i++) { switch ($events[$i].name) { "Information" { Out-MSWord $file -input "Information Events" -size 10 -append $events[$i].group | format-list TimeWritten,EventID,Source,Message | Out-MSWord $file -color Green -append } "SuccessAudit" { Out-MSWord $file -input "Success Audit Events" -size 10 -append $events[$i].group | format-list TimeWritten,EventID,Source,Message | Out-MSWord $file -color Green -append } "Error" { Out-MSWord $file -input "Error Events" -size 10 -append $events[$i].group | format-list TimeWritten,EventID,Source,Message | Out-MSWord $file -color Red -append } "FailureAudit" { Out-MSWord $file -input "Failure Audit Events" -size 10 -append $events[$i].group | format-list TimeWritten,EventID,Source,Message | Out-MSWord $file -color Red -append } "Warning" { Out-MSWord $file -input "Warning Events" -size 10 -append $events[$i].group | format-list TimeWritten,EventID,Source,Message | Out-MSWord $file -color Yellow -append } } #end Switch } #end foreach In this example a formatted Microsoft Word document is created that list eventlog information for the local computer. Event log information is grouped by EntryType and then group is processed by using a For statement and a Switch construct. Event information is written to the Microsoft Word document in a corresponding font color. This example also shows how to insert text into the document by explicitly using the -InputObject parameter. .Inputs Accepts objects as pipelined input. .Outputs Microsoft Word document object .Link Out-Printer Out-File .Notes NAME: Out-MSWord VERSION: 2.0 AUTHOR: Jeffery Hicks LASTEDIT: September 18, 2009 #> [CmdletBinding()] #define the parameters param ( [Parameter(ValueFromPipeline=$False,Position=0,Mandatory=$False,HelpMessage="The filename and path for the saved Word document.")] [ValidateScript({Test-Path (split-path $_)})] [String]$Path, [Parameter(ValueFromPipeline=$True,Position=1,Mandatory=$True,HelpMessage="Pipelined input.")] [object[]]$InputObject, [Parameter(ValueFromPipeline=$False,Mandatory=$False, HelpMessage="If specified, write to the console and the Word document.")] [switch]$Tee, [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="If specified, append to output write to the Word document.")] [switch]$Append, [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="If specified, don't overwrite the existing Word document specified by `$path.")] [switch]$NoClobber, [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="The font family to use for the document body.")] [string]$Font="Consolas", [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="The font size to use for the document body.")] [Alias("Size")] [double]$FontSize=8, [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="The font color to use for the document body.")] [ValidateSet("Auto","Black","Blue","Green","Red","Teal","Violet","Yellow")] [Alias("Color")] [string]$FontColor="Auto", [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="Text to use for the footer.")] [Alias("Footer")] [string]$FooterText=("printed {0}" -f (Get-Date)), [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="The font to use for the document footer.")] [string]$FooterFont="Consolas", [Parameter(ValueFromPipeline=$False,Mandatory=$False,HelpMessage="The font size to use for the document footer.")] [double]$FooterSize=8 ) #end param definition BEGIN{ #define some MS Word variables $wdSeekMainDocument = 0 $wdSeekPrimaryFooter = 4 $wdSeekPrimaryHeader = 1 $wdAlignPageNumberCenter = 1 $wdAlignPageNumberInside = 3 $wdAlignPageNumberLeft = 0 $wdAlignPageNumberOutside = 4 $wdAlignPageNumberRight = 2 $wdStory = 6 #define color values $Auto = 0 $Black = 1 $Blue = 16711680 $Green = 32768 $Red = 255 $Teal = 8421376 $Violet = 8388736 $Yellow = 32896 # #select font color switch ($fontcolor) { "Auto" {$color=$Auto} "Black" {$color=$Black } "Blue" {$color=$Blue } "Green" {$color=$Green } "Red" {$color=$Red } "Teal" {$color=$Teal } "Violet" {$color=$Violet } "Yellow" {$color=$Yellow } default { #this line should never get called since there is data validation with the fontcolor parameter, but I'll leave it in #just in case Write-Warning "Invalid color choice: $fontcolor. Using Default. Valid color choices are: Black,Blue,Green,Red,Teal,Violet and Yellow." $color=$wdAuto} } #end Switch $ErrorActionPreference="SilentlyContinue" Trap { Write-Warning "There was an error. Make sure you have Microsoft Word installed and that you are specifying valid filename or path." Break } #create the MS Word COM object $word=New-Object -ComObject "Word.Application" -ea Stop #get document if -append if ($append) { #verify file exists and if so, open it if (Test-Path $path) { $doc=$word.documents.open($path) $blnNewFile=$False } else { #you asked to append to a file that doesn't exist so create a new one $doc=$word.Documents.add() $blnNewfile=$True } } else { #create a new document $doc=$word.Documents.add() $blnNewFile=$True } $selection=$word.Selection #get the footer $doc.ActiveWindow.ActivePane.view.SeekView=$wdSeekPrimaryFooter #set the footer $selection.HeaderFooter.Range.Text=$footerText #add page numbering $selection.HeaderFooter.PageNumbers.Add($wdAlignPageNumberRight) | Out-Null #get the footer and format font $footers=$doc.Sections.Last.Footers foreach ($footer in $footers) { if ($footer.exists) { $footer.range.font.name=$footerfont $footer.range.font.size=$footersize } } #end Foreach #return focus to main document $doc.ActiveWindow.ActivePane.view.SeekView=$wdSeekMainDocument #initialize an array to hold incoming objects $data=@() } #end BEGIN scriptblock PROCESS { #save incoming objects to a variable if ($InputObject) { $data+=$InputObject } else { $data+=$_ } #write piped object if -Tee if ($tee) { write $_ } } #end PROCESS scriptblock END { #convert data to string $text=$data | Out-String #only write to the file if $text exists if ($text) { if (!$blnNewFile) #the file has been opened before { #jump to the end $selection.Endkey($wdStory) | Out-Null #insert blank lines $selection.TypeParagraph() $selection.TypeParagraph() } #end if !$blnNewFile #set font and paragraph settings $selection.font.name=$font $selection.font.size=$fontsize $selection.font.color=$color $selection.paragraphFormat.SpaceBefore = 0 $selection.paragraphFormat.SpaceAfter = 0 #add the text to the document $selection.TypeText($text.Trim()) if ($path) { #don't overwrite if -noclobber was specified if ($noclobber) { #does file exist? if (Test-path $path) { Write-Warning "-NoClobber specified and $path exists" #show the document so you can review and/or save $word.visible=$True } #end if item exists else { $doc.SaveAs([ref]$path) $word.quit() } } #end if $noclobber else { $doc.SaveAs([ref]$path) $word.quit() } } #end if $path else #no filepath { #jump to the beginning of the document $selection.Homekey($wdStory) | Out-Null #show the document so you can review and/or save $word.visible=$True } } #end if $text else { Write-Warning "No data to write." #turn off alerts $word.displayAlerts=0 #close without saving $doc.close([ref]$Word.WdSaveOptions.wdDoNotSaveChanges) #exit Microsoft Word $word.quit() } } #end END scriptblock } #end Function #create an alias Set-Alias ow Out-MSWord Get-Alias ow