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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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