Setting default formatting of PSCustomObjects from script

Welcome Forums General PowerShell Q&A Setting default formatting of PSCustomObjects from script

Viewing 3 reply threads
  • Author
    Posts
    • #198137
      Participant
      Topics: 2
      Replies: 1
      Points: 24
      Rank: Member

      Hi,

      Take the following demo script:

      foreach ($value in @(0, 1.2, 0.5))
      {
          [PSCustomObject] @{
              Property0 = (Get-Date).AddDays($value * 100)
              Property1 = $value
              Property2 = $value * $value
              Property3 = $value * $value * $value
              Property4 = "{0:0000.000000}" -f $value
          }
      }
      When run, the output is:
      Property0 : 2020-01-15 11:33:43
      Property1 : 0
      Property2 : 0
      Property3 : 0
      Property4 : 0000.000000
      
      Property0 : 2020-05-14 11:33:43
      Property1 : 1.2
      Property2 : 1.44
      Property3 : 1.728
      Property4 : 0001.200000
      
      Property0 : 2020-03-05 11:33:43
      Property1 : 0.5
      Property2 : 0.25
      Property3 : 0.125
      Property4 : 0000.500000

      I would like that the default display formatting when running the script be:

      • as if piped through Format-Table -Autosize
      • with the numbers formatted with a prescribed format

      For instance, I'd like the following display:

      Property0           Property1 Property2 Property3 Property4
      ---------           --------- --------- --------- ---------
      2020-01-15 11:35:31 0.00      0.00      0.000     0000.000000
      2020-05-14 11:35:31 1.20      1.44      1.728     0001.200000
      2020-03-05 11:35:31 0.50      0.25      0.125     0000.500000

      Can this be done (preferably without .ps1xml files, only from the script)?

      Thanks in advance for your help.

    • #198191
      Participant
      Topics: 10
      Replies: 1375
      Points: 1,481
      Helping Hand
      Rank: Community Hero

      To make this appear visually for reporting or output to an end-user, especially with numbers typically requires conversion to a string with string format or the .ToString() method.

      $results = foreach ($value in @(0, 1.2, 0.5))
      {
          [PSCustomObject] @{
              Property0 = (Get-Date).AddDays($value * 100)
              Property1 = '{0:F2}' -f $value
              Property2 = '{0:F2}' -f ($value * $value)
              Property3 = '{0:F3}' -f ($value * $value * $value)
              Property4 = "{0:0000.000000}" -f $value
          }
      }
      
      $results
      

      If the goal of the script is to output to a user and is not being consumed further, why not just use Format-List? Powershell chooses the format based on the number of properties, four (4) or greater and it displays in Table format, see if you just remove a single property:

      $results = foreach ($value in @(0, 1.2, 0.5))
      {
          [PSCustomObject] @{
              Property0 = 1
              Property1 = 2
              Property2 = '{0:F2}' -f ($value * $value)
              Property3 = '{0:F3}' -f ($value * $value * $value)
              #Property4 = "{0:0000.000000}" -f $value
          }
      }
      
      $results
      

      As you've eluded, you can override this with a PS1XML, but Format-Table can format it "pretty" for reporting purposes.

    • #198410
      Participant
      Topics: 2
      Replies: 1
      Points: 24
      Rank: Member

      Thanks for your response.

      Maybe my questioning was not precise enough, but the point is that the script's output is not restricted to being consumed "visually." For instance, I might want to pipe it through Where-Object, or Group-Object, whatever. This requires preserving the types (in the real script, there are double's, datetime's...).

      I just want that if I just display the output, it looks nicely formatted.

      I have a vague memory of encountering "properties attached to properties" (or whatever the proper wording should be) that determine the preferred formatting, but I can't remember where...

       

    • #198467
      Participant
      Topics: 10
      Replies: 1375
      Points: 1,481
      Helping Hand
      Rank: Community Hero

      Properties can be set to default and you can hide properties, as seen here:

      Essential PowerShell: Define default properties for custom objects

      Outside of that, I am not aware of how Powershell would know what you intend to do with an object such as display or use it to pass along and format it differently.

      PS C:\Users\rasim> $results[1].Property2
      1.44
      
      PS C:\Users\rasim> $results[2].Property2
      0.25
      
      PS C:\Users\rasim> $results[1].Property2 + $results[2].Property2
      1.440.25
      
      PS C:\Users\rasim> [double]$results[1].Property2 + [double]$results[2].Property2
      1.69
      

      The strings do break things, took me a minute to realize that 1.440.25 is just the string concatenated. If you are writing the functions, then you would define the type to do the conversion, like so:

      $results = foreach ($value in @(0, 1.2, 0.5))
      {
          [PSCustomObject] @{
              Property0 = (Get-Date).AddDays($value * 100)
              Property1 = '{0:F2}' -f $value
              Property2 = '{0:F2}' -f ($value * $value)
              Property3 = '{0:F3}' -f ($value * $value * $value)
              Property4 = "{0:0000.000000}" -f $value
          }
      }
      
      function Test-It {
          param (
             [Parameter(
                  Mandatory=$true,
                  ValueFromPipelineByPropertyName=$true
              )]
              [double]$Property2
          )
          begin{}
          process {
               $temp += $Property2
          }
          end {
              $temp
          }
      }
      
      $results | Test-It
      

      Then you can get the best of both worlds where things would display nicely and you convert back to required types for math operations.

Viewing 3 reply threads
  • You must be logged in to reply to this topic.