1

We have PowerShell objects that contain PSCustomObjects in the form of an array. To export this information to a text or Excel file we need to be able to flatten the data.

Example code:

$Fruits = [PSCustomObject]@{
    Name   = 'Banana'
    Colors = [PSCustomObject]@{
                Name = 'Green'
            },
            [PSCustomObject]@{
                Name = 'Yellow'
            }
    Taste = [PSCustomObject]@{
                Name = 'Good'
            },
            [PSCustomObject]@{
                Name = 'Bad'
            },
            [PSCustomObject]@{
                Name = 'Awful'
            }
}

Generates:

$Fruits | fl *

Name   : Banana
Colors : {@{Name=Green}, @{Name=Yellow}}
Taste  : {@{Name=Good}, @{Name=Bad}, @{Name=Awful}}

To be able to have a clean export, the desired result should be something like this:

Name    |   Color    |    Taste
----    |   -----    |    -----
Banana  |   Yellow   |    Good
Banana  |   Green    |    Bad
Banana  |            |    Awful

How is it possible to unravel this object?

2
  • You are missing a colour: Brown = Awful. Commented May 2, 2016 at 11:40
  • I know everything about fruit these days, that's why I left out the pears ;) But a brown banana.. I'd still take it! :D Commented May 2, 2016 at 11:53

1 Answer 1

2

You would need to find the column with the most values and use that as the limit for a for-/while-loop. Ex.

$maxLines = $Fruits.psobject.Properties | Where-Object { $_.TypeNameOfValue -match 'Object\[\]|ICollection' } | Foreach-Object { $_.Value.Count } | Sort-Object -Descending | Select-Object -First 1
0..($maxLines-1) | ForEach-Object {
    New-Object psobject -Property @{
        Name = $Fruits.Name
        Color = $Fruits.Colors[$_] | Foreach-Object { $_.Name }
        Taste = $Fruits.Taste[$_] | Foreach-Object { $_.Name }
    }
} | Select-Object Name, Color, Taste

Output:

Name   Color  Taste
----   -----  -----
Banana Green  Good 
Banana Yellow Bad  
Banana        Awful
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you Frode, this was exactly what I was looking for.
Only thing I improved was: Taste = if ($R.Taste | Select-Object -Index $_) {$R.Taste [$_] | Select-Object -ExpandProperty Name}; to avoid errors when nothing is available.
It should work fine in PS 3.0+ I think (tested on PS5), but in PS2 it would fail. There was also a bug with detecting the array-columns in PS2, so I've updated the answer to fix both.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.