2

Let's say that I have an Obj with data describing multiple entities. I want to output it like this (CSV, HTML, Format-Table, whatever):

Property Code   Property descr.  Entity1  Entity2  Entity3
abs_de234       abs prop for de  132      412      412
abs_fe234       abs prop for fe  423      432      234
...             ...              ...      ...      ...  

I would use something like:

$ObjData | % {Select-Object @{Label = "Property Code"; Expression = {$_.propcode}}, @{Label = "Property Desc."; Expression = {$_.descr}},  @{Label = "Entity1"; Expression = {$_.entity1}}, @{Label = "Entity2"; Expression = {$_.entity2}},@{Label = "Entity3"; Expression = {$_.entity3}} }| Format-Table

But what if my object has variable number of entities? Let's say these properties are all in an array:

$EntityList = @('Entity1', 'Entity2', 'Entity4', 'Entity5', 'Entity5')

How, based on $EntityList I can construct corresponding Select-Object command?

Upd.: Based on Help for Select-Object:

Select-Object
  [-InputObject <PSObject>]
  [[-Property] <Object[]>]
  [-ExcludeProperty <String[]>]
  [-ExpandProperty <String>]
  [-Unique]
  [-Last <Int32>]
  [-First <Int32>]
  [-Skip <Int32>]
  [-Wait]
  [<CommonParameters>]

Does this mean I should be able to just use Select-Object -Property $EntityList?

mklement0
  • 382,024
  • 64
  • 607
  • 775
miguello
  • 544
  • 5
  • 15

1 Answers1

4

| % {Select-Object

Don't use % (the ForEach-Object cmdlet) to pipe to Select-Object - pipe directly to Select-Object.

@{Label = "Entity1"; Expression = {$_.entity1}}

Unless you need to change the case of the label (property) name, just pass entity1 to Select-Object.

As with any cmdlet parameter that accepts an array of objects, you're free to pass the array either as an array literal (with the elements enumerated one by one with ,) or as a previously constructed array passed via a variable:

# Properties that need renaming.
# Note: Unless you need to *transform* the input property value,
#       you don't strictly need a *script block* ({ ... }) and can use
#       a *string* with the property name instead.
#       E.g., instead of {$_.propcode} you can use 'propcode'
$propDefs = 
  @{Label = "Property Code"; Expression = {$_.propcode}}, 
  @{Label = "Property Desc."; Expression = {$_.descr}}

# Add properties that can be extracted as-is:
$propDefs += 'Entity1', 'Entity2', 'Entity4', 'Entity5', 'Entity5'

# Note: Passing the array *positionally* implies binding to the -Property parameter.
$ObjData | Select-Object $propDefs # add Format-Table, if needed, for display formatting

To demonstrate:

# Sample input object
$ObjData = [pscustomobject] @{
  propcode = 'pc'
  descr = 'descr'
  Entity1 = 'e1'
  Entity2 = 'e2'
  Entity3 = 'e3'
  Entity4 = 'e4'
  Entity5 = 'e5'
}

$propDefs = 
  @{Label = "Property Code"; Expression = {$_.propcode}}, 
  @{Label = "Property Desc."; Expression = {$_.descr}}

$propDefs += 'Entity1', 'Entity2', 'Entity3', 'Entity4', 'Entity5'

$ObjData | Select-Object $propDefs

The above yields:

Property Code  : pc
Property Desc. : descr
Entity1        : e1
Entity2        : e2
Entity3        : e3
Entity4        : e4
Entity5        : e5
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Ok, yes, it works in this case. What might be wrong when I have a CSV file that looks like my original table, export it using `$ObjData = Import-CSV -Path $path` and try to do the same? – miguello Jun 13 '20 at 01:00
  • @miguello That's impossible to tell without further information - did you not get helpful answers to your related question? – mklement0 Jun 13 '20 at 02:05
  • Well, it's been helpful and I confirmed that it works the way you wrote it. And as you have said my problem might lie somewhere else. Looks like the Object that I construct during my script is not of the same structure as just a CSV read from file. I kept experimenting with it and the only way it would output the same way is if I spell the properties line verbatim, like `@{Label = "..."; Expression = {...}}`. When calling `GetType()` method on both objects - mine and one read directly from CSV, it shows Array of Objects on both. This will be my next step: find differences between structures – miguello Jun 13 '20 at 05:52
  • @miguello pipe the variables to `Get-Member` instead, which will tell you the actual type of the array's _elements_ - PowerShell arrays are `[object[]]`-typed, which means they can contains objects of any type. – mklement0 Jun 13 '20 at 12:42