I was working at a script where I created a custom object, and I wanted to to change the default properties shown when the object where written to the host. Easy enough, right? I have done this before of course, but this time I started thinking if it were possible to have the headings be different when using the default view, as opposed to, let’s say when shown using Format-List.
So, consider we have an object with the following properties: ‘FirstName’, ‘LastName’ and ‘Email’.
When called, it would display like this:
FirstName LastName Email --------- -------- ----- John Michaelson jm@email.com
And using Format-List:
FirstName : John LastName : Michaelson Email : jm@email.com
But this is what I wanted my output to be when calling the object:
First Name Last Name E-mail --------- -------- ----- John Michaelson jm@email.com
This is just an example of course, and could easily have been achieved using Select-Object with a custom expression.
So why didn’t I just name my properties this way when I defined the object in the script you might ask? I asked myself the same thing, but I like a challenge, ok? Besides, what I wanted was that the heading when used with Format-Table was for the headings to be ‘First Name’, ‘Last Name’ and ‘E-mail’, while when used with Format-Table * or Format-List, they should show as ‘FirstName’, ‘LastName’, and ‘Email’. Makes sense right?
After doing a little research I decided that I needed to define a format.ps1xml file to make this happen. After a lot of trial-and-error I got it working as I wanted. Was I happy now? No, of course not. There had to be a better way! Back to Google with me, and after a while I came over a link to Windows PowerShell Cookbook by Lee Holmes, at Google Books. I actually own this book, and see that in it, he have actually written a function called Add-FormatData that let’s you add a table formatting definition for a specific type name. His function didn’t solve my little problem though, but I had enough information now to build upon his function.
I ended up with two functions; New-FormatTableItem and Add-FormatTable, which let’s you perform what I wanted like this:
@( (New-FormatTableItem 'First Name' 'FirstName' 20), (New-FormatTableItem 'Last Name' 'LastName' 20), (New-FormatTableItem 'E-mail' 'Email' 20) ) | Add-FormatTable -TypeName 'Custom.UserType'
The New-FormatTableItem functions are used to create an array of Table Items, which I then pipe into Add-FormatTable. I don’t know how useful this is going to be for you guys, but it was a fun exercise for me, so I wanted to share it. Here is the code:
| function New-FormatTableItem { | |
| <# | |
| .SYNOPSIS | |
| Create new format Table Item | |
| .DESCRIPTION | |
| Create new format Table Item for use with Add-FormatTable | |
| .EXAMPLE | |
| Assuming you have a custom object with a type name of 'Custom.UserType': | |
| @( | |
| (New-FormatTableItem 'First Name' 'FirstName' 20), | |
| (New-FormatTableItem 'Last Name' 'LastName' 20), | |
| (New-FormatTableItem 'Sex' 'Sex' 10), | |
| (New-FormatTableItem 'E-mail' 'Email' 20) | |
| ) | Add-FormatTable -TypeName 'Custom.UserType' | |
| This will add a custom table formatting definition for the specified type name. | |
| .NOTES | |
| Based on a function by Lee Holmes in his excellent Windows PowerShell Cookbook (O'Reilly) | |
| Author: Øyvind Kallstad | |
| Date: 09.11.2014 | |
| Version: 1.0 | |
| #> | |
| [CmdletBinding()] | |
| param ( | |
| [Parameter()] | |
| [string] $Label, | |
| [Parameter(Mandatory)] | |
| [string] $PropertyName, | |
| [Parameter()] | |
| [int] $Width = 20, | |
| [Parameter()] | |
| [System.Management.Automation.Alignment] $Alignment = 'Undefined' | |
| ) | |
| $tableControlColumnHeader = New-Object -TypeName System.Management.Automation.TableControlColumnHeader $Label, $Width, $Alignment | |
| $tableControlColumn = New-Object -TypeName System.Management.Automation.TableControlColumn $Alignment, (New-Object -TypeName System.Management.Automation.DisplayEntry $PropertyName, 'Property') | |
| Write-Output ([PSCustomObject] @{ | |
| TableControlColumnHeader = $tableControlColumnHeader | |
| TableControlColumn = $tableControlColumn | |
| }) | |
| } | |
| function Add-FormatTable { | |
| <# | |
| .SYNOPSIS | |
| Add table formatting definition for the specified type | |
| .EXAMPLE | |
| Assuming you have a custom object with a type name of 'Custom.UserType': | |
| @( | |
| (New-FormatTableItem 'First Name' 'FirstName' 20), | |
| (New-FormatTableItem 'Last Name' 'LastName' 20), | |
| (New-FormatTableItem 'Sex' 'Sex' 10), | |
| (New-FormatTableItem 'E-mail' 'Email' 20) | |
| ) | Add-FormatTable -TypeName 'Custom.UserType' | |
| This will add a custom table formatting definition for the specified type name. | |
| .NOTES | |
| Based on a function by Lee Holmes in his excellent Windows PowerShell Cookbook (O'Reilly) | |
| Author: Øyvind Kallstad | |
| Date: 09.11.2014 | |
| Version: 1.0 | |
| #> | |
| [CmdletBinding()] | |
| param ( | |
| [Parameter(Mandatory)] | |
| [string] $TypeName, | |
| [Parameter(ValueFromPipelineByPropertyName)] | |
| [System.Management.Automation.TableControlColumnHeader[]] $TableControlColumnHeader, | |
| [Parameter(ValueFromPipelineByPropertyName)] | |
| [System.Management.Automation.TableControlColumn[]] $TableControlColumn | |
| ) | |
| BEGIN { | |
| $table = New-Object System.Management.Automation.TableControl | |
| $row = New-Object System.Management.Automation.TableControlRow | |
| } | |
| PROCESS { | |
| foreach($item in $TableControlColumn) { | |
| $row.Columns.Add($item) | |
| } | |
| foreach($header in $TableControlColumnHeader) { | |
| $table.Headers.Add($header) | |
| } | |
| } | |
| END { | |
| $table.Rows.Add($row) | |
| $formatView = New-Object System.Management.Automation.FormatViewDefinition 'TableView', $table | |
| $extendedType = New-Object System.Management.Automation.ExtendedTypeDefinition $TypeName | |
| $extendedType.FormatViewDefinition.Add($formatView) | |
| [Runspace]::DefaultRunspace.InitialSessionState.Formats.Add($extendedType) | |
| Update-FormatData | |
| } | |
| } |
Hi Øyvind,
Thanks a lot for sharing. I came across your post, since I was researching for a similar post on my blog(https://powershellone.wordpress.com/2015/03/09/powershell-format-table-views/). I came up with a similar function (Add-FormatTableView) to create custom table views (for Format-Table -View) for built-in objects.
Kind regards,
Dirk
LikeLike