miguello
miguello

Reputation: 584

How to send powershell script output to printer with formatting?

I need to send a script output (basically, agenda from my Outlook calendar filtered by category) that is made within the script to a printer. For the purpose of readability I'd like it to be formatted. At least print some words bold, some italics, maybe change font. The text is assembled from a custom object and might looks something like this:

text = 
@"
Monday

Meeting with Joe : 07:00 - 08:00
Meeting with Ann : 8:30 - 09:00

Tuesday

No meetings
"@

I would ideally like it to print something like this:


Monday

Meeting with Joe : 07:00 - 08:00

Meeting with Ann : 8:30 - 09:00

Tuesday

No meetings


What I have so far (leaving the code pulling calendar events out):

text = 
@"
Monday

Meeting with Joe : 07:00 - 08:00
Meeting with Ann : 8:30 - 09:00

Tuesday

No meetings
"@

Add-Type -AssemblyName System.Drawing
$PrintDocument = New-Object System.Drawing.Printing.PrintDocument
$PrintDocument.PrinterSettings.PrinterName = 'Microsoft Print to PDF'
$PrintDocument.DocumentName = "PipeHow Print Job"
$PrintDocument.DefaultPageSettings.PaperSize = $PrintDocument.PrinterSettings.PaperSizes | Where-Object { $_.PaperName -eq 'Letter' }
$PrintDocument.DefaultPageSettings.Landscape = $true

$PrintPageHandler =
{
    param([object]$sender, [System.Drawing.Printing.PrintPageEventArgs]$ev)

    $linesPerPage = 0
    $yPos = 0
    $count = 0
    $leftMargin = $ev.MarginBounds.Left
    $topMargin = $ev.MarginBounds.Top
    $line = $null

    $printFont = New-Object System.Drawing.Font "Arial", 10

    # Calculate the number of lines per page.
    $linesPerPage = $ev.MarginBounds.Height / $printFont.GetHeight($ev.Graphics)

    # Print each line of the file.
    while ($count -lt $linesPerPage -and (($line = ($text -split "`r`n")[$count]) -ne $null))
    {
        $yPos = $topMargin + ($count * $printFont.GetHeight($ev.Graphics))
        $ev.Graphics.DrawString($line, $printFont, [System.Drawing.Brushes]::Black, $leftMargin, $yPos, (New-Object System.Drawing.StringFormat))
        $count++
    }

    # If more lines exist, print another page.
    if ($line -ne $null) 
    {
        $ev.HasMorePages = $true
    }
    else
    {
        $ev.HasMorePages = $false
    }
}

$PrintDocument.add_PrintPage($PrintPageHandler)
$PrintDocument.Print()

which I took from the corresponding articles on the internet, replacing StremReader from the file by line-by-line reading the multiline string. How would I format text like that? Put some markers in the text, just like I do here or in HTML? and then parse them within $PrintPageHandler? Would I use $printFont for that or StringFormat in DrawString?

Please give me some direction to keep digging...

Upvotes: 1

Views: 1521

Answers (1)

PowerShellGuy
PowerShellGuy

Reputation: 801

Hm, because you have outlook, I'm going to assume you have Word as well. Using the Word COM object is the only really easy way I can think of doing what you're trying to do.

#didn't know how you generated the calender info, so I took liberties here,  using nested hashtables
$calendarStuff = @{

    week1 = @{
        Monday =  @(
            "Meeting with Joe : 07:00 - 08:00",
            "Meeting with Ann : 8:30 - 09:00"
        );
        Tuesday = @("No meetings")
    }

}

#path where to save the doc
$docPath = "C:\temp\printTestThing.docx"
# instantiation of the com-object. It's by default not visible
$wordCom = New-Object -ComObject Word.Application
# uncomment this to see what's going on
#$wordCom.visible = $true

# creates and selects the word document we'll be working with
$doc = $wordCom.Documents.Add()
$selection = $wordcom.Selection

# go through and grab each week
foreach($week in $calendarStuff.Keys)
{
    # go through each week and grab the days
    foreach($day in $calendarStuff[$week].keys)
    {
        # Apply the style 'Heading 1' to what we're about to type
        $selection.Style = "Heading 1"
        # type out what the day is
        $selection.TypeText($day)
        # make a paragraph
        $selection.TypeParagraph()
        # switch the style back to normal
        $selection.Style = "Normal"
        foreach($thing in $calendarStuff[$week][$day])
        {
            # type out what the event is, prepending it with a 'tab' character
            $selection.TypeText("`t" + $thing)
            # make a paragraph
            $selection.TypeParagraph()
        }
    }

}
# print the doc
Start-Process -FilePath $docPath -Verb print

You can add way more customization if you want, but hopefully this is the catalyst you needed.

Example of what this looks like if printed to pdf enter image description here

Upvotes: 1

Related Questions