PSHTMLTools.psm1
Function Set-AlternatingRow { <# .SYNOPSIS Simple function to alternate the row colors in an HTML table .DESCRIPTION This function accepts pipeline input from ConvertTo-HTML or any string with HTML in it. It will then search for <tr> and replace it with <tr class=(something)>. With the combination of CSS it can set alternating colors on table rows. CSS requirements: .odd { background-color:#ffffff; } .even { background-color:#dddddd; } Classnames can be anything and are configurable when executing the function. Colors can, of course, be set to your preference. This function does not add CSS to your report, so you must provide the style sheet, typically part of the ConvertTo-HTML cmdlet using the -Head parameter. .PARAMETER Line String containing the HTML line, typically piped in through the pipeline. .PARAMETER CSSEvenClass Define which CSS class is your "even" row and color. .PARAMETER CSSOddClass Define which CSS class is your "odd" row and color. .EXAMPLE $Report | ConvertTo-HTML -Head $Header | Set-AlternateRow -CSSEvenClass even -CSSOddClass odd | Out-File .\HTMLReport.html $Header can be defined with a here-string as: $Header = @" <style> TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;} TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;} TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;} .odd { background-color:#ffffff; } .even { background-color:#dddddd; } </style> "@ This will produce a table with alternating white and grey rows. Custom CSS is defined in the $Header string and included with the table thanks to the -Head parameter in ConvertTo-HTML. .EXAMPLE $RawHTML = $Report | ConvertTo-HTML -Head $Header $FinalHTML = Set-AlternateRow -CSSEvenClass even -CSSOddClass odd -InputObject $RawHTML $FinalHTML | Out-File .\HTMLReport.html .NOTES Author: Martin Pugh Twitter: @thesurlyadm1n Spiceworks: Martin9700 Blog: www.thesurlyadmin.com Changelog: 1.5 Added ability to specify HTML instead of piping it. Updated look of the script and added an additional example to help. 1.1 Modified replace to include the <td> tag, as it was changing the class for the TH row as well. 1.0 Initial function release .LINK http://community.spiceworks.com/scripts/show/1745-set-alternatingrows-function-modify-your-html-table-to-have-alternating-row-colors .LINK http://thesurlyadmin.com/2013/01/21/how-to-create-html-reports/ #> [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeline)] [string[]]$InputObject, [Parameter(Mandatory)] [string]$CSSEvenClass, [Parameter(Mandatory)] [string]$CSSOddClass ) Begin { $ClassName = $CSSEvenClass } Process { ForEach ($Line in $InputObject) { If ($Line.Contains("<tr><td>")) { $Line = $Line.Replace("<tr>","<tr class=""$ClassName"">") If ($ClassName -eq $CSSEvenClass) { $ClassName = $CSSOddClass } Else { $ClassName = $CSSEvenClass } } Write-Output $Line } } } Function Set-CellColor { <# .SYNOPSIS Function that allows you to set individual cell colors in an HTML table .DESCRIPTION To be used inconjunction with ConvertTo-HTML this simple function allows you to set particular colors for cells in an HTML table. You provide the criteria the script uses to make the determination if a cell should be a particular color (property -gt 5, property -like "*Apple*", etc). You can add the function to your scripts, dot source it to load into your current PowerShell session or add it to your $Profile so it is always available. To dot source: .".\Set-CellColor.ps1" .PARAMETER Color Name or 6-digit hex value of the color you want the cell to be .PARAMETER InputObject HTML you want the script to process. This can be entered directly into the parameter or piped to the function. .PARAMETER Filter Specifies a query to determine if a cell should have its color changed. $true results will make the color change while $false result will return nothing. Syntax <Property Name> <Operator> <Value> <Property Name>::= the same as $Property. This must match exactly <Operator>::= "-eq" | "-le" | "-ge" | "-ne" | "-lt" | "-gt"| "-approx" | "-like" | "-notlike" <JoinOperator> ::= "-and" | "-or" <NotOperator> ::= "-not" The script first attempts to convert the cell to a number, and if it fails it will cast it as a string. So 40 will be a number and you can use -lt, -gt, etc. But 40% would be cast as a string so you could only use -eq, -ne, -like, etc. .PARAMETER Row Instructs the script to change the entire row to the specified color instead of the individual cell. .INPUTS HTML with table .OUTPUTS HTML .EXAMPLE get-process | convertto-html | set-cellcolor -Propety cpu -Color red -Filter "cpu -gt 1000" | out-file c:\test\get-process.html Assuming Set-CellColor has been dot sourced, run Get-Process and convert to HTML. Then change the CPU cell to red only if the CPU field is greater than 1000. .EXAMPLE get-process | convertto-html | set-cellcolor -color red -filter "cpu -gt 1000 -and cpu -lt 2000" | out-file c:\test\get-process.html Same as Example 1, but now we will only turn a cell red if CPU is greater than 1000 but less than 2000. .EXAMPLE $HTML = $Data | sort server | ConvertTo-html -head $header | Set-CellColor -Color red -Filter "cookedvalue -gt 1" PS C:\> $HTML = $HTML | Set-CellColor Server green -Filter "server -eq 'dc2'" PS C:\> $HTML | Set-CellColor Path Yellow -Filter "Path -like ""*memory*""" | Out-File c:\Test\colortest.html Takes a collection of objects in $Data, sorts on the property Server and converts to HTML. From there we set the "CookedValue" property to red if it's greater then 1. We then send the HTML through Set-CellColor again, this time setting the Server cell to green if it's "dc2". One more time through Set-CellColor turns the Path cell to Yellow if it contains the word "memory" in it. .EXAMPLE $HTML = $Data | sort server | ConvertTo-html -head $header | Set-CellColor -Color red -Filter "cookedvalue -gt 1" -Row Now, if the cookedvalue property is greater than 1 the function will highlight the entire row red. .NOTES Author: Martin Pugh Twitter: @thesurlyadm1n Spiceworks: Martin9700 Blog: www.thesurlyadmin.com Changelog: 2.0 Major rewrite, now only replaces the column you specify (finally). Property parameter has been eliminated. 1.5 Added ability to set row color with -Row switch instead of the individual cell 1.03 Added error message in case the $Property field cannot be found in the table header 1.02 Added some additional text to help. Added some error trapping around $Filter creation. 1.01 Added verbose output 1.0 Initial Release .LINK http://community.spiceworks.com/scripts/show/2450-change-cell-color-in-html-table-with-powershell-set-cellcolor #> [CmdletBinding()] Param ( [Parameter(Mandatory,Position=0)] [string]$Filter, [Parameter(Mandatory,Position=0)] [string]$Color, [Parameter(Mandatory,ValueFromPipeline)] [Object[]]$InputObject, [switch]$Row ) Begin { Write-Verbose "$(Get-Date): Function Set-CellColor begins" } Process { $InputObject = $InputObject -split "`r`n" ForEach ($Line in $InputObject) { If ($Line.IndexOf("<tr><th") -ge 0) { Write-Verbose "$(Get-Date): Processing headers..." $Search = $Line | Select-String -Pattern '<th ?.*?>(.*?)<\/th>' -AllMatches $Index = 0 $Property = $null ForEach ($Header in $Search.Matches) { If ($Filter -match $Header.Groups[1].Value) { $Property = $Header.Groups[1].Value Break } $Index ++ } If (-not $Property) { Write-Error "$(Get-Date): Unable to locate the column in your filter. Filter: $Filter" -ErrorAction Stop } Else { $Filter = $Filter -replace $Property,"`$Value" Try { $Oper = [scriptblock]::Create($Filter) } Catch { Write-Error "$(Get-Date): ""$Filter"" invalid because ""$_""" -ErrorAction Stop } } Write-Verbose "$(Get-Date): $Property column found at index: $Index" } If ($Line -match "<tr ?.*?><td ?.*?>(.*?)<\/td><\/tr>") { $Search = $Line | Select-String -Pattern '<td ?.*?>(.*?)<\/td>' -AllMatches #Determine if the column value is a number Try { [double]$Value = $Search.Matches[$Index].Groups[1].Value } Catch { #Nope, treat it like a string [string]$Value = $Search.Matches[$Index].Groups[1].Value } If (Invoke-Command $Oper) { If ($Row) { Write-Verbose "$(Get-Date): Criteria met! Changing row to $Color..." If ($Line -match "<tr style=""background-color:(.+?)"">") { $Line = $Line -replace "<tr style=""background-color:$($Matches[1])","<tr style=""background-color:$Color" } Else { $Line = $Line.Replace("<tr>","<tr style=""background-color:$Color"">") } } Else { Write-Verbose "$(Get-Date): Criteria met! Changing cell to $Color..." $Count = 0 $Pattern = ".*?" ForEach ($Column in $Search.Matches) { $Pattern = "$Pattern$($Column.Groups[1].Value)</td>.*?" If ($Count -eq $Index - 1) { Break } $Count ++ } $null = $Line -match $Pattern $StartsWith = $Matches.Values $NewLine = $Line -replace $StartsWith,'' $NewLine = $NewLine -replace '^<td ?(style="background-color:.*")?>.*?<\/td>',"<td style=""background-color:$Color"">$Value</td>" $Line = "$StartsWith$($NewLine)" } } } Write-Output $Line } } End { Write-Verbose "$(Get-Date): Function Set-CellColor completed" } } Function Set-GroupRowColorsByColumn { <# .SYNOPSIS Set rows to alternating colors based on the value of a cell .DESCRIPTION Rows will alternate color in a HTML table. **This is designed for use with ConvertTo-HTML and other HTML tables may not work with it.** I recommend sorting your data by the column you intend to use as a trigger. .PARAMETER InputObject Your HTML input, either specified directly or through pipeline. .PARAMETER ColumnName This is the column that you will trigger off of. Whenever this column changes the script will flip to the other color. .PARAMETER CSSEvenClass The Even color used in the report. This will be the starting color. .PARAMETER CSSOddClass The alternate color in the report. .EXAMPLE $Data = @" "From","To","LastRepliationAttempt","LastReplicationResult","LastReplicationSuccess" "corpdc101","CORPDC102","2/11/2015 12:57:47 PM","0","2/11/2015 12:57:47 PM" "corpdc101","CORPDC103","2/11/2015 12:57:45 PM","0","2/11/2015 12:57:45 PM" "corpdc101","CORPDC701","2/11/2015 12:50:36 PM","0","2/11/2015 12:50:36 PM" "corpdc101","CORPDC001","2/11/2015 12:50:36 PM","0","2/11/2015 12:50:36 PM" "corpdc101","CORPDC202","2/11/2015 12:50:35 PM","0","2/11/2015 12:50:35 PM" "corpdc102","CORPDC103","2/11/2015 12:57:48 PM","0","2/11/2015 12:57:48 PM" "corpdc102","CORPDC101","2/11/2015 12:57:44 PM","0","2/11/2015 12:57:44 PM" "corpdc102","CORPDC301","2/11/2015 12:54:49 PM","0","2/11/2015 12:54:49 PM" "corpdc102","CORPDC402","2/11/2015 12:54:45 PM","0","2/11/2015 12:54:45 PM" "CORPRODC101","CORPDC102","2/11/2015 12:50:41 PM","0","2/11/2015 12:50:41 PM" "CORPRODC102","CORPDC102","2/11/2015 12:53:40 PM","0","2/11/2015 12:53:40 PM" "corpdc401","CORPDC402","2/11/2015 12:57:50 PM","0","2/11/2015 12:57:50 PM" "corpdc402","CORPDC401","2/11/2015 12:57:52 PM","0","2/11/2015 12:57:52 PM" "corpdc402","CORPDC102","2/11/2015 12:54:59 PM","0","2/11/2015 12:54:59 PM" "corpdc201","CORPDC202","2/11/2015 12:57:51 PM","0","2/11/2015 12:57:51 PM" "corpdc103","CORPDC102","2/11/2015 12:57:50 PM","0","2/11/2015 12:57:50 PM" "corpdc103","CORPDC101","2/11/2015 12:57:47 PM","0","2/11/2015 12:57:47 PM" "CORPDC202","CORPDC201","2/11/2015 12:57:43 PM","0","2/11/2015 12:57:43 PM" "CORPDC202","CORPDC101","2/11/2015 12:51:53 PM","0","2/11/2015 12:51:53 PM" "corpdc001","CORPDC002","2/11/2015 12:57:43 PM","0","2/11/2015 12:57:43 PM" "corpdc001","CORPDC101","2/11/2015 12:55:50 PM","0","2/11/2015 12:55:50 PM" "corpdc002","CORPDC001","2/11/2015 12:57:46 PM","0","2/11/2015 12:57:46 PM" "corpdc301","CORPDC101","2/11/2015 12:46:28 PM","0","2/11/2015 12:46:28 PM" "corpdc701","CORPDC702","2/11/2015 12:57:49 PM","0","2/11/2015 12:57:49 PM" "corpdc701","CORPDC102","2/11/2015 12:56:49 PM","0","2/11/2015 12:56:49 PM" "corpdc702","CORPDC701","2/11/2015 12:57:52 PM","0","2/11/2015 12:57:52 PM" "@ | ConvertFrom-CSV | Sort From $Header = @" <style> TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;} TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;} TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;} .odd { background-color:#ffffff; } .even { background-color:#dddddd; } </style> "@ $RawHTML = $Data | ConvertTo-Html -Head $Header $New = Set-GroupRowColorsByColumn -InputObject $RawHTML -ColumnName From -CSSEvenClass even -CSSOddClass odd #Can also use: $New = $RawHTML | Set-GroupRowColorsByColumn -ColumnName From -CSSEvenClass even -CSSOddClass odd $New | Out-File .\Report.html .NOTES Author: Martin Pugh Changelog: 1.52 Updated the help, removed an unnecessary variable 1.51 Removed test code, added comment based help 1.5 Added ability to set row color with -Row switch instead of the individual cell 1.03 Added error message in case the $Property field cannot be found in the table header 1.02 Added some additional text to help. Added some error trapping around $Filter creation. 1.01 Added verbose output 1.0 Initial Release #> [CmdletBinding()] Param ( [Parameter(Mandatory,ValueFromPipeline)] [string[]]$InputObject, [Parameter(Mandatory)] [string]$ColumnName, [string]$CSSEvenClass = "TREven", [string]$CSSOddClass = "TROdd" ) Process { ForEach ($Line in $InputObject) { If ($Line -like "*<th>*") { If ($Line -notlike "*$ColumnName*") { Write-Error "Unable to locate a column named $ColumnName" -ErrorAction Stop } $Search = $Line | Select-String -Pattern "<th>.*?</th>" -AllMatches $Index = 0 ForEach ($Column in $Search.Matches) { If (($Column.Groups.Value -replace "<th>|</th>","") -eq $ColumnName) { Break } $Index ++ } } If ($Line -like "*<td>*") { $Search = $Line | Select-String -Pattern "<td>.*?</td>" -AllMatches If ($LastColumn -ne $Search.Matches[$Index].Value) { If ($Class -eq $CSSEvenClass) { $Class = $CSSOddClass } Else { $Class = $CSSEvenClass } } $LastColumn = $Search.Matches[$Index].Value $Line = $Line.Replace("<tr>","<tr class=""$Class"">") } Write-Output $Line } } } |