Search code examples
powershellformattingpowershell-5.1

How can I set left/right column justification in Powershell's "format-table"


When I use "format-table" to display data created with [pscustomobject], if the data in a column is a value pulled from the output of a commandlet, it shows on the right of its column. However, if a value is something I set manually, it shows on the left of its column.

Here's an example using the "NetApp.ONTAP" module:

$volSis = Get-NcSis -Name 'MyVolume'
$object = [pscustomobject]@{
  'Compression' = $volSis.IsCompressionEnabled #This resolves to 'True' or 'False'
  'Dedupe' = 'Foo'
  }
$object | Format-Table

The output of this is:

Compression Dedupe
----------- ------
       True Foo

Is there any way to force all columns in a table to be left (or right) justified? Alternatively, is there a way to force manually-created data (i.e. the 'Foo' in this example) to be right-justified?


Solution

  • The easiest way to do it would be to coerce the bool property (displayed with Right alignment by default) to a string:

    [pscustomobject]@{
        Volume      = 'foo'
        Compression = $true -as [string] # strings always have Left alignment
        Dedupe      = 'foo'
    }
    

    Another option, you can use -Property with Alignment set to Left for the bool property:

    [pscustomobject]@{
        Volume      = 'foo'
        Compression = $true
        Dedupe      = 'foo'
    } | Format-Table Volume, @{ E = 'Compression'; Alignment = 'Left' }, Dedupe
    

    Unfortunately you also need to list the rest of the properties to be displayed.

    Yet another option, more complicated, is to create a custom ps1xml format file:

    Set-Content .\myCustomViewForMyCustomType.Format.ps1xml -Value @'
    <?xml version="1.0" encoding="utf-8"?>
    <Configuration>
      <ViewDefinitions>
        <View>
          <Name>myCustomViewForMyCustomType</Name>
          <ViewSelectedBy>
            <TypeName>MyCustomType</TypeName>
          </ViewSelectedBy>
          <TableControl>
            <TableHeaders>
              <TableColumnHeader>
                <Label>Volume</Label>
              </TableColumnHeader>
              <TableColumnHeader>
                <Label>Compression</Label>
                <Alignment>Left</Alignment>
              </TableColumnHeader>
              <TableColumnHeader>
                <Label>Dedupe</Label>
              </TableColumnHeader>
            </TableHeaders>
            <TableRowEntries>
              <TableRowEntry>
                <TableColumnItems>
                  <TableColumnItem>
                    <PropertyName>Volume</PropertyName>
                  </TableColumnItem>
                  <TableColumnItem>
                    <PropertyName>Compression</PropertyName>
                  </TableColumnItem>
                  <TableColumnItem>
                    <PropertyName>Dedupe</PropertyName>
                  </TableColumnItem>
                </TableColumnItems>
              </TableRowEntry>
            </TableRowEntries>
          </TableControl>
        </View>
      </ViewDefinitions>
    </Configuration>
    '@
    

    Then you can use Update-FormatData to add this custom format:

    Update-FormatData -AppendPath .\myCustomViewForMyCustomType.Format.ps1xml
    

    And lastly, if you add the special PSTypeName property with the same value used in <TypeName>MyCustomType</TypeName>, all your objects will be displayed using the specifics of that file, in this case the <Label>Compression</Label> will have <Alignment>Left</Alignment>:

    [pscustomobject]@{
        PSTypeName  = 'MyCustomType'
        Volume      = 'foo'
        Compression = $true
        Dedupe      = 'foo'
    }
    
    # Volume Compression Dedupe
    # ------ ----------- ------
    # foo    True        foo