PowerShell: Dynamically Color PosH Generated HTML:Part 1
PowerShell: Dynamically Color PosH Generated HTML:Part 2
PowerShell: Dynamically Color PosH Generated HTML:Part 3
In the first part of this article I discussed using CSS styles, table ids and classes to colorize individual tables. I ended with a question about how we might be able to colorize individual rows of a table in a way that would show up in an email message.
How about coloring individual lines? Can we use this to set a lines color depending on the value of a column? Of course. Next time I will show how easy it is to do that although I have already given you almost all of the pieces for doing it. We just need about three more lines of code and some knowledge about how XML works and how to make HTML do some of the work for us.
Here is the code that will colorize the individual rows based on a columns value in that row.
If you remember from before we loaded the HTML fragment into an XML DOM for manipulation. We will use the same DOM to find and colorize the rows.
$rows=$xml.table.selectNodes('//tr')
for($i=1;$i -lt $rows.count; $i++){
$value=$rows.Item($i).LastChild.'#text'
if($value.Length -gt 0 -and [int]$value -le $threshhold){
Write-Host "Candidate found - setting color to red at $value" -fore green
$attr=$xml.CreateAttribute('style')
$attr.Value='background-color: red;'
[void]$rows.Item($i).Attributes.Append($attr)
}
}
As you can see we are just adding an attribute to the row.
First we find all of the row objects which are represented by the ‘tr’ tag:
$rows=$xml.table.selectNodes('//tr')
This is the XPath that will return all rows of a table. Next I enumerate the rows but skip the first row as it is the header. I use an explicit ‘for’ loop because we need the index to return the row object. The index is $i and is incremented in the ‘for’ statement. The index allows us to dereference the ‘#text’ node of the ‘last child’ which is the end column of the row.
$value=$rows.Item($i).LastChild.'#text'
Now that I have the value of the column it is time to test the value against our ‘threshold’. We have to cast it to an integer for this to work correctly. We also need to filter out all nodes that may be blank so I check for zero length.
if($value.Length -gt 0 -and [int]$value -le $threshhold){
Once we find a column that meets our criteria we can add our attributes and set it as a color style: This is done by creating an attribute named ‘style’ and assigning its value to be ‘background-color: red;’ just like we would type it into the HTML tag
$attr=$xml.CreateAttribute('style')
$attr.Value='background-color: red;'
There we have successfully edited HTML without playing with strings again. Creating and modifying HTML this way prevents breaking the HTML because the XML DOM will never generate broken XML or broken XHTML.
Send Email Table With Rows Colored to Show Alerts
$threshhold=10
$html=gwmi win32_logicaldisk |
Select-Object __SERVER,deviceid,@{N='PercentFree';E={[math]::Round($_.Freespace/$_.Size * 100,0)}} |
ConvertTo-Html -Fragment
$xml=[xml]$html
$rows=$xml.table.selectNodes('//tr')
for($i=1;$i -lt $rows.count; $i++){
$value=$rows.Item($i).LastChild.'#text'
if($value.Length -gt 0 -and [int]$value -le $threshhold){
Write-Host "Candidate found - setting color to red at $value" -fore green
$attr=$xml.CreateAttribute('style')
$attr.Value='background-color: red;'
[void]$rows.Item($i).Attributes.Append($attr)
}
}
$html=$xml.OuterXml|Out-String
$style='<style type=text/css>#diskTbl { background-color: blue; }</style>'
$body=ConvertTo-Html -head $style -body $html -Title "Disk Usage Report"|Out-String
$msg=@{
To=$to
From=$from
Subject="Disk usage report for $([datetime]::Now)"
BodyAsHTML=$true
Body=$body
}
This is what the email looks like:
Of course we can do more but look at what has been accomplished in only a couple of lines. We can use theses two techniques to add more tables all colorized and alerted or highlighted in any manner we choose and all without playing with strings. We can be as fancy as we like now because the data is being stuffed into html fragments for us and we can then decorate the data in a very controlled fashion.
What is next?
Next time I will attempt to combine these techniques into a web page with multiple tables and FTP it to a public web site. I will also show how to add external style sheets and how to inject VBScript or JavaScript into the pages generated by PowerShell. Maybe we can even look at PowerShell generated ASP.NET pages.
Until next time….
Part 1: http://tech-comments.blogspot.com/2012/07/powershell-dynamically-color-posh.html