PowerShell Format-Table: Columns, Sorting and Long Text

Format-Table is the PowerShell cmdlet that shows command output as a table. Pipe objects to it and list the properties you want as columns. All the examples below use this small list of servers:

$servers = @(
    [pscustomobject]@{ Name = 'WEB01'; Site = 'Austin'; CPU = 72; MemoryGB = 16; Notes = 'Front-end web server for the customer portal' }
    [pscustomobject]@{ Name = 'SQL01'; Site = 'Dallas'; CPU = 91; MemoryGB = 64; Notes = 'Primary SQL Server for billing' }
    [pscustomobject]@{ Name = 'WEB02'; Site = 'Austin'; CPU = 35; MemoryGB = 16; Notes = 'Standby web server' }
)

With no properties listed, Format-Table shows every property that fits:

$servers | Format-Table

Output:

Name  Site   CPU MemoryGB Notes
----  ----   --- -------- -----
WEB01 Austin  72       16 Front-end web server for the customer portal
SQL01 Dallas  91       64 Primary SQL Server for billing
WEB02 Austin  35       16 Standby web server

I ran the examples in real PowerShell 7.6 and Windows PowerShell 5.1 consoles, 100 characters wide. The tables matched except for a few details I point out below.

Choose the columns

List the properties after -Property, in the order you want the columns:

$servers | Format-Table -Property Name, Site, CPU

Output:

Name  Site   CPU
----  ----   ---
WEB01 Austin  72
SQL01 Dallas  91
WEB02 Austin  35

Only the listed properties appear. The objects themselves don’t change, so a later command in the script still has every property.

Select-Object picks columns too, and it keeps real objects, as shown in PowerShell Select-Object.

How do I sort a table in PowerShell?

Sort first, then format. Format-Table doesn’t sort anything, so put Sort-Object before it in the pipeline:

$servers | Sort-Object -Property CPU -Descending | Format-Table -Property Name, Site, CPU

Output:

Name  Site   CPU
----  ----   ---
SQL01 Dallas  91
WEB01 Austin  72
WEB02 Austin  35
PowerShell Sort-Object before Format-Table to sort a table by a column
Sorting by CPU, highest first (PowerShell 7)

To sort by more than one column, list them: Sort-Object -Property Site, Name. That also keeps the order predictable in 5.1, whose Sort-Object can shuffle rows that have equal values.

Rename and format columns

A hashtable in the property list creates a calculated column. Label sets the header, Expression builds the value, and Align lines it up:

$servers | Format-Table -Property Name,
    @{ Label = 'CPU %'; Expression = { $_.CPU }; Align = 'Right' },
    @{ Label = 'Memory'; Expression = { '{0} GB' -f $_.MemoryGB }; Align = 'Right' }

Output:

Name  CPU % Memory
----  ----- ------
WEB01    72  16 GB
SQL01    91  64 GB
WEB02    35  16 GB

Build the text inside the expression, as with '{0} GB' -f here. The underlying objects stay the same, so this only changes what you see.

Long text and column width

A value that doesn’t fit the window is cut off. I used Out-String -Width 100 here so you get the same result at any window size:

$server = [pscustomobject]@{
    Name  = 'WEB01'
    Notes = 'Front-end web server for the customer portal. ' +
            'Patched on September 28, 2026. Next patch window: October 26, 2026.'
}

$server | Format-Table -Property Name, Notes | Out-String -Width 100

Output in PowerShell 7:

Name  Notes
----  -----
WEB01 Front-end web server for the customer portal. Patched on September 28, 2026. Next patch windo…
PowerShell Format-Table cutting off long text with ... in Windows PowerShell 5.1
Windows PowerShell 5.1 ends the text with three dots

PowerShell 7 marks the cut with a single … character, and 5.1 uses three dots. Add -Wrap to show the whole value on extra lines:

$server = [pscustomobject]@{
    Name  = 'WEB01'
    Notes = 'Front-end web server for the customer portal. ' +
            'Patched on September 28, 2026. Next patch window: October 26, 2026.'
}

$server | Format-Table -Property Name, Notes -Wrap | Out-String -Width 100

Output:

Name  Notes
----  -----
WEB01 Front-end web server for the customer portal. Patched on September 28, 2026. Next patch
      window: October 26, 2026.

Why Width doesn’t shorten a column

Many guides say you can limit a column by adding Width to a calculated property. In my tests, it didn’t shorten the column in either version when the table had room for the full text:

$servers | Format-Table -Property Name, @{ Label = 'Notes'; Expression = { $_.Notes }; Width = 20 }

Output:

Name  Notes
----  -----
WEB01 Front-end web server for the customer portal
SQL01 Primary SQL Server for billing
WEB02 Standby web server

The Notes column is still as wide as its longest value. What does work is shortening the text yourself inside the expression:

$servers | Format-Table -Property Name, @{
    Label      = 'Notes'
    Expression = { if ($_.Notes.Length -gt 20) { $_.Notes.Substring(0, 17) + '...' } else { $_.Notes } }
}

Output:

Name  Notes
----  -----
WEB01 Front-end web ser...
SQL01 Primary SQL Serve...
WEB02 Standby web server

Group rows and hide headers

-GroupBy starts a new table for each value of a property. Sort by that property first, or you’ll get a new group every time the value changes:

$servers | Sort-Object -Property Site, Name | Format-Table -Property Name, CPU -GroupBy Site

Output in PowerShell 7:

   Site: Austin

Name  CPU
----  ---
WEB01  72
WEB02  35

   Site: Dallas

Name  CPU
----  ---
SQL01  91

Windows PowerShell 5.1 prints the same groups with an extra blank line between them. For a plain list without the header rows, use -HideTableHeaders:

$servers | Format-Table -Property Name, Site -HideTableHeaders

Output:

WEB01 Austin
SQL01 Dallas
WEB02 Austin

Don’t pipe Format-Table to Export-Csv

This is the most common Format-Table mistake. It turns objects into formatting instructions for the console, so anything after it gets those instead of your data:

$servers | Format-Table -Property Name, CPU | Export-Csv -Path C:\psfaqs\servers.csv -NoTypeInformation
Get-Content -Path C:\psfaqs\servers.csv -TotalCount 2

Output:

"ClassId2e4f51ef21dd47e99d3c952918aff9cd","pageHeaderEntry","pageFooterEntry","autosizeInfo","shapeInfo","groupingEntry"
"033ecb2bc07a4d43b5ef94ed5a35d280",,,,"Microsoft.PowerShell.Commands.Internal.Format.TableHeaderInfo",