Last Update: Sep 04, 2024 | Published: Jul 25, 2017
Everybody loves a nice HTML report. Am I right? Creating these reports in PowerShell is not that difficult. I thought I would offer up some tips and tricks you may not be aware of, including a few that I use all the time when I am creating reports. Some of these are documented in the help for ConvertTo-HTML. You do read the help, correct? Remember that ConvertTo-HTML does not create an actual file, just the HTML code. This is good for us. This means that we can modify the HTML on the fly and save the file when finished.
The first, and perhaps most important tip, is to be selective. Let’s take a simple command and output like this one.
You want to create an HTML version of this, so you run a command like this:
Get-EventLog -list | convertto-html | out-file d:tempa.htm
When you open the file in your browser, things are not quite what you expected.
This is because Convertto-Html, like Export-CSV and Export-Clixml, take the entire object. This is not just the default result you see on the screen. Remember, everything will be treated as a string. In my example, if I want a similar HTML file, I will have to recreate the output with Select-Object. This might require piping the original result to Get-Member to discover the “real” property names.
Get-Eventlog -List | Select @{Name="Max(K)";Expression = {$_.MaximumKilobytes }}, @{Name="Retain";Expression = {$_.MinimumRetentionDays }}, OverFlowAction,@{Name="Entries";Expression = {$_.entries.count}}, @{Name="Log";Expression = {$_.LogDisplayname}}
I always test without converting first.
I get a list instead of a table but at least the properties are correct. Let’s recreate the HTML file by piping the above to Convert-HTML and then Out-File overwriting the original and useless file.
This is much better compared to what I had originally. Although, since everything is being treated as a string, I can format the numeric values to look more like the original PowerShell output.
Get-Eventlog -List | Select @{Name="Max(K)";Expression = {"{0:n0}" -f $_.MaximumKilobytes }}, @{Name="Retain";Expression = {$_.MinimumRetentionDays }}, OverFlowAction,@{Name="Entries";Expression = {"{0:n0}" -f $_.entries.count}}, @{Name="Log";Expression = {$_.LogDisplayname}} | convertto-html -Title "Event Log Report" | out-file d:tempa.htm
I also went and added a title, so I get something more useful than HTML TABLE.
We are starting to build something with a bit more visual appeal. This leads me to another suggestion, take advantage of the pre and post content parameters.
When you pipe something to ConvertTo-HTML, the cmdlet generally creates a table. But you can insert additional HTML directives for things to put in before the main code and after. You can use as much html code as you want.
Get-Eventlog -List | Select @{Name="Max(K)";Expression = {"{0:n0}" -f $_.MaximumKilobytes }}, @{Name="Retain";Expression = {$_.MinimumRetentionDays }}, OverFlowAction,@{Name="Entries";Expression = {"{0:n0}" -f $_.entries.count}}, @{Name="Log";Expression = {$_.LogDisplayname}} | convertto-html -Title "Event Log Report" -PreContent "<H1>$($env:COMPUTERNAME)</H1>" -PostContent "<H5><i>$(get-date)</i></H5>" | out-file d:tempa.htm
I added an intro element using the H1 tag to display the computer name. Following the content, I am inserting the current date and time formatted with the H5 heading and italic tags.
Of course, you can always specify the path to a CSS file.
Get-Eventlog -List | Select @{Name="Max(K)";Expression = {"{0:n0}" -f $_.MaximumKilobytes }}, @{Name="Retain";Expression = {$_.MinimumRetentionDays }}, OverFlowAction,@{Name="Entries";Expression = {"{0:n0}" -f $_.entries.count}}, @{Name="Log";Expression = {$_.LogDisplayname}} | convertto-html -Title "Event Log Report" -PreContent "<H1>$($env:COMPUTERNAME)</H1>" -PostContent "<H5><i>$(get-date)</i></H5>" -CssUri C:scriptstext.css | out-file d:tempa.htm
If you want to play along at home, this is the CSS code I am using:
body { background-color:#E5E4E2; font-family:Monospace; font-size:10pt; } td, th { border:0px solid black; border-collapse:collapse; white-space:pre; } th { color:white; background-color:black; } table, tr, td, th { padding: 0px; margin: 0px ;white-space:pre; } table { margin-left:25px; } h2 { font-family:Tahoma; color:#6D7B8D; } .footer { color:green; margin-left:25px; font-family:Tahoma; font-size:8pt; }
I am using a file on my hard drive. This means that if anyone else were to look at the file, they would not get the same formatting. The solution is to use a CSS file path that everyone can reach. Check back later for the next article in this series.