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...
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.